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

[Auto Suggest] Add MDS Support Along with A Few Cleanup and tests #7463

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,6 @@ snapshots.js

# Yarn local mirror content
.yarn-local-mirror

# Ignore the generated antlr files
/src/plugins/data/public/antlr/opensearch_sql/grammar/.antlr
2 changes: 2 additions & 0 deletions changelogs/fragments/7463.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
feat:
- Add MDS support along with a few cleanup and tests update ([#7463](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/7463))
52 changes: 16 additions & 36 deletions src/plugins/data/public/antlr/opensearch_sql/code_completion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { monaco } from 'packages/osd-monaco/target';
import { monaco } from '@osd/monaco';
import { Lexer as LexerType, ParserRuleContext, Parser as ParserType } from 'antlr4ng';
import { CodeCompletionCore } from 'antlr4-c3';
import {
Expand All @@ -21,10 +21,9 @@ import { createParser } from './parse';
import { SqlErrorListener } from './sql_error_listerner';
import { findCursorTokenIndex } from '../shared/cursor';
import { openSearchSqlAutocompleteData } from './opensearch_sql_autocomplete';
import { getUiSettings } from '../../services';
import { SQL_SYMBOLS } from './constants';
import { QuerySuggestionGetFnArgs } from '../../autocomplete';
import { fetchColumnValues, fetchTableSchemas } from '../shared/utils';
import { QuerySuggestion, QuerySuggestionGetFnArgs } from '../../autocomplete';
import { fetchTableSchemas } from '../shared/utils';

export interface SuggestionParams {
position: monaco.Position;
Expand All @@ -44,68 +43,48 @@ export const getSuggestions = async ({
selectionEnd,
position,
query,
connectionService,
}: QuerySuggestionGetFnArgs): Promise<ISuggestionItem[]> => {
const { api } = getUiSettings();
openSearchDashboards,
}: QuerySuggestionGetFnArgs): Promise<QuerySuggestion[]> => {
const { api } = openSearchDashboards.uiSettings;
const dataSetManager = openSearchDashboards.data.query.dataSet;
const suggestions = getOpenSearchSqlAutoCompleteSuggestions(query, {
line: position?.lineNumber || selectionStart,
column: position?.column || selectionEnd,
});

const finalSuggestions = [];
const finalSuggestions = [] as QuerySuggestion[];

try {
// Fetch columns and values
if ('suggestColumns' in suggestions && (suggestions.suggestColumns?.tables?.length ?? 0) > 0) {
const tableNames = suggestions.suggestColumns?.tables?.map((table) => table.name) ?? [];
const schemas = await fetchTableSchemas(tableNames, api, connectionService);
const schemas = await fetchTableSchemas(tableNames, api, dataSetManager);

schemas.forEach((schema) => {
if (schema.body?.fields?.length > 0) {
const columns = schema.body.fields.find((col) => col.name === 'COLUMN_NAME');
const fieldTypes = schema.body.fields.find((col) => col.name === 'DATA_TYPE');
if (columns && fieldTypes) {
finalSuggestions.push(
...columns.values.map((col: string, index: number) => ({
...columns.values.map((col: string) => ({
text: col,
type: 'field',
fieldType: fieldTypes.values[index],
type: monaco.languages.CompletionItemKind.Field,
}))
);
}
}
});

if (
'suggestValuesForColumn' in suggestions &&
/\S/.test(suggestions.suggestValuesForColumn as string) &&
suggestions.suggestValuesForColumn !== undefined
) {
const values = await fetchColumnValues(
tableNames,
suggestions.suggestValuesForColumn as string,
api,
connectionService
);
values.forEach((value) => {
if (value.body?.fields?.length > 0) {
finalSuggestions.push(
...value.body.fields[0].values.map((colVal: string) => ({
text: `'${colVal}'`,
type: 'value',
}))
);
}
});
}
// later TODO: fetch column values, currently within the industry, it's not a common practice to suggest
// values due to different types of the columns as well as the performance impact. For now just avoid it.
}

// Fill in aggregate functions
if ('suggestAggregateFunctions' in suggestions && suggestions.suggestAggregateFunctions) {
finalSuggestions.push(
...SQL_SYMBOLS.AGREGATE_FUNCTIONS.map((af) => ({
text: af,
type: 'function',
type: monaco.languages.CompletionItemKind.Function,
}))
);
}
Expand All @@ -115,12 +94,13 @@ export const getSuggestions = async ({
finalSuggestions.push(
...(suggestions.suggestKeywords ?? []).map((sk) => ({
text: sk.value,
type: 'keyword',
type: monaco.languages.CompletionItemKind.Keyword,
}))
);
}
} catch (error) {
// TODO: pipe error to the UI
return [];
}

return finalSuggestions;
Expand Down
Loading
Loading