-
Notifications
You must be signed in to change notification settings - Fork 8.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ES|QL] add validation for VALUES
and MV_SORT
#179874
Changes from 26 commits
7915807
81da135
6a70189
11485e2
ae67251
8469be6
881c265
f6368c5
3247190
9778c7d
42d3832
10e1c00
954d4b5
9bdde37
4b9feaf
90baa5b
979e40e
e5a2ae7
e21e5dd
d0d5caa
acff5e7
7de22de
ce13b6c
2ac7a3a
e17547e
243bab5
98c6b5f
3d8ab9c
4a1e176
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -245,7 +245,7 @@ describe('autocomplete', () => { | |
// simulate the editor behaviour for sorting suggestions | ||
.sort((a, b) => (a.sortText || '').localeCompare(b.sortText || '')); | ||
for (const [index, receivedSuggestion] of suggestionInertTextSorted.entries()) { | ||
if (typeof expected[index] === 'string') { | ||
if (typeof expected[index] !== 'object') { | ||
expect(receivedSuggestion.text).toEqual(expected[index]); | ||
} else { | ||
// check all properties that are defined in the expected suggestion | ||
|
@@ -1054,38 +1054,47 @@ describe('autocomplete', () => { | |
if (fn.name !== 'auto_bucket') { | ||
for (const signature of fn.signatures) { | ||
signature.params.forEach((param, i) => { | ||
if (i < signature.params.length - 1) { | ||
if (i < signature.params.length) { | ||
const canHaveMoreArgs = | ||
i + 1 < (signature.minParams ?? 0) || | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
signature.params.filter(({ optional }, j) => !optional && j > i).length > i; | ||
testSuggestions( | ||
`from a | eval ${fn.name}(${Array(i).fill('field').join(', ')}${i ? ',' : ''} )`, | ||
[ | ||
...getFieldNamesByType(param.type).map((f) => (canHaveMoreArgs ? `${f},` : f)), | ||
...getFunctionSignaturesByReturnType( | ||
'eval', | ||
param.type, | ||
{ evalMath: true }, | ||
undefined, | ||
[fn.name] | ||
).map((l) => (canHaveMoreArgs ? `${l},` : l)), | ||
...getLiteralsByType(param.type).map((d) => (canHaveMoreArgs ? `${d},` : d)), | ||
] | ||
param.literalOptions?.length | ||
? param.literalOptions.map((option) => `"${option}"${canHaveMoreArgs ? ',' : ''}`) | ||
: [ | ||
...getFieldNamesByType(param.type).map((f) => | ||
canHaveMoreArgs ? `${f},` : f | ||
), | ||
...getFunctionSignaturesByReturnType( | ||
'eval', | ||
param.type, | ||
{ evalMath: true }, | ||
undefined, | ||
[fn.name] | ||
).map((l) => (canHaveMoreArgs ? `${l},` : l)), | ||
...getLiteralsByType(param.type).map((d) => (canHaveMoreArgs ? `${d},` : d)), | ||
] | ||
); | ||
testSuggestions( | ||
`from a | eval var0 = ${fn.name}(${Array(i).fill('field').join(', ')}${ | ||
i ? ',' : '' | ||
} )`, | ||
[ | ||
...getFieldNamesByType(param.type).map((f) => (canHaveMoreArgs ? `${f},` : f)), | ||
...getFunctionSignaturesByReturnType( | ||
'eval', | ||
param.type, | ||
{ evalMath: true }, | ||
undefined, | ||
[fn.name] | ||
).map((l) => (canHaveMoreArgs ? `${l},` : l)), | ||
...getLiteralsByType(param.type).map((d) => (canHaveMoreArgs ? `${d},` : d)), | ||
] | ||
param.literalOptions?.length | ||
? param.literalOptions.map((option) => `"${option}"${canHaveMoreArgs ? ',' : ''}`) | ||
: [ | ||
...getFieldNamesByType(param.type).map((f) => | ||
canHaveMoreArgs ? `${f},` : f | ||
), | ||
...getFunctionSignaturesByReturnType( | ||
'eval', | ||
param.type, | ||
{ evalMath: true }, | ||
undefined, | ||
[fn.name] | ||
).map((l) => (canHaveMoreArgs ? `${l},` : l)), | ||
...getLiteralsByType(param.type).map((d) => (canHaveMoreArgs ? `${d},` : d)), | ||
] | ||
); | ||
} | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -165,6 +165,16 @@ export const buildConstantsDefinitions = ( | |
sortText: 'A', | ||
})); | ||
|
||
export const buildValueDefinitions = (values: string[]): SuggestionRawDefinition[] => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As a follow up of this PR I would probably reuse this for |
||
values.map((value) => ({ | ||
label: `"${value}"`, | ||
text: `"${value}"`, | ||
detail: i18n.translate('kbn-esql-validation-autocomplete.esql.autocomplete.valueDefinition', { | ||
defaultMessage: 'Literal value', | ||
}), | ||
kind: 'Value', | ||
})); | ||
|
||
export const buildNewVarDefinition = (label: string): SuggestionRawDefinition => { | ||
return { | ||
label, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,7 +97,6 @@ export const evalFunctionsDefinitions: FunctionDefinition[] = [ | |
], | ||
validate: validateLogFunctions, | ||
}, | ||
|
||
{ | ||
name: 'log', | ||
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.logDoc', { | ||
|
@@ -481,14 +480,9 @@ export const evalFunctionsDefinitions: FunctionDefinition[] = [ | |
signatures: [ | ||
{ | ||
params: [{ name: 'field', type: 'string' }], | ||
returnType: 'version', | ||
returnType: 'string', | ||
examples: [`from index | EVAL version = to_version(stringField)`], | ||
}, | ||
{ | ||
params: [{ name: 'field', type: 'version' }], | ||
returnType: 'version', | ||
examples: [`from index | EVAL version = to_version(versionField)`], | ||
}, | ||
], | ||
Comment on lines
480
to
486
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We aren't using Elasticsearch types yet (look at #174710). So, |
||
}, | ||
{ | ||
|
@@ -924,6 +918,30 @@ export const evalFunctionsDefinitions: FunctionDefinition[] = [ | |
}, | ||
], | ||
}, | ||
{ | ||
name: 'mv_sort', | ||
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.mvSortDoc', { | ||
defaultMessage: 'Sorts a multivalue expression in lexicographical order.', | ||
}), | ||
signatures: [ | ||
{ | ||
params: [ | ||
{ name: 'field', type: 'any' }, | ||
{ | ||
name: 'order', | ||
type: 'string', | ||
optional: true, | ||
drewdaemon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
literalOptions: ['asc', 'desc'], | ||
}, | ||
], | ||
returnType: 'any', | ||
examples: [ | ||
'row a = [4, 2, -3, 2] | eval sorted = mv_sort(a)', | ||
'row a = ["b", "c", "a"] | sorted = mv_sort(a, "DESC")', | ||
], | ||
}, | ||
], | ||
}, | ||
{ | ||
name: 'mv_avg', | ||
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.mvAvgDoc', { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,22 @@ export interface FunctionDefinition { | |
optional?: boolean; | ||
noNestingFunctions?: boolean; | ||
supportsWildcard?: boolean; | ||
/** | ||
* if set this indicates that the value must be a literal | ||
* but can be any literal of the correct type | ||
*/ | ||
literalOnly?: boolean; | ||
/** | ||
* if provided this means that the value must be one | ||
* of the options in the array iff the value is a literal. | ||
* | ||
* String values are case insensitive. | ||
* | ||
* If the value is not a literal, this field is ignored because | ||
* we can't check the return value of a function to see if it | ||
* matches one of the options prior to runtime. | ||
*/ | ||
literalOptions?: string[]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we call it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you clarify a bit? I'm thinking options better describes what this is. "value" implies what the user actually chooses, whereas "options" says to me a set of values they are allowed to choose. |
||
}>; | ||
minParams?: number; | ||
returnType: string; | ||
|
@@ -87,3 +102,5 @@ export type SignatureType = | |
| FunctionDefinition['signatures'][number] | ||
| CommandOptionsDefinition['signature']; | ||
export type SignatureArgType = SignatureType['params'][number]; | ||
|
||
export type FunctionArgSignature = FunctionDefinition['signatures'][number]['params'][number]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests were skipping the final parameter of each call signature. Updated to test all parameters of each function.