sqlparser-devexpress 2.5.0 → 2.5.1
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/core/converter.js +41 -33
- package/src/debug.js +1 -1
- package/tests/parser.test.js +93 -21
package/package.json
CHANGED
package/src/core/converter.js
CHANGED
|
@@ -33,7 +33,10 @@ function DevExpressConverter() {
|
|
|
33
33
|
// Handle special cases for short circuit
|
|
34
34
|
if (result === true || result === false || result === null) return [];
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
if (result.length == 1) {
|
|
37
|
+
return result[0];
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
/**
|
|
@@ -167,67 +170,58 @@ function DevExpressConverter() {
|
|
|
167
170
|
let isLeftNullCheck = isFunctionNullCheck(ast.left, true);
|
|
168
171
|
let isRightNullCheck = isFunctionNullCheck(ast.right, false) || (ast.value && isFunctionNullCheck(ast.value, false));
|
|
169
172
|
let isBothNullChecks = isLeftNullCheck && isRightNullCheck;
|
|
170
|
-
|
|
173
|
+
let isdestructured = false;
|
|
174
|
+
// 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.
|
|
171
175
|
if (!isBothNullChecks && isLeftNullCheck) {
|
|
172
176
|
const nullCheckArg = (ast.left ?? ast.value).args[1]?.value;
|
|
177
|
+
let valueRight = null
|
|
173
178
|
|
|
174
179
|
let baseComparison = comparison;
|
|
175
180
|
|
|
176
181
|
if (Array.isArray(right) && (right.includes("or") || right.includes("and"))) {
|
|
177
|
-
|
|
182
|
+
isdestructured = true;
|
|
183
|
+
valueRight = right.shift();
|
|
178
184
|
baseComparison = [[left, operatorToken, valueRight], ...right];
|
|
179
185
|
}
|
|
186
|
+
const _val = !isdestructured ? baseComparison[2] : valueRight;
|
|
187
|
+
if (normalizeBool(_val) == normalizeBool(nullCheckArg))
|
|
188
|
+
comparison = [[...baseComparison], 'or', [left, operatorToken, null, { type: "ISNULL", position: "column", defaultValue: nullCheckArg }, null]];
|
|
189
|
+
else
|
|
190
|
+
comparison = [...baseComparison, { type: "ISNULL", position: "column", defaultValue: nullCheckArg }, _val];
|
|
180
191
|
|
|
181
|
-
comparison = [[...baseComparison], 'or', [left, operatorToken, null, { type: "ISNULL", position: "column", defaultValue: nullCheckArg }, null]];
|
|
182
192
|
|
|
183
193
|
} else if (!isBothNullChecks && isRightNullCheck) {
|
|
184
194
|
const nullCheckArg = (ast.right ?? ast.value).args[1]?.value;
|
|
185
|
-
|
|
195
|
+
let valueLeft = null
|
|
186
196
|
let baseComparison = comparison;
|
|
187
197
|
|
|
188
198
|
if (Array.isArray(left) && (left.includes("or") || left.includes("and"))) {
|
|
189
|
-
|
|
199
|
+
isdestructured = true;
|
|
200
|
+
valueLeft = left.shift();
|
|
190
201
|
baseComparison = [[valueLeft, operatorToken, right], ...left];
|
|
191
202
|
}
|
|
203
|
+
const _val = !isdestructured ? baseComparison[2] : valueRight;
|
|
192
204
|
|
|
193
|
-
comparison = [
|
|
194
|
-
|
|
205
|
+
comparison = [...baseComparison, { type: "ISNULL", position: "value", defaultValue: nullCheckArg }, _val];
|
|
195
206
|
} else if (isBothNullChecks) {
|
|
196
207
|
const nullCheckArgleft = (ast.left ?? ast.value).args[1]?.value;
|
|
197
208
|
const nullCheckArgright = (ast.right ?? ast.value).args[1]?.value;
|
|
198
|
-
|
|
209
|
+
let valueLeft = null;
|
|
199
210
|
let baseComparison = comparison;
|
|
200
211
|
|
|
201
212
|
if (Array.isArray(left) && (left.includes("or") || left.includes("and"))) {
|
|
202
|
-
|
|
213
|
+
isdestructured = true;
|
|
214
|
+
valueLeft = left.shift();
|
|
203
215
|
baseComparison = [[valueLeft, operatorToken, right], ...left];
|
|
204
216
|
}
|
|
205
217
|
|
|
206
|
-
|
|
218
|
+
const _val = !isdestructured ? baseComparison[2] : valueLeft;
|
|
207
219
|
|
|
220
|
+
if (normalizeBool(nullCheckArgleft) == normalizeBool(nullCheckArgright))
|
|
221
|
+
comparison = [[...baseComparison, { type: "ISNULL", position: "both", defaultValue: nullCheckArgleft, defaultValueRight: nullCheckArgright }, _val], 'or', [left, operatorToken, null]];
|
|
222
|
+
else
|
|
223
|
+
comparison = [[...baseComparison, { type: "ISNULL", position: "both", defaultValue: nullCheckArgleft, defaultValueRight: nullCheckArgright }, _val]];
|
|
208
224
|
}
|
|
209
|
-
// 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
|
|
210
|
-
// if ((ast.left && isFunctionNullCheck(ast.left, true)) || (ast.value && isFunctionNullCheck(ast.value, false))) {
|
|
211
|
-
// const nullCheckArg = (ast.left ?? ast.value).args[1]?.value;
|
|
212
|
-
// let baseComparison = comparison;
|
|
213
|
-
|
|
214
|
-
// if (Array.isArray(right) && (right.includes("or") || right.includes("and"))) {
|
|
215
|
-
// const valueRight = right.shift();
|
|
216
|
-
// baseComparison = [[left, operatorToken, valueRight], ...right];
|
|
217
|
-
// }
|
|
218
|
-
|
|
219
|
-
// comparison = [baseComparison, 'or', [left, operatorToken, null, { type: "ISNULL", defaultValue: nullCheckArg }, null]];
|
|
220
|
-
// } else if (ast.right && isFunctionNullCheck(ast.right, true)) {
|
|
221
|
-
// const nullCheckArg = ast.right.args[1]?.value;
|
|
222
|
-
// let baseComparison = comparison;
|
|
223
|
-
|
|
224
|
-
// if (Array.isArray(right) && (right.includes("or") || right.includes("and"))) {
|
|
225
|
-
// const valueRight = right.shift();
|
|
226
|
-
// baseComparison = [[left, operatorToken, valueRight], ...right];
|
|
227
|
-
// }
|
|
228
|
-
|
|
229
|
-
// comparison = [baseComparison, 'or', [right, operatorToken, null, { type: "ISNULL", defaultValue: nullCheckArg }, null]];
|
|
230
|
-
// }
|
|
231
225
|
|
|
232
226
|
// Apply short-circuit evaluation if enabled
|
|
233
227
|
if (EnableShortCircuit && IsValueNullShortCircuit && (left == null || right == null)) {
|
|
@@ -259,6 +253,20 @@ function DevExpressConverter() {
|
|
|
259
253
|
return comparison;
|
|
260
254
|
}
|
|
261
255
|
|
|
256
|
+
/**
|
|
257
|
+
* Normalizes numeric boolean-like values to actual booleans.
|
|
258
|
+
*
|
|
259
|
+
* Converts the number `0` to `false` and `1` to `true`.
|
|
260
|
+
* If the input is not exactly `0` or `1`, it returns the value unchanged.
|
|
261
|
+
*
|
|
262
|
+
* @param {*} value - The value to normalize. Can be of any type.
|
|
263
|
+
* @returns {*} - Returns `false` if `value` is `0`, `true` if `value` is `1`, otherwise returns the original value.
|
|
264
|
+
*/
|
|
265
|
+
function normalizeBool(value) {
|
|
266
|
+
return value === 0 || value === 1 ? Boolean(value) : value;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
|
|
262
270
|
/**
|
|
263
271
|
* Handles function calls, focusing on ISNULL.
|
|
264
272
|
* @param {Object} ast - The function AST node.
|
package/src/debug.js
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
// const astTree = parsedResult.ast;
|
|
27
27
|
// console.log("AST Tree:", JSON.stringify(astTree, null, 2), "\n");
|
|
28
28
|
|
|
29
|
-
// return convertToDevExpressFormat({ ast: astTree, resultObject: sampleData, isValueNullShortCircuit: true });
|
|
29
|
+
// return convertToDevExpressFormat({ ast: astTree, resultObject: sampleData, options: { isValueNullShortCircuit: true, treatNumberAsNullableBit: true } });
|
|
30
30
|
// }
|
|
31
31
|
|
|
32
32
|
// const devexpress = parseFilterString("ISNULL(CompanyID,0) = ISNULL({TransferOutwardDocument.CompanyID},0) OR ISNULL(CompanyID,0) = 0", sampleData);
|
package/tests/parser.test.js
CHANGED
|
@@ -137,15 +137,15 @@ describe("Parser SQL to dx Filter Builder", () => {
|
|
|
137
137
|
{
|
|
138
138
|
input: "ISNULL(SourceID,0) = {ServiceOrderDocument.SourceID} OR ISNULL(SourceID,0) = 0",
|
|
139
139
|
expected: [
|
|
140
|
-
["SourceID", "=", 2],
|
|
140
|
+
["SourceID", "=", 2, { "defaultValue": 0, "position": "column", "type": "ISNULL" }, 2],
|
|
141
141
|
"or",
|
|
142
|
-
[
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
142
|
+
[
|
|
143
|
+
["SourceID", "=", 0],
|
|
144
|
+
"or",
|
|
145
|
+
["SourceID", "=", null, { "defaultValue": 0, "position": "column", "type": "ISNULL" }, null],
|
|
146
|
+
"or",
|
|
147
|
+
["SourceID", "=", false]
|
|
148
|
+
]
|
|
149
149
|
]
|
|
150
150
|
},
|
|
151
151
|
{
|
|
@@ -163,11 +163,13 @@ describe("Parser SQL to dx Filter Builder", () => {
|
|
|
163
163
|
]
|
|
164
164
|
],
|
|
165
165
|
"and",
|
|
166
|
-
[
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
166
|
+
// [
|
|
167
|
+
// ["IsSubdealer", "=", 0],
|
|
168
|
+
// "or",
|
|
169
|
+
// ["IsSubdealer", "=", null, { "defaultValue": 0, "position": "column", "type": "ISNULL" }, null],
|
|
170
|
+
// "or",
|
|
171
|
+
["IsSubdealer", "=", true, { "defaultValue": 0, "position": "column", "type": "ISNULL" }, true],
|
|
172
|
+
// ]
|
|
171
173
|
]
|
|
172
174
|
},
|
|
173
175
|
{
|
|
@@ -199,15 +201,15 @@ describe("Parser SQL to dx Filter Builder", () => {
|
|
|
199
201
|
{
|
|
200
202
|
input: "CompanyID = ISNULL({LeadDocument.CompanyID},0) OR (ISNULL(CompanyID,0) = 0))",
|
|
201
203
|
expected: [
|
|
202
|
-
["CompanyID", "=", 7],
|
|
203
|
-
"or",
|
|
204
|
-
["CompanyID", "=", null, { "type": "ISNULL", "position": "value", "defaultValue": 0 }, null],
|
|
205
|
-
"or",
|
|
206
|
-
["CompanyID", "=", 0],
|
|
207
|
-
"or",
|
|
208
|
-
["CompanyID", "=", null, { "type": "ISNULL", "position": "column", "defaultValue": 0 }, null],
|
|
204
|
+
["CompanyID", "=", 7, { "type": "ISNULL", "position": "value", "defaultValue": 0 }, 7],
|
|
209
205
|
"or",
|
|
210
|
-
[
|
|
206
|
+
[
|
|
207
|
+
["CompanyID", "=", 0],
|
|
208
|
+
"or",
|
|
209
|
+
["CompanyID", "=", null, { "type": "ISNULL", "position": "column", "defaultValue": 0 }, null],
|
|
210
|
+
"or",
|
|
211
|
+
["CompanyID", "=", false]
|
|
212
|
+
]
|
|
211
213
|
]
|
|
212
214
|
},
|
|
213
215
|
{
|
|
@@ -317,6 +319,76 @@ describe("Parser SQL to dx Filter Builder", () => {
|
|
|
317
319
|
"or",
|
|
318
320
|
["CompanyID", "=", false]
|
|
319
321
|
]
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
input: "ISNULL(CompanyID,0) = ISNULL({TransferOutwardDocument.CompanyID},0) OR (ISNULL(CompanyID,1) = 0)",
|
|
325
|
+
expected: [
|
|
326
|
+
["CompanyID", "=", 7, { "type": "ISNULL", "position": "both", "defaultValue": 0, "defaultValueRight": 0 }, 7],
|
|
327
|
+
"or",
|
|
328
|
+
["CompanyID", "=", null],
|
|
329
|
+
"or",
|
|
330
|
+
["CompanyID", "=", 0, { "type": "ISNULL", "position": "column", "defaultValue": 1 }, 0],
|
|
331
|
+
"or",
|
|
332
|
+
["CompanyID", "=", false]
|
|
333
|
+
]
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
input: "ISNULL(CompanyID,0) = {LeadDocument.CompanyID}",
|
|
337
|
+
expected: [
|
|
338
|
+
"CompanyID", "=", 7, { "type": "ISNULL", "position": "column", "defaultValue": 0 }, 7
|
|
339
|
+
]
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
input: "ISNULL(CompanyID,0) = ISNULL({LeadDocument.CompanyID},0)",
|
|
343
|
+
expected: [
|
|
344
|
+
["CompanyID", "=", 7, { "type": "ISNULL", "position": "both", "defaultValue": 0, "defaultValueRight": 0 }, 7],
|
|
345
|
+
"or",
|
|
346
|
+
["CompanyID", "=", null]
|
|
347
|
+
]
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
input: "ISNULL(CompanyID,1) = ISNULL({LeadDocument.CompanyID},2)",
|
|
351
|
+
expected: [
|
|
352
|
+
"CompanyID", "=", 7, { "type": "ISNULL", "position": "both", "defaultValue": 1, "defaultValueRight": 2 }, 7
|
|
353
|
+
]
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
input: "CompanyID = ISNULL({LeadDocument.CompanyID},0)",
|
|
357
|
+
expected: [
|
|
358
|
+
"CompanyID", "=", 7, { "type": "ISNULL", "position": "value", "defaultValue": 0 }, 7
|
|
359
|
+
]
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
input: "AllowSubDealer = ISNULL({LeadDocument.AllowSubDealer},0)",
|
|
363
|
+
expected: [
|
|
364
|
+
"AllowSubDealer", "=", true, { "type": "ISNULL", "position": "value", "defaultValue": 0 }, true
|
|
365
|
+
]
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
input: "AllowSubDealer = ISNULL({LeadDocument.AllowSubDealer},1)",
|
|
369
|
+
expected: [
|
|
370
|
+
"AllowSubDealer", "=", true, { "type": "ISNULL", "position": "value", "defaultValue": 1 }, true
|
|
371
|
+
]
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
input: "ISNULL(AllowSubDealer,0) = ISNULL({LeadDocument.AllowSubDealer},1)",
|
|
375
|
+
expected: [
|
|
376
|
+
"AllowSubDealer", "=", true, { "type": "ISNULL", "position": "both", "defaultValue": 0, "defaultValueRight": 1 }, true
|
|
377
|
+
]
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
input: "ISNULL(AllowSubDealer,0) = {LeadDocument.AllowSubDealer}",
|
|
381
|
+
expected: [
|
|
382
|
+
"AllowSubDealer", "=", true, { "type": "ISNULL", "position": "column", "defaultValue": 0 }, true
|
|
383
|
+
]
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
input: "ISNULL(AllowSubDealer,1) = {LeadDocument.AllowSubDealer}",
|
|
387
|
+
expected: [
|
|
388
|
+
["AllowSubDealer", "=", true],
|
|
389
|
+
'or',
|
|
390
|
+
["AllowSubDealer", "=", null, { "type": "ISNULL", "position": "column", "defaultValue": 1 }, null]
|
|
391
|
+
]
|
|
320
392
|
}
|
|
321
393
|
];
|
|
322
394
|
|