Skip to content
Snippets Groups Projects
Commit fbe9107b authored by S.Listl's avatar S.Listl
Browse files

JditoFilter_lib: fix for boolean/number/date filters

parent 7ae208dc
No related branches found
No related tags found
No related merge requests found
......@@ -214,16 +214,163 @@ JditoFilterUtils.filterRecords = function (pColumns, pRecords, pFilter, pCustomC
*/
JditoFilterUtils.getSqlCondition = function (pFilter, pTable, pTableAlias, pColumnOrFnMap)
{
var condition = newWhere();
var filterTranslator = new FilterSqlTranslator(pFilter)
.table(pTable, pTableAlias);
var ignoreCase = JditoFilterUtils.isUserIgnoreCase();
if (!pFilter)
if (pColumnOrFnMap)
{
for (let fieldName in pColumnOrFnMap)
{
var columnOrFn = pColumnOrFnMap[fieldName];
if (typeof columnOrFn === "function")
filterTranslator.addSpecialFieldConditionFn(fieldName, columnOrFn);
else
filterTranslator.addSqlFieldMapping(fieldName, columnOrFn);
}
}
return filterTranslator.getSqlCondition();
}
/**
* @return {boolean} the selectionIgnoreCase property of the current user, defaults to true
*/
JditoFilterUtils.isUserIgnoreCase = function ()
{
var user = tools.getCurrentUser();
var ignoreCase = user ? user[tools.PARAMS][tools.SELECTION_IGNORECASE] : "";
return ignoreCase == "" || /true/i.test(ignoreCase);
}
/**
* Object for translating a filter object to a sql condition.
*
* @param {Object} pFilter the filter object that should be used
* @param {String} pTable the database table to build the condition for
*/
function FilterSqlTranslator (pFilter, pTable)
{
this._filter = null;
this.filter(pFilter);
this._table = pTable;
this._tableAlias = null;
this._dbAlias = null;
this._sqlFieldMappings = {};
this._fieldConditionFns = {};
this._ignoreCase = JditoFilterUtils.isUserIgnoreCase();
}
/**
* Sets the filter of the object
*
* @param {Object} pFilter the filter object that should be used
* @return {FilterSqlTranslator} current object
*/
FilterSqlTranslator.prototype.filter = function (pFilter)
{
if (pFilter)
{
if (typeof pFilter !== "object")
throw new TypeError("FilterSqlTranslator: Wrong type for the filter, expected 'object' but got '" + (typeof pFilter) + "'");
this._filter = pFilter.filter || pFilter;
}
return this;
}
/**
* Sets the filter of the object
*
* @param {String} pFilter the filter object that should be used as JSON string
* @return {FilterSqlTranslator} current object
*/
FilterSqlTranslator.prototype.filterJSON = function (pFilter)
{
return this.filter(JSON.parse(pFilter));
}
/**
* Sets the table of the object
*
* @param {String} pTable the database table to build the condition for
* @param {String} [pTableAlias] the alias of the table
* @return {FilterSqlTranslator} current object
*/
FilterSqlTranslator.prototype.table = function (pTable, pTableAlias)
{
this._table = pTable;
if (pTableAlias)
this._tableAlias = pTableAlias;
return this;
}
/**
* Adds a special database field mapping for the given field that will be used for the sql condition
*
* @param {String} pFieldName the field name
* @param {String|String[]} the database field ("TABLE.COLUMN" or ["TABLE", "COLUMN", "alias"])
* @return {FilterSqlTranslator} current object
*/
FilterSqlTranslator.prototype.addSqlFieldMapping = function (pFieldName, pDBField)
{
this._sqlFieldMappings[pFieldName] = pDBField;
return this;
}
/**
* Adds a special function for building the condition for the given field. The function must return a sql condition (SqlBuilder or String)
*
* @param {String} pFieldName the field name
* @param {Function} pConditionFn a function that generates the condition
* @return {FilterSqlTranslator} current object
*/
FilterSqlTranslator.prototype.addSpecialFieldConditionFn = function (pFieldName, pConditionFn)
{
this._fieldConditionFns[pFieldName] = pConditionFn;
return this;
}
/**
* Sets the database alias
*
* @param {String} pAlias the alias to be used
* @return {FilterSqlTranslator} current object
*/
FilterSqlTranslator.prototype.dbAlias = function (pAlias)
{
this._dbAlias = pAlias;
return this;
}
/**
* Changes whether the condition should be case-insensitive for text
*
* @param {boolean} [pIgnoreCase=true] if it should be case-insensitive
* @return {FilterSqlTranslator} current object
*/
FilterSqlTranslator.prototype.ignoreCase = function (pIgnoreCase)
{
//"", 0 , false -> false, everything else is considered true
this._ignoreCase = pIgnoreCase != false;
return this;
}
/**
* Builds the sql condition from the filter
*
* @return {SqlBuilder} the sql condition
*/
FilterSqlTranslator.prototype.getSqlCondition = function ()
{
var condition = new SqlBuilder(this._dbAlias).where();
if (!this._filter)
return condition;
if (!pColumnOrFnMap)
pColumnOrFnMap = {};
_addCondition.call(condition, pFilter, pFilter.operator);
var table = this._table;
var tableAlias = this._tableAlias;
var ignoreCase = this._ignoreCase;
var sqlFieldMappings = this._sqlFieldMappings;
var fieldConditionFns = this._fieldConditionFns;
_addCondition.call(condition, this._filter, this._filter.operator);
return condition;
......@@ -233,53 +380,55 @@ JditoFilterUtils.getSqlCondition = function (pFilter, pTable, pTableAlias, pColu
{
if (pFilter.type == "row")
{
var sqlField;
if (pFilter.name in pColumnOrFnMap)
var sqlField, condition;
var filterValue = (pFilter.key || pFilter.value);
if (pFilter.name in fieldConditionFns)
{
sqlField = pColumnOrFnMap[pFilter.name];
var conditionFn = fieldConditionFns[pFilter.name];
condition = conditionFn.call(null, filterValue, pFilter.operator);
if (pOperator == "AND")
this.andIfSet(condition);
else if (pOperator == "OR")
this.orIfSet(condition);
return;
}
if (pFilter.name in sqlFieldMappings)
{
sqlField = sqlFieldMappings[sqlField];
//possibility to explicitly set the value to null/false so that the field is ignored
if (sqlField === null || sqlField === false)
return;
}
else if (pTable && pTableAlias)
sqlField = [pTable, pFilter.name, pTableAlias];
else if (pTable)
sqlField = pTable + "." + pFilter.name;
else if (table && tableAlias)
sqlField = [table, pFilter.name, tableAlias];
else if (table)
sqlField = table + "." + pFilter.name;
var filterValue = (pFilter.key || pFilter.value);
var condition;
if (typeof(sqlField) === "function")
var generatedCondition = _getCondition(filterValue, pFilter.operator, sqlField);
if (generatedCondition instanceof SqlBuilder || typeof generatedCondition === "string")
{
condition = sqlField.call(null, filterValue, pFilter.operator);
if (pOperator == "AND")
this.andIfSet(condition);
this.andIfSet(generatedCondition);
else if (pOperator == "OR")
this.orIfSet(condition);
this.orIfSet(generatedCondition);
}
else
{
var generatedCondition = _getCondition(filterValue, pFilter.operator, sqlField);
if (generatedCondition instanceof SqlBuilder)
{
if (pOperator == "AND")
this.andIfSet(generatedCondition);
else if (pOperator == "OR")
this.orIfSet(generatedCondition);
}
else
{
var isStringType;
[condition, filterValue, isStringType] = generatedCondition;
if (isStringType && ignoreCase)
condition = condition.replace("#", "UPPER(#)").replace("?", "UPPER(?)");
var isStringType = pFilter.contenttype != "NUMBER"
&& pFilter.contenttype != "DATE"
&& pFilter.contenttype != "BOOLEAN";
[condition, filterValue] = generatedCondition;
if (isStringType && ignoreCase)
condition = condition.replace("#", "UPPER(#)").replace("?", "UPPER(?)");
if (pOperator == "AND")
this.andIfSet(sqlField, filterValue, condition);
else if (pOperator == "OR")
this.orIfSet(sqlField, filterValue, condition);
}
if (pOperator == "AND")
this.andIfSet(sqlField, filterValue, condition);
else if (pOperator == "OR")
this.orIfSet(sqlField, filterValue, condition);
}
}
else if (pFilter.type == "group")
......@@ -297,53 +446,41 @@ JditoFilterUtils.getSqlCondition = function (pFilter, pTable, pTableAlias, pColu
}
}
//returns [condition, value with wildcards, is a string type] depending on the operator
//returns [condition, value with wildcards] depending on the operator
function _getCondition (pValue, pOperator, pField)
{
switch (pOperator)
{
case "CONTAINS":
return [SqlBuilder.LIKE(), "%" + pValue + "%", true];
return [SqlBuilder.LIKE(), "%" + pValue + "%"];
case "CONTAINSNOT":
return [SqlBuilder.NOT_LIKE(), "%" + pValue + "%", true];
return [SqlBuilder.NOT_LIKE(), "%" + pValue + "%"];
case "STARTSWITH":
return [SqlBuilder.LIKE(), pValue + "%", true];
return [SqlBuilder.LIKE(), pValue + "%"];
case "ENDSWITH":
return [SqlBuilder.LIKE(), "%" + pValue, true];
return [SqlBuilder.LIKE(), "%" + pValue];
case "EQUAL":
return [SqlBuilder.EQUAL(), pValue, true];
return [SqlBuilder.EQUAL(), pValue];
case "NOT_EQUAL":
return [SqlBuilder.NOT_EQUAL(), pValue, true];
return [SqlBuilder.NOT_EQUAL(), pValue];
case "LESS":
return [SqlBuilder.LESS(), pValue, false];
return [SqlBuilder.LESS(), pValue];
case "LESS_OR_EQUAL":
return [SqlBuilder.LESS_OR_EQUAL(), pValue, false];
return [SqlBuilder.LESS_OR_EQUAL(), pValue];
case "GREATER":
return [SqlBuilder.GREATER(), pValue, false];
return [SqlBuilder.GREATER(), pValue];
case "GREATER_OR_EQUAL":
return [SqlBuilder.GREATER_OR_EQUAL(), pValue, false];
return [SqlBuilder.GREATER_OR_EQUAL(), pValue];
case "ISNULL":
return ["# is null", pValue, false];
return pField + " is null";
case "ISNOTNULL":
return ["# is not null", pValue, false];
return pField + " is not null";
case "TIMEFRAME_EQUAL":
case "TIMEFRAME_COMING":
case "TIMEFRAME_PAST":
var [start, end] = datetime.resolveRelativeDateExpression(pValue);
return newWhere(pField, start, SqlBuilder.GREATER_OR_EQUAL())
.and(pField, end, SqlBuilder.LESS_OR_EQUAL());
}
}
}
/**
* @return {boolean} the selectionIgnoreCase property of the current user, defaults to true
*/
JditoFilterUtils.isUserIgnoreCase = function ()
{
var user = tools.getCurrentUser();
var ignoreCase = user ? user[tools.PARAMS][tools.SELECTION_IGNORECASE] : "";
return ignoreCase == "" || /true/i.test(ignoreCase);
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment