From 483ba038d65ba9214530138ee4752c79cee87ec1 Mon Sep 17 00:00:00 2001 From: RohitM-IN Date: Tue, 3 Jun 2025 15:23:11 +0530 Subject: [PATCH 1/2] bug: Fixed when the field and value is swapped devextreme wont handle it properly --- package.json | 4 ++-- src/core/converter.js | 4 ++-- src/core/parser.js | 18 ++++++++++++++++++ tests/parser.test.js | 20 ++++++++++++++++++++ 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index a794f72..e8b30eb 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "sqlparser-devexpress", - "version": "2.3.17", + "version": "2.3.18", "main": "src/index.js", "type": "module", "scripts": { - "test": "vitest" + "test": "vitest run" }, "exports": { "import": "./src/index.js", diff --git a/src/core/converter.js b/src/core/converter.js index 5ca3651..c4f2834 100644 --- a/src/core/converter.js +++ b/src/core/converter.js @@ -139,9 +139,9 @@ function DevExpressConverter() { } const left = ast.left !== undefined ? processAstNode(ast.left) : convertValue(ast.field); - const leftDefault = ast.left?.args[1]?.value; + const leftDefault = ast.left?.args && ast.left?.args[1]?.value; const right = ast.right !== undefined ? processAstNode(ast.right) : convertValue(ast.value); - const rightDefault = ast.right?.args[1]?.value; + const rightDefault = ast.right?.args && ast.right?.args[1]?.value; let operatorToken = ast.operator.toLowerCase(); let includeExtradata = false; diff --git a/src/core/parser.js b/src/core/parser.js index 9bbc6f7..f0873e1 100644 --- a/src/core/parser.js +++ b/src/core/parser.js @@ -140,6 +140,19 @@ export function parse(input, variables = []) { // Recursively parse the right-hand expression with adjusted precedence const right = parseExpression(OPERATOR_PRECEDENCE[operator]); left = { type: "logical", operator, left, right }; + } else if (currentToken?.type == "identifier") { + const right = parseValue(operator); + let newOp = operator; + if (operator === '>') newOp = '<'; + else if (operator === '<') newOp = '>'; + else if (operator === '>=') newOp = '<='; + else if (operator === '<=') newOp = '>='; + left = { + type: "comparison", + right: left, + operator: newOp, + left: { type: "field", value: right } + }; } } @@ -218,6 +231,11 @@ export function parse(input, variables = []) { throw new Error(`Invalid comparison: ${field} ${operator} ${value}`); } + // Swap the field and value if the field is a placeholder and the value is an identifier + if (valueType == "identifier" && fieldType == "placeholder") { + return { type: "comparison", value: field, operator, field: value, originalOperator }; + } + return { type: "comparison", field, operator, value, originalOperator }; } diff --git a/tests/parser.test.js b/tests/parser.test.js index 80cdc43..8657290 100644 --- a/tests/parser.test.js +++ b/tests/parser.test.js @@ -268,6 +268,26 @@ describe("Parser SQL to dx Filter Builder", () => { { input: "ID IN ({SaleOrderStatusStmtGlobalRpt.RegionID})", expected: [] + }, + { + input: "10 < ID AND ApplicableUoms IN ({WorkOrderLine.ApplicableUoms})", + expected: [ + ["ID", ">", 10], + "and", + [ + ["ApplicableUoms", "=", "UOM1"], + "or", + ["ApplicableUoms", "=", "UOM2"], + "or", + ["ApplicableUoms", "=", "UOM3"] + ] + ], + }, + { + input: "{ServiceOrderDocument.SourceID} = ID", + expected: [ + "ID", "=", 2 + ] } ]; From 671268ce3946bcf80f2fed76cbe7998d8c8d3b75 Mon Sep 17 00:00:00 2001 From: RohitM-IN Date: Tue, 3 Jun 2025 16:55:04 +0530 Subject: [PATCH 2/2] Fixed Operators Not Inverting when in reverse order --- package.json | 2 +- src/core/parser.js | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index e8b30eb..97c1d88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sqlparser-devexpress", - "version": "2.3.18", + "version": "2.3.19", "main": "src/index.js", "type": "module", "scripts": { diff --git a/src/core/parser.js b/src/core/parser.js index f0873e1..d2afc5b 100644 --- a/src/core/parser.js +++ b/src/core/parser.js @@ -142,15 +142,12 @@ export function parse(input, variables = []) { left = { type: "logical", operator, left, right }; } else if (currentToken?.type == "identifier") { const right = parseValue(operator); - let newOp = operator; - if (operator === '>') newOp = '<'; - else if (operator === '<') newOp = '>'; - else if (operator === '>=') newOp = '<='; - else if (operator === '<=') newOp = '>='; + let newOperator = inverseOperator(operator); + left = { type: "comparison", right: left, - operator: newOp, + operator: newOperator, left: { type: "field", value: right } }; } @@ -233,7 +230,8 @@ export function parse(input, variables = []) { // Swap the field and value if the field is a placeholder and the value is an identifier if (valueType == "identifier" && fieldType == "placeholder") { - return { type: "comparison", value: field, operator, field: value, originalOperator }; + let newOperator = inverseOperator(operator); + return { type: "comparison", value: field, operator: newOperator, field: value, originalOperator }; } return { type: "comparison", field, operator, value, originalOperator }; @@ -242,6 +240,16 @@ export function parse(input, variables = []) { return { type: "field", value: field }; } + function inverseOperator(operator) { + switch (operator.toUpperCase()) { + case ">": return "<"; + case "<": return ">"; + case ">=": return "<="; + case "<=": return ">="; + default: return operator; // Return the operator as is if no inverse is defined + } + } + // Parses values including numbers, strings, placeholders, and IN lists function parseValue(operatorToken) { if (!currentToken) throw new Error("Unexpected end of input");