You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Updated `Contributing.md` with more detailed instructions on grammar updates
6
+
- Added support for `WITH SECURITY_ENFORCED` (#61)
7
+
3
8
## 1.0.2
4
-
- If a field in a query happened to have a function reserved word, such as `Format`, then parsing the query failed. (#59)
9
+
10
+
- If a field in a query happened to have a function reserved word, such as `Format`, then parsing the query failed. (#59)
5
11
6
12
## 1.0.1
13
+
7
14
- Ensured that nothing is logged directly to the console unless logging is enabled
8
15
9
16
## 1.0.0
17
+
10
18
### Changed
19
+
11
20
**!BREAKING CHANGES!**
21
+
12
22
- Added literal type information to fields to provide additional information about the field type. (#51)
13
23
- WHERE clause fields have one of the following types `'STRING' | 'INTEGER' | 'DECIMAL' | 'BOOLEAN' | 'NULL' | 'DATE_LITERAL' | 'DATE_N_LITERAL';` stored in the condition.
14
-
- For date literal fields that have variables, `dateLiteralVariable` will be populated with the value
24
+
- For date literal fields that have variables, `dateLiteralVariable` will be populated with the value
15
25
- Modified Field data structure to have explicit type information. (#46, #52)
16
26
- The data structure for fields has been modified to include specific information about the structure of a given field to ease making sense of a parsed query,
17
27
- To aid in creating compose fields, a new helper method is available - `getComposedField()`. This takes in a simple data structure (or even a string) and will return the structure needed to compose a query.
18
28
19
29
### New
30
+
20
31
- An additional `queryUtils` object is available with the following functions:
Contributions of any kind are welcome and appreciated.
3
4
4
5
# What features are allowed
6
+
5
7
Any feature that is part of the core project and does not deviate from what the product is will be considered t obe accepted.
6
8
7
9
# Making Changes
8
-
* For the repository
9
-
* Create a new branch from master (usually) and with a meaningful name for your changes
10
-
* Make you changes
11
-
* Commit and push your change
12
-
* Please run `prettier` on all modified files prior to opening your pull request
13
-
* open a Pull Request for the master branch
10
+
11
+
- For the repository
12
+
- Create a new branch from master (usually) and with a meaningful name for your changes
13
+
- Make you changes
14
+
- Commit and push your change
15
+
- Please run `prettier` on all modified files prior to opening your pull request
16
+
- open a Pull Request for the master branch
17
+
18
+
# Re-generating parse after grammar change
19
+
20
+
:beetle: There is a bug in the generated ANTLR output that must be corrected by hand in the generated output to make this work.
21
+
22
+
- Note: I am not an expert with language parsing/antler and I did not create the grammar, so I was not able to figure this bug out. I believe the problem relies with `antlr4ts-cli` and the way imports are always added to the end of the file
23
+
24
+
## Generate lexer and parser
25
+
26
+
- Run `npm run antlr`
27
+
- This will remove and re-generate all of the lexer and parser files required to parse SOQL
28
+
-:beetle: Manual steps:
29
+
- Open `SOQLParser.ts` after the file generation
30
+
- Find the class `Keywords_alias_allowedContext` somewhere near line ~44K
31
+
- Cut this class and all remaining classes through the end of the file and paste right underneath the `import` statements
32
+
- Run all unit tests afterwards `npm run test` - if anything is broken, please troubleshoot or create a PR and ask for assistance
33
+
34
+
## Update code to support new grammar
35
+
36
+
- Start with adding a new unit test
37
+
- This will ensure the parser and composer support the syntax
38
+
- Update the parser to listen for the new grammar (this depends on grammar change that was implemented)
39
+
- Assuming there is a new clause somewhere, look in `lib/generated/SOQLListener.ts` to find the new enter/exit methods that were added
40
+
- Implement these methods in `lib/SOQLListener.ts` to handle parsing the logic
41
+
- Update `lib/SOQLComposer.ts` to handle creating the SOQL query from the parsed query
42
+
43
+
## Unit tests
44
+
45
+
- ensure your new unit tests cover all the cases
46
+
- Ensure unit tests are all passing, or open a PR and ask for assistance
SOQL Parser JS provides the following capabilities:
10
+
9
11
1. Parse a SOQL query into a usable data structure.
10
12
2. Turn a parsed query data structure back into well a SOQL query with various format options.
11
13
3. Check if a SOQL query is syntactically valid (**note**: some cases may be structurally sound but not allowed by SFDC).
12
14
13
15
This library is written in Typescript and all type definitions are included with the library for your benefit if you choose to use Typescript or use VSCode's automatic type checking.
14
16
15
-
*Warning*: antlr4 is dependency for this library and is a rather large library (~600 KB) and is required for the parser to function, use in the browser with care.
17
+
_Warning_: antlr4 is dependency for this library and is a rather large library (~600 KB) and is required for the parser to function, use in the browser with care.
16
18
17
19
## Examples
20
+
18
21
For an example of the parser, check out the [example application](https://paustint.github.io/soql-parser-js/).
19
22
20
23
Have a look through the unit tests for many more examples.
21
24
22
25
# Usage
26
+
23
27
## Parsing
28
+
24
29
Parsing a SOQL query can be completed by calling `parseQuery(soqlQueryString, options)` and a `Query` data structure will be returned;
// var soqlParserJs = require('soql-parser-js'); // node's require format - usage: soqlParserJs.parseQuery()
30
36
31
-
const soql ='SELECT UserId, COUNT(Id) from LoginHistory WHERE LoginTime > 2010-09-20T22:16:30.000Z AND LoginTime < 2010-09-21T22:16:30.000Z GROUP BY UserId';
37
+
const soql =
38
+
'SELECT UserId, COUNT(Id) from LoginHistory WHERE LoginTime > 2010-09-20T22:16:30.000Z AND LoginTime < 2010-09-21T22:16:30.000Z GROUP BY UserId';
32
39
33
40
const soqlQuery =parseQuery(soql);
34
41
// const soqlQuery = soqlParserJs.parseQuery(soql); // using require()
Composing a query will turn a Query object back to a SOQL query. The exact same data structure returned from `parseQuery()` can be used,
49
58
but there are many use-cases where you may need to build your own data structure to compose a query.
50
59
These examples show building your own Query object with the minimum required fields.
51
60
52
61
**Note:** For some operators, they may be converted to upper case (e.x. NOT, AND)
53
62
54
-
**Note:** There are a number of fields populated on the Query object when `parseQuery()` is called that are not required to compose a query. Look at the examples below and the comments in the data model for more information.
55
-
63
+
**Note:** There are a number of fields populated on the Query object when `parseQuery()` is called that are not required to compose a query. Look at the examples below and the comments in the data model for more information.
56
64
57
65
**The base query object is shaped like this:**
66
+
58
67
```typescript
59
68
exportinterfaceQueryBase {
60
69
fields:FieldType[];
@@ -74,7 +83,9 @@ export interface QueryBase {
74
83
The easiest way to build the fields is to call the utility function `getComposedField()`.
In the above examples, we made use of `getComposedField(input: string | ComposeFieldInput)` to help easily compose the fields. The input expects a string or one of the following shapes of data below. An error will be thrown if the data passed in is not one of the following shapes:
155
+
In the above examples, we made use of `getComposedField(input: string | ComposeFieldInput)` to help easily compose the fields. The input expects a string or one of the following shapes of data below. An error will be thrown if the data passed in is not one of the following shapes:
const soql ='SELECT UserId, COUNT(Id) from LoginHistory WHERE LoginTime > 2010-09-20T22:16:30.000Z AND LoginTime < 2010-09-21T22:16:30.000Z GROUP BY UserId';
202
+
const soql =
203
+
'SELECT UserId, COUNT(Id) from LoginHistory WHERE LoginTime > 2010-09-20T22:16:30.000Z AND LoginTime < 2010-09-21T22:16:30.000Z GROUP BY UserId';
190
204
191
205
const isValid =isQueryValid(soql);
192
206
193
207
console.log('isValid', isValid);
194
-
195
208
```
196
209
197
210
#### Node
211
+
198
212
```javascript
199
213
var soqlParserJs =require('soql-parser-js');
200
214
201
-
constsoql='SELECT UserId, COUNT(Id) from LoginHistory WHERE LoginTime > 2010-09-20T22:16:30.000Z AND LoginTime < 2010-09-21T22:16:30.000Z GROUP BY UserId';
215
+
constsoql=
216
+
'SELECT UserId, COUNT(Id) from LoginHistory WHERE LoginTime > 2010-09-20T22:16:30.000Z AND LoginTime < 2010-09-21T22:16:30.000Z GROUP BY UserId';
202
217
203
218
constisValid=isQueryValid(soql);
204
219
205
220
console.log('isValid', isValid);
206
221
```
207
222
208
223
## Format Query
224
+
209
225
This function is provided as a convenience and just calls parse and compose under the hood.
210
226
211
227
```typescript
@@ -214,9 +230,12 @@ import { formatQuery } from 'soql-parser-js';
214
230
const query =`SELECT Id, Name, AccountNumber, AccountSource, AnnualRevenue, BillingAddress, BillingCity, BillingCountry, BillingGeocodeAccuracy, ShippingStreet, Sic, SicDesc, Site, SystemModstamp, TickerSymbol, Type, Website, (SELECT Id, Name, AccountId, Amount, CampaignId, CloseDate, CreatedById, Type FROM Opportunities), (SELECT Id, Name, AccountNumber, AccountSource, AnnualRevenue, BillingAddress, Website FROM ChildAccounts) FROM Account WHERE Name LIKE 'a%' OR Name LIKE 'b%' OR Name LIKE 'c%'`;
1. Convenience method to construct fields in the correct data format. See example usage in the Compose example.
316
-
2.`isSubquery(query: Query | Subquery)`
317
-
1. Returns true if the data passed in is a subquery
318
-
3.`getFlattenedFields(query: Query)`
319
-
1. This provides a list of fields that are stringified and flattened in order to access data from a returned API call from Salesforce. Refer to `tests/publicUtils.spec.ts` for usage examples.
1. Convenience method to construct fields in the correct data format. See example usage in the Compose example.
337
+
1.`isSubquery(query: Query | Subquery)`
338
+
1. Returns true if the data passed in is a subquery
339
+
1.`getFlattenedFields(query: Query)`
340
+
1. This provides a list of fields that are stringified and flattened in order to access data from a returned API call from Salesforce. Refer to `tests/publicUtils.spec.ts` for usage examples.
321
341
322
342
## Data Models
343
+
323
344
### Query
345
+
324
346
These are all available for import in your typescript projects
All contributions are welcome on the project. Please read the [contribution guidelines](https://github.com/paustint/soql-parser-js/blob/master/CONTRIBUTING.md).
545
571
546
572
## Special Thanks
547
-
* This library is based on the ANTLR4 grammar file [produced by Mulesoft](https://github.com/mulesoft/salesforce-soql-parser/blob/antlr4/SOQL.g4).
548
-
* The following repository also was a help to get things started: https://github.com/petermetz/antlr-4-ts-test
573
+
574
+
- This library is based on the ANTLR4 grammar file [produced by Mulesoft](https://github.com/mulesoft/salesforce-soql-parser/blob/antlr4/SOQL.g4).
575
+
- The following repository also was a help to get things started: https://github.com/petermetz/antlr-4-ts-test
0 commit comments