Skip to content
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

[Discover] Supports SQL query language (#134429) #136702

Merged
merged 36 commits into from
Jul 26, 2022
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
95da4fc
[Discover] Supports SQL query language (#134429)
stratoula Jul 20, 2022
4cdbd3e
Merge with main and resolve conflicts
stratoula Jul 20, 2022
5af2a49
Fix types
stratoula Jul 20, 2022
c1b5ca2
Fix jest test
stratoula Jul 20, 2022
902dc58
More design fixes
stratoula Jul 20, 2022
0a2504b
Update advanced setting description
stratoula Jul 20, 2022
ab15187
Further design changes
stratoula Jul 20, 2022
074a694
[Discover] Remove document explorer header column edit data view fiel…
kertal Jul 21, 2022
76fc716
[Discover] Implement SQL data fetching for embeddable (#136793)
kertal Jul 21, 2022
0a91517
Allow filters on dashboard level for sql searches
stratoula Jul 21, 2022
42398c9
Merge branch 'main' into unified-search-text-based-lang
stratoula Jul 21, 2022
2927cc5
Fix the radius on the editor
stratoula Jul 21, 2022
56fea12
Add vertical padding on the editor
stratoula Jul 21, 2022
6a14a4c
Change the theme
stratoula Jul 21, 2022
687a8c5
Address PR comments
stratoula Jul 21, 2022
39c8230
Fix types
stratoula Jul 21, 2022
eebc483
Address some of the comments
stratoula Jul 21, 2022
6b8c02d
Fix bug on transitioning from SQL to dataview mode with the modal dis…
stratoula Jul 21, 2022
b29e637
More types fixes
stratoula Jul 21, 2022
2cb4ad6
Merge with main and resolve coflicts
stratoula Jul 22, 2022
68de233
Design review comments
stratoula Jul 22, 2022
65104c5
Discovery team review comments
stratoula Jul 22, 2022
0677400
Fix jest tests
stratoula Jul 22, 2022
6fba8ed
Fix bug on navigating from the SQL mode to the dataview mode and back…
stratoula Jul 22, 2022
c469244
Update src/plugins/discover/public/application/main/hooks/use_discove…
stratoula Jul 22, 2022
3e63318
Add padding to the top of the editor without creating any bug
stratoula Jul 22, 2022
408363e
Add some padding to the bottom without creating any bug
stratoula Jul 22, 2022
7cbbc3f
Fixes undo bug
stratoula Jul 22, 2022
8772fe8
Merge branch 'main' into unified-search-text-based-lang
kibanamachine Jul 25, 2022
3f9b97c
Fix confusing naming of variable
stratoula Jul 25, 2022
3a8abb3
Merge with main and resolve conflicts
stratoula Jul 25, 2022
29afcbf
Fix nested selects
stratoula Jul 25, 2022
f88e01f
Update texts for transition modal and warning
stratoula Jul 25, 2022
785bf57
Make it work with dashboard Query
stratoula Jul 25, 2022
f6846c6
Merge branch 'main' into unified-search-text-based-lang
stratoula Jul 26, 2022
51ad131
Address some of the comments
stratoula Jul 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/management/advanced-options.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,9 @@ The default sort direction for time-based data views.
[[doctable-hidetimecolumn]]`doc_table:hideTimeColumn`::
Hides the "Time" column in *Discover* and in all saved searches on dashboards.

[[discover:enableSql]]`discover:enableSql`::
When enabled, allows SQL queries for search.

[[doctable-highlight]]`doc_table:highlight`::
Highlights results in *Discover* and saved searches on dashboards. Highlighting
slows requests when working on big documents.
Expand Down
8 changes: 5 additions & 3 deletions packages/kbn-es-query/src/es_query/build_es_query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ import { SerializableRecord } from '@kbn/utility-types';
import { buildQueryFromKuery } from './from_kuery';
import { buildQueryFromFilters } from './from_filters';
import { buildQueryFromLucene } from './from_lucene';
import { Filter, Query } from '../filters';
import { Filter, Query, AggregateQuery } from '../filters';
import { isOfQueryType } from './es_query_sql';
import { BoolQuery, DataViewBase } from './types';
import type { KueryQueryOptions } from '../kuery';
import type { EsQueryFiltersConfig } from './from_filters';

type AnyQuery = Query | AggregateQuery;
/**
* Configurations to be used while constructing an ES query.
* @public
Expand Down Expand Up @@ -44,7 +46,7 @@ function removeMatchAll<T>(filters: T[]) {
*/
export function buildEsQuery(
indexPattern: DataViewBase | undefined,
queries: Query | Query[],
queries: AnyQuery | AnyQuery[],
filters: Filter | Filter[],
config: EsQueryConfig = {
allowLeadingWildcards: false,
Expand All @@ -55,7 +57,7 @@ export function buildEsQuery(
queries = Array.isArray(queries) ? queries : [queries];
filters = Array.isArray(filters) ? filters : [filters];

const validQueries = queries.filter((query) => has(query, 'query'));
const validQueries = queries.filter(isOfQueryType).filter((query) => has(query, 'query'));
const queriesByLanguage = groupBy(validQueries, 'language');
const kueryQuery = buildQueryFromKuery(
indexPattern,
Expand Down
79 changes: 79 additions & 0 deletions packages/kbn-es-query/src/es_query/es_query_sql.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import {
isOfQueryType,
isOfAggregateQueryType,
getAggregateQueryMode,
getIndexPatternFromSQLQuery,
} from './es_query_sql';

describe('sql query helpers', () => {
describe('isOfQueryType', () => {
it('should return true for a Query type query', () => {
const flag = isOfQueryType({ query: 'foo', language: 'test' });
expect(flag).toBe(true);
});

it('should return false for an Aggregate type query', () => {
const flag = isOfQueryType({ sql: 'SELECT * FROM foo' });
expect(flag).toBe(false);
});
});

describe('isOfAggregateQueryType', () => {
it('should return false for a Query type query', () => {
const flag = isOfAggregateQueryType({ query: 'foo', language: 'test' });
expect(flag).toBe(false);
});

it('should return true for an Aggregate type query', () => {
const flag = isOfAggregateQueryType({ sql: 'SELECT * FROM foo' });
expect(flag).toBe(true);
});
});

describe('getAggregateQueryMode', () => {
it('should return sql for an SQL AggregateQuery type', () => {
const mode = getAggregateQueryMode({ sql: 'SELECT * FROM foo' });
expect(mode).toBe('sql');
});

it('should return esql for an ESQL AggregateQuery type', () => {
const mode = getAggregateQueryMode({ esql: 'foo | where field > 100' });
expect(mode).toBe('esql');
});
});

describe('getIndexPatternFromSQLQuery', () => {
it('should return the index pattern string from sql queries', () => {
const idxPattern1 = getIndexPatternFromSQLQuery('SELECT * FROM foo');
expect(idxPattern1).toBe('foo');

const idxPattern2 = getIndexPatternFromSQLQuery('SELECT woof, meow FROM "foo"');
expect(idxPattern2).toBe('foo');

const idxPattern3 = getIndexPatternFromSQLQuery('SELECT woof, meow FROM "the_index_pattern"');
expect(idxPattern3).toBe('the_index_pattern');

const idxPattern4 = getIndexPatternFromSQLQuery('SELECT woof, meow FROM "the-index-pattern"');
expect(idxPattern4).toBe('the-index-pattern');

const idxPattern5 = getIndexPatternFromSQLQuery('SELECT woof, meow from "the-index-pattern"');
expect(idxPattern5).toBe('the-index-pattern');

const idxPattern6 = getIndexPatternFromSQLQuery('SELECT woof, meow from "logstash-*"');
expect(idxPattern6).toBe('logstash-*');

const idxPattern7 = getIndexPatternFromSQLQuery(
'SELECT woof, meow from logstash-1234! WHERE field > 100'
);
expect(idxPattern7).toBe('logstash-1234!');
});
});
});
41 changes: 41 additions & 0 deletions packages/kbn-es-query/src/es_query/es_query_sql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { Query, AggregateQuery } from '../filters';

type Language = keyof AggregateQuery;

// Checks if the query is of type Query
export function isOfQueryType(arg?: Query | AggregateQuery): arg is Query {
return Boolean(arg && 'query' in arg);
}

// Checks if the query is of type AggregateQuery
// currently only supports the sql query type
// should be enhanced to support other query types
export function isOfAggregateQueryType(
query: AggregateQuery | Query | { [key: string]: any }
): query is AggregateQuery {
return Boolean(query && ('sql' in query || 'esql' in query));
}

// returns the language of the aggregate Query, sql, esql etc
export function getAggregateQueryMode(query: AggregateQuery): Language {
return Object.keys(query)[0] as Language;
}

// retrieves the index pattern from the aggregate query
export function getIndexPatternFromSQLQuery(sqlQuery?: string): string {
const sql = sqlQuery?.replaceAll('"', '').replaceAll("'", '');
// case insensitive match for the index pattern
const regex = new RegExp(/FROM\s+([\w*-.!@$^()~;]+)/, 'i');
const matches = sql?.match(regex);
if (matches) {
return matches[1];
}
return '';
}
6 changes: 6 additions & 0 deletions packages/kbn-es-query/src/es_query/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ export { buildEsQuery } from './build_es_query';
export { buildQueryFromFilters } from './from_filters';
export { luceneStringToDsl } from './lucene_string_to_dsl';
export { decorateQuery } from './decorate_query';
export {
isOfQueryType,
isOfAggregateQueryType,
getAggregateQueryMode,
getIndexPatternFromSQLQuery,
} from './es_query_sql';
export type {
IFieldSubType,
BoolQuery,
Expand Down
2 changes: 2 additions & 0 deletions packages/kbn-es-query/src/filters/build_filters/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ export type Query = {
language: string;
};

export type AggregateQuery = { sql: string } | { esql: string };

/**
* An interface for a latitude-longitude pair
* @public
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-es-query/src/filters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export {

export type {
Query,
AggregateQuery,
Filter,
LatLon,
FieldFilter,
Expand Down
5 changes: 5 additions & 0 deletions packages/kbn-es-query/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export type {
PhraseFilter,
PhrasesFilter,
Query,
AggregateQuery,
QueryStringFilter,
RangeFilter,
RangeFilterMeta,
Expand All @@ -52,6 +53,10 @@ export {
decorateQuery,
luceneStringToDsl,
migrateFilter,
isOfQueryType,
isOfAggregateQueryType,
getAggregateQueryMode,
getIndexPatternFromSQLQuery,
} from './es_query';

export {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import { History } from 'history';
import { createQueryParamObservable } from '@kbn/kibana-utils-plugin/public';
import type { Query } from '@kbn/es-query';
import { DashboardAppLocatorParams, DashboardConstants } from '../..';
import { DashboardState } from '../../types';
import { getDashboardTitle } from '../../dashboard_strings';
Expand Down Expand Up @@ -113,7 +114,7 @@ function getLocatorParams({
timeRange: shouldRestoreSearchSession ? timefilter.getAbsoluteTime() : timefilter.getTime(),
searchSessionId: shouldRestoreSearchSession ? data.search.session.getSessionId() : undefined,
panels: getDashboardId() ? undefined : appState.panels,
query: queryString.formatQuery(appState.query),
query: queryString.formatQuery(appState.query) as Query,
filters: filterManager.getFilters(),
savedQuery: appState.savedQuery,
dashboardId: getDashboardId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import _ from 'lodash';
import { merge } from 'rxjs';
import { debounceTime, finalize, map, switchMap, tap } from 'rxjs/operators';

import { setQuery } from '../state';
import { DashboardBuildContext, DashboardState } from '../../types';
import { DashboardSavedObject } from '../../saved_dashboards';
Expand Down Expand Up @@ -100,7 +99,7 @@ export const syncDashboardFilterState = ({
// apply filters when the filter manager changes
const filterManagerSubscription = merge(filterManager.getUpdates$(), queryString.getUpdates$())
.pipe(debounceTime(100))
.subscribe(() => applyFilters(queryString.getQuery(), filterManager.getFilters()));
.subscribe(() => applyFilters(queryString.getQuery() as Query, filterManager.getFilters()));

const timeRefreshSubscription = merge(
timefilterService.getRefreshIntervalUpdate$(),
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/data/common/query/query_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import type { Filter } from '@kbn/es-query';
import type { TimeRange, RefreshInterval } from './timefilter/types';
import type { Query } from './types';
import type { Query, AggregateQuery } from './types';

/**
* All query state service state
Expand All @@ -22,5 +22,5 @@ export type QueryState = {
time?: TimeRange;
refreshInterval?: RefreshInterval;
filters?: Filter[];
query?: Query;
query?: Query | AggregateQuery;
};
Loading