mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[ES|QL] Fixes the wrong source validation in case of unknown patterns (#218352)
## Summary Closes https://github.com/elastic/kibana/issues/191556
This commit is contained in:
parent
a2b70a0d45
commit
eec1a9156a
4 changed files with 132 additions and 22 deletions
|
@ -58,6 +58,12 @@ export const validationFromCommandTestSuite = (setup: helpers.Setup) => {
|
|||
await expectErrors('fRoM *,-.*', []);
|
||||
await expectErrors('fRoM .secret_index', []);
|
||||
await expectErrors('from my-index', []);
|
||||
|
||||
await expectErrors('FROM index, missingIndex*', []);
|
||||
await expectErrors('FROM index, lol*catz', []);
|
||||
await expectErrors('FROM index*, lol*catz', []);
|
||||
await expectErrors('FROM missingIndex*, index', []);
|
||||
await expectErrors('FROM missingIndex*, missingIndex2*, index', []);
|
||||
});
|
||||
|
||||
test('errors on trailing comma', async () => {
|
||||
|
@ -95,6 +101,17 @@ export const validationFromCommandTestSuite = (setup: helpers.Setup) => {
|
|||
await expectErrors(`FROM indexes*`, ['Unknown index [indexes*]']);
|
||||
await expectErrors('from numberField', ['Unknown index [numberField]']);
|
||||
await expectErrors('FROM policy', ['Unknown index [policy]']);
|
||||
|
||||
await expectErrors('FROM index, missingIndex', ['Unknown index [missingIndex]']);
|
||||
await expectErrors('FROM missingIndex, index', ['Unknown index [missingIndex]']);
|
||||
await expectErrors('FROM *missingIndex, missingIndex2, index', [
|
||||
'Unknown index [missingIndex2]',
|
||||
]);
|
||||
await expectErrors('FROM missingIndex*', ['Unknown index [missingIndex*]']);
|
||||
await expectErrors('FROM *missingIndex, missing*Index2', [
|
||||
'Unknown index [*missingIndex]',
|
||||
'Unknown index [missing*Index2]',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
import { ESQLAstTimeseriesCommand, ESQLMessage } from '@kbn/esql-ast';
|
||||
import { ESQLFunction, ESQLSource } from '@kbn/esql-ast/src/types';
|
||||
import { ESQLFunction } from '@kbn/esql-ast/src/types';
|
||||
import {
|
||||
isAggFunction,
|
||||
isFunctionOperatorParam,
|
||||
|
@ -16,7 +16,7 @@ import {
|
|||
} from '../../../shared/helpers';
|
||||
import { ReferenceMaps } from '../../types';
|
||||
import { isFunctionItem, isLiteralItem } from '../../../..';
|
||||
import { validateSource } from '../../validation';
|
||||
import { validateSources } from '../../validation';
|
||||
|
||||
/**
|
||||
* Validates the TIMESERIES source command:
|
||||
|
@ -58,16 +58,6 @@ const findNestedAggFunctionInAggFunction = (agg: ESQLFunction): ESQLFunction | u
|
|||
}
|
||||
};
|
||||
|
||||
function validateSources(sources: ESQLSource[], references: ReferenceMaps): ESQLMessage[] {
|
||||
const messages: ESQLMessage[] = [];
|
||||
|
||||
for (const source of sources) {
|
||||
messages.push(...validateSource(source, references));
|
||||
}
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for first nested aggregate function in another aggregate a function,
|
||||
* recursively.
|
||||
|
|
|
@ -9662,6 +9662,31 @@
|
|||
"error": [],
|
||||
"warning": []
|
||||
},
|
||||
{
|
||||
"query": "FROM index, missingIndex*",
|
||||
"error": [],
|
||||
"warning": []
|
||||
},
|
||||
{
|
||||
"query": "FROM index, lol*catz",
|
||||
"error": [],
|
||||
"warning": []
|
||||
},
|
||||
{
|
||||
"query": "FROM index*, lol*catz",
|
||||
"error": [],
|
||||
"warning": []
|
||||
},
|
||||
{
|
||||
"query": "FROM missingIndex*, index",
|
||||
"error": [],
|
||||
"warning": []
|
||||
},
|
||||
{
|
||||
"query": "FROM missingIndex*, missingIndex2*, index",
|
||||
"error": [],
|
||||
"warning": []
|
||||
},
|
||||
{
|
||||
"query": "from index,",
|
||||
"error": [
|
||||
|
@ -9741,6 +9766,42 @@
|
|||
],
|
||||
"warning": []
|
||||
},
|
||||
{
|
||||
"query": "FROM index, missingIndex",
|
||||
"error": [
|
||||
"Unknown index [missingIndex]"
|
||||
],
|
||||
"warning": []
|
||||
},
|
||||
{
|
||||
"query": "FROM missingIndex, index",
|
||||
"error": [
|
||||
"Unknown index [missingIndex]"
|
||||
],
|
||||
"warning": []
|
||||
},
|
||||
{
|
||||
"query": "FROM *missingIndex, missingIndex2, index",
|
||||
"error": [
|
||||
"Unknown index [missingIndex2]"
|
||||
],
|
||||
"warning": []
|
||||
},
|
||||
{
|
||||
"query": "FROM missingIndex*",
|
||||
"error": [
|
||||
"Unknown index [missingIndex*]"
|
||||
],
|
||||
"warning": []
|
||||
},
|
||||
{
|
||||
"query": "FROM *missingIndex, missing*Index2",
|
||||
"error": [
|
||||
"Unknown index [*missingIndex]",
|
||||
"Unknown index [missing*Index2]"
|
||||
],
|
||||
"warning": []
|
||||
},
|
||||
{
|
||||
"query": "from index metadata _id",
|
||||
"error": [],
|
||||
|
|
|
@ -24,6 +24,7 @@ import {
|
|||
areFieldAndVariableTypesCompatible,
|
||||
getColumnExists,
|
||||
getCommandDefinition,
|
||||
hasWildcard,
|
||||
isColumnItem,
|
||||
isFunctionItem,
|
||||
isOptionItem,
|
||||
|
@ -282,11 +283,12 @@ function validateCommand(
|
|||
locations: arg.location,
|
||||
})
|
||||
);
|
||||
} else if (isSourceItem(arg)) {
|
||||
messages.push(...validateSource(arg, references));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const sources = command.args.filter((arg) => isSourceItem(arg)) as ESQLSource[];
|
||||
messages.push(...validateSources(sources, references));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,16 +388,56 @@ function validateUnsupportedTypeFields(fields: Map<string, ESQLRealField>, ast:
|
|||
return messages;
|
||||
}
|
||||
|
||||
export function validateSource(source: ESQLSource, { sources }: ReferenceMaps) {
|
||||
export function validateSources(
|
||||
sources: ESQLSource[],
|
||||
{ sources: availableSources }: ReferenceMaps
|
||||
) {
|
||||
const messages: ESQLMessage[] = [];
|
||||
if (source.incomplete) {
|
||||
return messages;
|
||||
|
||||
const knownIndexNames = [];
|
||||
const knownIndexPatterns = [];
|
||||
const unknownIndexNames = [];
|
||||
const unknownIndexPatterns = [];
|
||||
|
||||
for (const source of sources) {
|
||||
if (source.incomplete) {
|
||||
return messages;
|
||||
}
|
||||
|
||||
if (source.sourceType === 'index') {
|
||||
const index = source.index;
|
||||
const sourceName = source.cluster ? source.name : index?.valueUnquoted;
|
||||
if (!sourceName) continue;
|
||||
|
||||
if (sourceExists(sourceName, availableSources) && !hasWildcard(sourceName)) {
|
||||
knownIndexNames.push(source);
|
||||
}
|
||||
if (sourceExists(sourceName, availableSources) && hasWildcard(sourceName)) {
|
||||
knownIndexPatterns.push(source);
|
||||
}
|
||||
if (!sourceExists(sourceName, availableSources) && !hasWildcard(sourceName)) {
|
||||
unknownIndexNames.push(source);
|
||||
}
|
||||
if (!sourceExists(sourceName, availableSources) && hasWildcard(sourceName)) {
|
||||
unknownIndexPatterns.push(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (source.sourceType === 'index') {
|
||||
const index = source.index;
|
||||
const indexName = source.cluster ? source.name : index?.valueUnquoted;
|
||||
if (indexName && !sourceExists(indexName, sources)) {
|
||||
unknownIndexNames.forEach((source) => {
|
||||
messages.push(
|
||||
getMessageFromId({
|
||||
messageId: 'unknownIndex',
|
||||
values: { name: source.name },
|
||||
locations: source.location,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
if (knownIndexNames.length + unknownIndexNames.length + knownIndexPatterns.length === 0) {
|
||||
// only if there are no known index names, no known index patterns, and no unknown
|
||||
// index names do we worry about creating errors for unknown index patterns
|
||||
unknownIndexPatterns.forEach((source) => {
|
||||
messages.push(
|
||||
getMessageFromId({
|
||||
messageId: 'unknownIndex',
|
||||
|
@ -403,7 +445,7 @@ export function validateSource(source: ESQLSource, { sources }: ReferenceMaps) {
|
|||
locations: source.location,
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return messages;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue