Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
48 changes: 20 additions & 28 deletions web-console/script/create-sql-docs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,17 @@ const MINIMUM_EXPECTED_NUMBER_OF_FUNCTIONS = 198;
const MINIMUM_EXPECTED_NUMBER_OF_DATA_TYPES = 15;

const initialFunctionDocs = {
TABLE: [['external', convertMarkdownToHtml('Defines a logical table from an external.')]],
EXTERN: [
['inputSource, inputFormat, rowSignature?', convertMarkdownToHtml('Reads external data.')],
],
TABLE: ['external', convertMarkdownToHtml('Defines a logical table from an external.')],
EXTERN: ['inputSource, inputFormat, rowSignature?', convertMarkdownToHtml('Reads external data.')],
TYPE: [
[
'nativeType',
convertMarkdownToHtml(
'A purely type system modification function what wraps a Druid native type to make it into a SQL type.',
),
],
'nativeType',
convertMarkdownToHtml(
'A purely type system modification function what wraps a Druid native type to make it into a SQL type.',
),
],
UNNEST: [
[
'arrayExpression',
convertMarkdownToHtml("Unnests ARRAY typed values. The source for UNNEST can be an array type column, or an input that's been transformed into an array, such as with helper functions like `MV_TO_ARRAY` or `ARRAY`.")
]
'arrayExpression',
convertMarkdownToHtml("Unnests ARRAY typed values. The source for UNNEST can be an array type column, or an input that's been transformed into an array, such as with helper functions like `MV_TO_ARRAY` or `ARRAY`.")
]
};

Expand Down Expand Up @@ -97,10 +91,8 @@ const readDoc = async () => {
if (functionMatch) {
const functionName = functionMatch[1];
const args = sanitizeArguments(functionMatch[2]);
const description = convertMarkdownToHtml(functionMatch[3]);

functionDocs[functionName] = functionDocs[functionName] || [];
functionDocs[functionName].push([args, description]);
const description = convertMarkdownToHtml(functionMatch[3].trim());
functionDocs[functionName] = [args, description];
}

const dataTypeMatch = line.match(/^\|([A-Z]+)\|([A-Z]+)\|([^|]*)\|([^|]*)\|$/);
Expand Down Expand Up @@ -146,18 +138,18 @@ const readDoc = async () => {
// This file is auto generated and should not be modified

// prettier-ignore
export const SQL_DATA_TYPES: Record<string, [runtime: string, description: string]> = ${JSON.stringify(
dataTypeDocs,
null,
2,
)};
export const SQL_DATA_TYPES = new Map<string, [runtime: string, description: string]>(Object.entries(${JSON.stringify(
dataTypeDocs,
null,
2,
)}));

// prettier-ignore
export const SQL_FUNCTIONS: Record<string, [args: string, description: string][]> = ${JSON.stringify(
functionDocs,
null,
2,
)};
export const SQL_FUNCTIONS = new Map<string, [args: string, description: string]>(Object.entries(${JSON.stringify(
functionDocs,
null,
2,
)}));
`;

// eslint-disable-next-line no-undef
Expand Down
4 changes: 2 additions & 2 deletions web-console/src/ace-completions/make-doc-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ import { assemble } from '../utils';
export interface ItemDescription {
name: string;
syntax?: string;
description: string;
description?: string;
}

export function makeDocHtml(item: ItemDescription) {
return assemble(
`<div class="doc-name">${item.name}</div>`,
item.syntax ? `<div class="doc-syntax">${escape(item.syntax)}</div>` : undefined,
`<div class="doc-description">${item.description}</div>`,
item.description ? `<div class="doc-description">${item.description}</div>` : undefined,
).join('\n');
}
50 changes: 41 additions & 9 deletions web-console/src/ace-completions/sql-completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { C, filterMap, N, T } from 'druid-query-toolkit';
import { SQL_CONSTANTS, SQL_DYNAMICS, SQL_KEYWORDS } from '../../lib/keywords';
import { SQL_DATA_TYPES, SQL_FUNCTIONS } from '../../lib/sql-docs';
import { DEFAULT_SERVER_QUERY_CONTEXT } from '../druid-models';
import type { AvailableFunctions } from '../helpers';
import type { ColumnMetadata } from '../utils';
import { lookupBy, uniq } from '../utils';

Expand Down Expand Up @@ -158,8 +159,8 @@ const KNOWN_SQL_PARTS: Record<string, boolean> = {
),
...lookupBy(SQL_CONSTANTS, String, () => true),
...lookupBy(SQL_DYNAMICS, String, () => true),
...lookupBy(Object.values(SQL_DATA_TYPES), String, () => true),
...lookupBy(Object.values(SQL_FUNCTIONS), String, () => true),
...lookupBy(Array.from(SQL_DATA_TYPES.keys()), String, () => true),
...lookupBy(Array.from(SQL_FUNCTIONS.keys()), String, () => true),
};

export interface GetSqlCompletionsOptions {
Expand All @@ -169,6 +170,8 @@ export interface GetSqlCompletionsOptions {
prefix: string;
columnMetadata?: readonly ColumnMetadata[];
columns?: readonly string[];
availableSqlFunctions?: AvailableFunctions;
skipAggregates?: boolean;
}

export function getSqlCompletions({
Expand All @@ -178,6 +181,8 @@ export function getSqlCompletions({
prefix,
columnMetadata,
columns,
availableSqlFunctions,
skipAggregates,
}: GetSqlCompletionsOptions): Ace.Completion[] {
// We are in a single line comment
if (lineBeforePrefix.startsWith('--') || lineBeforePrefix.includes(' --')) {
Expand Down Expand Up @@ -219,7 +224,7 @@ export function getSqlCompletions({
meta: 'keyword',
})),
SQL_CONSTANTS.map(v => ({ name: v, value: v, score: 11, meta: 'constant' })),
Object.entries(SQL_DATA_TYPES).map(([name, [runtime, description]]) => {
Array.from(SQL_DATA_TYPES.entries()).map(([name, [runtime, description]]) => {
return {
name,
value: name,
Expand All @@ -241,11 +246,38 @@ export function getSqlCompletions({
) {
completions = completions.concat(
SQL_DYNAMICS.map(v => ({ name: v, value: v, score: 20, meta: 'dynamic' })),
Object.entries(SQL_FUNCTIONS).flatMap(([name, versions]) => {
return versions.map(([args, description]) => {
);

// If availableSqlFunctions map is provided, use it; otherwise fall back to static SQL_FUNCTIONS
if (availableSqlFunctions) {
completions = completions.concat(
Array.from(availableSqlFunctions.entries()).flatMap(([name, funcDef]) => {
if (skipAggregates && funcDef.isAggregate) return [];
const description = SQL_FUNCTIONS.get(name)?.[1];
return funcDef.args.map(args => {
return {
name,
value: funcDef.args.length > 1 ? `${name}(${args})` : name,
score: 30,
meta: funcDef.isAggregate ? 'aggregate' : 'function',
docHTML: makeDocHtml({ name, description, syntax: `${name}(${args})` }),
docText: description,
completer: {
insertMatch: (editor: any, data: any) => {
editor.completer.insertMatch({ value: data.name });
},
},
} as Ace.Completion;
});
}),
);
} else {
completions = completions.concat(
Array.from(SQL_FUNCTIONS.entries()).map(([name, argDesc]) => {
const [args, description] = argDesc;
return {
name,
value: versions.length > 1 ? `${name}(${args})` : name,
value: name,
score: 30,
meta: 'function',
docHTML: makeDocHtml({ name, description, syntax: `${name}(${args})` }),
Expand All @@ -256,9 +288,9 @@ export function getSqlCompletions({
},
},
} as Ace.Completion;
});
}),
);
}),
);
}
}
}

Expand Down
Loading