sqlparser-devexpress 2.1.3 → 2.1.4
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/constants.js +11 -0
- package/src/core/parser.js +1 -10
- package/src/core/tokenizer.js +9 -5
- package/src/index.js +5 -4
- package/tests/parser.test.js +8 -0
package/package.json
CHANGED
package/src/constants.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//
|
|
2
|
+
export const LITERALS = ["number", "string", "null"];
|
|
3
|
+
|
|
4
|
+
// Define operator precedence for parsing expressions
|
|
5
|
+
export const OPERATOR_PRECEDENCE = {
|
|
6
|
+
"OR": 1, "AND": 2, "=": 3, "!=": 3, ">": 3, "<": 3, ">=": 3, "<=": 3,
|
|
7
|
+
"IN": 3, "<>": 3, "LIKE": 3, "IS": 3, "BETWEEN": 3
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// Regular expression to check for unsupported SQL patterns (like SELECT-FROM or JOIN statements)
|
|
11
|
+
export const UNSUPPORTED_PATTERN = /\bSELECT\b.*\bFROM\b|\bINNER\s+JOIN\b/i;
|
package/src/core/parser.js
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
|
+
import { LITERALS, OPERATOR_PRECEDENCE, UNSUPPORTED_PATTERN } from "../constants.js";
|
|
1
2
|
import { Tokenizer } from "./tokenizer.js";
|
|
2
3
|
|
|
3
|
-
// Define operator precedence for parsing expressions
|
|
4
|
-
const OPERATOR_PRECEDENCE = {
|
|
5
|
-
"OR": 1, "AND": 2, "=": 3, "!=": 3, ">": 3, "<": 3, ">=": 3, "<=": 3,
|
|
6
|
-
"IN": 3, "<>": 3, "LIKE": 3, "IS": 3, "BETWEEN": 3
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
const LITERALS = ["number", "string", "null"];
|
|
10
|
-
|
|
11
|
-
// Regular expression to check for unsupported SQL patterns (like SELECT-FROM or JOIN statements)
|
|
12
|
-
const UNSUPPORTED_PATTERN = /\bSELECT\b.*\bFROM\b|\bINNER\s+JOIN\b/i;
|
|
13
4
|
|
|
14
5
|
export function parse(input, variables = []) {
|
|
15
6
|
|
package/src/core/tokenizer.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
import { LITERALS } from "../constants";
|
|
2
|
+
|
|
1
3
|
// Define regex patterns for different token types
|
|
2
4
|
const tokenPatterns = {
|
|
3
5
|
whitespace: "\\s+", // Matches spaces, tabs, and newlines
|
|
4
6
|
function: "\\b(ISNULL)\\b", // Matches function names like ISNULL (case-insensitive)
|
|
5
|
-
null: "\\bNULL\\b", // Matches NULL as a keyword
|
|
6
|
-
number: "\\d+", // Matches
|
|
7
|
+
null: "\\bNULL\\b|\\(\\s*NULL\\s*\\)", // Matches NULL as a keyword
|
|
8
|
+
number: "\\(\\d+\\)|\\d+", // Matches numbers while stripping unnecessary parentheses
|
|
7
9
|
placeholder: "'?\\{[^}]+\\}'?", // Matches placeholders like {variable} or '{variable}'
|
|
8
|
-
string: "'(?:''|[^'])*'", // Matches strings, allowing for escaped single quotes ('')
|
|
10
|
+
string: "\\('\\w+\\'\\)|'(?:''|[^'])*'", // Matches strings, allowing for escaped single quotes ('')
|
|
9
11
|
operator: "=>|<=|!=|>=|=|<>|>|<|\\bAND\\b|\\bOR\\b|\\bBETWEEN\\b|\\bIN\\b|\\bNOT IN\\b|\\bLIKE\\b|\\bIS NOT\\b|\\bNOT LIKE\\b|\\bIS\\b", // Matches SQL operators and logical keywords
|
|
10
12
|
identifier: "[\\w.]+", // Matches identifiers, including table.column format
|
|
11
|
-
paren: "[()]", // Matches parentheses
|
|
13
|
+
paren: "[()]", // Matches standalone parentheses
|
|
12
14
|
comma: "," // Matches commas
|
|
13
15
|
};
|
|
14
16
|
|
|
@@ -45,7 +47,7 @@ class Tokenizer {
|
|
|
45
47
|
let value = match.groups[type];
|
|
46
48
|
|
|
47
49
|
// Remove surrounding single quotes from placeholders
|
|
48
|
-
if (type === "placeholder") value = value.replace(/^['"]|['"]$/g, "").replace(" ","");
|
|
50
|
+
if (type === "placeholder") value = value.replace(/^['"]|['"]$/g, "").replace(" ", "");
|
|
49
51
|
|
|
50
52
|
if (type === "operator") {
|
|
51
53
|
const lowerValue = value.toLowerCase();
|
|
@@ -57,6 +59,8 @@ class Tokenizer {
|
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
61
|
|
|
62
|
+
if (LITERALS.includes(type)) value = value.replace(/^[(]|[)]$/g, "")
|
|
63
|
+
|
|
60
64
|
return { type, value };
|
|
61
65
|
}
|
|
62
66
|
|
package/src/index.js
CHANGED
|
@@ -5,13 +5,14 @@ import { sanitizeQuery } from "./core/sanitizer.js";
|
|
|
5
5
|
|
|
6
6
|
export function convertSQLToAst(filterString, enableConsoleLogs = false) {
|
|
7
7
|
let { sanitizedSQL, extractedVariables } = sanitizeQuery(filterString);
|
|
8
|
-
!!enableConsoleLogs && console.log("Sanitized SQL:", sanitizedSQL, "\n");
|
|
9
8
|
|
|
10
9
|
const parsedResult = parse(sanitizedSQL, extractedVariables);
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
if (enableConsoleLogs === true) {
|
|
12
|
+
console.log("Sanitized SQL:", sanitizedSQL, "\n");
|
|
13
|
+
console.log("Extracted Variables:", JSON.stringify(parsedResult.variables, null, 2), "\n");
|
|
14
|
+
console.log("AST Tree:", JSON.stringify(parsedResult.ast, null, 2), "\n");
|
|
15
|
+
}
|
|
15
16
|
return parsedResult;
|
|
16
17
|
}
|
|
17
18
|
|
package/tests/parser.test.js
CHANGED
|
@@ -183,6 +183,14 @@ describe("Parser SQL to dx Filter Builder", () => {
|
|
|
183
183
|
"and",
|
|
184
184
|
["AddressType", "!=", 4]
|
|
185
185
|
]
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
input: "AddressType IN ('2', ('4'))",
|
|
189
|
+
expected: [
|
|
190
|
+
["AddressType", "=", '2'],
|
|
191
|
+
"or",
|
|
192
|
+
["AddressType", "=", '4']
|
|
193
|
+
]
|
|
186
194
|
}
|
|
187
195
|
];
|
|
188
196
|
|