diff --git a/process/Sql_lib/process.js b/process/Sql_lib/process.js
index a61bc1aa625f99ebce9ca0759965eb4b016942dd..1a55a386f9d48a5ea2e61246bc900eae1d121fde 100644
--- a/process/Sql_lib/process.js
+++ b/process/Sql_lib/process.js
@@ -9,6 +9,636 @@ import("system.SQLTYPES");
 import("system.text");
 import("Util_lib");
 
+/**
+ * object for easier handling of conditions;
+ * With this object you do not have to check if the string is empty or not;
+ * you don't need to append a "1=1" condition or similar;
+ * this objects gains most benefit if you have a lot of conditions that are added (or not) depending on tons of JDito-conditions
+ * 
+ * You can also use SqlCondition.begin(alias) for simpler object creation without new and without the need for an extra variable to save the object.
+ * 
+ * @class 
+ * @param {String} [alias=the current alias] the database alias where the condition shall be executed later (important for column types of preparedStatements)
+ * @example 
+ * see others/guide/HowToSqlConditionLib.adoc
+ * 
+ * @deprecated The SqlCondition will be removed in version >= 2020.x
+ *             Use the SqlBuilder instead.
+ *             For SqlBuilder usage see the documentation-property of the Sql_lib.
+ */
+function SqlCondition(alias) {
+    // setting null is only needed to provide autocomplete for the ADITO-designer
+    this.preparedValues = null;
+    this._init(); // the properties are initalized in an extra function because init is nearly the same as resetting (clearing) the SqlConditions
+    this.alias = alias;
+    
+    // save, if the last condition was an OR. For better bracket-placement
+    this._lastWasOr = false;
+}
+
+/**
+ * Alternative possibility to crate a new condition.
+ * With this you don't need new SqlCondition and you can use the object directly after it's creation
+ * --> cleaner code
+ * 
+ * It is very usefull for the orSqlCondition() and andSqlCondition() because now you can create a new condition inline.
+ * You can also use it for simple selects without the need to save the conditionObject in an extra variable.
+ * See Examples!
+ * 
+ * @param {String} [alias=the current alias] the database alias where the condition shall be executed later (important for column types of preparedStatements)
+ * @return {SqlCondition} the new SqlCondition-object
+ * 
+ * @example 
+ * vars mySelect = SqlCondition.begin(alias)
+ *                             .and("MYID = '123'")
+ *                             .and(SqlCondition.begin()
+ *                                              .or("NAME = 'Max'")
+ *                                              .or("NAME = 'Bob'")
+ *                              )
+ *                             .buildSql("select * from MYTABLE");
+ *                             
+ * // Or use it for simple selects:
+ * var sum = db.cell(SqlCondition.begin()
+ *                               .andPrepared("STOCK.PRODUCT_ID", pid)
+ *                               .buildSql("select sum(QUANTITY * IN_OUT) from STOCK"));
+ *                               
+ * @deprecated The SqlCondition will be removed in version >= 2020.x
+ *             Use the SqlBuilder instead.
+ *             For SqlBuilder usage see the documentation-property of the Sql_lib."
+ */
+SqlCondition.begin = function(alias) {
+    return new SqlCondition(alias);
+}
+
+/**
+ * checks if conditions have been added to the object
+ * @return {Boolean} true if conditions have been added, false when not
+ */
+SqlCondition.prototype.isSet = function() {
+    if (this._sqlStorage)
+        return true;
+    return false;
+}
+
+
+/**
+ * append with SQL-and; no paranthesize of existing conditions is done
+ * @param {String} cond the condition string which shall be appended
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.and = function(cond) {
+    if (!cond)
+        return this;
+    if (this.isSet())
+        this._sqlStorage += " and ";
+    this._sqlStorage += cond;
+    return this;
+}
+
+/**
+ * append with SQL-or; Also paranthesize the existing conditions
+ * @param {String} cond the condition string which shall be appended
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.or = function(cond) {
+    if (!cond)
+        return this;
+    
+    if (this.isSet() && !this._lastWasOr) {
+        this._sqlStorage = "(" + this._sqlStorage + ") or (" + cond + ")";
+        this._lastWasOr = true;
+        
+    } else if (this.isSet() && this._lastWasOr) {
+        this._sqlStorage = this._sqlStorage + " or (" + cond + ")";
+        this._lastWasOr = true;
+        
+    } else {
+        this._sqlStorage = cond;
+    }
+    return this;
+}
+
+/**
+ * append a prepared-array to this sql condition with SQL-and
+ * @param {Array} preparedObj a prepared condition-array
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.andAttachPrepared = function(preparedObj) {
+    if (preparedObj)
+    {
+        this.preparedValues = this.preparedValues.concat(preparedObj[1]);
+        return this.and(preparedObj[0]);
+    }
+    
+    return this;
+}
+
+/**
+ * append a prepared-array to this sql condition with SQL-or
+ * @param {Array} preparedObj a prepared condition-array
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.orAttachPrepared = function(preparedObj) {
+    if (preparedObj)
+    {
+        this.preparedValues = this.preparedValues.concat(preparedObj[1]);
+        return this.or(preparedObj[0]);
+    }
+    
+    return this;
+}
+
+/**
+ * append another condition with SQL-and
+ * 
+ * @param {SqlCondition} cond the condition which shall be appended
+ * @param {String} [alternativeCond=""] condition if the given SqlCondition has none
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.andSqlCondition = function(cond, alternativeCond) {
+    if (!cond)
+        return this
+        
+    var otherCondition = cond.toString(alternativeCond);
+    if (otherCondition.trim() != "")
+    {
+        this.and(" ( " + cond.toString(alternativeCond) + " ) ");
+        if (cond.preparedValues) {
+            this.preparedValues = this.preparedValues.concat(cond.preparedValues);
+        }
+    }
+    return this;
+}
+
+/**
+ * append another condition with SQL-or; Also paranthesize the existing conditions
+ * 
+ * @param {SqlCondition} cond the condition which shall be appended
+ * @param {String} [alternativeCond=""] condition if the given SqlCondition has none
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.orSqlCondition = function(cond, alternativeCond) {
+    var otherCondition = cond.toString(alternativeCond);
+    if (otherCondition.trim() != "")
+    {
+        this.or(" ( " + cond.toString(alternativeCond) + " ) ");
+        if (cond.preparedValues) {
+            this.preparedValues = this.preparedValues.concat(cond.preparedValues);
+        }
+    }
+    return this;
+}
+
+/**
+ * append an condition that uses a subQuery with SQL-and
+ * 
+ * @param {SqlBuilder} subQuery the SqlBuilder object that will be used as a subquery
+ * @param {String} [cond="exists"] condition that is used (e. g. exists, not exists, COLUMN = any, COLUMN in, ...)
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.andSqlBuilder = function(subQuery, cond) {
+    if (!cond)
+        cond = "exists";
+    
+    var preparedObj = subQuery.build();
+    preparedObj[0] = cond + " ( " + preparedObj[0] + " ) ";
+    this.andAttachPrepared(preparedObj);
+    
+    return this;
+}
+
+/**
+ * append an condition that uses a subQuery with SQL-or
+ * 
+ * @param {SqlBuilder} subQuery the SqlBuilder object that will be used as a subquery
+ * @param {String} [cond="exists"] condition that is used (e. g. exists, not exists, COLUMN = any, COLUMN in, ...)
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.orSqlBuilder = function(subQuery, cond) {
+    if (!cond)
+        cond = "exists";
+    
+    var preparedObj = subQuery.build();
+    preparedObj[0] = cond + " ( " + preparedObj[0] + " ) ";
+    this.orAttachPrepared(preparedObj);
+    
+    return this;
+}
+
+/**
+ * same as the "and"-function but with preparedStatement functionality
+ * @param {String | String[]} field the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME" or as array with column-alias: ["ORGANISATION", "NAME", "myorgAlias"]
+ * @param {String} value the value that shall be set into the prepared statement
+ * @param {String} [cond="# = ?"] 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 "\"
+ * @param {Numeric | Boolean} [fieldType] 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, "# <> ?")
+ *                              }
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.andPrepare = function(field, value, cond, fieldType) {
+    cond = this._prepare(field, value, cond, fieldType);
+    return this.and(cond);
+}
+
+/**
+ * same as the "or"-function but with preparedStatement functionality
+ * @param {String | String[]} field the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME" or as array with column-alias: ["ORGANISATION", "NAME", "myorgAlias"]
+ * @param {String} value the value that shall be set into the prepared statement
+ * @param {String} [cond="# = ?"] 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 "\"
+ * @param {Numeric | Boolean} [fieldType] 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, "# <> ?")
+ *                              }
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.orPrepare = function(field, value, cond, fieldType) {
+    cond = this._prepare(field, value, cond, fieldType);
+    return this.or(cond);
+}
+
+/**
+ * same as the "andPrepare"-function but only applied if the passed "value" is truely
+ * @param {String | String[]} field the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME" or as array with column-alias: ["ORGANISATION", "NAME", "myorgAlias"]
+ * @param {String} value the value that shall be set into the prepared statement
+ * @param {String} [cond="# = ?"] 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 "\"
+ * @param {Numeric | Boolean} [fieldType] 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, "# <> ?")
+ *                              }
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.andPrepareIfSet = function(field, value, cond, fieldType) {
+    if (value)
+        return this.andPrepare(field, value, cond, fieldType);
+    return this;
+}
+
+/**
+ * same as the "orPrepare"-function but only applied if the passed "value" is truely
+ * @param {String | String[]} field the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME" or as array with column-alias: ["ORGANISATION", "NAME", "myorgAlias"]
+ * @param {String} value the value that shall be set into the prepared statement
+ * @param {String} [cond="# = ?"] 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 "\"
+ * @param {Numeric | Boolean} [fieldType] 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, "# <> ?")
+ *                              }
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.orPrepareIfSet = function(field, value, cond, fieldType) {
+    if (value)
+        return this.orPrepare(field, value, cond, fieldType);
+    return this;
+}
+
+/**
+ * same as the "andPrepare"-function but with validation of adito-variables functionality
+ * @param {String | String[]} field the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME" or as array with column-alias: ["ORGANISATION", "NAME", "myorgAlias"]
+ * @param {String} variable the adito-variable that shall be set into the prepared statement
+ * @param {String} [cond = "# = ?" ] 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 "\"
+ * @param {Numeric | Boolean} [fieldType] 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, "# <> ?")
+ *                              }
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.andPrepareVars = function(field, variable, cond, fieldType) {
+    variable = this._checkVars(variable)
+    if (variable) {
+        return this.andPrepare(field, variable, cond, fieldType);
+    }
+    return this;
+}
+
+/**
+ * same as the "orPrepare"-function but with validation of adito-variables functionality
+ * @param {String | String[]} field the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME" or as array with column-alias: ["ORGANISATION", "NAME", "myorgAlias"]
+ * @param {String} variable the adito-variable that shall be set into the prepared statement
+ * @param {String} [cond="# = ?"] 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 "\"
+ * @param {Numeric | Boolean} [fieldType] 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, "# <> ?")
+ *                              }
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.orPrepareVars = function(field, variable, cond, fieldType) {
+    variable = this._checkVars(variable)
+    if (variable) {
+        return this.orPrepare(field, variable, cond, fieldType);
+    }
+    return this;
+}
+
+/**
+ * creates a IN-statement out of a field and an array of values.
+ * Be carefull with a big number of values. This may have a bad performance.
+ * 
+ * @param {String | String[]} field the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME" or as array with column-alias: ["ORGANISATION", "NAME", "myorgAlias"]
+ * @param {String[]} values the value that shall be set into the prepared statement
+ * @param {Numeric | Boolean} [fieldType] 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} [not = undefined] if true, add not before in
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.andIn = function(field, values, fieldType, not) {
+    return this.andAttachPrepared(this._in(field, values, fieldType, not));
+}
+
+/**
+ * creates a IN-statement out of a field and an array of values.
+ * Be carefull with a big number of values. This may have a bad performance.
+ * 
+ * @param {String | String[]} field the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME" or as array with column-alias: ["ORGANISATION", "NAME", "myorgAlias"]
+ * @param {String[]} values the value that shall be set into the prepared statement
+ * @param {Numeric | Boolean} [fieldType] 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} [not = undefined] if true, add not before in
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype.orIn = function(field, values, fieldType, not) {
+    return this.orAttachPrepared(this._in(field, values, fieldType, not));
+}
+
+/**
+ * creates a IN-statement out of a field and an array of values.
+ * Be carefull with a big number of values. This may have a bad performance.
+ * 
+ * @param {String | String[]} field the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME" or as array with column-alias: ["ORGANISATION", "NAME", "myorgAlias"]
+ * @param {String[]} values the value that shall be set into the prepared statement
+ * @param {Numeric | Boolean} [fieldType] 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} [not = undefined] if true, add not before in
+ * @return {SqlCondition} current SqlCondition-object
+ */
+SqlCondition.prototype._in = function(field, values, fieldType, not) {
+    if (values && values.length > 0)
+    {
+        if (fieldType == undefined)
+            fieldType = SqlUtils.getSingleColumnType(field, undefined, this.alias);
+        
+        preparedStatement = SqlUtils.getSqlInStatement(field, values, undefined, true, fieldType);
+        if (not)
+            preparedStatement[0] = " not " + preparedStatement[0];
+        return preparedStatement;
+    }
+    
+    return null;
+}
+
+/**
+ * ready to use string; does not contain a where keyword at the beginning
+ * @param {String} [alternativeCond=""] condition that is returned when nothing has been appended.
+ * @return {String} concatenated SQL-condition; empty string if nothing has been appended or - if passed - the alternativeCond
+ */
+SqlCondition.prototype.toString = function(alternativeCond) {
+    if (!this.isSet() && alternativeCond)
+        return alternativeCond
+    else
+        return this._sqlStorage;
+}
+
+/**
+ * ready to use string; does contain a where keyword at the beginning
+ * @param {String} [alternativeCond=""] condition that is returned when nothing has been appended.
+ * @return {SqlCondition} concatenated SQL-condition; empty string if nothing has been appended or - if passed - the alternativeCond
+ */
+SqlCondition.prototype.toWhereString = function(alternativeCond) {
+    var cond = this.toString(alternativeCond);
+    if (cond)
+        return " where " + cond;
+    else 
+        return cond;
+}
+
+/**
+ * ready to use prepared condition; does not contain a where keyword at the beginning
+ * @param {String} [alternativeCond=""] Condition that is returned when nothing has been appended.
+ * @return {Array[][][]} Prepared condition with [condition, [[field1, type1], [field2, type2]]]
+ */
+SqlCondition.prototype.build = function(alternativeCond) {
+    return [this.toString(alternativeCond), this.preparedValues];
+}
+
+/**
+ * ready to use prepared select
+ * @param {String} pBeforeCondition Part of the sql before the condition without where (e.g. "select FIRSTNAME from PERSON")
+ * @param {String} [pAlternativeCond=""] Condition that is returned when nothing has been appended.
+ * @param {String} [pAfterCondition=""] Part of the sql after the condition (e.g. "order by FIRSTNAME").
+ * @param {Boolean} [pWithWere=true] true if where should be added to the bginning
+ * @return {Array[][][]} Prepared condition with [condition, [[field1, type1], [field2, type2]]]
+ */
+SqlCondition.prototype.buildSql = function(pBeforeCondition, pAlternativeCond, pAfterCondition, pWithWere) {
+    if (pAfterCondition == undefined)
+        pAfterCondition = "";
+    
+    if (pWithWere == undefined) 
+        pWithWere = true;
+    
+    return [pBeforeCondition  + " " + 
+            (pWithWere ? this.toWhereString(pAlternativeCond) : this.toString(pAlternativeCond)) +
+            " " + pAfterCondition, this.preparedValues];
+}
+
+/**
+ * translates SqlCondition to plain SQL. Use this if prepared statements are not supported.
+ * It resolves all prepared values.
+ * @param {String} pAlternativeCond used if the SqlCondition does not contain any condition.
+ * @return {String} plain SQL condition
+ */
+SqlCondition.prototype.translate = function(pAlternativeCond) 
+{
+    return SqlUtils.translateConditionWithQuotes(this.build(pAlternativeCond, this.alias));
+}
+
+/**
+ * Check if (adito-)variable exists and vars.getString is not empty
+ * @param {String} variable the variable name (e.g. "$field.CONTACT_ID")
+ * @return {String | Boolean} The value of the field as string OR false if it doesn't exist.
+ * 
+ * @ignore
+ */
+SqlCondition.prototype._checkVars = function(variable) {
+    if (vars.exists(variable)) {
+        var value = vars.getString(variable);
+        if (value) {
+            return value;
+        }
+    }
+    return false;
+}
+
+/**
+ * hidden function for composing preparedStatements
+ * @param {String | String[]} field the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME" or as array with column-alias: ["ORGANISATION", "NAME", "myorgAlias"]
+ * @param {String} value the value that shall be set into the prepared statement
+ * @param {String} cond 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 {Numeric | Boolean} [fieldType] 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, "# <> ?")
+ *                              }
+ * @return {String} the replaced SQL-condition string (replace # by the fieldname)
+ * @ignore
+ */
+SqlCondition.prototype._prepare = function(field, value, cond, fieldType) {
+    if (value == undefined)
+    {
+        throw new Error(translate.withArguments("${SQL_LIB_UNDEFINED_VALUE} field: %0", [field]));
+    }
+    
+    if (cond == undefined) {
+        cond = "# = ?"
+    }
+
+    var alias;
+    
+    if (typeof field === 'string')
+    {
+        var pointPos = field.indexOf(".");
+        
+        if (pointPos > 0 && pointPos < field.length-1)
+        {
+            alias = field;
+        }
+        else
+        {
+            throw new Error(translate.withArguments("${SQL_LIB_FIELD_WRONG_FORMAT} field: %0", [field]));
+        }
+    }
+    else
+    {
+        if (field.length == 3)
+        {
+            alias = field[2] + "." + field[1];
+            field = field[0] + "." + field[1];
+        }
+        else
+        {
+            throw new Error(translate.withArguments("${SQL_LIB_FIELD_WRONG_FORMAT} field: %0", [field.toSource()]));
+        }
+    }
+    
+    var type;
+    
+    if (fieldType == undefined)
+        fieldType = SqlUtils.getSingleColumnType(field, undefined, this.alias);
+
+    //this function looks more complex (and slower) than it actually is
+    /* the following regex looks like this after javascript-escaping of the backslash: (?<!\\)((?:\\\\)*)#
+    the regexp searches for the unescaped character and these characters are replaced by the field name
+
+    examples:
+    ---------------------
+    | # --match         |
+    | \# --no-match     |
+    | \\# --match       |
+    | \\\# --no-match   |
+    | \\\\# --match     |
+    ---------------------
+    */
+    //use replaceAll because it's faster and supports negative lookbehinds
+    cond = text.replaceAll(cond, {
+        //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
+        "(?<!\\\\)((?:\\\\\\\\)*)#": "$1" + text.replaceAll(alias, {
+            "$1": "\\$1"
+        }),
+        //now that we've replaced the correct field placeholder let's replace the escaped number sign "\#" to a normal number sign "#"
+        "\\\\#": "#"
+    });
+    
+    
+    
+    type = fieldType
+    this.preparedValues.push([value.toString(), type]);
+    return cond;
+}
+
+
+/**
+ * function that resets the current SqlCondition as if no conditions would have been added
+ * this is usefull if you want to reuse the same object over and over
+ * @return {null} 
+ */
+SqlCondition.prototype.clear = function() {
+    this._sqlStorage = "";
+    this.preparedValues = [];
+    return this;
+}
+
+/**
+ * hidden function for initializing all properties for the sql conditions
+ * @return {null} 
+ * 
+ * @ignore
+ */
+SqlCondition.prototype._init = function() {
+    //init only wraps the clear function to avoid confusion in the constructor (and provide better extensibility)
+    return this.clear();
+}
+
+// some static functions for often used tasks. They are only provided for very simple tasks.
+
+/**
+ * pField = pValue
+ * @param {String} pField the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME"
+ * @param {String} pValue the value that shall be set into the prepared statement
+ * @param {String} [pAlternativeCond=""] Condition that is returned when nothing has been appended.
+ * @param {String} [pAlias=the current alias] the database alias where the condition shall be executed later (important for column types of preparedStatements)
+ * 
+ * @return {Array[][][]} Prepared condition with [condition, [[field, type]]]
+ */
+SqlCondition.equals = function(pField, pValue, pAlternativeCond, pAlias) {
+    return SqlCondition.begin(pAlias).andPrepare(pField, pValue).build(pAlternativeCond);
+}
+
+/**
+ * pField <> pValue
+ * @param {String} pField the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME"
+ * @param {String} pValue the value that shall be set into the prepared statement
+ * @param {String} [pAlternativeCond=""] Condition that is returned when nothing has been appended.
+ * @param {String} [pAlias=the current alias] the database alias where the condition shall be executed later (important for column types of preparedStatements)
+ * 
+ * @return {Array[][][]} Prepared condition with [condition, [[field, type]]]
+ */
+SqlCondition.equalsNot = function(pField, pValue, pAlternativeCond, pAlias) {
+    return SqlCondition.begin(pAlias).andPrepare(pField, pValue, "# <> ?").build(pAlternativeCond);
+}
+
 // see Documentation property of this lib for further explanation
 
 /** 
@@ -287,6 +917,42 @@ 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)"));
 }
+/**
+ * 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.
+ */
+SqlBuilder.begin = function ()
+{
+    return new SqlBuilder();
+}
+
 
 /**
  * Builds the sql and uses SqlUtils.translateXXXWithQuotes to make a string out of it.
@@ -322,6 +988,17 @@ SqlBuilder.prototype.select = function(pFields)
     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)
+{
+    this._select = this._getClause(pFields, "select distinct", 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
@@ -368,6 +1045,14 @@ SqlBuilder.prototype.from = function(pTable, pTableAlias)
  */
 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");
     if (pPrefix)
         prefix = pPrefix + " " + prefix;
@@ -482,7 +1167,22 @@ SqlBuilder.prototype.rightJoin = function(pTable, pCondition, pTableAlias)
  * @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);
 }
 
@@ -1748,6 +2448,68 @@ SqlBuilder.prototype._checkForSelect = function(pExecuteOnlyIfConditionExists)
     }
 }
 
+/**
+ * generates a part of the sql
+ * 
+ * @param {String|String[]|SqlBuilder|SqlCondition} pElement the element to append
+ * @param {String} [pPrefix] string to be added before pElement
+ * @param {Boolean} [pAutoJoin] if this is true and pElement is an array, it will be automatically
+ *                               joined together to a string
+ * 
+ * @private
+ * @deprecated this method is only needed by deprecated methods
+ */
+SqlBuilder.prototype._getClause = function (pElement, pPrefix, pAutoJoin)
+{
+    var preparedValues = [];
+    if (typeof pElement !== "string")
+    {
+        if (pElement.length !== undefined && pAutoJoin) //array of fields
+        {
+            for (let i = 0, l = pElement.length; i < l; i++)
+            {
+                if (typeof pElement[i] !== "string")
+                    pElement[i] = _getElement(pElement[i]);
+            }
+            pElement = pElement.join(", ");
+        }
+        else
+        {
+            pElement = _getElement(pElement);
+        }
+    }
+
+    if (pPrefix && pElement)
+        pElement = pPrefix + " " + pElement;
+    
+    return [pElement.toString(), preparedValues];
+    
+    function _getElement (element)
+    {
+        if (element instanceof SqlBuilder || element instanceof SqlCondition)
+            element = element.build();
+        preparedValues = preparedValues.concat(element[1]);
+        if (element instanceof SqlBuilder || pAutoJoin)
+            return "(" + element[0] + ")";
+        return element[0];
+    }
+}
+
+/**
+ * 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
+ * @return {String} plain SQL statement
+ * 
+ * @deprecated use .toString()
+ */
+SqlBuilder.prototype.translate = function(pAlias)
+{
+    return SqlUtils.translateStatementWithQuotes(this.build(), pAlias);
+}
+
+
 /**
  *provides functions for masking sql functions
  *