From ebf66e1b733b61be8da4859d6d77b9ada006bde2 Mon Sep 17 00:00:00 2001 From: Johannes Hoermann <j.hoermann@adito.de> Date: Tue, 22 Oct 2019 16:56:15 +0200 Subject: [PATCH] use subselect alias in some cases + Testcases --- process/SqlLib_tests/process.js | 71 +++++++++++++++++++++++++++++++++ process/Sql_lib/process.js | 36 ++++++++++++----- 2 files changed, 96 insertions(+), 11 deletions(-) diff --git a/process/SqlLib_tests/process.js b/process/SqlLib_tests/process.js index e3b2a0e0f3..2c5dcd5893 100644 --- a/process/SqlLib_tests/process.js +++ b/process/SqlLib_tests/process.js @@ -902,6 +902,12 @@ var conditionFormatTests = new TestSuite([ ["pCondition should not fail if # an ? exist in correct order", function(pTester) { new SqlBuilder().where("PERSON.FIRSTNAME", "val1", "# = ?") + .and("PERSON.FIRSTNAME", "val1", "asdf # fdsa=asdf ?fdas") + }], + + ["pCondition should not fail if # an ? exist in correct order and there are additional, escaped # and ?", function(pTester) + { + new SqlBuilder().where("PERSON.FIRSTNAME", "val1", "\\? # \\#= ?"); }], ["pCondition should not fail if only ? exists", function(pTester) @@ -923,6 +929,70 @@ var conditionFormatTests = new TestSuite([ { new SqlBuilder().where("PERSON.FIRSTNAME", "val1", "? = #") }, SqlBuilder.ERROR_CONDITION_WRONG_FORMAT()] +]); + +var subqueryAliasTests = new TestSuite([ + ["subselectAlias should be added for subquery in .select", function(pTester) + { + var subQuery = newSelect("NAME") + .from("ORGANISATION") + .where("ORGANISATION.NAME", "Adito") + .subselectAlias("testAlias") + + var actual = new SqlBuilder() + .select([subQuery, "FIRSTNAME"]) + .from("PERSON") + + pTester.assert("select (select NAME from ORGANISATION where ORGANISATION.NAME = ?) testAlias, FIRSTNAME", actual._select._sqlStorage, "prepared select-sql"); + pTester.assert(1, actual._select.preparedValues.length, "number of params"); + }], + + ["subselectAlias should be added for subquery in .from", function(pTester) + { + var subQuery = newSelect("NAME") + .from("ORGANISATION") + .where("ORGANISATION.NAME", "Adito") + .subselectAlias("testAlias") + + var actual = new SqlBuilder() + .from(subQuery) + + pTester.assert("from (select NAME from ORGANISATION where ORGANISATION.NAME = ?) testAlias", actual._from._sqlStorage, "prepared select-sql"); + pTester.assert(1, actual._from.preparedValues.length, "number of params"); + }], + + ["subselectAlias should be overruled by the param in in .from", function(pTester) + { + var subQuery = newSelect("NAME") + .from("ORGANISATION") + .where("ORGANISATION.NAME", "Adito") + .subselectAlias("testAlias") + + var actual = new SqlBuilder() + .from(subQuery, "overwriteAlias") + + pTester.assert("from (select NAME from ORGANISATION where ORGANISATION.NAME = ?) overwriteAlias", actual._from._sqlStorage, "prepared select-sql"); + pTester.assert(1, actual._from.preparedValues.length, "number of params"); + }], + + ["subselectAlias should be added for subquery in .join", function(pTester) + { + var subQuery = newSelect("NAME, ORGANISATIONID") + .from("ORGANISATION") + .where("ORGANISATION.NAME", "Adito") + .subselectAlias("testAlias") + + var actual = new SqlBuilder() + .from("CONTACT") + .join(subQuery, "testAlias.ORGANISATIONID = ORGANISATION_ID") + .join(subQuery, "testAlias.ORGANISATIONID = ORGANISATION_ID", "overwriteAlias") + + pTester.assert("join (select NAME, ORGANISATIONID from ORGANISATION where ORGANISATION.NAME = ?) testAlias on testAlias.ORGANISATIONID = ORGANISATION_ID", actual._joins[0]._sqlStorage, "prepared select-sql join 1"); + pTester.assert(1, actual._joins[0].preparedValues.length, "number of params join 1"); + + pTester.assert("join (select NAME, ORGANISATIONID from ORGANISATION where ORGANISATION.NAME = ?) overwriteAlias on testAlias.ORGANISATIONID = ORGANISATION_ID", actual._joins[1]._sqlStorage, "prepared select-sql join 2"); + pTester.assert(1, actual._joins[1].preparedValues.length, "number of params join 2"); + }] ]) var tester = new Tester("Test SqlBuilder"); @@ -939,6 +1009,7 @@ tester.test(selectTests); tester.test(joinTests); tester.test(subqueryAsFieldTests); tester.test(conditionFormatTests); +tester.test(subqueryAliasTests); logging.log("-------------------------"); tester.printResults(); diff --git a/process/Sql_lib/process.js b/process/Sql_lib/process.js index cf6c9feef1..ed8d1b6b34 100644 --- a/process/Sql_lib/process.js +++ b/process/Sql_lib/process.js @@ -264,12 +264,12 @@ SqlBuilder.prototype.toString = function(pDefaultConditionIfNone) */ SqlBuilder.prototype.select = function(pFields) { - this._select = SqlBuilder._getStatement(pFields, "select", undefined, true); + this._select = SqlBuilder._getStatement(pFields, "select", undefined, true, true); return this; } /** - * sets an alias-name which is added to the built sql if it is a full select + * sets an alias-name which is added at some places if this SqlBuilder is used as subselect (e.g. in .select(), .join(), .from(), ...) * @param {String} pSubselectAlias * * @return {SqlBuilder} current SqlBuilder object @@ -293,7 +293,7 @@ SqlBuilder.prototype.subselectAlias = function(pSubselectAlias) */ SqlBuilder.prototype.from = function(pTable, pTableAlias) { - this._from = SqlBuilder._getStatement(pTable, "from", pTableAlias); + this._from = SqlBuilder._getStatement(pTable, "from", pTableAlias, false, (pTableAlias ? false : true)); if (typeof(pTable) === "string") this._tableName = pTable; return this; @@ -320,8 +320,11 @@ SqlBuilder.prototype.join = function(pTable, pCondition, pTableAlias, pPrefix, p prefix = pPrefix + " " + prefix; var postfix = "on"; + if (pTableAlias) postfix = pTableAlias + " " + postfix; + else if (pTable instanceof SqlBuilder && pTable._subselectAlias) + postfix = pTable._subselectAlias + " " + postfix; if (!pCondition) postfix = ""; @@ -1291,12 +1294,13 @@ SqlBuilder.prototype._prepare = function(pField, pValue, pCondition, pFieldType, * @param {String|String[]|SqlBuilder} pElement the element to append * @param {String} [pPrefix] string to be added before pElement * @param {String} [pPostfix] string to be added after pElement - * @param {Boolean} [pAutoJoin] if this is true and pElement is an array, it will be automatically <br/> + * @param {Boolean} [pAutoJoin=false] if this is true and pElement is an array, it will be automatically <br/> * joined together to a string + * @param {Boolean} [pUseSubselectAlias=false] if true the subselectAlias is added if the element is a subquery * * @ignore */ -SqlBuilder._getStatement = function (pElement, pPrefix, pPostfix, pAutoJoin) +SqlBuilder._getStatement = function (pElement, pPrefix, pPostfix, pAutoJoin, pUseSubselectAlias) { var preparedValues = []; if (typeof pElement !== "string") @@ -1330,16 +1334,23 @@ SqlBuilder._getStatement = function (pElement, pPrefix, pPostfix, pAutoJoin) function _getElement (element) { var isSubQuery = false; + var subselectAlias = ""; if (element instanceof SqlBuilder) { if (element.isFullSelect()) + { isSubQuery = true; + if (pUseSubselectAlias && element._subselectAlias) + subselectAlias = " " + element._subselectAlias; + } + + element = element.build(); } preparedValues = preparedValues.concat(element[1]); if (isSubQuery || pAutoJoin) - return "(" + element[0] + ")"; + return "(" + element[0] + ")" + subselectAlias; return element[0]; } } @@ -1363,14 +1374,11 @@ SqlBuilder.prototype.buildCondition = function() SqlBuilder.prototype.build = function(pDefaultConditionIfNone) { var wherePrefix = ""; - var subselectAlias = ""; if (this.isFullSelect()) { if (this._where._sqlStorage) wherePrefix = "where "; - - subselectAlias = this._subselectAlias; } var whereSql = this._where._sqlStorage; @@ -1408,7 +1416,6 @@ SqlBuilder.prototype.build = function(pDefaultConditionIfNone) } } - sqlStr += (subselectAlias ? " " + subselectAlias : ""); return [sqlStr, preparedVals]; } @@ -2750,13 +2757,20 @@ SqlUtils.replaceConditionTemplate = function(pCondition, pPlaceholder, pReplacem return text.replaceAll(pCondition, replacements); } +/** + * Checks if the '#' is 0 or 1 time in pCondition, '?' has to be 1 time in pCondition. + * Also checks if '#' is before '?' + * @param {String} pCondition + * + * @return {Boolean} true if the format is ok + */ SqlUtils.checkConditionFormat = function(pCondition) { // replace by {@NUMBERSIGN@} / {@QUESTIONSIGN@} as the js-regexp cannot do lookbehind (needed by the regexp used in replaceConditionTemplate to check escapes) // so we just use replaceConditionTemplate to replace by something which never should occur anywhere pCondition = SqlUtils.replaceConditionTemplate(pCondition, "#", "{@NUMBERSIGN@}") pCondition = SqlUtils.replaceConditionTemplate(pCondition, "\\?", "{@QUESTIONSIGN@}") - + var indexOfNumberSign = pCondition.indexOf("{@NUMBERSIGN@}"); var indexOfQuestionSign = pCondition.indexOf("{@QUESTIONSIGN@}"); -- GitLab