@steedos/odata-v4-parser 2.2.53-beta.3
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/LICENSE.txt +22 -0
- package/README.md +31 -0
- package/lib/expressions.d.ts +94 -0
- package/lib/expressions.js +942 -0
- package/lib/expressions.js.map +1 -0
- package/lib/json.d.ts +24 -0
- package/lib/json.js +391 -0
- package/lib/json.js.map +1 -0
- package/lib/lexer.d.ts +243 -0
- package/lib/lexer.js +595 -0
- package/lib/lexer.js.map +1 -0
- package/lib/nameOrIdentifier.d.ts +56 -0
- package/lib/nameOrIdentifier.js +850 -0
- package/lib/nameOrIdentifier.js.map +1 -0
- package/lib/odataUri.d.ts +6 -0
- package/lib/odataUri.js +34 -0
- package/lib/odataUri.js.map +1 -0
- package/lib/parser.d.ts +16 -0
- package/lib/parser.js +50 -0
- package/lib/parser.js.map +1 -0
- package/lib/primitiveLiteral.d.ts +63 -0
- package/lib/primitiveLiteral.js +793 -0
- package/lib/primitiveLiteral.js.map +1 -0
- package/lib/query.d.ts +42 -0
- package/lib/query.js +903 -0
- package/lib/query.js.map +1 -0
- package/lib/resourcePath.d.ts +31 -0
- package/lib/resourcePath.js +469 -0
- package/lib/resourcePath.js.map +1 -0
- package/lib/utils.d.ts +8 -0
- package/lib/utils.js +37 -0
- package/lib/utils.js.map +1 -0
- package/package.json +24 -0
- package/src/expressions.ts +825 -0
- package/src/json.ts +372 -0
- package/src/lexer.ts +491 -0
- package/src/nameOrIdentifier.ts +749 -0
- package/src/odataUri.ts +37 -0
- package/src/parser.ts +37 -0
- package/src/primitiveLiteral.ts +684 -0
- package/src/query.ts +884 -0
- package/src/resourcePath.ts +461 -0
- package/src/utils.ts +36 -0
- package/tsconfig.json +33 -0
package/src/query.ts
ADDED
|
@@ -0,0 +1,884 @@
|
|
|
1
|
+
import Utils from "./utils";
|
|
2
|
+
import Lexer from "./lexer";
|
|
3
|
+
import PrimitiveLiteral from "./primitiveLiteral";
|
|
4
|
+
import NameOrIdentifier from "./nameOrIdentifier";
|
|
5
|
+
import Expressions from "./expressions";
|
|
6
|
+
|
|
7
|
+
export namespace Query {
|
|
8
|
+
export function queryOptions(value: Utils.SourceArray, index: number, metadataContext?: any): Lexer.Token {
|
|
9
|
+
let token = Query.queryOption(value, index, metadataContext);
|
|
10
|
+
if (!token) return;
|
|
11
|
+
let start = index;
|
|
12
|
+
index = token.next;
|
|
13
|
+
|
|
14
|
+
let options = [];
|
|
15
|
+
while (token) {
|
|
16
|
+
options.push(token);
|
|
17
|
+
// &
|
|
18
|
+
if (value[index] !== 0x26) break;
|
|
19
|
+
index++;
|
|
20
|
+
|
|
21
|
+
token = Query.queryOption(value, index, metadataContext);
|
|
22
|
+
if (!token) return;
|
|
23
|
+
index = token.next;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return Lexer.tokenize(value, start, index, { options }, Lexer.TokenType.QueryOptions);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function queryOption(value: Utils.SourceArray, index: number, metadataContext?: any): Lexer.Token {
|
|
30
|
+
return Query.systemQueryOption(value, index, metadataContext) ||
|
|
31
|
+
Query.aliasAndValue(value, index) ||
|
|
32
|
+
Query.customQueryOption(value, index);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function systemQueryOption(value: Utils.SourceArray, index: number, metadataContext?: any): Lexer.Token {
|
|
36
|
+
return Query.expand(value, index, metadataContext) ||
|
|
37
|
+
Query.filter(value, index) ||
|
|
38
|
+
Query.format(value, index) ||
|
|
39
|
+
Query.id(value, index) ||
|
|
40
|
+
Query.inlinecount(value, index) ||
|
|
41
|
+
Query.orderby(value, index) ||
|
|
42
|
+
Query.search(value, index) ||
|
|
43
|
+
Query.select(value, index) ||
|
|
44
|
+
Query.skip(value, index) ||
|
|
45
|
+
Query.skiptoken(value, index) ||
|
|
46
|
+
Query.top(value, index);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function customQueryOption(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
50
|
+
let key = NameOrIdentifier.odataIdentifier(value, index);
|
|
51
|
+
if (!key) return;
|
|
52
|
+
let start = index;
|
|
53
|
+
index = key.next;
|
|
54
|
+
|
|
55
|
+
let eq = Lexer.EQ(value, index);
|
|
56
|
+
if (!eq) return;
|
|
57
|
+
index = eq;
|
|
58
|
+
|
|
59
|
+
while (value[index] !== 0x26 && index < value.length) index++;
|
|
60
|
+
if (index === eq) return;
|
|
61
|
+
|
|
62
|
+
return Lexer.tokenize(value, start, index, { key: key.raw, value: Utils.stringify(value, eq, index) }, Lexer.TokenType.CustomQueryOption);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function id(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
66
|
+
let start = index;
|
|
67
|
+
if (Utils.equals(value, index, "%24id")) {
|
|
68
|
+
index += 5;
|
|
69
|
+
}else
|
|
70
|
+
if (Utils.equals(value, index, "$id")) {
|
|
71
|
+
index += 3;
|
|
72
|
+
}else return;
|
|
73
|
+
|
|
74
|
+
let eq = Lexer.EQ(value, index);
|
|
75
|
+
if (!eq) return;
|
|
76
|
+
index = eq;
|
|
77
|
+
|
|
78
|
+
while (value[index] !== 0x26 && index < value.length) index++;
|
|
79
|
+
if (index === eq) return;
|
|
80
|
+
|
|
81
|
+
return Lexer.tokenize(value, start, index, Utils.stringify(value, eq, index), Lexer.TokenType.Id);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function expand(value: Utils.SourceArray, index: number, metadataContext?: any): Lexer.Token {
|
|
85
|
+
let start = index;
|
|
86
|
+
if (Utils.equals(value, index, "%24expand")) {
|
|
87
|
+
index += 9;
|
|
88
|
+
}else
|
|
89
|
+
if (Utils.equals(value, index, "$expand")) {
|
|
90
|
+
index += 7;
|
|
91
|
+
}else return;
|
|
92
|
+
|
|
93
|
+
let eq = Lexer.EQ(value, index);
|
|
94
|
+
if (!eq) return;
|
|
95
|
+
index = eq;
|
|
96
|
+
|
|
97
|
+
let items = [];
|
|
98
|
+
let token = Query.expandItem(value, index, metadataContext);
|
|
99
|
+
if (!token) return;
|
|
100
|
+
index = token.next;
|
|
101
|
+
|
|
102
|
+
while (token) {
|
|
103
|
+
items.push(token);
|
|
104
|
+
|
|
105
|
+
let comma = Lexer.COMMA(value, index);
|
|
106
|
+
if (comma) {
|
|
107
|
+
index = comma;
|
|
108
|
+
token = Query.expandItem(value, index, metadataContext);
|
|
109
|
+
if (!token) return;
|
|
110
|
+
index = token.next;
|
|
111
|
+
}else break;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return Lexer.tokenize(value, start, index, { items }, Lexer.TokenType.Expand);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function expandItem(value: Utils.SourceArray, index: number, metadataContext?: any): Lexer.Token {
|
|
118
|
+
let start = index;
|
|
119
|
+
let star = Lexer.STAR(value, index);
|
|
120
|
+
if (star) {
|
|
121
|
+
index = star;
|
|
122
|
+
let ref = Expressions.refExpr(value, index);
|
|
123
|
+
if (ref) {
|
|
124
|
+
index = ref.next;
|
|
125
|
+
return Lexer.tokenize(value, start, index, { path: "*", ref }, Lexer.TokenType.ExpandItem);
|
|
126
|
+
} else {
|
|
127
|
+
let open = Lexer.OPEN(value, index);
|
|
128
|
+
if (open) {
|
|
129
|
+
index = open;
|
|
130
|
+
let token = Query.levels(value, index);
|
|
131
|
+
if (!token) return;
|
|
132
|
+
index = token.next;
|
|
133
|
+
|
|
134
|
+
let close = Lexer.CLOSE(value, index);
|
|
135
|
+
if (!close) return;
|
|
136
|
+
index = close;
|
|
137
|
+
|
|
138
|
+
return Lexer.tokenize(value, start, index, { path: "*", levels: token }, Lexer.TokenType.ExpandItem);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
let path = Query.expandPath(value, index, metadataContext);
|
|
144
|
+
if (!path) return;
|
|
145
|
+
index = path.next;
|
|
146
|
+
|
|
147
|
+
let tokenValue: any = { path };
|
|
148
|
+
|
|
149
|
+
let ref = Expressions.refExpr(value, index);
|
|
150
|
+
if (ref) {
|
|
151
|
+
index = ref.next;
|
|
152
|
+
tokenValue.ref = ref;
|
|
153
|
+
|
|
154
|
+
let open = Lexer.OPEN(value, index);
|
|
155
|
+
if (open) {
|
|
156
|
+
index = open;
|
|
157
|
+
|
|
158
|
+
let option = Query.expandRefOption(value, index);
|
|
159
|
+
if (!option) return;
|
|
160
|
+
|
|
161
|
+
let refOptions = [];
|
|
162
|
+
while (option) {
|
|
163
|
+
refOptions.push(option);
|
|
164
|
+
index = option.next;
|
|
165
|
+
|
|
166
|
+
let semi = Lexer.SEMI(value, index);
|
|
167
|
+
if (semi) {
|
|
168
|
+
index = semi;
|
|
169
|
+
|
|
170
|
+
option = Query.expandRefOption(value, index);
|
|
171
|
+
if (!option) return;
|
|
172
|
+
}else break;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
let close = Lexer.CLOSE(value, index);
|
|
176
|
+
if (!close) return;
|
|
177
|
+
index = close;
|
|
178
|
+
|
|
179
|
+
tokenValue.options = refOptions;
|
|
180
|
+
}
|
|
181
|
+
} else {
|
|
182
|
+
let count = Expressions.countExpr(value, index);
|
|
183
|
+
if (count) {
|
|
184
|
+
index = count.next;
|
|
185
|
+
tokenValue.count = count;
|
|
186
|
+
|
|
187
|
+
let open = Lexer.OPEN(value, index);
|
|
188
|
+
if (open) {
|
|
189
|
+
index = open;
|
|
190
|
+
|
|
191
|
+
let option = Query.expandCountOption(value, index);
|
|
192
|
+
if (!option) return;
|
|
193
|
+
|
|
194
|
+
let countOptions = [];
|
|
195
|
+
while (option) {
|
|
196
|
+
countOptions.push(option);
|
|
197
|
+
index = option.next;
|
|
198
|
+
|
|
199
|
+
let semi = Lexer.SEMI(value, index);
|
|
200
|
+
if (semi) {
|
|
201
|
+
index = semi;
|
|
202
|
+
|
|
203
|
+
option = Query.expandCountOption(value, index);
|
|
204
|
+
if (!option) return;
|
|
205
|
+
}else break;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
let close = Lexer.CLOSE(value, index);
|
|
209
|
+
if (!close) return;
|
|
210
|
+
index = close;
|
|
211
|
+
tokenValue.options = countOptions;
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
let open = Lexer.OPEN(value, index);
|
|
215
|
+
if (open) {
|
|
216
|
+
index = open;
|
|
217
|
+
|
|
218
|
+
let option = Query.expandOption(value, index);
|
|
219
|
+
if (!option) return;
|
|
220
|
+
|
|
221
|
+
let options = [];
|
|
222
|
+
while (option) {
|
|
223
|
+
options.push(option);
|
|
224
|
+
index = option.next;
|
|
225
|
+
|
|
226
|
+
let semi = Lexer.SEMI(value, index);
|
|
227
|
+
if (semi) {
|
|
228
|
+
index = semi;
|
|
229
|
+
|
|
230
|
+
option = Query.expandOption(value, index);
|
|
231
|
+
if (!option) return;
|
|
232
|
+
}else break;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let close = Lexer.CLOSE(value, index);
|
|
236
|
+
if (!close) return;
|
|
237
|
+
index = close;
|
|
238
|
+
tokenValue.options = options;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return Lexer.tokenize(value, start, index, tokenValue, Lexer.TokenType.ExpandItem);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export function expandCountOption(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
247
|
+
return Query.filter(value, index) ||
|
|
248
|
+
Query.search(value, index);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export function expandRefOption(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
252
|
+
return Query.expandCountOption(value, index) ||
|
|
253
|
+
Query.orderby(value, index) ||
|
|
254
|
+
Query.skip(value, index) ||
|
|
255
|
+
Query.top(value, index) ||
|
|
256
|
+
Query.inlinecount(value, index);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export function expandOption(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
260
|
+
return Query.expandRefOption(value, index) ||
|
|
261
|
+
Query.select(value, index) ||
|
|
262
|
+
Query.expand(value, index) ||
|
|
263
|
+
Query.levels(value, index);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function expandPath(value: Utils.SourceArray, index: number, metadataContext?: any): Lexer.Token {
|
|
267
|
+
let start = index;
|
|
268
|
+
let path = [];
|
|
269
|
+
|
|
270
|
+
let token = NameOrIdentifier.qualifiedEntityTypeName(value, index, metadataContext) ||
|
|
271
|
+
NameOrIdentifier.qualifiedComplexTypeName(value, index, metadataContext);
|
|
272
|
+
|
|
273
|
+
if (token) {
|
|
274
|
+
index = token.next;
|
|
275
|
+
path.push(token);
|
|
276
|
+
if (value[index] !== 0x2f) return;
|
|
277
|
+
index++;
|
|
278
|
+
metadataContext = token.value.metadata;
|
|
279
|
+
delete token.value.metadata;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
let complex = NameOrIdentifier.complexProperty(value, index, metadataContext) ||
|
|
283
|
+
NameOrIdentifier.complexColProperty(value, index, metadataContext);
|
|
284
|
+
while (complex) {
|
|
285
|
+
if (value[complex.next] === 0x2f) {
|
|
286
|
+
index = complex.next + 1;
|
|
287
|
+
path.push(complex);
|
|
288
|
+
|
|
289
|
+
let complexTypeName = NameOrIdentifier.qualifiedComplexTypeName(value, index, metadataContext);
|
|
290
|
+
if (complexTypeName) {
|
|
291
|
+
if (value[complexTypeName.next] === 0x2f) {
|
|
292
|
+
index = complexTypeName.next + 1;
|
|
293
|
+
path.push(complexTypeName);
|
|
294
|
+
}
|
|
295
|
+
metadataContext = complexTypeName.value.metadata;
|
|
296
|
+
delete complexTypeName.value.metadata;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
complex = NameOrIdentifier.complexProperty(value, index, metadataContext) ||
|
|
300
|
+
NameOrIdentifier.complexColProperty(value, index, metadataContext);
|
|
301
|
+
}else break;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
let nav = NameOrIdentifier.navigationProperty(value, index, metadataContext);
|
|
305
|
+
|
|
306
|
+
if (!nav) return;
|
|
307
|
+
index = nav.next;
|
|
308
|
+
path.push(nav);
|
|
309
|
+
metadataContext = nav.metadata;
|
|
310
|
+
delete nav.metadata;
|
|
311
|
+
|
|
312
|
+
if (value[index] === 0x2f) {
|
|
313
|
+
let typeName = NameOrIdentifier.qualifiedEntityTypeName(value, index + 1, metadataContext);
|
|
314
|
+
if (typeName) {
|
|
315
|
+
index = typeName.next;
|
|
316
|
+
path.push(typeName);
|
|
317
|
+
metadataContext = typeName.value.metadata;
|
|
318
|
+
delete typeName.value.metadata;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return Lexer.tokenize(value, start, index, path, Lexer.TokenType.ExpandPath);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export function search(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
326
|
+
let start = index;
|
|
327
|
+
if (Utils.equals(value, index, "%24search")) {
|
|
328
|
+
index += 9;
|
|
329
|
+
}else
|
|
330
|
+
if (Utils.equals(value, index, "$search")) {
|
|
331
|
+
index += 7;
|
|
332
|
+
}else return;
|
|
333
|
+
|
|
334
|
+
let eq = Lexer.EQ(value, index);
|
|
335
|
+
if (!eq) return;
|
|
336
|
+
index = eq;
|
|
337
|
+
|
|
338
|
+
let expr = Query.searchExpr(value, index);
|
|
339
|
+
if (!expr) return;
|
|
340
|
+
index = expr.next;
|
|
341
|
+
|
|
342
|
+
return Lexer.tokenize(value, start, index, expr, Lexer.TokenType.Search);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export function searchExpr(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
346
|
+
let token = Query.searchParenExpr(value, index) ||
|
|
347
|
+
Query.searchTerm(value, index);
|
|
348
|
+
|
|
349
|
+
if (!token) return;
|
|
350
|
+
index = token.next;
|
|
351
|
+
|
|
352
|
+
let expr = Query.searchAndExpr(value, index) ||
|
|
353
|
+
Query.searchOrExpr(value, index);
|
|
354
|
+
|
|
355
|
+
if (expr) {
|
|
356
|
+
const left = Lexer.clone(token);
|
|
357
|
+
token.next = expr.value.next;
|
|
358
|
+
token.value = {
|
|
359
|
+
left: left,
|
|
360
|
+
right: expr.value
|
|
361
|
+
};
|
|
362
|
+
token.type = expr.type;
|
|
363
|
+
token.raw = Utils.stringify(value, token.position, token.next);
|
|
364
|
+
|
|
365
|
+
if (token.type === Lexer.TokenType.SearchAndExpression && token.value.right.type === Lexer.TokenType.SearchOrExpression) {
|
|
366
|
+
token.value.left = Lexer.tokenize(value, token.value.left.position, token.value.right.value.left.next, {
|
|
367
|
+
left: token.value.left,
|
|
368
|
+
right: token.value.right.value.left
|
|
369
|
+
}, token.type);
|
|
370
|
+
token.type = token.value.right.type;
|
|
371
|
+
token.value.right = token.value.right.value.right;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return token;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export function searchTerm(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
379
|
+
return Query.searchNotExpr(value, index) ||
|
|
380
|
+
Query.searchPhrase(value, index) ||
|
|
381
|
+
Query.searchWord(value, index);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export function searchNotExpr(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
385
|
+
let rws = Lexer.RWS(value, index);
|
|
386
|
+
if (!Utils.equals(value, rws, "NOT")) return;
|
|
387
|
+
let start = index;
|
|
388
|
+
index = rws + 3;
|
|
389
|
+
rws = Lexer.RWS(value, index);
|
|
390
|
+
if (rws === index) return;
|
|
391
|
+
index = rws;
|
|
392
|
+
let expr = Query.searchPhrase(value, index) ||
|
|
393
|
+
Query.searchWord(value, index);
|
|
394
|
+
if (!expr) return;
|
|
395
|
+
index = expr.next;
|
|
396
|
+
|
|
397
|
+
return Lexer.tokenize(value, start, index, expr, Lexer.TokenType.SearchNotExpression);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export function searchOrExpr(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
401
|
+
let rws = Lexer.RWS(value, index);
|
|
402
|
+
if (rws === index || !Utils.equals(value, rws, "OR")) return;
|
|
403
|
+
let start = index;
|
|
404
|
+
index = rws + 2;
|
|
405
|
+
rws = Lexer.RWS(value, index);
|
|
406
|
+
if (rws === index) return;
|
|
407
|
+
index = rws;
|
|
408
|
+
let token = Query.searchExpr(value, index);
|
|
409
|
+
if (!token) return;
|
|
410
|
+
index = token.next;
|
|
411
|
+
|
|
412
|
+
return Lexer.tokenize(value, start, index, token, Lexer.TokenType.SearchOrExpression);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export function searchAndExpr(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
416
|
+
let rws = Lexer.RWS(value, index);
|
|
417
|
+
if (rws === index || !Utils.equals(value, rws, "AND")) return;
|
|
418
|
+
let start = index;
|
|
419
|
+
index = rws + 3;
|
|
420
|
+
rws = Lexer.RWS(value, index);
|
|
421
|
+
if (rws === index) return;
|
|
422
|
+
index = rws;
|
|
423
|
+
let token = Query.searchExpr(value, index);
|
|
424
|
+
if (!token) return;
|
|
425
|
+
index = token.next;
|
|
426
|
+
|
|
427
|
+
return Lexer.tokenize(value, start, index, token, Lexer.TokenType.SearchAndExpression);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
export function searchPhrase(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
431
|
+
let mark = Lexer.quotationMark(value, index);
|
|
432
|
+
if (mark === index) return;
|
|
433
|
+
let start = index;
|
|
434
|
+
index = mark;
|
|
435
|
+
|
|
436
|
+
let valueStart = index;
|
|
437
|
+
let ch = Lexer.qcharNoAMPDQUOTE(value, index);
|
|
438
|
+
while (ch > index && !Lexer.OPEN(value, index) && !Lexer.CLOSE(value, index)) {
|
|
439
|
+
index = ch;
|
|
440
|
+
ch = Lexer.qcharNoAMPDQUOTE(value, index);
|
|
441
|
+
}
|
|
442
|
+
let valueEnd = index;
|
|
443
|
+
|
|
444
|
+
mark = Lexer.quotationMark(value, index);
|
|
445
|
+
if (!mark) return;
|
|
446
|
+
index = mark;
|
|
447
|
+
|
|
448
|
+
return Lexer.tokenize(value, start, index, Utils.stringify(value, valueStart, valueEnd), Lexer.TokenType.SearchPhrase);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
export function searchWord(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
452
|
+
let next = Utils.required(value, index, Lexer.ALPHA, 1);
|
|
453
|
+
if (!next) return;
|
|
454
|
+
let start = index;
|
|
455
|
+
index = next;
|
|
456
|
+
|
|
457
|
+
let token = Lexer.tokenize(value, start, index, null, Lexer.TokenType.SearchWord);
|
|
458
|
+
token.value = token.raw;
|
|
459
|
+
return token;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
export function searchParenExpr(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
463
|
+
let open = Lexer.OPEN(value, index);
|
|
464
|
+
if (!open) return;
|
|
465
|
+
let start = index;
|
|
466
|
+
index = open;
|
|
467
|
+
index = Lexer.BWS(value, index);
|
|
468
|
+
|
|
469
|
+
let expr = Query.searchExpr(value, index);
|
|
470
|
+
if (!expr) return;
|
|
471
|
+
index = expr.next;
|
|
472
|
+
|
|
473
|
+
index = Lexer.BWS(value, index);
|
|
474
|
+
let close = Lexer.CLOSE(value, index);
|
|
475
|
+
if (!close) return;
|
|
476
|
+
index = close;
|
|
477
|
+
|
|
478
|
+
return Lexer.tokenize(value, start, index, expr, Lexer.TokenType.SearchParenExpression);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
export function levels(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
482
|
+
let start = index;
|
|
483
|
+
if (Utils.equals(value, index, "%24levels")) {
|
|
484
|
+
index += 9;
|
|
485
|
+
}else
|
|
486
|
+
if (Utils.equals(value, index, "$levels")) {
|
|
487
|
+
index += 7;
|
|
488
|
+
}else return;
|
|
489
|
+
|
|
490
|
+
let eq = Lexer.EQ(value, index);
|
|
491
|
+
if (!eq) return;
|
|
492
|
+
index = eq;
|
|
493
|
+
|
|
494
|
+
let level;
|
|
495
|
+
if (Utils.equals(value, index, "max")) {
|
|
496
|
+
level = "max";
|
|
497
|
+
index += 3;
|
|
498
|
+
} else {
|
|
499
|
+
let token = PrimitiveLiteral.int32Value(value, index);
|
|
500
|
+
if (!token) return;
|
|
501
|
+
level = token.raw;
|
|
502
|
+
index = token.next;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
return Lexer.tokenize(value, start, index, level, Lexer.TokenType.Levels);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
export function filter(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
509
|
+
let start = index;
|
|
510
|
+
if (Utils.equals(value, index, "%24filter")) {
|
|
511
|
+
index += 9;
|
|
512
|
+
}else
|
|
513
|
+
if (Utils.equals(value, index, "$filter")) {
|
|
514
|
+
index += 7;
|
|
515
|
+
}else return;
|
|
516
|
+
|
|
517
|
+
let eq = Lexer.EQ(value, index);
|
|
518
|
+
if (!eq) return;
|
|
519
|
+
index = eq;
|
|
520
|
+
|
|
521
|
+
let expr = Expressions.boolCommonExpr(value, index);
|
|
522
|
+
if (!expr) return;
|
|
523
|
+
index = expr.next;
|
|
524
|
+
|
|
525
|
+
return Lexer.tokenize(value, start, index, expr, Lexer.TokenType.Filter);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
export function orderby(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
529
|
+
let start = index;
|
|
530
|
+
if (Utils.equals(value, index, "%24orderby")) {
|
|
531
|
+
index += 10;
|
|
532
|
+
}else
|
|
533
|
+
if (Utils.equals(value, index, "$orderby")) {
|
|
534
|
+
index += 8;
|
|
535
|
+
}else return;
|
|
536
|
+
|
|
537
|
+
let eq = Lexer.EQ(value, index);
|
|
538
|
+
if (!eq) return;
|
|
539
|
+
index = eq;
|
|
540
|
+
|
|
541
|
+
let items = [];
|
|
542
|
+
let token = Query.orderbyItem(value, index);
|
|
543
|
+
if (!token) return;
|
|
544
|
+
index = token.next;
|
|
545
|
+
|
|
546
|
+
while (token) {
|
|
547
|
+
items.push(token);
|
|
548
|
+
|
|
549
|
+
let comma = Lexer.COMMA(value, index);
|
|
550
|
+
if (comma) {
|
|
551
|
+
index = comma;
|
|
552
|
+
token = Query.orderbyItem(value, index);
|
|
553
|
+
if (!token) return;
|
|
554
|
+
index = token.next;
|
|
555
|
+
}else break;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
return Lexer.tokenize(value, start, index, { items }, Lexer.TokenType.OrderBy);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
export function orderbyItem(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
562
|
+
let expr = Expressions.commonExpr(value, index);
|
|
563
|
+
if (!expr) return;
|
|
564
|
+
let start = index;
|
|
565
|
+
index = expr.next;
|
|
566
|
+
|
|
567
|
+
let direction = 1;
|
|
568
|
+
let rws = Lexer.RWS(value, index);
|
|
569
|
+
if (rws > index) {
|
|
570
|
+
index = rws;
|
|
571
|
+
if (Utils.equals(value, index, "asc")) index += 3;
|
|
572
|
+
else if (Utils.equals(value, index, "desc")) {
|
|
573
|
+
index += 4;
|
|
574
|
+
direction = -1;
|
|
575
|
+
}else return;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
return Lexer.tokenize(value, start, index, { expr, direction }, Lexer.TokenType.OrderByItem);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
export function skip(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
582
|
+
let start = index;
|
|
583
|
+
if (Utils.equals(value, index, "%24skip")) {
|
|
584
|
+
index += 7;
|
|
585
|
+
}else
|
|
586
|
+
if (Utils.equals(value, index, "$skip")) {
|
|
587
|
+
index += 5;
|
|
588
|
+
}else return;
|
|
589
|
+
|
|
590
|
+
let eq = Lexer.EQ(value, index);
|
|
591
|
+
if (!eq) return;
|
|
592
|
+
index = eq;
|
|
593
|
+
|
|
594
|
+
let token = PrimitiveLiteral.int32Value(value, index);
|
|
595
|
+
if (!token) return;
|
|
596
|
+
index = token.next;
|
|
597
|
+
|
|
598
|
+
return Lexer.tokenize(value, start, index, token, Lexer.TokenType.Skip);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
export function top(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
602
|
+
let start = index;
|
|
603
|
+
if (Utils.equals(value, index, "%24top")) {
|
|
604
|
+
index += 6;
|
|
605
|
+
}else
|
|
606
|
+
if (Utils.equals(value, index, "$top")) {
|
|
607
|
+
index += 4;
|
|
608
|
+
}else return;
|
|
609
|
+
|
|
610
|
+
let eq = Lexer.EQ(value, index);
|
|
611
|
+
if (!eq) return;
|
|
612
|
+
index = eq;
|
|
613
|
+
|
|
614
|
+
let token = PrimitiveLiteral.int32Value(value, index);
|
|
615
|
+
if (!token) return;
|
|
616
|
+
index = token.next;
|
|
617
|
+
|
|
618
|
+
return Lexer.tokenize(value, start, index, token, Lexer.TokenType.Top);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
export function format(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
622
|
+
let start = index;
|
|
623
|
+
if (Utils.equals(value, index, "%24format")) {
|
|
624
|
+
index += 9;
|
|
625
|
+
}else
|
|
626
|
+
if (Utils.equals(value, index, "$format")) {
|
|
627
|
+
index += 7;
|
|
628
|
+
}else return;
|
|
629
|
+
|
|
630
|
+
let eq = Lexer.EQ(value, index);
|
|
631
|
+
if (!eq) return;
|
|
632
|
+
index = eq;
|
|
633
|
+
|
|
634
|
+
let format;
|
|
635
|
+
if (Utils.equals(value, index, "atom")) {
|
|
636
|
+
format = "atom";
|
|
637
|
+
index += 4;
|
|
638
|
+
}else if (Utils.equals(value, index, "json")) {
|
|
639
|
+
format = "json";
|
|
640
|
+
index += 4;
|
|
641
|
+
}else if (Utils.equals(value, index, "xml")) {
|
|
642
|
+
format = "xml";
|
|
643
|
+
index += 3;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
if (format) return Lexer.tokenize(value, start, index, { format }, Lexer.TokenType.Format);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
export function inlinecount(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
650
|
+
let start = index;
|
|
651
|
+
if (Utils.equals(value, index, "%24count")) {
|
|
652
|
+
index += 8;
|
|
653
|
+
}else
|
|
654
|
+
if (Utils.equals(value, index, "$count")) {
|
|
655
|
+
index += 6;
|
|
656
|
+
}else return;
|
|
657
|
+
|
|
658
|
+
let eq = Lexer.EQ(value, index);
|
|
659
|
+
if (!eq) return;
|
|
660
|
+
index = eq;
|
|
661
|
+
|
|
662
|
+
let token = PrimitiveLiteral.booleanValue(value, index);
|
|
663
|
+
if (!token) return;
|
|
664
|
+
index = token.next;
|
|
665
|
+
|
|
666
|
+
return Lexer.tokenize(value, start, index, token, Lexer.TokenType.InlineCount);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
export function select(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
670
|
+
let start = index;
|
|
671
|
+
if (Utils.equals(value, index, "%24select")) {
|
|
672
|
+
index += 9;
|
|
673
|
+
}else
|
|
674
|
+
if (Utils.equals(value, index, "$select")) {
|
|
675
|
+
index += 7;
|
|
676
|
+
}else return;
|
|
677
|
+
|
|
678
|
+
let eq = Lexer.EQ(value, index);
|
|
679
|
+
if (!eq) return;
|
|
680
|
+
index = eq;
|
|
681
|
+
|
|
682
|
+
let items = [];
|
|
683
|
+
let token = Query.selectItem(value, index);
|
|
684
|
+
if (!token) return;
|
|
685
|
+
while (token) {
|
|
686
|
+
items.push(token);
|
|
687
|
+
index = token.next;
|
|
688
|
+
|
|
689
|
+
let comma = Lexer.COMMA(value, index);
|
|
690
|
+
if (comma) {
|
|
691
|
+
index = comma;
|
|
692
|
+
token = Query.selectItem(value, index);
|
|
693
|
+
if (!token) return;
|
|
694
|
+
}else break;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
return Lexer.tokenize(value, start, index, { items }, Lexer.TokenType.Select);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
export function selectItem(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
701
|
+
let start = index;
|
|
702
|
+
let item;
|
|
703
|
+
let op = Query.allOperationsInSchema(value, index);
|
|
704
|
+
let star = Lexer.STAR(value, index);
|
|
705
|
+
if (op > index) {
|
|
706
|
+
item = { namespace: Utils.stringify(value, index, op - 2), value: "*" };
|
|
707
|
+
index = op;
|
|
708
|
+
}else if (star) {
|
|
709
|
+
item = { value: "*" };
|
|
710
|
+
index = star;
|
|
711
|
+
} else {
|
|
712
|
+
item = {};
|
|
713
|
+
let name = NameOrIdentifier.qualifiedEntityTypeName(value, index) ||
|
|
714
|
+
NameOrIdentifier.qualifiedComplexTypeName(value, index);
|
|
715
|
+
|
|
716
|
+
if (name && value[name.next] !== 0x2f) return;
|
|
717
|
+
else if (name && value[name.next] === 0x2f) {
|
|
718
|
+
index++;
|
|
719
|
+
item.name = name;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
let select = Query.selectProperty(value, index) ||
|
|
723
|
+
Query.qualifiedActionName(value, index) ||
|
|
724
|
+
Query.qualifiedFunctionName(value, index);
|
|
725
|
+
if (!select) return;
|
|
726
|
+
index = select.next;
|
|
727
|
+
|
|
728
|
+
item = name ? { name, select } : select;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
if (index > start) return Lexer.tokenize(value, start, index, item, Lexer.TokenType.SelectItem);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
export function allOperationsInSchema(value: Utils.SourceArray, index: number): number {
|
|
735
|
+
let namespaceNext = NameOrIdentifier.namespace(value, index);
|
|
736
|
+
let star = Lexer.STAR(value, namespaceNext + 1);
|
|
737
|
+
if (namespaceNext > index && value[namespaceNext] === 0x2e && star) return star;
|
|
738
|
+
return index;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
export function selectProperty(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
742
|
+
let token = Query.selectPath(value, index) ||
|
|
743
|
+
NameOrIdentifier.primitiveProperty(value, index) ||
|
|
744
|
+
NameOrIdentifier.primitiveColProperty(value, index) ||
|
|
745
|
+
NameOrIdentifier.navigationProperty(value, index);
|
|
746
|
+
if (!token) return;
|
|
747
|
+
let start = index;
|
|
748
|
+
index = token.next;
|
|
749
|
+
|
|
750
|
+
if (token.type === Lexer.TokenType.SelectPath) {
|
|
751
|
+
if (value[index] === 0x2f) {
|
|
752
|
+
index++;
|
|
753
|
+
let prop = Query.selectProperty(value, index);
|
|
754
|
+
|
|
755
|
+
if (!prop) return;
|
|
756
|
+
let path = Lexer.clone(token);
|
|
757
|
+
token.next = prop.next;
|
|
758
|
+
token.raw = Utils.stringify(value, start, token.next);
|
|
759
|
+
token.value = { path, next: prop };
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
return token;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
export function selectPath(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
767
|
+
let token = NameOrIdentifier.complexProperty(value, index) ||
|
|
768
|
+
NameOrIdentifier.complexColProperty(value, index);
|
|
769
|
+
|
|
770
|
+
if (!token) return;
|
|
771
|
+
let start = index;
|
|
772
|
+
index = token.next;
|
|
773
|
+
|
|
774
|
+
let tokenValue: any = token;
|
|
775
|
+
if (value[index] === 0x2f) {
|
|
776
|
+
let name = NameOrIdentifier.qualifiedComplexTypeName(value, index + 1);
|
|
777
|
+
if (name) {
|
|
778
|
+
index = name.next;
|
|
779
|
+
tokenValue = { prop: token, name };
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
return Lexer.tokenize(value, start, index, tokenValue, Lexer.TokenType.SelectPath);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
export function qualifiedActionName(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
787
|
+
let namespaceNext = NameOrIdentifier.namespace(value, index);
|
|
788
|
+
if (namespaceNext === index || value[namespaceNext] !== 0x2e) return;
|
|
789
|
+
let start = index;
|
|
790
|
+
index = namespaceNext + 1;
|
|
791
|
+
|
|
792
|
+
let action = NameOrIdentifier.action(value, index);
|
|
793
|
+
if (!action) return;
|
|
794
|
+
action.value.namespace = Utils.stringify(value, start, namespaceNext);
|
|
795
|
+
|
|
796
|
+
return Lexer.tokenize(value, start, action.next, action, Lexer.TokenType.Action);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
export function qualifiedFunctionName(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
800
|
+
let namespaceNext = NameOrIdentifier.namespace(value, index);
|
|
801
|
+
if (namespaceNext === index || value[namespaceNext] !== 0x2e) return;
|
|
802
|
+
let start = index;
|
|
803
|
+
index = namespaceNext + 1;
|
|
804
|
+
|
|
805
|
+
let fn = NameOrIdentifier.odataFunction(value, index);
|
|
806
|
+
if (!fn) return;
|
|
807
|
+
fn.value.namespace = Utils.stringify(value, start, namespaceNext);
|
|
808
|
+
index = fn.next;
|
|
809
|
+
let tokenValue: any = { name: fn };
|
|
810
|
+
|
|
811
|
+
let open = Lexer.OPEN(value, index);
|
|
812
|
+
if (open) {
|
|
813
|
+
index = open;
|
|
814
|
+
tokenValue.parameters = [];
|
|
815
|
+
let param = Expressions.parameterName(value, index);
|
|
816
|
+
if (!param) return;
|
|
817
|
+
|
|
818
|
+
while (param) {
|
|
819
|
+
index = param.next;
|
|
820
|
+
tokenValue.parameters.push(param);
|
|
821
|
+
|
|
822
|
+
let comma = Lexer.COMMA(value, index);
|
|
823
|
+
if (comma) {
|
|
824
|
+
index = comma;
|
|
825
|
+
let param = Expressions.parameterName(value, index);
|
|
826
|
+
if (!param) return;
|
|
827
|
+
}else break;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
let close = Lexer.CLOSE(value, index);
|
|
831
|
+
if (!close) return;
|
|
832
|
+
index = close;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
return Lexer.tokenize(value, start, index, tokenValue, Lexer.TokenType.Function);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
export function skiptoken(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
839
|
+
let start = index;
|
|
840
|
+
if (Utils.equals(value, index, "%24skiptoken")) {
|
|
841
|
+
index += 12;
|
|
842
|
+
}else
|
|
843
|
+
if (Utils.equals(value, index, "$skiptoken")) {
|
|
844
|
+
index += 10;
|
|
845
|
+
}else return;
|
|
846
|
+
|
|
847
|
+
let eq = Lexer.EQ(value, index);
|
|
848
|
+
if (!eq) return;
|
|
849
|
+
index = eq;
|
|
850
|
+
|
|
851
|
+
let ch = Lexer.qcharNoAMP(value, index);
|
|
852
|
+
if (!ch) return;
|
|
853
|
+
let valueStart = index;
|
|
854
|
+
|
|
855
|
+
while (ch > index) {
|
|
856
|
+
index = ch;
|
|
857
|
+
ch = Lexer.qcharNoAMP(value, index);
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
return Lexer.tokenize(value, start, index, Utils.stringify(value, valueStart, index), Lexer.TokenType.SkipToken);
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
export function aliasAndValue(value: Utils.SourceArray, index: number): Lexer.Token {
|
|
864
|
+
let alias = Expressions.parameterAlias(value, index);
|
|
865
|
+
if (!alias) return;
|
|
866
|
+
let start = index;
|
|
867
|
+
index = alias.next;
|
|
868
|
+
|
|
869
|
+
let eq = Lexer.EQ(value, index);
|
|
870
|
+
if (!eq) return;
|
|
871
|
+
index = eq;
|
|
872
|
+
|
|
873
|
+
let paramValue = Expressions.parameterValue(value, index);
|
|
874
|
+
if (!paramValue) return;
|
|
875
|
+
index = paramValue.next;
|
|
876
|
+
|
|
877
|
+
return Lexer.tokenize(value, start, index, {
|
|
878
|
+
alias,
|
|
879
|
+
value: paramValue
|
|
880
|
+
}, Lexer.TokenType.AliasAndValue);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
export default Query;
|