[ES|QL] Cleanup builtin and rename to operator (#211736)

## Summary

Cleanups the operators
This commit is contained in:
Stratoula Kalafateli 2025-02-20 08:16:02 +01:00 committed by GitHub
parent ba2caf92c6
commit f9193b5540
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 114 additions and 316 deletions

View file

@ -335,7 +335,7 @@ They look like this
testSuggestions('from a | eval a = 1 year /', [
',',
'| ',
...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true, skipAssign: true }, [
...getFunctionSignaturesByReturnType('eval', 'any', { operators: true, skipAssign: true }, [
'time_interval',
]),
]);

View file

@ -759,8 +759,7 @@ const enrichOperators = (
// so we are overriding to add proper support
supportedCommands,
supportedOptions,
// @TODO: change to operator type
type: 'builtin' as const,
type: 'operator' as const,
validate: validators[op.name],
...(isNotOperator ? { ignoreAsSuggestion: true } : {}),
};
@ -769,7 +768,7 @@ const enrichOperators = (
function printGeneratedFunctionsFile(
functionDefinitions: FunctionDefinition[],
functionsType: 'aggregation' | 'scalar' | 'operators' | 'grouping'
functionsType: 'aggregation' | 'scalar' | 'operator' | 'grouping'
) {
/**
* Deals with asciidoc internal cross-references in the function descriptions
@ -864,7 +863,7 @@ ${
import { isLiteralItem } from '../../shared/helpers';`
: ''
}
${functionsType === 'operators' ? `import { isNumericType } from '../../shared/esql_types';` : ''}
${functionsType === 'operator' ? `import { isNumericType } from '../../shared/esql_types';` : ''}
@ -944,7 +943,7 @@ ${functionsType === 'operators' ? `import { isNumericType } from '../../shared/e
);
await writeFile(
join(__dirname, '../src/definitions/generated/operators.ts'),
printGeneratedFunctionsFile(enrichOperators(operatorDefinitions), 'operators')
printGeneratedFunctionsFile(enrichOperators(operatorDefinitions), 'operator')
);
await writeFile(
join(__dirname, '../src/definitions/generated/grouping_functions.ts'),

View file

@ -60,7 +60,7 @@ describe('WHERE <expression>', () => {
'where',
'boolean',
{
builtin: true,
operators: true,
},
undefined,
['and', 'or', 'not']
@ -122,7 +122,7 @@ describe('WHERE <expression>', () => {
...getFunctionSignaturesByReturnType('where', 'any', { scalar: true }),
]);
await assertSuggestions(`from a | where keywordField >= keywordField ${op} doubleField /`, [
...getFunctionSignaturesByReturnType('where', 'boolean', { builtin: true }, ['double']),
...getFunctionSignaturesByReturnType('where', 'boolean', { operators: true }, ['double']),
]);
await assertSuggestions(
`from a | where keywordField >= keywordField ${op} doubleField == /`,
@ -158,9 +158,12 @@ describe('WHERE <expression>', () => {
const { assertSuggestions } = await setup();
await assertSuggestions('from a | stats a=avg(doubleField) | where a /', [
...getFunctionSignaturesByReturnType('where', 'any', { builtin: true, skipAssign: true }, [
'double',
]),
...getFunctionSignaturesByReturnType(
'where',
'any',
{ operators: true, skipAssign: true },
['double']
),
]);
});
@ -212,8 +215,8 @@ describe('WHERE <expression>', () => {
const { assertSuggestions } = await setup();
await assertSuggestions('from a | where log10(doubleField) /', [
...getFunctionSignaturesByReturnType('where', 'double', { builtin: true }, ['double']),
...getFunctionSignaturesByReturnType('where', 'boolean', { builtin: true }, ['double']),
...getFunctionSignaturesByReturnType('where', 'double', { operators: true }, ['double']),
...getFunctionSignaturesByReturnType('where', 'boolean', { operators: true }, ['double']),
]);
});
@ -239,7 +242,7 @@ describe('WHERE <expression>', () => {
...getFunctionSignaturesByReturnType(
'where',
'boolean',
{ builtin: true },
{ operators: true },
['boolean'],
[':']
),
@ -320,7 +323,7 @@ describe('WHERE <expression>', () => {
...getFunctionSignaturesByReturnType(
'where',
'any',
{ builtin: true, skipAssign: true },
{ operators: true, skipAssign: true },
['double'],
[':']
),

View file

@ -59,7 +59,7 @@ describe('autocomplete.suggest', () => {
]);
await assertSuggestions('from a | eval doubleField /', [
...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true, skipAssign: true }, [
...getFunctionSignaturesByReturnType('eval', 'any', { operators: true, skipAssign: true }, [
'double',
]),
',',
@ -145,7 +145,7 @@ describe('autocomplete.suggest', () => {
await assertSuggestions('from a | eval a=round(doubleField) /', [
',',
'| ',
...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true, skipAssign: true }, [
...getFunctionSignaturesByReturnType('eval', 'any', { operators: true, skipAssign: true }, [
'double',
'long',
]),
@ -362,7 +362,7 @@ describe('autocomplete.suggest', () => {
await assertSuggestions('from a | eval var0 = abs(doubleField) / | eval abs(var0)', [
',',
'| ',
...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true, skipAssign: true }, [
...getFunctionSignaturesByReturnType('eval', 'any', { operators: true, skipAssign: true }, [
'double',
]),
]);
@ -454,7 +454,7 @@ describe('autocomplete.suggest', () => {
// Wehther to prepend comma to suggestion string
// E.g. if true, "fieldName" -> "fieldName, "
const shouldAddComma = hasMoreMandatoryArgs && fn.type !== 'builtin';
const shouldAddComma = hasMoreMandatoryArgs && fn.type !== 'operator';
const constantOnlyParamDefs = typesToSuggestNext.filter(
(p) => p.constantOnly || /_literal/.test(p.type as string)
@ -551,9 +551,12 @@ describe('autocomplete.suggest', () => {
...dateSuggestions,
',',
'| ',
...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true, skipAssign: true }, [
'integer',
]),
...getFunctionSignaturesByReturnType(
'eval',
'any',
{ operators: true, skipAssign: true },
['integer']
),
],
{ triggerCharacter: ' ' }
);

View file

@ -10,7 +10,7 @@
import { camelCase } from 'lodash';
import { parse } from '@kbn/esql-ast';
import { scalarFunctionDefinitions } from '../../definitions/generated/scalar_functions';
import { builtinFunctions } from '../../definitions/builtin';
import { operatorsDefinitions } from '../../definitions/all_operators';
import { NOT_SUGGESTED_TYPES } from '../../shared/resources_helpers';
import { aggregationFunctionDefinitions } from '../../definitions/generated/aggregation_functions';
import { timeUnitsToSuggest } from '../../definitions/literals';
@ -137,7 +137,7 @@ export function getFunctionSignaturesByReturnType(
agg,
grouping,
scalar,
builtin,
operators,
// skipAssign here is used to communicate to not propose an assignment if it's not possible
// within the current context (the actual logic has it, but here we want a shortcut)
skipAssign,
@ -145,7 +145,7 @@ export function getFunctionSignaturesByReturnType(
agg?: boolean;
grouping?: boolean;
scalar?: boolean;
builtin?: boolean;
operators?: boolean;
skipAssign?: boolean;
} = {},
paramsTypes?: Readonly<FunctionParameterType[]>,
@ -167,8 +167,8 @@ export function getFunctionSignaturesByReturnType(
if (scalar) {
list.push(...scalarFunctionDefinitions);
}
if (builtin) {
list.push(...builtinFunctions.filter(({ name }) => (skipAssign ? name !== '=' : true)));
if (operators) {
list.push(...operatorsDefinitions.filter(({ name }) => (skipAssign ? name !== '=' : true)));
}
const deduped = Array.from(new Set(list));
@ -217,7 +217,7 @@ export function getFunctionSignaturesByReturnType(
.map<PartialSuggestionWithText>((definition) => {
const { type, name, signatures } = definition;
if (type === 'builtin') {
if (type === 'operator') {
return {
text: signatures.some(({ params }) => params.length > 1)
? `${name.toUpperCase()} $0`

View file

@ -80,7 +80,7 @@ describe('hidden functions', () => {
it('does not suggest hidden operators', async () => {
setTestFunctions([
{
type: 'builtin',
type: 'operator',
name: 'HIDDEN_OPERATOR',
description: 'This is a hidden function',
supportedCommands: ['eval', 'where', 'row', 'sort'],
@ -97,7 +97,7 @@ describe('hidden functions', () => {
],
},
{
type: 'builtin',
type: 'operator',
name: 'VISIBLE_OPERATOR',
description: 'This is a visible function',
supportedCommands: ['eval', 'where', 'row', 'sort'],

View file

@ -536,7 +536,7 @@ describe('autocomplete', () => {
'where',
'boolean',
{
builtin: true,
operators: true,
},
undefined,
['and', 'or', 'not']
@ -550,7 +550,7 @@ describe('autocomplete', () => {
'where',
'any',
{
builtin: true,
operators: true,
skipAssign: true,
},
['integer'],
@ -924,7 +924,7 @@ describe('autocomplete', () => {
'where',
'boolean',
{
builtin: true,
operators: true,
},
['keyword']
).map((s) => (s.text.toLowerCase().includes('null') ? s : attachTriggerCommand(s)))

View file

@ -104,7 +104,7 @@ import {
checkFunctionInvocationComplete,
} from './helper';
import { FunctionParameter, isParameterType } from '../definitions/types';
import { comparisonFunctions } from '../definitions/builtin';
import { comparisonFunctions } from '../definitions/all_operators';
import { getRecommendedQueriesSuggestions } from './recommended_queries/suggestions';
type GetFieldsMapFn = () => Promise<Map<string, ESQLRealField>>;
@ -992,11 +992,11 @@ async function getFunctionArgsSuggestions(
const shouldAddComma =
hasMoreMandatoryArgs &&
fnDefinition.type !== 'builtin' &&
fnDefinition.type !== 'operator' &&
!isCursorFollowedByComma &&
!canBeBooleanCondition;
const shouldAdvanceCursor =
hasMoreMandatoryArgs && fnDefinition.type !== 'builtin' && !isCursorFollowedByComma;
hasMoreMandatoryArgs && fnDefinition.type !== 'operator' && !isCursorFollowedByComma;
const suggestedConstants = uniq(
typesToSuggestNext

View file

@ -8,7 +8,7 @@
*/
import { Walker, type ESQLSingleAstItem, type ESQLFunction } from '@kbn/esql-ast';
import { logicalOperators } from '../../../definitions/builtin';
import { logicalOperators } from '../../../definitions/all_operators';
import { CommandSuggestParams, isParameterType } from '../../../definitions/types';
import { isFunctionItem } from '../../../shared/helpers';
import type { SuggestionRawDefinition } from '../../types';

View file

@ -9,7 +9,7 @@
import { i18n } from '@kbn/i18n';
import type { ItemKind, SuggestionRawDefinition } from './types';
import { builtinFunctions } from '../definitions/builtin';
import { operatorsDefinitions } from '../definitions/all_operators';
import { getOperatorSuggestion, TRIGGER_SUGGESTION_COMMAND } from './factories';
import { CommandDefinition, CommandTypeDefinition } from '../definitions/types';
import { getCommandDefinition } from '../shared/helpers';
@ -24,7 +24,7 @@ const techPreviewLabel = i18n.translate(
);
export function getAssignmentDefinitionCompletitionItem() {
const assignFn = builtinFunctions.find(({ name }) => name === '=')!;
const assignFn = operatorsDefinitions.find(({ name }) => name === '=')!;
return getOperatorSuggestion(assignFn);
}

View file

@ -27,7 +27,7 @@ import { DOUBLE_BACKTICK, SINGLE_TICK_REGEX } from '../shared/constants';
import { ESQLRealField } from '../validation/types';
import { isNumericType } from '../shared/esql_types';
import { getTestFunctions } from '../shared/test_functions';
import { builtinFunctions } from '../definitions/builtin';
import { operatorsDefinitions } from '../definitions/all_operators';
import { ESQLVariableType, ESQLControlVariable } from '../shared/types';
const techPreviewLabel = i18n.translate(
@ -168,7 +168,9 @@ export const getOperatorSuggestions = (
predicates?: FunctionFilterPredicates & { leftParamType?: FunctionParameterType }
): SuggestionRawDefinition[] => {
const filteredDefinitions = filterFunctionDefinitions(
getTestFunctions().length ? [...builtinFunctions, ...getTestFunctions()] : builtinFunctions,
getTestFunctions().length
? [...operatorsDefinitions, ...getTestFunctions()]
: operatorsDefinitions,
predicates
);
@ -188,7 +190,7 @@ export const getOperatorSuggestions = (
};
export const getSuggestionsAfterNot = (): SuggestionRawDefinition[] => {
return builtinFunctions
return operatorsDefinitions
.filter(({ name }) => name === 'like' || name === 'rlike' || name === 'in')
.map(getOperatorSuggestion);
};

View file

@ -291,7 +291,7 @@ export function getValidSignaturesAndTypesToSuggestNext(
// E.g. if true, "fieldName" -> "fieldName, "
const alreadyHasComma = fullText ? fullText[offset] === ',' : false;
const shouldAddComma =
hasMoreMandatoryArgs && fnDefinition.type !== 'builtin' && !alreadyHasComma;
hasMoreMandatoryArgs && fnDefinition.type !== 'operator' && !alreadyHasComma;
const currentArg = enrichedArgs[argIndex];
return {
shouldAddComma,
@ -610,7 +610,7 @@ export async function getSuggestionsToRightOfOperatorExpression({
// technically another boolean value should be suggested, but it is a better experience
// to actually suggest a wider set of fields/functions
const typeToUse =
finalType === 'boolean' && getFunctionDefinition(operator.name)?.type === 'builtin'
finalType === 'boolean' && getFunctionDefinition(operator.name)?.type === 'operator'
? ['any']
: (supportedTypes as string[]);

View file

@ -8,37 +8,10 @@
*/
import { i18n } from '@kbn/i18n';
import { isNumericType } from '../shared/esql_types';
import type { FunctionDefinition, FunctionParameterType, FunctionReturnType } from './types';
import { operatorsFunctionDefinitions } from './generated/operators';
import { operatorFunctionDefinitions } from './generated/operators';
type MathFunctionSignature = [FunctionParameterType, FunctionParameterType, FunctionReturnType];
function createMathDefinition(
name: string,
functionSignatures: MathFunctionSignature[],
description: string,
validate?: FunctionDefinition['validate']
): FunctionDefinition {
return {
type: 'builtin',
name,
description,
supportedCommands: ['eval', 'where', 'row', 'stats', 'metrics', 'sort'],
supportedOptions: ['by'],
signatures: functionSignatures.map((functionSignature) => {
const [lhs, rhs, result] = functionSignature;
return {
params: [
{ name: 'left', type: lhs },
{ name: 'right', type: rhs },
],
returnType: result,
};
}),
validate,
};
}
// https://www.elastic.co/guide/en/elasticsearch/reference/master/esql-functions-operators.html#_less_than
const baseComparisonTypeTable: MathFunctionSignature[] = [
['date', 'date', 'boolean'],
@ -84,7 +57,7 @@ function createComparisonDefinition(
});
return {
type: 'builtin' as const,
type: 'operator' as const,
name,
description,
supportedCommands: ['eval', 'where', 'row', 'sort'],
@ -121,176 +94,9 @@ function createComparisonDefinition(
};
}
const addTypeTable: MathFunctionSignature[] = [
['date_period', 'date_period', 'date_period'],
['date_period', 'date', 'date'],
['date', 'date_period', 'date'],
['date', 'time_duration', 'date'],
['date', 'time_literal', 'date'],
['double', 'double', 'double'],
['double', 'integer', 'double'],
['double', 'long', 'double'],
['integer', 'double', 'double'],
['integer', 'integer', 'integer'],
['integer', 'long', 'long'],
['long', 'double', 'double'],
['long', 'integer', 'long'],
['long', 'long', 'long'],
['time_duration', 'date', 'date'],
['time_duration', 'time_duration', 'time_duration'],
['unsigned_long', 'unsigned_long', 'unsigned_long'],
['time_literal', 'date', 'date'],
];
const subtractTypeTable: MathFunctionSignature[] = [
['date_period', 'date_period', 'date_period'],
['date', 'date_period', 'date'],
['date', 'time_duration', 'date'],
['date', 'time_literal', 'date'],
['double', 'double', 'double'],
['double', 'integer', 'double'],
['double', 'long', 'double'],
['integer', 'double', 'double'],
['integer', 'integer', 'integer'],
['integer', 'long', 'long'],
['long', 'double', 'double'],
['long', 'integer', 'long'],
['long', 'long', 'long'],
['time_duration', 'date', 'date'],
['time_duration', 'time_duration', 'time_duration'],
['unsigned_long', 'unsigned_long', 'unsigned_long'],
['time_literal', 'date', 'date'],
];
const multiplyTypeTable: MathFunctionSignature[] = [
['double', 'double', 'double'],
['double', 'integer', 'double'],
['double', 'long', 'double'],
['integer', 'double', 'double'],
['integer', 'integer', 'integer'],
['integer', 'long', 'long'],
['long', 'double', 'double'],
['long', 'integer', 'long'],
['long', 'long', 'long'],
['unsigned_long', 'unsigned_long', 'unsigned_long'],
];
const divideTypeTable: MathFunctionSignature[] = [
['double', 'double', 'double'],
['double', 'integer', 'double'],
['double', 'long', 'double'],
['integer', 'double', 'double'],
['integer', 'integer', 'integer'],
['integer', 'long', 'long'],
['long', 'double', 'double'],
['long', 'integer', 'long'],
['long', 'long', 'long'],
['unsigned_long', 'unsigned_long', 'unsigned_long'],
];
const modulusTypeTable: MathFunctionSignature[] = [
['double', 'double', 'double'],
['double', 'integer', 'double'],
['double', 'long', 'double'],
['integer', 'double', 'double'],
['integer', 'integer', 'integer'],
['integer', 'long', 'long'],
['long', 'double', 'double'],
['long', 'integer', 'long'],
['long', 'long', 'long'],
['unsigned_long', 'unsigned_long', 'unsigned_long'],
];
export const mathFunctions: FunctionDefinition[] = [
createMathDefinition(
'+',
addTypeTable,
i18n.translate('kbn-esql-validation-autocomplete.esql.definition.addDoc', {
defaultMessage: 'Add (+)',
})
),
createMathDefinition(
'-',
subtractTypeTable,
i18n.translate('kbn-esql-validation-autocomplete.esql.definition.subtractDoc', {
defaultMessage: 'Subtract (-)',
})
),
createMathDefinition(
'*',
multiplyTypeTable,
i18n.translate('kbn-esql-validation-autocomplete.esql.definition.multiplyDoc', {
defaultMessage: 'Multiply (*)',
})
),
createMathDefinition(
'/',
divideTypeTable,
i18n.translate('kbn-esql-validation-autocomplete.esql.definition.divideDoc', {
defaultMessage: 'Divide (/)',
}),
(fnDef) => {
const [left, right] = fnDef.args;
const messages = [];
if (!Array.isArray(left) && !Array.isArray(right)) {
if (right.type === 'literal' && isNumericType(right.literalType)) {
if (right.value === 0) {
messages.push({
type: 'warning' as const,
code: 'divideByZero',
text: i18n.translate(
'kbn-esql-validation-autocomplete.esql.divide.warning.divideByZero',
{
defaultMessage: 'Cannot divide by zero: {left}/{right}',
values: {
left: left.text,
right: right.value,
},
}
),
location: fnDef.location,
});
}
}
}
return messages;
}
),
createMathDefinition(
'%',
modulusTypeTable,
i18n.translate('kbn-esql-validation-autocomplete.esql.definition.moduleDoc', {
defaultMessage: 'Module (%)',
}),
(fnDef) => {
const [left, right] = fnDef.args;
const messages = [];
if (!Array.isArray(left) && !Array.isArray(right)) {
if (right.type === 'literal' && isNumericType(right.literalType)) {
if (right.value === 0) {
messages.push({
type: 'warning' as const,
code: 'moduleByZero',
text: i18n.translate(
'kbn-esql-validation-autocomplete.esql.divide.warning.zeroModule',
{
defaultMessage: 'Module by zero can return null value: {left}%{right}',
values: {
left: left.text,
right: right.value,
},
}
),
location: fnDef.location,
});
}
}
}
return messages;
}
),
];
// these functions are also in the operatorFunctionDefinitions. There is no way to extract them from there
// because the operatorFunctionDefinitions are generated from ES definitions. This is why we need to
// duplicate them here
export const comparisonFunctions: FunctionDefinition[] = [
{
name: '==',
@ -398,7 +204,7 @@ export const logicalOperators: FunctionDefinition[] = [
}),
},
].map(({ name, description }) => ({
type: 'builtin' as const,
type: 'operator' as const,
name,
description,
supportedCommands: ['eval', 'where', 'row', 'sort'],
@ -428,7 +234,7 @@ const nullFunctions: FunctionDefinition[] = [
}),
},
].map<FunctionDefinition>(({ name, description }) => ({
type: 'builtin',
type: 'operator',
name,
description,
supportedCommands: ['eval', 'where', 'row', 'sort'],
@ -442,7 +248,7 @@ const nullFunctions: FunctionDefinition[] = [
const otherDefinitions: FunctionDefinition[] = [
{
type: 'builtin' as const,
type: 'operator' as const,
name: 'not',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definition.notDoc', {
defaultMessage: 'Not',
@ -457,7 +263,7 @@ const otherDefinitions: FunctionDefinition[] = [
],
},
{
type: 'builtin' as const,
type: 'operator' as const,
name: '=',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definition.assignDoc', {
defaultMessage: 'Assign (=)',
@ -484,7 +290,7 @@ const otherDefinitions: FunctionDefinition[] = [
],
},
{
type: 'builtin' as const,
type: 'operator' as const,
name: 'as',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definition.asDoc', {
defaultMessage: 'Rename as (AS)',
@ -502,7 +308,7 @@ const otherDefinitions: FunctionDefinition[] = [
],
},
{
type: 'builtin' as const,
type: 'operator' as const,
name: 'where',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definition.whereDoc', {
defaultMessage: 'WHERE operator',
@ -522,7 +328,7 @@ const otherDefinitions: FunctionDefinition[] = [
{
// TODO — this shouldn't be a function or an operator...
name: 'info',
type: 'builtin',
type: 'operator',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definition.infoDoc', {
defaultMessage: 'Show information about the current ES node',
}),
@ -536,8 +342,8 @@ const otherDefinitions: FunctionDefinition[] = [
},
];
export const builtinFunctions: FunctionDefinition[] = [
...operatorsFunctionDefinitions,
export const operatorsDefinitions: FunctionDefinition[] = [
...operatorFunctionDefinitions,
...logicalOperators,
...nullFunctions,
...otherDefinitions,

View file

@ -143,7 +143,7 @@ const statsValidator = (command: ESQLCommand) => {
}
// now check that:
// * the agg function is at root level
// * or if it's a builtin function, then all operands are agg functions or literals
// * or if it's a operators function, then all operands are agg functions or literals
// * or if it's a eval function then all arguments are agg functions or literals
function checkFunctionContent(arg: ESQLFunction) {
// TODO the grouping function check may not

View file

@ -33,7 +33,7 @@ import { isNumericType } from '../../shared/esql_types';
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const addDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: '+',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.add', {
defaultMessage:
@ -377,7 +377,7 @@ const addDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const divDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: '/',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.div', {
defaultMessage:
@ -570,7 +570,7 @@ const divDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const equalsDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: '==',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.equals', {
defaultMessage:
@ -1060,7 +1060,7 @@ const equalsDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const greaterThanDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: '>',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.greater_than', {
defaultMessage:
@ -1434,7 +1434,7 @@ const greaterThanDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const greaterThanOrEqualDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: '>=',
description: i18n.translate(
'kbn-esql-validation-autocomplete.esql.definitions.greater_than_or_equal',
@ -1811,7 +1811,7 @@ const greaterThanOrEqualDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const inDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: 'in',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.in', {
defaultMessage:
@ -2053,7 +2053,7 @@ const inDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const lessThanDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: '<',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.less_than', {
defaultMessage:
@ -2427,7 +2427,7 @@ const lessThanDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const lessThanOrEqualDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: '<=',
description: i18n.translate(
'kbn-esql-validation-autocomplete.esql.definitions.less_than_or_equal',
@ -2748,7 +2748,7 @@ const lessThanOrEqualDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const likeDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: 'like',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.like', {
defaultMessage:
@ -2830,7 +2830,7 @@ const likeDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const matchOperatorDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: ':',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.match_operator', {
defaultMessage:
@ -3343,7 +3343,7 @@ const matchOperatorDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const modDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: '%',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.mod', {
defaultMessage:
@ -3536,7 +3536,7 @@ const modDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const mulDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: '*',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.mul', {
defaultMessage:
@ -3704,7 +3704,7 @@ const mulDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const negDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: '-',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.neg', {
defaultMessage: 'Returns the negation of the argument.',
@ -3771,7 +3771,7 @@ const negDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const notEqualsDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: '!=',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.not_equals', {
defaultMessage:
@ -4261,7 +4261,7 @@ const notEqualsDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const notInDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: 'not_in',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.not_in', {
defaultMessage:
@ -4505,7 +4505,7 @@ const notInDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const notLikeDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: 'not_like',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.not_like', {
defaultMessage:
@ -4555,7 +4555,7 @@ const notLikeDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const notRlikeDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: 'not_rlike',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.not_rlike', {
defaultMessage:
@ -4605,7 +4605,7 @@ const notRlikeDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const rlikeDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: 'rlike',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.rlike', {
defaultMessage:
@ -4689,7 +4689,7 @@ const rlikeDefinition: FunctionDefinition = {
// Do not edit this manually... generated by scripts/generate_function_definitions.ts
const subDefinition: FunctionDefinition = {
type: 'builtin',
type: 'operator',
name: '-',
description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.sub', {
defaultMessage:
@ -5000,7 +5000,7 @@ const subDefinition: FunctionDefinition = {
validate: undefined,
examples: [],
};
export const operatorsFunctionDefinitions = [
export const operatorFunctionDefinitions = [
addDefinition,
divDefinition,
equalsDefinition,

View file

@ -175,7 +175,7 @@ export interface Signature {
}
export interface FunctionDefinition {
type: 'builtin' | 'agg' | 'scalar' | 'operator' | 'grouping';
type: 'agg' | 'scalar' | 'operator' | 'grouping';
preview?: boolean;
ignoreAsSuggestion?: boolean;
name: string;

View file

@ -138,8 +138,8 @@ function isNotEnrichClauseAssigment(node: ESQLFunction, command: ESQLCommand) {
return node.name !== '=' && command.name !== 'enrich';
}
function isBuiltinFunction(node: ESQLFunction) {
return getFunctionDefinition(node.name)?.type === 'builtin';
function isOperator(node: ESQLFunction) {
return getFunctionDefinition(node.name)?.type === 'operator';
}
/**
@ -187,7 +187,7 @@ export function getAstContext(queryString: string, ast: ESQLAst, offset: number)
// be handled as functions for the stats command.
// I expect this to simplify once https://github.com/elastic/kibana/issues/195418
// is complete
!(isBuiltinFunction(node) && command.name !== 'stats')
!(isOperator(node) && command.name !== 'stats')
) {
// command ... fn( <here> )
return { type: 'function' as const, command, node, option, setting };

View file

@ -26,7 +26,7 @@ import {
ESQLProperNode,
} from '@kbn/esql-ast/src/types';
import { aggregationFunctionDefinitions } from '../definitions/generated/aggregation_functions';
import { builtinFunctions } from '../definitions/builtin';
import { operatorsDefinitions } from '../definitions/all_operators';
import { commandDefinitions } from '../definitions/commands';
import { scalarFunctionDefinitions } from '../definitions/generated/scalar_functions';
import { groupingFunctionDefinitions } from '../definitions/generated/grouping_functions';
@ -116,7 +116,7 @@ export function isMathFunction(query: string, offset: number) {
const [opString] = queryTrimmed.split(' ').reverse();
// compare last char for all math functions
// limit only to 2 chars operators
const fns = builtinFunctions.filter(({ name }) => name.length < 3).map(({ name }) => name);
const fns = operatorsDefinitions.filter(({ name }) => name.length < 3).map(({ name }) => name);
const tokenMatch = fns.some((op) => opString === op);
// there's a match, that's good
if (tokenMatch) {
@ -143,7 +143,7 @@ let commandLookups: Map<string, CommandDefinition<string>> | undefined;
function buildFunctionLookup() {
// we always refresh if we have test functions
if (!fnLookups || getTestFunctions().length) {
fnLookups = builtinFunctions
fnLookups = operatorsDefinitions
.concat(
scalarFunctionDefinitions,
aggregationFunctionDefinitions,

View file

@ -170,7 +170,7 @@ describe('function validation', () => {
it('list type', async () => {
const testFn: FunctionDefinition = {
name: 'in',
type: 'builtin',
type: 'operator',
description: '',
supportedCommands: ['row'],
signatures: [

View file

@ -278,18 +278,18 @@ export const validationStatsCommandTestSuite = (setup: helpers.Setup) => {
for (const nesting of NESTED_DEPTHS) {
describe(`depth = ${nesting}`, () => {
describe('builtin', () => {
const builtinWrapping = Array(nesting).fill('+1').join('');
describe('operators', () => {
const operatorsWrapping = Array(nesting).fill('+1').join('');
test('no errors', async () => {
const { expectErrors } = await setup();
await expectErrors(
`from a_index | INLINESTATS 5 + avg(doubleField) ${builtinWrapping}`,
`from a_index | INLINESTATS 5 + avg(doubleField) ${operatorsWrapping}`,
[]
);
await expectErrors(
`from a_index | INLINESTATS 5 ${builtinWrapping} + avg(doubleField)`,
`from a_index | INLINESTATS 5 ${operatorsWrapping} + avg(doubleField)`,
[]
);
});
@ -298,21 +298,21 @@ export const validationStatsCommandTestSuite = (setup: helpers.Setup) => {
const { expectErrors } = await setup();
await expectErrors(
`from a_index | INLINESTATS 5 ${builtinWrapping} + doubleField`,
`from a_index | INLINESTATS 5 ${operatorsWrapping} + doubleField`,
[
`At least one aggregation function required in [INLINESTATS], found [5${builtinWrapping}+doubleField]`,
`At least one aggregation function required in [INLINESTATS], found [5${operatorsWrapping}+doubleField]`,
]
);
await expectErrors(
`from a_index | INLINESTATS 5 + doubleField ${builtinWrapping}`,
`from a_index | INLINESTATS 5 + doubleField ${operatorsWrapping}`,
[
`At least one aggregation function required in [INLINESTATS], found [5+doubleField${builtinWrapping}]`,
`At least one aggregation function required in [INLINESTATS], found [5+doubleField${operatorsWrapping}]`,
]
);
await expectErrors(
`from a_index | INLINESTATS 5 + doubleField ${builtinWrapping}, var0 = sum(doubleField)`,
`from a_index | INLINESTATS 5 + doubleField ${operatorsWrapping}, var0 = sum(doubleField)`,
[
`At least one aggregation function required in [INLINESTATS], found [5+doubleField${builtinWrapping}]`,
`At least one aggregation function required in [INLINESTATS], found [5+doubleField${operatorsWrapping}]`,
]
);
});

View file

@ -272,18 +272,18 @@ export const validationStatsCommandTestSuite = (setup: helpers.Setup) => {
for (const nesting of NESTED_DEPTHS) {
describe(`depth = ${nesting}`, () => {
describe('builtin', () => {
const builtinWrapping = Array(nesting).fill('+1').join('');
describe('operators', () => {
const operatorsWrapping = Array(nesting).fill('+1').join('');
test('no errors', async () => {
const { expectErrors } = await setup();
await expectErrors(
`from a_index | stats 5 + avg(doubleField) ${builtinWrapping}`,
`from a_index | stats 5 + avg(doubleField) ${operatorsWrapping}`,
[]
);
await expectErrors(
`from a_index | stats 5 ${builtinWrapping} + avg(doubleField)`,
`from a_index | stats 5 ${operatorsWrapping} + avg(doubleField)`,
[]
);
});
@ -291,16 +291,16 @@ export const validationStatsCommandTestSuite = (setup: helpers.Setup) => {
test('errors', async () => {
const { expectErrors } = await setup();
await expectErrors(`from a_index | stats 5 ${builtinWrapping} + doubleField`, [
`At least one aggregation function required in [STATS], found [5${builtinWrapping}+doubleField]`,
await expectErrors(`from a_index | stats 5 ${operatorsWrapping} + doubleField`, [
`At least one aggregation function required in [STATS], found [5${operatorsWrapping}+doubleField]`,
]);
await expectErrors(`from a_index | stats 5 + doubleField ${builtinWrapping}`, [
`At least one aggregation function required in [STATS], found [5+doubleField${builtinWrapping}]`,
await expectErrors(`from a_index | stats 5 + doubleField ${operatorsWrapping}`, [
`At least one aggregation function required in [STATS], found [5+doubleField${operatorsWrapping}]`,
]);
await expectErrors(
`from a_index | stats 5 + doubleField ${builtinWrapping}, var0 = sum(doubleField)`,
`from a_index | stats 5 + doubleField ${operatorsWrapping}, var0 = sum(doubleField)`,
[
`At least one aggregation function required in [STATS], found [5+doubleField${builtinWrapping}]`,
`At least one aggregation function required in [STATS], found [5+doubleField${operatorsWrapping}]`,
]
);
});

View file

@ -5290,10 +5290,8 @@
"kbn-esql-validation-autocomplete.esql.autocomplete.timeSystemParamStart": "L'heure de début à partir du sélecteur de date",
"kbn-esql-validation-autocomplete.esql.autocomplete.valueDefinition": "Valeur littérale",
"kbn-esql-validation-autocomplete.esql.autocomplete.variableDefinition": "Variable spécifiée par l'utilisateur dans la requête ES|QL",
"kbn-esql-validation-autocomplete.esql.definition.addDoc": "Ajouter (+)",
"kbn-esql-validation-autocomplete.esql.definition.andDoc": "et",
"kbn-esql-validation-autocomplete.esql.definition.assignDoc": "Affecter (=)",
"kbn-esql-validation-autocomplete.esql.definition.divideDoc": "Diviser (/)",
"kbn-esql-validation-autocomplete.esql.definition.equalToDoc": "Égal à",
"kbn-esql-validation-autocomplete.esql.definition.greaterThanDoc": "Supérieur à",
"kbn-esql-validation-autocomplete.esql.definition.greaterThanOrEqualToDoc": "Supérieur ou égal à",
@ -5302,12 +5300,9 @@
"kbn-esql-validation-autocomplete.esql.definition.isNullDoc": "Prédicat pour la comparaison NULL : renvoie \"true\" si la valeur est NULL",
"kbn-esql-validation-autocomplete.esql.definition.lessThanDoc": "Inférieur à",
"kbn-esql-validation-autocomplete.esql.definition.lessThanOrEqualToDoc": "Inférieur ou égal à",
"kbn-esql-validation-autocomplete.esql.definition.moduleDoc": "Module (%)",
"kbn-esql-validation-autocomplete.esql.definition.multiplyDoc": "Multiplier (*)",
"kbn-esql-validation-autocomplete.esql.definition.notDoc": "Non",
"kbn-esql-validation-autocomplete.esql.definition.notEqualToDoc": "Différent de",
"kbn-esql-validation-autocomplete.esql.definition.orDoc": "ou",
"kbn-esql-validation-autocomplete.esql.definition.subtractDoc": "Subtract (-)",
"kbn-esql-validation-autocomplete.esql.definitions.abs": "Renvoie la valeur absolue.",
"kbn-esql-validation-autocomplete.esql.definitions.acos": "Renvoie l'arc cosinus de `n` sous forme d'angle, exprimé en radians.",
"kbn-esql-validation-autocomplete.esql.definitions.appendSeparatorDoc": "Le ou les caractères qui séparent les champs ajoutés. A pour valeur par défaut une chaîne vide (\"\").",

View file

@ -5285,10 +5285,8 @@
"kbn-esql-validation-autocomplete.esql.autocomplete.timeSystemParamStart": "日付ピッカーの開始日時",
"kbn-esql-validation-autocomplete.esql.autocomplete.valueDefinition": "リテラル値",
"kbn-esql-validation-autocomplete.esql.autocomplete.variableDefinition": "ES|QLクエリーでユーザーが指定した変数",
"kbn-esql-validation-autocomplete.esql.definition.addDoc": "加算(+",
"kbn-esql-validation-autocomplete.esql.definition.andDoc": "AND",
"kbn-esql-validation-autocomplete.esql.definition.assignDoc": "割り当て(=",
"kbn-esql-validation-autocomplete.esql.definition.divideDoc": "除算(/",
"kbn-esql-validation-autocomplete.esql.definition.equalToDoc": "等しい",
"kbn-esql-validation-autocomplete.esql.definition.greaterThanDoc": "より大きい",
"kbn-esql-validation-autocomplete.esql.definition.greaterThanOrEqualToDoc": "よりも大きいまたは等しい",
@ -5297,12 +5295,9 @@
"kbn-esql-validation-autocomplete.esql.definition.isNullDoc": "NULL比較の述部値がNULLである場合にTrueを返します",
"kbn-esql-validation-autocomplete.esql.definition.lessThanDoc": "より小さい",
"kbn-esql-validation-autocomplete.esql.definition.lessThanOrEqualToDoc": "以下",
"kbn-esql-validation-autocomplete.esql.definition.moduleDoc": "モジュール(%",
"kbn-esql-validation-autocomplete.esql.definition.multiplyDoc": "乗算(*",
"kbn-esql-validation-autocomplete.esql.definition.notDoc": "NOT",
"kbn-esql-validation-autocomplete.esql.definition.notEqualToDoc": "Not equal to",
"kbn-esql-validation-autocomplete.esql.definition.orDoc": "または",
"kbn-esql-validation-autocomplete.esql.definition.subtractDoc": "減算(-",
"kbn-esql-validation-autocomplete.esql.definitions.abs": "絶対値を返します。",
"kbn-esql-validation-autocomplete.esql.definitions.acos": "nのアークコサインをラジアンで表記された角度として返します。",
"kbn-esql-validation-autocomplete.esql.definitions.appendSeparatorDoc": "追加されたフィールドを区切る文字。デフォルトは空の文字列(\"\")です。",

View file

@ -5252,10 +5252,8 @@
"kbn-esql-validation-autocomplete.esql.autocomplete.timeSystemParamStart": "日期选取器中的开始时间",
"kbn-esql-validation-autocomplete.esql.autocomplete.valueDefinition": "文本值",
"kbn-esql-validation-autocomplete.esql.autocomplete.variableDefinition": "用户在 ES|QL 查询中指定的变量",
"kbn-esql-validation-autocomplete.esql.definition.addDoc": "添加 (+)",
"kbn-esql-validation-autocomplete.esql.definition.andDoc": "且",
"kbn-esql-validation-autocomplete.esql.definition.assignDoc": "分配 (=)",
"kbn-esql-validation-autocomplete.esql.definition.divideDoc": "除 (/)",
"kbn-esql-validation-autocomplete.esql.definition.equalToDoc": "等于",
"kbn-esql-validation-autocomplete.esql.definition.greaterThanDoc": "大于",
"kbn-esql-validation-autocomplete.esql.definition.greaterThanOrEqualToDoc": "大于或等于",
@ -5264,12 +5262,9 @@
"kbn-esql-validation-autocomplete.esql.definition.isNullDoc": "用于 NULL 比较的谓词:如果值为 NULL则返回 true",
"kbn-esql-validation-autocomplete.esql.definition.lessThanDoc": "小于",
"kbn-esql-validation-autocomplete.esql.definition.lessThanOrEqualToDoc": "小于或等于",
"kbn-esql-validation-autocomplete.esql.definition.moduleDoc": "取余数 (%)",
"kbn-esql-validation-autocomplete.esql.definition.multiplyDoc": "乘 (*)",
"kbn-esql-validation-autocomplete.esql.definition.notDoc": "非",
"kbn-esql-validation-autocomplete.esql.definition.notEqualToDoc": "不等于",
"kbn-esql-validation-autocomplete.esql.definition.orDoc": "或",
"kbn-esql-validation-autocomplete.esql.definition.subtractDoc": "减 (-)",
"kbn-esql-validation-autocomplete.esql.definitions.abs": "返回绝对值。",
"kbn-esql-validation-autocomplete.esql.definitions.acos": "返回 `n` 的反余弦作为角度,以弧度表示。",
"kbn-esql-validation-autocomplete.esql.definitions.appendSeparatorDoc": "分隔已追加字段的字符。默认为空字符串 (\"\")。",