sqlparser-devexpress 2.3.6 → 2.3.8
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/README.md +3 -49
- package/package.json +1 -1
- package/src/core/converter.js +12 -5
- package/src/core/parser.js +1 -1
- package/src/core/tokenizer.js +10 -1
- package/src/debug.js +1 -1
package/README.md
CHANGED
|
@@ -128,57 +128,11 @@ console.log("DevExpress Filter:", JSON.stringify(devexpressFilter, null, 2));
|
|
|
128
128
|
|
|
129
129
|
### **DevExtreme with React Example**
|
|
130
130
|
|
|
131
|
-
|
|
131
|
+
To see an example of how to use `sqlparser-devexpress` with DevExtreme DataGrid in React, check out the live example on CodeSandbox:
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
npm install devextreme devextreme-react
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
Now, create a simple React component that integrates DevExtreme with the `sqlparser-devexpress` library:
|
|
138
|
-
|
|
139
|
-
```javascript
|
|
140
|
-
import React, { useState } from 'react';
|
|
141
|
-
import DataGrid, { Column, FilterRow, HeaderFilter } from 'devextreme-react/data-grid';
|
|
142
|
-
import 'devextreme/dist/css/dx.light.css';
|
|
143
|
-
import { convertSQLToAst, convertAstToDevextreme } from 'sqlparser-devexpress';
|
|
144
|
-
|
|
145
|
-
const App = () => {
|
|
146
|
-
const [data, setData] = useState([
|
|
147
|
-
{ OrderID: 76548, Status: 1 },
|
|
148
|
-
{ OrderID: 76549, Status: 3 },
|
|
149
|
-
{ OrderID: 76550, Status: 2 },
|
|
150
|
-
]);
|
|
151
|
-
|
|
152
|
-
const sqlQuery = "OrderID = {CustomerOrders.OrderID} OR Status IN (1, 3)";
|
|
153
|
-
const { ast, variables } = convertSQLToAst(sqlQuery);
|
|
154
|
-
|
|
155
|
-
// Extracted state for dynamic variables (usually fetched from your app state)
|
|
156
|
-
const sampleState = { "CustomerOrders.OrderID": 76548 };
|
|
157
|
-
|
|
158
|
-
const devexpressFilter = convertAstToDevextreme(ast, sampleState);
|
|
159
|
-
|
|
160
|
-
return (
|
|
161
|
-
<div>
|
|
162
|
-
<DataGrid dataSource={data} filterValue={devexpressFilter}>
|
|
163
|
-
<Column dataField="OrderID" />
|
|
164
|
-
<Column dataField="Status" />
|
|
165
|
-
<FilterRow visible={true} />
|
|
166
|
-
<HeaderFilter visible={true} />
|
|
167
|
-
</DataGrid>
|
|
168
|
-
</div>
|
|
169
|
-
);
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
export default App;
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### **Explanation**:
|
|
176
|
-
1. **DataGrid**: Displays the data with filtering.
|
|
177
|
-
2. **convertSQLToAst**: Converts the SQL `WHERE` clause into an AST.
|
|
178
|
-
3. **convertAstToDevextreme**: Converts the AST to the DevExtreme filter format.
|
|
179
|
-
4. **filterValue**: Applies the filter to the `DataGrid`.
|
|
133
|
+
[DevExtreme DataGrid with SQL Filter Example](https://codesandbox.io/p/sandbox/with-data-grid-with-sql-as-filter-string-my64v2)
|
|
180
134
|
|
|
181
|
-
|
|
135
|
+
In this example, SQL `WHERE` clauses are parsed into an Abstract Syntax Tree (AST) and then transformed into a DevExpress-compatible filter format that is used directly in the DataGrid component for filtering data.
|
|
182
136
|
|
|
183
137
|
## Roadmap
|
|
184
138
|
|
package/package.json
CHANGED
package/src/core/converter.js
CHANGED
|
@@ -138,18 +138,19 @@ function DevExpressConverter() {
|
|
|
138
138
|
const right = ast.right !== undefined ? processAstNode(ast.right) : convertValue(ast.value);
|
|
139
139
|
let operatorToken = ast.operator.toLowerCase();
|
|
140
140
|
|
|
141
|
-
if(operatorToken === "like") {
|
|
141
|
+
if (operatorToken === "like") {
|
|
142
142
|
operatorToken = "contains";
|
|
143
|
-
}else if (operatorToken === "not like") {
|
|
143
|
+
} else if (operatorToken === "not like") {
|
|
144
144
|
operatorToken = "notcontains";
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
let comparison = [left, operatorToken, right];
|
|
148
148
|
|
|
149
|
+
//TODO: the ISNULL custom metadata is causing issues on filters will need to check this on server
|
|
149
150
|
if ((ast.left && isFunctionNullCheck(ast.left, true)) || (ast.value && isFunctionNullCheck(ast.value, false))) {
|
|
150
|
-
comparison = [[left, operatorToken, right], 'or', [left, operatorToken, null, {type: "ISNULL", defaultValue: (ast.left ?? ast.value).args[1]?.value}]];
|
|
151
|
+
comparison = [[left, operatorToken, right], 'or', [left, operatorToken, null,]];// {type: "ISNULL", defaultValue: (ast.left ?? ast.value).args[1]?.value}]];
|
|
151
152
|
} else if (ast.right && isFunctionNullCheck(ast.right, true)) {
|
|
152
|
-
comparison = [[left, operatorToken, right], 'or', [right, operatorToken, null, {type: "ISNULL", defaultValue: ast.right.args[1]?.value}]];
|
|
153
|
+
comparison = [[left, operatorToken, right], 'or', [right, operatorToken, null,]];// {type: "ISNULL", defaultValue: ast.right.args[1]?.value}]];
|
|
153
154
|
}
|
|
154
155
|
|
|
155
156
|
// Apply short-circuit evaluation if enabled
|
|
@@ -228,7 +229,13 @@ function DevExpressConverter() {
|
|
|
228
229
|
// Handle object-based values
|
|
229
230
|
if (typeof val === "object") {
|
|
230
231
|
if (val.type === "placeholder") {
|
|
231
|
-
|
|
232
|
+
const placeholderValue = resolvePlaceholderFromResultObject(val.value);
|
|
233
|
+
|
|
234
|
+
if (val?.dataType === "string") {
|
|
235
|
+
return placeholderValue?.toString();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return placeholderValue;
|
|
232
239
|
}
|
|
233
240
|
|
|
234
241
|
// Special handling for ISNULL function
|
package/src/core/parser.js
CHANGED
|
@@ -237,7 +237,7 @@ export function parse(input, variables = []) {
|
|
|
237
237
|
case "placeholder": {
|
|
238
238
|
const val = token.value.slice(1, -1);
|
|
239
239
|
if (!variables.includes(val)) variables.push(val);
|
|
240
|
-
return { type: "placeholder", value: val };
|
|
240
|
+
return { ...token ,type: "placeholder", value: val };
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
case "paren": {
|
package/src/core/tokenizer.js
CHANGED
|
@@ -45,8 +45,17 @@ class Tokenizer {
|
|
|
45
45
|
if (!type || type === "whitespace") return this.nextToken();
|
|
46
46
|
|
|
47
47
|
let value = match.groups[type];
|
|
48
|
+
let dataType = null;
|
|
48
49
|
|
|
49
50
|
// Remove surrounding single quotes from placeholders
|
|
51
|
+
if(type === "placeholder"){
|
|
52
|
+
|
|
53
|
+
if(value.startsWith("'") && value.endsWith("'")){
|
|
54
|
+
dataType = "string";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
value = value.replace(/^[\s'"\(\)]+|[\s'"\(\)]+|[\s]+/g, "");
|
|
58
|
+
}
|
|
50
59
|
if (type === "placeholder") value = value.replace(/^[\s'"\(\)]+|[\s'"\(\)]+|[\s]+/g, "");
|
|
51
60
|
|
|
52
61
|
if (type === "operator") {
|
|
@@ -68,7 +77,7 @@ class Tokenizer {
|
|
|
68
77
|
}
|
|
69
78
|
|
|
70
79
|
|
|
71
|
-
return { type, value };
|
|
80
|
+
return { type, value, ...(dataType !== null && { dataType }) };
|
|
72
81
|
}
|
|
73
82
|
|
|
74
83
|
// If no valid token is found, throw an error with the remaining input for debugging
|
package/src/debug.js
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
// return convertToDevExpressFormat({ ast: astTree, resultObject: sampleData });
|
|
29
29
|
// }
|
|
30
30
|
|
|
31
|
-
// const devexpress = parseFilterString("
|
|
31
|
+
// const devexpress = parseFilterString("(ISNULL(TicketID, 0) = ISNULL({CustomerOrders.OrderID}, 0))", sampleData);
|
|
32
32
|
// console.log("DevExpress Filter:", JSON.stringify(devexpress, null, 2));
|
|
33
33
|
// // const devexpress = parseFilterString("(RS2ID in ({LeadStatementGlobalRpt.StateID}) Or ({LeadStatementGlobalRpt.StateID} =0)) And (RS3ID in (0,{LeadStatementGlobalRpt.RegionID}) Or {LeadStatementGlobalRpt.RegionID} =0 )", sampleData);
|
|
34
34
|
|