@tellaro/tql 4.0.2 → 5.0.0
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/index.js +72 -64
- package/dist/src/completionProvider.js +60 -65
- package/dist/src/index.d.ts +2 -1
- package/dist/src/ordering.d.ts +32 -0
- package/dist/src/ordering.js +141 -0
- package/dist/src/types.d.ts +22 -2
- package/dist/src/validator.d.ts +14 -12
- package/dist/src/validator.js +127 -107
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,90 +1,98 @@
|
|
|
1
|
-
import { AGGREGATION_FUNCTIONS as t, BOOLEAN_PREDICATE_MUTATORS as o, BOOLEAN_PREDICATE_MUTATOR_SET as i, COLLECTION_OPERATORS as T, COMPARISON_OPERATORS as a, DATE_HISTOGRAM_CALENDAR_INTERVALS as E, DATE_HISTOGRAM_FIXED_UNITS as
|
|
2
|
-
import { TqlParser as f, dateHistogramIntervalProblem as h, formatParseError as x, geoPrecisionProblem as
|
|
3
|
-
import { CASE_SENSITIVE_MEMBERSHIP_OPERATORS as V, CASE_SENSITIVE_OPERATORS as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
1
|
+
import { AGGREGATION_FUNCTIONS as t, BOOLEAN_PREDICATE_MUTATORS as o, BOOLEAN_PREDICATE_MUTATOR_SET as i, COLLECTION_OPERATORS as T, COMPARISON_OPERATORS as a, DATE_HISTOGRAM_CALENDAR_INTERVALS as E, DATE_HISTOGRAM_FIXED_UNITS as O, GEO_GRID_PRECISION as S, GROUP_BY_BUCKET_FUNCTIONS as l, KEYWORDS as R, LOGICAL_OPERATORS as _, MUTATORS as n, NEGATION_SYMBOL_OPERATORS as A, SYMBOL_OPERATORS as s, TYPE_HINTS as g, TqlTokenizer as m, VISUALIZATION_TYPES as I, findPreviousToken as P, findTokenAtPosition as N, findTokenBefore as C, findTokensInRange as c, tokenizeTql as d, tokenizeTqlNoWhitespace as p } from "./src/tokenizer.js";
|
|
2
|
+
import { TqlParser as f, dateHistogramIntervalProblem as h, formatParseError as x, geoPrecisionProblem as M, getTqlErrors as U, isValidTql as u, parseTql as y, rangeBoundariesProblem as D } from "./src/parser.js";
|
|
3
|
+
import { CASE_SENSITIVE_MEMBERSHIP_OPERATORS as V, CASE_SENSITIVE_OPERATORS as q, CASE_SENSITIVE_WHOLE_VALUE_OPERATORS as z, MAX_REGEX_PATTERN_LENGTH as F, TqlValidator as Y, casePreservingForm as B, caseSensitiveSupport as H, formatValidationResult as k, getTqlIssues as v, isValidTqlSyntax as b, validateTql as Q } from "./src/validator.js";
|
|
4
|
+
import { ORDERABLE_FIELD_TYPES as X, ORDERING_OPERATORS as K, checkOrderingComparison as w, isOrderingOperator as Z, literalIsOrderable as j, orderingRefusalMessage as J, orderingVerdict as $ } from "./src/ordering.js";
|
|
5
|
+
import { getCompletionTriggerCharacters as re, getCompletions as te, getWordAtPosition as oe, shouldTriggerCompletion as ie } from "./src/completionProvider.js";
|
|
6
|
+
import { findClosestMatch as ae, fuzzyFilter as Ee, fuzzyMatch as Oe, highlightMatch as Se, levenshteinDistance as le } from "./src/fuzzyMatcher.js";
|
|
7
|
+
import { SchemaCache as _e, createSchemaCache as ne, getCachedField as Ae, getCachedFieldNames as se, getCachedFieldType as ge, getSchemaCache as me } from "./src/schemaCache.js";
|
|
8
|
+
import { ComplexityAnalyzer as Pe, analyzeComplexity as Ne, getComplexityMetrics as Ce, getComplexityWarnings as ce, isHighComplexity as de } from "./src/complexityAnalyzer.js";
|
|
9
|
+
import { SemanticPreview as Le, flattenLogicTree as fe, formatLogicTreeAscii as he, formatLogicTreeNode as xe, generatePreview as Me, getFieldUsage as Ue, getLogicTree as ue, getLogicTreeDepth as ye, getOperatorSummary as De, getUniqueFields as Ge } from "./src/semanticPreview.js";
|
|
10
|
+
import { buildStatsQuery as qe, parseVizHintString as ze } from "./src/builder.js";
|
|
11
|
+
import { QUERY_PLAN_EXPLAIN_KEYS as Ye, QUERY_PLAN_EXPLAIN_VERSION as Be, QUERY_PLAN_RULES as He, summarizeQueryPlan as ke } from "./src/queryPlan.js";
|
|
11
12
|
export {
|
|
12
13
|
t as AGGREGATION_FUNCTIONS,
|
|
13
14
|
o as BOOLEAN_PREDICATE_MUTATORS,
|
|
14
15
|
i as BOOLEAN_PREDICATE_MUTATOR_SET,
|
|
15
16
|
V as CASE_SENSITIVE_MEMBERSHIP_OPERATORS,
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
q as CASE_SENSITIVE_OPERATORS,
|
|
18
|
+
z as CASE_SENSITIVE_WHOLE_VALUE_OPERATORS,
|
|
18
19
|
T as COLLECTION_OPERATORS,
|
|
19
20
|
a as COMPARISON_OPERATORS,
|
|
20
|
-
|
|
21
|
+
Pe as ComplexityAnalyzer,
|
|
21
22
|
E as DATE_HISTOGRAM_CALENDAR_INTERVALS,
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
O as DATE_HISTOGRAM_FIXED_UNITS,
|
|
24
|
+
S as GEO_GRID_PRECISION,
|
|
24
25
|
l as GROUP_BY_BUCKET_FUNCTIONS,
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
R as KEYWORDS,
|
|
27
|
+
_ as LOGICAL_OPERATORS,
|
|
27
28
|
F as MAX_REGEX_PATTERN_LENGTH,
|
|
28
29
|
n as MUTATORS,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
A as NEGATION_SYMBOL_OPERATORS,
|
|
31
|
+
X as ORDERABLE_FIELD_TYPES,
|
|
32
|
+
K as ORDERING_OPERATORS,
|
|
33
|
+
Ye as QUERY_PLAN_EXPLAIN_KEYS,
|
|
34
|
+
Be as QUERY_PLAN_EXPLAIN_VERSION,
|
|
35
|
+
He as QUERY_PLAN_RULES,
|
|
33
36
|
s as SYMBOL_OPERATORS,
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
_e as SchemaCache,
|
|
38
|
+
Le as SemanticPreview,
|
|
36
39
|
g as TYPE_HINTS,
|
|
37
40
|
f as TqlParser,
|
|
38
41
|
m as TqlTokenizer,
|
|
39
42
|
Y as TqlValidator,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
I as VISUALIZATION_TYPES,
|
|
44
|
+
Ne as analyzeComplexity,
|
|
45
|
+
qe as buildStatsQuery,
|
|
43
46
|
B as casePreservingForm,
|
|
44
47
|
H as caseSensitiveSupport,
|
|
45
|
-
|
|
48
|
+
w as checkOrderingComparison,
|
|
49
|
+
ne as createSchemaCache,
|
|
46
50
|
h as dateHistogramIntervalProblem,
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
ae as findClosestMatch,
|
|
52
|
+
P as findPreviousToken,
|
|
49
53
|
N as findTokenAtPosition,
|
|
50
54
|
C as findTokenBefore,
|
|
51
55
|
c as findTokensInRange,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
fe as flattenLogicTree,
|
|
57
|
+
he as formatLogicTreeAscii,
|
|
58
|
+
xe as formatLogicTreeNode,
|
|
55
59
|
x as formatParseError,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
60
|
+
k as formatValidationResult,
|
|
61
|
+
Ee as fuzzyFilter,
|
|
62
|
+
Oe as fuzzyMatch,
|
|
63
|
+
Me as generatePreview,
|
|
64
|
+
M as geoPrecisionProblem,
|
|
65
|
+
Ae as getCachedField,
|
|
66
|
+
se as getCachedFieldNames,
|
|
67
|
+
ge as getCachedFieldType,
|
|
68
|
+
re as getCompletionTriggerCharacters,
|
|
69
|
+
te as getCompletions,
|
|
70
|
+
Ce as getComplexityMetrics,
|
|
71
|
+
ce as getComplexityWarnings,
|
|
72
|
+
Ue as getFieldUsage,
|
|
73
|
+
ue as getLogicTree,
|
|
74
|
+
ye as getLogicTreeDepth,
|
|
75
|
+
De as getOperatorSummary,
|
|
76
|
+
me as getSchemaCache,
|
|
77
|
+
U as getTqlErrors,
|
|
78
|
+
v as getTqlIssues,
|
|
79
|
+
Ge as getUniqueFields,
|
|
80
|
+
oe as getWordAtPosition,
|
|
81
|
+
Se as highlightMatch,
|
|
82
|
+
de as isHighComplexity,
|
|
83
|
+
Z as isOrderingOperator,
|
|
79
84
|
u as isValidTql,
|
|
80
|
-
|
|
81
|
-
|
|
85
|
+
b as isValidTqlSyntax,
|
|
86
|
+
le as levenshteinDistance,
|
|
87
|
+
j as literalIsOrderable,
|
|
88
|
+
J as orderingRefusalMessage,
|
|
89
|
+
$ as orderingVerdict,
|
|
82
90
|
y as parseTql,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
91
|
+
ze as parseVizHintString,
|
|
92
|
+
D as rangeBoundariesProblem,
|
|
93
|
+
ie as shouldTriggerCompletion,
|
|
94
|
+
ke as summarizeQueryPlan,
|
|
95
|
+
d as tokenizeTql,
|
|
96
|
+
p as tokenizeTqlNoWhitespace,
|
|
97
|
+
Q as validateTql
|
|
90
98
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { BOOLEAN_PREDICATE_MUTATORS as E, tokenizeTql as T, COMPARISON_OPERATORS as
|
|
1
|
+
import { BOOLEAN_PREDICATE_MUTATORS as E, tokenizeTql as T, COMPARISON_OPERATORS as $, LOGICAL_OPERATORS as R, GROUP_BY_BUCKET_FUNCTIONS as P, AGGREGATION_FUNCTIONS as D, VISUALIZATION_TYPES as M, TYPE_HINTS as z, MUTATORS as U } from "./tokenizer.js";
|
|
2
2
|
import { fuzzyMatch as v } from "./fuzzyMatcher.js";
|
|
3
3
|
import { getSchemaCache as I } from "./schemaCache.js";
|
|
4
|
-
import { ALL_FIELD_TYPES as
|
|
4
|
+
import { ALL_FIELD_TYPES as c, BETWEEN_FIELD_TYPES as w, ORDERED_FIELD_TYPES as f } from "./validator.js";
|
|
5
5
|
const F = [
|
|
6
6
|
{
|
|
7
7
|
label: "Simple equality",
|
|
@@ -105,24 +105,24 @@ const F = [
|
|
|
105
105
|
description: "Top 10 results by count",
|
|
106
106
|
category: "Stats"
|
|
107
107
|
}
|
|
108
|
-
],
|
|
108
|
+
], q = {
|
|
109
109
|
eq: { detail: "Equals", documentation: "Exact match comparison" },
|
|
110
110
|
ne: { detail: "Not equals", documentation: "Match any value except this one" },
|
|
111
111
|
gt: {
|
|
112
112
|
detail: "Greater than",
|
|
113
|
-
documentation: "Ordered comparison
|
|
113
|
+
documentation: "Ordered comparison, on numeric, date and ip fields only: a keyword or text field is refused (tql#302). With no schema the value must be a number, a date or an ip. An array-valued field matches if ANY element does."
|
|
114
114
|
},
|
|
115
115
|
gte: {
|
|
116
116
|
detail: "Greater than or equal",
|
|
117
|
-
documentation: "Ordered comparison
|
|
117
|
+
documentation: "Ordered comparison, on numeric, date and ip fields only: a keyword or text field is refused (tql#302). With no schema the value must be a number, a date or an ip. An array-valued field matches if ANY element does."
|
|
118
118
|
},
|
|
119
119
|
lt: {
|
|
120
120
|
detail: "Less than",
|
|
121
|
-
documentation: "Ordered comparison
|
|
121
|
+
documentation: "Ordered comparison, on numeric, date and ip fields only: a keyword or text field is refused (tql#302). With no schema the value must be a number, a date or an ip. An array-valued field matches if ANY element does."
|
|
122
122
|
},
|
|
123
123
|
lte: {
|
|
124
124
|
detail: "Less than or equal",
|
|
125
|
-
documentation: "Ordered comparison
|
|
125
|
+
documentation: "Ordered comparison, on numeric, date and ip fields only: a keyword or text field is refused (tql#302). With no schema the value must be a number, a date or an ip. An array-valued field matches if ANY element does."
|
|
126
126
|
},
|
|
127
127
|
contains: { detail: "Contains substring", documentation: "Case-insensitive substring match" },
|
|
128
128
|
not_contains: { detail: "Does not contain", documentation: "Negative substring match" },
|
|
@@ -138,7 +138,7 @@ const F = [
|
|
|
138
138
|
not_matches: { detail: "Not matching pattern", documentation: "Negative pattern match" },
|
|
139
139
|
between: {
|
|
140
140
|
detail: "Between range",
|
|
141
|
-
documentation: "Inclusive range. Usage: field between A AND B, or field between [A, B]. Numeric
|
|
141
|
+
documentation: "Inclusive range. Usage: field between A AND B, or field between [A, B]. Numeric, date and ip fields only: a keyword or text field is refused (tql#302), and with no schema both bounds must be numbers, dates or ips."
|
|
142
142
|
},
|
|
143
143
|
not_between: { detail: "Not between range", documentation: "Exclude values in range" },
|
|
144
144
|
in: { detail: "In list", documentation: 'Usage: field in ["a", "b", "c"]' },
|
|
@@ -257,30 +257,27 @@ const F = [
|
|
|
257
257
|
geo: "object",
|
|
258
258
|
// Array output (returns array of strings)
|
|
259
259
|
split: "keyword"
|
|
260
|
-
},
|
|
260
|
+
}, G = {
|
|
261
261
|
// Equality and membership — every field type, by NAME rather than by a transcribed list.
|
|
262
|
-
eq:
|
|
263
|
-
ne:
|
|
264
|
-
in:
|
|
265
|
-
not_in:
|
|
262
|
+
eq: c,
|
|
263
|
+
ne: c,
|
|
264
|
+
in: c,
|
|
265
|
+
not_in: c,
|
|
266
266
|
// Existence. `is null` is the SAME PREDICATE as `not exists`, so these four lists must be
|
|
267
267
|
// equal. They were not: `nested` and `object` were offered for `exists` and withheld from
|
|
268
268
|
// `is`, so the completion menu published one of two spellings of one operation depending
|
|
269
269
|
// on the field type. Pinned by `tests/collectionAndNullSemantics.spec.ts`.
|
|
270
|
-
exists:
|
|
271
|
-
not_exists:
|
|
272
|
-
is:
|
|
273
|
-
is_not:
|
|
274
|
-
// Ordered comparison — numeric, date and
|
|
275
|
-
// `validator.ts`:
|
|
276
|
-
//
|
|
277
|
-
// field's menu hid an operator every layer of the product supports.
|
|
270
|
+
exists: c,
|
|
271
|
+
not_exists: c,
|
|
272
|
+
is: c,
|
|
273
|
+
is_not: c,
|
|
274
|
+
// Ordered comparison — numeric, date and ip only (tql#302). See ORDERED_FIELD_TYPES in
|
|
275
|
+
// `validator.ts`: every engine refuses them on any other type, so offering one on a
|
|
276
|
+
// keyword field's menu would offer a query that cannot run.
|
|
278
277
|
gt: f,
|
|
279
278
|
gte: f,
|
|
280
279
|
lt: f,
|
|
281
280
|
lte: f,
|
|
282
|
-
// Numeric and date. `keyword` and `text` stay out because Python's `keyword_ops` excludes
|
|
283
|
-
// `between` while including `gte` — see BETWEEN_FIELD_TYPES in `validator.ts`.
|
|
284
281
|
between: w,
|
|
285
282
|
not_between: w,
|
|
286
283
|
// String operators (text/keyword only)
|
|
@@ -312,12 +309,12 @@ const F = [
|
|
|
312
309
|
// filter reads as "no restriction" — so the negated halves were offered on every type
|
|
313
310
|
// while their positive twins were withheld. Permissive by omission is not the same as
|
|
314
311
|
// permissive by decision, and only one of them survives someone reading the table.
|
|
315
|
-
any:
|
|
316
|
-
all:
|
|
317
|
-
none:
|
|
318
|
-
not_any:
|
|
319
|
-
not_all:
|
|
320
|
-
not_none:
|
|
312
|
+
any: c,
|
|
313
|
+
all: c,
|
|
314
|
+
none: c,
|
|
315
|
+
not_any: c,
|
|
316
|
+
not_all: c,
|
|
317
|
+
not_none: c
|
|
321
318
|
};
|
|
322
319
|
class Y {
|
|
323
320
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -354,7 +351,7 @@ function H(e, t, i) {
|
|
|
354
351
|
const n = T(e.substring(0, t)).filter((l) => l.type !== "whitespace");
|
|
355
352
|
if (n.length === 0)
|
|
356
353
|
return { type: "start" };
|
|
357
|
-
const a = n[n.length - 1], s = n.length > 1 ? n[n.length - 2] : null,
|
|
354
|
+
const a = n[n.length - 1], s = n.length > 1 ? n[n.length - 2] : null, u = a.end === t && !e[t - 1]?.match(/\s/), d = u ? a.value : void 0;
|
|
358
355
|
if (a.type === "logicalOp")
|
|
359
356
|
return { type: "start" };
|
|
360
357
|
if (a.type === "paren" && a.value === "(") {
|
|
@@ -362,7 +359,7 @@ function H(e, t, i) {
|
|
|
362
359
|
if (r && r.type === "visualization")
|
|
363
360
|
return { type: "in_viz_params" };
|
|
364
361
|
}
|
|
365
|
-
if (a.type === "comma" || a.type === "field" &&
|
|
362
|
+
if (a.type === "comma" || a.type === "field" && u) {
|
|
366
363
|
const l = n.indexOf(a);
|
|
367
364
|
for (let r = l - 1; r >= 0; r--) {
|
|
368
365
|
if (n[r].type === "paren" && n[r].value === "(") {
|
|
@@ -377,13 +374,13 @@ function H(e, t, i) {
|
|
|
377
374
|
return { type: "after_paren" };
|
|
378
375
|
if (a.type === "arrow")
|
|
379
376
|
return { type: "after_arrow", partialText: d };
|
|
380
|
-
if (s?.type === "doubleColon" &&
|
|
377
|
+
if (s?.type === "doubleColon" && u)
|
|
381
378
|
return { type: "after_double_colon", partialText: d };
|
|
382
379
|
if (a.type === "doubleColon")
|
|
383
380
|
return { type: "after_double_colon" };
|
|
384
|
-
if (a.type === "visualization" &&
|
|
381
|
+
if (a.type === "visualization" && u)
|
|
385
382
|
return { type: "after_arrow", partialText: d };
|
|
386
|
-
if (a.type === "typeHint" &&
|
|
383
|
+
if (a.type === "typeHint" && u)
|
|
387
384
|
return { type: "after_double_colon", partialText: d };
|
|
388
385
|
if (a.type === "keyword" && a.value.toLowerCase() === "stats")
|
|
389
386
|
return { type: "after_stats", partialText: d };
|
|
@@ -397,7 +394,7 @@ function H(e, t, i) {
|
|
|
397
394
|
if (n[r].type === "keyword" && n[r].value.toLowerCase() === "by" || n[r].type === "pipe") break;
|
|
398
395
|
}
|
|
399
396
|
}
|
|
400
|
-
if (a.type === "field" && !
|
|
397
|
+
if (a.type === "field" && !u) {
|
|
401
398
|
const l = n.indexOf(a);
|
|
402
399
|
for (let r = l - 1; r >= 0; r--) {
|
|
403
400
|
if (n[r].type === "keyword" && n[r].value.toLowerCase() === "by") {
|
|
@@ -414,7 +411,7 @@ function H(e, t, i) {
|
|
|
414
411
|
if (a.type === "pipe")
|
|
415
412
|
return { type: "after_pipe", partialText: d };
|
|
416
413
|
if (a.type === "mutator") {
|
|
417
|
-
if (
|
|
414
|
+
if (u)
|
|
418
415
|
return { type: "after_pipe", partialText: d };
|
|
419
416
|
const l = a.value.toLowerCase(), r = g[l];
|
|
420
417
|
return {
|
|
@@ -424,9 +421,9 @@ function H(e, t, i) {
|
|
|
424
421
|
};
|
|
425
422
|
}
|
|
426
423
|
if (a.type === "aggregation")
|
|
427
|
-
return
|
|
424
|
+
return u ? { type: "after_stats", partialText: d } : { type: "after_value" };
|
|
428
425
|
if (a.type === "field") {
|
|
429
|
-
if (
|
|
426
|
+
if (u)
|
|
430
427
|
return s?.type === "pipe" ? { type: "after_pipe", partialText: d } : { type: "start", partialText: d };
|
|
431
428
|
if (s?.type === "pipe")
|
|
432
429
|
return { type: "after_pipe", partialText: a.value };
|
|
@@ -434,7 +431,7 @@ function H(e, t, i) {
|
|
|
434
431
|
return { type: "after_field", fieldName: a.value, fieldType: l };
|
|
435
432
|
}
|
|
436
433
|
if (a.type === "operator") {
|
|
437
|
-
if (
|
|
434
|
+
if (u) {
|
|
438
435
|
if (s?.type === "field") {
|
|
439
436
|
const l = h(s.value, i);
|
|
440
437
|
return { type: "after_field", fieldName: s.value, fieldType: l, partialText: d };
|
|
@@ -447,14 +444,14 @@ function H(e, t, i) {
|
|
|
447
444
|
return { type: "after_operator", operatorName: a.value };
|
|
448
445
|
}
|
|
449
446
|
if (a.type === "string" || a.type === "number" || a.type === "boolean" || a.type === "null")
|
|
450
|
-
return
|
|
447
|
+
return u ? { type: "at_value_end" } : { type: "after_value" };
|
|
451
448
|
if (a.type === "paren" && a.value === ")")
|
|
452
449
|
return { type: "after_value" };
|
|
453
|
-
if (s?.type === "field" &&
|
|
450
|
+
if (s?.type === "field" && u) {
|
|
454
451
|
const l = h(s.value, i);
|
|
455
452
|
return { type: "after_field", fieldName: s.value, fieldType: l, partialText: d };
|
|
456
453
|
}
|
|
457
|
-
if (s?.type === "mutator" &&
|
|
454
|
+
if (s?.type === "mutator" && u) {
|
|
458
455
|
const l = s.value.toLowerCase(), r = g[l];
|
|
459
456
|
return { type: "after_mutator", mutatorName: l, mutatorOutputType: r, partialText: d };
|
|
460
457
|
}
|
|
@@ -477,10 +474,10 @@ function le(e, t = {}) {
|
|
|
477
474
|
a.push(...b(n.partialText, n.mutatorOutputType));
|
|
478
475
|
break;
|
|
479
476
|
case "after_operator":
|
|
480
|
-
a.push(...
|
|
477
|
+
a.push(...K(n.fieldName, t));
|
|
481
478
|
break;
|
|
482
479
|
case "after_value":
|
|
483
|
-
a.push(...
|
|
480
|
+
a.push(...A());
|
|
484
481
|
break;
|
|
485
482
|
case "at_value_end":
|
|
486
483
|
break;
|
|
@@ -540,20 +537,20 @@ function le(e, t = {}) {
|
|
|
540
537
|
a.push(...ae(n.partialText));
|
|
541
538
|
break;
|
|
542
539
|
case "after_stats":
|
|
543
|
-
a.push(...
|
|
540
|
+
a.push(...N(n.partialText));
|
|
544
541
|
break;
|
|
545
542
|
case "after_by":
|
|
546
543
|
a.push(...x(t.fields, n.partialText)), a.push(...J(n.partialText));
|
|
547
544
|
break;
|
|
548
545
|
default:
|
|
549
|
-
a.push(...x(t.fields, n.partialText)), a.push(...b(n.partialText)), a.push(...
|
|
546
|
+
a.push(...x(t.fields, n.partialText)), a.push(...b(n.partialText)), a.push(...A());
|
|
550
547
|
}
|
|
551
|
-
t.includeAggregations && n.type === "start" && a.push(...
|
|
548
|
+
t.includeAggregations && n.type === "start" && a.push(...N(n.partialText));
|
|
552
549
|
let s = a;
|
|
553
|
-
const
|
|
550
|
+
const u = t.fuzzyMatching !== !1, d = t.minFuzzyScore ?? 0;
|
|
554
551
|
if (n.partialText) {
|
|
555
552
|
const l = n.partialText.toLowerCase();
|
|
556
|
-
if (
|
|
553
|
+
if (u) {
|
|
557
554
|
const r = [];
|
|
558
555
|
for (const m of a) {
|
|
559
556
|
const p = v(l, m.label), _ = m.filterText ? v(l, m.filterText) : { matched: !1, score: 0 }, y = p.score >= _.score ? p : _;
|
|
@@ -576,10 +573,10 @@ function x(e, t) {
|
|
|
576
573
|
return j(t);
|
|
577
574
|
const i = [];
|
|
578
575
|
for (const o of e) {
|
|
579
|
-
const n =
|
|
576
|
+
const n = C(o);
|
|
580
577
|
if (i.push(n), o.nested)
|
|
581
578
|
for (const a of o.nested) {
|
|
582
|
-
const s =
|
|
579
|
+
const s = C(a, o.name);
|
|
583
580
|
i.push(s);
|
|
584
581
|
}
|
|
585
582
|
}
|
|
@@ -597,9 +594,6 @@ function j(e) {
|
|
|
597
594
|
{ name: "@timestamp", description: "Event timestamp" },
|
|
598
595
|
{ name: "message", description: "Message content" },
|
|
599
596
|
{ name: "user.name", description: "User name" },
|
|
600
|
-
{ name: "os.family", description: "Operating system family" },
|
|
601
|
-
{ name: "os.type", description: "Operating system type" },
|
|
602
|
-
{ name: "os.version", description: "Operating system version" },
|
|
603
597
|
{ name: "customer", description: "Customer identifier" },
|
|
604
598
|
{ name: "stack", description: "Stack identifier" }
|
|
605
599
|
].filter((i) => !e || i.name.toLowerCase().includes(e.toLowerCase())).map((i) => ({
|
|
@@ -611,7 +605,7 @@ function j(e) {
|
|
|
611
605
|
sortOrder: 10
|
|
612
606
|
}));
|
|
613
607
|
}
|
|
614
|
-
function
|
|
608
|
+
function C(e, t) {
|
|
615
609
|
const i = t ? `${t}.${e.name}` : e.name;
|
|
616
610
|
return {
|
|
617
611
|
label: i,
|
|
@@ -624,12 +618,12 @@ function N(e, t) {
|
|
|
624
618
|
};
|
|
625
619
|
}
|
|
626
620
|
function b(e, t) {
|
|
627
|
-
let i = [
|
|
621
|
+
let i = [...$];
|
|
628
622
|
return t && (i = i.filter((o) => {
|
|
629
|
-
const n =
|
|
623
|
+
const n = G[o];
|
|
630
624
|
return !n || n.includes(t);
|
|
631
625
|
})), e && (i = i.filter((o) => o.toLowerCase().includes(e.toLowerCase()))), i.map((o, n) => {
|
|
632
|
-
const a =
|
|
626
|
+
const a = q[o] || { detail: o, documentation: "" }, s = W(o, t);
|
|
633
627
|
return {
|
|
634
628
|
label: o,
|
|
635
629
|
insertText: s,
|
|
@@ -640,7 +634,7 @@ function b(e, t) {
|
|
|
640
634
|
};
|
|
641
635
|
});
|
|
642
636
|
}
|
|
643
|
-
function
|
|
637
|
+
function W(e, t) {
|
|
644
638
|
const i = [
|
|
645
639
|
"contains",
|
|
646
640
|
"not_contains",
|
|
@@ -683,6 +677,7 @@ function K(e, t) {
|
|
|
683
677
|
return `${e} $1`;
|
|
684
678
|
// Numbers, no quotes
|
|
685
679
|
case "date":
|
|
680
|
+
case "date_nanos":
|
|
686
681
|
return `${e} "$1"`;
|
|
687
682
|
// Dates typically quoted
|
|
688
683
|
case "ip":
|
|
@@ -695,8 +690,8 @@ function K(e, t) {
|
|
|
695
690
|
function O(e) {
|
|
696
691
|
return e === "long" || e === "integer" || e === "double" || e === "float" || e === "short" || e === "byte" || e === "half_float" || e === "scaled_float" || e === "unsigned_long";
|
|
697
692
|
}
|
|
698
|
-
function
|
|
699
|
-
return
|
|
693
|
+
function A() {
|
|
694
|
+
return R.filter((e) => e !== "NOT").map(
|
|
700
695
|
(e, t) => L(e, t)
|
|
701
696
|
);
|
|
702
697
|
}
|
|
@@ -709,7 +704,7 @@ function L(e, t = 0) {
|
|
|
709
704
|
sortOrder: 30 + t
|
|
710
705
|
};
|
|
711
706
|
}
|
|
712
|
-
function
|
|
707
|
+
function K(e, t) {
|
|
713
708
|
const i = [];
|
|
714
709
|
return e && t?.fieldValues?.[e] && t.fieldValues[e].forEach((n, a) => {
|
|
715
710
|
i.push({
|
|
@@ -775,7 +770,7 @@ function X(e) {
|
|
|
775
770
|
}
|
|
776
771
|
);
|
|
777
772
|
}
|
|
778
|
-
function
|
|
773
|
+
function N(e) {
|
|
779
774
|
return D.filter(
|
|
780
775
|
(t) => !e || t.toLowerCase().includes(e.toLowerCase())
|
|
781
776
|
).map((t, i) => ({
|
|
@@ -901,7 +896,7 @@ function se(e, t) {
|
|
|
901
896
|
function de() {
|
|
902
897
|
return [" ", "(", ".", '"', "'", "|", ":", "="];
|
|
903
898
|
}
|
|
904
|
-
function
|
|
899
|
+
function ue(e, t, i) {
|
|
905
900
|
if (!e) return !1;
|
|
906
901
|
if (i === " " || i === "(" || i === "." || i === "|" || i === ":" || i === "=") return !0;
|
|
907
902
|
const o = T(e.substring(0, t)), n = o[o.length - 1];
|
|
@@ -912,5 +907,5 @@ export {
|
|
|
912
907
|
de as getCompletionTriggerCharacters,
|
|
913
908
|
le as getCompletions,
|
|
914
909
|
se as getWordAtPosition,
|
|
915
|
-
|
|
910
|
+
ue as shouldTriggerCompletion
|
|
916
911
|
};
|
package/dist/src/index.d.ts
CHANGED
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @packageDocumentation
|
|
8
8
|
*/
|
|
9
|
-
export type { TqlToken, TqlTokenType, TqlExpression, TqlBinaryExpression, TqlUnaryExpression, TqlComparisonExpression, TqlCollectionExpression, TqlMutatorExpression, TqlAggregationExpression, TqlStatsExpression, TqlGroupByBucket, TqlLatLon, TqlGroupByLevel, TqlGroupByMetadata, TqlRowBucketMeta, TqlStatsRow, TqlGroupExpression, TqlLiteral, TqlFieldReference, TqlComparisonOperator, TqlLogicalOperator, TqlCollectionOperator, TqlMutator, TqlAggregationFunction, TqlTypeHint, TqlVisualizationType, TqlVizParams, TqlVizHint, TqlParseResult, TqlParseError, TqlParseWarning, TqlErrorCode, TqlWarningCode, TqlValidationResult, TqlValidationOptions, TqlFieldType, CaseSensitiveSupport, TqlCompletionItem, TqlCompletionKind, TqlCompletionContext, TqlCompletionOptions, TqlFieldSchema, TqlSnippet, TqlInputProps, TqlInputEmits, TqlInputExpose } from './types';
|
|
9
|
+
export type { TqlToken, TqlTokenType, TqlExpression, TqlBinaryExpression, TqlUnaryExpression, TqlComparisonExpression, TqlCollectionExpression, TqlMutatorExpression, TqlAggregationExpression, TqlStatsExpression, TqlGroupByBucket, TqlLatLon, TqlGroupByLevel, TqlGroupByMetadata, TqlRowBucketMeta, TqlStatsRow, TqlGroupExpression, TqlLiteral, TqlFieldReference, TqlComparisonOperator, TqlLogicalOperator, TqlCollectionOperator, TqlMutator, TqlAggregationFunction, TqlTypeHint, TqlVisualizationType, TqlVizParams, TqlVizHint, TqlParseResult, TqlParseError, TqlOrderingRefusal, TqlParseWarning, TqlErrorCode, TqlWarningCode, TqlValidationResult, TqlValidationOptions, TqlFieldType, CaseSensitiveSupport, TqlCompletionItem, TqlCompletionKind, TqlCompletionContext, TqlCompletionOptions, TqlFieldSchema, TqlSnippet, TqlInputProps, TqlInputEmits, TqlInputExpose } from './types';
|
|
10
10
|
export { TqlTokenizer, tokenizeTql, tokenizeTqlNoWhitespace, findTokenAtPosition, findTokensInRange, findTokenBefore, findPreviousToken, COMPARISON_OPERATORS, SYMBOL_OPERATORS, NEGATION_SYMBOL_OPERATORS, LOGICAL_OPERATORS, COLLECTION_OPERATORS, MUTATORS, BOOLEAN_PREDICATE_MUTATORS, BOOLEAN_PREDICATE_MUTATOR_SET, AGGREGATION_FUNCTIONS, GROUP_BY_BUCKET_FUNCTIONS, DATE_HISTOGRAM_CALENDAR_INTERVALS, DATE_HISTOGRAM_FIXED_UNITS, GEO_GRID_PRECISION, TYPE_HINTS, VISUALIZATION_TYPES, KEYWORDS } from './tokenizer';
|
|
11
11
|
export { TqlParser, parseTql, isValidTql, getTqlErrors, formatParseError, dateHistogramIntervalProblem, geoPrecisionProblem, rangeBoundariesProblem } from './parser';
|
|
12
12
|
export { TqlValidator, validateTql, isValidTqlSyntax, getTqlIssues, formatValidationResult, caseSensitiveSupport, casePreservingForm, CASE_SENSITIVE_OPERATORS, CASE_SENSITIVE_WHOLE_VALUE_OPERATORS, CASE_SENSITIVE_MEMBERSHIP_OPERATORS, MAX_REGEX_PATTERN_LENGTH } from './validator';
|
|
13
|
+
export { ORDERING_OPERATORS, ORDERABLE_FIELD_TYPES, isOrderingOperator, literalIsOrderable, orderingVerdict, orderingRefusalMessage, checkOrderingComparison } from './ordering';
|
|
13
14
|
export { getCompletions, getWordAtPosition, getCompletionTriggerCharacters, shouldTriggerCompletion } from './completionProvider';
|
|
14
15
|
export { fuzzyMatch, levenshteinDistance, findClosestMatch, fuzzyFilter, highlightMatch, type FuzzyMatchResult, type FuzzyMatchOptions } from './fuzzyMatcher';
|
|
15
16
|
export { SchemaCache, getSchemaCache, createSchemaCache, getCachedFieldNames, getCachedFieldType, getCachedField, type CachedSchema } from './schemaCache';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { TqlFieldType, TqlLiteral, TqlOrderingRefusal } from './types';
|
|
2
|
+
/** Every spelling of an ordering comparator the parser produces. */
|
|
3
|
+
export declare const ORDERING_OPERATORS: readonly string[];
|
|
4
|
+
/** The field types an ordering comparator is valid on, in the order the error lists them. */
|
|
5
|
+
export declare const ORDERABLE_FIELD_TYPES: readonly string[];
|
|
6
|
+
/** Type names a refusal reports as themselves; see `orderingVerdict`. */
|
|
7
|
+
export declare const REPORTED_TYPE_NAMES: ReadonlySet<string>;
|
|
8
|
+
export declare function isOrderingOperator(operator: string): boolean;
|
|
9
|
+
export type { TqlOrderingRefusal };
|
|
10
|
+
/** The refusal text. Byte-identical to Python's `TQLOrderingTypeError` and Rust's `OrderingTypeError`. */
|
|
11
|
+
export declare function orderingRefusalMessage(refusal: Omit<TqlOrderingRefusal, "allowedTypes">): string;
|
|
12
|
+
/** Is this literal a number, a date or an ip address? Judged on its text: quoting is not the rule. */
|
|
13
|
+
export declare function literalIsOrderable(literal: TqlLiteral): boolean;
|
|
14
|
+
/** `null` when nothing is known about the field's type; else its type and whether it is orderable. */
|
|
15
|
+
export type TqlFieldTypeVerdict = {
|
|
16
|
+
reported: string;
|
|
17
|
+
orderable: boolean;
|
|
18
|
+
} | null;
|
|
19
|
+
/**
|
|
20
|
+
* The verdict for `field` from a flat schema. A field is orderable when it, or a DIRECT subfield
|
|
21
|
+
* the schema lists (`f.num`), has an orderable type — the engines aim the clause at that subfield.
|
|
22
|
+
*/
|
|
23
|
+
export declare function orderingVerdict(field: string, fieldTypes?: Record<string, TqlFieldType | TqlFieldType[]>): TqlFieldTypeVerdict;
|
|
24
|
+
/** Refuse one ordering comparison with no meaningful order, or return `null`. See the module doc. */
|
|
25
|
+
export declare function checkOrderingComparison(args: {
|
|
26
|
+
field: string;
|
|
27
|
+
operator: string;
|
|
28
|
+
value: TqlLiteral | TqlLiteral[];
|
|
29
|
+
verdict: TqlFieldTypeVerdict;
|
|
30
|
+
typeHint?: string;
|
|
31
|
+
hasFieldMutators: boolean;
|
|
32
|
+
}): TqlOrderingRefusal | null;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
const h = [
|
|
2
|
+
"gt",
|
|
3
|
+
"gte",
|
|
4
|
+
"lt",
|
|
5
|
+
"lte",
|
|
6
|
+
">",
|
|
7
|
+
">=",
|
|
8
|
+
"<",
|
|
9
|
+
"<=",
|
|
10
|
+
"between",
|
|
11
|
+
"not_between",
|
|
12
|
+
"!between"
|
|
13
|
+
], c = [
|
|
14
|
+
"long",
|
|
15
|
+
"integer",
|
|
16
|
+
"short",
|
|
17
|
+
"byte",
|
|
18
|
+
"double",
|
|
19
|
+
"float",
|
|
20
|
+
"half_float",
|
|
21
|
+
"scaled_float",
|
|
22
|
+
"unsigned_long",
|
|
23
|
+
"date",
|
|
24
|
+
"date_nanos",
|
|
25
|
+
"ip"
|
|
26
|
+
], w = /* @__PURE__ */ new Set([
|
|
27
|
+
"keyword",
|
|
28
|
+
"text",
|
|
29
|
+
"long",
|
|
30
|
+
"double",
|
|
31
|
+
"boolean",
|
|
32
|
+
"date",
|
|
33
|
+
"ip",
|
|
34
|
+
"wildcard",
|
|
35
|
+
"object",
|
|
36
|
+
"nested",
|
|
37
|
+
"geo_point",
|
|
38
|
+
"unsigned_long",
|
|
39
|
+
"match_only_text",
|
|
40
|
+
"annotated_text",
|
|
41
|
+
"unknown"
|
|
42
|
+
]), y = /* @__PURE__ */ new Set(["integer", "int", "number", "decimal", "float", "double", "date", "ip"]), _ = /* @__PURE__ */ new Set(["string", "str", "boolean", "bool", "geo", "object"]);
|
|
43
|
+
function E(e) {
|
|
44
|
+
return h.includes(e);
|
|
45
|
+
}
|
|
46
|
+
function $(e) {
|
|
47
|
+
const t = e.operator === "!between" ? "not_between" : e.operator, s = e.literal === void 0 ? `field '${e.field}' of type '${e.fieldType}'` : `field '${e.field}' of unknown type with the literal '${e.literal}'`;
|
|
48
|
+
let r = `Cannot apply ordering operator '${t}' to ${s}. Ordering operators (gt, gte, lt, lte, between) are valid only on numeric, date and ip fields (allowed types: ${c.join(", ")}).`;
|
|
49
|
+
return e.literal !== void 0 && (r += " With no field type known, the literal must be a number, a date or an ip address."), r;
|
|
50
|
+
}
|
|
51
|
+
const O = /^[+-]?[0-9]+(\.[0-9]+)?([eE][+-]?[0-9]+)?$/, f = /^[0-9]{4}-[0-9]{2}-[0-9]{2}([T ][0-9]{2}:[0-9]{2}(:[0-9]{2}([.,][0-9]+)?)?(Z|[+-][0-9]{2}(:?[0-9]{2})?)?)?$/, p = /^([+-][0-9]+[yMwdhHms]|\/[yMwdhHms])*$/, g = /^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])){3}$/, v = /^[0-9A-Fa-f]{1,4}$/;
|
|
52
|
+
function A(e) {
|
|
53
|
+
if (!e.includes(":") || !/^[0-9A-Fa-f:.]+$/.test(e))
|
|
54
|
+
return !1;
|
|
55
|
+
const t = e.split("::");
|
|
56
|
+
if (t.length > 2)
|
|
57
|
+
return !1;
|
|
58
|
+
const s = (n) => n === "" ? [] : n.split(":"), r = s(t[0]), i = t.length === 2 ? s(t[1]) : [];
|
|
59
|
+
if (r === null || i === null)
|
|
60
|
+
return !1;
|
|
61
|
+
const a = [...r, ...i];
|
|
62
|
+
let u = 0;
|
|
63
|
+
for (let n = 0; n < a.length; n++) {
|
|
64
|
+
const l = a[n];
|
|
65
|
+
if (n === a.length - 1 && !e.endsWith("::") && l.includes(".")) {
|
|
66
|
+
if (!g.test(l)) return !1;
|
|
67
|
+
u += 2;
|
|
68
|
+
} else if (v.test(l))
|
|
69
|
+
u += 1;
|
|
70
|
+
else
|
|
71
|
+
return !1;
|
|
72
|
+
}
|
|
73
|
+
return t.length === 2 ? u <= 7 : u === 8;
|
|
74
|
+
}
|
|
75
|
+
function m(e) {
|
|
76
|
+
if (e.startsWith("now"))
|
|
77
|
+
return p.test(e.slice(3));
|
|
78
|
+
const t = e.indexOf("||");
|
|
79
|
+
return t === -1 ? f.test(e) : f.test(e.slice(0, t)) && p.test(e.slice(t + 2));
|
|
80
|
+
}
|
|
81
|
+
function R(e) {
|
|
82
|
+
if (e.valueType === "number") return !0;
|
|
83
|
+
if (e.valueType !== "string" || typeof e.value != "string") return !1;
|
|
84
|
+
const t = e.value;
|
|
85
|
+
return O.test(t) || m(t) || g.test(t) || A(t);
|
|
86
|
+
}
|
|
87
|
+
function T(e) {
|
|
88
|
+
return e.value === null ? "null" : String(e.value);
|
|
89
|
+
}
|
|
90
|
+
function S(e, t) {
|
|
91
|
+
const s = t?.[e];
|
|
92
|
+
if (s === void 0) return null;
|
|
93
|
+
const r = Array.isArray(s) ? s : [s];
|
|
94
|
+
if (r.length === 0) return null;
|
|
95
|
+
let i = r.some((n) => c.includes(n));
|
|
96
|
+
const a = r.every((n) => n === "object" || n === "nested");
|
|
97
|
+
if (!i && !a && t) {
|
|
98
|
+
const n = `${e}.`;
|
|
99
|
+
for (const [l, o] of Object.entries(t)) {
|
|
100
|
+
if (!l.startsWith(n) || l.slice(n.length).includes(".")) continue;
|
|
101
|
+
if ((Array.isArray(o) ? o : [o]).some((b) => c.includes(b))) {
|
|
102
|
+
i = !0;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return { reported: r.map((n) => i || w.has(n) ? n : "unknown").join(" or "), orderable: i };
|
|
108
|
+
}
|
|
109
|
+
function D(e) {
|
|
110
|
+
const { field: t, operator: s, value: r, verdict: i, typeHint: a, hasFieldMutators: u } = e;
|
|
111
|
+
if (!E(s)) return null;
|
|
112
|
+
const n = (o, d) => ({
|
|
113
|
+
field: t,
|
|
114
|
+
fieldType: o,
|
|
115
|
+
operator: s === "!between" ? "not_between" : s,
|
|
116
|
+
...d === void 0 ? {} : { literal: d },
|
|
117
|
+
allowedTypes: [...c]
|
|
118
|
+
});
|
|
119
|
+
if (!u) {
|
|
120
|
+
if (i !== null)
|
|
121
|
+
return i.orderable ? null : n(i.reported);
|
|
122
|
+
const o = (a ?? "").toLowerCase();
|
|
123
|
+
if (y.has(o)) return null;
|
|
124
|
+
if (_.has(o)) return n(o);
|
|
125
|
+
}
|
|
126
|
+
const l = Array.isArray(r) ? r : [r];
|
|
127
|
+
for (const o of l)
|
|
128
|
+
if (o.type === "literal" && !R(o))
|
|
129
|
+
return n("unknown", T(o));
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
export {
|
|
133
|
+
c as ORDERABLE_FIELD_TYPES,
|
|
134
|
+
h as ORDERING_OPERATORS,
|
|
135
|
+
w as REPORTED_TYPE_NAMES,
|
|
136
|
+
D as checkOrderingComparison,
|
|
137
|
+
E as isOrderingOperator,
|
|
138
|
+
R as literalIsOrderable,
|
|
139
|
+
$ as orderingRefusalMessage,
|
|
140
|
+
S as orderingVerdict
|
|
141
|
+
};
|
package/dist/src/types.d.ts
CHANGED
|
@@ -293,6 +293,18 @@ export interface TqlParseError {
|
|
|
293
293
|
severity: "error";
|
|
294
294
|
code: TqlErrorCode;
|
|
295
295
|
suggestion?: string;
|
|
296
|
+
/** Set on `UNORDERABLE_FIELD`: the field, its type, the operator and the allowed types. */
|
|
297
|
+
ordering?: TqlOrderingRefusal;
|
|
298
|
+
}
|
|
299
|
+
/** An ordering comparator refused on a field with no meaningful order (tql#302). */
|
|
300
|
+
export interface TqlOrderingRefusal {
|
|
301
|
+
field: string;
|
|
302
|
+
/** Mapped type, the type hint, or `"unknown"` when the literal was refused. */
|
|
303
|
+
fieldType: string;
|
|
304
|
+
operator: string;
|
|
305
|
+
/** Set when no field type was known and the LITERAL was refused. */
|
|
306
|
+
literal?: string;
|
|
307
|
+
allowedTypes: string[];
|
|
296
308
|
}
|
|
297
309
|
export interface TqlParseWarning {
|
|
298
310
|
message: string;
|
|
@@ -335,7 +347,15 @@ export type TqlErrorCode = "UNEXPECTED_TOKEN" | "UNEXPECTED_END" | "UNBALANCED_P
|
|
|
335
347
|
* malformed `range` boundaries, a duplicate `filters` label. Mirrors
|
|
336
348
|
* `cross_language_tests/fixtures/test_cases/validation/stats_bucket_errors.json`.
|
|
337
349
|
*/
|
|
338
|
-
| "INVALID_STATS_BUCKET"
|
|
350
|
+
| "INVALID_STATS_BUCKET"
|
|
351
|
+
/**
|
|
352
|
+
* An ordering comparator (`gt`/`gte`/`lt`/`lte`, `between`) on a field with no meaningful
|
|
353
|
+
* order (tql#302): a mapped type that is not numeric, date or ip, or — with no type known —
|
|
354
|
+
* a literal that is not a number, a date or an ip address. Both engines refuse the same
|
|
355
|
+
* query with the same message (`TQLOrderingTypeError` / `OrderingTypeError`). The error's
|
|
356
|
+
* `ordering` field carries the details.
|
|
357
|
+
*/
|
|
358
|
+
| "UNORDERABLE_FIELD";
|
|
339
359
|
export type TqlWarningCode = "UNKNOWN_FIELD" | "TYPE_MISMATCH" | "DEPRECATED_OPERATOR" | "REDUNDANT_PARENS"
|
|
340
360
|
/**
|
|
341
361
|
* The query parses, but only ONE of the two engines accepts it.
|
|
@@ -412,7 +432,7 @@ export interface TqlValidationOptions {
|
|
|
412
432
|
* documents the predicate and its two blind spots.
|
|
413
433
|
*/
|
|
414
434
|
export type CaseSensitiveSupport = "supported" | "unsupported" | "unknown";
|
|
415
|
-
export type TqlFieldType = "text" | "keyword" | "long" | "integer" | "short" | "byte" | "double" | "float" | "half_float" | "scaled_float" | "unsigned_long" | "date" | "boolean" | "ip" | "nested" | "object" | "geo_point";
|
|
435
|
+
export type TqlFieldType = "text" | "keyword" | "long" | "integer" | "short" | "byte" | "double" | "float" | "half_float" | "scaled_float" | "unsigned_long" | "date" | "date_nanos" | "boolean" | "ip" | "nested" | "object" | "geo_point";
|
|
416
436
|
export interface TqlCompletionItem {
|
|
417
437
|
label: string;
|
|
418
438
|
insertText: string;
|
package/dist/src/validator.d.ts
CHANGED
|
@@ -29,22 +29,18 @@ export declare const ALL_FIELD_TYPES: TqlFieldType[];
|
|
|
29
29
|
*/
|
|
30
30
|
export declare const NUMERIC_FIELD_TYPES: TqlFieldType[];
|
|
31
31
|
/**
|
|
32
|
-
* The types an ORDERED comparison (`gt`/`gte`/`lt`/`lte`) is defined over
|
|
32
|
+
* The types an ORDERED comparison (`gt`/`gte`/`lt`/`lte`) is defined over: numeric, date and
|
|
33
|
+
* ip — exactly `ORDERABLE_FIELD_TYPES` in `./ordering` (`date_nanos` joined this union in
|
|
34
|
+
* tql#302, so a `date_nanos` field's completion menu offers them).
|
|
33
35
|
*
|
|
34
|
-
*
|
|
35
|
-
* comparison
|
|
36
|
-
*
|
|
37
|
-
* range over an analyzed field compares tokens, not the value the user typed.
|
|
36
|
+
* `keyword` used to be here, because both evaluators fell back to a lexicographic string
|
|
37
|
+
* comparison. That fallback is what made `os.version gte "10"` match Windows 7, and every
|
|
38
|
+
* engine now refuses it (tql#302); `validate()` reports it as `UNORDERABLE_FIELD`.
|
|
38
39
|
*/
|
|
39
40
|
export declare const ORDERED_FIELD_TYPES: TqlFieldType[];
|
|
40
41
|
/**
|
|
41
|
-
* The types `between` / `not_between` are defined over
|
|
42
|
-
*
|
|
43
|
-
* `ORDERED_FIELD_TYPES` minus `keyword`. The four ordered operators and `between` are NOT
|
|
44
|
-
* the same set, and the difference is Python's, not this package's: `keyword_ops` in
|
|
45
|
-
* `_validate_simple_type_compatibility` lists `gt`/`gte`/`lt`/`lte` and excludes `between`.
|
|
46
|
-
* `tests/collectionAndNullSemantics.spec.ts` pins that exclusion against the Python source,
|
|
47
|
-
* so this constant self-retires if Python ever adds it.
|
|
42
|
+
* The types `between` / `not_between` are defined over: the same set as the four ordered
|
|
43
|
+
* operators since tql#302 (they differed only by `keyword`, which neither allows now).
|
|
48
44
|
*/
|
|
49
45
|
export declare const BETWEEN_FIELD_TYPES: TqlFieldType[];
|
|
50
46
|
/**
|
|
@@ -220,6 +216,12 @@ export declare class TqlValidator {
|
|
|
220
216
|
/**
|
|
221
217
|
* Suggest a similar field name using Levenshtein distance
|
|
222
218
|
*/
|
|
219
|
+
/**
|
|
220
|
+
* Report an ordering comparator with no meaningful order as `UNORDERABLE_FIELD`. Returns
|
|
221
|
+
* whether it did. A field with mutators (`f | length gt 5`) is judged by its literal, as the
|
|
222
|
+
* engines judge it.
|
|
223
|
+
*/
|
|
224
|
+
private validateOrdering;
|
|
223
225
|
private suggestField;
|
|
224
226
|
/**
|
|
225
227
|
* Calculate Levenshtein distance between two strings
|
package/dist/src/validator.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { isOrderingOperator as h, checkOrderingComparison as b, orderingVerdict as m, orderingRefusalMessage as v } from "./ordering.js";
|
|
2
|
+
import { parseTql as E } from "./parser.js";
|
|
3
|
+
const _ = 1e3, r = [
|
|
3
4
|
"text",
|
|
4
5
|
"keyword",
|
|
5
6
|
"long",
|
|
@@ -12,12 +13,13 @@ const g = 1e3, r = [
|
|
|
12
13
|
"scaled_float",
|
|
13
14
|
"unsigned_long",
|
|
14
15
|
"date",
|
|
16
|
+
"date_nanos",
|
|
15
17
|
"boolean",
|
|
16
18
|
"ip",
|
|
17
19
|
"nested",
|
|
18
20
|
"object",
|
|
19
21
|
"geo_point"
|
|
20
|
-
],
|
|
22
|
+
], k = [
|
|
21
23
|
"long",
|
|
22
24
|
"integer",
|
|
23
25
|
"short",
|
|
@@ -27,7 +29,7 @@ const g = 1e3, r = [
|
|
|
27
29
|
"half_float",
|
|
28
30
|
"scaled_float",
|
|
29
31
|
"unsigned_long"
|
|
30
|
-
],
|
|
32
|
+
], d = [...k, "date", "date_nanos", "ip"], g = d, T = {
|
|
31
33
|
// Equality (all types) — and now that is what it says.
|
|
32
34
|
//
|
|
33
35
|
// The transcribed twelve-element list this replaces claimed "all types" while omitting
|
|
@@ -39,29 +41,21 @@ const g = 1e3, r = [
|
|
|
39
41
|
"=": r,
|
|
40
42
|
"!=": r,
|
|
41
43
|
eq_ci: ["text", "keyword"],
|
|
42
|
-
// Ordered comparison — numeric, date
|
|
44
|
+
// Ordered comparison — numeric, date and ip (tql#302). These rows no longer produce the
|
|
45
|
+
// soft warning: `validateOrdering` reports every ordering comparator on another type as the
|
|
46
|
+
// `UNORDERABLE_FIELD` ERROR the engines' refusal deserves. They stay here because the
|
|
47
|
+
// completion menu is checked against this table (completionOperatorTableParity.spec.ts).
|
|
43
48
|
//
|
|
44
|
-
//
|
|
45
|
-
// first and falls back to a LEXICOGRAPHIC string comparison when both sides are strings,
|
|
46
|
-
// Python does the same, and Python's own validator lists all four in `keyword_ops`
|
|
47
|
-
// (`_validate_simple_type_compatibility`). Warning here was a false positive against every
|
|
48
|
-
// layer at once — `host.name gte "m"` is a query the editor flagged, the validator
|
|
49
|
-
// accepts, the evaluator answers and the cluster serves.
|
|
50
|
-
//
|
|
51
|
-
// `text` stays out, and that is the same source's judgement rather than an omission:
|
|
52
|
-
// `text_ops` excludes the four, because a range over an ANALYZED field compares tokens
|
|
53
|
-
// rather than the value the user typed. `between` also stays out — see the note on it.
|
|
54
|
-
//
|
|
55
|
-
// Every numeric width is listed via ALL_NUMERIC_FIELD_TYPES so the five narrow ones cannot
|
|
49
|
+
// Every numeric width is listed via NUMERIC_FIELD_TYPES so the five narrow ones cannot
|
|
56
50
|
// fall out again the way they did from `eq`.
|
|
57
|
-
gt:
|
|
58
|
-
gte:
|
|
59
|
-
lt:
|
|
60
|
-
lte:
|
|
61
|
-
">":
|
|
62
|
-
">=":
|
|
63
|
-
"<":
|
|
64
|
-
"<=":
|
|
51
|
+
gt: d,
|
|
52
|
+
gte: d,
|
|
53
|
+
lt: d,
|
|
54
|
+
lte: d,
|
|
55
|
+
">": d,
|
|
56
|
+
">=": d,
|
|
57
|
+
"<": d,
|
|
58
|
+
"<=": d,
|
|
65
59
|
// String operations
|
|
66
60
|
//
|
|
67
61
|
// ## The `_cs` operators list `text`, and that is deliberate — the rule lives in the caller
|
|
@@ -147,19 +141,12 @@ const g = 1e3, r = [
|
|
|
147
141
|
matches: ["text", "keyword"],
|
|
148
142
|
not_matches: ["text", "keyword"],
|
|
149
143
|
"!matches": ["text", "keyword"],
|
|
150
|
-
// Range. Numeric and
|
|
151
|
-
//
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
//
|
|
157
|
-
// `keyword` and `text` stay out, and that is a decision rather than an omission: Python's
|
|
158
|
-
// `keyword_ops` excludes `between` while including `gte`, which is the divergence pinned
|
|
159
|
-
// in `tests/collectionAndNullSemantics.spec.ts`.
|
|
160
|
-
between: u,
|
|
161
|
-
not_between: u,
|
|
162
|
-
"!between": u,
|
|
144
|
+
// Range. Numeric, date and ip, via the named constant — the same set as the four ordered
|
|
145
|
+
// operators since tql#302; on any other type `validateOrdering` reports the engines'
|
|
146
|
+
// refusal as an ERROR, and these rows never warn.
|
|
147
|
+
between: g,
|
|
148
|
+
not_between: g,
|
|
149
|
+
"!between": g,
|
|
163
150
|
// Membership — the same set as `eq`, because `in` IS a disjunction of equalities and both
|
|
164
151
|
// evaluators implement it that way. The transcribed list this replaces omitted the five
|
|
165
152
|
// narrow numeric widths plus `nested`, `object` and `geo_point`.
|
|
@@ -226,11 +213,11 @@ const g = 1e3, r = [
|
|
|
226
213
|
"!any": r,
|
|
227
214
|
"!all": r,
|
|
228
215
|
"!none": r
|
|
229
|
-
},
|
|
216
|
+
}, f = {
|
|
230
217
|
cidr: ["ip"],
|
|
231
218
|
not_cidr: ["ip"],
|
|
232
219
|
"!cidr": ["ip"]
|
|
233
|
-
},
|
|
220
|
+
}, A = [
|
|
234
221
|
"contains_cs",
|
|
235
222
|
"not_contains_cs",
|
|
236
223
|
"!contains_cs",
|
|
@@ -240,25 +227,25 @@ const g = 1e3, r = [
|
|
|
240
227
|
"endswith_cs",
|
|
241
228
|
"not_endswith_cs",
|
|
242
229
|
"!endswith_cs"
|
|
243
|
-
],
|
|
230
|
+
], w = [
|
|
244
231
|
"in_cs",
|
|
245
232
|
"not_in_cs",
|
|
246
233
|
"!in_cs"
|
|
247
|
-
],
|
|
248
|
-
...
|
|
249
|
-
...
|
|
234
|
+
], $ = [
|
|
235
|
+
...A,
|
|
236
|
+
...w
|
|
250
237
|
];
|
|
251
|
-
function
|
|
238
|
+
function u(o, t) {
|
|
252
239
|
const e = t?.[o];
|
|
253
240
|
return e === void 0 ? [] : Array.isArray(e) ? e : [e];
|
|
254
241
|
}
|
|
255
|
-
function
|
|
242
|
+
function R(o, t) {
|
|
256
243
|
if (!t)
|
|
257
244
|
return "unknown";
|
|
258
|
-
const e =
|
|
245
|
+
const e = u(o, t);
|
|
259
246
|
if (e.length === 0)
|
|
260
247
|
return "unknown";
|
|
261
|
-
if (e.includes("keyword") ||
|
|
248
|
+
if (e.includes("keyword") || u(`${o}.keyword`, t).includes("keyword"))
|
|
262
249
|
return "present";
|
|
263
250
|
const i = `${o}.`;
|
|
264
251
|
for (const [n, s] of Object.entries(t))
|
|
@@ -266,18 +253,18 @@ function E(o, t) {
|
|
|
266
253
|
return "present";
|
|
267
254
|
return "absent";
|
|
268
255
|
}
|
|
269
|
-
function
|
|
270
|
-
if (
|
|
256
|
+
function I(o, t, e) {
|
|
257
|
+
if (!$.includes(t))
|
|
271
258
|
return "supported";
|
|
272
|
-
const i =
|
|
259
|
+
const i = R(o, e);
|
|
273
260
|
if (i !== "absent")
|
|
274
261
|
return i === "present" ? "supported" : "unknown";
|
|
275
|
-
if (!
|
|
262
|
+
if (!w.includes(t))
|
|
276
263
|
return "unsupported";
|
|
277
|
-
const n =
|
|
264
|
+
const n = u(o, e);
|
|
278
265
|
return n.length > 0 && n.every((s) => s === "text") ? "unsupported" : "supported";
|
|
279
266
|
}
|
|
280
|
-
const
|
|
267
|
+
const S = {
|
|
281
268
|
eq: ["string", "number", "boolean"],
|
|
282
269
|
ne: ["string", "number", "boolean"],
|
|
283
270
|
"=": ["string", "number", "boolean"],
|
|
@@ -346,7 +333,7 @@ const T = {
|
|
|
346
333
|
"!all": ["string", "number", "boolean"],
|
|
347
334
|
"!none": ["string", "number", "boolean"]
|
|
348
335
|
};
|
|
349
|
-
class
|
|
336
|
+
class O {
|
|
350
337
|
options;
|
|
351
338
|
errors;
|
|
352
339
|
warnings;
|
|
@@ -359,7 +346,7 @@ class A {
|
|
|
359
346
|
validate(t) {
|
|
360
347
|
if (this.errors = [], this.warnings = [], !t)
|
|
361
348
|
return { valid: !0, errors: [], warnings: [] };
|
|
362
|
-
const e =
|
|
349
|
+
const e = E(t);
|
|
363
350
|
return this.errors.push(...e.errors), this.warnings.push(...e.warnings), e.ast && this.validateExpression(e.ast), {
|
|
364
351
|
valid: this.errors.length === 0,
|
|
365
352
|
errors: this.errors,
|
|
@@ -477,7 +464,7 @@ class A {
|
|
|
477
464
|
*/
|
|
478
465
|
validateComparison(t) {
|
|
479
466
|
const e = t.field.type === "field" ? t.field.name : "computed";
|
|
480
|
-
|
|
467
|
+
this.options.availableFields && this.options.strictMode && !this.options.availableFields.includes(e) && t.field.type === "field" && this.addWarning(
|
|
481
468
|
`Unknown field '${e}'`,
|
|
482
469
|
t.field.start,
|
|
483
470
|
t.field.end,
|
|
@@ -485,25 +472,27 @@ class A {
|
|
|
485
472
|
1,
|
|
486
473
|
"UNKNOWN_FIELD",
|
|
487
474
|
`Did you mean: ${this.suggestField(e)}`
|
|
488
|
-
)
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
475
|
+
);
|
|
476
|
+
const i = this.validateOrdering(t);
|
|
477
|
+
if (this.options.fieldTypes && t.field.type === "field") {
|
|
478
|
+
const s = u(e, this.options.fieldTypes), a = s.join(" or ");
|
|
479
|
+
if (s.length > 0) {
|
|
480
|
+
const l = f[t.operator];
|
|
481
|
+
l && !s.some((c) => l.includes(c)) && this.addError(
|
|
482
|
+
`Operator '${t.operator}' requires field type ${l.join(" or ")}, but '${e}' is type '${a}'`,
|
|
494
483
|
t.start,
|
|
495
484
|
t.end,
|
|
496
485
|
1,
|
|
497
486
|
1,
|
|
498
487
|
"TYPE_MISMATCH",
|
|
499
|
-
`Use '${t.operator}' only with ${
|
|
488
|
+
`Use '${t.operator}' only with ${l.join(" or ")} fields`
|
|
500
489
|
);
|
|
501
490
|
}
|
|
502
491
|
}
|
|
503
|
-
let
|
|
504
|
-
if (t.field.type === "field" &&
|
|
505
|
-
|
|
506
|
-
const
|
|
492
|
+
let n = !1;
|
|
493
|
+
if (t.field.type === "field" && I(e, t.operator, this.options.fieldTypes) === "unsupported") {
|
|
494
|
+
n = !0;
|
|
495
|
+
const s = t.operator.replace(/_cs$/, ""), a = this.options.fieldTypes?.[e], l = a === "text" ? `'${e}' is an analyzed text field with no case-preserving subfield in the supplied schema, so the analyzer lowercased every token it indexed and the case '${t.operator}' asks about is not in the index` : `'${e}' is type '${a}' and has no un-analyzed string form, which is what '${t.operator}' matches against`;
|
|
507
496
|
this.addWarning(
|
|
508
497
|
// "The query engine", singular and unqualified, and kept that way deliberately.
|
|
509
498
|
// It was written this way because "both engines" was FALSE in twelve cells —
|
|
@@ -512,34 +501,34 @@ class A {
|
|
|
512
501
|
// user does not choose the engine, the sentence is about what will go wrong
|
|
513
502
|
// rather than about who refuses, and a message that counts engines is a message
|
|
514
503
|
// that goes stale the next time one of them changes.
|
|
515
|
-
`${
|
|
504
|
+
`${l}. The query engine refuses this at execution.`,
|
|
516
505
|
t.start,
|
|
517
506
|
t.end,
|
|
518
507
|
1,
|
|
519
508
|
1,
|
|
520
509
|
"UNANSWERABLE_MAPPING",
|
|
521
|
-
|
|
510
|
+
a === "text" ? `Use the case-insensitive '${s}', or query a keyword subfield (\`${e}.keyword\`) if the index has one this schema does not list.` : `Use the case-insensitive '${s}', or compare '${e}' with an operator suited to '${a}'.`
|
|
522
511
|
);
|
|
523
512
|
}
|
|
524
513
|
if (this.options.fieldTypes && t.field.type === "field") {
|
|
525
|
-
const
|
|
526
|
-
if (
|
|
527
|
-
const
|
|
528
|
-
!i && !
|
|
529
|
-
`Operator '${t.operator}' may not work well with field type '${
|
|
514
|
+
const s = u(e, this.options.fieldTypes), a = s.join(" or ");
|
|
515
|
+
if (s.length > 0) {
|
|
516
|
+
const l = T[t.operator], c = f[t.operator];
|
|
517
|
+
!n && !i && !h(t.operator) && !c && l && !s.some((p) => l.includes(p)) && this.addWarning(
|
|
518
|
+
`Operator '${t.operator}' may not work well with field type '${a}'`,
|
|
530
519
|
t.start,
|
|
531
520
|
t.end,
|
|
532
521
|
1,
|
|
533
522
|
1,
|
|
534
523
|
"TYPE_MISMATCH",
|
|
535
|
-
`Consider using a different operator for ${
|
|
524
|
+
`Consider using a different operator for ${a} fields`
|
|
536
525
|
);
|
|
537
526
|
}
|
|
538
527
|
}
|
|
539
528
|
if (!Array.isArray(t.value) && t.value.type === "literal") {
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
`Operator '${t.operator}' expects ${
|
|
529
|
+
const s = S[t.operator];
|
|
530
|
+
s && !s.includes(t.value.valueType) && this.addWarning(
|
|
531
|
+
`Operator '${t.operator}' expects ${s.join(" or ")} value`,
|
|
543
532
|
t.value.start,
|
|
544
533
|
t.value.end,
|
|
545
534
|
1,
|
|
@@ -548,10 +537,10 @@ class A {
|
|
|
548
537
|
);
|
|
549
538
|
}
|
|
550
539
|
if ((t.operator === "regexp" || t.operator === "regex" || t.operator === "not_regexp" || t.operator === "not_regex" || t.operator === "matches" || t.operator === "not_matches") && !Array.isArray(t.value) && t.value.valueType === "string" && typeof t.value.value == "string") {
|
|
551
|
-
const
|
|
552
|
-
if (
|
|
540
|
+
const s = Array.from(t.value.value).length;
|
|
541
|
+
if (s > _)
|
|
553
542
|
this.addError(
|
|
554
|
-
`Regex pattern is ${
|
|
543
|
+
`Regex pattern is ${s} characters, which exceeds the maximum supported length of ${_}. The query cannot run as written.`,
|
|
555
544
|
t.value.start,
|
|
556
545
|
t.value.end,
|
|
557
546
|
1,
|
|
@@ -578,6 +567,36 @@ class A {
|
|
|
578
567
|
/**
|
|
579
568
|
* Suggest a similar field name using Levenshtein distance
|
|
580
569
|
*/
|
|
570
|
+
/**
|
|
571
|
+
* Report an ordering comparator with no meaningful order as `UNORDERABLE_FIELD`. Returns
|
|
572
|
+
* whether it did. A field with mutators (`f | length gt 5`) is judged by its literal, as the
|
|
573
|
+
* engines judge it.
|
|
574
|
+
*/
|
|
575
|
+
validateOrdering(t) {
|
|
576
|
+
if (!h(t.operator)) return !1;
|
|
577
|
+
let e = t.field, i = !1;
|
|
578
|
+
for (; e.type === "mutator"; )
|
|
579
|
+
i = !0, e = e.field;
|
|
580
|
+
((e.mutators?.length ?? 0) > 0 || (e.mutatorCalls?.length ?? 0) > 0) && (i = !0);
|
|
581
|
+
const n = b({
|
|
582
|
+
field: e.name,
|
|
583
|
+
operator: t.operator,
|
|
584
|
+
value: t.value,
|
|
585
|
+
verdict: m(e.name, this.options.fieldTypes),
|
|
586
|
+
typeHint: e.typeHint,
|
|
587
|
+
hasFieldMutators: i
|
|
588
|
+
});
|
|
589
|
+
return n === null ? !1 : (this.addError(
|
|
590
|
+
v(n),
|
|
591
|
+
t.start,
|
|
592
|
+
t.end,
|
|
593
|
+
1,
|
|
594
|
+
1,
|
|
595
|
+
"UNORDERABLE_FIELD",
|
|
596
|
+
n.literal === void 0 ? `Compare '${n.field}' with eq/ne/in, or order on a numeric, date or ip field (a version has numeric parts such as os.version_build).` : "Use a number, a date or an ip address, or compare with eq/ne/in.",
|
|
597
|
+
n
|
|
598
|
+
), !0);
|
|
599
|
+
}
|
|
581
600
|
suggestField(t) {
|
|
582
601
|
if (!this.options.availableFields || this.options.availableFields.length === 0)
|
|
583
602
|
return "check available fields";
|
|
@@ -606,7 +625,7 @@ class A {
|
|
|
606
625
|
);
|
|
607
626
|
return i[e.length][t.length];
|
|
608
627
|
}
|
|
609
|
-
addError(t, e, i, n, s, a,
|
|
628
|
+
addError(t, e, i, n, s, a, l, c) {
|
|
610
629
|
this.errors.push({
|
|
611
630
|
message: t,
|
|
612
631
|
start: e,
|
|
@@ -615,10 +634,11 @@ class A {
|
|
|
615
634
|
column: s,
|
|
616
635
|
severity: "error",
|
|
617
636
|
code: a,
|
|
618
|
-
suggestion:
|
|
637
|
+
suggestion: l,
|
|
638
|
+
...c ? { ordering: c } : {}
|
|
619
639
|
});
|
|
620
640
|
}
|
|
621
|
-
addWarning(t, e, i, n, s, a,
|
|
641
|
+
addWarning(t, e, i, n, s, a, l) {
|
|
622
642
|
this.warnings.push({
|
|
623
643
|
message: t,
|
|
624
644
|
start: e,
|
|
@@ -627,21 +647,21 @@ class A {
|
|
|
627
647
|
column: s,
|
|
628
648
|
severity: "warning",
|
|
629
649
|
code: a,
|
|
630
|
-
suggestion:
|
|
650
|
+
suggestion: l
|
|
631
651
|
});
|
|
632
652
|
}
|
|
633
653
|
}
|
|
634
|
-
function
|
|
635
|
-
return new
|
|
654
|
+
function y(o, t) {
|
|
655
|
+
return new O(t).validate(o);
|
|
636
656
|
}
|
|
637
|
-
function
|
|
638
|
-
return
|
|
657
|
+
function x(o) {
|
|
658
|
+
return y(o).valid;
|
|
639
659
|
}
|
|
640
|
-
function
|
|
641
|
-
const e =
|
|
660
|
+
function C(o, t) {
|
|
661
|
+
const e = y(o, t);
|
|
642
662
|
return [...e.errors, ...e.warnings];
|
|
643
663
|
}
|
|
644
|
-
function
|
|
664
|
+
function M(o) {
|
|
645
665
|
const t = [];
|
|
646
666
|
o.valid ? t.push("Query is valid") : t.push("Query has errors:");
|
|
647
667
|
for (const e of o.errors)
|
|
@@ -653,18 +673,18 @@ function R(o) {
|
|
|
653
673
|
}
|
|
654
674
|
export {
|
|
655
675
|
r as ALL_FIELD_TYPES,
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
676
|
+
g as BETWEEN_FIELD_TYPES,
|
|
677
|
+
w as CASE_SENSITIVE_MEMBERSHIP_OPERATORS,
|
|
678
|
+
$ as CASE_SENSITIVE_OPERATORS,
|
|
679
|
+
A as CASE_SENSITIVE_WHOLE_VALUE_OPERATORS,
|
|
680
|
+
_ as MAX_REGEX_PATTERN_LENGTH,
|
|
681
|
+
k as NUMERIC_FIELD_TYPES,
|
|
682
|
+
d as ORDERED_FIELD_TYPES,
|
|
683
|
+
O as TqlValidator,
|
|
684
|
+
R as casePreservingForm,
|
|
685
|
+
I as caseSensitiveSupport,
|
|
686
|
+
M as formatValidationResult,
|
|
687
|
+
C as getTqlIssues,
|
|
688
|
+
x as isValidTqlSyntax,
|
|
689
|
+
y as validateTql
|
|
670
690
|
};
|