From 9871c1811b0d365d50008a28b36b361db08397cb Mon Sep 17 00:00:00 2001 From: "j.goderbauer" <j.goderbauer@adito.de> Date: Thu, 29 Nov 2018 10:26:24 +0100 Subject: [PATCH] [Projekt: Entwicklung - Neon][TicketNr.: 1027750][JDito - libray Standard ist komplett definiert und wird in allen libs verwendet] --- process/Sql_lib/process.js | 718 +++++++++--------------------------- process/Util_lib/process.js | 32 -- 2 files changed, 168 insertions(+), 582 deletions(-) diff --git a/process/Sql_lib/process.js b/process/Sql_lib/process.js index a69021b68b8..9cc2ce5f5d3 100644 --- a/process/Sql_lib/process.js +++ b/process/Sql_lib/process.js @@ -24,6 +24,7 @@ function SqlCondition(alias){ this.cachedTypes = {}; this.lastWasOr = false; } + /** * append with SQL-and; no paranthesize of existing conditions is done * @param {String} cond the condition string which shall be appended @@ -201,7 +202,8 @@ SqlCondition.prototype.build = function(alternativeCond){ * @return {Array[][][]} Prepared condition with [condition, [[field1, type1], [field2, type2]]] */ SqlCondition.prototype.buildSelect = function(beforeCondition, alternativeCond, afterCondition) { - if (afterCondition == undefined) { afterCondition = "" }; + if (afterCondition == undefined) + afterCondition = "" return [beforeCondition + " " + this.toWhereString(alternativeCond) + " " + afterCondition, this.preparedValues]; } @@ -317,6 +319,7 @@ function SqlMaskingUtils(alias){ } }); this.dbType = null; + //provide the possibility to just set dbType (e.g. for testing) with no association to an alias Object.defineProperty(this, "dbType", { set: function(v){ this._alias = null; @@ -333,6 +336,31 @@ function SqlMaskingUtils(alias){ this.alias = alias; } +/** + * returns the concat symbol depending on database type + * @return {String} Concat Symbol + */ +SqlMaskingUtils.prototype.getConcatSymbol = function() +{ + var concatSymbol; + switch(Number(this.dbType)) { + case db.DBTYPE_SQLSERVER2000: + concatSymbol = " + "; + break; + case db.DBTYPE_MARIADB10: + case db.DBTYPE_MYSQL4: + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_THIN: + case db.DBTYPE_ORACLE10_OCI: + case db.DBTYPE_POSTGRESQL8: + case db.DBTYPE_DERBY10: + default: + concatSymbol = " || "; + break; + } + return concatSymbol; +} + /** * returns the trim function depending on the database behin the given alias * note that this function does not verifiy where the types of your expression are trimable or not @@ -528,6 +556,33 @@ SqlMaskingUtils.prototype.castLob = function(field, targetLength) { return res; } +/** + * returns the function which determines the length of binary data + * + * @param {String} fieldName name of the checked field + * + * @return {String} + */ +SqlMaskingUtils.prototype.binDataLength = function(fieldName) { + var res; + + switch(this.dbType) { + case db.DBTYPE_MARIADB10: + case db.DBTYPE_MYSQL4: + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_THIN: + case db.DBTYPE_ORACLE10_OCI: + case db.DBTYPE_POSTGRESQL8: + case db.DBTYPE_DERBY10: + res = "LENGTH(" + fieldName + ")"; + break; + case db.DBTYPE_SQLSERVER2000: + res = "DATALENGTH(" + fieldName + ")"; + break; + } + return res; +} + /** * masks the sql function substring * @@ -585,7 +640,7 @@ SqlMaskingUtils.prototype.concat = function(fields, separatorCharacter, autoTrim return "''"; else if (fields.length == 1) return fields[0]; - concatSql = " || "; + concatSql = this.getConcatSymbol(); isNotEmptyStrSql = " != '' "; isNotNullSql = " is not null "; separatorSql = separatorCharacter == undefined ? " " : separatorCharacter; @@ -611,7 +666,6 @@ SqlMaskingUtils.prototype.concat = function(fields, separatorCharacter, autoTrim case db.DBTYPE_SQLSERVER2000: //MS SQL Server supports "concat_ws" (and ignoring null values) from version SQL Server 2017 and newer: //https://docs.microsoft.com/de-de/sql/t-sql/functions/concat-ws-transact-sql?view=sql-server-2017 - concatSql = " + "; break; case db.DBTYPE_DERBY10: break; @@ -689,10 +743,10 @@ SqlUtils.getSingleColumnType = function(fieldOrTableName, columnName, alias) { } else if (fieldVarType != "object") { throw new TypeError(translate.text("${SQL_LIB_WRONG_FIELD_TYPE}")); } - + if (fieldOrTableName.hasOwnProperty("length")) { if (fieldOrTableName.length == 2) { - + } else { throw new TypeError(translate.text("${SQL_LIB_WRONG_FIELD_TYPE}")) } @@ -714,539 +768,25 @@ SqlUtils.getSingleColumnType = function(fieldOrTableName, columnName, alias) { alias = db.getCurrentAlias(); return db.getColumnTypes(tableName, [columnName], alias)[0]; -} - -/** - *Class containing utilities for SQL - *@deprecated use SqlMaskingUtils - *@todo: shift to newer objects or remove - *@class - */ -function LegacySqlUtils() -{ - var that = this; - /** - * builds a condition out of multiple conditions - * - * @param {Array} pArray req Array containing the conditions - * @param {String} pOperator req Operator that concatenates the conditions (AND/OR) - * - * @return {String} concatenated Condition - */ - this.concatConditions = function(pArray, pOperator) - { - var resultCondition = ""; - - for(var i = 0; i < pArray.length; i++) - { - if(pArray[i] != null && pArray[i] != '') - { - if(resultCondition.length > 0) - resultCondition += (" " + pOperator + " "); - - resultCondition += pArray[i]; - } - } - - return resultCondition; - } - /** - * Checks if a new entry already exists - * - * @param {String} pTable req Databasetable(z.B. "comm") - * @param {Array} pColumns req colums, like sqlInsert - * @param {Array} pTypes req die datatypes, like sqlInsert - * @param {Array} pValues req values, like sqlInsert - * @param {Array} pExcludeFields opt columns, that should not be checked - * @param {String} pAlias opt Database alias - * - * @return {Integer} - */ - this.isDuplicat = function(pTable, pColumns, pTypes, pValues, pExcludeFields, pAlias) - { - var col = new Array(); - var typ = new Array(); - var val = new Array(); - var excludefields = ["DATE_NEW" ,"DATE_EDIT" ,"USER_NEW" ,"USER_EDIT", "KEYVALUE", "KEYSORT", pTable.toUpperCase() + "ID"]; - - if(pExcludeFields != undefined) - excludefields = excludefields.concat(pExcludeFields); - if(pAlias == undefined) - pAlias = vars.getString("$sys.dbalias"); - - for(var i = 0; i < pColumns.length; i++) - { - if(!hasElement(excludefields, pColumns[i], true) && pValues[i] != "" && pTypes[i] != SQLTYPES.LONGVARCHAR && pTypes[i] != SQLTYPES.CLOB) - { - col.push(pColumns[i]); - typ.push(pTypes[i]); - val.push(pValues[i]); - } - } - var count = db.getRowCount(pTable, col, typ, val, pAlias); - return count; - } - - /** - * returns the day of a date - * - * @param {Datetime} pDate req the date - * @param {String} pAlias req database alias - * - * @return {String} - */ - this.dayFromDate = function(pDate, pAlias) - { - var usedAlias = pAlias; - - if(pAlias == undefined) - usedAlias = vars.getString("$sys.dbalias"); - - var dbAlias = db.getDatabaseType(usedAlias); - var string = ""; - - switch(Number(dbAlias)) - { - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - string = "to_char(" + pDate + ",'dd')"; - break; - case db.DBTYPE_DERBY10: - case db.DBTYPE_SQLSERVER2000: - case db.DBTYPE_MYSQL4: - case db.DBTYPE_MARIADB10: - string = "DAY(" + pDate + ")"; - break; - case db.DBTYPE_POSTGRESQL8: - string = "EXTRACT (DAY from " + pDate + ")"; - break; - } - return string; - } - /** - * returns the month of a date - * - * @param {Datetime} pDate req the date - * @param {String} pAlias req database alias - * - * @return {String} - */ - this.monthFromDate = function(pDate, pAlias) - { - var usedAlias = pAlias; - if(pAlias == undefined) - usedAlias = vars.getString("$sys.dbalias"); - - var dbAlias = db.getDatabaseType(usedAlias); - var string = ""; - - switch(Number(dbAlias)) - { - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - string = "to_char(" + pDate + ",'MM')"; - break; - case db.DBTYPE_DERBY10: - case db.DBTYPE_SQLSERVER2000: - case db.DBTYPE_MYSQL4: - case db.DBTYPE_MARIADB10: - string = "MONTH(" + pDate + ")"; - break; - case db.DBTYPE_POSTGRESQL8: - string = "EXTRACT (MONTH FROM " + pDate + ")"; - break; - } - return string; - } - /** - * returns the year of a date - * - * @param {Datetime} pDate req the date - * @param {String} pAlias req database alias - * - * @return {String} - */ - this.yearFromDate = function(pDate, pAlias) - { - var usedAlias = pAlias; - if(pAlias == undefined) - usedAlias = vars.getString("$sys.dbalias"); - - var dbAlias = db.getDatabaseType(usedAlias); - var string = ""; - - switch(Number(dbAlias)) - { - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - string = "to_char(" + pDate + ",'yyyy')"; - break; - case db.DBTYPE_DERBY10: - case db.DBTYPE_SQLSERVER2000: - case db.DBTYPE_MYSQL4: - case db.DBTYPE_MARIADB10: - string = "YEAR(" + pDate + ")"; - break; - case db.DBTYPE_POSTGRESQL8: - string = "EXTRACT (YEAR FROM " + pDate + ")"; - break; - } - return string; - } - /** - * returns the function for current date depending on database - * - * @return {String} expression - */ - this.currentDate = function() - { - var dbtype = db.getDatabaseType(vars.getString("$sys.dbalias")); - var expression = ""; - - switch (Number(dbtype)) - { - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - case db.DBTYPE_DERBY10: - expression = "CURRENT_DATE"; - break; - case db.DBTYPE_SQLSERVER2000: - expression = "GETDATE()"; - break; - case db.DBTYPE_MYSQL4: - case db.DBTYPE_MARIADB10: - expression = "NOW()"; - break; - } - return expression; - } - /** - * returns the current search string incl placeholders - * - * @param {String} pfield req the search field - * @param {String} pfind req the search string - * @param {String} pIgnoreCase opt (true/false) - * @param {String} pPlaceHolder opt (Platzhalter config) - * - * @return {String} - */ - this.getPlacerholderCondition = function( pfield, pfind, pIgnoreCase, pPlaceHolder ) - { - var user = tools.getCurrentUser(); - var IgCa; - var PlHo; - - //wenn optoinal IgnoreCase und PlaceHolder vorhanden, dann diese verwenden - if(pIgnoreCase != undefined) - IgCa = pIgnoreCase; - else - IgCa = user[tools.PARAMS][tools.SELECTION_IGNORECASE]; - - if(pPlaceHolder != undefined) - PlHo = pPlaceHolder; - else - PlHo = user[tools.PARAMS][tools.SELECTION_PLACEHOLDER]; - - if ( pfind ) - { - pfind = pfind.replace( new RegExp("\\'", "g"), "''"); - pfind = pfind.replace( new RegExp("\\*", "g"), "%"); - var ic = (IgCa == "true" ? "UPPER" : ""); - var cond = ""; - switch( PlHo ) - { - case "1": - cond = ic + "(" + pfield + ") like " + ic + "('" + pfind + "%')"; - break; - case "2": - cond = ic + "(" + pfield + ") like " + ic + "('%" + pfind + "')"; - break; - case "3": - cond = ic + "(" + pfield + ") like " + ic + "('%" + pfind + "%')"; - break; - case "4": - cond = ic + "(" + pfield + ") like " + ic + "('" + pfind + "')"; - break; - default: - cond = ic + "(" + pfield + ") = " + ic + "('" + pfind + "')"; - break; - } - } - return cond; - } - /** - * returns SQLSystax for a date. - * - * @param {String} pColumn req Column name - * @param {String} pAlias opt Database alias - * @param {Boolean} pWithTime opt if true, then add time hh:mm:ss - * @param {String} pFormat opt type of the format, e.g. yyyy-MM-dd; possible placeholers are: -dd -MM -yyyy - * - *@return {String} sqlstr, fully functional select for sql for different types of databases - */ - this.getSqlFormattedDate = function(pColumn, pAlias, pWithTime, pFormat) - { - if(pAlias == undefined) - pAlias = vars.getString("$sys.dbalias"); - - var pDatabaseType = db.getDatabaseType(pAlias); - - if (pFormat == undefined) - pFormat = translate.text("yyyy-MM-dd"); - - var str = ""; - - switch(Number(pDatabaseType)) - { - case db.DBTYPE_SQLSERVER2000: - day = "right('0' + cast(day(" + pColumn + ") as varchar(2)) , 2)"; - month = "right('0' + cast(month(" + pColumn + ") as varchar(2)) , 2)"; - year = "cast(year(" + pColumn + ") as char(4))"; - time = pWithTime == true? that.concat(["' '","cast(cast(" + pColumn + " as time) as char(8))"], "", pAlias) : ""; - break; - case db.DBTYPE_POSTGRESQL8: - day = "extract(day from " + pColumn + ")"; - month = "extract(month from " + pColumn + ")"; - year = "extract(year from " + pColumn + ")"; - time = pWithTime == true? that.concat(["' '","extract(time from" + pColumn + ")"], "", pAlias) : ""; - break; - case db.DBTYPE_DERBY10: - case db.DBTYPE_MYSQL4: - case db.DBTYPE_MARIADB10: - // concat will try to have a leading blank space if the number is => 10. This is why we had to use substr. - day = that.substring(that.concat(["case when day(" + pColumn + ") <= 9 then '00' else '0' end " - , " trim(cast(day(" + pColumn + ") as char(2)))"], "", pAlias), 2, 2, pAlias); - month = that.substring(that.concat(["case when month(" + pColumn + ") <= 9 then '00' else '0' end " - , "trim(cast(month(" + pColumn + ") as char(2)))"], "", pAlias), 2, 2, pAlias); - year = "trim(cast(year(" + pColumn + ") as char(4)))"; - time = pWithTime == true? that.concat(["cast(' ' as char(1))", "trim(cast(time(" + pColumn + ") as char(8)))"], "", pAlias) : ""; - break; - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_OCI: - case db.DBTYPE_ORACLE10_THIN: - - day = "to_char(" + pColumn + ", 'dd') "; - month = "to_char(" + pColumn + ", 'MM') "; - year = "to_char(" + pColumn + ", 'yyyy') "; - time = pWithTime == true ? " to_char(" + pColumn + ", ' hh24:mi:ss')" : ""; - break; - default: - str = "cast(" + pColumn + " as varchar (10))"; - return str; - break; - } - - var re = /(dd)|(MM)|(yyyy)/g // Regex to check the date - var matchResult; - var endOfLastMatch = 0; - var res = []; - - while ((matchResult = re.exec(pFormat)) !== null) - { - if( endOfLastMatch != matchResult.index) - { - res.push("'" + db.quote(pFormat.substring(endOfLastMatch, matchResult.index), pAlias) + "'"); // making sure we get the correct amount of quotations - } - switch(matchResult[0]) - { - case "dd": - res.push(day); - break; - case "MM": - res.push(month); - break; - case "yyyy": - res.push(year); - break; - } - endOfLastMatch = re.lastIndex; - } - // making sure we get the correct amount of quotations - // allows us to add custom strings behind the format which will be shown in the output - // e.g. "yyyy-MM-dd 00:00", "date: MM/dd/yyyy" - res.push("'" + db.quote(pFormat.slice(endOfLastMatch), pAlias) + "'"); - - if(time != "") - res.push(time); - - str = concat(res, "", pAlias); - - return str; - } - /** - * returns a SQL operator depending on an integer value, i.e. $local.operator - * - * @param {int} pVal - * - * @return {string} - */ - this.getSQLOperator = function(pVal) - { - var retval = ""; - switch(Number(pVal)) - { - case 1: - retval = "="; - break; //equals - case 2: - retval = "<>"; - break; //not equal - case 3: - retval = ">"; - break; //greater - case 4: - retval = "<"; - break; //lesser - case 5: - retval = "<="; - break; //lesser or equal - case 6: - retval = ">="; - break; //greater or equal - case 7: - retval = "like"; - break; //contains - case 8: - retval = "not like"; - break; //contains not - case 9: - retval = ""; - break; - case 10: - retval = ""; - break; - case 11: - retval = "is not null"; - break; - case 12: - retval = "is null"; - break; - } - return retval; - } - /** - * returns the function which determines the length of binary data, depending on db type - * - * @param {String} pField name of the checked field - * - * @return {String} - */ - this.binDataLength = function(pField) - { - var dbtype = db.getDatabaseType(vars.getString("$sys.dbalias")); - var length; - - switch(Number(dbtype)) - { - case db.DBTYPE_MARIADB10: - case db.DBTYPE_MYSQL4: - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - case db.DBTYPE_POSTGRESQL8: - case db.DBTYPE_DERBY10: - length = "LENGTH("+pField+")"; - break; - case db.DBTYPE_SQLSERVER2000: - length = "DATALENGTH("+pField+")"; - break; - } - return length; - } - - /** - * returns the concat symbol depending on database type - * - * @param {String} pAlias opt database alias - * - * @return {String} Concat Symbol - */ - this.getConcatSymbol = function(pAlias) - { - if(pAlias == undefined || pAlias == "") - pAlias = vars.getString("$sys.dbalias"); - - var dbtype = db.getDatabaseType(pAlias); - var concatSymbol = " "; - - switch(Number(dbtype)) - { - case db.DBTYPE_SQLSERVER2000: - concatSymbol = " + "; - break; - case db.DBTYPE_MARIADB10: - case db.DBTYPE_MYSQL4: - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - case db.DBTYPE_POSTGRESQL8: - case db.DBTYPE_DERBY10: - default: - concatSymbol = " || "; - break; - } - - return concatSymbol; - } - /** - * 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.RELATIONID - * @param {String[]|String[][]} pData req Data as ID Array - * @param {String} pQuoteSymbol opt symbol for quoting values, - * Strings i.e.: ' default is no symbol - * - * @return {String} SQL condition: where VALS in (1,2,3) - */ - this.getSqlInStatement = function(pFieldname, pData, pQuoteSymbol) - { - if (pData.length == 0) - return " 1 = 2 "; - - var res = ""; - var qs = pQuoteSymbol || ""; - - var MAX_COUNT = 1000; - //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 - //<= verwenden, da bei einer Länge von "126" der Vorgang einmal ausgeführt werden soll - for (var i = 0; i <= count; i++) - { - if (i > 0) - res += "or "; - - res += pFieldname + " in (" + qs + pData.slice(i * MAX_COUNT, i * MAX_COUNT + MAX_COUNT) - .join(qs + ", " + qs) + qs + ") "; - } - - //wenn mehrere Zeilen mit "or" verknüpft wurden nochmal klammern - if (count > 0) - res = "(" + res + ")"; - - return res; - } +}; +//scope for internal functions; +//it's extremly important that the semicolon of the function expression above is correctly set because otherwise the function is called immediately +(function(){ /** * 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} pSql req sql statement that shall be executed + * @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} pBlockSize req Amount of records that shall be read per block. (you need to specify an ORDER BY in your SQL-query) + * @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 {Object (function)} pCallback req a callback-function that is called for every block and has the following params: + * @param {Object (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} pDbAlias opt Database-Aliasname, where the SQL-Statement shall be executed; default is the current dbalias - * @param {Number} pTimeout opt Timeout in milliseconds; When it's reached the SQL-Statement will abort; default is in PREFERENCES configured - * @param {Number} pStartOffset opt Position where to begin with the data-reading-process; default is 0 + * @param {String} [dbAlias=the 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 {bool} returns whether the function read all available data or not: @@ -1284,36 +824,114 @@ function LegacySqlUtils() * logging.show(letValues);//contains orgnames * logging.show(varValues);//contains orgnames */ - this.sqlPageData = function(pSql, pBlockSize, pCallback, pDbAlias, pTimeout, pStartOffset) - { - if (pDbAlias == undefined) - pDbAlias = db.getCurrentAlias(); + SqlUtils.pageTableData = function(sqlStatement, blockSize, callbackFn, dbAlias, timeout, startOffset) { + return _pageData(null, sqlStatement, blockSize, callbackFn, dbAlias, timeout, startOffset); + }; - if (pStartOffset == undefined) - pStartOffset = 0; - - let count = 0; - while (pStartOffset > -1) - { - let data; - if (pTimeout == undefined) - data = db.tablePage(pSql, pDbAlias, pStartOffset, pBlockSize); - else - data = db.tablePage(pSql, pDbAlias, pStartOffset, pBlockSize, pTimeout); + /** + * 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 {Object (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=the 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 {bool} 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) { + return _pageData(db.COLUMN, sqlStatement, blockSize, callbackFn, dbAlias, timeout, startOffset); + }; + + //internal function for paging through data; for description take a look at sqlArrayPageData + function _pageData(sqlType ,sqlStatement, blockSize, callbackFn, dbAlias, timeout, startOffset){ + if (dbAlias == undefined) + dbAlias = db.getCurrentAlias(); + if (startOffset == undefined) + startOffset = 0; + + var count = 0; + while (startOffset > -1) { + var 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); + } - pStartOffset += pBlockSize; + startOffset += blockSize; - //this happens when all-records % pBlockSize == 0 + //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 < pBlockSize || pBlockSize == 0)//blocksize 0 is everything - pStartOffset = -1;//call callback the last time + else if (data.length < blockSize || blockSize == 0)//blocksize 0 is everything + startOffset = -1;//call callback the last time - if (pCallback.call(this, data, ++count) === false) + if (callbackFn.call(this, data, ++count) === false) return false;//callback can return false to manually stop the paging-process - } return true; } +})(); + + + +/** + * 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.RELATIONID + * @param {String[]|String[][]} pData req Data as ID Array + * @param {String} pQuoteSymbol opt symbol for quoting values, + * Strings i.e.: ' default is no symbol + * + * @return {String} SQL condition: where VALS in (1,2,3) + */ +this.getSqlInStatement = function(pFieldname, pData, pQuoteSymbol) +{ + if (pData.length == 0) + return " 1 = 2 "; + + var res = ""; + var qs = pQuoteSymbol || ""; + + var MAX_COUNT = 1000; + //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 + //<= verwenden, da bei einer Länge von "126" der Vorgang einmal ausgeführt werden soll + for (var i = 0; i <= count; i++) + { + if (i > 0) + res += "or "; + + res += pFieldname + " in (" + qs + pData.slice(i * MAX_COUNT, i * MAX_COUNT + MAX_COUNT) + .join(qs + ", " + qs) + qs + ") "; + } + + //wenn mehrere Zeilen mit "or" verknüpft wurden nochmal klammern + if (count > 0) + res = "(" + res + ")"; + + return res; } diff --git a/process/Util_lib/process.js b/process/Util_lib/process.js index ace960b642d..51cbe5d0afd 100644 --- a/process/Util_lib/process.js +++ b/process/Util_lib/process.js @@ -452,35 +452,3 @@ function JDitoUtils() return dbAliases; } } - - -/** - * Class containing String utility functions - * @class - * @deprecated - * @todo: remove this funciton - */ -function StringUtils(){} -{ - - /** - * uses the right translate method, depending on the parameters - * - * @param {String} pText string to be translated - * @param {String} pLocale locale for translating - * - * @return {String} - * - * - */ - this.translateStr = function( pText, pLocale ) - { - if ( pLocale == undefined ) - return translate.text(pText); - else - return translate.text(pText, pLocale) - } - - -} - -- GitLab