@malloydata/malloy-filter 0.0.237-dev250222025222 → 0.0.237-dev250222205057
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/dist/a_simple_parser.js +12 -9
- package/dist/a_simple_parser.js.map +1 -1
- package/dist/base_parser.d.ts +0 -2
- package/dist/base_parser.js.map +1 -1
- package/dist/boolean_parser.d.ts +2 -2
- package/dist/boolean_parser.js +3 -1
- package/dist/boolean_parser.js.map +1 -1
- package/dist/boolean_serializer.d.ts +4 -4
- package/dist/boolean_serializer.js +12 -4
- package/dist/boolean_serializer.js.map +1 -1
- package/dist/clause_types.d.ts +40 -47
- package/dist/date_parser.d.ts +13 -11
- package/dist/date_parser.js +192 -131
- package/dist/date_parser.js.map +1 -1
- package/dist/date_serializer.d.ts +6 -5
- package/dist/date_serializer.js +65 -77
- package/dist/date_serializer.js.map +1 -1
- package/dist/date_types.d.ts +75 -0
- package/dist/{filter_types.js → date_types.js} +1 -1
- package/dist/date_types.js.map +1 -0
- package/dist/generate_samples.js +162 -87
- package/dist/generate_samples.js.map +1 -1
- package/dist/number_parser.d.ts +2 -5
- package/dist/number_parser.js +10 -51
- package/dist/number_parser.js.map +1 -1
- package/dist/number_serializer.d.ts +4 -4
- package/dist/number_serializer.js +17 -14
- package/dist/number_serializer.js.map +1 -1
- package/dist/string_parser.d.ts +2 -2
- package/dist/string_parser.js +21 -21
- package/dist/string_parser.js.map +1 -1
- package/dist/string_serializer.d.ts +6 -5
- package/dist/string_serializer.js +38 -24
- package/dist/string_serializer.js.map +1 -1
- package/package.json +1 -2
- package/src/DEVELOPING.md +2 -5
- package/src/a_simple_parser.ts +12 -9
- package/src/base_parser.ts +0 -3
- package/src/boolean_parser.ts +10 -5
- package/src/boolean_serializer.ts +14 -7
- package/src/clause_types.ts +65 -108
- package/src/date_parser.ts +229 -192
- package/src/date_serializer.ts +59 -87
- package/src/date_types.ts +159 -0
- package/src/generate_samples.ts +178 -109
- package/src/number_parser.ts +14 -63
- package/src/number_serializer.ts +19 -20
- package/src/string_parser.ts +40 -27
- package/src/string_serializer.ts +58 -32
- package/tsconfig.json +1 -6
- package/dist/a_simple_serializer.d.ts +0 -1
- package/dist/a_simple_serializer.js +0 -31
- package/dist/a_simple_serializer.js.map +0 -1
- package/dist/base_serializer.d.ts +0 -6
- package/dist/base_serializer.js +0 -11
- package/dist/base_serializer.js.map +0 -1
- package/dist/filter_parser.d.ts +0 -12
- package/dist/filter_parser.js +0 -66
- package/dist/filter_parser.js.map +0 -1
- package/dist/filter_serializer.d.ts +0 -13
- package/dist/filter_serializer.js +0 -43
- package/dist/filter_serializer.js.map +0 -1
- package/dist/filter_types.d.ts +0 -10
- package/dist/filter_types.js.map +0 -1
- package/src/a_simple_serializer.ts +0 -40
- package/src/base_serializer.ts +0 -9
- package/src/filter_parser.ts +0 -68
- package/src/filter_serializer.ts +0 -49
- package/src/filter_types.ts +0 -12
package/src/generate_samples.ts
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import {Clause} from './clause_types';
|
|
2
1
|
import {SpecialToken, Tokenizer, TokenizerParams} from './tokenizer';
|
|
3
2
|
import {BooleanParser} from './boolean_parser';
|
|
4
3
|
import {StringParser} from './string_parser';
|
|
5
4
|
import {NumberParser} from './number_parser';
|
|
6
5
|
import {DateParser} from './date_parser';
|
|
7
|
-
import {BaseParser} from './base_parser';
|
|
8
6
|
import {BooleanSerializer} from './boolean_serializer';
|
|
9
7
|
import {StringSerializer} from './string_serializer';
|
|
10
8
|
import {NumberSerializer} from './number_serializer';
|
|
11
9
|
import {DateSerializer} from './date_serializer';
|
|
12
|
-
import {
|
|
10
|
+
import {BooleanClause, NumberClause, StringClause} from './clause_types';
|
|
11
|
+
import {DateClause} from './date_types';
|
|
12
|
+
|
|
13
|
+
type Clause = BooleanClause | DateClause | NumberClause | StringClause;
|
|
13
14
|
|
|
14
15
|
const numberExamples = [
|
|
15
16
|
'5',
|
|
16
17
|
'!=5',
|
|
17
|
-
'1, 3,
|
|
18
|
+
'1, 3, 5, null',
|
|
18
19
|
'<1, >=100 ',
|
|
19
20
|
'>=1',
|
|
20
21
|
' <= 10 ',
|
|
@@ -69,9 +70,10 @@ const stringExamples = [
|
|
|
69
70
|
const booleanExamples = [
|
|
70
71
|
'true',
|
|
71
72
|
'FALSE',
|
|
73
|
+
'=false',
|
|
72
74
|
'null',
|
|
73
75
|
'-NULL',
|
|
74
|
-
' True , faLSE,NULl,-null',
|
|
76
|
+
' True , faLSE,=false,NULl,-null',
|
|
75
77
|
"-'null'",
|
|
76
78
|
'10',
|
|
77
79
|
'nnull',
|
|
@@ -88,7 +90,7 @@ const dateExamples = [
|
|
|
88
90
|
'before 3 days ago',
|
|
89
91
|
'before 2025-08-30 08:30:20',
|
|
90
92
|
'after 2025-10-05',
|
|
91
|
-
'2025-08-30 12:00
|
|
93
|
+
'2025-08-30 12:00 to 2025-09-18 14:30',
|
|
92
94
|
'this year',
|
|
93
95
|
'next tuesday',
|
|
94
96
|
'7 years from now',
|
|
@@ -103,11 +105,14 @@ const dateExamples = [
|
|
|
103
105
|
'next week',
|
|
104
106
|
'now',
|
|
105
107
|
'now to next month',
|
|
108
|
+
'null',
|
|
109
|
+
'-null,',
|
|
106
110
|
' yyesterday ', // Typo
|
|
107
111
|
'before', // Bad syntax
|
|
108
112
|
'for', // Bad syntax
|
|
109
113
|
'7', // Bad syntax
|
|
110
114
|
'from now', // Bad syntax
|
|
115
|
+
'2025-12-25 12:32:', // Bad syntax
|
|
111
116
|
'',
|
|
112
117
|
];
|
|
113
118
|
|
|
@@ -207,77 +212,89 @@ function testTokenizerNumber() {
|
|
|
207
212
|
}
|
|
208
213
|
}
|
|
209
214
|
|
|
210
|
-
function
|
|
215
|
+
function testNumberParserSingle(
|
|
211
216
|
str: string,
|
|
212
|
-
parser: BaseParser,
|
|
213
217
|
outputFormatter?: (clauses: Clause[]) => string
|
|
214
218
|
): void {
|
|
215
219
|
console.log('Input: ', str);
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
if (response.errors && response.errors.length > 0) {
|
|
227
|
-
console.log('Errors: ', ...response.errors);
|
|
228
|
-
}
|
|
229
|
-
} catch (ex: Error | unknown) {
|
|
230
|
-
if (ex instanceof Error) console.error('Thrown Error: ', ex.message);
|
|
231
|
-
else {
|
|
232
|
-
console.error('Thrown Unknown error: ', ex);
|
|
220
|
+
const parser = new NumberParser(str);
|
|
221
|
+
const response = parser.parse();
|
|
222
|
+
// console.log('Tokens: ', parser.getTokens());
|
|
223
|
+
if (response.clauses && response.clauses.length > 0) {
|
|
224
|
+
if (outputFormatter) {
|
|
225
|
+
console.log('Output: ', outputFormatter(response.clauses));
|
|
226
|
+
} else {
|
|
227
|
+
console.log('Output: ', ...response.clauses);
|
|
233
228
|
}
|
|
234
229
|
}
|
|
230
|
+
if (response.errors && response.errors.length > 0) {
|
|
231
|
+
console.log('Errors: ', ...response.errors);
|
|
232
|
+
}
|
|
235
233
|
console.log('');
|
|
236
234
|
}
|
|
237
235
|
|
|
238
|
-
function
|
|
236
|
+
function testNumberParser() {
|
|
237
|
+
for (const example of numberExamples) {
|
|
238
|
+
testNumberParserSingle(example);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function testStringParserSingle(
|
|
239
243
|
str: string,
|
|
240
|
-
|
|
241
|
-
serializerFunc: (clauses: Clause[]) => BaseSerializer
|
|
244
|
+
outputFormatter?: (clauses: Clause[]) => string
|
|
242
245
|
): void {
|
|
243
|
-
console.log('Input:
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
console.log('Output: '
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
console.log('Errors: ', ...response.errors);
|
|
253
|
-
}
|
|
254
|
-
} catch (ex: Error | unknown) {
|
|
255
|
-
if (ex instanceof Error) console.error('Thrown Error: ', ex.message);
|
|
256
|
-
else {
|
|
257
|
-
console.error('Thrown Unknown error: ', ex);
|
|
246
|
+
console.log('Input: ', str);
|
|
247
|
+
const parser = new StringParser(str);
|
|
248
|
+
const response = parser.parse();
|
|
249
|
+
// console.log('Tokens: ', parser.getTokens());
|
|
250
|
+
if (response.clauses && response.clauses.length > 0) {
|
|
251
|
+
if (outputFormatter) {
|
|
252
|
+
console.log('Output: ', outputFormatter(response.clauses));
|
|
253
|
+
} else {
|
|
254
|
+
console.log('Output: ', ...response.clauses);
|
|
258
255
|
}
|
|
259
256
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
const parser = new NumberParser(example);
|
|
266
|
-
testParserSingle(example, parser);
|
|
257
|
+
if (response.quotes) {
|
|
258
|
+
console.log('Quotes: ', ...response.quotes);
|
|
259
|
+
}
|
|
260
|
+
if (response.errors && response.errors.length > 0) {
|
|
261
|
+
console.log('Errors: ', ...response.errors);
|
|
267
262
|
}
|
|
263
|
+
console.log('');
|
|
268
264
|
}
|
|
269
265
|
|
|
270
266
|
function testStringParser() {
|
|
271
267
|
for (const example of stringExamples) {
|
|
272
268
|
const parser = new StringParser(example);
|
|
273
|
-
|
|
269
|
+
testStringParserSingle(example);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function testBooleanParserSingle(
|
|
274
|
+
str: string,
|
|
275
|
+
outputFormatter?: (clauses: Clause[]) => string
|
|
276
|
+
): void {
|
|
277
|
+
console.log('Input: ', str);
|
|
278
|
+
const parser = new BooleanParser(str);
|
|
279
|
+
const response = parser.parse();
|
|
280
|
+
// console.log('Tokens: ', parser.getTokens());
|
|
281
|
+
if (response.clauses && response.clauses.length > 0) {
|
|
282
|
+
if (outputFormatter) {
|
|
283
|
+
console.log('Output: ', outputFormatter(response.clauses));
|
|
284
|
+
} else {
|
|
285
|
+
console.log('Output: ', ...response.clauses);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (response.errors && response.errors.length > 0) {
|
|
289
|
+
console.log('Errors: ', ...response.errors);
|
|
274
290
|
}
|
|
291
|
+
console.log('');
|
|
275
292
|
}
|
|
276
293
|
|
|
277
294
|
function testBooleanParser() {
|
|
278
295
|
for (const example of booleanExamples) {
|
|
279
296
|
const parser = new BooleanParser(example);
|
|
280
|
-
|
|
297
|
+
testBooleanParserSingle(example);
|
|
281
298
|
}
|
|
282
299
|
}
|
|
283
300
|
|
|
@@ -289,67 +306,112 @@ function jsonFormatter(clauses: Clause[]): string {
|
|
|
289
306
|
return str;
|
|
290
307
|
}
|
|
291
308
|
|
|
309
|
+
function testDateParserSingle(
|
|
310
|
+
str: string,
|
|
311
|
+
outputFormatter?: (clauses: Clause[]) => string
|
|
312
|
+
): void {
|
|
313
|
+
console.log('Input: ', str);
|
|
314
|
+
const parser = new DateParser(str);
|
|
315
|
+
const response = parser.parse();
|
|
316
|
+
// console.log('Tokens: ', parser.getTokens());
|
|
317
|
+
if (response.clauses && response.clauses.length > 0) {
|
|
318
|
+
if (outputFormatter) {
|
|
319
|
+
console.log('Output: ', outputFormatter(response.clauses));
|
|
320
|
+
} else {
|
|
321
|
+
console.log('Output: ', ...response.clauses);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (response.errors && response.errors.length > 0) {
|
|
325
|
+
console.log('Errors: ', ...response.errors);
|
|
326
|
+
}
|
|
327
|
+
console.log('');
|
|
328
|
+
}
|
|
329
|
+
|
|
292
330
|
function testDateParser() {
|
|
293
331
|
for (const example of dateExamples) {
|
|
294
332
|
const parser = new DateParser(example);
|
|
295
|
-
|
|
296
|
-
|
|
333
|
+
testDateParserSingle(example);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function testNumberRoundtrip(str: string): void {
|
|
338
|
+
console.log('Input: ' + str);
|
|
339
|
+
const response = new NumberParser(str).parse();
|
|
340
|
+
// console.log('Clause: ', ...response.clauses, '\n');
|
|
341
|
+
if (response.clauses && response.clauses.length > 0) {
|
|
342
|
+
const result = new NumberSerializer(response.clauses || []).serialize();
|
|
343
|
+
console.log('Output: ' + result);
|
|
344
|
+
}
|
|
345
|
+
if (response.errors && response.errors.length > 0) {
|
|
346
|
+
console.log('Errors: ', ...response.errors);
|
|
297
347
|
}
|
|
348
|
+
console.log('');
|
|
298
349
|
}
|
|
299
350
|
|
|
300
351
|
function testNumberSerializer(): void {
|
|
301
|
-
const examples = [
|
|
302
|
-
[{operator: '>', value: 10}],
|
|
303
|
-
[{startOperator: '>=', startValue: 20, endOperator: '<=', endValue: 30}],
|
|
304
|
-
];
|
|
305
352
|
for (const example of numberExamples) {
|
|
306
|
-
|
|
307
|
-
example,
|
|
308
|
-
new NumberParser(example),
|
|
309
|
-
clauses => new NumberSerializer(clauses)
|
|
310
|
-
);
|
|
353
|
+
testNumberRoundtrip(example);
|
|
311
354
|
}
|
|
312
355
|
}
|
|
313
356
|
|
|
357
|
+
function testStringRoundtrip(str: string): void {
|
|
358
|
+
console.log('Input: ' + str);
|
|
359
|
+
const response = new StringParser(str).parse();
|
|
360
|
+
// console.log('Clause: ', ...response.clauses, '\n');
|
|
361
|
+
if (response.clauses && response.clauses.length > 0) {
|
|
362
|
+
const result = new StringSerializer(response.clauses || []).serialize();
|
|
363
|
+
console.log('Output: ' + result);
|
|
364
|
+
}
|
|
365
|
+
if (response.errors && response.errors.length > 0) {
|
|
366
|
+
console.log('Errors: ', ...response.errors);
|
|
367
|
+
}
|
|
368
|
+
console.log('');
|
|
369
|
+
}
|
|
370
|
+
|
|
314
371
|
function testStringSerializer(): void {
|
|
315
372
|
for (const example of stringExamples) {
|
|
316
|
-
|
|
317
|
-
example,
|
|
318
|
-
new StringParser(example),
|
|
319
|
-
clauses => new StringSerializer(clauses)
|
|
320
|
-
);
|
|
373
|
+
testStringRoundtrip(example);
|
|
321
374
|
}
|
|
322
375
|
}
|
|
323
376
|
|
|
377
|
+
function testBooleanRoundtrip(str: string): void {
|
|
378
|
+
console.log('Input: ' + str);
|
|
379
|
+
const response = new BooleanParser(str).parse();
|
|
380
|
+
// console.log('Clause: ', ...response.clauses, '\n');
|
|
381
|
+
if (response.clauses && response.clauses.length > 0) {
|
|
382
|
+
const result = new BooleanSerializer(response.clauses || []).serialize();
|
|
383
|
+
console.log('Output: ' + result);
|
|
384
|
+
}
|
|
385
|
+
if (response.errors && response.errors.length > 0) {
|
|
386
|
+
console.log('Errors: ', ...response.errors);
|
|
387
|
+
}
|
|
388
|
+
console.log('');
|
|
389
|
+
}
|
|
390
|
+
|
|
324
391
|
function testBooleanSerializer(): void {
|
|
325
392
|
const examples = [[{operator: 'TRUE'}]];
|
|
326
393
|
for (const example of booleanExamples) {
|
|
327
|
-
|
|
328
|
-
example,
|
|
329
|
-
new BooleanParser(example),
|
|
330
|
-
clauses => new BooleanSerializer(clauses)
|
|
331
|
-
);
|
|
394
|
+
testBooleanRoundtrip(example);
|
|
332
395
|
}
|
|
333
396
|
}
|
|
334
397
|
|
|
398
|
+
function testDateRoundtrip(str: string): void {
|
|
399
|
+
console.log('Input: ' + str);
|
|
400
|
+
const response = new DateParser(str).parse();
|
|
401
|
+
// console.log('Clause: ', ...response.clauses, '\n');
|
|
402
|
+
if (response.clauses && response.clauses.length > 0) {
|
|
403
|
+
const result = new DateSerializer(response.clauses || []).serialize();
|
|
404
|
+
console.log('Output: ' + result);
|
|
405
|
+
}
|
|
406
|
+
if (response.errors && response.errors.length > 0) {
|
|
407
|
+
console.log('Errors: ', ...response.errors);
|
|
408
|
+
}
|
|
409
|
+
console.log('');
|
|
410
|
+
}
|
|
411
|
+
|
|
335
412
|
function testDateSerializer(): void {
|
|
336
|
-
const examples = [
|
|
337
|
-
[{prefix: 'BEFORE', values: [{type: 'day', value: 'yesterday'}]}],
|
|
338
|
-
[
|
|
339
|
-
{
|
|
340
|
-
start: [{type: 'day', value: 'today'}],
|
|
341
|
-
operator: 'TO',
|
|
342
|
-
end: [{type: 'day', value: 'tomorrow'}],
|
|
343
|
-
},
|
|
344
|
-
],
|
|
345
|
-
[{type: 'day', value: 'today'}],
|
|
346
|
-
];
|
|
347
413
|
for (const example of dateExamples) {
|
|
348
|
-
|
|
349
|
-
example,
|
|
350
|
-
new DateParser(example),
|
|
351
|
-
clauses => new DateSerializer(clauses)
|
|
352
|
-
);
|
|
414
|
+
testDateRoundtrip(example);
|
|
353
415
|
}
|
|
354
416
|
}
|
|
355
417
|
|
|
@@ -362,26 +424,33 @@ function printHeader(title: string): void {
|
|
|
362
424
|
|
|
363
425
|
// Comment or uncomment the following function calls to disable/enable examples.
|
|
364
426
|
function generateSamples() {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
427
|
+
try {
|
|
428
|
+
//printHeader('Tokenizer');
|
|
429
|
+
//testTokenizerString();
|
|
430
|
+
//testTokenizerNumber();
|
|
431
|
+
//testTokenizerMatchTypes();
|
|
432
|
+
printHeader('Numbers');
|
|
433
|
+
testNumberParser();
|
|
434
|
+
printHeader('Strings');
|
|
435
|
+
testStringParser();
|
|
436
|
+
printHeader('Booleans');
|
|
437
|
+
testBooleanParser();
|
|
438
|
+
printHeader('Dates and Times');
|
|
439
|
+
testDateParser();
|
|
440
|
+
printHeader('Number Serializer');
|
|
441
|
+
testNumberSerializer();
|
|
442
|
+
printHeader('String Serializer');
|
|
443
|
+
testStringSerializer();
|
|
444
|
+
printHeader('Boolean Serializer');
|
|
445
|
+
testBooleanSerializer();
|
|
446
|
+
printHeader('Date and Time Serializer');
|
|
447
|
+
testDateSerializer();
|
|
448
|
+
} catch (ex: Error | unknown) {
|
|
449
|
+
if (ex instanceof Error) console.error('Thrown Error: ', ex.message);
|
|
450
|
+
else {
|
|
451
|
+
console.error('Thrown Unknown error: ', ex);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
385
454
|
}
|
|
386
455
|
|
|
387
456
|
generateSamples();
|
package/src/number_parser.ts
CHANGED
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
NumberOperator,
|
|
6
6
|
NumberRangeOperator,
|
|
7
7
|
NumberClause,
|
|
8
|
-
|
|
8
|
+
NumberParserResponse,
|
|
9
|
+
FilterError,
|
|
9
10
|
} from './clause_types';
|
|
10
11
|
import {BaseParser} from './base_parser';
|
|
11
12
|
import {Token} from './token_types';
|
|
12
|
-
import {FilterParserResponse, FilterError} from './filter_types';
|
|
13
13
|
|
|
14
14
|
export class NumberParser extends BaseParser {
|
|
15
15
|
constructor(input: string) {
|
|
@@ -46,7 +46,7 @@ export class NumberParser extends BaseParser {
|
|
|
46
46
|
this.tokens = tokenizer.parse();
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
public parse():
|
|
49
|
+
public parse(): NumberParserResponse {
|
|
50
50
|
this.index = 0;
|
|
51
51
|
this.tokenize();
|
|
52
52
|
let clauses: NumberClause[] = [];
|
|
@@ -98,7 +98,9 @@ export class NumberParser extends BaseParser {
|
|
|
98
98
|
outputs.push(clause);
|
|
99
99
|
} else if (
|
|
100
100
|
previous !== undefined &&
|
|
101
|
-
previous.operator === clause.operator
|
|
101
|
+
previous.operator === clause.operator &&
|
|
102
|
+
'values' in previous &&
|
|
103
|
+
'values' in clause
|
|
102
104
|
) {
|
|
103
105
|
previous.values.push(...clause.values);
|
|
104
106
|
} else {
|
|
@@ -204,59 +206,6 @@ export class NumberParser extends BaseParser {
|
|
|
204
206
|
return clauses;
|
|
205
207
|
}
|
|
206
208
|
|
|
207
|
-
private static getNegatedType(tokenType: NumberOperator): NumberOperator {
|
|
208
|
-
switch (tokenType) {
|
|
209
|
-
case '<=':
|
|
210
|
-
return '>';
|
|
211
|
-
case '>=':
|
|
212
|
-
return '<';
|
|
213
|
-
case '<':
|
|
214
|
-
return '>';
|
|
215
|
-
case '>':
|
|
216
|
-
return '<';
|
|
217
|
-
case '=':
|
|
218
|
-
return '!=';
|
|
219
|
-
case '!=':
|
|
220
|
-
return '=';
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
private static getNumberOperator(
|
|
225
|
-
tokenType: string
|
|
226
|
-
): NumberOperator | undefined {
|
|
227
|
-
switch (tokenType) {
|
|
228
|
-
case '<=':
|
|
229
|
-
return '<=';
|
|
230
|
-
case '>=':
|
|
231
|
-
return '>=';
|
|
232
|
-
case '<':
|
|
233
|
-
return '<';
|
|
234
|
-
case '>':
|
|
235
|
-
return '>';
|
|
236
|
-
case '=':
|
|
237
|
-
return '=';
|
|
238
|
-
case '!=':
|
|
239
|
-
return '!=';
|
|
240
|
-
}
|
|
241
|
-
return undefined;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
private static getNumberRnageOperator(
|
|
245
|
-
tokenType: string
|
|
246
|
-
): NumberRangeOperator | undefined {
|
|
247
|
-
switch (tokenType) {
|
|
248
|
-
case '<=':
|
|
249
|
-
return '<=';
|
|
250
|
-
case '>=':
|
|
251
|
-
return '>=';
|
|
252
|
-
case '<':
|
|
253
|
-
return '<';
|
|
254
|
-
case '>':
|
|
255
|
-
return '>';
|
|
256
|
-
}
|
|
257
|
-
return undefined;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
209
|
private checkNumericExpression(
|
|
261
210
|
tokenType: NumberOperator,
|
|
262
211
|
clauses: NumberClause[]
|
|
@@ -281,7 +230,7 @@ export class NumberParser extends BaseParser {
|
|
|
281
230
|
return false;
|
|
282
231
|
}
|
|
283
232
|
|
|
284
|
-
private checkSimpleNumber(clauses:
|
|
233
|
+
private checkSimpleNumber(clauses: NumberClause[]): boolean {
|
|
285
234
|
if (this.getNext().type === 'word') {
|
|
286
235
|
const numericValue: number = NumberParser.parseNumber(
|
|
287
236
|
this.getAt(this.index).value
|
|
@@ -296,11 +245,13 @@ export class NumberParser extends BaseParser {
|
|
|
296
245
|
return false;
|
|
297
246
|
}
|
|
298
247
|
|
|
299
|
-
private checkNull(clauses:
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
248
|
+
private checkNull(clauses: NumberClause[]): boolean {
|
|
249
|
+
const type = this.getNext().type;
|
|
250
|
+
if (type === 'NULL') {
|
|
251
|
+
clauses.push({operator: 'NULL'});
|
|
252
|
+
return true;
|
|
253
|
+
} else if (type === 'NOTNULL') {
|
|
254
|
+
clauses.push({operator: 'NOTNULL'});
|
|
304
255
|
return true;
|
|
305
256
|
}
|
|
306
257
|
return false;
|
package/src/number_serializer.ts
CHANGED
|
@@ -3,13 +3,12 @@ import {
|
|
|
3
3
|
NumberRange,
|
|
4
4
|
NumberOperator,
|
|
5
5
|
NumberRangeOperator,
|
|
6
|
-
|
|
6
|
+
NumberClause,
|
|
7
7
|
} from './clause_types';
|
|
8
|
-
import {BaseSerializer} from './base_serializer';
|
|
9
8
|
|
|
10
|
-
export class NumberSerializer
|
|
11
|
-
constructor(clauses:
|
|
12
|
-
|
|
9
|
+
export class NumberSerializer {
|
|
10
|
+
constructor(private clauses: NumberClause[]) {
|
|
11
|
+
this.clauses = clauses;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
public serialize(): string {
|
|
@@ -17,15 +16,13 @@ export class NumberSerializer extends BaseSerializer {
|
|
|
17
16
|
return result.trim().replace(/,$/, '');
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
// NumberOperator = '<=' | '>=' | '!=' | '=' | '>' | '<'
|
|
19
|
+
// NumberOperator = '<=' | '>=' | '!=' | '=' | '>' | '<'
|
|
21
20
|
private static numberConditionToString(
|
|
22
21
|
operator: NumberOperator,
|
|
23
|
-
value: number
|
|
22
|
+
value: number
|
|
24
23
|
): string {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
const operatorString = operator === '=' ? '' : operator; // Remove operator for eg "5, 7, 9"
|
|
24
|
+
// Remove operator for eg "5, 7, 9".
|
|
25
|
+
const operatorString = operator === '=' ? '' : operator;
|
|
29
26
|
return operatorString + value;
|
|
30
27
|
}
|
|
31
28
|
|
|
@@ -44,7 +41,7 @@ export class NumberSerializer extends BaseSerializer {
|
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
43
|
|
|
47
|
-
private static isNumberOperator(value: string):
|
|
44
|
+
private static isNumberOperator(value: string): boolean {
|
|
48
45
|
return ['<=', '>=', '!=', '=', '>', '<'].includes(value);
|
|
49
46
|
}
|
|
50
47
|
|
|
@@ -69,16 +66,20 @@ export class NumberSerializer extends BaseSerializer {
|
|
|
69
66
|
);
|
|
70
67
|
}
|
|
71
68
|
|
|
72
|
-
private static clauseToString(clauses:
|
|
69
|
+
private static clauseToString(clauses: NumberClause[]): string {
|
|
73
70
|
let result = '';
|
|
74
71
|
for (const clause of clauses) {
|
|
75
|
-
if ('operator' in clause
|
|
72
|
+
if (!('operator' in clause)) {
|
|
73
|
+
throw new Error('Invalid number clause ' + JSON.stringify(clause));
|
|
74
|
+
}
|
|
75
|
+
if (clause.operator === 'range') {
|
|
76
76
|
result += NumberSerializer.rangeToString(clause);
|
|
77
77
|
result += ', ';
|
|
78
|
-
} else if (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
} else if (clause.operator === 'NULL') {
|
|
79
|
+
result += 'NULL, ';
|
|
80
|
+
} else if (clause.operator === 'NOTNULL') {
|
|
81
|
+
result += '-NULL, ';
|
|
82
|
+
} else if (NumberSerializer.isNumberOperator(clause.operator)) {
|
|
82
83
|
const numberClause: NumberCondition = clause as NumberCondition;
|
|
83
84
|
for (const value of numberClause.values) {
|
|
84
85
|
result += NumberSerializer.numberConditionToString(
|
|
@@ -87,8 +88,6 @@ export class NumberSerializer extends BaseSerializer {
|
|
|
87
88
|
);
|
|
88
89
|
result += ', ';
|
|
89
90
|
}
|
|
90
|
-
} else {
|
|
91
|
-
throw new Error('Invalid number clause ' + JSON.stringify(clause));
|
|
92
91
|
}
|
|
93
92
|
}
|
|
94
93
|
return result;
|