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 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
- First, install the necessary DevExtreme packages:
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
- ```sh
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
- This is a simple integration where the filter from SQLParser is used to filter the grid data in a React app using DevExtreme's `DataGrid`.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sqlparser-devexpress",
3
- "version": "2.3.6",
3
+ "version": "2.3.8",
4
4
  "main": "src/index.js",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -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
- return resolvePlaceholderFromResultObject(val.value);
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
@@ -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": {
@@ -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("CompanyID not like '{CustomerOrders.OrderID}'", sampleData);
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