sqlparser-devexpress 2.3.15 → 2.3.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sqlparser-devexpress",
3
- "version": "2.3.15",
3
+ "version": "2.3.17",
4
4
  "main": "src/index.js",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -10,6 +10,7 @@ export interface ConvertOptions {
10
10
  ast: ASTNode;
11
11
  resultObject?: ResultObject;
12
12
  enableShortCircuit?: boolean;
13
+ isValueNullShortCircuit?: boolean;
13
14
  }
14
15
 
15
16
  /**
@@ -32,10 +32,12 @@ export function convertSQLToAst(filterString: string, enableConsoleLogs?: boolea
32
32
  * @param ast - The parsed AST from `convertSQLToAst`.
33
33
  * @param state - An optional result object to resolve placeholders to actual values.
34
34
  * @param enableShortCircuit - Whether to apply short-circuit evaluation.
35
+ * @param isValueNullShortCircuit - Whether to treat null values as short-circuit conditions.
35
36
  * @returns DevExpressFilter - The DevExpress-compatible filter array or null.
36
37
  */
37
38
  export function convertAstToDevextreme(
38
39
  ast: ASTNode,
39
40
  state?: ResultObject | null,
40
41
  enableShortCircuit?: boolean,
42
+ isValueNullShortCircuit?: boolean
41
43
  ): DevExpressFilter;
@@ -8,6 +8,7 @@ function DevExpressConverter() {
8
8
  // Global variables accessible throughout the converter
9
9
  let resultObject = null;
10
10
  let EnableShortCircuit = true;
11
+ let IsValueNullShortCircuit = false; // Flag to enable/disable null short-circuiting
11
12
 
12
13
  /**
13
14
  * Main conversion function that sets up the global context
@@ -16,10 +17,11 @@ function DevExpressConverter() {
16
17
  * @param {boolean} enableShortCircuit - Optional enabling and disabling the shortcircuit ie evaluating value = value scenario
17
18
  * @returns {Array|null} DevExpress format filter
18
19
  */
19
- function convert(ast, ResultObject = null, enableShortCircuit = true) {
20
+ function convert(ast, ResultObject = null, enableShortCircuit = true, isValueNullShortCircuit = false) {
20
21
  // Set up global context
21
22
  resultObject = ResultObject;
22
23
  EnableShortCircuit = enableShortCircuit;
24
+ IsValueNullShortCircuit = isValueNullShortCircuit;
23
25
 
24
26
  // Process the AST
25
27
  let result = processAstNode(ast);
@@ -89,6 +91,7 @@ function DevExpressConverter() {
89
91
  const left = processAstNode(ast.left, operator);
90
92
  const right = processAstNode(ast.right, operator);
91
93
 
94
+
92
95
  if (EnableShortCircuit) {
93
96
  // Short-circuit: always-true conditions
94
97
  if (left === true || right === true) {
@@ -100,7 +103,6 @@ function DevExpressConverter() {
100
103
  if (left === false || right === false) {
101
104
  return left === false ? right : left;
102
105
  }
103
-
104
106
  }
105
107
 
106
108
  // Detect and flatten nested logical expressions
@@ -165,6 +167,10 @@ function DevExpressConverter() {
165
167
  }
166
168
 
167
169
  // Apply short-circuit evaluation if enabled
170
+ if (EnableShortCircuit && IsValueNullShortCircuit && (left == null || right == null)) {
171
+ return true; // If either value is null, return true for short-circuit evaluation
172
+ }
173
+
168
174
  if (EnableShortCircuit) {
169
175
  if (isAlwaysTrue(comparison, leftDefault, rightDefault)) return true;
170
176
  if (isAlwaysFalse(comparison, leftDefault, rightDefault)) return false;
@@ -242,6 +248,10 @@ function DevExpressConverter() {
242
248
  }
243
249
  }
244
250
 
251
+ if (EnableShortCircuit && IsValueNullShortCircuit && (ast.field?.type === "placeholder" || ast.value?.type === "placeholder" || ast.value === null) && resolvedValue === null) {
252
+ return true;
253
+ }
254
+
245
255
  let operatorToken = operator === "IN" ? '=' : operator === "NOT IN" ? '!=' : operator;
246
256
  let joinOperatorToken = operator === "IN" ? 'or' : operator === "NOT IN" ? 'and' : operator;
247
257
  let field = convertValue(ast.field);
@@ -410,6 +420,10 @@ function DevExpressConverter() {
410
420
 
411
421
  if ((left !== null && isNaN(left)) || (right !== null && isNaN(right))) return null;
412
422
 
423
+ // Handle NULL == 0 OR NULL == "" cases
424
+ if (left === null && (right == 0 || right == "")) return true;
425
+ if (right === null && (left == 0 || left == "")) return true;
426
+
413
427
  if (left === null || right === null) {
414
428
  if (operator === '=' || operator === '==') return left === right;
415
429
  if (operator === '<>' || operator === '!=') return left !== right;
@@ -439,8 +453,9 @@ const devExpressConverter = DevExpressConverter();
439
453
  * @param {Object} ast - The abstract syntax tree
440
454
  * @param {Object} resultObject - Optional object for placeholder resolution
441
455
  * @param {string} enableShortCircuit - Optional enabling and disabling the shortcircuit ie evaluating value = value scenario
456
+ * @param {boolean} isValueNullShortCircuit - Optional enabling and disabling the null shortcircuit ie evaluating value = null scenario
442
457
  * @returns {Array|null} DevExpress format filter
443
458
  */
444
- export function convertToDevExpressFormat({ ast, resultObject = null, enableShortCircuit = true }) {
445
- return devExpressConverter.init(ast, resultObject, enableShortCircuit);
459
+ export function convertToDevExpressFormat({ ast, resultObject = null, enableShortCircuit = true, isValueNullShortCircuit = false }) {
460
+ return devExpressConverter.init(ast, resultObject, enableShortCircuit, isValueNullShortCircuit);
446
461
  }
package/src/debug.js CHANGED
@@ -25,7 +25,7 @@
25
25
  // const astTree = parsedResult.ast;
26
26
  // console.log("AST Tree:", JSON.stringify(astTree, null, 2), "\n");
27
27
 
28
- // return convertToDevExpressFormat({ ast: astTree, resultObject: sampleData });
28
+ // return convertToDevExpressFormat({ ast: astTree, resultObject: sampleData, isValueNullShortCircuit: true });
29
29
  // }
30
30
 
31
31
  // const devexpress = parseFilterString("(ISNULL(TicketID, 0) = ISNULL({CustomerOrders.OrderID}, 0))", sampleData);
package/src/index.js CHANGED
@@ -16,8 +16,8 @@ export function convertSQLToAst(filterString, enableConsoleLogs = false) {
16
16
  return parsedResult;
17
17
  }
18
18
 
19
- export function convertAstToDevextreme(ast, state = null, enableShortCircuit = true) {
20
- return convertToDevExpressFormat({ ast, resultObject: state, enableShortCircuit })
19
+ export function convertAstToDevextreme(ast, state = null, enableShortCircuit = true, isValueNullShortCircuit = false) {
20
+ return convertToDevExpressFormat({ ast, resultObject: state, enableShortCircuit, isValueNullShortCircuit })
21
21
  }
22
22
 
23
23
 
@@ -232,6 +232,42 @@ describe("Parser SQL to dx Filter Builder", () => {
232
232
  "or",
233
233
  ["CompanyID", "!=", 8, { "type": "IS NOT" }, 8]
234
234
  ]
235
+ },
236
+ {
237
+ input: "null = 0",
238
+ expected: []
239
+ },
240
+ {
241
+ input: "null = null",
242
+ expected: []
243
+ },
244
+ {
245
+ input: "null = {SaleOrderStatusStmtGlobalRpt.StateID}",
246
+ expected: []
247
+ },
248
+ {
249
+ input: "null = {SaleOrderStatusStmtGlobalRpt.RegionID}",
250
+ expected: []
251
+ },
252
+ {
253
+ input: "null = {LeadDocument.CompanyID}",
254
+ expected: []
255
+ },
256
+ {
257
+ input: "{LeadDocument.BranchID} = null",
258
+ expected: []
259
+ },
260
+ {
261
+ input: "{LeadDocument.AllowSubDealer} != null",
262
+ expected: []
263
+ },
264
+ {
265
+ input: "ID = {SaleOrderStatusStmtGlobalRpt.RegionID}",
266
+ expected: []
267
+ },
268
+ {
269
+ input: "ID IN ({SaleOrderStatusStmtGlobalRpt.RegionID})",
270
+ expected: []
235
271
  }
236
272
  ];
237
273
 
@@ -254,7 +290,7 @@ describe("Parser SQL to dx Filter Builder", () => {
254
290
  const variables = astwithVariables.variables;
255
291
  const ast = astwithVariables.ast;
256
292
 
257
- const result = convertAstToDevextreme(ast, sampleData);
293
+ const result = convertAstToDevextreme(ast, sampleData, true, true);
258
294
 
259
295
  if (result == null || result == true || result == false) {
260
296
  expect([]).toEqual(expected);