Skip to content

Commit 5309215

Browse files
authored
Merge pull request #19 from RohitM-IN/development
Value = NULL added Short circuit optional change (#18)
2 parents 8e14faa + e67b39e commit 5309215

File tree

7 files changed

+31
-9
lines changed

7 files changed

+31
-9
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "sqlparser-devexpress",
3-
"version": "2.3.16",
3+
"version": "2.3.17",
44
"main": "src/index.js",
55
"type": "module",
66
"scripts": {

src/@types/core/converter.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface ConvertOptions {
1010
ast: ASTNode;
1111
resultObject?: ResultObject;
1212
enableShortCircuit?: boolean;
13+
isValueNullShortCircuit?: boolean;
1314
}
1415

1516
/**

src/@types/default.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@ export function convertSQLToAst(filterString: string, enableConsoleLogs?: boolea
3232
* @param ast - The parsed AST from `convertSQLToAst`.
3333
* @param state - An optional result object to resolve placeholders to actual values.
3434
* @param enableShortCircuit - Whether to apply short-circuit evaluation.
35+
* @param isValueNullShortCircuit - Whether to treat null values as short-circuit conditions.
3536
* @returns DevExpressFilter - The DevExpress-compatible filter array or null.
3637
*/
3738
export function convertAstToDevextreme(
3839
ast: ASTNode,
3940
state?: ResultObject | null,
4041
enableShortCircuit?: boolean,
42+
isValueNullShortCircuit?: boolean
4143
): DevExpressFilter;

src/core/converter.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ function DevExpressConverter() {
88
// Global variables accessible throughout the converter
99
let resultObject = null;
1010
let EnableShortCircuit = true;
11+
let IsValueNullShortCircuit = false; // Flag to enable/disable null short-circuiting
1112

1213
/**
1314
* Main conversion function that sets up the global context
@@ -16,10 +17,11 @@ function DevExpressConverter() {
1617
* @param {boolean} enableShortCircuit - Optional enabling and disabling the shortcircuit ie evaluating value = value scenario
1718
* @returns {Array|null} DevExpress format filter
1819
*/
19-
function convert(ast, ResultObject = null, enableShortCircuit = true) {
20+
function convert(ast, ResultObject = null, enableShortCircuit = true, isValueNullShortCircuit = false) {
2021
// Set up global context
2122
resultObject = ResultObject;
2223
EnableShortCircuit = enableShortCircuit;
24+
IsValueNullShortCircuit = isValueNullShortCircuit;
2325

2426
// Process the AST
2527
let result = processAstNode(ast);
@@ -89,6 +91,7 @@ function DevExpressConverter() {
8991
const left = processAstNode(ast.left, operator);
9092
const right = processAstNode(ast.right, operator);
9193

94+
9295
if (EnableShortCircuit) {
9396
// Short-circuit: always-true conditions
9497
if (left === true || right === true) {
@@ -100,7 +103,6 @@ function DevExpressConverter() {
100103
if (left === false || right === false) {
101104
return left === false ? right : left;
102105
}
103-
104106
}
105107

106108
// Detect and flatten nested logical expressions
@@ -165,6 +167,10 @@ function DevExpressConverter() {
165167
}
166168

167169
// 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+
168174
if (EnableShortCircuit) {
169175
if (isAlwaysTrue(comparison, leftDefault, rightDefault)) return true;
170176
if (isAlwaysFalse(comparison, leftDefault, rightDefault)) return false;
@@ -242,6 +248,10 @@ function DevExpressConverter() {
242248
}
243249
}
244250

251+
if (EnableShortCircuit && IsValueNullShortCircuit && (ast.field?.type === "placeholder" || ast.value?.type === "placeholder" || ast.value === null) && resolvedValue === null) {
252+
return true;
253+
}
254+
245255
let operatorToken = operator === "IN" ? '=' : operator === "NOT IN" ? '!=' : operator;
246256
let joinOperatorToken = operator === "IN" ? 'or' : operator === "NOT IN" ? 'and' : operator;
247257
let field = convertValue(ast.field);
@@ -443,8 +453,9 @@ const devExpressConverter = DevExpressConverter();
443453
* @param {Object} ast - The abstract syntax tree
444454
* @param {Object} resultObject - Optional object for placeholder resolution
445455
* @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
446457
* @returns {Array|null} DevExpress format filter
447458
*/
448-
export function convertToDevExpressFormat({ ast, resultObject = null, enableShortCircuit = true }) {
449-
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);
450461
}

src/debug.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
// const astTree = parsedResult.ast;
2626
// console.log("AST Tree:", JSON.stringify(astTree, null, 2), "\n");
2727

28-
// return convertToDevExpressFormat({ ast: astTree, resultObject: sampleData });
28+
// return convertToDevExpressFormat({ ast: astTree, resultObject: sampleData, isValueNullShortCircuit: true });
2929
// }
3030

3131
// const devexpress = parseFilterString("(ISNULL(TicketID, 0) = ISNULL({CustomerOrders.OrderID}, 0))", sampleData);

src/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ export function convertSQLToAst(filterString, enableConsoleLogs = false) {
1616
return parsedResult;
1717
}
1818

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 })
2121
}
2222

2323

tests/parser.test.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,14 @@ describe("Parser SQL to dx Filter Builder", () => {
260260
{
261261
input: "{LeadDocument.AllowSubDealer} != null",
262262
expected: []
263+
},
264+
{
265+
input: "ID = {SaleOrderStatusStmtGlobalRpt.RegionID}",
266+
expected: []
267+
},
268+
{
269+
input: "ID IN ({SaleOrderStatusStmtGlobalRpt.RegionID})",
270+
expected: []
263271
}
264272
];
265273

@@ -282,7 +290,7 @@ describe("Parser SQL to dx Filter Builder", () => {
282290
const variables = astwithVariables.variables;
283291
const ast = astwithVariables.ast;
284292

285-
const result = convertAstToDevextreme(ast, sampleData);
293+
const result = convertAstToDevextreme(ast, sampleData, true, true);
286294

287295
if (result == null || result == true || result == false) {
288296
expect([]).toEqual(expected);

0 commit comments

Comments
 (0)