@malloydata/malloy-filter 0.0.237-dev250222034547 → 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.
@@ -1,7 +1,8 @@
1
1
  import {SpecialToken, Tokenizer, TokenizerParams} from './tokenizer';
2
2
  import {
3
3
  StringClause,
4
- StringOperator,
4
+ StringCondition,
5
+ StringConditionOperator,
5
6
  QuoteType,
6
7
  FilterError,
7
8
  StringParserResponse,
@@ -49,17 +50,13 @@ export class StringParser extends BaseParser {
49
50
  const token = this.getNext();
50
51
  if (token.type === ',') {
51
52
  this.index++;
52
- } else if (token.type === 'NULL') {
53
- clauses.push({operator: '=', values: [null]});
54
- this.index++;
55
- } else if (token.type === 'EMPTY') {
56
- clauses.push({operator: 'EMPTY', values: [null]});
57
- this.index++;
58
- } else if (token.type === 'NOTNULL') {
59
- clauses.push({operator: '!=', values: [null]});
60
- this.index++;
61
- } else if (token.type === 'NOTEMPTY') {
62
- clauses.push({operator: 'NOTEMPTY', values: [null]});
53
+ } else if (
54
+ token.type === 'NULL' ||
55
+ token.type === 'NOTNULL' ||
56
+ token.type === 'EMPTY' ||
57
+ token.type === 'NOTEMPTY'
58
+ ) {
59
+ clauses.push({operator: token.type});
63
60
  this.index++;
64
61
  } else if (this.checkSimpleWord(clauses)) {
65
62
  this.index++;
@@ -72,7 +69,15 @@ export class StringParser extends BaseParser {
72
69
  this.index++;
73
70
  }
74
71
  }
75
- return {clauses: StringParser.groupClauses(clauses), errors};
72
+ const response: StringParserResponse = {
73
+ clauses: StringParser.groupClauses(clauses),
74
+ errors,
75
+ };
76
+ const quotes: QuoteType[] = StringParser.findQuotes(this.inputString);
77
+ if (quotes.length > 0) {
78
+ response.quotes = quotes;
79
+ }
80
+ return response;
76
81
  }
77
82
 
78
83
  private static findQuotes(str: string): QuoteType[] {
@@ -131,11 +136,16 @@ export class StringParser extends BaseParser {
131
136
  let previous: StringClause = clauses[0];
132
137
  const outputs: StringClause[] = [previous];
133
138
  for (let i = 1; i < clauses.length; i++) {
134
- if (previous.operator === clauses[i].operator) {
135
- previous.values.push(...clauses[i].values);
139
+ const current = clauses[i];
140
+ if (
141
+ previous.operator === current.operator &&
142
+ 'values' in previous &&
143
+ 'values' in current
144
+ ) {
145
+ previous.values.push(...current.values);
136
146
  } else {
137
- previous = clauses[i];
138
- outputs.push(previous);
147
+ previous = current;
148
+ outputs.push(current);
139
149
  }
140
150
  }
141
151
  return outputs;
@@ -166,7 +176,7 @@ export class StringParser extends BaseParser {
166
176
  const isUnderscore = StringParser.underscoreRegex.test(word);
167
177
  const isPercentMiddle = StringParser.percentInMiddle(word);
168
178
 
169
- let operator: StringOperator = negatedMatch ? '!=' : '=';
179
+ let operator: StringConditionOperator = negatedMatch ? '!=' : '=';
170
180
  if (isUnderscore || isPercentMiddle || (isPercentBoth && word.length < 3)) {
171
181
  operator = negatedMatch ? '!~' : '~';
172
182
  } else if (isPercentBoth && word.length > 2) {
@@ -189,9 +199,7 @@ export class StringParser extends BaseParser {
189
199
  return false;
190
200
  }
191
201
 
192
- const clause: StringClause = {operator: operator, values: [word]};
193
- //const quotes: QuoteType[] = StringParser.findQuotes(word);
194
- //if (quotes.length > 0) { clause.quotes = quotes; }
202
+ const clause: StringCondition = {operator: operator, values: [word]};
195
203
  clauses.push(clause);
196
204
  return true;
197
205
  }
@@ -1,4 +1,8 @@
1
- import {StringClause, StringOperator} from './clause_types';
1
+ import {
2
+ StringClause,
3
+ StringCondition,
4
+ StringConditionOperator,
5
+ } from './clause_types';
2
6
 
3
7
  export class StringSerializer {
4
8
  constructor(private clauses: StringClause[]) {
@@ -10,9 +14,8 @@ export class StringSerializer {
10
14
  return result.trim().replace(/,$/, '');
11
15
  }
12
16
 
13
- private static isNegated(operator: StringOperator): boolean {
17
+ private static isNegated(operator: StringConditionOperator): boolean {
14
18
  return (
15
- operator === 'NOTEMPTY' ||
16
19
  operator === '!~' ||
17
20
  operator === '!=' ||
18
21
  operator === 'notStarts' ||
@@ -29,22 +32,14 @@ export class StringSerializer {
29
32
  return input.replace(/[_%]/g, match => `\\${match}`);
30
33
  }
31
34
 
32
- // export type StringOperator = 'EMPTY' | 'NOTEMPTY' | 'starts' | 'ends' | 'contains' | 'notStarts' |
33
- // 'notEnds' | 'notContains' | '~' | '=' | '!~' | '!=';
34
- private static StringClauseToString(
35
- operator: StringOperator,
36
- value: string | null
35
+ // export type StringOperator =
36
+ // | 'starts' | 'ends' | 'contains' | 'notStarts' | 'notEnds' | 'notContains'
37
+ // | '~' | '=' | '!~' | '!=';
38
+ private static StringConditionWordToString(
39
+ operator: StringConditionOperator,
40
+ value: string
37
41
  ): string {
38
- if (operator === 'EMPTY') {
39
- return 'EMPTY';
40
- } else if (operator === 'NOTEMPTY') {
41
- return '-EMPTY';
42
- }
43
-
44
42
  const negated: boolean = StringSerializer.isNegated(operator);
45
- if (value === null) {
46
- return negated ? '-NULL' : 'NULL';
47
- }
48
43
  if (value === 'NULL' || value === '-NULL') {
49
44
  return (negated ? '-' : '') + '\\' + value;
50
45
  }
@@ -67,18 +62,50 @@ export class StringSerializer {
67
62
  return (negated ? '-' : '') + value;
68
63
  }
69
64
 
65
+ private static StringClauseToString(
66
+ operator:
67
+ | StringConditionOperator
68
+ | 'EMPTY'
69
+ | 'NOTEMPTY'
70
+ | 'NULL'
71
+ | 'NOTNULL',
72
+ clause: StringClause
73
+ ): string {
74
+ if (operator === 'EMPTY') {
75
+ return 'EMPTY';
76
+ } else if (operator === 'NOTEMPTY') {
77
+ return '-EMPTY';
78
+ } else if (operator === 'NULL') {
79
+ return 'NULL';
80
+ } else if (operator === 'NOTNULL') {
81
+ return '-NULL';
82
+ }
83
+ if (!('values' in clause) || clause.values.length === 0) {
84
+ return '';
85
+ }
86
+ let result = '';
87
+ const condition: StringCondition = clause;
88
+ for (const value of condition.values) {
89
+ const word = StringSerializer.StringConditionWordToString(
90
+ condition.operator,
91
+ value
92
+ );
93
+ if (word) {
94
+ result += word + ', ';
95
+ }
96
+ }
97
+ return result;
98
+ }
99
+
70
100
  private static clauseToString(clauses: StringClause[]): string {
71
101
  let result = '';
72
- for (const genericClause of clauses) {
73
- const clause: StringClause = genericClause as StringClause;
74
- for (const value of clause.values) {
75
- const word = StringSerializer.StringClauseToString(
76
- clause.operator,
77
- value
78
- );
79
- if (word) {
80
- result += word + ', ';
81
- }
102
+ for (const clause of clauses) {
103
+ const words = StringSerializer.StringClauseToString(
104
+ clause.operator,
105
+ clause
106
+ );
107
+ if (words) {
108
+ result += words + ', ';
82
109
  }
83
110
  }
84
111
  return result;