Skip to content
Snippets Groups Projects
Commit d1df9174 authored by Johannes Hörmann's avatar Johannes Hörmann
Browse files

fix some sql generation of sql builder, add "or"

parent 98441ff0
No related branches found
No related tags found
No related merge requests found
......@@ -5,168 +5,312 @@ import("system.SQLTYPES");
import("Sql_lib");
import("UnitTest_lib");
var andTests = [
// First the tests with only the first parameter
["plain text-condition", function(pTester) {
var expected = "PERSON.FIRSTNAME = 'Admin'";
var validAndUsageTests = [
["and should just add simple strings as condition just as it is", function(pTester)
{
var expected = "PERSON.FIRSTNAME = 'Tim' and PERSON.LASTNAME = 'Admin'";
var actual = new SqlBuilder()
.and("PERSON.FIRSTNAME = 'Tim'") // NOTE: you should not do this as this does not add a real prepared statement with "?"
.and("PERSON.LASTNAME = 'Admin'")
pTester.assert(expected, actual._where._sqlStorage, "prepared sql");
pTester.assert(0, actual._where.preparedValues.length, "number of params");
}],
["and should add a condition if field and value are passed", function(pTester)
{
var actual = new SqlBuilder()
.and("PERSON.FIRSTNAME", "Tim")
.and("PERSON.LASTNAME", "Admin")
pTester.assert("PERSON.FIRSTNAME = ? and PERSON.LASTNAME = ?", actual._where._sqlStorage, "prepared sql");
pTester.assert(2, actual._where.preparedValues.length, "number of params");
}],
["and should add a condition if field and value as jdito-var are passed", function(pTester)
{
vars.set("$global.TestUnitValueName", "Tim");
var actual = new SqlBuilder()
.and("PERSON.FIRSTNAME", "$global.TestUnitValueName")
pTester.assert("PERSON.FIRSTNAME = 'Tim' ", actual.toString());
}],
["and should use the given condition pattern", function(pTester)
{
var actual = new SqlBuilder()
.and("PERSON.FIRSTNAME", "Tim", "# <> ?")
.and("PERSON.LASTNAME", "Admin")
pTester.assert("PERSON.FIRSTNAME <> ? and PERSON.LASTNAME = ?", actual._where._sqlStorage, "prepared sql");
pTester.assert(2, actual._where.preparedValues.length, "number of params");
}],
["and should use the given SQLTYPE if provided", function(pTester)
{
var actual = new SqlBuilder()
.andCondition(expected)
.toString()
.and("PERSON.FIRSTNAME", 6, null, SQLTYPES.INTEGER)
.and("PERSON.LASTNAME", 7, undefined, SQLTYPES.INTEGER)
.and("PERSON.LASTNAME", 8, "# <> ?", SQLTYPES.INTEGER)
pTester.assert(expected, actual);
pTester.assert("PERSON.FIRSTNAME = ? and PERSON.LASTNAME = ? and PERSON.LASTNAME <> ?", actual._where._sqlStorage, "prepared sql");
pTester.assert(3, actual._where.preparedValues.length, "number of params");
pTester.assert(SQLTYPES.INTEGER, actual._where.preparedValues[0][1], "sql type of param 1 is the provided type");
pTester.assert(SQLTYPES.INTEGER, actual._where.preparedValues[1][1], "sql type of param 2 is the provided type");
pTester.assert(SQLTYPES.INTEGER, actual._where.preparedValues[2][1], "sql type of param 3 is the provided type");
}],
["prepared statement", function(pTester) {
var testPrepared = ["PERSON.FIRSTNAME = ?", [["Admin", SQLTYPES.CHAR]]];
var expected = " ( PERSON.FIRSTNAME = 'Admin' ) ";
["and only with a prepared statement-array should just use it as it is", function(pTester)
{
var actual = new SqlBuilder()
.andCondition(testPrepared)
.toString()
.and([
"PERSON.FIRSTNAME = ?", [["Peter", 12]]
])
.and([
"exists (select * FROM CONTACT where PERSON_ID = PERSONID)", []
])
pTester.assert(" ( PERSON.FIRSTNAME = ? ) and ( exists (select * FROM CONTACT where PERSON_ID = PERSONID) ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(1, actual._where.preparedValues.length, "number of params");
}],
["and only with a SqlBulder object should just use the condition from it", function(pTester)
{
var actual = new SqlBuilder()
.and(new SqlBuilder()
.and("PERSON.FIRSTNAME", "Tim")
.and("PERSON.LASTNAME", "Admin"))
pTester.assert(" ( PERSON.FIRSTNAME = ? and PERSON.LASTNAME = ? ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(2, actual._where.preparedValues.length, "number of params");
}],
["and with a builder as value and condition (field is null|undefined) should add the whole builder as subquery", function(pTester)
{
var actual = new SqlBuilder()
.and(null, new SqlBuilder()
.select("FIRSTNAME")
.from("PERSON")
.and("PERSON.FIRSTNAME", "Tim")
.and("PERSON.LASTNAME", "Admin"),
"exists ?")
pTester.assert(expected, actual);
pTester.assert("exists ( select FIRSTNAME from PERSON where PERSON.FIRSTNAME = ? and PERSON.LASTNAME = ? ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(2, actual._where.preparedValues.length, "number of params");
}],
["SqlBuilder as first param. It should use only the condition from the Builder.", function(pTester) {
var testCond = new SqlBuilder()
.select("FIRSTNAME")
.from("PERSON")
.andCondition("PERSON.FIRSTNAME = 'Admin'");
var expected = " ( PERSON.FIRSTNAME = 'Admin' ) ";
["and with a builder as value and field should add the whole builder as subquery with field = (subquery)", function(pTester)
{
var actual = new SqlBuilder()
.and("PERSON.FIRSTNAME", new SqlBuilder()
.select("FIRSTNAME")
.from("PERSON")
.and("PERSON.FIRSTNAME", "Tim")
.and("PERSON.LASTNAME", "Admin"))
pTester.assert("PERSON.FIRSTNAME = ( select FIRSTNAME from PERSON where PERSON.FIRSTNAME = ? and PERSON.LASTNAME = ? ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(2, actual._where.preparedValues.length, "number of params");
}],
["and with a prepared statement-array as value and field is null|undefined should add the whole statement as subquery", function(pTester)
{
var actual = new SqlBuilder()
.andCondition(testCond)
.toString()
.and(null, ["select FIRSTNAME from PERSON.FIRSTNAME = ?", [["Peter", 12]]], "exists ?")
.and(null, ["exists (select FIRSTNAME from PERSON.FIRSTNAME = ?)", [["Peter", 12]]]) // also without pCond it should work as the condition could be included in the prep statement
pTester.assert(expected, actual);
pTester.assert("exists ( select FIRSTNAME from PERSON.FIRSTNAME = ? ) and ( exists (select FIRSTNAME from PERSON.FIRSTNAME = ?) ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(2, actual._where.preparedValues.length, "number of params");
}],
["wrong type as first parameter throws error", function(pTester) {
new SqlBuilder()
.andCondition(9)
.toString()
["and with a prepared statement-array as value and field should add the whole statement as subquery with field = (subquery)", function(pTester)
{
var actual = new SqlBuilder()
.and("PERSON.FIRSTNAME", ["select FIRSTNAME from PERSON.FIRSTNAME = ?", [["Peter", 12]]])
}, SqlBuilder.ERROR_INVALID_CONDITION_VALUE_TYPE()],
pTester.assert("PERSON.FIRSTNAME = ( select FIRSTNAME from PERSON.FIRSTNAME = ? ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(1, actual._where.preparedValues.length, "number of params");
}]
];
var validOrUsageTests = [
["or should just add simple strings as condition just as it is", function(pTester)
{
var actual = new SqlBuilder()
.or("PERSON.FIRSTNAME = 'Tim'") // NOTE: you should not do this as this does not add a real prepared statement with "?"
.or("PERSON.LASTNAME = 'Admin'")
pTester.assert("PERSON.FIRSTNAME = 'Tim' or PERSON.LASTNAME = 'Admin'", actual._where._sqlStorage, "prepared sql");
pTester.assert(0, actual._where.preparedValues.length, "number of params");
}],
// Then the tests with more parameters
["default usage with Table.Column and normal field", function(pTester) {
var expected = " ( PERSON.FIRSTNAME = 'Admin' ) "
["or should add a condition if field and value are passed", function(pTester)
{
var actual = new SqlBuilder()
.and("PERSON.FIRSTNAME", "Admin")
.toString()
pTester.assert(expected, actual);
.or("PERSON.FIRSTNAME", "Tim")
.or("PERSON.LASTNAME", "Admin")
pTester.assert("PERSON.FIRSTNAME = ? or PERSON.LASTNAME = ?", actual._where._sqlStorage, "prepared sql");
pTester.assert(2, actual._where.preparedValues.length, "number of params");
}],
["default usage with only Column should error", function(pTester) {
new SqlBuilder()
.and("FIRSTNAME", "Admin")
.toString()
}, new Error(translate.withArguments("${SQL_LIB_FIELD_WRONG_FORMAT} field: %0", ["FIRSTNAME"]))],
["or should add a condition if field and value as jdito-var are passed", function(pTester)
{
vars.set("$global.TestUnitValueName", "Tim");
var actual = new SqlBuilder()
.or("PERSON.FIRSTNAME", "$global.TestUnitValueName")
pTester.assert("PERSON.FIRSTNAME = 'Tim' ", actual.toString());
}],
["default usage with [Table, Column, TableAlias] and normal field", function(pTester) {
var expected = " ( pers.FIRSTNAME = 'Admin' ) "
["or should use the given condition pattern", function(pTester)
{
var actual = new SqlBuilder()
.and(["PERSON", "FIRSTNAME", "pers"], "Admin")
.toString()
pTester.assert(expected, actual);
.or("PERSON.FIRSTNAME", "Tim", "# <> ?")
.or("PERSON.LASTNAME", "Admin")
pTester.assert("PERSON.FIRSTNAME <> ? or PERSON.LASTNAME = ?", actual._where._sqlStorage, "prepared sql");
pTester.assert(2, actual._where.preparedValues.length, "number of params");
}],
["default usage with Table.Column and variable field", function(pTester) {
var expected = " ( PERSON.USER_NEW = '" + vars.get("$sys.user") + "' ) "
["or should use the given SQLTYPE if provided", function(pTester)
{
var actual = new SqlBuilder()
.and("PERSON.USER_NEW", "$sys.user") // use sys.user in this test as it's always available
.toString()
pTester.assert(expected, actual);
.or("PERSON.FIRSTNAME", 6, null, SQLTYPES.INTEGER)
.or("PERSON.LASTNAME", 7, undefined, SQLTYPES.INTEGER)
.or("PERSON.LASTNAME", 8, "# <> ?", SQLTYPES.INTEGER)
pTester.assert("PERSON.FIRSTNAME = ? or PERSON.LASTNAME = ? or PERSON.LASTNAME <> ?", actual._where._sqlStorage, "prepared sql");
pTester.assert(3, actual._where.preparedValues.length, "number of params");
}],
["SqlBuilder as subcondition with field and cond", function(pTester) {
var expected = "select * from CONTACT where ( CONTACT.PERSON_ID <> ( select PERSONID from PERSON where ( PERSON.FIRSTNAME = 'Admin' ) ) ) ";
["or only with a prepared statement-array should just use it as it is", function(pTester)
{
var actual = new SqlBuilder()
.or([
"PERSON.FIRSTNAME = ?", [["Peter", 12]]
])
.or([
"exists (select * FROM CONTACT where PERSON_ID = PERSONID)", []
])
pTester.assert(" ( PERSON.FIRSTNAME = ? ) or ( exists (select * FROM CONTACT where PERSON_ID = PERSONID) ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(1, actual._where.preparedValues.length, "number of params");
}],
["or only with a SqlBulder object should just use the condition from it", function(pTester)
{
var actual = new SqlBuilder()
.select("*")
.from("CONTACT")
.and("CONTACT.PERSON_ID",
new SqlBuilder()
.select("PERSONID")
.from("PERSON")
.and("PERSON.FIRSTNAME", "Admin")
,false , "# <> ?")
.toString();
.or(new SqlBuilder()
.or("PERSON.FIRSTNAME", "Tim")
.or("PERSON.LASTNAME", "Admin"))
pTester.assert(" ( PERSON.FIRSTNAME = ? or PERSON.LASTNAME = ? ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(2, actual._where.preparedValues.length, "number of params");
}],
["or with a builder as value and condition (field is null|undefined) should add the whole builder as subquery", function(pTester)
{
var actual = new SqlBuilder()
.or(null, new SqlBuilder()
.select("FIRSTNAME")
.from("PERSON")
.or("PERSON.FIRSTNAME", "Tim")
.or("PERSON.LASTNAME", "Admin"),
"exists ?")
pTester.assert(expected, actual);
pTester.assert("exists ( select FIRSTNAME from PERSON where PERSON.FIRSTNAME = ? or PERSON.LASTNAME = ? ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(2, actual._where.preparedValues.length, "number of params");
}],
["SqlBuilder as subcondition with cond = 'exists ?' and field = null", function(pTester) {
var expected = "select * from CONTACT where ( exists ( select PERSONID from PERSON where ( PERSON.FIRSTNAME = 'Admin' ) ) ) ";
["or with a builder as value and field should add the whole builder as subquery with field = (subquery)", function(pTester)
{
var actual = new SqlBuilder()
.or("PERSON.FIRSTNAME", new SqlBuilder()
.select("FIRSTNAME")
.from("PERSON")
.or("PERSON.FIRSTNAME", "Tim")
.or("PERSON.LASTNAME", "Admin"))
pTester.assert("PERSON.FIRSTNAME = ( select FIRSTNAME from PERSON where PERSON.FIRSTNAME = ? or PERSON.LASTNAME = ? ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(2, actual._where.preparedValues.length, "number of params");
}],
["or with a prepared statement-array as value and field is null|undefined should add the whole statement as subquery", function(pTester)
{
var actual = new SqlBuilder()
.select("*")
.from("CONTACT")
.and(undefined,
new SqlBuilder()
.select("PERSONID")
.from("PERSON")
.and("PERSON.FIRSTNAME", "Admin")
,false , "exists ?")
.toString();
.or(null, ["select FIRSTNAME from PERSON.FIRSTNAME = ?", [["Peter", 12]]], "exists ?")
.or(null, ["exists (select FIRSTNAME from PERSON.FIRSTNAME = ?)", [["Peter", 12]]]) // also without pCond it should work as the condition could be included in the prep statement
pTester.assert(expected, actual);
pTester.assert("exists ( select FIRSTNAME from PERSON.FIRSTNAME = ? ) or ( exists (select FIRSTNAME from PERSON.FIRSTNAME = ?) ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(2, actual._where.preparedValues.length, "number of params");
}],
]
var mandatoryAndTests = [
["default of pMandatory should be true -> error on pValue = null", function(pTester) {
new SqlBuilder().and("PERSON.USER_NEW", "");
}, SqlBuilder.ERROR_VALUE_IS_MANDATORY()],
["if pMandatory = true error on pValue = null", function(pTester) {
new SqlBuilder().and("PERSON.USER_NEW", null, true);
}, SqlBuilder.ERROR_VALUE_IS_MANDATORY()],
["if pMandatory = false: NO error on pValue = null and no condition added", function(pTester) {
var expected = ""
var actual = new SqlBuilder()
.and("PERSON.FIRSTNAME", null, false)
.toString();
pTester.assert(expected, actual, "no condition added");
}],
["SqlBuilder with an incomplete subcondition (SqlBuilder) should error as value is set as mandatory", function(pTester) {
new SqlBuilder()
.select("*")
.from("CONTACT")
.and(null,
new SqlBuilder()
.and("PERSON.FIRSTNAME", "Admin")
,true , "exists ?");
}, SqlBuilder.ERROR_INVALID_SUBQUERY_TYPE()],
["SqlBuilder with an incomplete subcondition (SqlBuilder) but mandatory = false should NOT error but ignore the condition", function(pTester) {
var expected = "select * from CONTACT";
var actual = new SqlBuilder()
.select("*")
.from("CONTACT")
.and(null,
new SqlBuilder()
.and("PERSON.FIRSTNAME", "Admin")
,false , "exists ?")
.toString();
pTester.assert(expected, actual, "no condition added");
["or with a prepared statement-array as value and field should add the whole statement as subquery with field = (subquery)", function(pTester)
{
var actual = new SqlBuilder()
.or("PERSON.FIRSTNAME", ["select FIRSTNAME from PERSON.FIRSTNAME = ?", [["Peter", 12]]])
pTester.assert("PERSON.FIRSTNAME = ( select FIRSTNAME from PERSON.FIRSTNAME = ? ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(1, actual._where.preparedValues.length, "number of params");
}]
];
var combinedAndOrTests = [
["or combining two and", function(pTester)
{
var actual = new SqlBuilder()
.and("PERSON.FIRSTNAME", "Tim")
.and("PERSON.LASTNAME", "Admin")
.or(new SqlBuilder()
.and("PERSON.FIRSTNAME", "Peter")
.and("PERSON.LASTNAME", "Müller"))
pTester.assert("(PERSON.FIRSTNAME = ? and PERSON.LASTNAME = ?) or ( PERSON.FIRSTNAME = ? and PERSON.LASTNAME = ? ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(4, actual._where.preparedValues.length, "number of params");
}],
["jdito variable returning null and mandatory = true should error", function(pTester) {
vars.set("$global.MyNullVariable", null);
new SqlBuilder()
.and("PERSON.USER_NEW", "$global.MyNullVariable") // use sys.user in this test as it's always available
.toString()
}, SqlBuilder.ERROR_VALUE_IS_MANDATORY_JDITO_VAR()],
["and combining two or", function(pTester)
{
var actual = new SqlBuilder()
.and(new SqlBuilder()
.or("PERSON.FIRSTNAME", "Tim")
.or("PERSON.LASTNAME", "Admin"))
.and(new SqlBuilder()
.or("PERSON.FIRSTNAME", "Peter")
.or("PERSON.LASTNAME", "Müller"))
pTester.assert(" ( PERSON.FIRSTNAME = ? or PERSON.LASTNAME = ? ) and ( PERSON.FIRSTNAME = ? or PERSON.LASTNAME = ? ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(4, actual._where.preparedValues.length, "number of params");
}],
["some and/or combinations in one select", function(pTester)
{
var actual = new SqlBuilder()
.or("PERSON.FIRSTNAME", "Tim")
.or("PERSON.FIRSTNAME", "Franz")
.and("PERSON.LASTNAME", "Admin")
.and(new SqlBuilder()
.or("PERSON.FIRSTNAME", "Peter")
.or("PERSON.LASTNAME", "Müller"))
.or("PERSON.FIRSTNAME", "Franz")
.and("PERSON.FIRSTNAME", "Franz")
.or(new SqlBuilder()
.and("PERSON.FIRSTNAME", "Peter")
.and("PERSON.LASTNAME", "Müller")
.and(new SqlBuilder()
.or("PERSON.FIRSTNAME", "Peter")
.or("PERSON.LASTNAME", "Müller")))
pTester.assert("PERSON.FIRSTNAME = ? or PERSON.FIRSTNAME = ? and PERSON.LASTNAME = ? and ( PERSON.FIRSTNAME = ? or PERSON.LASTNAME = ? ) or (PERSON.FIRSTNAME = ?) and PERSON.FIRSTNAME = ? or ( PERSON.FIRSTNAME = ? and PERSON.LASTNAME = ? and ( PERSON.FIRSTNAME = ? or PERSON.LASTNAME = ? ) ) ", actual._where._sqlStorage, "prepared sql");
pTester.assert(11, actual._where.preparedValues.length, "number of params");
}]
]
var tester = new Tester("Test SqlBuilder.and()");
tester.test(andTests);
tester.test(mandatoryAndTests);
tester.test(validAndUsageTests);
tester.test(validOrUsageTests);
tester.test(combinedAndOrTests);
logging.log("-------------------------");
tester.printResults();
......@@ -661,7 +661,8 @@ function SqlBuilder (pAlias)
_sqlStorage: "",
// save, if the last condition was an OR. For better bracket-placement
_lastWasOr: false
_lastWasOr: false,
_previouslyOnlyOr: false
}
}
......@@ -844,8 +845,7 @@ SqlBuilder.prototype.where = function(pCondition)
return this;
}
SqlBuilder.prototype.andCondition = function(pCondition, pMandatory)
SqlBuilder.prototype._whereCondition = function(pCondition, pMandatory, pAddPreparedConditionCallback, pBrackets)
{
if (pCondition === undefined)
return this;
......@@ -859,10 +859,8 @@ SqlBuilder.prototype.andCondition = function(pCondition, pMandatory)
// the field is a simple string -> just add the string, no prepared statement
if (typeofSql == "string")
{
if (this.hasCondition())
this._where._sqlStorage += " and ";
this._where._sqlStorage += sql;
pAddPreparedConditionCallback([sql, []])
return this;
}
......@@ -870,8 +868,12 @@ SqlBuilder.prototype.andCondition = function(pCondition, pMandatory)
if (Array.isArray(sql))
{
this._where.preparedValues = this._where.preparedValues.concat(sql[1]);
return this.andCondition(" ( " + sql[0] + " ) ");
// add only brackets if needed
if (pBrackets)
sql[0] = " ( " + sql[0] + " ) ";
pAddPreparedConditionCallback([sql[0], []], pBrackets)
return this;
}
......@@ -879,14 +881,15 @@ SqlBuilder.prototype.andCondition = function(pCondition, pMandatory)
// TODO: maybe call add(null, sql, pMandatory, pCond, ...) if sql.isFullSelect() and pCond is proviede. Else use only select and throw error -> better: only one possible way and a clear solution if someone does it wrong less implict
if (sql instanceof SqlBuilder)
{
var condString = " ( " + sql._where._sqlStorage + " ) ";
// add only brackets if needed
var sqlString = sql._where._sqlStorage;
if (pBrackets)
sqlString = " ( " + sqlString + " ) ";
var condString = sqlString;
if (condString.trim() != "")
{
this.andCondition(condString);
if (sql._where.preparedValues)
{
this._where.preparedValues = this._where.preparedValues.concat(sql._where.preparedValues);
}
pAddPreparedConditionCallback([condString, sql._where.preparedValues], pBrackets);
}
return this;
}
......@@ -894,7 +897,7 @@ SqlBuilder.prototype.andCondition = function(pCondition, pMandatory)
throw SqlBuilder.ERROR_INVALID_CONDITION_VALUE_TYPE();
}
SqlBuilder.prototype.andSubquery = function(pSubquery, pMandatory, pCond)
SqlBuilder.prototype._whereSubquery = function(pSubquery, pMandatory, pCondition, pAddPreparedConditionCallback)
{
if (pSubquery === undefined)
return this;
......@@ -906,11 +909,11 @@ SqlBuilder.prototype.andSubquery = function(pSubquery, pMandatory, pCond)
var typeofSql = typeof sql;
// the field is a simple string -> just add the string, no prepared statement
// the field is an array -> it is a prepared condition
// the field is an array -> it is a prepared statement which already SHOULD contain exists or another condition
// Both can be handled by _prepare
if (Array.isArray(sql) || typeofSql == "string")
{
this.andCondition(this._prepare(undefined, sql, pCond));
pAddPreparedConditionCallback(this._prepare(undefined, sql, pCondition));
return this;
}
......@@ -919,8 +922,8 @@ SqlBuilder.prototype.andSubquery = function(pSubquery, pMandatory, pCond)
{
var subQuery = pSubquery;
// Without condition this function cannot be used
if (!pCond)
// Without condition this function cannot be used with SqlBuilder object as it cannot contain a condition
if (!pCondition)
{
throw SqlBuilder.ERROR_NO_CONDITION();
}
......@@ -928,7 +931,7 @@ SqlBuilder.prototype.andSubquery = function(pSubquery, pMandatory, pCond)
if (subQuery.isFullSelect())
{
var preparedObj = subQuery.build();
this.andCondition(this._prepare(undefined, preparedObj, pCond));
pAddPreparedConditionCallback(this._prepare(undefined, preparedObj, pCondition));
}
else if (pMandatory)
{
......@@ -955,7 +958,7 @@ SqlBuilder.prototype.andSubquery = function(pSubquery, pMandatory, pCond)
* }
* @return {SqlBuilder} current SqlBuilder object
*/
SqlBuilder.prototype.and = function(pFieldOrCond, pValue, pMandatory, pCond, pFieldType)
SqlBuilder.prototype._addWhere = function(pFieldOrCond, pValue, pMandatory, pCond, pFieldType, pAddPreparedConditionCallback)
{
// For now: treat "" as null just like db.insert, db.table etc. Maybe otion for later: more pMandatory-types
if (pValue === "")
......@@ -964,34 +967,48 @@ SqlBuilder.prototype.and = function(pFieldOrCond, pValue, pMandatory, pCond, pFi
if (pMandatory === undefined)
pMandatory = true;
// // just call the andCondition function if it is only a Condition
// if (!pFieldOrCond !== undefined && (pValue === undefined) && pCond === undefined && pFieldType === undefined)
// {
// return this.andCondition(pFieldOrCond, pMandatory);
// }
// just call the andCondition function if it is only a Condition
if (!pFieldOrCond !== undefined && (pValue === undefined) && pCond === undefined && pFieldType === undefined)
{
return this._whereCondition(pFieldOrCond, pMandatory, pAddPreparedConditionCallback, true);
}
// first check the default-mandatory-cases: null or undefined. everything else such as ch3ecking $-variables is done later
// first check the default-mandatory-cases: null or undefined. everything else such as checking $-variables is done later
if (pMandatory && !(pValue === false || pValue))
throw SqlBuilder.ERROR_VALUE_IS_MANDATORY();
// a field and a value is given OR pFieldOrSQL == null and pValue instanceof SqlBuilder and pCond is given -> preparedSQL
if((typeof pFieldOrCond == "string" || Array.isArray(pFieldOrCond)) || (!pFieldOrCond && pCond))
// a field is string or array -> normal case
// OR !pFieldOrCond and pValue and pCond is given -> preparedSQL/SqlBuilder can be used without field if pCond is set
if((typeof pFieldOrCond == "string" || Array.isArray(pFieldOrCond)) || (!pFieldOrCond && (pCond && pValue instanceof SqlBuilder || !(pValue instanceof SqlBuilder))))
{
var field = pFieldOrCond;
var typeofValue = typeof pValue;
// pValue can be...
// ... a SqlBuilder -> it is a SqlBuilder containing a complete subquery
if (pValue instanceof SqlBuilder || Array.isArray(pValue) || (typeofValue == "string" && (pFieldOrCond == undefined || pFieldOrCond == null)))
{
if (pFieldOrCond !== null && pFieldOrCond !== undefined)
{
if (!pCond)
pCond = "# = ?"
pCond = SqlUtils.replaceConditionTemplate(pCond, '#', SqlUtils.parseField(pFieldOrCond)[0])
}
return this.andSubquery(pValue, pMandatory, pCond)
else
{
if (!pCond)
pCond = "?"
}
return this._whereSubquery(pValue, pMandatory, pCond, pAddPreparedConditionCallback);
}
if (!pCond)
pCond = "# = ?"
// ... a string starting with $ -> jdito varable which has to be resolved
if (typeofValue == "string" && pValue[0] == "$")
{
......@@ -1004,7 +1021,7 @@ SqlBuilder.prototype.and = function(pFieldOrCond, pValue, pMandatory, pCond, pFi
if (pValue)
{
this.andCondition(this._prepare(field, pValue, pCond, pFieldType));
this._whereCondition(this._prepare(field, pValue, pCond, pFieldType), undefined, pAddPreparedConditionCallback);
}
return this;
}
......@@ -1017,7 +1034,7 @@ SqlBuilder.prototype.and = function(pFieldOrCond, pValue, pMandatory, pCond, pFi
// ... everything else -> just pass it
if (pValue === false || pValue)
this.andCondition(this._prepare(field, pValue, pCond, pFieldType));
this._whereCondition(this._prepare(field, pValue, pCond, pFieldType), undefined, pAddPreparedConditionCallback);
return this;
}
......@@ -1025,6 +1042,93 @@ SqlBuilder.prototype.and = function(pFieldOrCond, pValue, pMandatory, pCond, pFi
throw SqlBuilder.ERROR_UNSUPPORTED_PARAMETER_COMBINATION();
}
SqlBuilder.prototype._and = function(pFieldOrCond, pValue, pMandatory, pCond, pFieldType)
{
var that = this;
return this._addWhere(pFieldOrCond, pValue, pMandatory, pCond, pFieldType, function(pPreparedCondition) {
that._where._previouslyOnlyOr = false;
if (pPreparedCondition.length == 2 && typeof pPreparedCondition[0] == "string" && pPreparedCondition[0] != "" && Array.isArray(pPreparedCondition[1]))
{
if (that.hasCondition())
that._where._sqlStorage += " and ";
that._where._sqlStorage += pPreparedCondition[0];
that._where.preparedValues = that._where.preparedValues.concat(pPreparedCondition[1]);
}
})
}
SqlBuilder.prototype._or = function(pFieldOrCond, pValue, pMandatory, pCond, pFieldType)
{
var that = this;
return this._addWhere(pFieldOrCond, pValue, pMandatory, pCond, pFieldType, function(pPreparedCondition, pAlreadySurroundedByBrackets) {
if (pPreparedCondition.length == 2 && typeof pPreparedCondition[0] == "string" && pPreparedCondition[0] != "" && Array.isArray(pPreparedCondition[1]))
{
if (that._where._previouslyOnlyOr)
{
that._where._sqlStorage = that._where._sqlStorage + " or " + pPreparedCondition[0];
that._where._lastWasOr = true;
}
else if (that.hasCondition() && !that._where._lastWasOr)
{
var cond = pPreparedCondition[0];
if (!pAlreadySurroundedByBrackets)
cond = "(" + pPreparedCondition[0] + ")";
that._where._sqlStorage = "(" + that._where._sqlStorage + ") or " + cond;
that._where._lastWasOr = true;
}
else if (that.hasCondition() && that._where._lastWasOr)
{
var cond = pPreparedCondition[0];
if (!pAlreadySurroundedByBrackets)
cond = "(" + pPreparedCondition[0] + ")";
that._where._sqlStorage = that._where._sqlStorage + " or " + cond;
that._where._lastWasOr = true;
}
else
{
if (!that.hasCondition())
that._where._previouslyOnlyOr = true;
that._where._sqlStorage = pPreparedCondition[0];
}
that._where.preparedValues = that._where.preparedValues.concat(pPreparedCondition[1]);
}
})
}
SqlBuilder.prototype.or = function(pFieldOrCond, pValue, pCond, pFieldType)
{
return this._or(pFieldOrCond, pValue, true, pCond, pFieldType);
}
SqlBuilder.prototype.orIfSet = function(pFieldOrCond, pValue, pCond, pFieldType)
{
return this._or(pFieldOrCond, pValue, false, pCond, pFieldType);
}
SqlBuilder.prototype.and = function(pFieldOrCond, pValue, pCond, pFieldType)
{
return this._and(pFieldOrCond, pValue, true, pCond, pFieldType);
}
SqlBuilder.prototype.andIfSet = function(pFieldOrCond, pValue, pCond, pFieldType)
{
return this._and(pFieldOrCond, pValue, false, pCond, pFieldType);
}
/**
* Sets the order by clause of the sql.
* @param {String} pOrderBy
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment