@tellaro/tql 2.0.0 → 3.0.1
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 +70 -65
- package/dist/src/index.d.ts +2 -2
- package/dist/src/types.d.ts +53 -7
- package/dist/src/validator.d.ts +135 -1
- package/dist/src/validator.js +192 -113
- package/dist/tql.css +1 -1
- package/dist/vue/TqlAutocomplete.vue.d.ts +24 -1
- package/dist/vue/TqlChart.vue.d.ts +19 -1
- package/dist/vue/TqlChart.vue.js +1 -1
- package/dist/vue/TqlInput.vue.d.ts +92 -1
- package/dist/vue/TqlInput.vue.js +1 -1
- package/dist/vue/TqlInput.vue2.js +11 -4
- package/dist/vue/components/TqlPreview.vue.d.ts +89 -2
- package/dist/vue/components/TqlPreview.vue.js +4 -4
- package/dist/vue/index.d.ts +1 -1
- package/dist/vue/useTqlInput.d.ts +38 -29
- package/package.json +3 -5
package/dist/index.js
CHANGED
|
@@ -1,73 +1,78 @@
|
|
|
1
|
-
import { AGGREGATION_FUNCTIONS as r, BOOLEAN_PREDICATE_MUTATORS as i, BOOLEAN_PREDICATE_MUTATOR_SET as o, COLLECTION_OPERATORS as T, COMPARISON_OPERATORS as a, KEYWORDS as
|
|
2
|
-
import { TqlParser as
|
|
3
|
-
import { MAX_REGEX_PATTERN_LENGTH as
|
|
4
|
-
import { getCompletionTriggerCharacters as
|
|
5
|
-
import { findClosestMatch as
|
|
6
|
-
import { SchemaCache as
|
|
7
|
-
import { ComplexityAnalyzer as
|
|
8
|
-
import { SemanticPreview as
|
|
9
|
-
import { buildStatsQuery as
|
|
1
|
+
import { AGGREGATION_FUNCTIONS as r, BOOLEAN_PREDICATE_MUTATORS as i, BOOLEAN_PREDICATE_MUTATOR_SET as o, COLLECTION_OPERATORS as T, COMPARISON_OPERATORS as a, KEYWORDS as E, LOGICAL_OPERATORS as l, MUTATORS as S, NEGATION_SYMBOL_OPERATORS as O, SYMBOL_OPERATORS as n, TYPE_HINTS as s, TqlTokenizer as g, VISUALIZATION_TYPES as A, findPreviousToken as m, findTokenAtPosition as R, findTokenBefore as c, findTokensInRange as C, tokenizeTql as _, tokenizeTqlNoWhitespace as p } from "./src/tokenizer.js";
|
|
2
|
+
import { TqlParser as d, formatParseError as f, getTqlErrors as h, isValidTql as I, parseTql as N } from "./src/parser.js";
|
|
3
|
+
import { CASE_SENSITIVE_MEMBERSHIP_OPERATORS as x, CASE_SENSITIVE_OPERATORS as y, CASE_SENSITIVE_WHOLE_VALUE_OPERATORS as M, MAX_REGEX_PATTERN_LENGTH as q, TqlValidator as u, casePreservingForm as z, caseSensitiveSupport as V, formatValidationResult as F, getTqlIssues as U, isValidTqlSyntax as k, validateTql as v } from "./src/validator.js";
|
|
4
|
+
import { getCompletionTriggerCharacters as B, getCompletions as H, getWordAtPosition as D, shouldTriggerCompletion as W } from "./src/completionProvider.js";
|
|
5
|
+
import { findClosestMatch as w, fuzzyFilter as X, fuzzyMatch as b, highlightMatch as K, levenshteinDistance as Q } from "./src/fuzzyMatcher.js";
|
|
6
|
+
import { SchemaCache as j, createSchemaCache as J, getCachedField as $, getCachedFieldNames as ee, getCachedFieldType as te, getSchemaCache as re } from "./src/schemaCache.js";
|
|
7
|
+
import { ComplexityAnalyzer as oe, analyzeComplexity as Te, getComplexityMetrics as ae, getComplexityWarnings as Ee, isHighComplexity as le } from "./src/complexityAnalyzer.js";
|
|
8
|
+
import { SemanticPreview as Oe, flattenLogicTree as ne, formatLogicTreeAscii as se, formatLogicTreeNode as ge, generatePreview as Ae, getFieldUsage as me, getLogicTree as Re, getLogicTreeDepth as ce, getOperatorSummary as Ce, getUniqueFields as _e } from "./src/semanticPreview.js";
|
|
9
|
+
import { buildStatsQuery as Pe, parseVizHintString as de } from "./src/builder.js";
|
|
10
10
|
export {
|
|
11
11
|
r as AGGREGATION_FUNCTIONS,
|
|
12
12
|
i as BOOLEAN_PREDICATE_MUTATORS,
|
|
13
13
|
o as BOOLEAN_PREDICATE_MUTATOR_SET,
|
|
14
|
+
x as CASE_SENSITIVE_MEMBERSHIP_OPERATORS,
|
|
15
|
+
y as CASE_SENSITIVE_OPERATORS,
|
|
16
|
+
M as CASE_SENSITIVE_WHOLE_VALUE_OPERATORS,
|
|
14
17
|
T as COLLECTION_OPERATORS,
|
|
15
18
|
a as COMPARISON_OPERATORS,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
19
|
+
oe as ComplexityAnalyzer,
|
|
20
|
+
E as KEYWORDS,
|
|
21
|
+
l as LOGICAL_OPERATORS,
|
|
22
|
+
q as MAX_REGEX_PATTERN_LENGTH,
|
|
23
|
+
S as MUTATORS,
|
|
24
|
+
O as NEGATION_SYMBOL_OPERATORS,
|
|
25
|
+
n as SYMBOL_OPERATORS,
|
|
26
|
+
j as SchemaCache,
|
|
27
|
+
Oe as SemanticPreview,
|
|
28
|
+
s as TYPE_HINTS,
|
|
29
|
+
d as TqlParser,
|
|
30
|
+
g as TqlTokenizer,
|
|
31
|
+
u as TqlValidator,
|
|
32
|
+
A as VISUALIZATION_TYPES,
|
|
33
|
+
Te as analyzeComplexity,
|
|
34
|
+
Pe as buildStatsQuery,
|
|
35
|
+
z as casePreservingForm,
|
|
36
|
+
V as caseSensitiveSupport,
|
|
37
|
+
J as createSchemaCache,
|
|
38
|
+
w as findClosestMatch,
|
|
39
|
+
m as findPreviousToken,
|
|
40
|
+
R as findTokenAtPosition,
|
|
41
|
+
c as findTokenBefore,
|
|
37
42
|
C as findTokensInRange,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
43
|
+
ne as flattenLogicTree,
|
|
44
|
+
se as formatLogicTreeAscii,
|
|
45
|
+
ge as formatLogicTreeNode,
|
|
46
|
+
f as formatParseError,
|
|
47
|
+
F as formatValidationResult,
|
|
48
|
+
X as fuzzyFilter,
|
|
49
|
+
b as fuzzyMatch,
|
|
50
|
+
Ae as generatePreview,
|
|
51
|
+
$ as getCachedField,
|
|
52
|
+
ee as getCachedFieldNames,
|
|
53
|
+
te as getCachedFieldType,
|
|
54
|
+
B as getCompletionTriggerCharacters,
|
|
55
|
+
H as getCompletions,
|
|
56
|
+
ae as getComplexityMetrics,
|
|
57
|
+
Ee as getComplexityWarnings,
|
|
58
|
+
me as getFieldUsage,
|
|
59
|
+
Re as getLogicTree,
|
|
60
|
+
ce as getLogicTreeDepth,
|
|
61
|
+
Ce as getOperatorSummary,
|
|
62
|
+
re as getSchemaCache,
|
|
63
|
+
h as getTqlErrors,
|
|
64
|
+
U as getTqlIssues,
|
|
65
|
+
_e as getUniqueFields,
|
|
66
|
+
D as getWordAtPosition,
|
|
67
|
+
K as highlightMatch,
|
|
68
|
+
le as isHighComplexity,
|
|
69
|
+
I as isValidTql,
|
|
70
|
+
k as isValidTqlSyntax,
|
|
71
|
+
Q as levenshteinDistance,
|
|
72
|
+
N as parseTql,
|
|
73
|
+
de as parseVizHintString,
|
|
74
|
+
W as shouldTriggerCompletion,
|
|
75
|
+
_ as tokenizeTql,
|
|
76
|
+
p as tokenizeTqlNoWhitespace,
|
|
77
|
+
v as validateTql
|
|
73
78
|
};
|
package/dist/src/index.d.ts
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @packageDocumentation
|
|
8
8
|
*/
|
|
9
|
-
export type { TqlToken, TqlTokenType, TqlExpression, TqlBinaryExpression, TqlUnaryExpression, TqlComparisonExpression, TqlCollectionExpression, TqlMutatorExpression, TqlAggregationExpression, TqlStatsExpression, TqlGroupExpression, TqlLiteral, TqlFieldReference, TqlComparisonOperator, TqlLogicalOperator, TqlCollectionOperator, TqlMutator, TqlAggregationFunction, TqlTypeHint, TqlVisualizationType, TqlVizParams, TqlVizHint, TqlParseResult, TqlParseError, TqlParseWarning, TqlErrorCode, TqlWarningCode, TqlValidationResult, TqlValidationOptions, TqlFieldType, TqlCompletionItem, TqlCompletionKind, TqlCompletionContext, TqlCompletionOptions, TqlFieldSchema, TqlSnippet, TqlInputProps, TqlInputEmits, TqlInputExpose } from './types';
|
|
9
|
+
export type { TqlToken, TqlTokenType, TqlExpression, TqlBinaryExpression, TqlUnaryExpression, TqlComparisonExpression, TqlCollectionExpression, TqlMutatorExpression, TqlAggregationExpression, TqlStatsExpression, 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';
|
|
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, TYPE_HINTS, VISUALIZATION_TYPES, KEYWORDS } from './tokenizer';
|
|
11
11
|
export { TqlParser, parseTql, isValidTql, getTqlErrors, formatParseError } from './parser';
|
|
12
|
-
export { TqlValidator, validateTql, isValidTqlSyntax, getTqlIssues, formatValidationResult, MAX_REGEX_PATTERN_LENGTH } from './validator';
|
|
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
13
|
export { getCompletions, getWordAtPosition, getCompletionTriggerCharacters, shouldTriggerCompletion } from './completionProvider';
|
|
14
14
|
export { fuzzyMatch, levenshteinDistance, findClosestMatch, fuzzyFilter, highlightMatch, type FuzzyMatchResult, type FuzzyMatchOptions } from './fuzzyMatcher';
|
|
15
15
|
export { SchemaCache, getSchemaCache, createSchemaCache, getCachedFieldNames, getCachedFieldType, getCachedField, type CachedSchema } from './schemaCache';
|
package/dist/src/types.d.ts
CHANGED
|
@@ -236,7 +236,39 @@ export type TqlWarningCode = "UNKNOWN_FIELD" | "TYPE_MISMATCH" | "DEPRECATED_OPE
|
|
|
236
236
|
* refuse the query, because silently accepting it is the worse half of the same failure:
|
|
237
237
|
* the user finds out at execution instead of at the keystroke.
|
|
238
238
|
*/
|
|
239
|
-
| "ENGINE_DIVERGENCE"
|
|
239
|
+
| "ENGINE_DIVERGENCE"
|
|
240
|
+
/**
|
|
241
|
+
* The query parses, but the field cannot answer the operator and the query engine refuses
|
|
242
|
+
* it at execution.
|
|
243
|
+
*
|
|
244
|
+
* Raised for the `_cs` (case-sensitive) operators, under TWO rules rather than one --
|
|
245
|
+
* they do not share a predicate, and describing only the first is how this docstring was
|
|
246
|
+
* wrong on 90 of its own 98 firing cells before review:
|
|
247
|
+
*
|
|
248
|
+
* * the WHOLE-VALUE six (`contains_cs`, `startswith_cs`, `endswith_cs` + negations)
|
|
249
|
+
* whenever the field has no case-preserving form at all. That includes analyzed `text`
|
|
250
|
+
* with no `keyword` subfield AND every non-string type -- a `long`, `ip`, `date`,
|
|
251
|
+
* `boolean`, `geo_point`, `nested` or `object` field has no un-analyzed STRING form,
|
|
252
|
+
* and a substring match against one is not imprecise, it is unanswerable.
|
|
253
|
+
* * the MEMBERSHIP two (`in_cs`, `not_in_cs`) only when the base field is analyzed
|
|
254
|
+
* `text`. Case-sensitivity is vacuous for a number or an instant, and the query engine
|
|
255
|
+
* answers `in_cs` on those perfectly well.
|
|
256
|
+
*
|
|
257
|
+
* See `caseSensitiveSupport` in `src/validator.ts` for the predicate and for what the
|
|
258
|
+
* schema has to carry for this to fire at all.
|
|
259
|
+
*
|
|
260
|
+
* A WARNING and never an error, deliberately. The verdict is only as good as the schema
|
|
261
|
+
* the host supplied: a converter that flattens field names but drops multifields makes a
|
|
262
|
+
* perfectly translatable query look unanswerable, and a red squiggle over a query the
|
|
263
|
+
* cluster serves is the worse failure.
|
|
264
|
+
*
|
|
265
|
+
* Distinct from `TYPE_MISMATCH` because the objection is to the MAPPING, not the type --
|
|
266
|
+
* `text` is an accepted type for every `_cs` operator. The two can coincide on a
|
|
267
|
+
* non-string field, where the type is also wrong; the validator suppresses the softer
|
|
268
|
+
* `TYPE_MISMATCH` there rather than reporting both, so a consumer filtering by code sees
|
|
269
|
+
* one diagnostic per clause and the more accurate one.
|
|
270
|
+
*/
|
|
271
|
+
| "UNANSWERABLE_MAPPING";
|
|
240
272
|
export interface TqlValidationResult {
|
|
241
273
|
valid: boolean;
|
|
242
274
|
errors: TqlParseError[];
|
|
@@ -250,6 +282,16 @@ export interface TqlValidationOptions {
|
|
|
250
282
|
allowMutators?: boolean;
|
|
251
283
|
maxDepth?: number;
|
|
252
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* Whether a field can answer a case-SENSITIVE (`_cs`) operator, as far as a supplied schema shows.
|
|
287
|
+
*
|
|
288
|
+
* Three-valued because the engines' rule keys on the index MAPPING while this package is
|
|
289
|
+
* handed a flat name→type map: `"unknown"` is a real and common answer, distinct from
|
|
290
|
+
* `"supported"`, and conflating the two is what let the editor green-light a query the
|
|
291
|
+
* engines refuse (tql#206). Produced by `caseSensitiveSupport` in `src/validator.ts`, which
|
|
292
|
+
* documents the predicate and its two blind spots.
|
|
293
|
+
*/
|
|
294
|
+
export type CaseSensitiveSupport = "supported" | "unsupported" | "unknown";
|
|
253
295
|
export type TqlFieldType = "text" | "keyword" | "long" | "integer" | "short" | "byte" | "double" | "float" | "half_float" | "scaled_float" | "unsigned_long" | "date" | "boolean" | "ip" | "nested" | "object" | "geo_point";
|
|
254
296
|
export interface TqlCompletionItem {
|
|
255
297
|
label: string;
|
|
@@ -346,6 +388,10 @@ export interface TqlInputEmits {
|
|
|
346
388
|
* Reactive reference type for Vue computed properties.
|
|
347
389
|
* This is a simplified type that matches Vue's ComputedRef interface
|
|
348
390
|
* without requiring Vue as a direct dependency.
|
|
391
|
+
*
|
|
392
|
+
* @deprecated No longer used by `TqlInputExpose`: Vue unwraps refs on a
|
|
393
|
+
* component's exposed instance, so a template ref never saw a `.value` here.
|
|
394
|
+
* Kept exported so existing imports keep compiling.
|
|
349
395
|
*/
|
|
350
396
|
export interface ReactiveRef<T> {
|
|
351
397
|
readonly value: T;
|
|
@@ -359,12 +405,12 @@ export interface TqlInputExpose {
|
|
|
359
405
|
getTokenAtPosition(pos: number): TqlToken | null;
|
|
360
406
|
getCursorPosition(): number;
|
|
361
407
|
setCursorPosition(pos: number): void;
|
|
362
|
-
/** Whether the current query is valid (no syntax errors).
|
|
363
|
-
isValid:
|
|
364
|
-
/** Whether the current query has validation errors.
|
|
365
|
-
hasErrors:
|
|
366
|
-
/** Array of current validation errors.
|
|
367
|
-
errors:
|
|
408
|
+
/** Whether the current query is valid (no syntax errors). */
|
|
409
|
+
readonly isValid: boolean;
|
|
410
|
+
/** Whether the current query has validation errors. */
|
|
411
|
+
readonly hasErrors: boolean;
|
|
412
|
+
/** Array of current validation errors. */
|
|
413
|
+
readonly errors: TqlParseError[];
|
|
368
414
|
}
|
|
369
415
|
export type ComplexityScore = "low" | "medium" | "high";
|
|
370
416
|
export interface ComplexityWarning {
|
package/dist/src/validator.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TqlFieldType, TqlParseError, TqlParseWarning, TqlValidationOptions, TqlValidationResult } from './types';
|
|
1
|
+
import { CaseSensitiveSupport, TqlComparisonOperator, TqlFieldType, TqlParseError, TqlParseWarning, TqlValidationOptions, TqlValidationResult } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* Maximum regex pattern length TQL will compile, in characters (code points).
|
|
4
4
|
*
|
|
@@ -47,6 +47,140 @@ export declare const ORDERED_FIELD_TYPES: TqlFieldType[];
|
|
|
47
47
|
* so this constant self-retires if Python ever adds it.
|
|
48
48
|
*/
|
|
49
49
|
export declare const BETWEEN_FIELD_TYPES: TqlFieldType[];
|
|
50
|
+
/**
|
|
51
|
+
* The case-SENSITIVE WHOLE-VALUE operators: every spelling the `TqlComparisonOperator` type
|
|
52
|
+
* admits.
|
|
53
|
+
*
|
|
54
|
+
* TWELVE spellings across both families, EIGHT operators. The engines' constants — same two
|
|
55
|
+
* names, in `tql/src/opensearch/field_mappings.rs` and
|
|
56
|
+
* `src/tql/opensearch_components/field_mapping.py` — carry eight, because the engines only
|
|
57
|
+
* ever see `not_contains_cs`.
|
|
58
|
+
*
|
|
59
|
+
* The four `!` members are unreachable from `validate()`: `normalizeOperator` in
|
|
60
|
+
* `src/parser.ts` maps every `!x` through `NEGATION_SYMBOL_OPERATORS` before an AST exists,
|
|
61
|
+
* and `TqlValidator` takes a query string and nothing else. They are kept because this array
|
|
62
|
+
* is exported public API and a host may match raw user-typed text against it — pinned by "the
|
|
63
|
+
* `!` spellings reach the validator normalised", which also goes red if normalisation is ever
|
|
64
|
+
* removed and the `!` forms become live.
|
|
65
|
+
*
|
|
66
|
+
* `tests/caseSensitiveOperatorMapping.spec.ts` reads both engine constants and asserts these
|
|
67
|
+
* arrays cover exactly them, family by family, once the `!` forms are normalised — so the two
|
|
68
|
+
* cannot drift in either direction, and neither can the SPLIT between the families, which is
|
|
69
|
+
* the part that actually changes the predicate.
|
|
70
|
+
*/
|
|
71
|
+
export declare const CASE_SENSITIVE_WHOLE_VALUE_OPERATORS: TqlComparisonOperator[];
|
|
72
|
+
/**
|
|
73
|
+
* The case-SENSITIVE MEMBERSHIP operators, kept separate for the reason the engines keep them
|
|
74
|
+
* separate: their refusal predicate is NARROWER.
|
|
75
|
+
*
|
|
76
|
+
* `in_cs` is a keyword operator (an exact-match `terms` query), so it routes through a
|
|
77
|
+
* different branch of `get_field_for_operator` (Python) / `get_query_field` (Rust), and that branch refuses
|
|
78
|
+
* only when the base field is analyzed `text`. The whole-value six refuse whenever there is
|
|
79
|
+
* no un-analyzed form at all. Folding the two lists into one is what made
|
|
80
|
+
* `caseSensitiveSupport` wrong for six operators in this PR's first round.
|
|
81
|
+
*/
|
|
82
|
+
export declare const CASE_SENSITIVE_MEMBERSHIP_OPERATORS: TqlComparisonOperator[];
|
|
83
|
+
/** Every spelling of every case-SENSITIVE operator — the union of the two families above. */
|
|
84
|
+
export declare const CASE_SENSITIVE_OPERATORS: TqlComparisonOperator[];
|
|
85
|
+
/**
|
|
86
|
+
* Whether a field offers a CASE-PRESERVING form, as far as the supplied schema shows.
|
|
87
|
+
*
|
|
88
|
+
* This is the field half of the engines' rule, on its own because the two `_cs` operator
|
|
89
|
+
* families consume it differently (see `caseSensitiveSupport`, which is the function you
|
|
90
|
+
* probably want).
|
|
91
|
+
*
|
|
92
|
+
* * `"present"` — the field itself is `keyword`, or it has a `keyword` subfield. One whole
|
|
93
|
+
* value, one indexed term, case intact.
|
|
94
|
+
* * `"absent"` — no such form. That covers analyzed `text` with no `keyword` sibling AND
|
|
95
|
+
* every non-string type: a `long`, `ip`, `date` or `boolean` field has no un-analyzed
|
|
96
|
+
* STRING form either. Whether that matters depends on the operator, which is why this
|
|
97
|
+
* function does not decide it.
|
|
98
|
+
* * `"unknown"` — no `fieldTypes` was supplied, or this field is not in it.
|
|
99
|
+
*
|
|
100
|
+
* Mirrors `FieldMappings::unanalyzed_form` (Rust) and `FieldMapping.unanalyzed_field`
|
|
101
|
+
* (Python) as closely as a flat name→type map allows. Two documented divergences, both of
|
|
102
|
+
* which fail quiet — see `caseSensitiveSupport`.
|
|
103
|
+
*
|
|
104
|
+
* ## The sibling test is on TYPE, not on the name `.keyword`
|
|
105
|
+
*
|
|
106
|
+
* Both engines scan a field's declared subfields for one whose TYPE is `keyword` (Rust:
|
|
107
|
+
* `subfield_of(field, |t| *t == FieldType::Keyword)`; Python: `keyword_field`, set for any
|
|
108
|
+
* subfield with `"type": "keyword"`). A multifield named `.raw` or `.kw` answers exactly as
|
|
109
|
+
* well as one named `.keyword`, and hard-coding the name would report `"absent"` on a working
|
|
110
|
+
* mapping. So this walks the map for `${field}.` prefixed entries and looks at their type.
|
|
111
|
+
*
|
|
112
|
+
* ## One level down, matching the engines
|
|
113
|
+
*
|
|
114
|
+
* A subfield is a DIRECT child: both engines read a declared `subfields` map, so
|
|
115
|
+
* `f.sub.deep` is not a subfield of `f` to either of them. Scanning descendants at any depth
|
|
116
|
+
* would report `"present"` for a mapping the engines refuse.
|
|
117
|
+
*/
|
|
118
|
+
export declare function casePreservingForm(field: string, fieldTypes?: Record<string, TqlFieldType>): "present" | "absent" | "unknown";
|
|
119
|
+
/**
|
|
120
|
+
* Whether a field can answer a case-SENSITIVE operator, as far as the supplied schema shows.
|
|
121
|
+
*
|
|
122
|
+
* Three-valued on purpose. The engines' rule keys on the MAPPING and this package is handed a
|
|
123
|
+
* flat name→type map, so there are genuinely three answers and collapsing them to two is how
|
|
124
|
+
* this ended up unimplemented for a release (tql#206):
|
|
125
|
+
*
|
|
126
|
+
* * `"unsupported"` — both engines raise (`TQLTypeError` / `OpenSearchError::TypeError`)
|
|
127
|
+
* for this field-and-operator pair. That is now true of every type, which it was not
|
|
128
|
+
* when this check was written: Rust's `parse_field_type` had no arm for `geo_point` or
|
|
129
|
+
* `unsigned_long`, dropped such a field from its mappings, and permitted the query —
|
|
130
|
+
* emitting a `wildcard` that could never match. Fixed in tql#210, in this same PR, and
|
|
131
|
+
* `no_field_type_is_silently_dropped` in
|
|
132
|
+
* `tql/tests/opensearch_case_sensitive_unanswerable.rs` holds the property for type
|
|
133
|
+
* names neither engine lists, not just for the two that were noticed.
|
|
134
|
+
* * `"supported"` — the schema shows nothing that would stop the engines translating it.
|
|
135
|
+
* * `"unknown"` — no `fieldTypes` was supplied, or this field is not in it. Nothing is
|
|
136
|
+
* claimed and no diagnostic should be produced.
|
|
137
|
+
*
|
|
138
|
+
* ## Why the OPERATOR is a parameter and not an afterthought
|
|
139
|
+
*
|
|
140
|
+
* The two `_cs` families do NOT share a predicate, and a field-only version of this function
|
|
141
|
+
* got it wrong for six of the eight operators before review caught it:
|
|
142
|
+
*
|
|
143
|
+
* * **Whole-value** (`contains_cs`, `startswith_cs`, `endswith_cs` + negations) refuse
|
|
144
|
+
* whenever there is no un-analyzed form at all — `field_mapping.py`'s
|
|
145
|
+
* `if self.unanalyzed_field is None and operator in CASE_SENSITIVE_WHOLE_VALUE_OPERATORS`,
|
|
146
|
+
* and the unconditional `if CASE_SENSITIVE_WHOLE_VALUE_OPERATORS.contains(&operator)` in
|
|
147
|
+
* `field_mappings.rs`. Neither is gated on the base type. Measured against the Python
|
|
148
|
+
* engine at `{"f": {"type": t}}`: `contains_cs`, `startswith_cs` and `endswith_cs` all
|
|
149
|
+
* raise for `long`, `ip`, `date` and `boolean`.
|
|
150
|
+
* * **Membership** (`in_cs`, `not_in_cs`) refuse only when the base field is analyzed
|
|
151
|
+
* `text` — `operator in CASE_SENSITIVE_MEMBERSHIP_OPERATORS and
|
|
152
|
+
* self.field_types.get(self.base_field_name) == "text"`, and its Rust twin. The same
|
|
153
|
+
* measurement: `f in_cs ['a']` translates to `{"terms": …}` for all four of those types,
|
|
154
|
+
* because case-sensitivity is vacuous for a number, an address, an instant or a flag.
|
|
155
|
+
*
|
|
156
|
+
* So "no case-preserving form" is the whole answer for six operators and half of it for two.
|
|
157
|
+
* `test_a_non_text_field_without_a_keyword_form_is_not_caught` pins the membership half only;
|
|
158
|
+
* reading its NAME as covering all eight is exactly how the field-only version passed review
|
|
159
|
+
* of its own tests.
|
|
160
|
+
*
|
|
161
|
+
* ## Two blind spots, both of which fail SILENT rather than loud
|
|
162
|
+
*
|
|
163
|
+
* 1. **A `wildcard` sibling reads as absent.** The engines accept `wildcard` as a
|
|
164
|
+
* case-preserving form (`FieldType::is_unanalyzed_string`), but `wildcard` is not a member
|
|
165
|
+
* of `TqlFieldType`, so a host cannot express it and this cannot see it.
|
|
166
|
+
* 2. **An object CHILD is indistinguishable from a multifield.** `os` (`text`) beside
|
|
167
|
+
* `os.name` (`keyword`) is read as case-preserving though `os.name` is a sibling field,
|
|
168
|
+
* not a subfield of `os`. A flat map carries no way to tell them apart.
|
|
169
|
+
*
|
|
170
|
+
* Blind spot 2 under-reports (a real refusal goes unwarned — no worse than before this
|
|
171
|
+
* existed), and blind spot 1 over-reports, which is the whole reason the caller emits a
|
|
172
|
+
* WARNING and not an error. Neither justifies staying silent in the ordinary ECS case, which
|
|
173
|
+
* is the case this answers.
|
|
174
|
+
*
|
|
175
|
+
* @param field - the field name as written in the query
|
|
176
|
+
* @param operator - the `_cs` operator being applied. A non-`_cs` operator always returns
|
|
177
|
+
* `"supported"`: this function answers one rule and does not stand in for the type tables.
|
|
178
|
+
* @param fieldTypes - the flat schema, exactly as passed in `TqlValidationOptions.fieldTypes`.
|
|
179
|
+
* For this to return anything but `"unknown"` it must contain the field; for it to
|
|
180
|
+
* distinguish the two `text` shapes it must ALSO contain the multifield entries
|
|
181
|
+
* (`message.keyword`), which is what an index-mapping flattener naturally produces.
|
|
182
|
+
*/
|
|
183
|
+
export declare function caseSensitiveSupport(field: string, operator: TqlComparisonOperator, fieldTypes?: Record<string, TqlFieldType>): CaseSensitiveSupport;
|
|
50
184
|
export declare class TqlValidator {
|
|
51
185
|
private options;
|
|
52
186
|
private errors;
|