Skip to content

Commit 631a479

Browse files
author
jialan
committed
feat: support built-in sql snippets
1 parent c1b619c commit 631a479

16 files changed

Lines changed: 1071 additions & 14 deletions

src/baseSQLWorker.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { BasicSQL } from 'dt-sql-parser/dist/parser/common/basicSQL';
22
import { worker } from './fillers/monaco-editor-core';
33
import { Suggestions, ParseError, EntityContext } from 'dt-sql-parser';
44
import { Position } from './fillers/monaco-editor-core';
5+
import { SemanticContext } from 'dt-sql-parser/dist/parser/common/types';
56

67
export interface ICreateData {
78
languageId: string;
@@ -45,17 +46,32 @@ export abstract class BaseSQLWorker {
4546
async doCompletionWithEntities(
4647
code: string,
4748
position: Position
48-
): Promise<[Suggestions | null, EntityContext[] | null]> {
49+
): Promise<{
50+
suggestions: Suggestions | null;
51+
allEntities: EntityContext[] | null;
52+
context: SemanticContext | null;
53+
}> {
4954
code = code || this.getTextDocument();
5055
if (code) {
5156
const suggestions = this.parser.getSuggestionAtCaretPosition(code, position);
5257
let allEntities = null;
5358
if (suggestions?.syntax?.length) {
5459
allEntities = this.parser.getAllEntities(code, position);
5560
}
56-
return Promise.resolve([suggestions, allEntities]);
61+
const semanticContext = this.parser.getSemanticContextAtCaretPosition(code, position);
62+
63+
return Promise.resolve({
64+
suggestions,
65+
allEntities,
66+
context: semanticContext
67+
});
5768
}
58-
return Promise.resolve([null, null]);
69+
70+
return Promise.resolve({
71+
suggestions: null,
72+
allEntities: null,
73+
context: null
74+
});
5975
}
6076

6177
async getAllEntities(code: string, position?: Position): Promise<EntityContext[] | null> {

src/languageFeatures.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
import { debounce } from './common/utils';
1212
import { BaseSQLWorker } from './baseSQLWorker';
1313
import type { ParseError } from 'dt-sql-parser';
14-
import type { LanguageServiceDefaults } from './monaco.contribution';
14+
import type { CompletionSnippet, LanguageServiceDefaults } from './monaco.contribution';
1515

1616
export interface WorkerAccessor<T extends BaseSQLWorker> {
1717
(...uris: Uri[]): Promise<T>;
@@ -159,13 +159,22 @@ export class CompletionAdapter<T extends BaseSQLWorker>
159159
}
160160
return worker.doCompletionWithEntities(code, position);
161161
})
162-
.then(([suggestions, allEntities]) => {
162+
.then(({ suggestions, allEntities, context: semanticContext }) => {
163+
let snippets: CompletionSnippet[] = [];
164+
if (semanticContext?.isStatementBeginning) {
165+
snippets = this._defaults.completionSnippets.map((item) => ({
166+
...item,
167+
insertText: typeof item.body === 'string' ? item.body : item.body.join('\n')
168+
}));
169+
}
170+
163171
return this._defaults.completionService(
164172
model,
165173
position,
166174
context,
167175
suggestions,
168-
allEntities
176+
allEntities,
177+
snippets
169178
);
170179
})
171180
.then((completions) => {
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import type { CompletionSnippetOption } from 'src/monaco.contribution';
2+
3+
export const flinkSnippets: CompletionSnippetOption[] = [
4+
{
5+
label: 'create-source-table',
6+
prefix: 'CREATE-SOURCE-TABLE',
7+
body: [
8+
'CREATE TABLE ${1:source_table} (',
9+
'\tid STRING,',
10+
'\tval BIGINT,',
11+
'\tts TIMESTAMP(3),',
12+
"\tWATERMARK FOR ts AS ts - INTERVAL '5' SECOND",
13+
') WITH (',
14+
"\t'connector' = 'kafka',",
15+
"\t'topic' = 'input_topic',",
16+
"\t'properties.bootstrap.servers' = 'localhost:9092',",
17+
"\t'format' = 'json',",
18+
"\t'scan.startup.mode' = 'earliest-offset'",
19+
');'
20+
]
21+
},
22+
{
23+
label: 'create-sink-table',
24+
prefix: 'CREATE-SINK-TABLE',
25+
body: [
26+
'CREATE TABLE ${1:sink_table} (',
27+
'\tid STRING,',
28+
'\tcnt BIGINT',
29+
') WITH (',
30+
"\t'connector' = 'jdbc',",
31+
"\t'url' = 'jdbc:mysql://localhost:3306/test',",
32+
"\t'table-name' = 'output_table',",
33+
"\t'username' = 'root',",
34+
"\t'password' = 'password'",
35+
');'
36+
]
37+
},
38+
{
39+
label: 'tumble-window',
40+
prefix: 'TUMBLE-WINDOW',
41+
body: [
42+
'SELECT',
43+
'\twindow_start,',
44+
'\twindow_end,',
45+
'\tSUM(price) as total_price',
46+
'FROM',
47+
'\tTABLE(TUMBLE(TABLE table_name2,',
48+
'\tDESCRIPTOR(create_time),',
49+
"\tINTERVAL '1' MINUTE))",
50+
'GROUP BY',
51+
'\twindow_start,',
52+
'\twindow_end;'
53+
]
54+
},
55+
{
56+
label: 'hop-window',
57+
prefix: 'HOP-WINDOW',
58+
body: [
59+
'SELECT',
60+
'\twindow_start,',
61+
'\twindow_end,',
62+
'\tSUM(price) as total_price',
63+
'FROM',
64+
'\tTABLE(HOP(TABLE table_name2,',
65+
'\tDESCRIPTOR(create_time),',
66+
"\tINTERVAL '30' SECONDS,",
67+
"\tINTERVAL '1' MINUTE))",
68+
'GROUP BY',
69+
'\twindow_start,',
70+
'\twindow_end;'
71+
]
72+
},
73+
{
74+
label: 'comulate-window',
75+
prefix: 'CUMULATE-WINDOW',
76+
body: [
77+
'SELECT',
78+
'\twindow_start,',
79+
'\twindow_end,',
80+
'\tSUM(price) as total_price',
81+
'FROM',
82+
'\tTABLE(CUMULATE(TABLE table_name2,',
83+
'\tDESCRIPTOR(create_time),',
84+
"\tINTERVAL '30' SECONDS,",
85+
"\tINTERVAL '1' MINUTE))",
86+
'GROUP BY',
87+
'\twindow_start,',
88+
'\twindow_end;'
89+
]
90+
},
91+
{
92+
label: 'session-window',
93+
prefix: 'SESSION-WINDOW',
94+
body: [
95+
'SELECT',
96+
"\tSESSION_START(create_time, INTERVAL '10' SECOND) AS session_beg,",
97+
"\tSESSION_ROWTIME(create_time, INTERVAL '10' SECOND) AS session_end,",
98+
'\tSUM(price) AS total_price',
99+
'FROM',
100+
'\ttable_name',
101+
'GROUP BY',
102+
"\tSESSION(create_time, INTERVAL '10' SECOND);"
103+
]
104+
},
105+
{
106+
label: 'insert-into-select',
107+
prefix: 'INSERT-INTO-SELECT',
108+
body: [
109+
'INSERT INTO ${1:table_name}',
110+
'SELECT ${2:column1}, ${3:column2}',
111+
'FROM ${4:source_table}',
112+
'WHERE ${5:conditions};\n$6'
113+
]
114+
}
115+
];

src/languages/hive/hive.snippet.ts

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import type { CompletionSnippetOption } from 'src/monaco.contribution';
2+
3+
export const hiveSnippets: CompletionSnippetOption[] = [
4+
{
5+
label: 'select',
6+
prefix: 'SELECT',
7+
body: ['SELECT ${2:column1}, ${3:column2} FROM ${1:table_name};\n$4']
8+
},
9+
{
10+
label: 'select-join',
11+
prefix: 'SELECT-JOIN',
12+
body: [
13+
'SELECT ${8:column1} FROM ${1:table_name} ${2:t1}',
14+
'${3:LEFT} JOIN ${4:table2} ${5:t2} ON ${2:t1}.${6:column1} = ${5:t2}.${7:column2};\n$9'
15+
]
16+
},
17+
{
18+
label: 'select-order-by',
19+
prefix: 'SELECT-ORDERBY',
20+
body: [
21+
'SELECT ${2:column1}, ${3:column2} FROM ${1:table_name} ORDER BY ${4:column1} ${5:desc};\n$6'
22+
]
23+
},
24+
{
25+
label: 'insert',
26+
prefix: 'INSERT-INTO',
27+
body: [
28+
'INSERT INTO ${1:table_name} (${2:column1}, ${3:column2}) VALUES (${4:value1}, ${5:value2});\n$6'
29+
]
30+
},
31+
{
32+
label: 'insert-into-select',
33+
prefix: 'INSERT-INTO-SELECT',
34+
body: [
35+
'INSERT INTO TABLE ${1:table_name}',
36+
'SELECT ${3:column1}, ${4:column2}',
37+
'FROM ${2:source_table}',
38+
'WHERE ${5:conditions};\n$6'
39+
]
40+
},
41+
{
42+
label: 'insert-overwrite-table',
43+
prefix: 'INSERT-OVERWRITE-TABLE',
44+
body: [
45+
'INSERT OVERWRITE TABLE ${1:table_name}',
46+
'SELECT ${3:column1}, ${4:column2}',
47+
'FROM ${2:source_table}',
48+
'WHERE ${5:conditions};\n$6'
49+
]
50+
},
51+
{
52+
label: 'update',
53+
prefix: 'UPDATE',
54+
body: [
55+
'UPDATE ${1:table_name}',
56+
'SET ${2:column1} = ${3:value1}',
57+
'WHERE ${4:column2} = ${5:value2};\n$6'
58+
]
59+
},
60+
{
61+
label: 'delete',
62+
prefix: 'DELETE',
63+
body: ['DELETE FROM ${1:table_name}', 'WHERE ${2:column1} = ${3:value1};\n$4']
64+
},
65+
{
66+
label: 'create-table',
67+
prefix: 'CREATE-TABLE',
68+
body: [
69+
'CREATE TABLE IF NOT EXISTS ${1:table_name} (',
70+
'\t${2:column1} ${3:STRING},',
71+
'\t${4:column2} ${5:STRING}',
72+
')',
73+
"COMMENT '${6:table_comment}'",
74+
'ROW FORMAT ${7:DELIMITED}',
75+
"FIELDS TERMINATED BY '${8:\\t}'",
76+
'STORED AS ${9:PARQUET};\n$10'
77+
]
78+
},
79+
{
80+
label: 'create-table-as-select',
81+
prefix: 'CREATE-TABLE-AS-SELECT',
82+
body: [
83+
'CREATE TABLE IF NOT EXISTS ${1:table_name}',
84+
'AS',
85+
'SELECT ${2:column1}, ${3:column2}',
86+
'FROM ${4:source_table}',
87+
'WHERE ${5:conditions};\n$6'
88+
]
89+
},
90+
{
91+
label: 'create-partition-table',
92+
prefix: 'CREATE-PARTITION-TABLE',
93+
body: [
94+
'CREATE TABLE IF NOT EXISTS ${1:table_name} (',
95+
'\t${2:column1} ${3:STRING},',
96+
'\t${4:column2} ${5:STRING}',
97+
')',
98+
"COMMENT '${6:table_comment}'",
99+
'PARTITIONED BY (${7:part_column_name} STRING)',
100+
'ROW FORMAT ${8:DELIMITED}',
101+
"FIELDS TERMINATED BY '${9:\\t}'",
102+
'STORED AS ${10:PARQUET};\n$11'
103+
]
104+
},
105+
{
106+
label: 'create-bucket-table',
107+
prefix: 'CREATE-BUCKET-TABLE',
108+
body: [
109+
'CREATE TABLE IF NOT EXISTS ${1:table_name} (',
110+
'\t${2:column1} ${3:STRING},',
111+
'\t${4:column2} ${5:STRING}',
112+
')',
113+
"COMMENT '${6:table_comment}'",
114+
'PARTITIONED BY (${7:part_column_name} STRING)',
115+
'CLUSTERED BY (${8:bucket_column_name}) INTO ${9:1} BUCKETS',
116+
'ROW FORMAT ${10:DELIMITED}',
117+
"FIELDS TERMINATED BY '${11:\\t}'",
118+
'STORED AS ${12:PARQUET};\n$13'
119+
]
120+
},
121+
{
122+
label: 'alter-table-partition',
123+
prefix: 'ALTER-TABLE-PARTITION',
124+
body: [
125+
"ALTER TABLE ${1:table_name} ${2:ADD} PARTITION (${3:part_column}='${4:part_value}');\n$5"
126+
]
127+
},
128+
{
129+
label: 'alter-table-properties',
130+
prefix: 'ALTER-TABLE-PROPERTIES',
131+
body: [
132+
"ALTER TABLE ${1:table_name} SET TBLPROPERTIES ('${2:property_name}'='${3:property_value}');\n$4"
133+
]
134+
},
135+
{
136+
label: 'alter-table-columns',
137+
prefix: 'ALTER-TABLE-COLUMNS',
138+
body: [
139+
'ALTER TABLE ${1:table_name} ADD COLUMNS (',
140+
"\t${2:column_name} ${3:STRING} COMMENT '${4:desc}'",
141+
');\n$5'
142+
]
143+
}
144+
];

0 commit comments

Comments
 (0)