mirror of
https://github.com/elastic/kibana.git
synced 2025-06-28 19:13:14 -04:00
[ES|QL] accept null values for function arguments (#184254)
## Summary
Accepts null values for all function and operator arguments.
<img width="510" alt="Screenshot 2024-05-24 at 11 04 43 AM"
src="75ce23ed
-ec91-404b-8c65-6f023fb71a57">
### Checklist
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
Co-authored-by: Stratoula Kalafateli <efstratia.kalafateli@elastic.co>
This commit is contained in:
parent
d7a095fb74
commit
574fe0a436
7 changed files with 1239 additions and 45 deletions
|
@ -24,6 +24,7 @@ import {
|
|||
isSupportedFieldType,
|
||||
} from '../src/definitions/types';
|
||||
import { FUNCTION_DESCRIBE_BLOCK_NAME } from '../src/validation/function_describe_block_name';
|
||||
import { getMaxMinNumberOfParams } from '../src/validation/helpers';
|
||||
|
||||
export const fieldNameFromType = (type: SupportedFieldType) => `${camelCase(type)}Field`;
|
||||
|
||||
|
@ -51,6 +52,7 @@ function generateTestsForEvalFunction(definition: FunctionDefinition) {
|
|||
generateWhereCommandTestsForEvalFunction(definition, testCases);
|
||||
generateEvalCommandTestsForEvalFunction(definition, testCases);
|
||||
generateSortCommandTestsForEvalFunction(definition, testCases);
|
||||
generateNullAcceptanceTestsForFunction(definition, testCases);
|
||||
return testCases;
|
||||
}
|
||||
|
||||
|
@ -60,6 +62,7 @@ function generateTestsForAggFunction(definition: FunctionDefinition) {
|
|||
generateSortCommandTestsForAggFunction(definition, testCases);
|
||||
generateWhereCommandTestsForAggFunction(definition, testCases);
|
||||
generateEvalCommandTestsForAggFunction(definition, testCases);
|
||||
generateNullAcceptanceTestsForFunction(definition, testCases);
|
||||
return testCases;
|
||||
}
|
||||
|
||||
|
@ -67,9 +70,60 @@ function generateTestsForGroupingFunction(definition: FunctionDefinition) {
|
|||
const testCases: Map<string, string[]> = new Map();
|
||||
generateStatsCommandTestsForGroupingFunction(definition, testCases);
|
||||
generateSortCommandTestsForGroupingFunction(definition, testCases);
|
||||
generateNullAcceptanceTestsForFunction(definition, testCases);
|
||||
return testCases;
|
||||
}
|
||||
|
||||
function generateNullAcceptanceTestsForFunction(
|
||||
definition: FunctionDefinition,
|
||||
testCases: Map<string, string[]>
|
||||
) {
|
||||
const { max, min } = getMaxMinNumberOfParams(definition);
|
||||
const numberOfArgsToTest = max === Infinity ? min : max;
|
||||
const signatureWithGreatestNumberOfParams = definition.signatures.find(
|
||||
(signature) => signature.params.length === numberOfArgsToTest
|
||||
)!;
|
||||
|
||||
const commandToTestWith = definition.supportedCommands.includes('eval') ? 'eval' : 'stats';
|
||||
|
||||
// test that the function accepts nulls
|
||||
testCases.set(
|
||||
`from a_index | ${commandToTestWith} ${
|
||||
getFunctionSignatures(
|
||||
{
|
||||
...definition,
|
||||
signatures: [
|
||||
{
|
||||
...signatureWithGreatestNumberOfParams,
|
||||
params: new Array(numberOfArgsToTest).fill({ name: 'null' }),
|
||||
},
|
||||
],
|
||||
},
|
||||
{ withTypes: false }
|
||||
)[0].declaration
|
||||
}`,
|
||||
[]
|
||||
);
|
||||
|
||||
testCases.set(
|
||||
`row nullVar = null | ${commandToTestWith} ${
|
||||
getFunctionSignatures(
|
||||
{
|
||||
...definition,
|
||||
signatures: [
|
||||
{
|
||||
...signatureWithGreatestNumberOfParams,
|
||||
params: new Array(numberOfArgsToTest).fill({ name: 'nullVar' }),
|
||||
},
|
||||
],
|
||||
},
|
||||
{ withTypes: false }
|
||||
)[0].declaration
|
||||
}`,
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
function generateRowCommandTestsForEvalFunction(
|
||||
{ name, alias, signatures, ...defRest }: FunctionDefinition,
|
||||
testCases: Map<string, string[]>
|
||||
|
@ -262,9 +316,11 @@ function generateWhereCommandTestsForAggFunction(
|
|||
}
|
||||
|
||||
function generateEvalCommandTestsForEvalFunction(
|
||||
{ name, signatures, alias, ...defRest }: FunctionDefinition,
|
||||
definition: FunctionDefinition,
|
||||
testCases: Map<string, string[]>
|
||||
) {
|
||||
const { name, signatures, alias, ...defRest } = definition;
|
||||
|
||||
for (const { params, ...signRest } of signatures) {
|
||||
const fieldMapping = getFieldMapping(params);
|
||||
testCases.set(
|
||||
|
@ -401,26 +457,10 @@ function generateEvalCommandTestsForEvalFunction(
|
|||
|
||||
// test that additional args are spotted
|
||||
|
||||
const getNumberOfParams = (signature: FunctionDefinition['signatures'][number]) => ({
|
||||
all: signature.params.length,
|
||||
required: signature.params.filter(({ optional }) => !optional).length,
|
||||
});
|
||||
|
||||
// get the signature with the greatest number of params
|
||||
const [first, ...rest] = signatures;
|
||||
let signatureWithGreatestNumberOfParams = first;
|
||||
let { all: maxNumberOfArgs, required: minNumberOfArgs } = getNumberOfParams(first);
|
||||
|
||||
for (const signature of rest) {
|
||||
const numberOfParams = signature.params.length;
|
||||
if (numberOfParams > signatureWithGreatestNumberOfParams.params.length) {
|
||||
signatureWithGreatestNumberOfParams = signature;
|
||||
}
|
||||
|
||||
maxNumberOfArgs = Math.max(maxNumberOfArgs, numberOfParams);
|
||||
const numberOfRequiredParams = signature.params.filter(({ optional }) => !optional).length;
|
||||
minNumberOfArgs = Math.min(minNumberOfArgs, numberOfRequiredParams);
|
||||
}
|
||||
const { max: maxNumberOfArgs, min: minNumberOfArgs } = getMaxMinNumberOfParams(definition);
|
||||
const signatureWithGreatestNumberOfParams = signatures.find(
|
||||
(signature) => signature.params.length === maxNumberOfArgs
|
||||
)!;
|
||||
|
||||
const fieldMappingWithOneExtraArg = getFieldMapping(
|
||||
signatureWithGreatestNumberOfParams.params
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue