1
1
import type {
2
2
ColumnAliasSuggestion ,
3
3
KeywordSuggestion ,
4
+ VariableSuggestion ,
4
5
} from '@gravity-ui/websql-autocomplete/shared' ;
5
6
import type { YQLEntity , YqlAutocompleteResult } from '@gravity-ui/websql-autocomplete/yql' ;
6
7
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api' ;
@@ -107,6 +108,10 @@ function removeBackticks(value: string) {
107
108
return value . slice ( sliceStart , sliceEnd ) ;
108
109
}
109
110
111
+ function isVariable ( value : string ) {
112
+ return value . startsWith ( '$' ) ;
113
+ }
114
+
110
115
function removeStartSlash ( value : string ) {
111
116
if ( value . startsWith ( '/' ) ) {
112
117
return value . slice ( 1 ) ;
@@ -199,7 +204,8 @@ function getColumnDetails(col: AutocompleteColumn) {
199
204
200
205
export async function generateColumnsSuggestion (
201
206
rangeToInsertSuggestion : monaco . IRange ,
202
- suggestColumns : YqlAutocompleteResult [ 'suggestColumns' ] | undefined ,
207
+ suggestColumns : YqlAutocompleteResult [ 'suggestColumns' ] ,
208
+ suggestVariables : YqlAutocompleteResult [ 'suggestVariables' ] ,
203
209
database : string ,
204
210
) : Promise < monaco . languages . CompletionItem [ ] > {
205
211
if ( ! suggestColumns ?. tables ) {
@@ -209,27 +215,67 @@ export async function generateColumnsSuggestion(
209
215
const normalizedColumns = suggestColumns . all ? ( [ ] as string [ ] ) : undefined ;
210
216
const multi = suggestColumns . tables . length > 1 ;
211
217
212
- const normalizedTableNames =
218
+ const normalizedSuggestions =
213
219
suggestColumns . tables ?. map ( ( entity ) => {
214
220
let normalizedEntityName = removeBackticks ( entity . name ) ;
215
- if ( ! normalizedEntityName . endsWith ( '/' ) ) {
221
+ if ( ! normalizedEntityName . endsWith ( '/' ) && ! isVariable ( normalizedEntityName ) ) {
216
222
normalizedEntityName = `${ normalizedEntityName } /` ;
217
223
}
218
- return normalizeEntityPrefix ( normalizedEntityName , database ) ;
224
+ return { ... entity , name : normalizeEntityPrefix ( normalizedEntityName , database ) } ;
219
225
} ) ?? [ ] ;
220
226
227
+ const normalizedTableNames = normalizedSuggestions . map ( ( entity ) => entity . name ) ;
228
+
221
229
// remove duplicates if any
222
230
const filteredTableNames = Array . from ( new Set ( normalizedTableNames ) ) ;
223
231
224
- const autocompleteResponse = await window . api . viewer . autocomplete ( {
225
- database,
226
- table : filteredTableNames ,
227
- limit : 1000 ,
228
- } ) ;
229
- if ( ! autocompleteResponse . Success ) {
230
- return [ ] ;
232
+ const tableSources = filteredTableNames . filter ( ( name ) => ! isVariable ( name ) ) ;
233
+
234
+ let autocompleteEntities : TAutocompleteEntity [ ] = [ ] ;
235
+ if ( tableSources . length ) {
236
+ const autocompleteResponse = await window . api . viewer . autocomplete ( {
237
+ database,
238
+ table : tableSources ,
239
+ limit : 1000 ,
240
+ } ) ;
241
+ if ( autocompleteResponse . Success ) {
242
+ autocompleteEntities = autocompleteResponse . Result . Entities ?? [ ] ;
243
+ }
244
+ }
245
+
246
+ const variableSources = filteredTableNames . filter ( isVariable ) ;
247
+ const columnsFromVariable : TAutocompleteEntity [ ] = [ ] ;
248
+ if ( variableSources . length ) {
249
+ variableSources . forEach ( ( source ) => {
250
+ const newColumns =
251
+ suggestVariables
252
+ // Variable name from suggestions doesn't include $ sign
253
+ ?. find ( ( variable ) => source . slice ( 1 ) === variable . name )
254
+ ?. value ?. columns ?. map ( ( col ) => ( {
255
+ Name : col ,
256
+ Type : 'column' as const ,
257
+ Parent : source ,
258
+ } ) ) ?? [ ] ;
259
+ columnsFromVariable . push ( ...newColumns ) ;
260
+ } ) ;
231
261
}
232
262
263
+ const predefinedColumns : TAutocompleteEntity [ ] = normalizedSuggestions . reduce <
264
+ TAutocompleteEntity [ ]
265
+ > ( ( acc , entity ) => {
266
+ const columns = entity . columns ;
267
+ if ( columns ) {
268
+ acc . push (
269
+ ...columns . map ( ( col ) => ( {
270
+ Name : col ,
271
+ Type : 'column' as const ,
272
+ Parent : entity . name ,
273
+ } ) ) ,
274
+ ) ;
275
+ }
276
+ return acc ;
277
+ } , [ ] ) ;
278
+
233
279
const tableNameToAliasMap = suggestColumns . tables ?. reduce (
234
280
( acc , entity ) => {
235
281
const normalizedEntityName = normalizeEntityPrefix (
@@ -246,7 +292,7 @@ export async function generateColumnsSuggestion(
246
292
{ } as Record < string , string [ ] > ,
247
293
) ;
248
294
249
- autocompleteResponse . Result . Entities ? .forEach ( ( col ) => {
295
+ [ ... autocompleteEntities , ... columnsFromVariable , ... predefinedColumns ] . forEach ( ( col ) => {
250
296
if ( ! isAutocompleteColumn ( col ) ) {
251
297
return ;
252
298
}
@@ -293,7 +339,7 @@ export async function generateColumnsSuggestion(
293
339
normalizedColumns ?. push ( columnNameSuggestion ) ;
294
340
}
295
341
} ) ;
296
- if ( normalizedColumns && normalizedColumns . length > 0 ) {
342
+ if ( normalizedColumns && normalizedColumns . length > 1 ) {
297
343
const allColumns = normalizedColumns . join ( ', ' ) ;
298
344
suggestions . push ( {
299
345
label : allColumns ,
@@ -341,13 +387,13 @@ export function generateKeywordsSuggestion(
341
387
342
388
export function generateVariableSuggestion (
343
389
rangeToInsertSuggestion : monaco . IRange ,
344
- suggestVariables ?: string [ ] ,
390
+ suggestVariables ?: VariableSuggestion [ ] ,
345
391
) {
346
392
if ( ! suggestVariables ) {
347
393
return [ ] ;
348
394
}
349
- return suggestVariables . map ( ( rawVariable ) => {
350
- const variable = '$' + rawVariable ;
395
+ return suggestVariables . map ( ( { name } ) => {
396
+ const variable = '$' + name ;
351
397
return {
352
398
label : variable ,
353
399
insertText : variable ,
0 commit comments