Make code editor work
This commit is contained in:
@@ -8,7 +8,7 @@ import { getSchema, showDatabases, showTables } from './MSSqlMetaQuery';
|
||||
import { MSSqlQueryModel } from './MSSqlQueryModel';
|
||||
import { MSSqlResponseParser } from './response_parser';
|
||||
import { fetchColumns, fetchTables, getSqlCompletionProvider } from './sqlCompletionProvider';
|
||||
import { getIcon, getRAQBType, toRawSql } from './sqlUtil';
|
||||
import { getIcon, getRAQBType, SCHEMA_NAME, toRawSql } from './sqlUtil';
|
||||
|
||||
export class MssqlDatasource extends SqlDatasource {
|
||||
completionProvider: LanguageCompletionProvider | undefined = undefined;
|
||||
@@ -72,7 +72,7 @@ export class MssqlDatasource extends SqlDatasource {
|
||||
lookup: async (path?: string) => {
|
||||
if (!path) {
|
||||
const datasets = await this.fetchDatasets();
|
||||
return datasets.map((d) => ({ name: d, completion: `${d}.` }));
|
||||
return datasets.map((d) => ({ name: d, completion: `${d}.${SCHEMA_NAME}.` }));
|
||||
} else {
|
||||
const parts = path.split('.').filter((s: string) => s);
|
||||
if (parts.length > 2) {
|
||||
@@ -80,7 +80,7 @@ export class MssqlDatasource extends SqlDatasource {
|
||||
}
|
||||
if (parts.length === 1) {
|
||||
const tables = await this.fetchTables(parts[0]);
|
||||
return tables.map((t) => ({ name: t, completion: `${t}\`` }));
|
||||
return tables.map((t) => ({ name: t, completion: `${t}` }));
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
LanguageCompletionProvider,
|
||||
LinkedToken,
|
||||
StatementPlacementProvider,
|
||||
// StatementPosition,
|
||||
SuggestionKindProvider,
|
||||
TableDefinition,
|
||||
TokenType,
|
||||
@@ -15,10 +14,11 @@ import {
|
||||
import { AGGREGATE_FNS, OPERATORS } from 'app/features/plugins/sql/constants';
|
||||
import { DB, SQLQuery } from 'app/features/plugins/sql/types';
|
||||
|
||||
import { SCHEMA_NAME } from './sqlUtil';
|
||||
|
||||
interface CompletionProviderGetterArgs {
|
||||
getColumns: React.MutableRefObject<(t: SQLQuery) => Promise<ColumnDefinition[]>>;
|
||||
getTables: React.MutableRefObject<(d?: string) => Promise<TableDefinition[]>>;
|
||||
// getTableSchema: React.MutableRefObject<(p: string, d: string, t: string) => Promise<TableSchema | null>>;
|
||||
}
|
||||
|
||||
export const getSqlCompletionProvider: (args: CompletionProviderGetterArgs) => LanguageCompletionProvider =
|
||||
@@ -33,20 +33,19 @@ export const getSqlCompletionProvider: (args: CompletionProviderGetterArgs) => L
|
||||
let processedToken = token;
|
||||
let tablePath = processedToken.value;
|
||||
|
||||
while (processedToken.next) {
|
||||
while (processedToken.next && processedToken.next.type !== TokenType.Whitespace) {
|
||||
tablePath += processedToken.next.value;
|
||||
processedToken = processedToken.next;
|
||||
}
|
||||
|
||||
return tablePath;
|
||||
const tableName = tablePath.split('.').pop();
|
||||
|
||||
return tableName || tablePath;
|
||||
},
|
||||
},
|
||||
|
||||
columns: {
|
||||
resolve: async (t: string) => {
|
||||
// TODO - seems like a limitation in experimental since we may need database and table to get columns
|
||||
// use . as delimiter?
|
||||
// const cols = await getColumns({ table: t } as SQLQuery);
|
||||
return await getColumns.current({ table: t, refId: 'A' });
|
||||
},
|
||||
},
|
||||
@@ -57,58 +56,36 @@ export const getSqlCompletionProvider: (args: CompletionProviderGetterArgs) => L
|
||||
});
|
||||
|
||||
export enum CustomStatementPlacement {
|
||||
AfterDataset = 'afterDataset',
|
||||
AfterDatabase = 'afterDatabase',
|
||||
}
|
||||
|
||||
export enum CustomSuggestionKind {
|
||||
TablesWithinDataset = 'tablesWithinDataset',
|
||||
Partition = 'partition',
|
||||
TablesWithinDatabase = 'tablesWithinDatabase',
|
||||
}
|
||||
|
||||
export const customStatementPlacement: StatementPlacementProvider = () => [
|
||||
{
|
||||
id: CustomStatementPlacement.AfterDataset,
|
||||
id: CustomStatementPlacement.AfterDatabase,
|
||||
resolve: (currentToken, previousKeyword) => {
|
||||
return Boolean(
|
||||
currentToken?.is(TokenType.Delimiter, '.') ||
|
||||
(currentToken?.is(TokenType.Whitespace) && currentToken?.previous?.is(TokenType.Delimiter, '.')) ||
|
||||
// (currentToken?.value === '`' && currentToken?.previous?.is(TokenType.Delimiter, '.')) ||
|
||||
(currentToken?.isNumber() && currentToken.value.endsWith('.')) // number with dot at the end like "projectname-21342."
|
||||
// (currentToken?.value === '`' && isTypingTableIn(currentToken))
|
||||
(currentToken?.isNumber() && currentToken.value.endsWith('.'))
|
||||
);
|
||||
},
|
||||
},
|
||||
// TODO - remove - frin big query
|
||||
// Overriding default behaviour of AfterFrom resolver
|
||||
// {
|
||||
// id: StatementPosition.AfterFrom,
|
||||
// overrideDefault: true,
|
||||
// resolve: (currentToken) => {
|
||||
// const untilFrom = currentToken?.getPreviousUntil(TokenType.Keyword, [], 'from');
|
||||
// if (!untilFrom) {
|
||||
// return false;
|
||||
// }
|
||||
// let q = '';
|
||||
// for (let i = untilFrom?.length - 1; i >= 0; i--) {
|
||||
// q += untilFrom[i].value;
|
||||
// }
|
||||
|
||||
// return q.startsWith('`') && q.endsWith('`');
|
||||
// },
|
||||
// },
|
||||
];
|
||||
|
||||
export const customSuggestionKinds: (
|
||||
getTables: CompletionProviderGetterArgs['getTables'],
|
||||
getFields: CompletionProviderGetterArgs['getColumns']
|
||||
// getTableSchema: CompletionProviderGetterArgs['getTableSchema']
|
||||
) => SuggestionKindProvider = (getTables) => () =>
|
||||
[
|
||||
{
|
||||
id: CustomSuggestionKind.TablesWithinDataset,
|
||||
applyTo: [CustomStatementPlacement.AfterDataset],
|
||||
id: CustomSuggestionKind.TablesWithinDatabase,
|
||||
applyTo: [CustomStatementPlacement.AfterDatabase],
|
||||
suggestionsResolver: async (ctx) => {
|
||||
const tablePath = ctx.currentToken ? getTablePath(ctx.currentToken) : '';
|
||||
const tablePath = ctx.currentToken ? getDatabaseName(ctx.currentToken) : '';
|
||||
const t = await getTables.current(tablePath);
|
||||
|
||||
return t.map((table) => ({
|
||||
@@ -125,76 +102,25 @@ export const customSuggestionKinds: (
|
||||
}));
|
||||
},
|
||||
},
|
||||
// {
|
||||
// id: CustomSuggestionKind.TablesWithinDataset,
|
||||
// applyTo: [StatementPosition.AfterFrom],
|
||||
// suggestionsResolver: async (ctx) => {
|
||||
// console.log('after from');
|
||||
// const tablePath = ctx.currentToken ? getTablePath(ctx.currentToken) : '';
|
||||
// const t = await getTables.current(tablePath);
|
||||
|
||||
// return t.map((table) => ({
|
||||
// label: table.name,
|
||||
// insertText: table.completion ?? table.name,
|
||||
// command: { id: 'editor.action.triggerSuggest', title: '' },
|
||||
// kind: CompletionItemKind.Field,
|
||||
// sortText: CompletionItemPriority.High,
|
||||
// range: {
|
||||
// ...ctx.range,
|
||||
// startColumn: ctx.range.endColumn,
|
||||
// endColumn: ctx.range.endColumn,
|
||||
// },
|
||||
// }));
|
||||
// }
|
||||
// }
|
||||
];
|
||||
|
||||
export function getTablePath(token: LinkedToken) {
|
||||
export function getDatabaseName(token: LinkedToken) {
|
||||
let processedToken = token;
|
||||
let tablePath = '';
|
||||
let database = '';
|
||||
while (processedToken?.previous && !processedToken.previous.isWhiteSpace()) {
|
||||
processedToken = processedToken.previous;
|
||||
tablePath = processedToken.value + tablePath;
|
||||
database = processedToken.value + database;
|
||||
}
|
||||
|
||||
tablePath = tablePath.trim();
|
||||
if (database.includes(SCHEMA_NAME)) {
|
||||
database = database.replace(SCHEMA_NAME, '');
|
||||
}
|
||||
|
||||
// TODO - remove - frin big query
|
||||
database = database.trim();
|
||||
|
||||
// if (tablePath.startsWith('`')) {
|
||||
// tablePath = tablePath.slice(1);
|
||||
// }
|
||||
|
||||
// if (tablePath.endsWith('`')) {
|
||||
// tablePath = tablePath.slice(0, -1);
|
||||
// }
|
||||
|
||||
return tablePath;
|
||||
return database;
|
||||
}
|
||||
|
||||
// TODO - not sure if we need this
|
||||
// function isTypingTableIn(token: LinkedToken | null, l?: boolean) {
|
||||
// if (!token) {
|
||||
// return false;
|
||||
// }
|
||||
// const tokens = token.getPreviousUntil(TokenType.Keyword, [], 'from');
|
||||
// if (!tokens) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// let path = '';
|
||||
// for (let i = tokens.length - 1; i >= 0; i--) {
|
||||
// path += tokens[i].value;
|
||||
// }
|
||||
|
||||
// // TODO - remove - frin big query
|
||||
// // if (path.startsWith('`')) {
|
||||
// // path = path.slice(1);
|
||||
// // }
|
||||
|
||||
// return path.split('.').length === 2;
|
||||
// }
|
||||
|
||||
export async function fetchColumns(db: DB, q: SQLQuery) {
|
||||
const cols = await db.fields(q);
|
||||
if (cols.length > 0) {
|
||||
|
||||
@@ -79,6 +79,8 @@ export function getRAQBType(type: string): RAQBFieldTypes {
|
||||
}
|
||||
}
|
||||
|
||||
export const SCHEMA_NAME = 'dbo';
|
||||
|
||||
export function toRawSql({ sql, dataset, table }: SQLQuery): string {
|
||||
let rawQuery = '';
|
||||
|
||||
@@ -90,7 +92,7 @@ export function toRawSql({ sql, dataset, table }: SQLQuery): string {
|
||||
rawQuery += createSelectClause(sql.columns, sql.limit);
|
||||
|
||||
if (dataset && table) {
|
||||
rawQuery += `FROM ${dataset}.dbo.${table} `;
|
||||
rawQuery += `FROM ${dataset}.${SCHEMA_NAME}.${table} `;
|
||||
}
|
||||
|
||||
if (sql.whereString) {
|
||||
|
||||
Reference in New Issue
Block a user