diff --git a/entity/SlaveAdministration_entity/recordcontainers/db/orderClauseProcess.js b/entity/SlaveAdministration_entity/recordcontainers/db/orderClauseProcess.js
index 15573a0041204ad95d34527e83c5eea5fd65893f..ebce5894dd3bdab6da45463445e5722003d8afc4 100644
--- a/entity/SlaveAdministration_entity/recordcontainers/db/orderClauseProcess.js
+++ b/entity/SlaveAdministration_entity/recordcontainers/db/orderClauseProcess.js
@@ -1,3 +1,3 @@
 import { db, result } from "@aditosoftware/jdito-types";
 
-result.object({"ASYS_SYNCSLAVES.LASTSYNC": db.ASCENDING});
\ No newline at end of file
+result.object({ "ASYS_SYNCSLAVES.LASTSYNC": db.ASCENDING });
\ No newline at end of file
diff --git a/process/PreparedSqlStatement_lib/PreparedSqlStatement_lib.aod b/process/PreparedSqlStatement_lib/PreparedSqlStatement_lib.aod
new file mode 100644
index 0000000000000000000000000000000000000000..45fc5569e2e79988c8a7cf2557d794e6b19f73e8
--- /dev/null
+++ b/process/PreparedSqlStatement_lib/PreparedSqlStatement_lib.aod
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.3.0">
+  <name>PreparedSqlStatement_lib</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/PreparedSqlStatement_lib/process.js</process>
+  <variants>
+    <element>LIBRARY</element>
+  </variants>
+</process>
diff --git a/process/PreparedSqlStatement_lib/process.js b/process/PreparedSqlStatement_lib/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..421142594bff6806ae05e52f6ead6bfebc80497b
--- /dev/null
+++ b/process/PreparedSqlStatement_lib/process.js
@@ -0,0 +1,138 @@
+
+/**
+ * Object containing a prepared sql statement
+ * 
+ * @param {string} [pSqlString] - The sql statement that contains already the placeholders for values: `?`. 
+ *
+ *                                **Never** include values from external sources such as user input, web services, entity-parameters, etc. 
+ *                                directly as pSqlString. Doing so will expose the system to SQL injection attacks because only the 
+ *                                `pPreparedValues` are set as bind parameters and/or are escaped automatically.
+ *
+ * @param {[string, number][]} [pPreparedValues] - The values for the query
+ * @class
+ */
+export function PreparedSqlStatement(pSqlString, pPreparedValues)
+{
+    /**
+     * @type {string}
+     */
+    this.sqlString = "";
+    /**
+     * @type {[string, number][]}
+     */
+    this.preparedValues = [];
+
+    this.append(pSqlString, pPreparedValues);
+}
+
+/**
+ * Creates a new PreparedSqlStatement object from a prepared statement array
+ *
+ * @param {[string, [string, number][]]} preparedArray - The sql statement and its prepared values and types.
+ *
+ *                                **Never** include values from external sources such as web services, entity-parameters, etc. 
+ *                                directly and unverified as parameter here. Doing so will expose the system to SQL injection attacks because the 
+ *                                first element of the array-param is the sql-expression part.
+ *                                This means, that a sql expression could be passed from external sources into the execution.
+ * 
+ *                                Example A, **not okay**:
+ *                                ```
+ *                                var conditionParam = JSON.parse(vars.get("$param.condition_param"));
+ *                                var prepared = PreparedSqlStatement.fromArray(conditionParam);// sql injection possible here
+ *                                entityCondition.and(prepared);
+ *                                ```
+ *                                The parameter could be overwritten by the user with a value like `["); drop table users;", []]`
+ *
+ *                                Example B, **okay**:
+ *                                ```
+ *                                var idList = JSON.parse(vars.get("$param.idList_param"));
+ *                                var prepared = PreparedSqlStatement.fromArray(["MYTABLE.MYID in (?, ?, ?)", idList]);// sql injection not possible
+ *                                entityCondition.and(prepared);
+ *                                ```
+ *                                Because the values are passed as bind parameters, the user may pass `["''); drop table users;"]` as parameter but
+ *                                that is never parsed and executed as sql-expression.
+ * 
+ *                                For this particular example here the best solution however is to use the `SqlBuilder` without using 
+ *                                `PreparedSqlStatement` at all.
+ *
+ *
+ * @return {PreparedSqlStatement} A new PreparedSqlStatement object
+ */
+PreparedSqlStatement.fromArray = function([pSqlString, pPreparedValues])
+{
+    return new PreparedSqlStatement(pSqlString, pPreparedValues);
+};
+
+/**
+ * Creates a prepared statement array that can be used by some db.* methods
+ *
+ * @return {[string, [string, number][]]} The statement as an array
+ */
+PreparedSqlStatement.prototype.toArray = function()
+{
+    return [this.sqlString, this.preparedValues];
+};
+
+/**
+ * Adds the given sql to the statement
+ * 
+ * @param {string} pSqlString - The sql statement that contains already the placeholders for values: `?`. 
+ *
+ *                              **Never** include values from external sources such as user input, web services, entity-parameters, etc. 
+ *                              directly as pSqlString. Doing so will expose the system to SQL injection attacks because only the 
+ *                              `pPreparedValues` are set as bind parameters and/or are escaped automatically.
+ *
+ * @param {[string, number][]} [pPreparedValues] - The values for the query
+ * @return {PreparedSqlStatement} The current object
+ */
+PreparedSqlStatement.prototype.append = function(pSqlString, pPreparedValues)
+{
+    if (pSqlString)
+    {
+        this.sqlString += pSqlString;
+    }
+    if (pPreparedValues)
+    {
+        pPreparedValues.forEach(([value, type]) => this.addPreparedValue(value, type));
+    }
+    return this;
+};
+
+/**
+ *  Adds the sql from a PreparedSqlStatement to the statement
+ * 
+ * @param {PreparedSqlStatement} pPreparedStatement - The sql statement and its prepared values and types
+ * @param {string} [pSeparator] - A string that is added between the existing and new sql
+ * @return {PreparedSqlStatement} The current object
+ */
+PreparedSqlStatement.prototype.appendStatement = function(pPreparedStatement, pSeparator)
+{
+    if (pSeparator == undefined || !this.sqlString)
+    {
+        pSeparator = "";
+    }
+    return this.append(pSeparator + pPreparedStatement.sqlString, pPreparedStatement.preparedValues);
+};
+
+/**
+ * Adds a prepared value
+ * 
+ * @param {string} pValue - The value for the query
+ * @param {number} pType - The type of the value (SQLTYPES.*)
+ * @return {PreparedSqlStatement} The current object
+ */
+PreparedSqlStatement.prototype.addPreparedValue = function(pValue, pType)
+{
+    this.preparedValues.push([pValue, pType]);
+    return this;
+};
+
+/**
+ * Checks if the sql stamtement has no content
+ * 
+ * @returns {boolean} If the statement is empty
+ */
+PreparedSqlStatement.prototype.isEmpty = function()
+{
+    return this.sqlString == "";
+};
\ No newline at end of file
diff --git a/process/Sql_lib/process.js b/process/Sql_lib/process.js
index b5fe4b8975ce7859e1943b046c16cad8cdeb9b82..cac1aed0a9f8bba8c65735848c3abaa59b54131c 100644
--- a/process/Sql_lib/process.js
+++ b/process/Sql_lib/process.js
@@ -1,64 +1,96 @@
-import { db, logging, SQLTYPES, text, translate, util, vars } from "@aditosoftware/jdito-types";
+import { db, logging, project, SQLTYPES, text, translate, util, vars } from "@aditosoftware/jdito-types";
 import { ArrayUtils, Utils } from "Util_lib";
+import { PreparedSqlStatement } from "PreparedSqlStatement_lib";
 
 // see Documentation property of this lib for further explanation
 
+/**
+ * @typedef {[string, number][]} PreparedValueArray
+ * @typedef {[string, PreparedValueArray]} PreparedSqlArray
+ */
+
 /** 
  * Creates a new SqlBuilder object and sets the select clause of the sql.
  * 
- * @param {string|Array|SqlBuilder} pFields You can pass:<br/>
- *                                          - A String is just used AS IT IS. (e.g. "FIRSTNAME, LASTNAME")<br/>
- *                                          - SqlBuilder is used as Subquery<br/>
- *                                          - The array can also contain Strings, SqlBuilder which are just concatenated (e.g. ["FIRSTNAME", "LASTNAME", someSqlBuilderContainingFullSelect])<br/>
+ * @param {string|Array|SqlBuilder} pFields - You can pass:
+ *                                          - A String is just used AS IT IS. (e.g. "FIRSTNAME, LASTNAME")
+ *                                          - SqlBuilder is used as Subquery
+ *                                          - The array can also contain Strings, SqlBuilder which are just concatenated (e.g. ["FIRSTNAME", "LASTNAME", someSqlBuilderContainingFullSelect])
  *                                          Please see .select() for more information and examples.
- * @param {string} [pAlias=currentAlias] This alias is used for fetching the ColumnTypes and also for the .table, .cell, .updateData, ... -functions
+ * @param {string} [pAlias=currentAlias] - This alias is used for fetching the ColumnTypes and also for the .table, .cell, .updateData, ... -functions
  * @return {SqlBuilder} A new SqlBuilder object already containing the provided fields
  * 
  * @example
- * var lastname = "Huber";
+ * let lastname = "Huber";
  * 
- * var persons = newSelect("FIRSTNAME")
+ * let persons = newSelect("FIRSTNAME")
  *                  .from("PERSON")
  *                  .where("PERSON.LASTNAME", lastname)
  *                  .arrayColumn();
  */
 export function newSelect(pFields, pAlias)
 {
-    return new SqlBuilder(pAlias).select(pFields);
+    return new SqlBuilder(pAlias)
+        .select(pFields);
 }
 
 /** 
- * Creates a new SqlBuilder object and calls .where on it.<br/>
- * This is very useful if you just need a condition as you can pass the first condition directly.<br/>
- * Note: Even if you ommit all parameters, you do not have to call .where again. You can directly write .and / .or after newWhere().<br/>
+ * Creates a new SqlBuilder object and calls .where on it.
+ * This is very useful if you just need a condition as you can pass the first condition directly.
+ * Note: Even if you ommit all parameters, you do not have to call .where again. You can directly write .and / .or after newWhere().
  * 
- * @param {string|Array|SqlBuilder} [pFieldOrCond] If this is the only parameter, it is used as Subselect <br/>
- *                                                                     else it is used as Field. <br/>
- *                                                                     Please see .where() for more information and examples.
- * @param {string|SqlBuilder|Array} [pValue] This is the value whitch is used for the condition.<br/>
- *                                                                       Basically it can be nearly everything you need.<br/>
- *                                                                       Please see .where() for more information and examples.
- * @param {string} [pCondition="# = ?"] This is the condition which should be used.<br/>
- *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #<br/>
- *                               ? will be replaced by pValue<br/>
- *                               <strong>IMPORTANT: the # has to be before the ?</strong><br/>
- *                               Please see .where() for more information and examples.
- * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] You can specify which datatype should be used for the prepared statement<br/>
- *                                                                In most cases you don't need this.<br/>
- *                                                                Please see .where() for more information and examples.
- * @param {string} [pAlias=currentAlias] This alias is used for fetching the ColumnTypes and also for the .table, .cell, .updateData, ... -functions
+ * @param {string|PreparedSqlStatement|SqlBuilder|null} [pFieldOrCond] - This can be either a full condition (then it has to be the only parameter provided) or a field.
+ * 
+ *                                                                          If you pass a condition (the only param), these types are allowed:
+ *                                                                           - string: just added as it is
+ *                                                                           - PreparedSqlStatement: a PreparedSqlStatement object is used as it is
+ *                                                                           - SqlBuilder: ONLY THE WHERE-CONDITION is used from it
+ *                                                                           
+ *                                                                          If you pass a field (at least pValue has to be filled), this param provides the field information to
+ *                                                                          load the SQLTYPE for this condition. 
+ *                                                                          It can be provided in the following ways:
+ *                                                                          - a string: ONLY in this form: "TABLENAME.COLUMNNAME" 
+ *                                                                               Note1: you may have problems with names containing a '.' Use the next variant (as array) in this case
+ *                                                                               Note2: if you need a table alias use the next variant (as array)
+ *                                                                          - an array: ["TABLENAME", "COLUMNNAME", "tableAlias"] OR ["TABLENAME", "COLUMNNAME"]
+ *                                                                          - a SqlBuilder: the full select is used as subselect and compared with pValue. 
+ *                                                                               (e.g. select * from PERSON where (select "NAME" from ORGANISATION where ... ) = ?)
+ *                                                                                Note: for this you have to provide pFieldType as the type cannot be calculated from the subselect!
+ *                                                                          Note: this can also be null if you don't need the field and use a pCondition without a #
+ *                                                                     
+ * @param {*} [pValue] - This is the value which is used for the condition. The type can be anything, but some types are handled in different ways:
+ *                          - string: Is just used as value for the prepared statement. Of course it has to fit the type of the db-column.
+ *                                    If the string starts with a '$' it is recognized as a jdito variable and will be resolved automatically,
+ *                                    Use 2 '$' to escape the $ if you don't want it to be treated as jdito variable (see {@link SqlUtils.escapeVars})
+ *                          - Array: If the condition allows multiple values (for example 'in'), the values can be passed in an array.
+ *                          - SqlBuilder: Can be used for sub-queries
+ *                          - PreparedSqlStatement: Can be used for sub-queries
+ *                          - all other types: Will be converted to a string
+ *                          - NOT ALLOWED: Prepared sql arrays - these will raise an error, because they could provoke sql injection
+ * 
+ *                                                                           
+ * @param {string} [pCondition="# = ?"] - This is the condition which should be used to compare the field with the value.
+ *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #
+ *                               ? will be replaced by pValue
+ *                               <strong>IMPORTANT: the # has to be before the ?</strong>
+ *                               
+ * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] - You can specify which datatype should be used for the prepared statement 
+ *                                                                In most cases you don't need this, but it's required if pFieldOrCond is a sub-select or null.
+ *                                                                This is helpful if you for example have a pCondition "year(#) = ?"
+ *                                                                  then the db-field is DATETIME, but the value is INTEGER. In this case you can overwrite the type.
+ * @param {string} [pAlias=currentAlias] - This alias is used for fetching the ColumnTypes and also for the .table, .cell, .updateData, ... -functions
  * @return {SqlBuilder} A new SqlBuilder object which already called .where
  * 
  * @example
  * // examples, how where / whereIfSet could be used in a conditionProcess.
  * //////Example 1/////
- * var cond = newWhereIfSet("CONTACT.PERSON_ID", "$param.PersonId_param")
+ * let cond = newWhereIfSet("CONTACT.PERSON_ID", "$param.PersonId_param")
  *                  .andIfSet("CONTACT.PERSON_ID", JSON.parse(vars.getString("$param.BlacklistPersons_param")), SqlBuilder.NOT_IN())
  *                  
  * result.string(cond.toString());
  * 
  * //////Example 2/////
- * var cond = newWhere();
+ * let cond = newWhere();
  * 
  * // note: we can use .and* now without an extra .where
  * if (SOMECHECKS)
@@ -71,41 +103,67 @@ export function newSelect(pFields, pAlias)
  */
 export function newWhere(pFieldOrCond, pValue, pCondition, pFieldType, pAlias)
 {
-    return new SqlBuilder(pAlias).where(pFieldOrCond, pValue, pCondition, pFieldType);
+    return new SqlBuilder(pAlias)
+        .where(pFieldOrCond, pValue, pCondition, pFieldType);
 }
 
 /** 
- * Creates a new SqlBuilder object and calls .whereIfSet on it.<br/>
- * This is very useful if you just need a condition as you can pass the first condition directly.<br/>
+ * Creates a new SqlBuilder object and calls .whereIfSet on it.
+ * This is very useful if you just need a condition as you can pass the first condition directly.
  * Note: Even if you ommit all parameters, you do not have to call .where again. You can directly write .and / .or after newWhere().
  * 
- * @param {string|Array|SqlBuilder} [pFieldOrCond] If this is the only parameter, it is used as Subselect <br/>
- *                                                                     else it is used as Field. <br/>
- *                                                                     Please see .whereIfSet() for more information and examples.
- * @param {string|SqlBuilder|Array} [pValue] This is the value whitch is used for the condition.<br/>
- *                                                                       Basically it can be nearly everything you need.<br/>
- *                                                                       Please see .whereIfSet() for more information and examples.
- * @param {string} [pCondition="# = ?"] This is the condition which should be used.<br/>
- *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #<br/>
- *                               ? will be replaced by pValue<br/>
- *                               <strong>IMPORTANT: the # has to be before the ?</strong><br/>
- *                               Please see .whereIfSet() for more information and examples.
- * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] You can specify which datatype should be used for the prepared statement<br/>
- *                                                                In most cases you don't need this.<br/>
- *                                                                Please see .whereIfSet() for more information and examples.
- * @param {string} [pAlias=currentAlias] This alias is used for fetching the ColumnTypes and also for the .table, .cell, .updateData, ... -functions
+ * @param {string|PreparedSqlStatement|SqlBuilder|null} [pFieldOrCond] - This can be either a full condition (then it has to be the only parameter provided) or a field.
+ * 
+ *                                                                          If you pass a condition (the only param), these types are allowed:
+ *                                                                           - string: just added as it is
+ *                                                                           - PreparedSqlStatement: a PreparedSqlStatement object is used as it is
+ *                                                                           - SqlBuilder: ONLY THE WHERE-CONDITION is used from it
+ *                                                                           
+ *                                                                          If you pass a field (at least pValue has to be filled), this param provides the field information to
+ *                                                                          load the SQLTYPE for this condition. 
+ *                                                                          It can be provided in the following ways:
+ *                                                                          - a string: ONLY in this form: "TABLENAME.COLUMNNAME" 
+ *                                                                               Note1: you may have problems with names containing a '.' Use the next variant (as array) in this case
+ *                                                                               Note2: if you need a table alias use the next variant (as array)
+ *                                                                          - an array: ["TABLENAME", "COLUMNNAME", "tableAlias"] OR ["TABLENAME", "COLUMNNAME"]
+ *                                                                          - a SqlBuilder: the full select is used as subselect and compared with pValue. 
+ *                                                                               (e.g. select * from PERSON where (select "NAME" from ORGANISATION where ... ) = ?)
+ *                                                                                Note: for this you have to provide pFieldType as the type cannot be calculated from the subselect!
+ *                                                                          Note: this can also be null if you don't need the field and use a pCondition without a #
+ *                                                                     
+ * @param {*} [pValue] - This is the value which is used for the condition. The type can be anything, but some types are handled in different ways:
+ *                          - string: Is just used as value for the prepared statement. Of course it has to fit the type of the db-column.
+ *                                    If the string starts with a '$' it is recognized as a jdito variable and will be resolved automatically,
+ *                                    Use 2 '$' to escape the $ if you don't want it to be treated as jdito variable (see {@link SqlUtils.escapeVars})
+ *                          - Array: If the condition allows multiple values (for example 'in'), the values can be passed in an array.
+ *                          - SqlBuilder: Can be used for sub-queries
+ *                          - PreparedSqlStatement: Can be used for sub-queries
+ *                          - all other types: Will be converted to a string
+ *                          - NOT ALLOWED: Prepared sql arrays - these will raise an error, because they could provoke sql injection
+ * 
+ *                                                                           
+ * @param {string} [pCondition="# = ?"] - This is the condition which should be used to compare the field with the value.
+ *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #
+ *                               ? will be replaced by pValue
+ *                               <strong>IMPORTANT: the # has to be before the ?</strong>
+ *                               
+ * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] - You can specify which datatype should be used for the prepared statement 
+ *                                                                In most cases you don't need this, but it's required if pFieldOrCond is a sub-select or null.
+ *                                                                This is helpful if you for example have a pCondition "year(#) = ?"
+ *                                                                  then the db-field is DATETIME, but the value is INTEGER. In this case you can overwrite the type.
+ * @param {string} [pAlias=currentAlias] - This alias is used for fetching the ColumnTypes and also for the .table, .cell, .updateData, ... -functions
  * @return {SqlBuilder} A new SqlBuilder object which already called .whereIfSet
  * 
  * @example
  * // examples, how where / whereIfSet could be used in a conditionProcess.
  * //////Example 1/////
- * var cond = newWhereIfSet("CONTACT.PERSON_ID", "$param.PersonId_param")
+ * let cond = newWhereIfSet("CONTACT.PERSON_ID", "$param.PersonId_param")
  *                  .andIfSet("CONTACT.PERSON_ID", JSON.parse(vars.getString("$param.BlacklistPersons_param")), SqlBuilder.NOT_IN())
  *                  
  * result.string(cond.toString());
  * 
  * //////Example 2/////
- * var cond = newWhere();
+ * let cond = newWhere();
  * 
  * // note: we can use .and* now without an extra .where
  * if (SOMECHECKS)
@@ -118,31 +176,48 @@ export function newWhere(pFieldOrCond, pValue, pCondition, pFieldType, pAlias)
  */
 export function newWhereIfSet(pFieldOrCond, pValue, pCondition, pFieldType, pAlias)
 {
-    return new SqlBuilder(pAlias).whereIfSet(pFieldOrCond, pValue, pCondition, pFieldType);
+    return new SqlBuilder(pAlias)
+        .whereIfSet(pFieldOrCond, pValue, pCondition, pFieldType);
 }
 
 /**
- * Object for building sqls. The main purpose of this is to make it easy to use prepared statements.<br/>
- * You should ALWAYS use prepared statemnts for Security and maybe also for performance reasons.<br/>
- * If you are not used to use prepared statements all the time you WILL forget to use it, when it's really needed. (eg. direct user input, not just ids)<br/>
- * <br/>
- * This can also be useful to build complex sqls where parts should be added<br/>
- * dynamically while keeping the code clean.<br/>
- * <br/>
- * There exist some shortcut funtions<br/>
- * - if you need a full select use newSelect(...)<br/>
+ * Object for building sqls. The main purpose of this is to make it easy to use prepared statements.
+ * You should ALWAYS use prepared statemnts for Security and maybe also for performance reasons.
+ * If you are not used to use prepared statements all the time you WILL forget to use it, when it's really needed. (eg. direct user input, not just ids)
+ * 
+ * This can also be useful to build complex sqls where parts should be added
+ * dynamically while keeping the code clean.
+ * 
+ * There exist some shortcut funtions
+ * - if you need a full select use newSelect(...)
  * - if you need only a condition use newWhere(...) or newWhereIfSet(...) 
  * 
- * @param {string} [pAlias=currentAlias] This alias is used for fetching the ColumnTypes and also for the .table, .cell, .updateData, ... -functions
+ * @param {string} [pAlias=currentAlias] - This alias is used for fetching the ColumnTypes and also for the .table, .cell, .updateData, ... -functions
+ * @property {PreparedSqlStatement} _select
+ * @property {PreparedSqlStatement} _from
+ * @property {string} _tableName - Caches the table name of a condition, used for insert/update/delete
+ * @property {PreparedSqlStatement[]} _joins
+ * @property {PreparedSqlStatement} _groupBy
+ * @property {PreparedSqlStatement} _having
+ * @property {PreparedSqlStatement} _orderBy
+ * @property {PreparedSqlStatement[]} _unions
+ * @property {number} _startRow
+ * @property {number} _pageSize
+ * @property {boolean} _hasMoreRows
+ * @property {string} _subselectAlias
+ * @property {PreparedSqlStatement} _where
+ * @property {SqlBuilder._WhereStatus} _whereStatus
  * @class
  */
-export function SqlBuilder (pAlias)
+export function SqlBuilder(pAlias)
 {
     if(!(this instanceof SqlBuilder)) 
+    {
         throw SqlBuilder._ERROR_INSTANCIATE_WITH_NEW();
+    }
     this._select = null;
     this._from = null;
-    this._tableName = null; //for insert/update/delete
+    this._tableName = null;
     this._joins = [];
     this._groupBy = null;
     this._having = null;
@@ -157,203 +232,215 @@ export function SqlBuilder (pAlias)
     
     this._subselectAlias = null;
     
-    this._where = {};
+    this._where = null;
+    /**
+     * @typedef {object} SqlBuilder._WhereStatus
+     * @property {boolean} _lastWasOr - If the last condition was an OR. For better bracket-placement
+     * @property {boolean} _previouslyOnlyOr - Also for better bracket-placement
+     * @property {boolean} _whereWasCalled - .where has always to be called first for a better semantic
+     */
+    this._whereStatus = null;
     this._initWhere();
 }
 
 /**
- * @return {Symbol}
+ * @return {symbol}
  */
-SqlBuilder.getCanBuildSqlSymbol = function ()
+SqlBuilder.getCanBuildSqlSymbol = function()
 {
-    return Symbol["for"]("canBuildSql");
-}
+    return Symbol.for("canBuildSql");
+};
 
-SqlBuilder.defineCanBuildSql = function (pObject)
+/**
+ * @param {object} pObject
+ */
+SqlBuilder.defineCanBuildSql = function(pObject)
 {
     pObject[SqlBuilder.getCanBuildSqlSymbol()] = true;
-}
+};
 
-SqlBuilder.checkCanBuildSql = function (pObject)
+/**
+ * @param {object} pObject
+ */
+SqlBuilder.checkCanBuildSql = function(pObject)
 {
     return pObject[SqlBuilder.getCanBuildSqlSymbol()];
-}
+};
 
 SqlBuilder.defineCanBuildSql(SqlBuilder.prototype);
 
 /**
- * Deep copies the SqlBuilder object and returns a new one.<br/>
+ * Deep copies the SqlBuilder object and returns a new one.
  * Use this if you want to add for example add additional parameters without modifying the current builder.
+ *
  * @return a full copy of the current SqlBuilder
  */
 SqlBuilder.prototype.copy = function()
 {
     return Utils.clone(this);
-}
+};
 
 // errors which are thrown by the SqlBuilder
 SqlBuilder._ERROR_INSTANCIATE_WITH_NEW = function() 
 {
-    return new Error(translate.text("SqlBuilder must be instanciated with 'new' or one of the factory methods (newSelect, newWhere, newWhereIfSet)"));
-}
+    return new Error("SqlBuilder must be instanciated with 'new' or one of the factory methods (newSelect, newWhere, newWhereIfSet)");
+};
 
 SqlBuilder._ERROR_INVALID_CONDITION_VALUE_TYPE = function() 
 {
-    return new Error(translate.text("SqlBuilder: invalid value-type for pCondition"));
-}
+    return new Error("SqlBuilder: invalid value-type for pCondition");
+};
 
 SqlBuilder._ERROR_NO_CONDITION = function() 
 {
-    return new Error(translate.text("SqlBuilder: if you use a subQuery (e.g. SqlBuilder) you have to provide pCondition (e.g. \"exists ?\")"));
-}
+    return new Error("SqlBuilder: if you use a subQuery (e.g. SqlBuilder) you have to provide pCondition (e.g. \"exists ?\")");
+};
 
 SqlBuilder._ERROR_INVALID_SUBQUERY_TYPE = function() 
 {
-    return new Error(translate.text("SqlBuilder: invalid value-type for pFieldOrCond. It can be a fully qualified SqlBuilder (e.g. select, from, ... have to be set) or an jdito-prepared-statement array"));
-}
+    return new Error("SqlBuilder: invalid value-type for pFieldOrCond. It can be a fully qualified SqlBuilder (e.g. select, from, ... have to be set) or an jdito-prepared-statement array");
+};
 
 SqlBuilder._ERROR_VALUE_IS_MANDATORY = function() 
 {
-    return new Error(translate.text("SqlBuilder: pValue (or pFieldOrCond if only one param) is not allowed to be null, undefined or []. (use *IfSet functions if you need optional conditions which are just ignored if value is null or undefined)"));
-}
+    return new Error("SqlBuilder: pValue (or pFieldOrCond if only one param) is not allowed to be null, undefined or []. (use *IfSet functions if you need optional conditions which are just ignored if value is null or undefined)");
+};
 
 SqlBuilder._ERROR_VALUE_IS_MANDATORY_JDITO_VAR = function() 
 {
-    return new Error(translate.text("SqlBuilder: pValue has to be a jdito variable which returns something different than null. (use *IfSet functions if you need optional conditions which are just ignored if value is null or undefined)"));
-}
+    return new Error("SqlBuilder: pValue has to be a jdito variable which returns something different than null. (use *IfSet functions if you need optional conditions which are just ignored if value is null or undefined)");
+};
 
 SqlBuilder._ERROR_UNSUPPORTED_PARAMETER_COMBINATION = function() 
 {
-    return new Error(translate.text("SqlBuilder: unsupportet parameter combination"));
-}
+    return new Error("SqlBuilder: unsupportet parameter combination");
+};
 
 SqlBuilder._ERROR_NO_TABLE = function()
 {
-    return new Error(translate.text("SqlBuilder.deleteDat/updateData: You have to specify a tablename"));
-}
+    return new Error("SqlBuilder.deleteDat/updateData: You have to specify a tablename");
+};
 
 SqlBuilder._ERROR_NO_PARAMETER_PROVIDED = function()
 {
-    return new Error(translate.text("SqlBuilder: You have to specify at least one parameter"));
-}
+    return new Error("SqlBuilder: You have to specify at least one parameter");
+};
 
 SqlBuilder._ERROR_WHERE_NOT_FIRST = function()
 {
-    return new Error(translate.text("SqlBuilder: .where has to be called before following and/or."));
-}
+    return new Error("SqlBuilder: .where has to be called before following and/or.");
+};
 
 SqlBuilder._ERROR_ONLY_ONE_WHERE = function()
 {
-    return new Error(translate.text("SqlBuilder: .where has to be called only one time. Use and/or for further conditions."));
-}
+    return new Error("SqlBuilder: .where has to be called only one time. Use and/or for further conditions.");
+};
 
-SqlBuilder._ERROR_INCOMPLETE_SELECT = function ()
+SqlBuilder._ERROR_INCOMPLETE_SELECT = function()
 {
-    return new Error(translate.text("SqlBuilder: select and from were expected, but not provided."));
-}
+    return new Error("SqlBuilder: select and from were expected, but not provided.");
+};
 
-SqlBuilder._ERROR_CONDITION_IS_MANDATORY = function ()
+SqlBuilder._ERROR_CONDITION_IS_MANDATORY = function()
 {
-    return new Error(translate.text("SqlBuilder: You have to provide a subquery as SqlBuilder, prepared-array or string"));
-}
+    return new Error("SqlBuilder: You have to provide a subquery as SqlBuilder, prepared-array or string");
+};
 
-SqlBuilder._ERROR_SUBSELECT_AS_FIELD_NOT_COMPLETE = function ()
+SqlBuilder._ERROR_SUBSELECT_AS_FIELD_NOT_COMPLETE = function()
 {
-    return new Error(translate.text("SqlBuilder: If pFieldOrCond is a SqlBuilder & pValue is provided, pFieldOrCond has to be a full SqlBuilder which will be used as subselect"));
-}
+    return new Error("SqlBuilder: If pFieldOrCond is a SqlBuilder & pValue is provided, pFieldOrCond has to be a full SqlBuilder which will be used as subselect");
+};
 
-SqlBuilder._ERROR_SUBSELECT_AS_FIELD_NO_FIELD_TYPE = function ()
+SqlBuilder._ERROR_SUBSELECT_AS_FIELD_NO_FIELD_TYPE = function()
 {
-    return new Error(translate.text("SqlBuilder: If pFieldOrCond is a SqlBuilder & pValue is provided, you have to provide also pFieldType, as the type cannot be calculated from pFieldOrCond because it is a subselect"));
-}
+    return new Error("SqlBuilder: If pFieldOrCond is a SqlBuilder & pValue is provided, you have to provide also pFieldType, as the type cannot be calculated from pFieldOrCond because it is a subselect");
+};
 
-SqlBuilder._ERROR_CONDITION_WRONG_FORMAT = function ()
+SqlBuilder._ERROR_CONDITION_WRONG_FORMAT = function()
 {
-    return new Error(translate.text("SqlBuilder: The '#' in pCondition has to occur before the '?' and '?' has to occur 1 time, '#' has to occur 1 or 0 times."));
-}
+    return new Error("SqlBuilder: The '#' in pCondition has to occur before the '?' and '?' has to occur 1 time, '#' has to occur 1 or 0 times.");
+};
 
-SqlBuilder._ERROR_NOT_BOOLEAN = function ()
+SqlBuilder._ERROR_NOT_BOOLEAN = function()
 {
-    return new Error(translate.text("pExecuteOnlyIfConditionExists has to be of type boolean. This parameter controls what happens if the condition is empty (select / delete all or nothing)"));
-}
+    return new Error("pExecuteOnlyIfConditionExists has to be of type boolean. This parameter controls what happens if the condition is empty (select / delete all or nothing)");
+};
 
-SqlBuilder._ERROR_UPDATE_VALUES_INVALID = function ()
+SqlBuilder._ERROR_UPDATE_VALUES_INVALID = function()
 {
-    return new Error(translate.text("SqlBuilder: The provided values object for updateFields is invalid or is not an object."));
-}
+    return new Error("SqlBuilder: The provided values object for updateFields is invalid or is not an object.");
+};
 
-SqlBuilder._ERROR_PAGESIZE_INVALID = function ()
+SqlBuilder._ERROR_PAGESIZE_INVALID = function()
 {
-    return new Error(translate.text("SqlBuilder: The pagesize is not set or is not a number."));
-}
+    return new Error("SqlBuilder: The pagesize is not set or is not a number.");
+};
 
-SqlBuilder._ERROR_NOT_A_FUNCTION = function ()
+SqlBuilder._ERROR_NOT_A_FUNCTION = function()
 {
-    return new Error(translate.text("SqlBuilder: The provided callback function is not a function."));
-}
+    return new Error("SqlBuilder: The provided callback function is not a function.");
+};
+
+SqlBuilder._ERROR_SQL_ARRAY_AS_VALUE_NOT_ALLOWED = function()
+{
+    return new Error("SqlBuilder: Prepared SQL arrays are not allowed as values for conditions. You can use a SqlBuilder or PreparedSqlStatement object to pass a subquery instead.");
+};
+
+SqlBuilder._ERROR_SQL_ARRAY_AS_FIELD_OR_COND_NOT_ALLOWED = function()
+{
+    return new Error("SqlBuilder: Prepared SQL arrays are not allowed as fields or conditions. You can use a SqlBuilder or PreparedSqlStatement object to pass a condition instead.");
+};
+
+SqlBuilder._ERROR_PREPARED_SQL_AS_FIELD_NOT_ALLOWED = function()
+{
+    return new Error("SqlBuilder: PreparedSqlStatement objects are not allowed as fields. To use a PreparedSqlStatement, it has to be a full condition and the only argument.");
+};
+
 /**
  * Alternative way of creating a new SqlBuilder object that allows to use
  * methods on it directly without having to put brackets around it
  * 
  * @return {SqlBuilder} a new SqlBuilder object
  * 
- * @example 
- * var query = SqlBuilder.begin()
- *   .select("ORGANISATION.NAME, FIRSTNAME, LASTNAME")
- *   .from("PERSON")
- *   .join("CONTACT", "CONTACT.PERSON_ID = PERSON.PERSONID")
- *   .leftJoin("ORGANISATION", SqlCondition.begin()
- *       .and("CONTACT.ORGANISATION_ID = ORGANISATION.ORGANISATIONID")
- *       .andPrepare("ORGANISATION.NAME", "S%", "# like ?")
- *       .build("1=2"))
- *   .where(SqlCondition.begin()
- *       .andPrepare("CONTACT.STATUS", $KeywordRegistry.contactStatus$active())
- *       .build("1=2"));
- * 
- * if (getCountry) //changing and adding parts
- * {
- *   query.select("ORGANISATION.NAME, FIRSTNAME, LASTNAME, COUNTRY");
- *   query.leftJoin("ADDRESS", "CONTACT.ADDRESS_ID = ADDRESS.ADDRESSID");
- * }
- *   
- * var data = db.table(query.build());
- * 
  * @deprecated using .begin is deprecated as it's now possible to write "new SqlBuilder().select(...).from(...)....
-               You can now use "newSelect(...)", "newWhere(...)", "newWhereIfSet(...)" or "new SqlBuilder()" to create a new SqlBuilder instance.
-               For further SqlBuilder usage see the documentation-property of the Sql_lib.
+ * You can now use "newSelect(...)", "newWhere(...)", "newWhereIfSet(...)" or "new SqlBuilder()" to create a new SqlBuilder instance.
+ * For further SqlBuilder usage see the documentation-property of the Sql_lib.
  */
-SqlBuilder.begin = function ()
+SqlBuilder.begin = function()
 {
     return new SqlBuilder();
-}
-
+};
 
 /**
  * Builds the sql and uses SqlUtils.translateXXXWithQuotes to make a string out of it.
- * @param {string} [pDefaultConditionIfNone=""] the default condition string to use if the SqlBuilder contains no condition. In most cases you won't need this
- * @param {boolean} [pForceAsStatement=false] forces the use of SqlUtils.translateStatementWithQuotes even if it's no full statement. This is needed for example if you do not want brakets around the generated statement
+ *
+ * @param {string} [pDefaultConditionIfNone=""] - the default condition string to use if the SqlBuilder contains no condition. In most cases you won't need this
+ * @param {boolean} [pForceAsStatement=false] - forces the use of SqlUtils.translateStatementWithQuotes even if it's no full statement. This is needed for example if you do not want brakets around the generated statement
  * @return {string} the sql as string
  */
 SqlBuilder.prototype.toString = function(pDefaultConditionIfNone, pForceAsStatement)
 {
-    var built = this.build(pDefaultConditionIfNone)
-    
+    let built = this.build(pDefaultConditionIfNone);
     if (built[0] !== "")
     {
         if (!pForceAsStatement && !this.isFullSelect() && (this.hasCondition() || pDefaultConditionIfNone))
+        {
             return SqlUtils.translateConditionWithQuotes(built, this.alias);
+        }
         else
+        {
             return SqlUtils.translateStatementWithQuotes(built, this.alias);
+        }
     }
-    
     return "";
-}
+};
 
 /**
  * Sets the select clause of the sql.
- * @param {string|Array|SqlBuilder} pFields You can pass:<br/>
- *                                          - A String is just used AS IT IS. (e.g. "FIRSTNAME, LASTNAME")<br/>
- *                                          - SqlBuilder is used as Subquery<br/>
+ *
+ * @param {string|Array|SqlBuilder} pFields - You can pass:
+ *                                          - A String is just used AS IT IS. (e.g. "FIRSTNAME, LASTNAME")
+ *                                          - SqlBuilder is used as Subquery
  *                                          - The array can also contain Strings, SqlBuilder which are just concatenated (e.g. ["FIRSTNAME", "LASTNAME", someSqlBuilderContainingFullSelect])
  * 
  * @return {SqlBuilder} current SqlBuilder object
@@ -362,25 +449,27 @@ SqlBuilder.prototype.select = function(pFields)
 {
     this._select = SqlBuilder._getStatement(pFields, "select", undefined, true, true);
     return this;
-}
+};
 
 /**
  * Sets the select clause of the sql with distinct.
+ *
  * @param {string|string[]} pFields
  * @return {SqlBuilder} current SqlBuilder object
  */
-SqlBuilder.prototype.selectDistinct = function (pFields)
+SqlBuilder.prototype.selectDistinct = function(pFields)
 {
     this._select = SqlBuilder._getStatement(pFields, "select distinct", undefined, true, true);
     return this;
-}
+};
 
 /**
  * Sets the select clause to "select count(...)"
- * @param {string} [pField=*]   sql column to count, if omitted "count(*)" will be used
+ *
+ * @param {string} [pField="*"] - sql column to count, if omitted "count(*)" will be used
  * @return {SqlBuilder} current SqlBuilder object
  */
-SqlBuilder.prototype.selectCount = function (pField)
+SqlBuilder.prototype.selectCount = function(pField)
 {
     if (pField == undefined)
     {
@@ -388,11 +477,11 @@ SqlBuilder.prototype.selectCount = function (pField)
     }
     this._select = SqlBuilder._getStatement(pField, "select count(", ")", true, true);
     return this;
-}
-
+};
 
 /**
  * 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
@@ -401,7 +490,7 @@ SqlBuilder.prototype.subselectAlias = function(pSubselectAlias)
 {
     this._subselectAlias = pSubselectAlias;
     return this;
-}
+};
 
 /**
  * Sets the table that is used for insert/update/delete functions.
@@ -409,442 +498,448 @@ SqlBuilder.prototype.subselectAlias = function(pSubselectAlias)
  * @param {string} pTable
  * @return {SqlBuilder} current SqlBuilder object
  */
-SqlBuilder.prototype.tableName = function (pTable)
+SqlBuilder.prototype.tableName = function(pTable)
 {
     this._tableName = pTable;
     return this;
-}
+};
 
 /**
- * Sets the from clause of the sql.<br/>
- * <br/>
- * Note: It is recommended to add joins via the .join functions.<br/>
- *       But in some cases you may already get a full from clause including the joins. In this case it is also possible to include them in the from-string.<br/>
+ * Sets the from clause of the sql.
+ * 
+ * Note: It is recommended to add joins via the .join functions.
+ *       But in some cases you may already get a full from clause including the joins. In this case it is also possible to include them in the from-string.
  * 
- * @param {string|SqlBuilder} pTable if it is a String, it is used as it is as table<br/>
+ * @param {string|SqlBuilder} pTable - if it is a String, it is used as it is as table
  *                                   if it is a SqlBuilder, it is used as subselect: e.g. select * from (select FIRSTNAME from PERSON)
- * @param {string} [pTableAlias] table alias
+ * @param {string} [pTableAlias] - table alias
  * @return {SqlBuilder} current SqlBuilder object
  */
 SqlBuilder.prototype.from = function(pTable, pTableAlias)
 {
     this._from = SqlBuilder._getStatement(pTable, "", pTableAlias, false, (pTableAlias ? false : true));
     if (typeof(pTable) === "string")
+    {
         this._tableName = pTable;
+    }
     return this;
-}
+};
 
 /**
  * Adds a join clause to the sql.
- * @param {string|SqlBuilder} pTable if it is a String, it is used as it is as table<br/>
+ *
+ * @param {string|SqlBuilder} pTable - if it is a String, it is used as it is as table
  *                                   if it is a SqlBuilder, it is used as subselect: e.g. select * from Table1 join (select FIRSTNAME from PERSON) on ...
- * @param {string|SqlBuilder} [pCondition] The where condition. This can be<br/>
- *                                                - a string (without the where keyword)<br/>
+ * @param {string|SqlBuilder|Array} [pCondition] - The where condition. This can be
+ *                                                - a string (without the where keyword)
  *                                                - a SqlBuilder NOTE: only the condition is used from it
  *
- * @param {string} [pTableAlias] This alias is used to add an alias to the tablename 
- * @param {string} [pPrefix] string before the join, for example "left", "right"
- * @param {string} [pReplacementForWordJoin] if this is set, this is used instead of the word "join". Needed for e.g. OUTER APPLY in MSSQL
+ * @param {string} [pTableAlias] - This alias is used to add an alias to the tablename 
+ * @param {string} [pPrefix] - string before the join, for example "left", "right"
+ * @param {string} [pReplacementForWordJoin] - if this is set, this is used instead of the word "join". Needed for e.g. OUTER APPLY in MSSQL
  * @return {SqlBuilder} current SqlBuilder object
  */
 SqlBuilder.prototype.join = function(pTable, pCondition, pTableAlias, pPrefix, pReplacementForWordJoin)
 {
-    // support for deprecated SqlCondition
-    if (pCondition instanceof SqlCondition)
-    {
-        pCondition = newWhere(pCondition);
-        logging.log("Warning: using .where with a SqlCondition as pFieldOrCond is deprecated. The SqlCondition will be removed in version >= 2020.x\n"
-                    + "For SqlBuilder usage see the documentation-property of the Sql_lib.");
-    }
-    
-    var prefix = (pReplacementForWordJoin ? pReplacementForWordJoin : "join");
+    let prefix = (pReplacementForWordJoin ? pReplacementForWordJoin : "join");
     if (pPrefix)
+    {
         prefix = pPrefix + " " + prefix;
+    }
     
-    var postfix = pCondition ? "on" : "";
+    let postfix = pCondition ? "on" : "";
     
     if (pTableAlias)
+    {
         postfix = pTableAlias + " " + postfix;
+    }
     else if (pTable instanceof SqlBuilder && pTable._subselectAlias)
+    {
         postfix = pTable._subselectAlias + " " + postfix;
+    }
     
-    var joinPart = SqlBuilder._getStatement(pTable, prefix, postfix.trim());
+    let joinPart = SqlBuilder._getStatement(pTable, prefix, postfix.trim());
     
     if (pCondition)
     {
         if (pCondition instanceof SqlBuilder)
-            pCondition = [pCondition._where.sqlStorage, pCondition._where.preparedValues]
+        {
+            pCondition = pCondition._where.toArray();
+        }
 
-        var conditionPart = SqlBuilder._getStatement(pCondition);
+        let conditionPart = SqlBuilder._getStatement(pCondition);
 
-        joinPart.sqlStorage += " " + conditionPart.sqlStorage;
-        joinPart.preparedValues = joinPart.preparedValues.concat(conditionPart.preparedValues);
+        joinPart.appendStatement(conditionPart, " ");
     }
-    
-    this._joins.push(joinPart)
+    this._joins.push(joinPart);
     return this;
-}
+};
 
 /**
  * Adds a left join clause to the sql.
  * 
- * @param {string|SqlBuilder} pTable if it is a String, it is used as it is as table<br/>
+ * @param {string|SqlBuilder} pTable - if it is a String, it is used as it is as table
  *                                   if it is a SqlBuilder, it is used as subselect: e.g. select * from Table1 join (select FIRSTNAME from PERSON) on ...
- * @param {string|SqlBuilder} [pCondition] The where condition. This can be<br/>
- *                                                - a string (without the where keyword)<br/>
+ * @param {string|SqlBuilder} [pCondition] - The where condition. This can be
+ *                                                - a string (without the where keyword)
  *                                                - a SqlBuilder NOTE: only the condition is used from it
  *
- * @param {string} [pTableAlias] This alias is used to add an alias to the tablename 
+ * @param {string} [pTableAlias] - This alias is used to add an alias to the tablename 
  * @return {SqlBuilder} current SqlBuilder object
  */
 SqlBuilder.prototype.leftJoin = function(pTable, pCondition, pTableAlias)
 {
     return this.join(pTable, pCondition, pTableAlias, "left");
-}
+};
 
 /**
  * Adds a right join clause to the sql.
  * 
- * @param {string|SqlBuilder} pTable if it is a String, it is used as it is as table<br/>
+ * @param {string|SqlBuilder} pTable - if it is a String, it is used as it is as table
  *                                   if it is a SqlBuilder, it is used as subselect: e.g. select * from Table1 join (select FIRSTNAME from PERSON) on ...
- * @param {string|SqlBuilder} [pCondition] The where condition. This can be<br/>
- *                                                - a string (without the where keyword)<br/>
+ * @param {string|SqlBuilder} [pCondition] - The where condition. This can be
+ *                                                - a string (without the where keyword)
  *                                                - a SqlBuilder NOTE: only the condition is used from it
  *
- * @param {string} [pTableAlias] This alias is used to add an alias to the tablename 
+ * @param {string} [pTableAlias] - This alias is used to add an alias to the tablename 
  * @return {SqlBuilder} current SqlBuilder object
  */
 SqlBuilder.prototype.rightJoin = function(pTable, pCondition, pTableAlias)
 {
     return this.join(pTable, pCondition, pTableAlias, "right");
-}
+};
 
 /**
- * Throws an error if pValue is null, undefined or a SqlBuilder without condition (or if pValue is a $-variable: error if the result of it is null or undefined)<br/>
- * Also throws an error if pFieldOrCond is the only parameter and it is null<br/>
- * <br/>
- * Starts the where clause of the SQL. You may pass the first condition with it.<br/>
- * But you can also call this function without any parameter and add the conditions with subsequent .and / .or<br/>
- * <br/>
- * This method exists mainly for semantic reasons and can only be callled once.<br/>
- * As shourtcut you could use the newWhere(...) function.<br/>
- * 
- * @param {string|Array|SqlBuilder|null} [pFieldOrCond] If this is the only parameter, it is used as Condition <br/>
- *                                                                          else it is used as Field.<br/>
- *                                                                     <br/>
- *                                                                          If you use it as Subselect (the only param), it can be:<br/>
- *                                                                           - a string: just added as it is<br/>
- *                                                                           - a PreparedSqlArray: an Array in this form: [sqlStr, [[value1, type1], [valueN, typeN]]]<br/>
- *                                                                                                 the sql is just used as it is.<br/>
- *                                                                           - a SqlBuilder: ONLY THE CONDITION is used from it<br/>
- *                                                                           <br/>
- *                                                                          If you use it as a Field (at least pValue has to be filled), this param provides the field information to<br/>
- *                                                                          load the SQLTYPE for this condition. <br/>
- *                                                                          It can be provided in the following ways:<br/>
- *                                                                          - a string: ONLY in this form: "TABLENAME.COLUMNNAME" <br/>
- *                                                                               Note1: you may have problems with names containing a '.' Use the next variant (as array) in this case<br/>
- *                                                                               Note2: if you need a table alias use the next variant (as array)<br/>
- *                                                                          - a array: ["TABLENAME", "COLUMNNAME", "tableAlias"] OR ["TABLENAME", "COLUMNNAME"]<br/>
- *                                                                          - a SqlBuilder: the full select is used as subselect and compared with pValue. <br/>
- *                                                                               (e.g. select * from PERSON where (select "NAME" from ORGANISATION where ... ) = ?)<br/>
- *                                                                                Note: for this you have to provide pFieldType as the type cannot be calculated from the subselect!<br/>
+ * Throws an error if pValue is null, undefined or a SqlBuilder without condition (or if pValue is a $-variable: error if the result of it is null or undefined)
+ * Also throws an error if pFieldOrCond is the only parameter and it is null
+ * 
+ * Starts the where clause of the SQL. You may pass the first condition with it.
+ * But you can also call this function without any parameter and add the conditions with subsequent .and / .or
+ * 
+ * This method exists mainly for semantic reasons and can only be callled once.
+ * As shourtcut you could use the newWhere(...) function.
+ * 
+ * @param {string|PreparedSqlStatement|SqlBuilder|null} [pFieldOrCond] - This can be either a full condition (then it has to be the only parameter provided) or a field.
+ * 
+ *                                                                          If you pass a condition (the only param), these types are allowed:
+ *                                                                           - string: just added as it is
+ *                                                                           - PreparedSqlStatement: a PreparedSqlStatement object is used as it is
+ *                                                                           - SqlBuilder: ONLY THE WHERE-CONDITION is used from it
+ *                                                                           
+ *                                                                          If you pass a field (at least pValue has to be filled), this param provides the field information to
+ *                                                                          load the SQLTYPE for this condition. 
+ *                                                                          It can be provided in the following ways:
+ *                                                                          - a string: ONLY in this form: "TABLENAME.COLUMNNAME" 
+ *                                                                               Note1: you may have problems with names containing a '.' Use the next variant (as array) in this case
+ *                                                                               Note2: if you need a table alias use the next variant (as array)
+ *                                                                          - an array: ["TABLENAME", "COLUMNNAME", "tableAlias"] OR ["TABLENAME", "COLUMNNAME"]
+ *                                                                          - a SqlBuilder: the full select is used as subselect and compared with pValue. 
+ *                                                                               (e.g. select * from PERSON where (select "NAME" from ORGANISATION where ... ) = ?)
+ *                                                                                Note: for this you have to provide pFieldType as the type cannot be calculated from the subselect!
  *                                                                          Note: this can also be null if you don't need the field and use a pCondition without a #
  *                                                                     
- * @param {string|SqlBuilder|Array} [pValue] This is the value which is used for the condition.<br/>
- *                                                                       Basically it can be nearly everything you need.<br/>
- *                                                                       - String, etc: is just used as value for the prepared statement. Of course it has to fit the type of the db-column<br/>
- *                                                                       - String starting with '$' is treated as jdito-variable: is loaded with vars.getString("$..."). <br/>
- *                                                                        Note: Use 2 '$' to escape the $ if you don't want it to be treated as JditoVar
+ * @param {*} [pValue] - This is the value which is used for the condition. The type can be anything, but some types are handled in different ways:
+ *                          - string: Is just used as value for the prepared statement. Of course it has to fit the type of the db-column.
+ *                                    If the string starts with a '$' it is recognized as a jdito variable and will be resolved automatically,
+ *                                    Use 2 '$' to escape the $ if you don't want it to be treated as jdito variable (see {@link SqlUtils.escapeVars})
+ *                          - Array: If the condition allows multiple values (for example 'in'), the values can be passed in an array.
+ *                          - SqlBuilder: Can be used for sub-queries
+ *                          - PreparedSqlStatement: Can be used for sub-queries
+ *                          - all other types: Will be converted to a string
+ *                          - NOT ALLOWED: Prepared sql arrays - these will raise an error, because they could provoke sql injection
+ * 
  *                                                                           
- * @param {string} [pCondition="# = ?"] This is the condition which should be used to compare the field with the value.<br/>
- *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #<br/>
- *                               ? will be replaced by pValue<br/>
+ * @param {string} [pCondition="# = ?"] - This is the condition which should be used to compare the field with the value.
+ *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #
+ *                               ? will be replaced by pValue
  *                               <strong>IMPORTANT: the # has to be before the ?</strong>
- * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] You can specify which datatype should be used for the prepared statement <br/>
- *                                                                In most cases you don't need this.<br/>
- *                                                                This is helpful if you for example have a pCondition "year(#) = ?"<br/>
+ *                               
+ * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] - You can specify which datatype should be used for the prepared statement 
+ *                                                                In most cases you don't need this, but it's required if pFieldOrCond is a sub-select or null.
+ *                                                                This is helpful if you for example have a pCondition "year(#) = ?"
  *                                                                  then the db-field is DATETIME, but the value is INTEGER. In this case you can overwrite the type.
- *                                                                  
+ *
  * @return {SqlBuilder} current SqlBuilder object
  */
 SqlBuilder.prototype.where = function(pFieldOrCond, pValue, pCondition, pFieldType)
-{    
-    // support for deprecated SqlCondition
-    if (pFieldOrCond instanceof SqlCondition && pValue === undefined && pCondition === undefined && pFieldType === undefined)
-    {
-        let copiedCondition = newWhere();
-        
-        copiedCondition._where.preparedValues = pFieldOrCond.preparedValues;
-        copiedCondition._where._lastWasOr = pFieldOrCond._lastWasOr;
-        copiedCondition._where.sqlStorage = pFieldOrCond._sqlStorage;
-        
-        pFieldOrCond = copiedCondition;
-        
-        logging.log("Warning: using .where with a SqlCondition as pFieldOrCond is deprecated. The SqlCondition will be removed in version >= 2020.x\n"
-                    + "For SqlBuilder usage see the documentation-property of the Sql_lib.");
-    }
-    
-    return this._setWhere(pFieldOrCond, pValue, pCondition, pFieldType, this.or);
-}
+{   
+    return this._setWhere(this.or, pFieldOrCond, pValue, pCondition, pFieldType);
+};
 
 /**
- * Difference to where(): where throws errors on invalid values, whereIfSet just ignores the condition and does nothing (usefull e.g. for the parameter variables ("$param.ddd") in conditionProcesses.)<br/>
- * <br/>
- * Starts the whereIfSet clause of the SQL. You may pass the first condition with it.<br/>
- * But you can also call this function without any parameter and add the conditions with subsequent .and / .or<br/>
- * <br/>
- * This method exists mainly for semantic reasons and can only be callled once.<br/>
+ * Difference to where(): where throws errors on invalid values, whereIfSet just ignores the condition and does nothing (usefull e.g. for the parameter variables ("$param.ddd") in conditionProcesses.)
+ * 
+ * Starts the whereIfSet clause of the SQL. You may pass the first condition with it.
+ * But you can also call this function without any parameter and add the conditions with subsequent .and / .or
+ * 
+ * This method exists mainly for semantic reasons and can only be callled once.
  * As shourtcut you could use the newWhereIfSet(...) function.
  * 
- * @param {string|Array|SqlBuilder|null} [pFieldOrCond] If this is the only parameter, it is used as Condition <br/>
- *                                                                          else it is used as Field.<br/>
- *                                                                     <br/>
- *                                                                          If you use it as Subselect (the only param), it can be:<br/>
- *                                                                           - a string: just added as it is<br/>
- *                                                                           - a PreparedSqlArray: an Array in this form: [sqlStr, [[value1, type1], [valueN, typeN]]]<br/>
- *                                                                                                 the sql is just used as it is.<br/>
- *                                                                           - a SqlBuilder: ONLY THE CONDITION is used from it<br/>
- *                                                                           <br/>
- *                                                                          If you use it as a Field (at least pValue has to be filled), this param provides the field information to<br/>
- *                                                                          load the SQLTYPE for this condition. <br/>
- *                                                                          It can be provided in the following ways:<br/>
- *                                                                          - a string: ONLY in this form: "TABLENAME.COLUMNNAME" <br/>
- *                                                                               Note1: you may have problems with names containing a '.' Use the next variant (as array) in this case<br/>
- *                                                                               Note2: if you need a table alias use the next variant (as array)<br/>
- *                                                                          - a array: ["TABLENAME", "COLUMNNAME", "tableAlias"] OR ["TABLENAME", "COLUMNNAME"]<br/>
- *                                                                          - a SqlBuilder: the full select is used as subselect and compared with pValue. <br/>
- *                                                                               (e.g. select * from PERSON where (select "NAME" from ORGANISATION where ... ) = ?)<br/>
- *                                                                                Note: for this you have to provide pFieldType as the type cannot be calculated from the subselect!<br/>
+ * @param {string|PreparedSqlStatement|SqlBuilder|null} [pFieldOrCond] - This can be either a full condition (then it has to be the only parameter provided) or a field.
+ * 
+ *                                                                          If you pass a condition (the only param), these types are allowed:
+ *                                                                           - string: just added as it is
+ *                                                                           - PreparedSqlStatement: a PreparedSqlStatement object is used as it is
+ *                                                                           - SqlBuilder: ONLY THE WHERE-CONDITION is used from it
+ *                                                                           
+ *                                                                          If you pass a field (at least pValue has to be filled), this param provides the field information to
+ *                                                                          load the SQLTYPE for this condition. 
+ *                                                                          It can be provided in the following ways:
+ *                                                                          - a string: ONLY in this form: "TABLENAME.COLUMNNAME" 
+ *                                                                               Note1: you may have problems with names containing a '.' Use the next variant (as array) in this case
+ *                                                                               Note2: if you need a table alias use the next variant (as array)
+ *                                                                          - an array: ["TABLENAME", "COLUMNNAME", "tableAlias"] OR ["TABLENAME", "COLUMNNAME"]
+ *                                                                          - a SqlBuilder: the full select is used as subselect and compared with pValue. 
+ *                                                                               (e.g. select * from PERSON where (select "NAME" from ORGANISATION where ... ) = ?)
+ *                                                                                Note: for this you have to provide pFieldType as the type cannot be calculated from the subselect!
  *                                                                          Note: this can also be null if you don't need the field and use a pCondition without a #
  *                                                                     
- * @param {string|SqlBuilder|Array} [pValue] This is the value which is used for the condition.<br/>
- *                                                                       Basically it can be nearly everything you need.<br/>
- *                                                                       - String, etc: is just used as value for the prepared statement. Of course it has to fit the type of the db-column<br/>
- *                                                                       - String starting with '$' is treated as jdito-variable: is loaded with vars.getString("$..."). <br/>
- *                                                                        Note: Use 2 '$' to escape the $ if you don't want it to be treated as JditoVar
+ * @param {*} [pValue] - This is the value which is used for the condition. The type can be anything, but some types are handled in different ways:
+ *                          - string: Is just used as value for the prepared statement. Of course it has to fit the type of the db-column.
+ *                                    If the string starts with a '$' it is recognized as a jdito variable and will be resolved automatically,
+ *                                    Use 2 '$' to escape the $ if you don't want it to be treated as jdito variable (see {@link SqlUtils.escapeVars})
+ *                          - Array: If the condition allows multiple values (for example 'in'), the values can be passed in an array.
+ *                          - SqlBuilder: Can be used for sub-queries
+ *                          - PreparedSqlStatement: Can be used for sub-queries
+ *                          - all other types: Will be converted to a string
+ *                          - NOT ALLOWED: Prepared sql arrays - these will raise an error, because they could provoke sql injection
+ * 
  *                                                                           
- * @param {string} [pCondition="# = ?"] This is the condition which should be used to compare the field with the value.<br/>
- *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #<br/>
- *                               ? will be replaced by pValue<br/>
+ * @param {string} [pCondition="# = ?"] - This is the condition which should be used to compare the field with the value.
+ *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #
+ *                               ? will be replaced by pValue
  *                               <strong>IMPORTANT: the # has to be before the ?</strong>
  *                               
- * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] You can specify which datatype should be used for the prepared statement <br/>
- *                                                                In most cases you don't need this.<br/>
- *                                                                This is helpful if you for example have a pCondition "year(#) = ?"<br/>
+ * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] - You can specify which datatype should be used for the prepared statement 
+ *                                                                In most cases you don't need this, but it's required if pFieldOrCond is a sub-select or null.
+ *                                                                This is helpful if you for example have a pCondition "year(#) = ?"
  *                                                                  then the db-field is DATETIME, but the value is INTEGER. In this case you can overwrite the type.
  *
  * @return {SqlBuilder} current SqlBuilder object
  */
 SqlBuilder.prototype.whereIfSet = function(pFieldOrCond, pValue, pCondition, pFieldType)
 {
-    return this._setWhere(pFieldOrCond, pValue, pCondition, pFieldType, this.orIfSet);
-}
+    return this._setWhere(this.orIfSet, pFieldOrCond, pValue, pCondition, pFieldType);
+};
 
 /**
- * helper function for .where and .whereIfSet because they do almost the same<br/>
+ * helper function for .where and .whereIfSet because they do almost the same
  * See .where() for further explanations
  * 
- * @param {string|Array|SqlBuilder|null} [pFieldOrCond] 
- * @param {string|SqlBuilder|Array} [pValue] 
- * @param {string} [pCondition="# = ?"] <strong>IMPORTANT: the # has to be before the ?</strong><br/>
+ * @param {Function} pAddCondFn - This is a callback which is called if a condition should be added (needs to have same parameters as .or()
+ * @param {string|PreparedSqlStatement|SqlBuilder|null} [pFieldOrCond] 
+ * @param {*} [pValue] 
+ * @param {string} [pCondition="# = ?"] - <strong>IMPORTANT: the # has to be before the ?</strong>
  * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] 
- * @param {Function} pAddCondFn This is a callback which is called if a condition should be added (needs to have same parameters as .or()
  * 
  * @return {SqlBuilder} current SqlBuilder object
  * @ignore
  */
-SqlBuilder.prototype._setWhere = function (pFieldOrCond, pValue, pCondition, pFieldType, pAddCondFn)
+SqlBuilder.prototype._setWhere = function(pAddCondFn, pFieldOrCond, pValue, pCondition, pFieldType)
 {
     // allow where-call without parameter to just enable where mode
     if (pFieldOrCond === undefined && pValue === undefined && pCondition === undefined && pFieldType === undefined)
     {
-        this._where._whereWasCalled = true;
+        this._whereStatus._whereWasCalled = true;
         return this;
     }
-    
     // where has to be called before all other and / or
     if (this.hasCondition())
+    {
         throw SqlBuilder._ERROR_WHERE_NOT_FIRST();
+    }
     
     // only one where call is allowed
-    if (this._where._whereWasCalled)
+    if (this._whereStatus._whereWasCalled)
+    {
         throw SqlBuilder._ERROR_ONLY_ONE_WHERE();
+    }
     
-    this._where._whereWasCalled = true;
+    this._whereStatus._whereWasCalled = true;
     return pAddCondFn.call(this, pFieldOrCond, pValue, pCondition, pFieldType);
-}
+};
 
 /**
  * helper function which adds a condition
  * 
- * @param {string|SqlBuilder|Array} pCondition the condition to add
- * @param {boolean} [pMandatory=true] if true: throws error on SqlBuilder without conditon or PreparedSqlArray with empty string. Else: just does nothing
- * @param {Function} pAddPreparedConditionCallback A Callback funtion which receives a PreparedSqlArray as parameter
- * @param {boolean} pBrackets if true, Brackets are added in some cases
+ * @param {string|Array|SqlBuilder|PreparedSqlStatement} pCondition - the condition to add
+ * @param {Function} pAddPreparedConditionCallback - A Callback funtion which receives a PreparedSqlArray as parameter
+ * @param {boolean} [pMandatory=true] - if true: throws error on SqlBuilder without conditon or PreparedSqlArray with empty string. Else: just does nothing
+ * @param {boolean} [pBrackets] - if true, Brackets are added in some cases
  *
  * @return {SqlBuilder} current SqlBuilder object
  * @ignore
  */
-SqlBuilder.prototype._addWhereCondition = function(pCondition, pMandatory, pAddPreparedConditionCallback, pBrackets)
+SqlBuilder.prototype._addWhereCondition = function(pCondition, pAddPreparedConditionCallback, pMandatory, pBrackets)
 {
     if (pCondition === undefined)
+    {
         return this;
+    }
     
     if (pMandatory === undefined)
+    {
         pMandatory = true;
-    
-    var sql = pCondition;
+    }
 
     // the field is a simple string -> just add the string, no prepared statement
-    if (Utils.isString(sql))
+    if (Utils.isString(pCondition))
     {
-        pAddPreparedConditionCallback.call(this, [sql, []]);
+        pAddPreparedConditionCallback.call(this, new PreparedSqlStatement(pCondition));
         return this;
     }
 
-    // the field is an array -> it is a prepared condition
-    if (Array.isArray(sql))
-    {
-        if (sql[0])
-        {
-            this._where.preparedValues = this._where.preparedValues.concat(sql[1]);
+    let sqlString = "";
+    let preparedValues = [];
 
-            // add only brackets if needed
-            if (pBrackets)
-                sql[0] = " ( " + sql[0] + " ) ";
+    if (pCondition instanceof SqlBuilder)
+    {
+        //use only the where condition of the SqlBuilder
+        pCondition = pCondition._where;
+    }
 
-            pAddPreparedConditionCallback.call(this, [sql[0], []], pBrackets)
-            return this;
-        }
-        else if (pMandatory)
-            throw SqlBuilder._ERROR_CONDITION_IS_MANDATORY();
-        
-        return this;
+    if (pCondition instanceof PreparedSqlStatement)
+    {
+        sqlString = pCondition.sqlString;
+        preparedValues = pCondition.preparedValues;
+    }
+    else if (Array.isArray(pCondition))
+    {
+        sqlString = pCondition[0];
+        preparedValues = pCondition[1];
+    }
+    else
+    {
+        throw SqlBuilder._ERROR_INVALID_CONDITION_VALUE_TYPE();
     }
 
-    // the field is a SqlBuilder -> it is a SqlBuilder which contains a condition -> the condition of the SqlBuilder is added.
-    if (sql instanceof SqlBuilder)
+    if (sqlString.trim())
     {
-        // add only brackets if needed
-        var sqlString = sql._where.sqlStorage;
-        
-        
-        var condString = sqlString;
-        if (condString.trim() != "")
+        if (pBrackets)
         {
-            if (pBrackets)
-                condString = " ( " + condString + " ) ";
-            
-            pAddPreparedConditionCallback.call(this, [condString, sql._where.preparedValues], pBrackets);
-            return this;
+            sqlString = " ( " + sqlString + " ) ";
         }
-        else if (pMandatory)
-            throw SqlBuilder._ERROR_CONDITION_IS_MANDATORY();
-        
-        return this;
+        pAddPreparedConditionCallback.call(this, new PreparedSqlStatement(sqlString, preparedValues), pBrackets);
+    }
+    else if (pMandatory)
+    {
+        throw SqlBuilder._ERROR_CONDITION_IS_MANDATORY();
     }
 
-    throw SqlBuilder._ERROR_INVALID_CONDITION_VALUE_TYPE();
-}
+    return this;
+};
 
 /**
  * helper function which adds a Subquery-condition
  * 
- * @param {SqlBuilder|Array} pSubquery the subquery to add
- * @param {boolean} [pMandatory=true] if true: throws error on SqlBuilder without conditon or PreparedSqlArray with empty string. Else: just does nothing
- * @param {boolean} pCondition the condition to be used: e.g. "exists(?)" the ? is replaced by the subquery
- * @param {Function} pAddPreparedConditionCallback A Callback funtion which receives a PreparedSqlArray as parameter
+ * @param {SqlBuilder|PreparedSqlStatement} pSubquery - the subquery to add
+ * @param {string} pCondition - the condition to be used: e.g. "exists(?)" the ? is replaced by the subquery
+ * @param {Function} pAddPreparedConditionCallback - A Callback funtion which receives a PreparedSqlArray as parameter
+ * @param {boolean} [pMandatory=true] - if true: throws error on SqlBuilder without conditon or PreparedSqlArray with empty string. Else: just does nothing
  *
  * @return {SqlBuilder} current SqlBuilder object
  * @ignore
  */
-SqlBuilder.prototype._addWhereSubquery = function(pSubquery, pMandatory, pCondition, pAddPreparedConditionCallback)
+SqlBuilder.prototype._addWhereSubquery = function(pSubquery, pCondition, pAddPreparedConditionCallback, pMandatory)
 {
     if (pSubquery === undefined)
+    {
         return this;
+    }
 
     if (pMandatory === undefined)
+    {
         pMandatory = true;
-    
-    var sql = pSubquery;
+    }
 
-    // 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))
+    if (pSubquery instanceof PreparedSqlStatement)
     {        
-        if (sql[0])
-            pAddPreparedConditionCallback.call(this, this._prepare(undefined, sql, pCondition));
+        if (pSubquery.sqlString)
+        {
+            pAddPreparedConditionCallback.call(this, this._prepare(undefined, pSubquery.toArray(), pCondition));
+        }
         else if (pMandatory)
+        {
             throw SqlBuilder._ERROR_VALUE_IS_MANDATORY();
+        }
         
         return this;
     }
-
     // the field is a SqlBuilder -> it is a SqlBuilder which contains a condition -> the condition of the SqlBuilder is added.
-    if (sql instanceof SqlBuilder)
+    if (pSubquery instanceof SqlBuilder)
     {
-         var subQuery = pSubquery;
-
         // Without condition this function cannot be used with SqlBuilder object as it cannot contain a condition
         if (!pCondition)
+        {
             throw SqlBuilder._ERROR_NO_CONDITION();
+        }
         
-        if (subQuery.isFullSelect() || subQuery.hasCondition()) //can also be only an condition if SqlBuilder.NOT() is used
+        if (pSubquery.isFullSelect() || pSubquery.hasCondition()) //can also be only an condition if SqlBuilder.NOT() is used
         {
-            var preparedObj = subQuery.build();
+            let preparedObj = pSubquery.build();
             pAddPreparedConditionCallback.call(this, this._prepare(undefined, preparedObj, pCondition));
         } 
         else if (pMandatory)
+        {
             throw SqlBuilder._ERROR_VALUE_IS_MANDATORY();
+        }
         
         return this;
     }
-    
     throw SqlBuilder._ERROR_INVALID_SUBQUERY_TYPE();
-}
+};
 
 /**
  * helper function which adds a condition to the where
  * 
- * @param {string|Array|SqlBuilder|null} pFieldOrCond see .where()
- * @param {string|SqlBuilder|Array} pValue see .where()
- * @param {boolean} pMandatory if true: throw error if pValue is null, undefined, SqlBuilder without condition, etc... else just ignore the condition
- * @param {string} [pCondition="# = ?"] see .where()
- * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] see .where()
- * @param {Function} pAddPreparedConditionCallback A Callback funtion which receives a PreparedSqlArray as parameter
+ * @param {string|Array|PreparedSqlStatement|SqlBuilder|null} pFieldOrCond - see .where()
+ * @param {*} pValue - see .where()
+ * @param {Function} pAddPreparedConditionCallback - A Callback funtion which receives a PreparedSqlArray as parameter
+ * @param {boolean} [pMandatory] - if true: throw error if pValue is null, undefined, SqlBuilder without condition, etc... else just ignore the condition
+ * @param {string|((pAlias: string)=>(string|[string,number]))} [pCondition="# = ?"] - see .where()
+ * @param {number} [pFieldType=AutomaticallyLoadedType] - see .where()
  * 
  * @return {SqlBuilder} current SqlBuilder object
  * @ignore
  */
-SqlBuilder.prototype._addWhere = function(pFieldOrCond, pValue, pMandatory, pCondition, pFieldType, pAddPreparedConditionCallback)
+SqlBuilder.prototype._addWhere = function(pFieldOrCond, pValue, pAddPreparedConditionCallback, pMandatory, pCondition, pFieldType)
 {
-    if (!this._where._whereWasCalled)
+    if (!this._whereStatus._whereWasCalled)
+    {
         throw SqlBuilder._ERROR_WHERE_NOT_FIRST();
+    }
 
     //skip if no values are provided and mandatory is false
     if (!pMandatory && pFieldOrCond === undefined && pValue === undefined && pCondition === undefined && pFieldType === undefined)
+    {
         return this;
+    }
 
     if (pFieldOrCond === undefined && pValue === undefined && pCondition === undefined && pFieldType === undefined)
+    {
         throw SqlBuilder._ERROR_NO_PARAMETER_PROVIDED();
+    }
     
     //In a special case, pCondition can be a function. It will be called with the alias as argument and
     //must return an array of the condition string and (optionally) the required sql field type.
     //alternatively the function may return a string only to make the usage more bulletproof and convenient, so both SqlBuilder.EQUAL() 
     //and SqlBuilder.EQUAL work equally 
-    if (typeof pCondition === "function")
+    if (Utils.isFunction(pCondition))
     {
-        var resCond = pCondition(this.alias);
-        if (Array.isArray(resCond))
+        let resCondition = pCondition(this.alias);
+        let resConditionString;
+        if (Array.isArray(resCondition))
         {
-            pCondition = resCond[0];
-            pFieldType = pFieldType || resCond[1];
+            resConditionString = resCondition[0];
+            pFieldType = pFieldType || resCondition[1];
         }
-        else if(Utils.isString(pCondition))
+        else if(Utils.isString(resCondition))
         {
-            pCondition = resCond;
+            resConditionString = resCondition;
         }
+        pCondition = resConditionString;
     }
+    
     this._verifyConditionFormat(pCondition);
  
     // Special case: if only pFieldOrCond is set and we can identify it as a valid field-string (e.g. "Table.Field") we assume that it is not just a condition string.
@@ -855,15 +950,32 @@ SqlBuilder.prototype._addWhere = function(pFieldOrCond, pValue, pMandatory, pCon
     if (pValue === undefined && pCondition === undefined && pFieldType === undefined && typeof pFieldOrCond == "string" && SqlUtils.isFullFieldQualifier(pFieldOrCond))
     {
         if (pMandatory)
+        {
             throw SqlBuilder._ERROR_VALUE_IS_MANDATORY();
+        }
         
         return this;
     }
-  
+    
+    if (SqlUtils.isPreparedSqlArray(pValue))
+    {
+        throw SqlBuilder._ERROR_SQL_ARRAY_AS_VALUE_NOT_ALLOWED();
+    }
+
+    if (SqlUtils.isPreparedSqlArray(pFieldOrCond))
+    {
+        throw SqlBuilder._ERROR_SQL_ARRAY_AS_FIELD_OR_COND_NOT_ALLOWED();
+    }
+
     // just call the andCondition function if it is only a Condition
     if (pFieldOrCond !== undefined && pValue === undefined && pCondition === undefined && pFieldType === undefined)
     {
-        return this._addWhereCondition(pFieldOrCond, pMandatory, pAddPreparedConditionCallback, true);
+        return this._addWhereCondition(pFieldOrCond, pAddPreparedConditionCallback, pMandatory, true);
+    }
+
+    if (pFieldOrCond instanceof PreparedSqlStatement)
+    {
+        throw SqlBuilder._ERROR_PREPARED_SQL_AS_FIELD_NOT_ALLOWED();
     }
     
     // Subselects containing full select can be used as field, if pValue and pFieldType are provided.
@@ -877,133 +989,145 @@ SqlBuilder.prototype._addWhere = function(pFieldOrCond, pValue, pMandatory, pCon
         {
             throw SqlBuilder._ERROR_SUBSELECT_AS_FIELD_NO_FIELD_TYPE();
         }
-        
-        var tmpCond = newWhere(this.alias)
-            ._addWhere("SQL_LIB_DUMMY_TABLE.SQL_LIB_DUMMY_COLUMN", pValue, pMandatory, pCondition, pFieldType, pAddPreparedConditionCallback);
+        let tmpCond = newWhere(this.alias)
+            ._addWhere("SQL_LIB_DUMMY_TABLE.SQL_LIB_DUMMY_COLUMN", pValue, pAddPreparedConditionCallback, pMandatory, pCondition, pFieldType);
                 
-        var subSqlPrepared = pFieldOrCond.build();
+        let subSqlPrepared = pFieldOrCond.build();
         
-        tmpCond._where.sqlStorage = SqlUtils.replaceConditionTemplate(tmpCond._where.sqlStorage, 'SQL_LIB_DUMMY_TABLE.SQL_LIB_DUMMY_COLUMN', "( " + subSqlPrepared[0] + " )");
-        tmpCond._where.preparedValues = subSqlPrepared[1].concat(tmpCond._where.preparedValues)
+        tmpCond._where.sqlString = SqlUtils.replaceConditionTemplate(tmpCond._where.sqlString, "SQL_LIB_DUMMY_TABLE.SQL_LIB_DUMMY_COLUMN", "( " + subSqlPrepared[0] + " )");
+        tmpCond._where.preparedValues = subSqlPrepared[1].concat(tmpCond._where.preparedValues);
         
-        this._addWhereCondition(tmpCond, pMandatory, pAddPreparedConditionCallback, true)
+        this._addWhereCondition(tmpCond, pAddPreparedConditionCallback, pMandatory, true);
         return this;
     }
     
     // first check the default-mandatory-cases: null or undefined. everything else such as checking $-variables is done later
     if (pMandatory && (pValue === null || pValue === undefined))
+    {
         throw SqlBuilder._ERROR_VALUE_IS_MANDATORY();
+    }
     
     // a field is string or array -> normal case
     // OR !pFieldOrCond and pValue and pCondition is given -> preparedSQL/SqlBuilder can be used without field if pCondition is set (e.g. with "exists ?")
-    if ((typeof pFieldOrCond == "string" || Array.isArray(pFieldOrCond) || (!pFieldOrCond && pFieldType))
-        || (!pFieldOrCond && (pCondition && pValue instanceof SqlBuilder || !(pValue instanceof SqlBuilder))))
+    if (!(typeof pFieldOrCond == "string" || Array.isArray(pFieldOrCond) || (!pFieldOrCond && pFieldType))
+        && !(!pFieldOrCond && (pCondition && pValue instanceof SqlBuilder || !(pValue instanceof SqlBuilder))))
     {
-        var field = pFieldOrCond;
-        var typeofValue = typeof pValue;
+        throw SqlBuilder._ERROR_UNSUPPORTED_PARAMETER_COMBINATION();
+    }
+
+    let field = pFieldOrCond;
+    let typeofValue = typeof pValue;
 
-        // ... a string starting with $ -> jdito varable which has to be resolved
-        if (typeofValue == "string" && pValue.length >= 2 && pValue[0] == "$" && pValue[1] != "$") // escape $ if using two $
+    // ... a string starting with $ -> jdito varable which has to be resolved
+    if (typeofValue == "string" && pValue.length >= 2 && pValue[0] == "$") 
+    {
+        if (pValue[1] != "$") // escape $ if using two $
         {
             //important: just overwrite the value because some $local variables may contain an array and then the default handling of arrays (which
             //is generating an IN-statement) should apply
             pValue = vars.get(pValue);
             if (pMandatory && pValue === null)
+            {
                 throw SqlBuilder._ERROR_VALUE_IS_MANDATORY_JDITO_VAR();
+            }
+            if (SqlUtils.isPreparedSqlArray(pValue))
+            {
+                throw SqlBuilder._ERROR_SQL_ARRAY_AS_VALUE_NOT_ALLOWED();
+            }
             typeofValue = typeof pValue;
         }
-
-        // remove the first $ if there are two $
-        if (typeofValue == "string" && pValue.length >= 2 && pValue[0] == "$" && pValue[1] == "$")
+        else // remove the first $ if there are two $
+        {
             pValue = pValue.slice(1);
-        
-        //support for Set by converting to Array
-        if (pValue instanceof Set)
-            pValue = Array.from(pValue);
-        
-        // pValue can be...
-        // ... a SqlBuilder / Prepared statement array -> it is a SqlBuilder containing a complete subquery or an simple array (in statement)
-        if (pValue instanceof SqlBuilder || Array.isArray(pValue) || (typeofValue == "string" && (pFieldOrCond == undefined || pFieldOrCond == null)))
-        {            
-            // check if the array is really a value-array for an in and not a prepared statement
-            if (Array.isArray(pValue) && !SqlUtils.isPreparedSqlArray(pValue))
+        }
+    }
+    
+    //support for Set by converting to Array
+    if (pValue instanceof Set)
+    {
+        pValue = Array.from(pValue);
+    }
+    
+    if (Array.isArray(pValue))
+    {
+        if (pValue.length == 0)
+        {
+            if (pMandatory)
             {
-                if (pValue.length == 0)
-                {
-                    if (pMandatory)
-                        throw SqlBuilder._ERROR_VALUE_IS_MANDATORY();
-                    
-                    return this;
-                }
-                               
-                // if it is null -> ignore it. -> the pCondition should not contain a # in this case
-                if (field != null)
-                {
-                    var [alias, parsedField] = SqlUtils.parseField(field);
-                    if (pFieldType === undefined || pFieldType === null)
-                        pFieldType = SqlUtils.getSingleColumnType(parsedField, undefined, this.alias);
-                }
-                //overwrite condition to set a default behaviour
-                if (pCondition == undefined)
-                    pCondition = SqlBuilder.IN();
-                // value-array -> convert it to a prepared statement ["(?, ?, ?)", [[val1, type1], [val2, type2], [val3, type3]]]
-                
-                var mergeOp = pCondition == SqlBuilder.NOT_IN() ? " and " : " or ";
-                var inCondition = ArrayUtils.chunk(pValue, 1000)
-                    .map(function (values)
-                    {
-                        return this._prepare(field, SqlUtils.getSqlInStatement(undefined, values, undefined, true, pFieldType), pCondition, pFieldType, false);
-                    }, this)
-                    .reduce(function (fullCondition, nextCondition)
-                    {
-                        return [
-                            fullCondition[0] + mergeOp + nextCondition[0],
-                            fullCondition[1].concat(nextCondition[1])
-                        ];
-                    });
-                
-                this._addWhereCondition(inCondition, undefined, pAddPreparedConditionCallback, true);
-                return this;
+                throw SqlBuilder._ERROR_VALUE_IS_MANDATORY();
             }
             
-            if (pFieldOrCond !== null && pFieldOrCond !== undefined)
-            {
-                if (!pCondition)
-                    pCondition = SqlBuilder.EQUAL();
-                
-                pCondition = SqlUtils.replaceConditionTemplate(pCondition, '#', SqlUtils.parseField(pFieldOrCond)[0]);
-            }
-            else if (!pCondition)
+            return this;
+        }
+                        
+        // if it is null -> ignore it. -> the pCondition should not contain a # in this case
+        if (field != null)
+        {
+            let parsedField = SqlUtils.parseField(field)[1];
+            if (pFieldType === undefined || pFieldType === null)
             {
-                pCondition = "?";
+                pFieldType = SqlUtils.getSingleColumnType(parsedField, undefined, this.alias);
             }
-            
-            // _addWhereSubquery can handle SqlBuilder and prepared statements as value
-            return this._addWhereSubquery(pValue, pMandatory, pCondition, pAddPreparedConditionCallback);
         }
-
-        if (!pCondition)
-            pCondition = SqlBuilder.EQUAL();
-
-        // ... everything else -> just pass it
-        if (pValue === false || pValue === 0 || pValue === "" || pValue)
+        //overwrite condition to set a default behaviour
+        if (pCondition == undefined)
         {
-            let prep = this._prepare(field, pValue, pCondition, pFieldType)
-            this._addWhereCondition(prep, undefined, pAddPreparedConditionCallback);
+            pCondition = SqlBuilder.IN();
         }
+        // value-array -> convert it to a prepared statement ["(?, ?, ?)", [[val1, type1], [val2, type2], [val3, type3]]]
+        
+        let mergeOp = pCondition == SqlBuilder.NOT_IN() ? " and " : " or ";
+        let inCondition = ArrayUtils.chunk(pValue, 1000)
+            .map(values =>
+            {
+                return this._prepare(field, SqlUtils.getSqlInStatement(undefined, values, undefined, true, pFieldType), 
+                    pCondition, pFieldType, false);
+            })
+            .reduce((fullCondition, nextCondition) => fullCondition.appendStatement(nextCondition, mergeOp));
+        
+        this._addWhereCondition(inCondition, pAddPreparedConditionCallback, undefined, true);
         return this;
     }
+        
+    // pValue can be...
+    // ... a SqlBuilder / Prepared statement array -> it is a SqlBuilder containing a complete subquery or an simple array (in statement)
+    if (pValue instanceof SqlBuilder || (typeofValue == "string" && (pFieldOrCond == undefined || pFieldOrCond == null))
+        || pValue instanceof PreparedSqlStatement)
+    {   
+        if (pFieldOrCond !== null && pFieldOrCond !== undefined)
+        {
+            pCondition = SqlUtils.replaceConditionTemplate(pCondition || SqlBuilder.EQUAL(), "#", SqlUtils.parseField(pFieldOrCond)[0]);
+        }
+        else if (!pCondition)
+        {
+            pCondition = "?";
+        }
+        
+        // _addWhereSubquery can handle SqlBuilder and prepared statements as value
+        return this._addWhereSubquery(pValue, pCondition, pAddPreparedConditionCallback, pMandatory);
+    }
 
-    throw SqlBuilder._ERROR_UNSUPPORTED_PARAMETER_COMBINATION();
-}
+    if (!pCondition)
+    {
+        pCondition = SqlBuilder.EQUAL();
+    }
+
+    // ... everything else -> just pass it
+    if (pValue === false || pValue === 0 || pValue === "" || pValue)
+    {
+        let prep = this._prepare(field, pValue, pCondition, pFieldType);
+        this._addWhereCondition(prep, pAddPreparedConditionCallback);
+    }
+    return this;
+};
 
 /**
  * helper function that checks if the format of a condition is valid
  * 
- * @param {string} pCondition   condition
+ * @param {*} pCondition - condition
  * @throws when the format is invalid
  */
-SqlBuilder.prototype._verifyConditionFormat = function (pCondition)
+SqlBuilder.prototype._verifyConditionFormat = function(pCondition)
 {
     if (!pCondition)
     {
@@ -1012,13 +1136,13 @@ SqlBuilder.prototype._verifyConditionFormat = 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 (it uses text.replaceAll which supports lookbehind because it uses java)
-    var conditionFormat = SqlUtils.replaceConditionTemplate(pCondition, "#", "{@NUMBERSIGN@}")
-    conditionFormat = SqlUtils.replaceConditionTemplate(conditionFormat, "\\?", "{@QUESTIONSIGN@}")
+    let conditionFormat = SqlUtils.replaceConditionTemplate(pCondition, "#", "{@NUMBERSIGN@}");
+    conditionFormat = SqlUtils.replaceConditionTemplate(conditionFormat, "\\?", "{@QUESTIONSIGN@}");
 
-    var indexOfNumberSign = conditionFormat.indexOf("{@NUMBERSIGN@}");
-    var indexOfQuestionSign = conditionFormat.indexOf("{@QUESTIONSIGN@}");
+    let indexOfNumberSign = conditionFormat.indexOf("{@NUMBERSIGN@}");
+    let indexOfQuestionSign = conditionFormat.indexOf("{@QUESTIONSIGN@}");
     
-    var isFormatValid = !(indexOfQuestionSign == -1 
+    let isFormatValid = !(indexOfQuestionSign == -1 
         || indexOfNumberSign > indexOfQuestionSign 
         || indexOfNumberSign != conditionFormat.lastIndexOf("{@NUMBERSIGN@}") 
         || indexOfQuestionSign != conditionFormat.lastIndexOf("{@QUESTIONSIGN@}"));
@@ -1027,83 +1151,100 @@ SqlBuilder.prototype._verifyConditionFormat = function (pCondition)
     {
         throw SqlBuilder._ERROR_CONDITION_WRONG_FORMAT();
     }
-}
+};
 
 /**
  * helper function to add a condition via "and"
  * 
- * @param {string|Array|SqlBuilder|null} pFieldOrCond see .where()
- * @param {string|SqlBuilder|Array} pValue see .where()
- * @param {boolean} [pMandatory=true] if true: throw error if pValue is null, undefined, SqlBuilder without condition, etc... else just ignore the condition
- * @param {string} [pCondition="# = ?"] see .where()
- * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] see .where()
+ * @param {string|Array|PreparedSqlStatement|SqlBuilder|null} pFieldOrCond - see .where()
+ * @param {*} pValue - see .where()
+ * @param {boolean} [pMandatory=true] - if true: throw error if pValue is null, undefined, SqlBuilder without condition, etc... else just ignore the condition
+ * @param {string} [pCondition="# = ?"] - see .where()
+ * @param {number} [pFieldType=AutomaticallyLoadedType] - see .where()
  * 
  * @ignore
  */
 SqlBuilder.prototype._and = function(pFieldOrCond, pValue, pMandatory, pCondition, pFieldType)
 {
-    return this._addWhere(pFieldOrCond, pValue, pMandatory, pCondition, pFieldType, function(pPreparedCondition) 
-    {
-        this._where._previouslyOnlyOr = false;
-        if (SqlUtils.isNonEmptyPreparedSqlArray(pPreparedCondition))
+    return this._addWhere(pFieldOrCond, pValue, 
+        /**
+         * @this {SqlBuilder}
+         * @param {PreparedSqlStatement} pPreparedCondition
+         */
+        function(pPreparedCondition) 
         {
-            if (this.hasCondition())
-                this._where.sqlStorage += " and ";
-            
-            this._where.sqlStorage += pPreparedCondition[0];
-            this._where.preparedValues = this._where.preparedValues.concat(pPreparedCondition[1]);
-        }
-    });
-}
+            this._whereStatus._previouslyOnlyOr = false;
+            if (!(pPreparedCondition instanceof PreparedSqlStatement) || pPreparedCondition.isEmpty())
+            {
+                return;
+            }
+            this._where.appendStatement(pPreparedCondition, " and ");
+        }, pMandatory, pCondition, pFieldType);
+};
 
 /**
  * helper function to add a condition via "or"
  * The callback inside of this function adds brackets where needed.
  * 
- * @param {string|Array|SqlBuilder|null} pFieldOrCond see .where()
- * @param {string|SqlBuilder|Array} pValue see .where()
- * @param {boolean} [pMandatory=true] if true: throw error if pValue is null, undefined, SqlBuilder without condition, etc... else just ignore the condition
- * @param {string} [pCondition="# = ?"] see .where()
- * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] see .where()
+ * @param {string|Array|PreparedSqlStatement|SqlBuilder|null} pFieldOrCond - see .where()
+ * @param {*} pValue - see .where()
+ * @param {boolean} [pMandatory=true] - if true: throw error if pValue is null, undefined, SqlBuilder without condition, etc... else just ignore the condition
+ * @param {string} [pCondition="# = ?"] - see .where()
+ * @param {number} [pFieldType=AutomaticallyLoadedType] - see .where()
  * 
  * @ignore
  */
 SqlBuilder.prototype._or = function(pFieldOrCond, pValue, pMandatory, pCondition, pFieldType)
 {    
-    return this._addWhere(pFieldOrCond, pValue, pMandatory, pCondition, pFieldType, function(pPreparedCondition, pAlreadySurroundedByBrackets) 
-    {
-        if (SqlUtils.isNonEmptyPreparedSqlArray(pPreparedCondition))
-        {   
-            if (this._where._previouslyOnlyOr)
+    return this._addWhere(pFieldOrCond, pValue, 
+        /**
+         * @this {SqlBuilder}
+         * @param {PreparedSqlStatement} pPreparedCondition
+         * @param {boolean} pAlreadySurroundedByBrackets
+         */
+        function(pPreparedCondition, pAlreadySurroundedByBrackets) 
+        {
+            if (!(pPreparedCondition instanceof PreparedSqlStatement) || pPreparedCondition.isEmpty())
             {
-                this._where.sqlStorage = this._where.sqlStorage + " or " + pPreparedCondition[0];
-                this._where._lastWasOr = true;
+                return;
+            }
+            if (this._whereStatus._previouslyOnlyOr)
+            {
+                this._where.append(" or " + pPreparedCondition.sqlString);
+                this._whereStatus._lastWasOr = true;
             }
             else if (this.hasCondition())
             {
-                let cond = pPreparedCondition[0];
-                
+                let cond = pPreparedCondition.sqlString;
+
                 if (!pAlreadySurroundedByBrackets)
+                {
                     cond = "(" + cond + ")";
-                
-                if (this._where._lastWasOr)
-                    this._where.sqlStorage = this._where.sqlStorage + " or " + cond;
+                }
+
+                if (this._whereStatus._lastWasOr)
+                {
+                    this._where.append(" or " + cond);
+                }
                 else
-                    this._where.sqlStorage = "(" + this._where.sqlStorage + ") or " + cond;
-                
-                this._where._lastWasOr = true;
+                {
+                    this._where.sqlString = "(" + this._where.sqlString + ") or " + cond;
+                }
+
+                this._whereStatus._lastWasOr = true;
             } 
             else
             {
                 if (!this.hasCondition())
-                    this._where._previouslyOnlyOr = true;
-                
-                this._where.sqlStorage = pPreparedCondition[0];
+                {
+                    this._whereStatus._previouslyOnlyOr = true;
+                }
+
+                this._where.sqlString = pPreparedCondition.sqlString;
             }
-            this._where.preparedValues = this._where.preparedValues.concat(pPreparedCondition[1]);
-        }
-    });
-}
+            this._where.append(null, pPreparedCondition.preparedValues);
+        }, pMandatory, pCondition, pFieldType);
+};
 
 /**
  * Constant-like function which provides a value for pCondition if you need a "not" statement.
@@ -1111,12 +1252,12 @@ SqlBuilder.prototype._or = function(pFieldOrCond, pValue, pMandatory, pCondition
  * @return {string} 
  * 
  * @example
- * var cond = newWhere(null, someCondition, SqlBuilder.NOT())
+ * let cond = newWhere(null, someCondition, SqlBuilder.NOT())
  */
 SqlBuilder.NOT = function()
 {
     return "not ?";
-}
+};
 
 /**
  * Constant-like function which provides a value for pCondition if you need a "not in" statement.
@@ -1124,12 +1265,12 @@ SqlBuilder.NOT = function()
  * @return {string} 
  * 
  * @example
- * var cond = newWhere("PERSON.FIRSTNAME", ["Fritz"], SqlBuilder.NOT_IN())
+ * let cond = newWhere("PERSON.FIRSTNAME", ["Fritz"], SqlBuilder.NOT_IN())
  */
 SqlBuilder.NOT_IN = function()
 {
     return "# not in ?";
-}
+};
 
 /**
  * Constant-like function which provides a value for pCondition if you need a "in" statement.
@@ -1137,12 +1278,12 @@ SqlBuilder.NOT_IN = function()
  * @return {string} 
  * 
  * @example
- * var cond = newWhere("PERSON.FIRSTNAME", ["Fritz"], SqlBuilder.IN())
+ * let cond = newWhere("PERSON.FIRSTNAME", ["Fritz"], SqlBuilder.IN())
  */
 SqlBuilder.IN = function()
 {
     return "# in ?";
-}
+};
 
 /**
  * Constant-like function which provides a value for pCondition if you need a "exists" statement.
@@ -1150,12 +1291,12 @@ SqlBuilder.IN = function()
  * @return {string} 
  * 
  * @example
- * var cond = newWhere(null, mySubSqlBuilder, SqlBuilder.EXISTS())
+ * let cond = newWhere(null, mySubSqlBuilder, SqlBuilder.EXISTS())
  */
 SqlBuilder.EXISTS = function()
 {
     return "exists ?";
-}
+};
 
 /**
  * Constant-like function which provides a value for pCondition if you need a "not exists" statement.
@@ -1163,12 +1304,12 @@ SqlBuilder.EXISTS = function()
  * @return {string} 
  * 
  * @example
- * var cond = newWhere(null, mySubSqlBuilder, SqlBuilder.NOT_EXISTS())
+ * let cond = newWhere(null, mySubSqlBuilder, SqlBuilder.NOT_EXISTS())
  */
 SqlBuilder.NOT_EXISTS = function()
 {
     return "not exists ?";
-}
+};
 
 /**
  * Constant-like function which provides a value for pCondition if you need a "year(#) = ?" statement.
@@ -1177,13 +1318,18 @@ SqlBuilder.NOT_EXISTS = function()
  * @return {Function} 
  * 
  * @example
- * var cond = newWhere("FORECAST.DATE_START", DateUtils.getCurrentYear(), SqlBuilder.YEAR_EQUALS());
+ * let cond = newWhere("FORECAST.DATE_START", DateUtils.getCurrentYear(), SqlBuilder.YEAR_EQUALS());
  */
-SqlBuilder.YEAR_EQUALS = function ()
+SqlBuilder.YEAR_EQUALS = function()
 {
     //function will be called later so it can use the alias of the SqlBuilder
-    return function (pAlias) {return [(new SqlMaskingUtils(pAlias).yearFromDate("#")) + " = ?", SQLTYPES.INTEGER];};
-}
+    return function(pAlias) 
+    
+    {
+        return [(new SqlMaskingUtils(pAlias)
+            .yearFromDate("#")) + " = ?", SQLTYPES.INTEGER];
+    };
+};
 
 /**
  * Constant-like function which provides a value for pCondition if you need a "# = ?" statement.
@@ -1192,12 +1338,12 @@ SqlBuilder.YEAR_EQUALS = function ()
  * @return {string} 
  * 
  * @example
- * var cond = newWhere("PERSON.FIRSTNAME", "Fritz", SqlBuilder.EQUAL())
+ * let cond = newWhere("PERSON.FIRSTNAME", "Fritz", SqlBuilder.EQUAL())
  */
-SqlBuilder.EQUAL = function ()
+SqlBuilder.EQUAL = function()
 {
     return "# = ?";
-}
+};
 
 /**
  * Constant-like function which provides a value for pCondition if you need a "# &lt;&gt; ?" statement.
@@ -1205,12 +1351,12 @@ SqlBuilder.EQUAL = function ()
  * @return {string} 
  * 
  * @example
- * var cond = newWhere("PERSON.FIRSTNAME", "Fritz", SqlBuilder.NOT_EQUALS())
+ * let cond = newWhere("PERSON.FIRSTNAME", "Fritz", SqlBuilder.NOT_EQUALS())
  */
-SqlBuilder.NOT_EQUAL = function ()
+SqlBuilder.NOT_EQUAL = function()
 {
     return "# <> ?";
-}
+};
 
 /**
  * Constant-like function which provides a value for pCondition if you need a "# like ?" statement.
@@ -1218,12 +1364,12 @@ SqlBuilder.NOT_EQUAL = function ()
  * @return {string} 
  * 
  * @example
- * var cond = newWhere("PERSON.FIRSTNAME", "F%", SqlBuilder.LIKE())
+ * let cond = newWhere("PERSON.FIRSTNAME", "F%", SqlBuilder.LIKE())
  */
-SqlBuilder.LIKE = function ()
+SqlBuilder.LIKE = function()
 {
     return "# like ?";
-}
+};
 
 /**
  * Constant-like function which provides a value for pCondition if you need a "# like ?" statement.
@@ -1231,62 +1377,62 @@ SqlBuilder.LIKE = function ()
  * @return {string} 
  * 
  * @example
- * var cond = newWhere("PERSON.FIRSTNAME", "F%", SqlBuilder.NOT_LIKE())
+ * let cond = newWhere("PERSON.FIRSTNAME", "F%", SqlBuilder.NOT_LIKE())
  */
-SqlBuilder.NOT_LIKE = function ()
+SqlBuilder.NOT_LIKE = function()
 {
     return "# not like ?";
-}
+};
 
 /**
  * Constant-like function which provides a value for pCondition if you need a "# &gt; ?" statement.
  * 
  * @return {string} 
  */
-SqlBuilder.GREATER = function ()
+SqlBuilder.GREATER = function()
 {
     return "# > ?";
-}
+};
 
 /**
  * Constant-like function which provides a value for pCondition if you need a "# &lt; ?" statement.
  * 
  * @return {string} 
  */
-SqlBuilder.LESS = function ()
+SqlBuilder.LESS = function()
 {
     return "# < ?";
-}
+};
 
 /**
  * Constant-like function which provides a value for pCondition if you need a "# &gt;= ?" statement.
  * 
  * @return {string} 
  */
-SqlBuilder.GREATER_OR_EQUAL = function ()
+SqlBuilder.GREATER_OR_EQUAL = function()
 {
     return "# >= ?";
-}
+};
 
 /**
  * Constant-like function which provides a value for pCondition if you need a "# &lt;= ?" statement.
  * 
  * @return {string}
  */
-SqlBuilder.LESS_OR_EQUAL = function ()
+SqlBuilder.LESS_OR_EQUAL = function()
 {
     return "# <= ?";
-}
+};
 
 /**
  * Constant-like function which returns an impossible condition ("1 = 2").
  * 
  * @return {string}
  */
-SqlBuilder.NORESULT_CONDITION = function ()
+SqlBuilder.NORESULT_CONDITION = function()
 {
     return "1 = 2";
-}
+};
 
 /**
  * Object providing constant-like functions for sql-any-conditions.
@@ -1295,28 +1441,52 @@ SqlBuilder.ANY = {
     /**
      * Constant-like function that returns a "# = any ?" statement.
      */
-    EQUAL : function () {return "# = any ?";},
+    EQUAL: function() 
+    
+    {
+        return "# = any ?";
+    },
     /**
      * Constant-like function that returns a "# &lt;&gt; any ?" statement.
      */
-    NOT_EQUAL : function () {return "# <> any ?";},
+    NOT_EQUAL: function() 
+    
+    {
+        return "# <> any ?";
+    },
     /**
      * Constant-like function that returns a "# &gt; any ?" statement.
      */
-    GREATER : function () {return "# > any ?";},
+    GREATER: function() 
+    
+    {
+        return "# > any ?";
+    },
     /**
      * Constant-like function that returns a "# &gt;= any ?" statement.
      */
-    GREATER_OR_EQUAL : function () {return "# >= any ?";},
+    GREATER_OR_EQUAL: function() 
+    
+    {
+        return "# >= any ?";
+    },
     /**
      * Constant-like function that returns a "# &lt; any ?" statement.
      */
-    LESS : function () {return "# < any ?";},
+    LESS: function() 
+    
+    {
+        return "# < any ?";
+    },
     /**
      * Constant-like function that returns a "# &lt;= any ?" statement.
      */
-    LESS_OR_EQUAL : function () {return "# <= any ?";}
-}
+    LESS_OR_EQUAL: function() 
+    
+    {
+        return "# <= any ?";
+    }
+};
 
 /**
  * Object providing constant-like functions for sql-all-conditions.
@@ -1325,67 +1495,98 @@ SqlBuilder.ALL = {
     /**
      * Constant-like function that returns a "# = all ?" statement.
      */
-    EQUAL : function () {return "# = all ?";},
+    EQUAL: function() 
+    
+    {
+        return "# = all ?";
+    },
     /**
      * Constant-like function that returns a "# &lt;&gt; all ?" statement.
      */
-    NOT_EQUAL : function () {return "# <> all ?";},
+    NOT_EQUAL: function() 
+    
+    {
+        return "# <> all ?";
+    },
     /**
      * Constant-like function that returns a "# &gt; all ?" statement.
      */
-    GREATER : function () {return "# > all ?";},
+    GREATER: function() 
+    
+    {
+        return "# > all ?";
+    },
     /**
      * Constant-like function that returns a "# &gt;= all ?" statement.
      */
-    GREATER_OR_EQUAL : function () {return "# >= all ?";},
+    GREATER_OR_EQUAL: function() 
+    
+    {
+        return "# >= all ?";
+    },
     /**
      * Constant-like function that returns a "# &lt; all ?" statement.
      */
-    LESS : function () {return "# < all ?";},
+    LESS: function() 
+    
+    {
+        return "# < all ?";
+    },
     /**
      * Constant-like function that returns a "# &lt;= all ?" statement.
      */
-    LESS_OR_EQUAL : function () {return "# <= all ?";}
-}
+    LESS_OR_EQUAL: function() 
+    
+    {
+        return "# <= all ?";
+    }
+};
 
 /**
- * Throws an error if pValue is null, undefined or a SqlBuilder without condition (or if pValue is a $-variable: error if the result of it is null or undefined)<br/>
- * Also throws an error if pFieldOrCond is the only parameter and it is null<br/>
- * <br/>
- * Adds a condition by using "or" to the Sql.<br/>
+ * Throws an error if pValue is null, undefined or a SqlBuilder without condition (or if pValue is a $-variable: error if the result of it is null or undefined)
+ * Also throws an error if pFieldOrCond is the only parameter and it is null
+ * 
+ * Adds a condition by using "or" to the Sql.
  * Note: You have to call .where before using .and / .or (this is mainly for semantic reasons)
  * 
- * @param {string|Array|SqlBuilder|null} [pFieldOrCond] If this is the only parameter, it is used as Condition <br/>
- *                                                                          else it is used as Field.<br/>
- *                                                                     <br/>
- *                                                                          If you use it as Subselect (the only param), it can be:<br/>
- *                                                                           - a string: just added as it is<br/>
- *                                                                           - a PreparedSqlArray: an Array in this form: [sqlStr, [[value1, type1], [valueN, typeN]]]<br/>
- *                                                                                                 the sql is just used as it is.<br/>
- *                                                                           - a SqlBuilder: ONLY THE CONDITION is used from it<br/>
- *                                                                           <br/>
- *                                                                          If you use it as a Field (at least pValue has to be filled), this param provides the field information to<br/>
- *                                                                          load the SQLTYPE for this condition. <br/>
- *                                                                          It can be provided in the following ways:<br/>
- *                                                                          - a string: ONLY in this form: "TABLENAME.COLUMNNAME" <br/>
- *                                                                               Note1: you may have problems with names containing a '.' Use the next variant (as array) in this case<br/>
- *                                                                               Note2: if you need a table alias use the next variant (as array)<br/>
- *                                                                          - a array: ["TABLENAME", "COLUMNNAME", "tableAlias"] OR ["TABLENAME", "COLUMNNAME"]<br/>
+ * @param {string|PreparedSqlStatement|SqlBuilder|null} [pFieldOrCond] - This can be either a full condition (then it has to be the only parameter provided) or a field.
+ * 
+ *                                                                          If you pass a condition (the only param), these types are allowed:
+ *                                                                           - string: just added as it is
+ *                                                                           - PreparedSqlStatement: a PreparedSqlStatement object is used as it is
+ *                                                                           - SqlBuilder: ONLY THE WHERE-CONDITION is used from it
+ *                                                                           
+ *                                                                          If you pass a field (at least pValue has to be filled), this param provides the field information to
+ *                                                                          load the SQLTYPE for this condition. 
+ *                                                                          It can be provided in the following ways:
+ *                                                                          - a string: ONLY in this form: "TABLENAME.COLUMNNAME" 
+ *                                                                               Note1: you may have problems with names containing a '.' Use the next variant (as array) in this case
+ *                                                                               Note2: if you need a table alias use the next variant (as array)
+ *                                                                          - an array: ["TABLENAME", "COLUMNNAME", "tableAlias"] OR ["TABLENAME", "COLUMNNAME"]
+ *                                                                          - a SqlBuilder: the full select is used as subselect and compared with pValue. 
+ *                                                                               (e.g. select * from PERSON where (select "NAME" from ORGANISATION where ... ) = ?)
+ *                                                                                Note: for this you have to provide pFieldType as the type cannot be calculated from the subselect!
  *                                                                          Note: this can also be null if you don't need the field and use a pCondition without a #
  *                                                                     
- * @param {string|SqlBuilder|Array} [pValue] This is the value which is used for the condition.<br/>
- *                                                                       Basically it can be nearly everything you need.<br/>
- *                                                                       - String, etc: is just used as value for the prepared statement. Of course it has to fit the type of the db-column<br/>
- *                                                                       - String starting with '$' is treated as jdito-variable: is loaded with vars.getString("$..."). <br/>
- *                                                                        Note: Use 2 '$' to escape the $ if you don't want it to be treated as JditoVar
+ * @param {*} [pValue] - This is the value which is used for the condition. The type can be anything, but some types are handled in different ways:
+ *                          - string: Is just used as value for the prepared statement. Of course it has to fit the type of the db-column.
+ *                                    If the string starts with a '$' it is recognized as a jdito variable and will be resolved automatically,
+ *                                    Use 2 '$' to escape the $ if you don't want it to be treated as jdito variable (see {@link SqlUtils.escapeVars})
+ *                          - Array: If the condition allows multiple values (for example 'in'), the values can be passed in an array.
+ *                          - SqlBuilder: Can be used for sub-queries
+ *                          - PreparedSqlStatement: Can be used for sub-queries
+ *                          - all other types: Will be converted to a string
+ *                          - NOT ALLOWED: Prepared sql arrays - these will raise an error, because they could provoke sql injection
+ * 
  *                                                                           
- * @param {string} [pCondition="# = ?"] This is the condition which should be used to compare the field with the value.<br/>
- *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #<br/>
+ * @param {string} [pCondition="# = ?"] - This is the condition which should be used to compare the field with the value.
+ *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #
  *                               ? will be replaced by pValue
+ *                               <strong>IMPORTANT: the # has to be before the ?</strong>
  *                               
- * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] You can specify which datatype should be used for the prepared statement <br/>
- *                                                                In most cases you don't need this.<br/>
- *                                                                This is helpful if you for example have a pCondition "year(#) = ?"<br/>
+ * @param {number} [pFieldType=AutomaticallyLoadedType] - You can specify which datatype should be used for the prepared statement 
+ *                                                                In most cases you don't need this, but it's required if pFieldOrCond is a sub-select or null.
+ *                                                                This is helpful if you for example have a pCondition "year(#) = ?"
  *                                                                  then the db-field is DATETIME, but the value is INTEGER. In this case you can overwrite the type.
  *                                                                  
  * @return {SqlBuilder} current SqlBuilder object
@@ -1393,45 +1594,52 @@ SqlBuilder.ALL = {
 SqlBuilder.prototype.or = function(pFieldOrCond, pValue, pCondition, pFieldType)
 {
     return this._or(pFieldOrCond, pValue, true, pCondition, pFieldType);
-}
+};
 
 /**
- * Difference to or(): or() throws errors on invalid values, orIfSet just ignores the condition and does nothing (usefull e.g. for the parameter variables ("$param.ddd") in conditionProcesses.)<br/>
- * <br/>
- * Adds a condition by using "or" to the Sql.<br/>
+ * Difference to or(): or() throws errors on invalid values, orIfSet just ignores the condition and does nothing (usefull e.g. for the parameter variables ("$param.ddd") in conditionProcesses.)
+ * 
+ * Adds a condition by using "or" to the Sql.
  * Note: You have to call .where before using .and / .or (this is mainly for semantic reasons)
  * 
- * @param {string|Array|SqlBuilder|null} [pFieldOrCond] If this is the only parameter, it is used as Condition <br/>
- *                                                                          else it is used as Field.<br/>
- *                                                                     <br/>
- *                                                                          If you use it as Subselect (the only param), it can be:<br/>
- *                                                                           - a string: just added as it is<br/>
- *                                                                           - a PreparedSqlArray: an Array in this form: [sqlStr, [[value1, type1], [valueN, typeN]]]<br/>
- *                                                                                                 the sql is just used as it is.<br/>
- *                                                                           - a SqlBuilder: ONLY THE CONDITION is used from it<br/>
- *                                                                           <br/>
- *                                                                          If you use it as a Field (at least pValue has to be filled), this param provides the field information to<br/>
- *                                                                          load the SQLTYPE for this condition. <br/>
- *                                                                          It can be provided in the following ways:<br/>
- *                                                                          - a string: ONLY in this form: "TABLENAME.COLUMNNAME" <br/>
- *                                                                               Note1: you may have problems with names containing a '.' Use the next variant (as array) in this case<br/>
- *                                                                               Note2: if you need a table alias use the next variant (as array)<br/>
- *                                                                          - a array: ["TABLENAME", "COLUMNNAME", "tableAlias"] OR ["TABLENAME", "COLUMNNAME"]<br/>
+ * @param {string|PreparedSqlStatement|SqlBuilder|null} [pFieldOrCond] - This can be either a full condition (then it has to be the only parameter provided) or a field.
+ * 
+ *                                                                          If you pass a condition (the only param), these types are allowed:
+ *                                                                           - string: just added as it is
+ *                                                                           - PreparedSqlStatement: a PreparedSqlStatement object is used as it is
+ *                                                                           - SqlBuilder: ONLY THE WHERE-CONDITION is used from it
+ *                                                                           
+ *                                                                          If you pass a field (at least pValue has to be filled), this param provides the field information to
+ *                                                                          load the SQLTYPE for this condition. 
+ *                                                                          It can be provided in the following ways:
+ *                                                                          - a string: ONLY in this form: "TABLENAME.COLUMNNAME" 
+ *                                                                               Note1: you may have problems with names containing a '.' Use the next variant (as array) in this case
+ *                                                                               Note2: if you need a table alias use the next variant (as array)
+ *                                                                          - an array: ["TABLENAME", "COLUMNNAME", "tableAlias"] OR ["TABLENAME", "COLUMNNAME"]
+ *                                                                          - a SqlBuilder: the full select is used as subselect and compared with pValue. 
+ *                                                                               (e.g. select * from PERSON where (select "NAME" from ORGANISATION where ... ) = ?)
+ *                                                                                Note: for this you have to provide pFieldType as the type cannot be calculated from the subselect!
  *                                                                          Note: this can also be null if you don't need the field and use a pCondition without a #
  *                                                                     
- * @param {string|SqlBuilder|Array} [pValue] This is the value which is used for the condition.<br/>
- *                                                                       Basically it can be nearly everything you need.<br/>
- *                                                                       - String, etc: is just used as value for the prepared statement. Of course it has to fit the type of the db-column<br/>
- *                                                                       - String starting with '$' is treated as jdito-variable: is loaded with vars.getString("$..."). <br/>
- *                                                                        Note: Use 2 '$' to escape the $ if you don't want it to be treated as JditoVar
+ * @param {*} [pValue] - This is the value which is used for the condition. The type can be anything, but some types are handled in different ways:
+ *                          - string: Is just used as value for the prepared statement. Of course it has to fit the type of the db-column.
+ *                                    If the string starts with a '$' it is recognized as a jdito variable and will be resolved automatically,
+ *                                    Use 2 '$' to escape the $ if you don't want it to be treated as jdito variable (see {@link SqlUtils.escapeVars})
+ *                          - Array: If the condition allows multiple values (for example 'in'), the values can be passed in an array.
+ *                          - SqlBuilder: Can be used for sub-queries
+ *                          - PreparedSqlStatement: Can be used for sub-queries
+ *                          - all other types: Will be converted to a string
+ *                          - NOT ALLOWED: Prepared sql arrays - these will raise an error, because they could provoke sql injection
+ * 
  *                                                                           
- * @param {string} [pCondition="# = ?"] This is the condition which should be used to compare the field with the value.<br/>
- *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #<br/>
+ * @param {string} [pCondition="# = ?"] - This is the condition which should be used to compare the field with the value.
+ *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #
  *                               ? will be replaced by pValue
+ *                               <strong>IMPORTANT: the # has to be before the ?</strong>
  *                               
- * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] You can specify which datatype should be used for the prepared statement <br/>
- *                                                                In most cases you don't need this.<br/>
- *                                                                This is helpful if you for example have a pCondition "year(#) = ?"<br/>
+ * @param {number} [pFieldType=AutomaticallyLoadedType] - You can specify which datatype should be used for the prepared statement 
+ *                                                                In most cases you don't need this, but it's required if pFieldOrCond is a sub-select or null.
+ *                                                                This is helpful if you for example have a pCondition "year(#) = ?"
  *                                                                  then the db-field is DATETIME, but the value is INTEGER. In this case you can overwrite the type.
  *
  * @return {SqlBuilder} current SqlBuilder object
@@ -1439,46 +1647,53 @@ SqlBuilder.prototype.or = function(pFieldOrCond, pValue, pCondition, pFieldType)
 SqlBuilder.prototype.orIfSet = function(pFieldOrCond, pValue, pCondition, pFieldType)
 {
     return this._or(pFieldOrCond, pValue, false, pCondition, pFieldType);
-}
+};
 
 /**
- * Throws an error if pValue is null, undefined or a SqlBuilder without condition (or if pValue is a $-variable: error if the result of it is null or undefined)<br/>
- * Also throws an error if pFieldOrCond is the only parameter and it is null<br/>
- * <br/>
- * Adds a condition by using "and" to the Sql.<br/>
+ * Throws an error if pValue is null, undefined or a SqlBuilder without condition (or if pValue is a $-variable: error if the result of it is null or undefined)
+ * Also throws an error if pFieldOrCond is the only parameter and it is null
+ * 
+ * Adds a condition by using "and" to the Sql.
  * Note: You have to call .where before using .and / .or (this is mainly for semantic reasons)
  * 
- * @param {string|Array|SqlBuilder|null} [pFieldOrCond] If this is the only parameter, it is used as Condition <br/>
- *                                                                          else it is used as Field.<br/>
- *                                                                     <br/>
- *                                                                          If you use it as Subselect (the only param), it can be:<br/>
- *                                                                           - a string: just added as it is<br/>
- *                                                                           - a PreparedSqlArray: an Array in this form: [sqlStr, [[value1, type1], [valueN, typeN]]]<br/>
- *                                                                                                 the sql is just used as it is.<br/>
- *                                                                           - a SqlBuilder: ONLY THE CONDITION is used from it<br/>
- *                                                                           <br/>
- *                                                                          If you use it as a Field (at least pValue has to be filled), this param provides the field information to<br/>
- *                                                                          load the SQLTYPE for this condition. <br/>
- *                                                                          It can be provided in the following ways:<br/>
- *                                                                          - a string: ONLY in this form: "TABLENAME.COLUMNNAME" <br/>
- *                                                                               Note1: you may have problems with names containing a '.' Use the next variant (as array) in this case<br/>
- *                                                                               Note2: if you need a table alias use the next variant (as array)<br/>
- *                                                                          - a array: ["TABLENAME", "COLUMNNAME", "tableAlias"] OR ["TABLENAME", "COLUMNNAME"]<br/>
+ * @param {string|PreparedSqlStatement|SqlBuilder|null} [pFieldOrCond] - This can be either a full condition (then it has to be the only parameter provided) or a field.
+ * 
+ *                                                                          If you pass a condition (the only param), these types are allowed:
+ *                                                                           - string: just added as it is
+ *                                                                           - PreparedSqlStatement: a PreparedSqlStatement object is used as it is
+ *                                                                           - SqlBuilder: ONLY THE WHERE-CONDITION is used from it
+ *                                                                           
+ *                                                                          If you pass a field (at least pValue has to be filled), this param provides the field information to
+ *                                                                          load the SQLTYPE for this condition. 
+ *                                                                          It can be provided in the following ways:
+ *                                                                          - a string: ONLY in this form: "TABLENAME.COLUMNNAME" 
+ *                                                                               Note1: you may have problems with names containing a '.' Use the next variant (as array) in this case
+ *                                                                               Note2: if you need a table alias use the next variant (as array)
+ *                                                                          - an array: ["TABLENAME", "COLUMNNAME", "tableAlias"] OR ["TABLENAME", "COLUMNNAME"]
+ *                                                                          - a SqlBuilder: the full select is used as subselect and compared with pValue. 
+ *                                                                               (e.g. select * from PERSON where (select "NAME" from ORGANISATION where ... ) = ?)
+ *                                                                                Note: for this you have to provide pFieldType as the type cannot be calculated from the subselect!
  *                                                                          Note: this can also be null if you don't need the field and use a pCondition without a #
  *                                                                     
- * @param {string|SqlBuilder|Array} [pValue] This is the value which is used for the condition.<br/>
- *                                                                       Basically it can be nearly everything you need.<br/>
- *                                                                       - String, etc: is just used as value for the prepared statement. Of course it has to fit the type of the db-column<br/>
- *                                                                       - String starting with '$' is treated as jdito-variable: is loaded with vars.getString("$..."). <br/>
- *                                                                        Note: Use 2 '$' to escape the $ if you don't want it to be treated as JditoVar
+ * @param {*} [pValue] - This is the value which is used for the condition. The type can be anything, but some types are handled in different ways:
+ *                          - string: Is just used as value for the prepared statement. Of course it has to fit the type of the db-column.
+ *                                    If the string starts with a '$' it is recognized as a jdito variable and will be resolved automatically,
+ *                                    Use 2 '$' to escape the $ if you don't want it to be treated as jdito variable (see {@link SqlUtils.escapeVars})
+ *                          - Array: If the condition allows multiple values (for example 'in'), the values can be passed in an array.
+ *                          - SqlBuilder: Can be used for sub-queries
+ *                          - PreparedSqlStatement: Can be used for sub-queries
+ *                          - all other types: Will be converted to a string
+ *                          - NOT ALLOWED: Prepared sql arrays - these will raise an error, because they could provoke sql injection
+ * 
  *                                                                           
- * @param {string} [pCondition="# = ?"] This is the condition which should be used to compare the field with the value.<br/>
- *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #<br/>
+ * @param {string} [pCondition="# = ?"] - This is the condition which should be used to compare the field with the value.
+ *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #
  *                               ? will be replaced by pValue
+ *                               <strong>IMPORTANT: the # has to be before the ?</strong>
  *                               
- * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] You can specify which datatype should be used for the prepared statement <br/>
- *                                                                In most cases you don't need this.<br/>
- *                                                                This is helpful if you for example have a pCondition "year(#) = ?"<br/>
+ * @param {number} [pFieldType=AutomaticallyLoadedType] - You can specify which datatype should be used for the prepared statement 
+ *                                                                In most cases you don't need this, but it's required if pFieldOrCond is a sub-select or null.
+ *                                                                This is helpful if you for example have a pCondition "year(#) = ?"
  *                                                                  then the db-field is DATETIME, but the value is INTEGER. In this case you can overwrite the type.
  *                                                                  
  * @return {SqlBuilder} current SqlBuilder object
@@ -1486,45 +1701,52 @@ SqlBuilder.prototype.orIfSet = function(pFieldOrCond, pValue, pCondition, pField
 SqlBuilder.prototype.and = function(pFieldOrCond, pValue, pCondition, pFieldType)
 {
     return this._and(pFieldOrCond, pValue, true, pCondition, pFieldType);
-}
+};
 
 /**
- * Difference to and(): and() throws errors on invalid values, andIfSet just ignores the condition and does nothing (usefull e.g. for the parameter variables ("$param.ddd") in conditionProcesses.)<br/>
- * <br/>
- * Adds a condition by using "and" to the Sql.<br/>
+ * Difference to and(): and() throws errors on invalid values, andIfSet just ignores the condition and does nothing (usefull e.g. for the parameter variables ("$param.ddd") in conditionProcesses.)
+ * 
+ * Adds a condition by using "and" to the Sql.
  * Note: You have to call .where before using .and / .or (this is mainly for semantic reasons)
  * 
- * @param {string|Array|SqlBuilder|null} [pFieldOrCond] If this is the only parameter, it is used as Condition <br/>
- *                                                                          else it is used as Field.<br/>
- *                                                                     <br/>
- *                                                                          If you use it as Subselect (the only param), it can be:<br/>
- *                                                                           - a string: just added as it is<br/>
- *                                                                           - a PreparedSqlArray: an Array in this form: [sqlStr, [[value1, type1], [valueN, typeN]]]<br/>
- *                                                                                                 the sql is just used as it is.<br/>
- *                                                                           - a SqlBuilder: ONLY THE CONDITION is used from it<br/>
- *                                                                           <br/>
- *                                                                          If you use it as a Field (at least pValue has to be filled), this param provides the field information to<br/>
- *                                                                          load the SQLTYPE for this condition. <br/>
- *                                                                          It can be provided in the following ways:<br/>
- *                                                                          - a string: ONLY in this form: "TABLENAME.COLUMNNAME" <br/>
- *                                                                               Note1: you may have problems with names containing a '.' Use the next variant (as array) in this case<br/>
- *                                                                               Note2: if you need a table alias use the next variant (as array)<br/>
- *                                                                          - a array: ["TABLENAME", "COLUMNNAME", "tableAlias"] OR ["TABLENAME", "COLUMNNAME"]<br/>
+ * @param {string|PreparedSqlStatement|SqlBuilder|null} [pFieldOrCond] - This can be either a full condition (then it has to be the only parameter provided) or a field.
+ * 
+ *                                                                          If you pass a condition (the only param), these types are allowed:
+ *                                                                           - string: just added as it is
+ *                                                                           - PreparedSqlStatement: a PreparedSqlStatement object is used as it is
+ *                                                                           - SqlBuilder: ONLY THE WHERE-CONDITION is used from it
+ *                                                                           
+ *                                                                          If you pass a field (at least pValue has to be filled), this param provides the field information to
+ *                                                                          load the SQLTYPE for this condition. 
+ *                                                                          It can be provided in the following ways:
+ *                                                                          - a string: ONLY in this form: "TABLENAME.COLUMNNAME" 
+ *                                                                               Note1: you may have problems with names containing a '.' Use the next variant (as array) in this case
+ *                                                                               Note2: if you need a table alias use the next variant (as array)
+ *                                                                          - an array: ["TABLENAME", "COLUMNNAME", "tableAlias"] OR ["TABLENAME", "COLUMNNAME"]
+ *                                                                          - a SqlBuilder: the full select is used as subselect and compared with pValue. 
+ *                                                                               (e.g. select * from PERSON where (select "NAME" from ORGANISATION where ... ) = ?)
+ *                                                                                Note: for this you have to provide pFieldType as the type cannot be calculated from the subselect!
  *                                                                          Note: this can also be null if you don't need the field and use a pCondition without a #
  *                                                                     
- * @param {string|SqlBuilder|Array} [pValue] This is the value which is used for the condition.<br/>
- *                                                                       Basically it can be nearly everything you need.<br/>
- *                                                                       - String, etc: is just used as value for the prepared statement. Of course it has to fit the type of the db-column<br/>
- *                                                                       - String starting with '$' is treated as jdito-variable: is loaded with vars.getString("$..."). <br/>
- *                                                                        Note: Use 2 '$' to escape the $ if you don't want it to be treated as JditoVar
+ * @param {*} [pValue] - This is the value which is used for the condition. The type can be anything, but some types are handled in different ways:
+ *                          - string: Is just used as value for the prepared statement. Of course it has to fit the type of the db-column.
+ *                                    If the string starts with a '$' it is recognized as a jdito variable and will be resolved automatically,
+ *                                    Use 2 '$' to escape the $ if you don't want it to be treated as jdito variable (see {@link SqlUtils.escapeVars})
+ *                          - Array: If the condition allows multiple values (for example 'in'), the values can be passed in an array.
+ *                          - SqlBuilder: Can be used for sub-queries
+ *                          - PreparedSqlStatement: Can be used for sub-queries
+ *                          - all other types: Will be converted to a string
+ *                          - NOT ALLOWED: Prepared sql arrays - these will raise an error, because they could provoke sql injection
+ * 
  *                                                                           
- * @param {string} [pCondition="# = ?"] This is the condition which should be used to compare the field with the value.<br/>
- *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #<br/>
+ * @param {string} [pCondition="# = ?"] - This is the condition which should be used to compare the field with the value.
+ *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #
  *                               ? will be replaced by pValue
+ *                               <strong>IMPORTANT: the # has to be before the ?</strong>
  *                               
- * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] You can specify which datatype should be used for the prepared statement <br/>
- *                                                                In most cases you don't need this.<br/>
- *                                                                This is helpful if you for example have a pCondition "year(#) = ?"<br/>
+ * @param {number} [pFieldType=AutomaticallyLoadedType] - You can specify which datatype should be used for the prepared statement 
+ *                                                                In most cases you don't need this, but it's required if pFieldOrCond is a sub-select or null.
+ *                                                                This is helpful if you for example have a pCondition "year(#) = ?"
  *                                                                  then the db-field is DATETIME, but the value is INTEGER. In this case you can overwrite the type.
  *
  * @return {SqlBuilder} current SqlBuilder object
@@ -1532,31 +1754,31 @@ SqlBuilder.prototype.and = function(pFieldOrCond, pValue, pCondition, pFieldType
 SqlBuilder.prototype.andIfSet = function(pFieldOrCond, pValue, pCondition, pFieldType)
 {
     return this._and(pFieldOrCond, pValue, false, pCondition, pFieldType);
-}
+};
 
 /**
  * Sets the order by clause of the sql.
  * 
- * @param {string|string[]} pOrderBy a string is added as it is, a array is concatenated by ', '
+ * @param {string|string[]} pOrderBy - a string is added as it is, a array is concatenated by ', '
  * @return {SqlBuilder} current SqlBuilder object
  */
 SqlBuilder.prototype.orderBy = function(pOrderBy)
 {
     this._orderBy = SqlBuilder._getStatement(pOrderBy, "order by", undefined, true);
     return this;
-}
+};
 
 /**
  * Sets the group by clause of the sql.
  * 
- * @param {string|string[]} pFields a string is added as it is, a array is concatenated by ', '
+ * @param {string|string[]} pFields - a string is added as it is, a array is concatenated by ', '
  * @return {SqlBuilder} current SqlBuilder object
  */
 SqlBuilder.prototype.groupBy = function(pFields)
 {
     this._groupBy = SqlBuilder._getStatement(pFields, "group by", undefined, true);
     return this;
-}
+};
 
 /**
  * Adds another SqlBuilder object or select string with union.
@@ -1568,7 +1790,7 @@ SqlBuilder.prototype.union = function(pSelect)
 {
     this._unions.push(SqlBuilder._getStatement(pSelect, "union"));
     return this;
-}
+};
 
 /**
  * Adds another SqlBuilder object or select string with union all.
@@ -1580,12 +1802,12 @@ SqlBuilder.prototype.unionAll = function(pSelect)
 {
     this._unions.push(SqlBuilder._getStatement(pSelect, "union all"));
     return this;
-}
+};
 
 /**
  * Adds a having clause to the sql.
  * 
- * @param {string|SqlBuilder} [pCondition] The having condition. This can be
+ * @param {string|SqlBuilder} [pCondition] - The having condition. This can be
  *                                                - a string (without the where keyword)
  *                                                - a SqlBuilder NOTE: only the condition is used from it
  *          
@@ -1595,36 +1817,39 @@ SqlBuilder.prototype.having = function(pCondition)
 {
     this._having = SqlBuilder._getStatement(pCondition, "having");
     return this;
-}
+};
 
 /**
  * checks if conditions have been added to the object
+ *
  * @return {boolean} true if conditions have been added, false when not
  */
-SqlBuilder.prototype.hasCondition = function() {
-    if (this._where.sqlStorage)
-        return true;
-    return false;
-}
+SqlBuilder.prototype.hasCondition = function() 
+{
+    return !this._where.isEmpty();
+};
 
 /**
  * checks if conditions have been added to the object
  * Note: this does not nessecarily mean that hasCondition() is true
+ *
  * @return {boolean} true if .where was already called
  */
-SqlBuilder.prototype.whereWasCalled = function() {
-    return this._where._whereWasCalled;
-}
+SqlBuilder.prototype.whereWasCalled = function() 
+{
+    return this._whereStatus._whereWasCalled;
+};
 
 /**
  * checks if all mandatory parts to execute the select have been added to the object
  * ("select" and "from" parts)
+ *
  * @return {boolean} true if select and from have been added, false if not
  */
 SqlBuilder.prototype.isFullSelect = function() 
 {
     return !(!this._select || !this._from);
-}
+};
 
 /**
  * Function that resets the current where-condition as if no conditions would have been added
@@ -1637,68 +1862,79 @@ SqlBuilder.prototype.clearWhere = function()
 {
     this._initWhere();
     return this;
-}
+};
 
 /**
  * function that initializes the properties of the ._where object, this is used in the
  * constructor and .clearWhere 
  */
-SqlBuilder.prototype._initWhere = function ()
+SqlBuilder.prototype._initWhere = function()
 {
-    //TODO: maybe put conditions in an object/array for better internal object structure
-    this._where.sqlStorage = "";
-    this._where.preparedValues = [];
-    this._where._lastWasOr = false; // save, if the last condition was an OR. For better bracket-placement
-    this._where._previouslyOnlyOr = false; // also for better bracket-placement
-    this._where._whereWasCalled = false; // where has always to be called first for a better semantic
-}
+    this._where = new PreparedSqlStatement();
+    this._whereStatus = {
+        _lastWasOr: false,
+        _previouslyOnlyOr: false,
+        _whereWasCalled: false
+    };
+};
 
 /**
- * helper function for composing preparedStatements <br/>
- *  <br/>
+ * helper function for composing preparedStatements 
+ *  
  * see .where for more information about the parameters
  * 
- * @param {string | String[]} pField the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME" or as array with column-alias: ["ORGANISATION", "NAME", "myorgAlias"]
- * @param {string} pValue the value that shall be set into the prepared statement
- * @param {string} pCondition the strucutre of the SQL condition as preparedString, you can use a number sign "#" as placeholder for you fieldname;  <br/>
- *                 e.g. "# > ?"; escaping the number sign is possible with a backslash "\" <br/>
+ * @param {string | string[]} pField - the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME" or as array with column-alias: ["ORGANISATION", "NAME", "myorgAlias"]
+ * @param {*} pValue - the value that shall be set into the prepared statement
+ * @param {string} pCondition - the strucutre of the SQL condition as preparedString, you can use a number sign "#" as placeholder for you fieldname;  
+ *                 e.g. "# > ?"; escaping the number sign is possible with a backslash "\" 
  *                 Default is "# = ?" 
- * @param {number|boolean} [pFieldType] SQL-column-type; if the fieldType is not given it's loaded automatically; <br/>
- *                              The loaded type is cached if no type is given. So it is also safe to use this in a loop. <br/>
- *                              e.g. <br/>
- *                              for (...) { <br/>
- *                                  cond.andPrepare("SALESPROJECT_CLASSIFICATION.TYPE", entry, "# <> ?") <br/>
+ * @param {number} [pFieldType] - SQL-column-type; if the fieldType is not given it's loaded automatically; 
+ *                              The loaded type is cached if no type is given. So it is also safe to use this in a loop. 
+ *                              e.g. 
+ *                              for (...) { 
+ *                                  cond.andPrepare("SALESPROJECT_CLASSIFICATION.TYPE", entry, "# <> ?") 
  *                              }
- * @param {boolean} pSubselectBrackets if true, brackets are added to subselects
- * @return {Array} a preparedSqlArray built out of the given parameters
+ * @param {boolean} [pSubselectBrackets] - if true, brackets are added to subselects
+ * @return {PreparedSqlStatement} a PreparedSqlStatement built out of the given parameters
  * 
  * @ignore
  */
 SqlBuilder.prototype._prepare = function(pField, pValue, pCondition, pFieldType, pSubselectBrackets) 
 {
     if (pSubselectBrackets == undefined)
+    {
         pSubselectBrackets = true;
+    }
     
     if (pValue == undefined)
-        throw new Error(translate.withArguments("${SQL_LIB_UNDEFINED_VALUE} field: %0", [pField]));
+    {
+        throw new Error(translate.withArguments("${SQL_LIB_UNDEFINED_VALUE} field: %0", [pField.toString()]));
+    }
     
     if (pCondition == undefined) 
+    {
         pCondition = SqlBuilder.EQUAL();
+    }
 
-    var alias, field;
+    let alias;
     if (pField != null)
     {
-        [alias, field] = SqlUtils.parseField(pField)
+        [alias] = SqlUtils.parseField(pField);
         if (pFieldType == undefined)
+        {
             pFieldType = SqlUtils.getSingleColumnType(pField, undefined, this.alias);
+        }
         
-        var table = SqlUtils._parseFieldQualifier(pField).table;
+        let table = SqlUtils._parseFieldQualifier(pField).table;
         //Set the table for update/delete if it isn't already set, so you don't need to specify the table if the where-condition contains it
         if (table && !this._tableName)
+        {
             this._tableName = table;
+        }
     }
     
-    var values = [];
+    /** @type {[string, number][]} */
+    let values = [];
 
     // If subselect: replace '?' with the subselect
     if (Array.isArray(pValue))
@@ -1708,42 +1944,52 @@ SqlBuilder.prototype._prepare = function(pField, pValue, pCondition, pFieldType,
     } 
     else
     {
-        var type = pFieldType;
+        let type = pFieldType;
         //booleans are normally stored with TINYINT, this is to support true/false directly
         if (_isIntegerType(type) && Utils.isBoolean(pValue))
+        {
             pValue = Number(pValue);
+        }
         values = [[pValue.toString(), type]];
     }
 
     if (pField != null)
+    {
         pCondition = SqlUtils.replaceConditionTemplate(pCondition, "#", alias);
+    }
     
-    return [pCondition, values];
+    return new PreparedSqlStatement(pCondition, values);
     
-    function _isIntegerType (pType)
+    /**
+     * Checks if the given sql type is a form of integer
+     * 
+     * @param {number} pType - The sql type
+     * @returns If it's an integer type
+     */
+    function _isIntegerType(pType)
     {
         return pType == SQLTYPES.TINYINT
             || pType == SQLTYPES.SMALLINT
             || pType == SQLTYPES.INTEGER
             || pType == SQLTYPES.BIGINT;
     }
-}
+};
 
 /**
  * generates a part of the sql
  * 
- * @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=false] if this is true and pElement is an array, it will be automatically <br/>
+ * @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=false] - if this is true and pElement is an array, it will be automatically 
  *                               joined together to a string
- * @param {boolean} [pUseSubselectAlias=false] if true the subselectAlias is added if the element is a subquery
- * 
+ * @param {boolean} [pUseSubselectAlias=false] - if true the subselectAlias is added if the element is a subquery
+ * @return {PreparedSqlStatement}
  * @ignore
  */
-SqlBuilder._getStatement = function (pElement, pPrefix, pPostfix, pAutoJoin, pUseSubselectAlias)
+SqlBuilder._getStatement = function(pElement, pPrefix, pPostfix, pAutoJoin, pUseSubselectAlias)
 {
-    var preparedValues = [];
+    let preparedValues = [];
     if (typeof pElement !== "string")
     {
         if (Array.isArray(pElement) && pElement.length !== undefined && pAutoJoin) //array of fields
@@ -1751,7 +1997,9 @@ SqlBuilder._getStatement = function (pElement, pPrefix, pPostfix, pAutoJoin, pUs
             for (let i = 0; i < pElement.length; i++)
             {
                 if (typeof pElement[i] !== "string")
+                {
                     pElement[i] = _getElement(pElement[i]);
+                }
             }
              
             pElement = ArrayUtils.joinNonEmptyFields(pElement, ", ");
@@ -1763,19 +2011,26 @@ SqlBuilder._getStatement = function (pElement, pPrefix, pPostfix, pAutoJoin, pUs
     }
 
     if (pPrefix && pElement)
+    {
         pElement = pPrefix + " " + pElement;
+    }
     if (pPostfix && pElement)
+    {
         pElement += " " + pPostfix;
+    }
     
-    return {
-        preparedValues: preparedValues,
-        sqlStorage: pElement.toString()
-    };
+    return new PreparedSqlStatement(pElement.toString(), preparedValues);
 
-    function _getElement (element)
+    /**
+     * Builds an sql element
+     * 
+     * @param {*} element - Part of a sql
+     * @returns The sql element
+     */
+    function _getElement(element)
     {
-        var isSubQuery = false;
-        var subselectAlias = "";
+        let isSubQuery = false;
+        let subselectAlias = "";
         if (SqlBuilder.checkCanBuildSql(element))
         {
             if (element instanceof SqlBuilder && element.isFullSelect())
@@ -1783,98 +2038,96 @@ SqlBuilder._getStatement = function (pElement, pPrefix, pPostfix, pAutoJoin, pUs
                 isSubQuery = true;
                 
                 if (pUseSubselectAlias && element._subselectAlias)
+                {
                     subselectAlias = " " + element._subselectAlias;
+                }
             }
             element = element.build();
         }
         preparedValues = preparedValues.concat(element[1]);
         if (isSubQuery || pAutoJoin)
+        {
             return "(" + element[0] + ")" + subselectAlias;
+        }
         return element[0];
     }
-}
+};
 
 /**
  * builds a prepared condition out of the object. Only the condition is used. Select, from, ... are ignored.
  * 
- * @return {Array} prepared condition
+ * @return {PreparedSqlArray} prepared condition
  */
 SqlBuilder.prototype.buildCondition = function()
 {   
-    return [this._where.sqlStorage, this._where.preparedValues];
-}
+    return this._where.toArray();
+};
 
 /**
  * builds a prepared statement out of the object. If a part doesn't exit, it's just ignored.
  * 
- * @param {string} [pDefaultConditionIfNone=""] a default condition string which should be used if the SqlBuilder doesn't have any condition
- * @return {Array} prepared statement
+ * @param {string} [pDefaultConditionIfNone=""] - a default condition string which should be used if the SqlBuilder doesn't have any condition
+ * @return {PreparedSqlArray} prepared statement
  */
 SqlBuilder.prototype.build = function(pDefaultConditionIfNone)
 {
-    var wherePrefix = "";
-    var fromObj = this._from;
+    let wherePrefix = "";
+    let fromStatement = this._from;
     
     if (this.isFullSelect())
     {
-        fromObj = {
-            sqlStorage: "from " + this._from.sqlStorage,
-            preparedValues: this._from.preparedValues
-        };
-        if (this._where.sqlStorage)
+        fromStatement = new PreparedSqlStatement("from " + fromStatement.sqlString, fromStatement.preparedValues);
+        if (!this._where.isEmpty())
+        {
             wherePrefix = "where ";
+        }
     }
     
-    var whereSql = this._where.sqlStorage;
+    let whereSql = this._where.sqlString;
     
     if (!this.hasCondition() && pDefaultConditionIfNone)
+    {
         whereSql = wherePrefix + pDefaultConditionIfNone;
+    }
     
-    var whereObj = {
-        sqlStorage : wherePrefix + whereSql,
-        preparedValues : this._where.preparedValues
-    };
+    let whereStatement = new PreparedSqlStatement(wherePrefix + whereSql, this._where.preparedValues);
     
-    var allParts = [
+    let allParts = [
         this._select,
-        fromObj
-        ].concat(this._joins).concat([
-        whereObj,
-        this._groupBy,
-        this._having,
-        this._orderBy
-        ]).concat(this._unions);
+        fromStatement
+    ].concat(this._joins)
+        .concat([
+            whereStatement,
+            this._groupBy,
+            this._having,
+            this._orderBy
+        ])
+        .concat(this._unions);
         
-    var sqlStr = "";
-    var preparedVals = [];
-    for (let i = 0, l = allParts.length; i < l; i++)
+    let fullSqlStatement = new PreparedSqlStatement();
+    for (let part of allParts)
     {
-        let part = allParts[i];
         if (part)
         {
-            if (sqlStr && part.sqlStorage)
-                sqlStr += " ";
-            sqlStr += part.sqlStorage;
-            if (part.preparedValues.length)
-                preparedVals = preparedVals.concat(part.preparedValues);
+            fullSqlStatement.appendStatement(part, " ");
         }
     }
     
-    return [sqlStr, preparedVals];
-}
+    return fullSqlStatement.toArray();
+};
 
 /**
- * Updates data in the database.<br/>
+ * Updates data in the database.
  * Note: the default for pExecuteOnlyIfConditionExists is true to prevent updating all rows if the SqlBuilder has no condition.
  * 
- * @param {boolean} [pExecuteOnlyIfConditionExists=true] If true, the update is only done if there is a condition.<br/>
+ * @param {boolean} pExecuteOnlyIfConditionExists - If true, the update is only done if there is a condition.
  *      <strong>IMPORTANT: If this is set to false and there is no condition, every row in the table will be updated!</strong>
- * @param {string} [pTableName] The table for updating data. If undefined, the from part of the SqlBuilder will be used (works only if it is a tablename). If no from is set,
+ * @param {string} pTableName - The table for updating data. If undefined, the from part of the SqlBuilder will be used (works only if it is a tablename). If no from is set,
  *      the table of the first where-condition is used.
- * @param {string[]} pColumns The columns where you want to update.
- * @param {SQLTYPES[]} [pColumnTypes=null] normally you can set this to null as the types are calculated if not provided
- * @param {string[]} pValues The values to be updated.
- * @param {number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ * @param {string[]} pColumns - The columns where you want to update.
+ * @param {number[]} pColumnTypes - normally you can set this to null as the types are calculated if not provided
+ * @param {string[]} pValues - The values to be updated.
+ * @param {number} [pTimeout=-1] - Specifies the period, in milliseconds, after which the query will be aborted.
  *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
  *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {number} the number of rows affected
@@ -1885,10 +2138,14 @@ SqlBuilder.prototype.updateData = function(pExecuteOnlyIfConditionExists, pTable
     if (this._checkForUpdate(pExecuteOnlyIfConditionExists))
     {
         if (!pTableName && !this._tableName)
+        {
             throw SqlBuilder._ERROR_NO_TABLE();
+        }
         
         if (!pColumns)
+        {
             pColumns = null;
+        }
         
         return db.updateData(
             (pTableName ? pTableName : this._tableName),
@@ -1901,54 +2158,62 @@ SqlBuilder.prototype.updateData = function(pExecuteOnlyIfConditionExists, pTable
     }
     
     return 0;
-}
+};
 
 /**
  * Updates data in the database. This function calls SqlBuilder.prototype.updateData, but provides a shorter syntax to
  * improve the readability.
  * 
- * @param {Object|Map} pFieldValues Object with the columns to update as keys mapped to their values
- * @param {string} [pTableName] The table for updating data. If undefined, the from part of the SqlBuilder will be used (works only if it is a tablename). If no from is set,
+ * @param {object | Map} pFieldValues - Object with the columns to update as keys mapped to their values
+ * @param {string} [pTableName] - The table for updating data. If undefined, the from part of the SqlBuilder will be used (works only if it is a tablename). If no from is set,
  *      the table of the first where-condition is used.
  * @return {number} the number of rows affected
  * @example
  * newWhere("SALESORDER.SALESORDERID", "$field.SALESORDERID")
  *  .updateFields({"ORDERSTATUS" : "1"}); //pTableName can be omitted here since it's clearly defined by the given condition
  */
-SqlBuilder.prototype.updateFields = function (pFieldValues, pTableName)
+SqlBuilder.prototype.updateFields = function(pFieldValues, pTableName)
 {
     if (!pFieldValues || typeof(pFieldValues) !== "object")
+    {
         throw SqlBuilder._ERROR_UPDATE_VALUES_INVALID;
+    }
         
-    var columnValues = SqlBuilder._columnsValuesFromObject(pFieldValues, true);
+    let columnValues = SqlBuilder._columnsValuesFromObject(pFieldValues, true);
     if (columnValues.columns.length === 0)
+    {
         return 0;
+    }
     return this.updateData(true, pTableName, columnValues.columns, null, columnValues.values);
-}
+};
 
 /**
  * Builds an array containing the table and condition for an update.
  * 
- * @param {Object|Map} pFieldValues Object with the columns to update as keys mapped to their values
- * @param {string} [pTableName] The table for updating data. If undefined, the from part of the SqlBuilder will be used (works only if it is a tablename). If no from is set,
+ * @param {object | Map} pFieldValues - Object with the columns to update as keys mapped to their values
+ * @param {string} [pTableName] - The table for updating data. If undefined, the from part of the SqlBuilder will be used (works only if it is a tablename). If no from is set,
  *      the table of the first where-condition is used.
- * @return {Array} array of [tableName, columns, columnTypes, values, preparedCondition], like it is required by db.updates or null if there is no condition
+ * @return {[string, string[], number[], string[], Array]} array of [tableName, columns, columnTypes, values, preparedCondition], like it is required by db.updates or null if there is no condition
  * @example 
- * var updateStatements = [];
+ * let updateStatements = [];
  * updateStatements.push(newWhere("PERSON.PERSONID", pPersonId).buildUpdateStatement({"FIRSTNAME" : firstName}));
  * updateStatements.push(newWhere("ORGANISATION.ORGANISATIONID", pOrganisationId).buildUpdateStatement({"NAME" : organisationName}));
  * db.updates(updateStatements);
  */
-SqlBuilder.prototype.buildUpdateStatement = function (pFieldValues, pTableName)
+SqlBuilder.prototype.buildUpdateStatement = function(pFieldValues, pTableName)
 {
     if (!pFieldValues || typeof(pFieldValues) !== "object")
+    {
         throw SqlBuilder._ERROR_UPDATE_VALUES_INVALID;
+    }
         
-    var columnValues = SqlBuilder._columnsValuesFromObject(pFieldValues, true);
+    let columnValues = SqlBuilder._columnsValuesFromObject(pFieldValues, true);
     if (columnValues.columns.length !== 0 && this._checkForUpdate())
     {
         if (!pTableName && !this._tableName)
+        {
             throw SqlBuilder._ERROR_NO_TABLE();
+        }
         
         return [
             (pTableName ? pTableName : this._tableName),
@@ -1959,30 +2224,36 @@ SqlBuilder.prototype.buildUpdateStatement = function (pFieldValues, pTableName)
         ];
     }
     return null;
-}
+};
 
 /**
  * Builds an array containing the data for an insert.
  * 
- * @param {Object|Map} pFieldValues Object with the columns to insert into as keys mapped to their values
- * @param {string} [pTableName] The table for updating data. If undefined, the from part of the SqlBuilder will be used (works only if it is a tablename). If no from is set,
+ * @param {object | Map} pFieldValues - Object with the columns to insert into as keys mapped to their values
+ * @param {string} [pTableName] - The table for updating data. If undefined, the from part of the SqlBuilder will be used (works only if it is a tablename). If no from is set,
  *      the table of the first where-condition is used.
- * @param {string} [pAutoUidField] UID column that should be filled with a random UUID 
+ * @param {string} [pAutoUidField] - UID column that should be filled with a random UUID 
  * @return {Array} array of [tableName, columns, columnTypes, values, preparedCondition], like it is required by db.updates or null if there is no condition
  */
-SqlBuilder.prototype.buildInsertStatement = function (pFieldValues, pTableName, pAutoUidField)
+SqlBuilder.prototype.buildInsertStatement = function(pFieldValues, pTableName, pAutoUidField)
 {
     if (!pFieldValues || !Utils.isObject(pFieldValues))
+    {
         throw SqlBuilder._ERROR_UPDATE_VALUES_INVALID;
+    }
         
     if (pAutoUidField)
+    {
         pFieldValues[pAutoUidField] = util.getNewUUID();
+    }
     
-    var columnValues = SqlBuilder._columnsValuesFromObject(pFieldValues);
+    let columnValues = SqlBuilder._columnsValuesFromObject(pFieldValues);
     if (columnValues.columns.length !== 0)
     {
         if (!pTableName && !this._tableName)
+        {
             throw SqlBuilder._ERROR_NO_TABLE();
+        }
         
         return [
             (pTableName ? pTableName : this._tableName),
@@ -1992,17 +2263,17 @@ SqlBuilder.prototype.buildInsertStatement = function (pFieldValues, pTableName,
         ];
     }
     return null;
-}
+};
 
 /**
- * Inserts data in the database. This function doesn't require any where-condition, it is intended to be called right after 'new SqlBuilder()'. <br/>
+ * Inserts data in the database. This function doesn't require any where-condition, it is intended to be called right after 'new SqlBuilder()'. 
  * 
- * @param {string} [pTableName] The table for inserting data. If undefined, the from part of the SqlBuilder will be used (works only if it is a tablename). If no from is set,
+ * @param {string} pTableName - The table for inserting data. If undefined, the from part of the SqlBuilder will be used (works only if it is a tablename). If no from is set,
  *      the table of the first where-condition is used.
- * @param {string[]} pColumns The columns where you want to insert into.
- * @param {SQLTYPES[]} [pColumnTypes=null] normally you can set this to null as the types are calculated if not provided
- * @param {string[]} pValues The values to be inserted.
- * @param {number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ * @param {string[]} pColumns - The columns where you want to insert into.
+ * @param {number[]} pColumnTypes - normally you can set this to null as the types are calculated if not provided
+ * @param {string[]} pValues - The values to be inserted.
+ * @param {number} [pTimeout=-1] - Specifies the period, in milliseconds, after which the query will be aborted.
  *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
  *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {number} the number of rows affected
@@ -2011,10 +2282,14 @@ SqlBuilder.prototype.buildInsertStatement = function (pFieldValues, pTableName,
 SqlBuilder.prototype.insertData = function(pTableName, pColumns, pColumnTypes, pValues, pTimeout)
 {
     if (!pTableName && !this._tableName)
+    {
         throw SqlBuilder._ERROR_NO_TABLE();
+    }
 
     if (!pColumns)
+    {
         pColumns = null;
+    }
 
     return db.insertData(
         (pTableName ? pTableName : this._tableName),
@@ -2023,16 +2298,16 @@ SqlBuilder.prototype.insertData = function(pTableName, pColumns, pColumnTypes, p
         pValues,
         (this.alias ? this.alias : db.getCurrentAlias()),
         (pTimeout ? pTimeout : -1));
-}
+};
 
 /**
  * Inserts data in the database. This function calls SqlBuilder.prototype.insertData, but provides a shorter syntax to
  * improve the readability.
  * 
- * @param {Object|Map} pFieldValues Object with the columns to update as keys mapped to their values
- * @param {string} [pTableName] The table for updating data. If undefined, the from part of the SqlBuilder will be used (works only if it is a tablename). If no from is set,
+ * @param {object | Map} pFieldValues - Object with the columns to update as keys mapped to their values
+ * @param {string} [pTableName] - The table for updating data. If undefined, the from part of the SqlBuilder will be used (works only if it is a tablename). If no from is set,
  *      the table of the first where-condition is used.
- * @param {string} [pAutoUidField] UID column that should be filled with a random UUID 
+ * @param {string} [pAutoUidField] - UID column that should be filled with a random UUID 
  * @return {number} the number of rows affected
  * @example
  * new SqlBuilder().insertFields({
@@ -2041,27 +2316,40 @@ SqlBuilder.prototype.insertData = function(pTableName, pColumns, pColumnTypes, p
  *         "OBJECT_TYPE" : pObjectType
  *     }, "ACTIVITYLINK", "ACTIVITYLINKID");
  */
-SqlBuilder.prototype.insertFields = function (pFieldValues, pTableName, pAutoUidField)
+SqlBuilder.prototype.insertFields = function(pFieldValues, pTableName, pAutoUidField)
 {
     if (!pFieldValues || typeof(pFieldValues) !== "object")
+    {
         throw SqlBuilder._ERROR_UPDATE_VALUES_INVALID;
+    }
         
     if (pAutoUidField)
+    {
         pFieldValues[pAutoUidField] = util.getNewUUID();
+    }
     
-    var columnValues = SqlBuilder._columnsValuesFromObject(pFieldValues);
+    let columnValues = SqlBuilder._columnsValuesFromObject(pFieldValues);
     if (columnValues.columns.length === 0)
+    {
         return 0;
+    }
     return this.insertData(pTableName, columnValues.columns, null, columnValues.values);
-}
+};
 
-SqlBuilder._columnsValuesFromObject = function (pFieldValues, pIncludeNullValues)
+/**
+ * Maps an object of fields and values to two seperate arrays
+ *
+ * @param {object} pFieldValues - Object with fields and values, the values will be stringified
+ * @param {boolean} [pIncludeNullValues=false] - If properties with no value should be mapped as empty strings or if they should be omitted
+ * @return {{columns: string[], values: string[]}} Object containing arrays of columns and values
+ */
+SqlBuilder._columnsValuesFromObject = function(pFieldValues, pIncludeNullValues)
 {
-    var columns = [];
-    var values = [];
+    let columns = [];
+    let values = [];
     if (Utils.isMap(pFieldValues))
     {
-        pFieldValues.forEach(function (value, key)
+        pFieldValues.forEach(function(value, key)
         {
             if (pIncludeNullValues || (value !== undefined && value !== null))
             {
@@ -2086,23 +2374,31 @@ SqlBuilder._columnsValuesFromObject = function (pFieldValues, pIncludeNullValues
         values: values
     };
     
-    function _valueToString (pValue)
+    /**
+     * Stringifies a value
+     * 
+     * @param {*} pValue - The value
+     * @returns {string} String representation of the value
+     */
+    function _valueToString(pValue)
     {
         if (pValue === undefined || pValue === null)
+        {
             return "";
+        }
         return pValue.toString();
     }
-}
+};
 
 /**
- * Deletes data from the database.<br/>
+ * Deletes data from the database.
  * Note: the default for pExecuteOnlyIfConditionExists is true to prevent updating all rows if the SqlBuilder has no condition.
-
- * @param {boolean} [pExecuteOnlyIfConditionExists=true] If true, the deletion is only done if there is a condition.<br/>
+ *
+ * @param {boolean} [pExecuteOnlyIfConditionExists=true] - If true, the deletion is only done if there is a condition.
  *      <strong>IMPORTANT: If this is set to false and there is no condition, every row in the table will be deleted!</strong>
- * @param {string} [pTableName] The table for deleting data. If undefined, the from part of the SqlBuilder will be used. If no from is set,
+ * @param {string} [pTableName] - The table for deleting data. If undefined, the from part of the SqlBuilder will be used. If no from is set,
  *      the table of the first where-condition is used.
- * @param {number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ * @param {number} [pTimeout=-1] - Specifies the period, in milliseconds, after which the query will be aborted.
  *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
  *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {number} the number of rows affected
@@ -2116,7 +2412,9 @@ SqlBuilder.prototype.deleteData = function(pExecuteOnlyIfConditionExists, pTable
     if (this._checkForUpdate(pExecuteOnlyIfConditionExists))
     {
         if (!pTableName && !this._tableName)
+        {
             throw SqlBuilder._ERROR_NO_TABLE();
+        }
         
         return db.deleteData(
             (pTableName ? pTableName : this._tableName),
@@ -2128,18 +2426,18 @@ SqlBuilder.prototype.deleteData = function(pExecuteOnlyIfConditionExists, pTable
     {
         return 0;
     }
-}
+};
 
 /**
  * Builds an array containing the table and condition for a delete.
  * 
- * @param {boolean} [pOnlyIfConditionExists=true] If true and there is no condition, null is returned.<br/>
+ * @param {boolean} [pOnlyIfConditionExists=true] - If true and there is no condition, null is returned.
  *      <strong>IMPORTANT: If this is set to false and there is no condition, every row in the table will be deleted!</strong>
- * @param {string} [pTableName] The table for deleting data. If undefined, the from part of the SqlBuilder will be used. If no from is set,
+ * @param {string} [pTableName] - The table for deleting data. If undefined, the from part of the SqlBuilder will be used. If no from is set,
  *      the table of the first where-condition is used.
  * @return {Array} array of [tableName, preparedCondition], like it is required by db.deletes
  * @example 
- * var deleteStatements = [];
+ * let deleteStatements = [];
  * deleteStatements.push(newWhere("PERSON.PERSONID", pPersonId).buildDeleteStatement());
  * deleteStatements.push(newWhere("CONTACT.CONTACTID", pContactId).buildDeleteStatement());
  * db.deletes(deleteStatements);
@@ -2149,7 +2447,9 @@ SqlBuilder.prototype.buildDeleteStatement = function(pOnlyIfConditionExists, pTa
     if (this._checkForUpdate(pOnlyIfConditionExists))
     {
         if (!pTableName && !this._tableName)
+        {
             throw SqlBuilder._ERROR_NO_TABLE();
+        }
         
         return [
             (pTableName ? pTableName : this._tableName),
@@ -2157,15 +2457,17 @@ SqlBuilder.prototype.buildDeleteStatement = function(pOnlyIfConditionExists, pTa
         ];
     }
     else
+    {
         return null;
-}
+    }
+};
 
 /**
- * Executes the SQL using db.cell and returns the result.<br/>
+ * Executes the SQL using db.cell and returns the result.
  * Note: the default for pExecuteOnlyIfConditionExists is false becausse it is more natural to select all rows if no condition exists.
  * 
- * @param {boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, "" or the provided FallbackValue is returned
- * @param {any} [pFallbackValue=""] here you can provide a fallback value if pExecuteOnlyIfConditionExists is true and the SqlBuilder has no condition.<br/>
+ * @param {boolean} [pExecuteOnlyIfConditionExists=false] - if true and there is no condition, "" or the provided FallbackValue is returned
+ * @param {any} [pFallbackValue=""] - here you can provide a fallback value if pExecuteOnlyIfConditionExists is true and the SqlBuilder has no condition.
  *                                       This is intended for e.g. select count(*) from ... because there a default value of "0" is more helpful
  * @return {string} the result of the query
  */
@@ -2180,54 +2482,54 @@ SqlBuilder.prototype.cell = function(pExecuteOnlyIfConditionExists, pFallbackVal
     {
         return (pFallbackValue ? pFallbackValue : "");
     }
-}
+};
 
 /**
- * Executes the SQL using db.array(db.ROW, ...) and returns the result.<br/>
+ * Executes the SQL using db.array(db.ROW, ...) and returns the result.
  * Note: the default for pExecuteOnlyIfConditionExists is false becausse it is more natural to select all rows if no condition exists.
  * 
- * @param {boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {number} [pMaxRows=0] The maximum number of rows to be returned (ORDER BY must be defined in the SQL statement!).
-   *                If you specify maxRows, this restriction might apply to all tables indicated in the JOIN part of the query.
-   *                If you do not want to restrict this value, enter 0.
- * @param {number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ * @param {boolean} [pExecuteOnlyIfConditionExists=false] - if true and there is no condition, [] is returned
+ * @param {number} [pMaxRows=0] - The maximum number of rows to be returned (ORDER BY must be defined in the SQL statement!).
+ *                If you specify maxRows, this restriction might apply to all tables indicated in the JOIN part of the query.
+ *                If you do not want to restrict this value, enter 0.
+ * @param {number} [pTimeout=-1] - Specifies the period, in milliseconds, after which the query will be aborted.
  *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
  *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {string[]} the result of the query
  */
-SqlBuilder.prototype.arrayRow = function (pExecuteOnlyIfConditionExists, pMaxRows, pTimeout)
+SqlBuilder.prototype.arrayRow = function(pExecuteOnlyIfConditionExists, pMaxRows, pTimeout)
 {
     return this.array(db.ROW, pExecuteOnlyIfConditionExists, pMaxRows, pTimeout);
-}
+};
 
 /**
- * Executes the SQL using db.array(db.COLUMN, ...) and returns the result.<br/>
+ * Executes the SQL using db.array(db.COLUMN, ...) and returns the result.
  * Note: the default for pExecuteOnlyIfConditionExists is false becausse it is more natural to select all rows if no condition exists.
  * 
- * @param {boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {number} [pMaxRows=0] The maximum number of rows to be returned (ORDER BY must be defined in the SQL statement!).
-   *                If you specify maxRows, this restriction might apply to all tables indicated in the JOIN part of the query.
-   *                If you do not want to restrict this value, enter 0.
- * @param {number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ * @param {boolean} [pExecuteOnlyIfConditionExists=false] - if true and there is no condition, [] is returned
+ * @param {number} [pMaxRows=0] - The maximum number of rows to be returned (ORDER BY must be defined in the SQL statement!).
+ *                If you specify maxRows, this restriction might apply to all tables indicated in the JOIN part of the query.
+ *                If you do not want to restrict this value, enter 0.
+ * @param {number} [pTimeout=-1] - Specifies the period, in milliseconds, after which the query will be aborted.
  *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
  *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {string[]} the result of the query
  */
-SqlBuilder.prototype.arrayColumn = function (pExecuteOnlyIfConditionExists, pMaxRows, pTimeout)
+SqlBuilder.prototype.arrayColumn = function(pExecuteOnlyIfConditionExists, pMaxRows, pTimeout)
 {
     return this.array(db.COLUMN, pExecuteOnlyIfConditionExists, pMaxRows, pTimeout);
-}
+};
 
 /**
- * Executes the SQL using db.array and returns the result.<br/>
+ * Executes the SQL using db.array and returns the result.
  * Note: the default for pExecuteOnlyIfConditionExists is false becausse it is more natural to select all rows if no condition exists.
  * 
- * @param {number} pType db.ROW or db.COLUMN
- * @param {boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {number} [pMaxRows=0] The maximum number of rows to be returned (ORDER BY must be defined in the SQL statement!).
-   *                If you specify maxRows, this restriction might apply to all tables indicated in the JOIN part of the query.
-   *                If you do not want to restrict this value, enter 0.
- * @param {number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ * @param {number} pType - db.ROW or db.COLUMN
+ * @param {boolean} [pExecuteOnlyIfConditionExists=false] - if true and there is no condition, [] is returned
+ * @param {number} [pMaxRows=0] - The maximum number of rows to be returned (ORDER BY must be defined in the SQL statement!).
+ *                If you specify maxRows, this restriction might apply to all tables indicated in the JOIN part of the query.
+ *                If you do not want to restrict this value, enter 0.
+ * @param {number} [pTimeout=-1] - Specifies the period, in milliseconds, after which the query will be aborted.
  *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
  *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {string[]} the result of the query
@@ -2245,17 +2547,17 @@ SqlBuilder.prototype.array = function(pType, pExecuteOnlyIfConditionExists, pMax
     {
         return [];
     }
-}
+};
 
 /**
- * Executes the SQL using db.arrayPage and returns the result.<br/>
+ * Executes the SQL using db.arrayPage and returns the result.
  * Note: the default for pExecuteOnlyIfConditionExists is false becausse it is more natural to select all rows if no condition exists.
  * 
- * @param {number} pType db.ROW or db.COLUMN
+ * @param {number} pType - db.ROW or db.COLUMN
  * @param {number} pStartIndex
  * @param {number} pRowCount
- * @param {boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ * @param {boolean} [pExecuteOnlyIfConditionExists=false] - if true and there is no condition, [] is returned
+ * @param {number} [pTimeout=-1] - Specifies the period, in milliseconds, after which the query will be aborted.
  *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
  *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {string[]} the result of the query
@@ -2274,17 +2576,17 @@ SqlBuilder.prototype.arrayPage = function(pType, pStartIndex, pRowCount, pExecut
     {
         return [];
     }
-}
+};
 
 /**
- * Executes the SQL using db.table and returns the result.<br/>
+ * Executes the SQL using db.table and returns the result.
  * Note: the default for pExecuteOnlyIfConditionExists is false becausse it is more natural to select all rows if no condition exists.
  * 
- * @param {boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {number} [pMaxRows=0] The maximum number of rows to be returned (ORDER BY must be defined in the SQL statement!).
-   *                If you specify maxRows, this restriction might apply to all tables indicated in the JOIN part of the query.
-   *                If you do not want to restrict this value, enter 0.
- * @param {number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ * @param {boolean} [pExecuteOnlyIfConditionExists=false] - if true and there is no condition, [] is returned
+ * @param {number} [pMaxRows=0] - The maximum number of rows to be returned (ORDER BY must be defined in the SQL statement!).
+ *                If you specify maxRows, this restriction might apply to all tables indicated in the JOIN part of the query.
+ *                If you do not want to restrict this value, enter 0.
+ * @param {number} [pTimeout=-1] - Specifies the period, in milliseconds, after which the query will be aborted.
  *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
  *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {string[][]} the result of the query
@@ -2302,16 +2604,16 @@ SqlBuilder.prototype.table = function(pExecuteOnlyIfConditionExists, pMaxRows, p
     {
         return [];
     }
-}
+};
 
 /**
- * Executes the SQL using db.tablePage and returns the result.<br/>
+ * Executes the SQL using db.tablePage and returns the result.
  * Note: the default for pExecuteOnlyIfConditionExists is false becausse it is more natural to select all rows if no condition exists.
  * 
  * @param {number} pStartIndex
  * @param {number} pRowCount
- * @param {boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ * @param {boolean} [pExecuteOnlyIfConditionExists=false] - if true and there is no condition, [] is returned
+ * @param {number} [pTimeout=-1] - Specifies the period, in milliseconds, after which the query will be aborted.
  *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
  *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {string[][]} the result of the query
@@ -2330,7 +2632,7 @@ SqlBuilder.prototype.tablePage = function(pStartIndex, pRowCount, pExecuteOnlyIf
     {
         return [];
     }
-}
+};
 
 /**
  * Sets the pagesize for paging
@@ -2338,11 +2640,11 @@ SqlBuilder.prototype.tablePage = function(pStartIndex, pRowCount, pExecuteOnlyIf
  * @param {number} pPageSize
  * @return {SqlBuilder} current SqlBuilder object
  */
-SqlBuilder.prototype.pageSize = function (pPageSize)
+SqlBuilder.prototype.pageSize = function(pPageSize)
 {
     this._pageSize = pPageSize;
     return this;
-}
+};
 
 /**
  * Sets the start row for paging
@@ -2350,35 +2652,41 @@ SqlBuilder.prototype.pageSize = function (pPageSize)
  * @param {number} pStartRow
  * @return {SqlBuilder} current SqlBuilder object
  */
-SqlBuilder.prototype.startRow = function (pStartRow)
+SqlBuilder.prototype.startRow = function(pStartRow)
 {
     this._startRow = pStartRow;
     return this;
-}
+};
 
 /**
  * Executes the SQL and returns the result. The startRow for paging will be increased by the pageSize, so you can use this method
  * for iterating over the table pages. You can use SqlBuilder.prototype.hasMoreRows() to check if the end of rows was reached.
  * 
- * @param {boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ * @param {boolean} [pExecuteOnlyIfConditionExists=false] - if true and there is no condition, [] is returned
+ * @param {number} [pTimeout=-1] - Specifies the period, in milliseconds, after which the query will be aborted.
  *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
  *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {string[][]} the result of the query
  */
-SqlBuilder.prototype.nextTablePage = function (pExecuteOnlyIfConditionExists, pTimeout)
+SqlBuilder.prototype.nextTablePage = function(pExecuteOnlyIfConditionExists, pTimeout)
 {
     if (this._pageSize == null || isNaN(this._pageSize))
+    {
         throw SqlBuilder._ERROR_PAGESIZE_INVALID();
+    }
     
     if (this._startRow == null)
+    {
         this._startRow = 0;
+    }
     
     if (this._hasMoreRows && this._checkForSelect(pExecuteOnlyIfConditionExists))
     {
-        var data = this.tablePage(this._startRow, this._pageSize, pExecuteOnlyIfConditionExists, pTimeout);
+        let data = this.tablePage(this._startRow, this._pageSize, pExecuteOnlyIfConditionExists, pTimeout);
         if (data.length < this._pageSize)
+        {
             this._hasMoreRows = false;
+        }
         this._startRow += this._pageSize;
         return data;
     }
@@ -2387,77 +2695,88 @@ SqlBuilder.prototype.nextTablePage = function (pExecuteOnlyIfConditionExists, pT
         this._hasMoreRows = false;
         return [];
     }
-}
+};
 
 /**
  * @return {boolean} whether there are rows left for paging
  */
-SqlBuilder.prototype.hasMoreRows = function ()
+SqlBuilder.prototype.hasMoreRows = function()
 {
     return this._hasMoreRows;
-}
+};
 
 /**
  * Executes the SQL with paging and executes the given callback-function for every resultset until the last row has been reached or the function
  * returns false.
  * 
- * @param {Function} pCallBackFn CallBack-Function to execute for every page. If the function returns false, the execution will be stopped.
- * @param {boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ * @param {Function} pCallBackFn - CallBack-Function to execute for every page. If the function returns false, the execution will be stopped.
+ * @param {boolean} [pExecuteOnlyIfConditionExists=false] - if true and there is no condition, [] is returned
+ * @param {number} [pTimeout=-1] - Specifies the period, in milliseconds, after which the query will be aborted.
  *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
  *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  */
-SqlBuilder.prototype.forEachPage = function (pCallBackFn, pExecuteOnlyIfConditionExists, pTimeout)
+SqlBuilder.prototype.forEachPage = function(pCallBackFn, pExecuteOnlyIfConditionExists, pTimeout)
 {
     if (typeof pCallBackFn !== "function")
+    {
         throw SqlBuilder._ERROR_NOT_A_FUNCTION();
+    }
     
-    var run = true;
-    var idx = 0;
+    let run = true;
+    let idx = 0;
     while (run && this.hasMoreRows())
     {
         run = pCallBackFn.call(null, this.nextTablePage(pExecuteOnlyIfConditionExists, pTimeout), idx++) != false;
     }
-}
+};
 
 /**
  * Sets an impossible where-condition, so that the query won't return any rows.
  * 
  * @return {SqlBuilder} current object
  */
-SqlBuilder.prototype.noResult = function ()
+SqlBuilder.prototype.noResult = function()
 {
-    return this.clearWhere().where(SqlBuilder.NORESULT_CONDITION());
-}
+    return this.clearWhere()
+        .where(SqlBuilder.NORESULT_CONDITION());
+};
 
 /**
  * checks if an update /delete statement should be called or not
+ *
  * @return {boolean}
- * @private
  */
 SqlBuilder.prototype._checkForUpdate = function(pExecuteOnlyIfConditionExists) 
 {
     if (pExecuteOnlyIfConditionExists === undefined)
+    {
         pExecuteOnlyIfConditionExists = true;
+    }
     
     if (typeof pExecuteOnlyIfConditionExists !== "boolean")
+    {
         throw SqlBuilder._ERROR_NOT_BOOLEAN();
+    }
     
     return !pExecuteOnlyIfConditionExists || this.hasCondition();
-}
+};
 
 /**
  * checks if a select statement should be called or not
+ *
  * @return {boolean}
- * @private
  */
 SqlBuilder.prototype._checkForSelect = function(pExecuteOnlyIfConditionExists) 
 {
     if (pExecuteOnlyIfConditionExists == undefined)
+    {
         pExecuteOnlyIfConditionExists = false;
+    }
     
     if (typeof pExecuteOnlyIfConditionExists !== "boolean")
+    {
         throw SqlBuilder._ERROR_NOT_BOOLEAN();
+    }
     
     if (this.isFullSelect())
     {
@@ -2467,13 +2786,14 @@ SqlBuilder.prototype._checkForSelect = function(pExecuteOnlyIfConditionExists)
     {
         throw SqlBuilder._ERROR_INCOMPLETE_SELECT();
     }
-}
+};
 
 /**
  * translates SqlBuilder to plain SQL. Use this if prepared statements are not supported.
  * For the db-functions (db.table, db.cell, etc.) use ".build()" as they support prepared statements.
  * It resolves all prepared values.
- * @param {string} [pAlias=undefined] the alias to use for db.translateStatement
+ *
+ * @param {string} [pAlias=undefined] - the alias to use for db.translateStatement
  * @return {string} plain SQL statement
  * 
  * @deprecated use .toString()
@@ -2481,181 +2801,195 @@ SqlBuilder.prototype._checkForSelect = function(pExecuteOnlyIfConditionExists)
 SqlBuilder.prototype.translate = function(pAlias)
 {
     return SqlUtils.translateStatementWithQuotes(this.build(), pAlias);
-}
+};
 
 /**
  * Creates an object for building a case-when statement.
  * 
- * @param {string|Array|SqlBuilder} [pFieldOrCond] If this is the only parameter, it is used as Subselect <br/>
- *                                                                     else it is used as Field. <br/>
+ * @param {string|PreparedSqlStatement|SqlBuilder} [pFieldOrCond] - If this is the only parameter, it is used as Subselect 
+ *                                                                     else it is used as Field. 
  *                                                                     Please see .where() for more information and examples.
- * @param {string|SqlBuilder|Array} [pValue] This is the value whitch is used for the condition.<br/>
- *                                                                       Basically it can be nearly everything you need.<br/>
+ * @param {string|SqlBuilder|Array} [pValue] - This is the value whitch is used for the condition.
+ *                                                                       Basically it can be nearly everything you need.
  *                                                                       Please see .where() for more information and examples.
- * @param {string} [pCondition="# = ?"] This is the condition which should be used.<br/>
- *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #<br/>
- *                               ? will be replaced by pValue<br/>
- *                               <strong>IMPORTANT: the # has to be before the ?</strong><br/>
+ * @param {string} [pCondition="# = ?"] - This is the condition which should be used.
+ *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #
+ *                               ? will be replaced by pValue
+ *                               <strong>IMPORTANT: the # has to be before the ?</strong>
  *                               Please see .where() for more information and examples.
- * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] You can specify which datatype should be used for the prepared statement<br/>
- *                                                                In most cases you don't need this.<br/>
+ * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] - You can specify which datatype should be used for the prepared statement
+ *                                                                In most cases you don't need this.
  *                                                                Please see .where() for more information and examples.
  * 
  * @return {SqlBuilder._CaseWhen}
  */
-SqlBuilder.caseWhen = function (pFieldOrCond, pValue, pCondition, pFieldType)
+SqlBuilder.caseWhen = function(pFieldOrCond, pValue, pCondition, pFieldType)
 {
-    return new SqlBuilder._CaseStatement().when(pFieldOrCond, pValue, pCondition, pFieldType);
-}
+    return new SqlBuilder._CaseStatement()
+        .when(pFieldOrCond, pValue, pCondition, pFieldType);
+};
 
 /**
  * @return {SqlBuilder._CaseStatement}
  */
-SqlBuilder.caseStatement = function ()
+SqlBuilder.caseStatement = function()
 {
     return new SqlBuilder._CaseStatement();
-}
+};
 
 /**
  * Represents a case-when statement
  */
-SqlBuilder._CaseStatement = function ()
+SqlBuilder._CaseStatement = function()
 {
     this._whenCondition = null;
     this._whenThens = [];
     this._elseValue = null;
     this._afterWhenMask = new SqlBuilder._CaseWhen(this);
-}
+};
 
 SqlBuilder.defineCanBuildSql(SqlBuilder._CaseStatement.prototype);
 
 /**
- * @param {string|Array|SqlBuilder} [pFieldOrCond] If this is the only parameter, it is used as Subselect <br/>
- *                                                                     else it is used as Field. <br/>
+ * @param {string|PreparedSqlStatement|SqlBuilder} [pFieldOrCond] - If this is the only parameter, it is used as Subselect 
+ *                                                                     else it is used as Field. 
  *                                                                     Please see .where() for more information and examples.
- * @param {string|SqlBuilder|Array} [pValue] This is the value whitch is used for the condition.<br/>
- *                                                                       Basically it can be nearly everything you need.<br/>
+ * @param {string|SqlBuilder|Array} [pValue] - This is the value whitch is used for the condition.
+ *                                                                       Basically it can be nearly everything you need.
  *                                                                       Please see .where() for more information and examples.
- * @param {string} [pCondition="# = ?"] This is the condition which should be used.<br/>
- *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #<br/>
- *                               ? will be replaced by pValue<br/>
- *                               <strong>IMPORTANT: the # has to be before the ?</strong><br/>
+ * @param {string} [pCondition="# = ?"] - This is the condition which should be used.
+ *                               # will be replaced by the field (pFieldOrCond) If pFieldOrCond is null, you can ommit #
+ *                               ? will be replaced by pValue
+ *                               <strong>IMPORTANT: the # has to be before the ?</strong>
  *                               Please see .where() for more information and examples.
- * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] You can specify which datatype should be used for the prepared statement<br/>
- *                                                                In most cases you don't need this.<br/>
+ * @param {SQLTYPES|number} [pFieldType=AutomaticallyLoadedType] - You can specify which datatype should be used for the prepared statement
+ *                                                                In most cases you don't need this.
  *                                                                Please see .where() for more information and examples.
- * @param {string} [pAlias=currentAlias] This alias is used for fetching the ColumnTypes and also for the .table, .cell, .updateData, ... -functions
  * 
  * @return {SqlBuilder._CaseWhen}
  */
-SqlBuilder._CaseStatement.prototype.when = function (pFieldOrCond, pValue, pCondition, pFieldType, pAlias)
+SqlBuilder._CaseStatement.prototype.when = function(pFieldOrCond, pValue, pCondition, pFieldType)
 {
-    this._whenCondition = newWhere(pFieldOrCond, pValue, pCondition, pFieldType, pAlias);
+    this._whenCondition = newWhere(pFieldOrCond, pValue, pCondition, pFieldType);
     return this._afterWhenMask;
-}
+};
 
 /**
  * Sets the expression used for the else-part
  * 
- * @param {string|SqlBuilder} pValue else-value
+ * @param {string|SqlBuilder} pValue - else-value
  * @return {SqlBuilder._CaseStatement}
  */
-SqlBuilder._CaseStatement.prototype.elseValue = function (pValue)
+SqlBuilder._CaseStatement.prototype.elseValue = function(pValue)
 {
+    if (SqlUtils.isPreparedSqlArray(pValue))
+    {
+        throw SqlBuilder._ERROR_SQL_ARRAY_AS_VALUE_NOT_ALLOWED();
+    }
     this._elseValue = pValue;
     return this;
-}
+};
 
 /**
  * Sets the value used for the else-part, but wraps the value in ''
  * 
- * @param {string} pValue else-value
+ * @param {string} pValue - else-value
  * @return {SqlBuilder._CaseStatement}
  */
-SqlBuilder._CaseStatement.prototype.elseString = function (pValue)
+SqlBuilder._CaseStatement.prototype.elseString = function(pValue)
 {
-    return this.elseValue("'" + pValue + "'");
-}
+    return this.elseValue("'" + db.quote(pValue, db.getCurrentAlias()) + "'");
+};
 
 /**
  * @return {string} the case-when expression
  */
-SqlBuilder._CaseStatement.prototype.toString = function (pAlias)
+SqlBuilder._CaseStatement.prototype.toString = function()
 {
-    return db.translateStatement(this.build(), pAlias || db.getCurrentAlias());
-}
+    let built = this.build();
+    
+    if (built[0] !== "")
+    {
+        return SqlUtils.translateConditionWithQuotes(built, db.getCurrentAlias());
+    }
+    
+    return "";
+};
 
-SqlBuilder._CaseStatement.prototype.build = function (pParameters)
+/**
+ * Builds a prepared sql array from the case statements
+ */
+SqlBuilder._CaseStatement.prototype.build = function()
 {
-    var caseStatement = ["case"];
-    var preparedValues = [];
-    this._whenThens.forEach(function (whenThen)
+    let caseStatement = new PreparedSqlStatement("case");
+    this._whenThens.forEach(function(whenThen)
     {
-        var when = SqlBuilder._getStatement(whenThen.condition, "when");
-        var then = SqlBuilder._getStatement(whenThen.thenValue, "then");
-        caseStatement.push(when.sqlStorage);
-        caseStatement.push(then.sqlStorage);
-        preparedValues = preparedValues.concat(when.preparedValues, then.preparedValues);
+        let when = SqlBuilder._getStatement(whenThen.condition, "when");
+        caseStatement.appendStatement(when, " ");
+        let then = SqlBuilder._getStatement(whenThen.thenValue, "then");
+        caseStatement.appendStatement(then, " ");
     });
     if (this._elseValue)
     {
         let elseStatement = SqlBuilder._getStatement(this._elseValue, "else");
-        caseStatement.push(elseStatement.sqlStorage);
-        preparedValues = preparedValues.concat(elseStatement.preparedValues);
+        caseStatement.appendStatement(elseStatement, " ");
     }
-    caseStatement.push("end");
+    caseStatement.append(" end");
     
-    return [
-        caseStatement.join(" "),
-        preparedValues
-    ];
-}
+    return caseStatement.toArray();
+};
 
 /**
  * Custom toJSON method that omits the property '_afterWhenMask', because cyclic references can't be stringified
  */
-SqlBuilder._CaseStatement.prototype.toJSON = function ()
+SqlBuilder._CaseStatement.prototype.toJSON = function()
 {
     return {
         _whenCondition: this._whenCondition,
         _whenThens: this._whenThens,
         _elseValue: this._elseValue
     };
-}
+};
 
 /**
  * Object providing the then-methods for the case-when expression. It can be only be accessed after calling .when to ensure a 'then' 
  * can only be added after a 'when'.
+ *
+ * @param {SqlBuilder._CaseStatement} pCaseStatement
  */
-SqlBuilder._CaseWhen = function (pCaseStatement)
+SqlBuilder._CaseWhen = function(pCaseStatement)
 {
     this._caseStatement = pCaseStatement;
-}
+};
 
 /**
  * Sets the expression for the then
  * 
- * @param {string|SqlBuilder} pValue then-value
+ * @param {string|SqlBuilder} pValue - then-value
  * @return {SqlBuilder._CaseStatement}
  */
-SqlBuilder._CaseWhen.prototype.then = function (pValue)
+SqlBuilder._CaseWhen.prototype.then = function(pValue)
 {
-    var condition = this._caseStatement._whenCondition;
+    if (SqlUtils.isPreparedSqlArray(pValue))
+    {
+        throw SqlBuilder._ERROR_SQL_ARRAY_AS_VALUE_NOT_ALLOWED();
+    }
+    let condition = this._caseStatement._whenCondition;
     this._caseStatement._whenCondition = null;
-    this._caseStatement._whenThens.push({condition: condition, thenValue: pValue});
+    this._caseStatement._whenThens.push({ condition: condition, thenValue: pValue });
     return this._caseStatement;
-}
+};
 
 /**
  * Sets the value for the then, but wraps the value in ''
  * 
- * @param {string} pValue then-value
+ * @param {string} pValue - then-value
  * @return {SqlBuilder._CaseStatement}
  */
-SqlBuilder._CaseWhen.prototype.thenString = function (pValue)
+SqlBuilder._CaseWhen.prototype.thenString = function(pValue)
 {
-    return this.then("'" + pValue + "'");
-}
+    return this.then("'" + db.quote(pValue, db.getCurrentAlias()) + "'");
+};
 
 /**
  *provides functions for masking sql functions
@@ -3644,6 +3978,35 @@ SqlMaskingUtils.prototype.hourFromDate = function(pField)
     }
 }
 
+/**
+ * Get the sytem db name in the format "database.schema."
+ *
+ * @param {string} [pAlias] the alias
+ *
+ * @return {string} the system db name of the alias
+ */
+SqlMaskingUtils.prototype.getSytemDbName = function(pAlias) 
+{
+    if (!pAlias)
+    {
+        pAlias = this.alias;
+    }
+    
+    var aliasModel = project.getAliasModel(pAlias);
+    var systemDbName = "";
+
+    if (aliasModel[project.ALIAS_PROPERTIES].database) 
+    {
+        systemDbName += aliasModel[project.ALIAS_PROPERTIES].database + ".";
+    }
+    if (aliasModel[project.ALIAS_PROPERTIES].schema) 
+    {
+        systemDbName += aliasModel[project.ALIAS_PROPERTIES].schema + ".";
+    }
+    
+    return systemDbName;
+}
+
 /**
  * gets the hour from a timestamp
  *
@@ -3892,34 +4255,33 @@ SqlMaskingUtils.prototype.toChar = function(pColumnName)
 }
 
 /**
- * functions for various Sql-actions
- * Do not create an instance of this!
+ * Provides functions for various sql actions
  *
- * @class
- * @static
+ * @namespace
  */
-export function SqlUtils() {}
+export function SqlUtils() 
+{}
 
 /**
-* parses given name of table and name of column to clearly find out the tablename and columnanme
-*
-* @param {string|Array} pFieldOrTableName you've got several possibilites to pass here:
-*                                   <br/> 1. the name of the table if also a pColumnName is specified 
-*                                   <br/> 2. the name of the table and columname as "tablename.columnname" (e.g. "ORGANISATION.NAME") if no pColumnName is specified
-*                                   <br/> 3. an array with 2 elements: [tablename, columnname] (e.g. ["ORGANISATION", "NAME"]) if no pColumnName is specified
-*                                   <br/> 4. an array with 3 elements: [tablename, columnname, tablealias] (e.g. ["ORGANISATION", "NAME", "org"]) if no pColumnName is specified
-*                                   <br/> Everything else will raise an error
-*                                   
-* @param {string} [pColumnName] depending on pFieldOrTableName this should be undefined/null or the name of a column
-*
-* @return {Object|TypeError} TypeError if something wrong has been passed or returns a object with these properties: 
-*                           1. "table" which is the tablename
-*                           2. "column" which is the columnname
-*                           3. "tableAlias" which is the tableAlias if it exists. else it is also the table
-*                           e.g. {table: "ORGANISATION", column: "NAME", tableAlias: "org"}
-* 
-*
-*/
+ * Parses given name of table and name of column to clearly find out the tablename and columnanme
+ *
+ * @param {string|Array} pFieldOrTableName - You've got several possibilites to pass here:
+ *                                   <br/> 1. the name of the table if also a pColumnName is specified 
+ *                                   <br/> 2. the name of the table and columname as "tablename.columnname" (e.g. "ORGANISATION.NAME") if no pColumnName is specified
+ *                                   <br/> 3. an array with 2 elements: [tablename, columnname] (e.g. ["ORGANISATION", "NAME"]) if no pColumnName is specified
+ *                                   <br/> 4. an array with 3 elements: [tablename, columnname, tablealias] (e.g. ["ORGANISATION", "NAME", "org"]) if no pColumnName is specified
+ *                                   <br/> Everything else will raise an error
+ *                                   
+ * @param {string} [pColumnName] - Depending on pFieldOrTableName this should be undefined/null or the name of a column
+ *
+ * @return {object | TypeError} TypeError if something wrong has been passed or returns a object with these properties: 
+ *                           1. "table" which is the tablename
+ *                           2. "column" which is the columnname
+ *                           3. "tableAlias" which is the tableAlias if it exists. else it is also the table
+ *                           e.g. {table: "ORGANISATION", column: "NAME", tableAlias: "org"}
+ * 
+ *
+ */
 SqlUtils._parseFieldQualifier = function(pFieldOrTableName, pColumnName) 
 {
     var fnName = "SqlUtils._parseFieldQualifier";//for return errors
@@ -3927,10 +4289,12 @@ SqlUtils._parseFieldQualifier = function(pFieldOrTableName, pColumnName)
     if (typeof pFieldOrTableName == "string")
     {
         if (pFieldOrTableName.search(/[\s=\(\)<>!]/) != -1)
+        {
             return new TypeError(translate.withArguments("[%0]%1 has to be a string without empty spaces, (, ), =, <, >  but it contains at least one of them", [fnName, "pFieldOrTableName"]));
+        }
     }
     
-    var tableName, columnName, tableAlias;
+    let tableName, columnName, tableAlias;
     if (pColumnName != undefined)
     {
         tableName = pFieldOrTableName;
@@ -3938,8 +4302,8 @@ SqlUtils._parseFieldQualifier = function(pFieldOrTableName, pColumnName)
     }
     else
     {
-        var fieldVarType = typeof(pFieldOrTableName);
-        if (fieldVarType == "string") 
+        let fieldVarType = typeof(pFieldOrTableName);
+        if (typeof pFieldOrTableName == "string") 
         {
             pFieldOrTableName = text.split(pFieldOrTableName, "\\.");
         }
@@ -3964,23 +4328,34 @@ SqlUtils._parseFieldQualifier = function(pFieldOrTableName, pColumnName)
             }
             else
             {
-                return new TypeError(translate.withArguments("[%0]has now an incorrect length; estimated 2 or 3 elements but got %1", [fnName, pFieldOrTableName.length ]));
+                return new TypeError(translate.withArguments("[%0]has now an incorrect length; estimated 2 or 3 elements but got %1", [fnName, pFieldOrTableName.length.toString()]));
             }            
         }
         else //check for object happens since there exists JavaArrays and JavaScript arrays which are both valid
+        {
             return  new TypeError(translate.withArguments("[%0]%1 is an object but seems not to be a valid array or array-like", [
-                    fnName, "pFieldOrTableName"]));
+                fnName, "pFieldOrTableName"
+            ]));
+        }
     }
 
     if (!tableAlias)
+    {
         tableAlias = tableName;
+    }
 
     if (typeof(columnName) != "string")
+    {
         return  new TypeError(translate.withArguments("[%0]the columnName is not a string after interpreting", [fnName]));
+    }
     if (typeof(tableName) != "string")
+    {
         return  new TypeError(translate.withArguments("[%0]the tableName is not a string after interpreting", [fnName]));
+    }
     if (typeof(tableAlias) != "string")
+    {
         return  new TypeError(translate.withArguments("[%0]the tableAlias is not a string after interpreting", [fnName]));
+    }
 
     return {
         table: tableName,
@@ -3990,186 +4365,167 @@ SqlUtils._parseFieldQualifier = function(pFieldOrTableName, pColumnName)
 };
 
 /**
-* determines if given values match a full field qualifier (name of table and name of column)
-*
-* @param {string|Array} pFieldOrTableName you've got several possibilites to pass here:
-*                                   <br/> 1. the name of the table if also a pColumnName is specified 
-*                                   <br/> 2. the name of the table and columname as "tablename.columnname" (e.g. "ORGANISATION.NAME") if no pColumnName is specified
-*                                   <br/> 3. an array with 2 elements: [tablename, columnname] (e.g. ["ORGANISATION", "NAME"]) if no pColumnName is specified
-*                                   <br/> 4. an array with 3 elements: [tablename, columnname, tablealias] (e.g. ["ORGANISATION", "NAME", "org"]) if no pColumnName is specified
-*                                   <br/> Everything else will raise an error
-*                                   
-* @param {string} [pColumnName] depending on pFieldOrTableName this should be undefined/null or the name of a column
-*
-* @return {boolean} returns true if it's a full qualifier or false if not
-*
-*/
+ * Determines if given values match a full field qualifier (name of table and name of column)
+ *
+ * @param {string|Array} pFieldOrTableName - You've got several possibilites to pass here:
+ *                                   <br/> 1. the name of the table if also a pColumnName is specified 
+ *                                   <br/> 2. the name of the table and columname as "tablename.columnname" (e.g. "ORGANISATION.NAME") if no pColumnName is specified
+ *                                   <br/> 3. an array with 2 elements: [tablename, columnname] (e.g. ["ORGANISATION", "NAME"]) if no pColumnName is specified
+ *                                   <br/> 4. an array with 3 elements: [tablename, columnname, tablealias] (e.g. ["ORGANISATION", "NAME", "org"]) if no pColumnName is specified
+ *                                   <br/> Everything else will raise an error
+ *                                   
+ * @param {string} [pColumnName] - Depending on pFieldOrTableName this should be undefined/null or the name of a column
+ *
+ * @return {boolean} True if it's a full qualifier or false if not
+ *
+ */
 SqlUtils.isFullFieldQualifier = function(pFieldOrTableName, pColumnName)
 {
-    var parsed = SqlUtils._parseFieldQualifier(pFieldOrTableName, pColumnName);
+    let parsed = SqlUtils._parseFieldQualifier(pFieldOrTableName, pColumnName);
     return !(parsed instanceof TypeError);
 };
 
 /**
  * Checks if the given value has the correct format for a prepared sql array
  * 
- * @param {Object|Array} pPreparedArray     value to check
- * @return {boolean} if the format is correct
+ * @param {object | Array} pPreparedArray - Value to check
+ * @return {pPreparedArray is [string, Array]} If the format is correct
  */
-SqlUtils.isPreparedSqlArray = function (pPreparedArray)
+SqlUtils.isPreparedSqlArray = function(pPreparedArray)
 {
-    return pPreparedArray.length === 2 && Utils.isString(pPreparedArray[0]) && Array.isArray(pPreparedArray[1]);
-}
+    return Array.isArray(pPreparedArray) && pPreparedArray.length === 2 && Utils.isString(pPreparedArray[0]) && Array.isArray(pPreparedArray[1]);
+};
 
 /**
  * Checks if the given value has the correct format for a prepared sql array and contains something
  * 
- * @param {Object|Array} pPreparedArray     value to check
- * @return {boolean} if the format is correct
+ * @param {object | Array} pPreparedArray - Value to check
+ * @return {pPreparedArray is [string, Array]} If the format is correct
  */
-SqlUtils.isNonEmptyPreparedSqlArray = function (pPreparedArray)
+SqlUtils.isNonEmptyPreparedSqlArray = function(pPreparedArray)
 {
     return SqlUtils.isPreparedSqlArray(pPreparedArray) && pPreparedArray[0] != "";
-}
+};
 
 /**
-* determines the type of a single database column in a table; if you want to  get several columntypes at once use db.getColumnTypes instead 
-*
-* @param {string|Array} pFieldOrTableName you've got several possibilites to pass here:
-*                                   <br/> 1. the name of the table if also a pColumnName is specified 
-*                                   <br/> 2. the name of the table and columname as "tablename.columnname" (e.g. "ORGANISATION.NAME") if no pColumnName is specified
-*                                   <br/> 3. an array with 2 elements: [tablename, columnname] (e.g. ["ORGANISATION", "NAME"]) if no pColumnName is specified
-*                                   <br/> 4. an array with 3 elements: [tablename, columnname, tablealias] (e.g. ["ORGANISATION", "NAME", "org"]) if no pColumnName is specified
-*                                   <br/> Everything else will raise an error
-*                                   
-* @param {string} [pColumnName] depending on pFieldOrTableName this should be undefined/null or the name of a column
-* @param {string} [pAlias=the current alias] Database-Aliasname, where the SQL-Statement shall be executed; default is the current dbalias
-*
-* @throws TypeError if a wrong format is passed as table/column-combination
-*
-* @return {number} returns the corresponding SQLTYPES-value
-*
-*/
+ * Determines the type of a single database column in a table; if you want to  get several columntypes at once use db.getColumnTypes instead 
+ *
+ * @param {string|Array} pFieldOrTableName - You've got several possibilites to pass here:
+ *                                   <br/> 1. the name of the table if also a pColumnName is specified 
+ *                                   <br/> 2. the name of the table and columname as "tablename.columnname" (e.g. "ORGANISATION.NAME") if no pColumnName is specified
+ *                                   <br/> 3. an array with 2 elements: [tablename, columnname] (e.g. ["ORGANISATION", "NAME"]) if no pColumnName is specified
+ *                                   <br/> 4. an array with 3 elements: [tablename, columnname, tablealias] (e.g. ["ORGANISATION", "NAME", "org"]) if no pColumnName is specified
+ *                                   <br/> Everything else will raise an error
+ *                                   
+ * @param {string} [pColumnName] - Depending on pFieldOrTableName this should be undefined/null or the name of a column
+ * @param {string} [pAlias=currentalias] - Database alias name, where the SQL-Statement shall be executed; default is the current dbalias
+ * @return {number} returns the corresponding SQLTYPES-value
+ *
+ * @throws TypeError if a wrong format is passed as table/column-combination
+ */
 SqlUtils.getSingleColumnType = function(pFieldOrTableName, pColumnName, pAlias) 
 {
-    var fields = SqlUtils._parseFieldQualifier(pFieldOrTableName, pColumnName);
+    let fields = SqlUtils._parseFieldQualifier(pFieldOrTableName, pColumnName);
     if (fields instanceof TypeError)
+    {
         throw fields;
+    }
     
     if (pAlias == undefined)
+    {
         pAlias = db.getCurrentAlias();
+    }
 
     return db.getColumnTypes(fields.table, [fields.column], pAlias)[0];
 };
 
 /**
-* calls a given function for N blocks of sql-data as long as records are available or the paging-process is manually canceled
-*
-* @param {Object|string} sqlStatement the sql statement that shall be executed
-*                                 String: SQL-query in a simple text form
-*                                 Object: prepared-sql-query: [sqlStr, [[value1, type1], [valueN, typeN]]]
-* @param {number} blockSize Amount of records that shall be read per block. (you need to specify an ORDER BY in your SQL-query)
-*                                "0" <=> all records
-* @param {Function} callbackFn a callback-function that is called for every block and has the following params:
-*                                            myCallback(myDataBlockAs2Darray, myLoopCountThatStartsWith1)
-*                                          If "false" is returned sqlPageData will abort the paging process and return false
-* @param {string} [dbAlias=current_alias] Database-Aliasname, where the SQL-Statement shall be executed; default is the current dbalias
-* @param {number} [timeout=configured_dbTimeout_in_Preferences] Timeout in milliseconds; When it's reached the SQL-Statement will abort; default is in PREFERENCES configured
-* @param {number} [startOffset=0] Position where to begin with  the data-reading-process; default is 0
-*
-*
-* @return {boolean} returns whether the function read all available data or not:
-*                        false if the callback-function returned false, otherwise true
-*
-* @example
-* var varValues = [];//you've got access to variables declared with 'var'
-* let letValues = [];//you've got access to variables declared with 'let'
-* var count = 0;//you cannot overwrite a variable of 'sqlPageData' by accident
-*
-* var sql = "select ORGNAME from ORGANISATION";
-* var blockSize = 5 * 1000;
-*
-* var allRows = +db.cell("select count(*) from ORGANISATION");
-*
-* sqlPageData(sql, blockSize, function(pData, pRunNo){
-*     var j = pData.length;//pData is the current block with data
-*     logMsg(pRunNo.toString() + "#" + j);//pRunNo is the amount how often the func. has been already called
-*     //you can calculate the progress easily by: progress = (blockSize* (pRunNo-1) + pData.length) / (allRows - startOffset)
-*     //example in per cent:
-*     var startOffset = 0;//we did not pass any startOffset to sqlPageData - this is equivalent to zero
-*     var progress = (blockSize* (pRunNo-1) + pData.length) / (allRows - startOffset);
-*     logMsg("progess: " + eMath.roundDec(progress * 100, 2, eMath.ROUND_CEILING) + "%");
-*
-*     for (var i = 0; i < j; i++)
-*     {
-*         varValues.push(pData[i][0]);
-*         letValues.push(pData[i][0]);
-*     }
-*
-*     count += pRunNo * 100;
-*     logMsg("count:" + count);//you cannot overwrite a variable of 'sqlPageData' by accident
-* });
-*
-* logging.show(letValues);//contains orgnames
-* logging.show(varValues);//contains orgnames
-*/
-SqlUtils.pageTableData = function(sqlStatement, blockSize, callbackFn, dbAlias, timeout, startOffset) 
+ * Calls a given function for N blocks of sql-data as long as records are available or the paging-process is manually canceled
+ *
+ * @param {object | string} pSqlStatement - The sql statement that shall be executed
+ *                                 String: SQL-query in a simple text form
+ *                                 Object: prepared-sql-query: [sqlStr, [[value1, type1], [valueN, typeN]]]
+ * @param {number} pBlockSize - Amount of records that shall be read per block. (you need to specify an ORDER BY in your SQL-query)
+ *                                "0" <=> all records
+ * @param {Function} pCallbackFn - A callback-function that is called for every block and has the following params:
+ *                                            myCallback(myDataBlockAs2Darray, myLoopCountThatStartsWith1)
+ *                                          If "false" is returned sqlPageData will abort the paging process and return false
+ * @param {string} [pDbAlias=current_alias] - Database-Aliasname, where the SQL-Statement shall be executed; default is the current dbalias
+ * @param {number} [pTimeout=configured_dbTimeout_in_Preferences] - Timeout in milliseconds; When it's reached the SQL-Statement will abort; default is in PREFERENCES configured
+ * @param {number} [pStartOffset=0] - Position where to begin with  the data-reading-process; default is 0
+ *
+ *
+ * @return {boolean} Whether the function read all available data or not:
+ *                        false if the callback-function returned false, otherwise true
+ */
+SqlUtils.pageTableData = function(pSqlStatement, pBlockSize, pCallbackFn, pDbAlias, pTimeout, pStartOffset) 
 {
-    return SqlUtils._pageData(null, sqlStatement, blockSize, callbackFn, dbAlias, timeout, startOffset);
+    return SqlUtils._pageData(null, pSqlStatement, pBlockSize, pCallbackFn, pDbAlias, pTimeout, pStartOffset);
 };
 
 /**
-* calls a given function for N blocks of sql-data as long as records are available or the paging-process is manually canceled
-*
-* @param {Object|string} sqlStatement the sql statement that shall be executed
-*                                 String: SQL-query in a simple text form
-*                                 Object: prepared-sql-query: [sqlStr, [[value1, type1], [valueN, typeN]]]
-* @param {number} blockSize Amount of records that shall be read per block. (you need to specify an ORDER BY in your SQL-query)
-*                                "0" <=> all records
-* @param {Function} callbackFn a callback-function that is called for every block and has the following params:
-*                                            myCallback(myColumnDataBlockAsArray, myLoopCountThatStartsWith1)
-*                                          If "false" is returned sqlPageData will abort the paging process and return false
-* @param {string} [dbAlias=current_alias] Database-Aliasname, where the SQL-Statement shall be executed; default is the current dbalias
-* @param {number} [timeout=configured_dbTimeout_in_Preferences] Timeout in milliseconds; When it's reached the SQL-Statement will abort; default is in PREFERENCES configured
-* @param {number} [startOffset=0] Position where to begin with  the data-reading-process; default is 0
-*
-*
-* @return {boolean} returns whether the function read all available data or not:
-*                        false if the callback-function returned false, otherwise true
-*
-* @example
-* similar to sqlTablePageData -> take a look at the example there
-*/
-SqlUtils.pageColumnData = function(sqlStatement, blockSize, callbackFn, dbAlias, timeout, startOffset) 
+ * Calls a given function for N blocks of sql-data as long as records are available or the paging-process is manually canceled
+ *
+ * @param {object | string} pSqlStatement - The sql statement that shall be executed
+ *                                 String: SQL-query in a simple text form
+ *                                 Object: prepared-sql-query: [sqlStr, [[value1, type1], [valueN, typeN]]]
+ * @param {number} pBlockSize - Amount of records that shall be read per block. (you need to specify an ORDER BY in your SQL-query)
+ *                                "0" <=> all records
+ * @param {Function} pCallbackFn - A callback-function that is called for every block and has the following params:
+ *                                            myCallback(myColumnDataBlockAsArray, myLoopCountThatStartsWith1)
+ *                                          If "false" is returned sqlPageData will abort the paging process and return false
+ * @param {string} [pDbAlias=current_alias] - Database-Aliasname, where the SQL-Statement shall be executed; default is the current dbalias
+ * @param {number} [pTimeout=configured_dbTimeout_in_Preferences] - Timeout in milliseconds; When it's reached the SQL-Statement will abort; default is in PREFERENCES configured
+ * @param {number} [pStartOffset=0] - Position where to begin with  the data-reading-process; default is 0
+ * @return {boolean} Whether the function read all available data or not:
+ *                        false if the callback-function returned false, otherwise true
+ *
+ * @see SqlUtils.pageTableData
+ */
+SqlUtils.pageColumnData = function(pSqlStatement, pBlockSize, pCallbackFn, pDbAlias, pTimeout, pStartOffset) 
 {
-    return SqlUtils._pageData(db.COLUMN, sqlStatement, blockSize, callbackFn, dbAlias, timeout, startOffset);
+    return SqlUtils._pageData(db.COLUMN, pSqlStatement, pBlockSize, pCallbackFn, pDbAlias, pTimeout, pStartOffset);
 };
 
-//internal function for paging through data; for description take a look at sqlArrayPageData
-SqlUtils._pageData = function(sqlType ,sqlStatement, blockSize, callbackFn, dbAlias, timeout, startOffset) 
+/**
+ * internal function for paging through data; for description take a look at sqlArrayPageData
+ */
+SqlUtils._pageData = function(sqlType, sqlStatement, blockSize, callbackFn, dbAlias, timeout, startOffset) 
 {
     if (dbAlias == undefined)
+    {
         dbAlias = db.getCurrentAlias();
+    }
     if (startOffset == undefined)
+    {
         startOffset = 0;
+    }
 
-    var count = 0;
+    let count = 0;
     while (startOffset > -1) 
     {
-        var data;
+        let data;
         if (sqlType == null) 
         {
             if (timeout == undefined)
+            {
                 data = db.tablePage(sqlStatement, dbAlias, startOffset, blockSize);
+            }
             else
+            {
                 data = db.tablePage(sqlStatement, dbAlias, startOffset, blockSize, timeout);
+            }
         }
         else 
         {
             if (timeout == undefined)
+            {
                 data = db.arrayPage(sqlType, sqlStatement, dbAlias, startOffset, blockSize);
+            }
             else
+            {
                 data = db.arrayPage(sqlType, sqlStatement, dbAlias, startOffset, blockSize, timeout);
+            }
         }
 
         startOffset += blockSize;
@@ -4177,158 +4533,193 @@ SqlUtils._pageData = function(sqlType ,sqlStatement, blockSize, callbackFn, dbAl
         //this happens when all-records % blockSize == 0
         //we do not want to call the callback-fn
         if (data.length == 0)
+        {
             return true;
+        }
         else if (data.length < blockSize || blockSize == 0)//blocksize 0 is everything
-            startOffset = -1;//call callback the last time
+        {
+            startOffset = -1;
+        }//call callback the last time
 
         if (callbackFn.call(this, data, ++count) === false)
-            return false;//callback can return false to manually stop the paging-process
+        {
+            return false;
+        }//callback can return false to manually stop the paging-process
     }
     return true;
-}
+};
 
 /**
- *  @return the alias for table asys_binaries
+ * @return {string} The alias for table asys_binaries
  */
 SqlUtils.getBinariesAlias = function()
 {
     return SqlUtils.getSystemAlias();
-}
+};
 
 /**
- *  @return the sytemalias
+ * @return {string} The sytem alias
  */
 SqlUtils.getSystemAlias = function()
 {
     return "_____SYSTEMALIAS";
-}
+};
 
 /**
- *  @return the dataalias
+ * @return {string} The data alias
  */
 SqlUtils.getDataAlias = function()
 {
     return "Data_alias";
-}
+};
 
 /**
-     * Builds a SQL IN condition, while accounting for the 1000 elements maximum
-     * Single conditions are concatenated with OR, which can be devastating for performance!
-     *
-     * @param {string} pFieldname req name of the field with table alias
-     *                                z.B ORGREL.CONTACTID
-     * @param {string[]|string[][]} pData req Data as ID Array
-     * @param {string} [pQuoteSymbol=""] symbol for quoting values,
-     *                                  Strings i.e.: ' default is no symbol
-     * @param {boolean} [pAsPrepared=undefined] true if result should be returned as prepared condition     
-     * @param {boolean} [pPreparedDbType=undefined] if pAsPrepared is true, this param has to be filld with the correct db type
-     *
-     * @return {string|Array} SQL condition: where VALS in (1,2,3) OR as prepared Statement if pAsPrepared is true ["VALS in (1,2,3)", [...]
-     */
+ * Builds a SQL IN condition, while accounting for the 1000 elements maximum.
+ * Single conditions are concatenated with OR, which can be devastating for performance!
+ *
+ * @param {string} pFieldname - Name of the field with table alias
+ *                                z.B ORGREL.CONTACTID
+ * @param {string[]|string[][]} pData - Data as ID Array
+ * @param {string} [pQuoteSymbol=""] - symbol for quoting values,
+ *                                  Strings i.e.: ' default is no symbol
+ * @param {boolean} [pAsPrepared=undefined] - True if result should be returned as prepared condition     
+ * @param {number} [pPreparedDbType=undefined] - If pAsPrepared is true, this param has to be filld with the correct db type
+ *
+ * @return {string|Array} SQL condition: where VALS in (1,2,3) OR as prepared Statement if pAsPrepared is true ["VALS in (1,2,3)", [...]
+ */
 SqlUtils.getSqlInStatement = function(pFieldname, pData, pQuoteSymbol, pAsPrepared, pPreparedDbType) 
 {
-    var MAX_COUNT = 1000;
+    const MAX_COUNT = 1000;
     if (pData.length > 1000)
-        logging.log(translate.text("SqlUtils.getSqlInStatement: WARNING: You should not create in-statements with more than 1000 values. As this has a very bad performance."))
+    {
+        logging.log(translate.text("SqlUtils.getSqlInStatement: WARNING: You should not create in-statements with more than 1000 values. As this has a very bad performance."));
+    }
     
     if (pData.length == 0)
+    {
         return " 1 = 2 ";
+    }
 
-    var res = "";
-    var qs = pQuoteSymbol || "";
+    let res = "";
+    let qs = pQuoteSymbol || "";
     
-    var preparedValues;
+    let preparedValues;
     if (pAsPrepared)
     {
         preparedValues = [];
         if (!pPreparedDbType)
+        {
             throw new Error(translate.text("SqlUtils.getSqlInStatement: if pAsPrepared is true, pPreparedDbType has to be filld with the correct db type"));
+        }
     }
 
     //pData.length -1 um für den Fall, dass MAX_COUNT == pData.length ist trotzdem nur einen Aufruf
     //zu machen
-    var count = ((pData.length -1) / MAX_COUNT) >> 0;//aus kommazahl eine ganzzahl machen
+    let count = ((pData.length - 1) / MAX_COUNT) >> 0;//aus kommazahl eine ganzzahl machen
     //<= verwenden, da bei einer Länge von "126" der Vorgang einmal ausgeführt werden soll
-    for (var i = 0; i <= count; i++)
+    for (let i = 0; i <= count; i++)
     {
         if (i > 0)
+        {
             res += " or ";
+        }
         
         if (pAsPrepared) 
         {
             res += (pFieldname ? pFieldname + " in " : "") + "(";
-            var subData = pData.slice(i * MAX_COUNT, i * MAX_COUNT + MAX_COUNT);
+            let subData = pData.slice(i * MAX_COUNT, i * MAX_COUNT + MAX_COUNT);
             
-            subData.forEach(function(pVal, pIndex) {
+            subData.forEach(function(pVal, pIndex) 
+            {
                 res += "?";
-                preparedValues.push([pVal, pPreparedDbType])
-                if (pIndex != subData.length-1)
+                preparedValues.push([pVal, pPreparedDbType]);
+                if (pIndex != subData.length - 1)
+                {
                     res += ", ";
+                }
             });
-            res += ")"
+            res += ")";
         }
         else
         {
             res += (pFieldname ? pFieldname + " in " : "") + "(" + qs + pData.slice(i * MAX_COUNT, i * MAX_COUNT + MAX_COUNT)
-                    .join(qs + ", " + qs) + qs + ") ";
+                .join(qs + ", " + qs) + qs + ") ";
         }
     }
 
     //wenn mehrere Zeilen mit "or" verknüpft wurden nochmal klammern
     if (count > 0)
+    {
         res = "(" + res + ")";
+    }
 
     if (pAsPrepared)
+    {
         return [res, preparedValues];
+    }
     else
+    {
         return res;
-}
+    }
+};
 
 /**
-* resolves key-value pairs (of strings) into a case when expression; 
-* This function tries to get the columntype for better type comparison
-* 
-* @param {string[][]} pKeyValueArray you've to pass a 2D-Array where each element has at pos0 the key and pos1 the value
-* @param {string} pDbFieldName name fo the database field where the KEY-value is stored; prefers TABLENAME.COLUMNNAME
-* @param {string|boolean} [pLocale=current_client_language] specifies the locale for translating the title; can be false if nothing shalle be translated
-* @param {boolean} [pIsCurrency]
-* @param {string} [pAlias=currentAlias] db alias
-* 
-* @return {string} a SQL-expression (case-when-statement) that resolves the KEYID into the title -> as preparedSatement-elements
-*/
+ * Resolves key-value pairs (of strings) into a case when expression; 
+ * This function tries to get the columntype for better type comparison
+ * 
+ * @param {string[][]} pKeyValueArray - You have to pass a 2D-Array where each element has at pos0 the key and pos1 the value
+ * @param {string} pDbFieldName - Name fo the database field where the KEY-value is stored; prefers TABLENAME.COLUMNNAME
+ * @param {string|boolean} [pLocale=current_client_language] - Specifies the locale for translating the title; can be false if nothing shalle be translated
+ * @param {boolean} [pIsCurrency]
+ * @param {string} [pAlias=currentAlias] - Db alias
+ * @return {[string, [string, number][]]} SQL-expression (case-when-statement) that resolves the KEYID into the title -> as preparedSatement-elements
+ */
 SqlUtils.getResolvingCaseWhen = function(pKeyValueArray, pDbFieldName, pLocale, pIsCurrency, pAlias) 
 {
-    var keyData = pKeyValueArray;
+    let keyData = pKeyValueArray;
     if (keyData.length == 0)
+    {
         return  ["''", []];
+    }
     
     //a helper function for easy translation
-    var translateValue = function(value){
+    let translateValue = function(value)
+    {
         if (pLocale === false)
+        {
             return value;
+        }
         else if (pLocale)
+        {
             return translate.text(value, pLocale);
+        }
         else
+        {
             return translate.text(value);
+        }
     };
     //!SqlBuilder
-    var resSql = "case ", preparedValues = [];
+    let resSql = "case ";
+    /** @type {[string, number][]} */
+    let preparedValues = [];
     
-    var colTypeKeyId = SQLTYPES.CHAR; //the standard type is char
-    var fields = SqlUtils._parseFieldQualifier(pDbFieldName); //validate the DB-field for proper form (CONTACT.CONTACTID)
+    let colTypeKeyId = SQLTYPES.CHAR; //the standard type is char
+    let fields = SqlUtils._parseFieldQualifier(pDbFieldName); //validate the DB-field for proper form (CONTACT.CONTACTID)
     if (!(fields instanceof TypeError))
+    {
         colTypeKeyId = SqlUtils.getSingleColumnType(pDbFieldName, undefined, pAlias); 
-     //some databases dont auto cast on their own so we need the proper type
+    } 
+    //some databases dont auto cast on their own so we need the proper type
     
-    var colTypeTitle = SQLTYPES.NVARCHAR;
-    for (var i = 0, l = keyData.length; i < l; i++) 
+    let colTypeTitle = SQLTYPES.NVARCHAR;
+    for (let i = 0, l = keyData.length; i < l; i++) 
     {
-        var translatedTitle;
+        let translatedTitle;
         if(pIsCurrency)
         {
-            var titleWithiso = keyData[i][1]; //Euro (EUR) (iso ALWAYS has a length of 3 + the columns and one space)
-            var title = titleWithiso.substring(0, titleWithiso.length - 6);
-            var iso = titleWithiso.substring(titleWithiso.length - 6, titleWithiso.length);
+            let titleWithiso = keyData[i][1]; //Euro (EUR) (iso ALWAYS has a length of 3 + the columns and one space)
+            let title = titleWithiso.substring(0, titleWithiso.length - 6);
+            let iso = titleWithiso.substring(titleWithiso.length - 6, titleWithiso.length);
             translatedTitle = translateValue(title) + iso;
         }
         else
@@ -4336,89 +4727,93 @@ SqlUtils.getResolvingCaseWhen = function(pKeyValueArray, pDbFieldName, pLocale,
             translatedTitle = translateValue(keyData[i][1]);
         }
         
-        resSql += " when " + pDbFieldName + " = ? then ? "
+        resSql += " when " + pDbFieldName + " = ? then ? ";
         preparedValues.push([keyData[i][0], colTypeKeyId]);
         preparedValues.push([translatedTitle, colTypeTitle]);
     }
     resSql += " else '' end ";
-    resSql = [resSql, preparedValues];
-    return resSql;
+    return [resSql, preparedValues];
 };
 
 /**
-* resolves an array of key-value pairs (of strings) into a sql case when expression<br/>
-* This is useful for results of entities.getRows for example.
-* 
-* @param {Array} pKeyValueObject    <p/>you've to pass a 2D-Array where each element has to be an object with at least one key: value-pair, e.g.: 
-*                                   <br/>[{uid: "uid1", value: "value1"}, {uid: "uidN", value: "valueN"}]
-* @param {string} pUid              <p/>name of the key where the rawvalue (the uid) is located in the object
-* @param {string} pTranslatedValue  <p/>name of the key where the already translated value is located in the object
-* @param {string} pDbFieldName      <p/>name fo the database field where the KEY-value is stored
-* 
-* @return {string}                  <p/>a SQL-expression (case-when-statement) that resolves the KEYID into the title -> as 
-*                                       preparedSatement-elements
-*                                   <br/>The else-value is "unassigned".
-* 
-* @example
-* var exampleDataStack = [
-*       {keyVal: "PHONE", titleOriginal: "Phone", titleTranslated: "Telefon", origin: "MetaImporter"},
-*       {keyVal: "EMAIL", titleOriginal: "email", titleTranslated: "E-Mail", origin: "MetaImporter"}
-* ];
-* 
-* var sqlExpr = SqlUtils.getResolvingCaseWhenFromObject(exampleDataStack, "keyVal", "titleTranslated", "FORM.COMMUNICATION");
-* //results in a sql case when as prepared statement that is resolvedas following: 
-* //case  when FORM.COMMUNICATION = 'PHONE'  then 'Telefon'   when FORM.COMMUNICATION = 'EMAIL'  then 'E-Mail'   else 'nicht zugeordnet' end
-*/
+ * Resolves an array of key-value pairs (of strings) into a sql case when expression.
+ * This is useful for results of entities.getRows for example.
+ * 
+ * @param {Array} pKeyValueObject - You have to pass a 2D-Array where each element has to be an object with at least one key: value-pair, e.g.: 
+ *                                  [{uid: "uid1", value: "value1"}, {uid: "uidN", value: "valueN"}]
+ * @param {string} pUid - Name of the key where the rawvalue (the uid) is located in the object
+ * @param {string} pTranslatedValue - Name of the key where the already translated value is located in the object
+ * @param {string} pDbFieldName - Name fo the database field where the KEY-value is stored
+ * @return {[string, [string, number][]]} SQL-expression (case-when-statement) that resolves the KEYID into the title -> as preparedSatement-elements.
+ *                                   The else-value is "unassigned".
+ * 
+ * @example
+ * let exampleDataStack = [
+ *       {keyVal: "PHONE", titleOriginal: "Phone", titleTranslated: "Telefon", origin: "MetaImporter"},
+ *       {keyVal: "EMAIL", titleOriginal: "email", titleTranslated: "E-Mail", origin: "MetaImporter"}
+ * ];
+ * 
+ * let sqlExpr = SqlUtils.getResolvingCaseWhenFromObject(exampleDataStack, "keyVal", "titleTranslated", "FORM.COMMUNICATION");
+ * //results in a sql case when as prepared statement that is resolvedas following: 
+ * //case  when FORM.COMMUNICATION = 'PHONE'  then 'Telefon'   when FORM.COMMUNICATION = 'EMAIL'  then 'E-Mail'   else 'nicht zugeordnet' end
+ */
 SqlUtils.getResolvingCaseWhenFromObject = function(pKeyValueObject, pUid, pTranslatedValue, pDbFieldName) 
 {
-    var keyData = pKeyValueObject;
+    let keyData = pKeyValueObject;
     if (keyData.length == 0)
+    {
         return  ["''", []];
+    }
     
-    var translateValue = pTranslatedValue;
-    var uid = pUid;
-    var unassigned = translate.text("unassigned")
+    let translateValue = pTranslatedValue;
+    let unassigned = translate.text("unassigned");
     
-    var resSql = "case ", preparedValues = [];
-    var colTypeKeyId = SQLTYPES.CHAR;
-    var colTypeTitle = SQLTYPES.NVARCHAR;
-    for (var i = 0, l = keyData.length; i < l; i++) 
+    let resSql = "case ";
+    /** @type {[string, number][]} */
+    let preparedValues = [];
+    let colTypeKeyId = SQLTYPES.CHAR;
+    let colTypeTitle = SQLTYPES.NVARCHAR;
+    for (let i = 0, l = keyData.length; i < l; i++) 
     {
-        var translatedTitle = keyData[i][translateValue];
-        resSql += " when " + pDbFieldName + " = ? then ? "
+        let translatedTitle = keyData[i][translateValue];
+        resSql += " when " + pDbFieldName + " = ? then ? ";
         preparedValues.push([keyData[i][pUid], colTypeKeyId]);
         preparedValues.push([translatedTitle, colTypeTitle]);
-
     }
-    resSql += " else '"+ unassigned +"' end ";
-    resSql = [resSql, preparedValues];
-    return resSql;
+    resSql += " else '" + unassigned + "' end ";
+    return [resSql, preparedValues];
 };
 
 /**
  * Will quote all prepared statement values from the given statement.
  * 
- * @param {Array} pStatement Same as first paraemter of db.translateStatement.
- * @param {string} pAlias The database alias
- * @param {Function} pExecutionCallback (PreparedSqlArray) => String A function which must return the final SQL.
- * @return The SQL, same as the result of db.translateStatement.
+ * @param {[string, Array]} pStatement - Same as first paraemter of db.translateStatement.
+ * @param {string} pAlias - The database alias
+ * @param {(pStatement: Array)=>string} pExecutionCallback - A function which must return the final SQL
+ * @return {string} The SQL, same as the result of db.translateStatement.
  */
 SqlUtils.translateWithQuotes = function(pStatement, pAlias, pExecutionCallback) 
 {
     // Validate type of incoming paramter.
     if (!Array.isArray(pStatement))
+    {
         return null;
+    }
 
     // The second element of the array has to be an array.
     if (!Array.isArray(pStatement[1]))
+    {
         return null;
+    }
 
     // As the second element represents the prepared statements we need to map it...
-    var preparedStatements = pStatement[1].map(function(pValue) 
+    let preparedStatements = pStatement[1].map(function(pValue) 
     {
         // Just in case as a fallback value..
         if (!(Array.isArray(pValue)))
+        {
             return pValue;
+        }
 
         // As the first element represents the value it will be quoted here.
         if(pAlias)
@@ -4432,13 +4827,13 @@ SqlUtils.translateWithQuotes = function(pStatement, pAlias, pExecutionCallback)
     });
 
     return pExecutionCallback([pStatement[0], preparedStatements]);
-}
+};
 
 /**
  * Will quote all prepared statement values from the given statement.
  * 
- * @param {Array|string} pStatement Same as the first parameter of db.translateStatement.
- * @param {string} [pAlias] the alias which should be used for db.translateStatement()
+ * @param {[string, Array]} pStatement - Same as the first parameter of db.translateStatement.
+ * @param {string} [pAlias] - The alias which should be used for db.translateStatement()
  * @returns {string} The SQL, same as the result of db.translateStatement.
  */
 SqlUtils.translateStatementWithQuotes = function(pStatement, pAlias) 
@@ -4446,17 +4841,21 @@ SqlUtils.translateStatementWithQuotes = function(pStatement, pAlias)
     return SqlUtils.translateWithQuotes(pStatement, pAlias, function(pValue) 
     {
         if (pAlias)
-            return db.translateStatement(pValue, pAlias)
+        {
+            return db.translateStatement(pValue, pAlias);
+        }
         else
-            return db.translateStatement(pValue)
+        {
+            return db.translateStatement(pValue);
+        }
     });
-}
+};
 
 /**
  * Will quote all prepared statement values from the given statement.
  * 
- * @param {Array} pStatement Same as the first parameter of db.translateCondition.
- * @param {string} [pAlias] the alias which should be used for db.translateStatement()
+ * @param {[string, Array]} pStatement - Same as the first parameter of db.translateCondition.
+ * @param {string} [pAlias] - The alias which should be used for db.translateStatement()
  * @returns {string} The SQL, same as the result of db.translateCondition.
  */
 SqlUtils.translateConditionWithQuotes = function(pStatement, pAlias) 
@@ -4464,28 +4863,45 @@ SqlUtils.translateConditionWithQuotes = function(pStatement, pAlias)
     return SqlUtils.translateWithQuotes(pStatement, pAlias, function(pValue) 
     {
         if (pAlias)
-            return db.translateCondition(pValue, pAlias)
+        {
+            return db.translateCondition(pValue, pAlias);
+        }
         else
-            return db.translateCondition(pValue)
+        {
+            return db.translateCondition(pValue);
+        }
     });
-}
+};
 
+/**
+ * Parses the field name
+ *
+ * @param {string|string[]} pField - The field name, can be a string with the format "TABLENAME.COLUMNNAME", 
+ *                                   or an array: [tableName, columnName, alias], "alias" is optional
+ * @return {[string, string]} Array with the structure [columnIdentifierWithAlias, columnIdentifier]
+ */
 SqlUtils.parseField = function(pField)
 {
-    var alias = "";
-    if (typeof pField === 'string')
+    let alias = "";
+    if (typeof pField === "string")
     {
-        var pointPos = pField.indexOf(".");
+        let pointPos = pField.indexOf(".");
 
-        if (pointPos > 0 && pointPos < pField.length-1)
+        if (pointPos > 0 && pointPos < pField.length - 1)
+        {
             alias = pField;
+        }
         else
+        {
             throw new Error(translate.text("${SQL_LIB_FIELD_WRONG_FORMAT}") + pField + translate.withArguments("${SQL_LIB_FIELD_WRONG_FORMAT} field: %0", [pField]));
+        }
     }
     else
     {
         if (pField.length == 2)
+        {
             pField.push(pField[0]);
+        }
         
         if (pField.length == 3)
         {
@@ -4493,11 +4909,22 @@ SqlUtils.parseField = function(pField)
             pField = pField[0] + "." + pField[1];
         }
         else
-            throw new Error(translate.text("${SQL_LIB_FIELD_WRONG_FORMAT}") + pField.toSource() + translate.withArguments("${SQL_LIB_FIELD_WRONG_FORMAT} field: %0", [pField.toSource()]));
+        {
+            throw new Error(translate.text("${SQL_LIB_FIELD_WRONG_FORMAT}") + JSON.stringify(pField) 
+                + translate.withArguments("${SQL_LIB_FIELD_WRONG_FORMAT} field: %0", [JSON.stringify(pField)]));
+        }
     }
-    return [alias, pField]
-}
+    return [alias, pField];
+};
 
+/**
+ * Replaces placeholders in a condition string
+ * 
+ * @param {string} pCondition - The sql condition
+ * @param {string} pPlaceholder - The placeholder name
+ * @param {string} pReplacement - The value to replace the placeholder
+ * @return {string} Condition with filled placeholders
+ */
 SqlUtils.replaceConditionTemplate = function(pCondition, pPlaceholder, pReplacement) 
 {
     //SqlUtils.replaceConditionTemplate(pCondition, '#', SqlUtils.parseField(pFieldOrCond).join("."))
@@ -4516,63 +4943,71 @@ SqlUtils.replaceConditionTemplate = function(pCondition, pPlaceholder, pReplacem
     ---------------------
     */
     //use replaceAll because it's faster and supports negative lookbehinds
-    var replacements = {};
+    let replacements = {};
     //manually readd the replaced backslashes by using a group reference, because they a part of the match and therefore replaced by "replaceAll"
     //since the field COULD contain already a group reference (I think this is extremely uncommon; 
     //probably that never happens but better stay save): escape that references within the fieldname
     replacements["(?<!\\\\)((?:\\\\\\\\)*)" + pPlaceholder] = "$1" + text.replaceAll(pReplacement, {
         "$1": "\\$1"
-    })
-     //now that we've replaced the correct field placeholder let's replace the escaped placeholder sign "\#" to a normal placeholder sign "#"
-    replacements["\\\\" + pPlaceholder] = pPlaceholder
+    });
+    //now that we've replaced the correct field placeholder let's replace the escaped placeholder sign "\#" to a normal placeholder sign "#"
+    replacements["\\\\" + pPlaceholder] = pPlaceholder;
     
     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
+ * @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 (it uses text.replaceAll which supports lookbehind because it uses java)
-    pCondition = SqlUtils.replaceConditionTemplate(pCondition, "#", "{@NUMBERSIGN@}")
-    pCondition = SqlUtils.replaceConditionTemplate(pCondition, "\\?", "{@QUESTIONSIGN@}")
+    pCondition = SqlUtils.replaceConditionTemplate(pCondition, "#", "{@NUMBERSIGN@}");
+    pCondition = SqlUtils.replaceConditionTemplate(pCondition, "\\?", "{@QUESTIONSIGN@}");
 
-    var indexOfNumberSign = pCondition.indexOf("{@NUMBERSIGN@}");
-    var indexOfQuestionSign = pCondition.indexOf("{@QUESTIONSIGN@}");
+    let indexOfNumberSign = pCondition.indexOf("{@NUMBERSIGN@}");
+    let indexOfQuestionSign = pCondition.indexOf("{@QUESTIONSIGN@}");
     
-    return !(indexOfQuestionSign == -1 || indexOfNumberSign > indexOfQuestionSign || indexOfNumberSign != pCondition.lastIndexOf("{@NUMBERSIGN@}") || indexOfQuestionSign != pCondition.lastIndexOf("{@QUESTIONSIGN@}"))
-}
+    return !(indexOfQuestionSign == -1 || indexOfNumberSign > indexOfQuestionSign || indexOfNumberSign != pCondition.lastIndexOf("{@NUMBERSIGN@}") || indexOfQuestionSign != pCondition.lastIndexOf("{@QUESTIONSIGN@}"));
+};
 
 /**
  * Escapes a jdito variable for the value of a SqlBuilder condition. SqlBuilder.prototype.where/and/or/... automatically resolve the value as a jdito
  * variable if it starts with a single '$', so you can use this function to make sure the value is used as it is.
- * <br>
+ * 
  * Note: The main purpose of this is to prevent errors resulting from unexpected user inputs. But if you are loading the input from a jdito variable
  * anyways, you can just wite the variable name as the condition value and it will be safe.
  * 
- * @param {string} pValue the value
+ * @param {string} pValue - the value
  * @return {string} the escaped string
  * @example
  * 
- * var sqlCond = newWhere("TABLE.COLUMN", SqlUtils.escapeVars(userInput)); //userInput could start with '$'
+ * let sqlCond = newWhere("TABLE.COLUMN", SqlUtils.escapeVars(userInput)); //userInput could start with '$'
  */
-SqlUtils.escapeVars = function (pValue)
+SqlUtils.escapeVars = function(pValue)
 {
     if (typeof(pValue) == "string" && pValue.charAt(0) == "$")
+    {
         return "$" + pValue;
+    }
     return pValue;
-}
+};
 
+/**
+ * Maps the integer operator value from "$local.operator" to SqlBuilder constants
+ * 
+ * @param {number} pOperator - The number value of the operator
+ * @return {string} Sql representation of the operator
+ */
 SqlUtils.getSqlConditionalOperator = function(pOperator)
 {
     pOperator = pOperator || vars.get("$local.operator");
-    switch(parseInt(pOperator))
+    switch(Number(pOperator))
     {
         case 1:
             return SqlBuilder.EQUAL();
@@ -4597,23 +5032,24 @@ SqlUtils.getSqlConditionalOperator = function(pOperator)
         default:
             throw new Error("Unsupported operator " + pOperator);
     }
-}
+};
 
 /**
- * Returns the pNullableExpr if pNullableExpr is not null
+ * Returns the pNullableExpr if pNullableExpr is not null,
  * otherwise it returns pDefaultExpr
  * 
- * @param {string|SqlBuilder} pNullableExpr a nullable expression
- * @param {string|SqlBuilder} pDefaultExpr the default expression if pNullableExpr is null
+ * @param {string|SqlBuilder} pNullableExpr - A nullable expression
+ * @param {string|SqlBuilder} pDefaultExpr - The default expression if pNullableExpr is null
  * 
  * @returns {SqlBuilder._CaseStatement} pNullableExpr with pDefaultExpr as fallback
  */
 SqlUtils.nullableWithDefault = function(pNullableExpr, pDefaultExpr)
 {
     return SqlBuilder.caseStatement()
-        .when("(" + pNullableExpr.toString() + ") is null").then(pDefaultExpr)
+        .when("(" + pNullableExpr.toString() + ") is null")
+        .then(pDefaultExpr)
         .elseValue(pNullableExpr);
-}
+};
 
 /**
  * Adds a whitelist condition to pCondition. This function handles empty whitelists differently than no whitelists:
@@ -4621,7 +5057,7 @@ SqlUtils.nullableWithDefault = function(pNullableExpr, pDefaultExpr)
  * 
  * @param {SqlBuilder} pCondition SqlBuilder where condition
  * @param {string} pField the field the whitelist should be compared to
- * @param {array|string} [pWhitelist] whitelist to compare
+ * @param {Array | string} [pWhitelist] whitelist to compare
  * @returns {SqlBuilder} condition
  */
 SqlUtils.addWhitelistCondition = function(pCondition, pField, pWhitelist) 
@@ -4643,9 +5079,7 @@ SqlUtils.addWhitelistCondition = function(pCondition, pField, pWhitelist)
         }
     }
     return cond;
-}
-
-
+};