Skip to content

Commit 051c655

Browse files
authored
Query for functions (#18214)
1 parent 8a16132 commit 051c655

File tree

14 files changed

+974
-809
lines changed

14 files changed

+974
-809
lines changed

web-console/script/create-sql-docs.mjs

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,17 @@ const MINIMUM_EXPECTED_NUMBER_OF_FUNCTIONS = 198;
2727
const MINIMUM_EXPECTED_NUMBER_OF_DATA_TYPES = 15;
2828

2929
const initialFunctionDocs = {
30-
TABLE: [['external', convertMarkdownToHtml('Defines a logical table from an external.')]],
31-
EXTERN: [
32-
['inputSource, inputFormat, rowSignature?', convertMarkdownToHtml('Reads external data.')],
33-
],
30+
TABLE: ['external', convertMarkdownToHtml('Defines a logical table from an external.')],
31+
EXTERN: ['inputSource, inputFormat, rowSignature?', convertMarkdownToHtml('Reads external data.')],
3432
TYPE: [
35-
[
36-
'nativeType',
37-
convertMarkdownToHtml(
38-
'A purely type system modification function what wraps a Druid native type to make it into a SQL type.',
39-
),
40-
],
33+
'nativeType',
34+
convertMarkdownToHtml(
35+
'A purely type system modification function what wraps a Druid native type to make it into a SQL type.',
36+
),
4137
],
4238
UNNEST: [
43-
[
44-
'arrayExpression',
45-
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`.")
46-
]
39+
'arrayExpression',
40+
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`.")
4741
]
4842
};
4943

@@ -97,10 +91,8 @@ const readDoc = async () => {
9791
if (functionMatch) {
9892
const functionName = functionMatch[1];
9993
const args = sanitizeArguments(functionMatch[2]);
100-
const description = convertMarkdownToHtml(functionMatch[3]);
101-
102-
functionDocs[functionName] = functionDocs[functionName] || [];
103-
functionDocs[functionName].push([args, description]);
94+
const description = convertMarkdownToHtml(functionMatch[3].trim());
95+
functionDocs[functionName] = [args, description];
10496
}
10597

10698
const dataTypeMatch = line.match(/^\|([A-Z]+)\|([A-Z]+)\|([^|]*)\|([^|]*)\|$/);
@@ -146,18 +138,18 @@ const readDoc = async () => {
146138
// This file is auto generated and should not be modified
147139
148140
// prettier-ignore
149-
export const SQL_DATA_TYPES: Record<string, [runtime: string, description: string]> = ${JSON.stringify(
150-
dataTypeDocs,
151-
null,
152-
2,
153-
)};
141+
export const SQL_DATA_TYPES = new Map<string, [runtime: string, description: string]>(Object.entries(${JSON.stringify(
142+
dataTypeDocs,
143+
null,
144+
2,
145+
)}));
154146
155147
// prettier-ignore
156-
export const SQL_FUNCTIONS: Record<string, [args: string, description: string][]> = ${JSON.stringify(
157-
functionDocs,
158-
null,
159-
2,
160-
)};
148+
export const SQL_FUNCTIONS = new Map<string, [args: string, description: string]>(Object.entries(${JSON.stringify(
149+
functionDocs,
150+
null,
151+
2,
152+
)}));
161153
`;
162154

163155
// eslint-disable-next-line no-undef

web-console/src/ace-completions/make-doc-html.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ import { assemble } from '../utils';
2323
export interface ItemDescription {
2424
name: string;
2525
syntax?: string;
26-
description: string;
26+
description?: string;
2727
}
2828

2929
export function makeDocHtml(item: ItemDescription) {
3030
return assemble(
3131
`<div class="doc-name">${item.name}</div>`,
3232
item.syntax ? `<div class="doc-syntax">${escape(item.syntax)}</div>` : undefined,
33-
`<div class="doc-description">${item.description}</div>`,
33+
item.description ? `<div class="doc-description">${item.description}</div>` : undefined,
3434
).join('\n');
3535
}

web-console/src/ace-completions/sql-completions.ts

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { C, filterMap, N, T } from 'druid-query-toolkit';
2222
import { SQL_CONSTANTS, SQL_DYNAMICS, SQL_KEYWORDS } from '../../lib/keywords';
2323
import { SQL_DATA_TYPES, SQL_FUNCTIONS } from '../../lib/sql-docs';
2424
import { DEFAULT_SERVER_QUERY_CONTEXT } from '../druid-models';
25+
import type { AvailableFunctions } from '../helpers';
2526
import type { ColumnMetadata } from '../utils';
2627
import { lookupBy, uniq } from '../utils';
2728

@@ -158,8 +159,8 @@ const KNOWN_SQL_PARTS: Record<string, boolean> = {
158159
),
159160
...lookupBy(SQL_CONSTANTS, String, () => true),
160161
...lookupBy(SQL_DYNAMICS, String, () => true),
161-
...lookupBy(Object.values(SQL_DATA_TYPES), String, () => true),
162-
...lookupBy(Object.values(SQL_FUNCTIONS), String, () => true),
162+
...lookupBy(Array.from(SQL_DATA_TYPES.keys()), String, () => true),
163+
...lookupBy(Array.from(SQL_FUNCTIONS.keys()), String, () => true),
163164
};
164165

165166
export interface GetSqlCompletionsOptions {
@@ -169,6 +170,8 @@ export interface GetSqlCompletionsOptions {
169170
prefix: string;
170171
columnMetadata?: readonly ColumnMetadata[];
171172
columns?: readonly string[];
173+
availableSqlFunctions?: AvailableFunctions;
174+
skipAggregates?: boolean;
172175
}
173176

174177
export function getSqlCompletions({
@@ -178,6 +181,8 @@ export function getSqlCompletions({
178181
prefix,
179182
columnMetadata,
180183
columns,
184+
availableSqlFunctions,
185+
skipAggregates,
181186
}: GetSqlCompletionsOptions): Ace.Completion[] {
182187
// We are in a single line comment
183188
if (lineBeforePrefix.startsWith('--') || lineBeforePrefix.includes(' --')) {
@@ -219,7 +224,7 @@ export function getSqlCompletions({
219224
meta: 'keyword',
220225
})),
221226
SQL_CONSTANTS.map(v => ({ name: v, value: v, score: 11, meta: 'constant' })),
222-
Object.entries(SQL_DATA_TYPES).map(([name, [runtime, description]]) => {
227+
Array.from(SQL_DATA_TYPES.entries()).map(([name, [runtime, description]]) => {
223228
return {
224229
name,
225230
value: name,
@@ -241,11 +246,38 @@ export function getSqlCompletions({
241246
) {
242247
completions = completions.concat(
243248
SQL_DYNAMICS.map(v => ({ name: v, value: v, score: 20, meta: 'dynamic' })),
244-
Object.entries(SQL_FUNCTIONS).flatMap(([name, versions]) => {
245-
return versions.map(([args, description]) => {
249+
);
250+
251+
// If availableSqlFunctions map is provided, use it; otherwise fall back to static SQL_FUNCTIONS
252+
if (availableSqlFunctions) {
253+
completions = completions.concat(
254+
Array.from(availableSqlFunctions.entries()).flatMap(([name, funcDef]) => {
255+
if (skipAggregates && funcDef.isAggregate) return [];
256+
const description = SQL_FUNCTIONS.get(name)?.[1];
257+
return funcDef.args.map(args => {
258+
return {
259+
name,
260+
value: funcDef.args.length > 1 ? `${name}(${args})` : name,
261+
score: 30,
262+
meta: funcDef.isAggregate ? 'aggregate' : 'function',
263+
docHTML: makeDocHtml({ name, description, syntax: `${name}(${args})` }),
264+
docText: description,
265+
completer: {
266+
insertMatch: (editor: any, data: any) => {
267+
editor.completer.insertMatch({ value: data.name });
268+
},
269+
},
270+
} as Ace.Completion;
271+
});
272+
}),
273+
);
274+
} else {
275+
completions = completions.concat(
276+
Array.from(SQL_FUNCTIONS.entries()).map(([name, argDesc]) => {
277+
const [args, description] = argDesc;
246278
return {
247279
name,
248-
value: versions.length > 1 ? `${name}(${args})` : name,
280+
value: name,
249281
score: 30,
250282
meta: 'function',
251283
docHTML: makeDocHtml({ name, description, syntax: `${name}(${args})` }),
@@ -256,9 +288,9 @@ export function getSqlCompletions({
256288
},
257289
},
258290
} as Ace.Completion;
259-
});
260-
}),
261-
);
291+
}),
292+
);
293+
}
262294
}
263295
}
264296

0 commit comments

Comments
 (0)