From 7054f58170ffd4d31aa69d767ab3a5e5f49d6fde Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Fri, 10 May 2024 18:07:31 +0200 Subject: [PATCH] [ES|QL] More usages of getESQLQueryColumns (#182691) ## Summary This PR is an attempt to use the `getESQLQueryColumns` util everywhere we are trying to fetch the columns (using the limit 0). --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .i18nrc.json | 1 + packages/kbn-esql-utils/index.ts | 1 + packages/kbn-esql-utils/src/index.ts | 2 +- .../kbn-esql-utils/src/utils/run_query.ts | 96 ++++++++++++++----- packages/kbn-esql-utils/tsconfig.json | 3 +- .../classes/sources/esql_source/esql_utils.ts | 38 ++------ .../rule_creation/logic/esql_validator.ts | 10 +- .../logic/get_esql_query_config.ts | 14 +-- .../use_esql_fields_options.test.ts | 36 +++---- .../use_esql_fields_options.ts | 15 +-- .../hooks/use_investigation_fields.test.ts | 15 +-- .../hooks/use_investigation_fields.ts | 15 +-- .../plugins/security_solution/tsconfig.json | 1 - .../expression/esql_query_expression.tsx | 12 ++- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 17 files changed, 142 insertions(+), 120 deletions(-) diff --git a/.i18nrc.json b/.i18nrc.json index 1a29b7b9ed68d..4d546716ffe2e 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -96,6 +96,7 @@ "randomSampling": "x-pack/packages/kbn-random-sampling", "reactPackages": "packages/react", "textBasedEditor": "packages/kbn-text-based-editor", + "esqlUtils": "packages/kbn-esql-utils", "reporting": "packages/kbn-reporting", "savedObjects": "src/plugins/saved_objects", "savedObjectsFinder": "src/plugins/saved_objects_finder", diff --git a/packages/kbn-esql-utils/index.ts b/packages/kbn-esql-utils/index.ts index 029b7aab48db1..f3203cba662cf 100644 --- a/packages/kbn-esql-utils/index.ts +++ b/packages/kbn-esql-utils/index.ts @@ -17,6 +17,7 @@ export { appendToESQLQuery, appendWhereClauseToESQLQuery, getESQLQueryColumns, + getESQLQueryColumnsRaw, TextBasedLanguages, } from './src'; diff --git a/packages/kbn-esql-utils/src/index.ts b/packages/kbn-esql-utils/src/index.ts index 373223419b22d..0b62f2aedc58d 100644 --- a/packages/kbn-esql-utils/src/index.ts +++ b/packages/kbn-esql-utils/src/index.ts @@ -16,4 +16,4 @@ export { removeDropCommandsFromESQLQuery, } from './utils/query_parsing_helpers'; export { appendToESQLQuery, appendWhereClauseToESQLQuery } from './utils/append_to_query'; -export { getESQLQueryColumns } from './utils/run_query'; +export { getESQLQueryColumns, getESQLQueryColumnsRaw } from './utils/run_query'; diff --git a/packages/kbn-esql-utils/src/utils/run_query.ts b/packages/kbn-esql-utils/src/utils/run_query.ts index d94d2e07e5a53..099b4b876b943 100644 --- a/packages/kbn-esql-utils/src/utils/run_query.ts +++ b/packages/kbn-esql-utils/src/utils/run_query.ts @@ -5,10 +5,11 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ +import { i18n } from '@kbn/i18n'; import type { DatatableColumn } from '@kbn/expressions-plugin/common'; import type { ISearchGeneric } from '@kbn/search-types'; import { esFieldTypeToKibanaFieldType } from '@kbn/field-types'; -import type { ESQLSearchReponse } from '@kbn/es-types'; +import type { ESQLColumn, ESQLSearchReponse } from '@kbn/es-types'; import { lastValueFrom } from 'rxjs'; import { ESQL_LATEST_VERSION } from '../../constants'; @@ -21,32 +22,77 @@ export async function getESQLQueryColumns({ search: ISearchGeneric; signal?: AbortSignal; }): Promise { - const response = await lastValueFrom( - search( - { - params: { - query: `${esqlQuery} | limit 0`, - version: ESQL_LATEST_VERSION, + try { + const response = await lastValueFrom( + search( + { + params: { + query: `${esqlQuery} | limit 0`, + version: ESQL_LATEST_VERSION, + }, }, - }, - { - abortSignal: signal, - strategy: 'esql_async', - } - ) - ); + { + abortSignal: signal, + strategy: 'esql_async', + } + ) + ); - const columns = - (response.rawResponse as unknown as ESQLSearchReponse).columns?.map(({ name, type }) => { - const kibanaType = esFieldTypeToKibanaFieldType(type); - const column = { - id: name, - name, - meta: { type: kibanaType, esType: type }, - } as DatatableColumn; + const columns = + (response.rawResponse as unknown as ESQLSearchReponse).columns?.map(({ name, type }) => { + const kibanaType = esFieldTypeToKibanaFieldType(type); + const column = { + id: name, + name, + meta: { type: kibanaType, esType: type }, + } as DatatableColumn; - return column; - }) ?? []; + return column; + }) ?? []; - return columns; + return columns; + } catch (error) { + throw new Error( + i18n.translate('esqlUtils.columnsErrorMsg', { + defaultMessage: 'Unable to load columns. {errorMessage}', + values: { errorMessage: error.message }, + }) + ); + } +} + +export async function getESQLQueryColumnsRaw({ + esqlQuery, + search, + signal, +}: { + esqlQuery: string; + search: ISearchGeneric; + signal?: AbortSignal; +}): Promise { + try { + const response = await lastValueFrom( + search( + { + params: { + query: `${esqlQuery} | limit 0`, + version: ESQL_LATEST_VERSION, + }, + }, + { + abortSignal: signal, + strategy: 'esql_async', + } + ) + ); + + return (response.rawResponse as unknown as ESQLSearchReponse).columns ?? []; + } catch (error) { + throw new Error( + i18n.translate('esqlUtils.columnsErrorMsg', { + defaultMessage: 'Unable to load columns. {errorMessage}', + values: { errorMessage: error.message }, + }) + ); + } } diff --git a/packages/kbn-esql-utils/tsconfig.json b/packages/kbn-esql-utils/tsconfig.json index dcd3a6da1795b..a6470bec40ee1 100644 --- a/packages/kbn-esql-utils/tsconfig.json +++ b/packages/kbn-esql-utils/tsconfig.json @@ -23,6 +23,7 @@ "@kbn/search-types", "@kbn/expressions-plugin", "@kbn/field-types", - "@kbn/es-types" + "@kbn/es-types", + "@kbn/i18n" ] } diff --git a/x-pack/plugins/maps/public/classes/sources/esql_source/esql_utils.ts b/x-pack/plugins/maps/public/classes/sources/esql_source/esql_utils.ts index 90df8e174a0c2..32ab2c88cc57b 100644 --- a/x-pack/plugins/maps/public/classes/sources/esql_source/esql_utils.ts +++ b/x-pack/plugins/maps/public/classes/sources/esql_source/esql_utils.ts @@ -6,14 +6,13 @@ */ import { i18n } from '@kbn/i18n'; -import { lastValueFrom } from 'rxjs'; import type { DataView } from '@kbn/data-plugin/common'; import { - ESQL_LATEST_VERSION, getESQLAdHocDataview, getIndexPatternFromESQLQuery, + getESQLQueryColumnsRaw, } from '@kbn/esql-utils'; -import type { ESQLColumn, ESQLSearchReponse } from '@kbn/es-types'; +import type { ESQLColumn } from '@kbn/es-types'; import { ES_GEO_FIELD_TYPE } from '../../../../common/constants'; import { getData, getIndexPatternService } from '../../../kibana_services'; @@ -59,7 +58,10 @@ export async function getESQLMeta(esql: string) { getIndexPatternService() ); return { - columns: await getColumns(esql), + columns: await getESQLQueryColumnsRaw({ + esqlQuery: esql, + search: getData().search.search, + }), adhocDataViewId: adhocDataView.id!, ...getFields(adhocDataView), }; @@ -87,34 +89,6 @@ export function getFieldType(column: ESQLColumn) { } } -async function getColumns(esql: string) { - const params = { - query: esql + ' | limit 0', - version: ESQL_LATEST_VERSION, - }; - - try { - const resp = await lastValueFrom( - getData().search.search( - { params }, - { - strategy: 'esql', - } - ) - ); - - const searchResponse = resp.rawResponse as unknown as ESQLSearchReponse; - return searchResponse.all_columns ? searchResponse.all_columns : searchResponse.columns; - } catch (error) { - throw new Error( - i18n.translate('xpack.maps.source.esql.getColumnsErrorMsg', { - defaultMessage: 'Unable to load columns. {errorMessage}', - values: { errorMessage: error.message }, - }) - ); - } -} - export function getFields(dataView: DataView) { const dateFields: string[] = []; const geoFields: string[] = []; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/logic/esql_validator.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/logic/esql_validator.ts index e7a6e523965b2..b7e9f1b033e31 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/logic/esql_validator.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/logic/esql_validator.ts @@ -71,16 +71,16 @@ export const esqlValidator = async ( }; } - const data = await securitySolutionQueryClient.fetchQuery( - getEsqlQueryConfig({ esqlQuery: query, expressions: services.expressions }) + const columns = await securitySolutionQueryClient.fetchQuery( + getEsqlQueryConfig({ esqlQuery: query, search: services.data.search.search }) ); - if (data && 'error' in data) { - return constructValidationError(data.error); + if (columns && 'error' in columns) { + return constructValidationError(columns.error); } // check whether _id field is present in response - const isIdFieldPresent = (data?.columns ?? []).find(({ id }) => '_id' === id); + const isIdFieldPresent = (columns ?? []).find(({ id }) => '_id' === id); // for non-aggregating query, we want to disable queries w/o _id property returned in response if (!isEsqlQueryAggregating && !isIdFieldPresent) { return { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/logic/get_esql_query_config.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/logic/get_esql_query_config.ts index bb07b0438a49d..c7d4f9184f181 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/logic/get_esql_query_config.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/logic/get_esql_query_config.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { fetchFieldsFromESQL } from '@kbn/text-based-editor'; -import type { ExpressionsStart } from '@kbn/expressions-plugin/public'; +import { getESQLQueryColumns } from '@kbn/esql-utils'; +import type { ISearchGeneric } from '@kbn/search-types'; /** * react-query configuration to be used to fetch ES|QL fields @@ -14,12 +14,11 @@ import type { ExpressionsStart } from '@kbn/expressions-plugin/public'; */ export const getEsqlQueryConfig = ({ esqlQuery, - expressions, + search, }: { esqlQuery: string | undefined; - expressions: ExpressionsStart; + search: ISearchGeneric; }) => { - const emptyResultsEsqlQuery = `${esqlQuery} | limit 0`; return { queryKey: [(esqlQuery ?? '').trim()], queryFn: async () => { @@ -27,7 +26,10 @@ export const getEsqlQueryConfig = ({ return null; } try { - const res = await fetchFieldsFromESQL({ esql: emptyResultsEsqlQuery }, expressions); + const res = await getESQLQueryColumns({ + esqlQuery, + search, + }); return res; } catch (e) { return { error: e }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/esql_autocomplete/use_esql_fields_options.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/esql_autocomplete/use_esql_fields_options.test.ts index d70d0c154b45e..e6a6b3d4a3d78 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/esql_autocomplete/use_esql_fields_options.test.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/esql_autocomplete/use_esql_fields_options.test.ts @@ -19,17 +19,13 @@ describe('esqlToOptions', () => { }); it('should transform all columns if fieldTYpe is not passed', () => { expect( - esqlToOptions({ - type: 'datatable', - rows: [], - columns: [ - { name: '@timestamp', id: '@timestamp', meta: { type: 'date' } }, - { name: 'agent.build.original', id: 'agent.build.original', meta: { type: 'string' } }, - { name: 'amqp.app-id', id: 'amqp.app-id', meta: { type: 'string' } }, - { name: 'amqp.auto-delete', id: 'amqp.auto-delete', meta: { type: 'number' } }, - { name: 'amqp.class-id', id: 'amqp.class-id', meta: { type: 'boolean' } }, - ], - }) + esqlToOptions([ + { name: '@timestamp', id: '@timestamp', meta: { type: 'date' } }, + { name: 'agent.build.original', id: 'agent.build.original', meta: { type: 'string' } }, + { name: 'amqp.app-id', id: 'amqp.app-id', meta: { type: 'string' } }, + { name: 'amqp.auto-delete', id: 'amqp.auto-delete', meta: { type: 'number' } }, + { name: 'amqp.class-id', id: 'amqp.class-id', meta: { type: 'boolean' } }, + ]) ).toEqual([ { label: '@timestamp' }, { label: 'agent.build.original' }, @@ -41,17 +37,13 @@ describe('esqlToOptions', () => { it('should transform only columns of exact fieldType', () => { expect( esqlToOptions( - { - type: 'datatable', - rows: [], - columns: [ - { name: '@timestamp', id: '@timestamp', meta: { type: 'date' } }, - { name: 'agent.build.original', id: 'agent.build.original', meta: { type: 'string' } }, - { name: 'amqp.app-id', id: 'amqp.app-id', meta: { type: 'string' } }, - { name: 'amqp.auto-delete', id: 'amqp.auto-delete', meta: { type: 'number' } }, - { name: 'amqp.class-id', id: 'amqp.class-id', meta: { type: 'boolean' } }, - ], - }, + [ + { name: '@timestamp', id: '@timestamp', meta: { type: 'date' } }, + { name: 'agent.build.original', id: 'agent.build.original', meta: { type: 'string' } }, + { name: 'amqp.app-id', id: 'amqp.app-id', meta: { type: 'string' } }, + { name: 'amqp.auto-delete', id: 'amqp.auto-delete', meta: { type: 'number' } }, + { name: 'amqp.class-id', id: 'amqp.class-id', meta: { type: 'boolean' } }, + ], 'string' ) ).toEqual([{ label: 'agent.build.original' }, { label: 'amqp.app-id' }]); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/esql_autocomplete/use_esql_fields_options.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/esql_autocomplete/use_esql_fields_options.ts index b8fc47c41c798..b29d44c0b855f 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/esql_autocomplete/use_esql_fields_options.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/esql_autocomplete/use_esql_fields_options.ts @@ -6,7 +6,8 @@ */ import { useMemo } from 'react'; import type { EuiComboBoxOptionOption } from '@elastic/eui'; -import type { Datatable, ExpressionsStart } from '@kbn/expressions-plugin/public'; +import type { DatatableColumn } from '@kbn/expressions-plugin/public'; +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { useQuery } from '@tanstack/react-query'; @@ -16,14 +17,14 @@ import { getEsqlQueryConfig } from '../../../rule_creation/logic/get_esql_query_ import type { FieldType } from '../../../rule_creation/logic/esql_validator'; export const esqlToOptions = ( - data: { error: unknown } | Datatable | undefined | null, + columns: { error: unknown } | DatatableColumn[] | undefined | null, fieldType?: FieldType ) => { - if (data && 'error' in data) { + if (columns && 'error' in columns) { return []; } - const options = (data?.columns ?? []).reduce>((acc, { id, meta }) => { + const options = (columns ?? []).reduce>((acc, { id, meta }) => { // if fieldType absent, we do not filter columns by type if (!fieldType || fieldType === meta.type) { acc.push({ label: id }); @@ -46,11 +47,11 @@ type UseEsqlFieldOptions = ( * fetches ES|QL fields and convert them to Combobox options */ export const useEsqlFieldOptions: UseEsqlFieldOptions = (esqlQuery, fieldType) => { - const kibana = useKibana<{ expressions: ExpressionsStart }>(); + const kibana = useKibana<{ data: DataPublicPluginStart }>(); - const { expressions } = kibana.services; + const { data: dataService } = kibana.services; - const queryConfig = getEsqlQueryConfig({ esqlQuery, expressions }); + const queryConfig = getEsqlQueryConfig({ esqlQuery, search: dataService.search.search }); const { data, isLoading } = useQuery(queryConfig); const options = useMemo(() => { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_investigation_fields.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_investigation_fields.test.ts index 6a159f87d89d8..597d44f47f0d9 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_investigation_fields.test.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_investigation_fields.test.ts @@ -13,18 +13,21 @@ import { useInvestigationFields } from './use_investigation_fields'; import { createQueryWrapperMock } from '../../../common/__mocks__/query_wrapper'; import { computeIsESQLQueryAggregating } from '@kbn/securitysolution-utils'; -import { fetchFieldsFromESQL } from '@kbn/text-based-editor'; +import { getESQLQueryColumns } from '@kbn/esql-utils'; jest.mock('@kbn/securitysolution-utils', () => ({ computeIsESQLQueryAggregating: jest.fn(), })); -jest.mock('@kbn/text-based-editor', () => ({ - fetchFieldsFromESQL: jest.fn(), -})); +jest.mock('@kbn/esql-utils', () => { + return { + getESQLQueryColumns: jest.fn(), + getIndexPatternFromESQLQuery: jest.fn().mockReturnValue('auditbeat*'), + }; +}); const computeIsESQLQueryAggregatingMock = computeIsESQLQueryAggregating as jest.Mock; -const fetchFieldsFromESQLMock = fetchFieldsFromESQL as jest.Mock; +const getESQLQueryColumnsMock = getESQLQueryColumns as jest.Mock; const { wrapper } = createQueryWrapperMock(); @@ -48,7 +51,7 @@ const mockEsqlDatatable = { describe('useInvestigationFields', () => { beforeEach(() => { jest.clearAllMocks(); - fetchFieldsFromESQLMock.mockResolvedValue(mockEsqlDatatable); + getESQLQueryColumnsMock.mockResolvedValue(mockEsqlDatatable.columns); }); it('should return loading true when esql fields still loading', () => { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_investigation_fields.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_investigation_fields.ts index b9b5dc1a07713..1627bddaa82be 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_investigation_fields.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_investigation_fields.ts @@ -5,7 +5,8 @@ * 2.0. */ import { useMemo } from 'react'; -import type { Datatable, ExpressionsStart } from '@kbn/expressions-plugin/public'; +import type { DatatableColumn } from '@kbn/expressions-plugin/public'; +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { DataViewFieldBase } from '@kbn/es-query'; import { computeIsESQLQueryAggregating } from '@kbn/securitysolution-utils'; @@ -16,13 +17,13 @@ import { useKibana } from '@kbn/kibana-react-plugin/public'; import { getEsqlQueryConfig } from '../../rule_creation/logic/get_esql_query_config'; const esqlToFields = ( - data: { error: unknown } | Datatable | undefined | null + columns: { error: unknown } | DatatableColumn[] | undefined | null ): DataViewFieldBase[] => { - if (data && 'error' in data) { + if (columns && 'error' in columns) { return []; } - const fields = (data?.columns ?? []).map(({ id, meta }) => { + const fields = (columns ?? []).map(({ id, meta }) => { return { name: id, type: meta.type, @@ -41,11 +42,11 @@ type UseEsqlFields = (esqlQuery: string | undefined) => { * fetches ES|QL fields and convert them to DataViewBase fields */ const useEsqlFields: UseEsqlFields = (esqlQuery) => { - const kibana = useKibana<{ expressions: ExpressionsStart }>(); + const kibana = useKibana<{ data: DataPublicPluginStart }>(); - const { expressions } = kibana.services; + const { data: dataService } = kibana.services; - const queryConfig = getEsqlQueryConfig({ esqlQuery, expressions }); + const queryConfig = getEsqlQueryConfig({ esqlQuery, search: dataService?.search?.search }); const { data, isLoading } = useQuery(queryConfig); const fields = useMemo(() => { diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json index dd625a978f316..b5778dbf20e39 100644 --- a/x-pack/plugins/security_solution/tsconfig.json +++ b/x-pack/plugins/security_solution/tsconfig.json @@ -154,7 +154,6 @@ "@kbn/expressions-plugin", "@kbn/dev-proc-runner", "@kbn/alerts-ui-shared", - "@kbn/text-based-editor", "@kbn/security-solution-navigation", "@kbn/security-solution-upselling", "@kbn/discover-plugin", diff --git a/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/esql_query_expression.tsx b/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/esql_query_expression.tsx index 7b5220906610e..febae77ad0f22 100644 --- a/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/esql_query_expression.tsx +++ b/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/esql_query_expression.tsx @@ -16,6 +16,7 @@ import { EuiSelect, EuiSpacer, } from '@elastic/eui'; +import { getESQLQueryColumns } from '@kbn/esql-utils'; import { getFields, RuleTypeParamsExpressionProps } from '@kbn/triggers-actions-ui-plugin/public'; import { TextBasedLangEditor } from '@kbn/text-based-languages/public'; import { fetchFieldsFromESQL } from '@kbn/text-based-editor'; @@ -41,7 +42,7 @@ import { rowToDocument, toEsQueryHits, transformDatatableToEsqlTable } from '../ export const EsqlQueryExpression: React.FC< RuleTypeParamsExpressionProps, EsQueryRuleMetaData> > = ({ ruleParams, setRuleParams, setRuleProperty, errors }) => { - const { expressions, http, fieldFormats, isServerless } = useTriggerUiActionServices(); + const { expressions, http, fieldFormats, isServerless, data } = useTriggerUiActionServices(); const { esqlQuery, timeWindowSize, timeWindowUnit, timeField, sourceFields } = ruleParams; const [currentRuleParams, setCurrentRuleParams] = useState< @@ -182,9 +183,12 @@ export const EsqlQueryExpression: React.FC< const refreshEsFields = async (q: AggregateQuery, resetSourceFields: boolean = true) => { let fields: FieldOption[] = []; try { - const table = await fetchFieldsFromESQL({ esql: `${get(q, 'esql')} | limit 0` }, expressions); - if (table) { - fields = table.columns.map((c) => ({ + const columns = await getESQLQueryColumns({ + esqlQuery: `${get(q, 'esql')}`, + search: data.search.search, + }); + if (columns.length) { + fields = columns.map((c) => ({ name: c.id, type: c.meta.type, normalizedType: c.meta.type, diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 8c079ea4fca43..13de72efe1050 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -24324,7 +24324,6 @@ "xpack.maps.source.esGrid.compositePaginationErrorMessage": "{layerName} génère trop de requêtes. Réduisez \"Résolution de la grille\" et/ou réduisez le nombre d'indicateurs de premier terme.", "xpack.maps.source.esGrid.resolutionParamErrorMessage": "Paramètre de résolution de grille non reconnu : {resolution}", "xpack.maps.source.esJoin.countLabel": "compte de {indexPatternLabel}", - "xpack.maps.source.esql.getColumnsErrorMsg": "Impossible de charger les colonnes. {errorMessage}", "xpack.maps.source.esql.multipleGeometryColumnErrorMsg": "La requête Elasticsearch ES|QL comporte {count} colonnes géométriques alors qu'une seule est autorisée. Utilisez 'DROP' (abandonner) ou 'KEEP' (conserver) pour réduire les colonnes.", "xpack.maps.source.esSearch.clusterScalingLabel": "Afficher les clusters lorsque les résultats dépassent {maxResultWindow}", "xpack.maps.source.esSearch.convertToGeoJsonErrorMsg": "Impossible de convertir la réponse de la recherche à la collecte de fonctionnalités geoJson, erreur : {errorMsg}", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 1b5881673ca58..5d7fd8c925d8c 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -24299,7 +24299,6 @@ "xpack.maps.source.esGrid.compositePaginationErrorMessage": "{layerName} はリクエスト過多の原因になります。「グリッド解像度」を下げるか、またはトップ用語「メトリック」の数を減らしてください。", "xpack.maps.source.esGrid.resolutionParamErrorMessage": "グリッド解像度パラメーターが認識されません:{resolution}", "xpack.maps.source.esJoin.countLabel": "{indexPatternLabel}の数", - "xpack.maps.source.esql.getColumnsErrorMsg": "列を読み込めません。{errorMessage}", "xpack.maps.source.esql.multipleGeometryColumnErrorMsg": "1のみが許可されているときには、Elasticsearch ES|QLクエリには{count}ジオメトリ列があります。DROPまたはKEEPを使用して、列を絞り込んでください。", "xpack.maps.source.esSearch.clusterScalingLabel": "結果が{maxResultWindow}を超えたらクラスターを表示", "xpack.maps.source.esSearch.convertToGeoJsonErrorMsg": "検索への応答を geoJson 機能コレクションに変換できません。エラー:{errorMsg}", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index c2b897e9f4b36..adda160b16fa7 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -24332,7 +24332,6 @@ "xpack.maps.source.esGrid.compositePaginationErrorMessage": "{layerName} 正导致过多的请求。降低“网格分辨率”和/或减少热门词“指标”的数量。", "xpack.maps.source.esGrid.resolutionParamErrorMessage": "无法识别网格分辨率参数:{resolution}", "xpack.maps.source.esJoin.countLabel": "{indexPatternLabel} 的计数", - "xpack.maps.source.esql.getColumnsErrorMsg": "无法加载列。{errorMessage}", "xpack.maps.source.esql.multipleGeometryColumnErrorMsg": "只允许 1 列时,Elasticsearch ES|QL 查询具有 {count} 个几何图形列。请使用“DROP”或“KEEP”缩小列范围。", "xpack.maps.source.esSearch.clusterScalingLabel": "结果超过 {maxResultWindow} 个时显示集群", "xpack.maps.source.esSearch.convertToGeoJsonErrorMsg": "无法将搜索响应转换成 geoJson 功能集合,错误:{errorMsg}",