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 +1 -1
- package/src/@types/core/converter.d.ts +1 -0
- package/src/@types/default.d.ts +2 -0
- package/src/core/converter.js +19 -4
- package/src/debug.js +1 -1
- package/src/index.js +2 -2
- package/tests/parser.test.js +37 -1
package/package.json
CHANGED
package/src/@types/default.d.ts
CHANGED
|
@@ -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;
|
package/src/core/converter.js
CHANGED
|
@@ -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
|
|
package/tests/parser.test.js
CHANGED
|
@@ -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);
|