From 93d3b448dd34699b591cbe49cccbcdf2c43289bc Mon Sep 17 00:00:00 2001 From: RohitM-IN Date: Thu, 20 Mar 2025 12:42:53 +0530 Subject: [PATCH 1/3] temp fix bug causing dropdowns showing incorrect data --- package.json | 2 +- src/core/converter.js | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 93d3ce7..d1c3b88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sqlparser-devexpress", - "version": "2.3.7", + "version": "2.3.8", "main": "src/index.js", "type": "module", "scripts": { diff --git a/src/core/converter.js b/src/core/converter.js index 80f5bfe..75dd115 100644 --- a/src/core/converter.js +++ b/src/core/converter.js @@ -138,18 +138,19 @@ function DevExpressConverter() { const right = ast.right !== undefined ? processAstNode(ast.right) : convertValue(ast.value); let operatorToken = ast.operator.toLowerCase(); - if(operatorToken === "like") { + if (operatorToken === "like") { operatorToken = "contains"; - }else if (operatorToken === "not like") { + } else if (operatorToken === "not like") { operatorToken = "notcontains"; } let comparison = [left, operatorToken, right]; + //TODO: the ISNULL custom metadata is causing issues on filters will need to check this on server if ((ast.left && isFunctionNullCheck(ast.left, true)) || (ast.value && isFunctionNullCheck(ast.value, false))) { - comparison = [[left, operatorToken, right], 'or', [left, operatorToken, null, {type: "ISNULL", defaultValue: (ast.left ?? ast.value).args[1]?.value}]]; + comparison = [[left, operatorToken, right], 'or', [left, operatorToken, null,]];// {type: "ISNULL", defaultValue: (ast.left ?? ast.value).args[1]?.value}]]; } else if (ast.right && isFunctionNullCheck(ast.right, true)) { - comparison = [[left, operatorToken, right], 'or', [right, operatorToken, null, {type: "ISNULL", defaultValue: ast.right.args[1]?.value}]]; + comparison = [[left, operatorToken, right], 'or', [right, operatorToken, null,]];// {type: "ISNULL", defaultValue: ast.right.args[1]?.value}]]; } // Apply short-circuit evaluation if enabled @@ -229,8 +230,8 @@ function DevExpressConverter() { if (typeof val === "object") { if (val.type === "placeholder") { const placeholderValue = resolvePlaceholderFromResultObject(val.value); - - if(val?.dataType === "string"){ + + if (val?.dataType === "string") { return placeholderValue?.toString(); } From a3e24147f95c8119891c4e4e063387d8be7a1f9a Mon Sep 17 00:00:00 2001 From: RohitM-IN Date: Thu, 20 Mar 2025 15:21:35 +0530 Subject: [PATCH 2/3] Fix isnull Extra metadata ref: https://github.com/DevExpress/DevExtreme/blob/25_1/packages/devextreme/js/__internal/data/m_utils.ts#L18 --- package.json | 2 +- src/core/converter.js | 6 +++--- tests/parser.test.js | 16 +++++++--------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index d1c3b88..85fb78c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sqlparser-devexpress", - "version": "2.3.8", + "version": "2.3.9", "main": "src/index.js", "type": "module", "scripts": { diff --git a/src/core/converter.js b/src/core/converter.js index 75dd115..0271754 100644 --- a/src/core/converter.js +++ b/src/core/converter.js @@ -146,11 +146,11 @@ function DevExpressConverter() { let comparison = [left, operatorToken, right]; - //TODO: the ISNULL custom metadata is causing issues on filters will need to check this on server + // Last null because of special case when using dropdown it https://github.com/DevExpress/DevExtreme/blob/25_1/packages/devextreme/js/__internal/data/m_utils.ts#L18 it takes last value as null if ((ast.left && isFunctionNullCheck(ast.left, true)) || (ast.value && isFunctionNullCheck(ast.value, false))) { - comparison = [[left, operatorToken, right], 'or', [left, operatorToken, null,]];// {type: "ISNULL", defaultValue: (ast.left ?? ast.value).args[1]?.value}]]; + comparison = [[left, operatorToken, right], 'or', [left, operatorToken, null, { type: "ISNULL", defaultValue: (ast.left ?? ast.value).args[1]?.value }, null]]; } else if (ast.right && isFunctionNullCheck(ast.right, true)) { - comparison = [[left, operatorToken, right], 'or', [right, operatorToken, null,]];// {type: "ISNULL", defaultValue: ast.right.args[1]?.value}]]; + comparison = [[left, operatorToken, right], 'or', [right, operatorToken, null, { type: "ISNULL", defaultValue: ast.right.args[1]?.value }, null]]; } // Apply short-circuit evaluation if enabled diff --git a/tests/parser.test.js b/tests/parser.test.js index e8f849a..45fa2d7 100644 --- a/tests/parser.test.js +++ b/tests/parser.test.js @@ -137,11 +137,11 @@ describe("Parser SQL to dx Filter Builder", () => { expected: [ ["SourceID", "=", 2], "or", - ["SourceID", "=", null,{ "defaultValue": 0, "type": "ISNULL"}], + ["SourceID", "=", null, { "defaultValue": 0, "type": "ISNULL" }, null], "or", ["SourceID", "=", 0], "or", - ["SourceID", "=", null,{ "defaultValue": 0, "type": "ISNULL"}] + ["SourceID", "=", null, { "defaultValue": 0, "type": "ISNULL" }, null] ] }, { @@ -153,14 +153,14 @@ describe("Parser SQL to dx Filter Builder", () => { [ ["CompanyID", "=", 0], "or", - ["CompanyID", "=", null,{ "defaultValue": 0, "type": "ISNULL"}] + ["CompanyID", "=", null, { "defaultValue": 0, "type": "ISNULL" }, null] ] ], "and", [ ["IsSubdealer", "=", true], "or", - ["IsSubdealer", "=", null,{ "defaultValue": 0, "type": "ISNULL"}] + ["IsSubdealer", "=", null, { "defaultValue": 0, "type": "ISNULL" }, null] ] ] }, @@ -187,7 +187,7 @@ describe("Parser SQL to dx Filter Builder", () => { expected: [ ["TicketID", "=", 123], "or", - ["TicketID", "=", null,{ "defaultValue": 0, "type": "ISNULL"}] + ["TicketID", "=", null, { "defaultValue": 0, "type": "ISNULL" }, null] ] }, { @@ -195,14 +195,12 @@ describe("Parser SQL to dx Filter Builder", () => { expected: [ ["CompanyID", "=", 7], "or", - ["CompanyID", "=", null,{ "defaultValue": 0, "type": "ISNULL"}], + ["CompanyID", "=", null, { "defaultValue": 0, "type": "ISNULL" }, null], "or", ["CompanyID", "=", 0], "or", - ["CompanyID", "=", null,{ "defaultValue": 0, "type": "ISNULL"}, + ["CompanyID", "=", null, { "defaultValue": 0, "type": "ISNULL" }, null] - ] - ] }, { From ba7584ea02e0fa0cc3a8d4b3eb2a10d5120878a4 Mon Sep 17 00:00:00 2001 From: RohitM-IN Date: Thu, 27 Mar 2025 17:52:37 +0530 Subject: [PATCH 3/3] Update ISNULL Check ShortCircuit and added tests for same --- package.json | 2 +- src/core/converter.js | 25 ++++++++++++++++++------- tests/parser.test.js | 8 +++++++- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 85fb78c..f6742aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sqlparser-devexpress", - "version": "2.3.9", + "version": "2.3.10", "main": "src/index.js", "type": "module", "scripts": { diff --git a/src/core/converter.js b/src/core/converter.js index 0271754..8724780 100644 --- a/src/core/converter.js +++ b/src/core/converter.js @@ -135,7 +135,9 @@ function DevExpressConverter() { } const left = ast.left !== undefined ? processAstNode(ast.left) : convertValue(ast.field); + const leftDefault = ast.left?.args[1]?.value; const right = ast.right !== undefined ? processAstNode(ast.right) : convertValue(ast.value); + const rightDefault = ast.right?.args[1]?.value; let operatorToken = ast.operator.toLowerCase(); if (operatorToken === "like") { @@ -155,8 +157,8 @@ function DevExpressConverter() { // Apply short-circuit evaluation if enabled if (EnableShortCircuit) { - if (isAlwaysTrue(comparison)) return true; - if (isAlwaysFalse(comparison)) return false; + if (isAlwaysTrue(comparison, leftDefault, rightDefault)) return true; + if (isAlwaysFalse(comparison, leftDefault, rightDefault)) return false; } return comparison; @@ -332,19 +334,23 @@ function DevExpressConverter() { /** * Checks if a condition is always true. * @param {Array} condition - The condition to check. + * @param {*} leftDefault - The default value for the left operand. + * @param {*} rightDefault - The default value for the right operand. * @returns {boolean} True if the condition is always true. */ - function isAlwaysTrue(condition) { - return Array.isArray(condition) && condition.length >= 3 && evaluateExpression(...condition) == true; + function isAlwaysTrue(condition, leftDefault, rightDefault) { + return Array.isArray(condition) && condition.length >= 3 && evaluateExpression(...condition, leftDefault, rightDefault) == true; } /** * Checks if a condition is always false. * @param {Array} condition - The condition to check. + * @param {*} leftDefault - The default value for the left operand. + * @param {*} rightDefault - The default value for the right operand. * @returns {boolean} True if the condition is always false. */ - function isAlwaysFalse(condition) { - return Array.isArray(condition) && condition.length >= 3 && evaluateExpression(...condition) == false; + function isAlwaysFalse(condition, leftDefault, rightDefault) { + return Array.isArray(condition) && condition.length >= 3 && evaluateExpression(...condition, leftDefault, rightDefault) == false; } /** @@ -352,9 +358,14 @@ function DevExpressConverter() { * @param {*} left - The left operand. * @param {string} operator - The operator. * @param {*} right - The right operand. + * @param {*} leftDefault - The default value for the left operand. + * @param {*} rightDefault - The default value for the right * @returns {boolean|null} The result of the evaluation or null if not evaluable. */ - function evaluateExpression(left, operator, right) { + function evaluateExpression(left, operator, right, leftDefault, rightDefault) { + if (left == null && leftDefault != undefined) left = leftDefault; + if (right == null && rightDefault != undefined) right = rightDefault; + if ((left !== null && isNaN(left)) || (right !== null && isNaN(right))) return null; if (left === null || right === null) { diff --git a/tests/parser.test.js b/tests/parser.test.js index 45fa2d7..a4cb4f3 100644 --- a/tests/parser.test.js +++ b/tests/parser.test.js @@ -210,6 +210,10 @@ describe("Parser SQL to dx Filter Builder", () => { "and", ["BranchName", "notcontains", "42"] ] + }, + { + input: "(RS2ID in ({SaleOrderStatusStmtGlobalRpt.StateID}) Or (ISNULL({SaleOrderStatusStmtGlobalRpt.StateID},0) =0)) And (RS3ID in (0,{SaleOrderStatusStmtGlobalRpt.RegionID}) Or ISNULL({SaleOrderStatusStmtGlobalRpt.RegionID},0) =0 )", + expected: [] } ]; @@ -270,5 +274,7 @@ const sampleData = { "LeadDocument.CompanyID": 7, "ServiceOrderDocument.SourceID": 2, "LeadDocument.AllowSubDealer": true, - "SupportResolution.TicketID": 123 + "SupportResolution.TicketID": 123, + "SaleOrderStatusStmtGlobalRpt.StateID": null, + "SaleOrderStatusStmtGlobalRpt.RegionID": null, }; \ No newline at end of file