Skip to content

Commit e75cd35

Browse files
authored
Deal with double quotes (#116)
* deal with double quotes on parsing * split test cases * fix parser
1 parent 5b1237b commit e75cd35

File tree

7 files changed

+1814
-1506
lines changed

7 files changed

+1814
-1506
lines changed

packages/server/test/complete.test.ts

Lines changed: 0 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -191,121 +191,6 @@ describe('on blank space', () => {
191191
})
192192
})
193193

194-
describe('TableName completion', () => {
195-
test("complete function keyword", () => {
196-
const result = complete('SELECT arr', { line: 0, column: 10 }, SIMPLE_SCHEMA)
197-
expect(result.candidates.length).toEqual(2)
198-
expect(result.candidates[0].label).toEqual('array_concat()')
199-
expect(result.candidates[1].label).toEqual('array_contains()')
200-
})
201-
202-
test("complete function keyword", () => {
203-
const result = complete('SELECT ARR', { line: 0, column: 10 }, SIMPLE_SCHEMA)
204-
expect(result.candidates.length).toEqual(2)
205-
expect(result.candidates[0].label).toEqual('ARRAY_CONCAT()')
206-
expect(result.candidates[1].label).toEqual('ARRAY_CONTAINS()')
207-
})
208-
209-
test("complete TableName", () => {
210-
const result = complete('SELECT T FROM TABLE1', { line: 0, column: 8 }, SIMPLE_SCHEMA)
211-
expect(result.candidates.length).toEqual(1)
212-
expect(result.candidates[0].label).toEqual('TABLE1')
213-
})
214-
test("complete alias", () => {
215-
const result = complete('SELECT ta FROM TABLE1 as tab', { line: 0, column: 9 }, SIMPLE_SCHEMA)
216-
expect(result.candidates.length).toEqual(1)
217-
expect(result.candidates[0].label).toEqual('tab')
218-
})
219-
test("complete SELECT star", () => {
220-
const result = complete('SELECT FROM TABLE1', { line: 0, column: 6 }, SIMPLE_SCHEMA)
221-
expect(result.candidates.length).toEqual(2)
222-
expect(result.candidates[0].label).toEqual('Select all columns from TABLE1')
223-
expect(result.candidates[0].insertText).toEqual('SELECT\nTABLE1.COLUMN1,\nTABLE1.COLUMN2')
224-
expect(result.candidates[1].label).toEqual('SELECT')
225-
})
226-
// This is difficult because we can't parse the statement to get
227-
// at the column names
228-
test.skip("complete partial SELECT star", () => {
229-
const result = complete('SELEC FROM TABLE1', { line: 0, column: 5 }, SIMPLE_SCHEMA)
230-
expect(result.candidates.length).toEqual(2)
231-
expect(result.candidates[0].label).toEqual('SELECT')
232-
expect(result.candidates[1].label).toEqual('Select all columns from TABLE1')
233-
expect(result.candidates[1].insertText).toEqual('SELECT\nTABLE1.COLUMN1,\nTABLE1.COLUMN2')
234-
})
235-
test("complete SELECT star passed select ", () => {
236-
const result = complete('SELECT FROM TABLE1', { line: 0, column: 7 }, SIMPLE_SCHEMA)
237-
expect(result.candidates.length).toEqual(13)
238-
const expected = [
239-
expect.objectContaining({ label: 'Select all columns from TABLE1', insertText: 'TABLE1.COLUMN1,\nTABLE1.COLUMN2' }),
240-
]
241-
expect(result.candidates).toEqual(expect.arrayContaining(expected))
242-
})
243-
})
244-
245-
describe('ColumnName completion', () => {
246-
test("complete column name", () => {
247-
const result = complete('SELECT COL FROM TABLE1', { line: 0, column: 10 }, SIMPLE_SCHEMA)
248-
expect(result.candidates.length).toEqual(0)
249-
})
250-
251-
test("complete ColumnName", () => {
252-
const result = complete('SELECT TABLE1.C FROM TABLE1', { line: 0, column: 15 }, SIMPLE_SCHEMA)
253-
expect(result.candidates.length).toEqual(2)
254-
const expected = [
255-
expect.objectContaining({ label: 'COLUMN1' }),
256-
expect.objectContaining({ label: 'COLUMN2' }),
257-
]
258-
expect(result.candidates).toEqual(expect.arrayContaining(expected))
259-
})
260-
261-
test("complete ColumnName with previous back tick column", () => {
262-
const result = complete('SELECT `COLUMN2`, TABLE1.C FROM TABLE1', { line: 0, column: 26 }, SIMPLE_SCHEMA)
263-
expect(result.candidates.length).toEqual(2)
264-
expect(result.candidates[0].label).toEqual('COLUMN1')
265-
expect(result.candidates[1].label).toEqual('COLUMN2')
266-
})
267-
268-
test("complete ColumnName: cursor on dot", () => {
269-
const result = complete('SELECT TABLE1. FROM TABLE1', { line: 0, column: 14 }, SIMPLE_SCHEMA)
270-
expect(result.candidates.length).toEqual(2)
271-
expect(result.candidates[0].label).toEqual('COLUMN1')
272-
expect(result.candidates[1].label).toEqual('COLUMN2')
273-
})
274-
275-
test("complete ColumnName:cursor on dot:multi line", () => {
276-
const result = complete('SELECT *\nFROM TABLE1\nWHERE TABLE1.', { line: 2, column: 13 }, SIMPLE_SCHEMA)
277-
expect(result.candidates.length).toEqual(2)
278-
expect(result.candidates[0].label).toEqual('COLUMN1')
279-
expect(result.candidates[1].label).toEqual('COLUMN2')
280-
})
281-
282-
test("complete ColumnName:cursor on dot:using alias", () => {
283-
const result = complete('SELECT *\nFROM TABLE1 t\nWHERE t.', { line: 2, column: 8 }, SIMPLE_SCHEMA)
284-
expect(result.candidates.length).toEqual(2)
285-
expect(result.candidates[0].label).toEqual('COLUMN1')
286-
expect(result.candidates[1].label).toEqual('COLUMN2')
287-
})
288-
289-
test("complete ColumnName:cursor on dot:using alias", () => {
290-
const result = complete('SELECT t. FROM TABLE1 as t', { line: 0, column: 9 }, SIMPLE_SCHEMA)
291-
expect(result.candidates.length).toEqual(2)
292-
expect(result.candidates[0].label).toEqual('COLUMN1')
293-
expect(result.candidates[1].label).toEqual('COLUMN2')
294-
})
295-
296-
test("complete ColumnName:cursor on first char:using alias", () => {
297-
const result = complete('SELECT t.C FROM TABLE1 as t', { line: 0, column: 10 }, SIMPLE_SCHEMA)
298-
expect(result.candidates.length).toEqual(2)
299-
expect(result.candidates[0].label).toEqual('COLUMN1')
300-
expect(result.candidates[1].label).toEqual('COLUMN2')
301-
})
302-
303-
test("complete ColumnName:cursor on first char:using back tick", () => {
304-
const result = complete('SELECT `t`.C FROM TABLE1 as t', { line: 0, column: 12 }, SIMPLE_SCHEMA)
305-
expect(result.candidates.length).toEqual(0)
306-
})
307-
})
308-
309194
describe('From clause', () => {
310195
test("from clause: complete TableName:single line", () => {
311196
const result = complete('SELECT TABLE1.COLUMN1 FROM T', { line: 0, column: 28 }, SIMPLE_SCHEMA)
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { complete } from '../../src/complete'
2+
3+
const SIMPLE_SCHEMA = {
4+
tables: [
5+
{
6+
catalog: null,
7+
database: null,
8+
tableName: 'TABLE1',
9+
columns: [
10+
{ columnName: 'COLUMN1', description: '' },
11+
{ columnName: 'COLUMN2', description: '' }
12+
]
13+
}
14+
],
15+
functions: [
16+
{
17+
name: 'array_concat()',
18+
description: 'desc1'
19+
},
20+
{
21+
name: 'array_contains()',
22+
description: 'desc2'
23+
}
24+
]
25+
}
26+
27+
describe('ColumnName completion', () => {
28+
test("complete column name", () => {
29+
const result = complete('SELECT COL FROM TABLE1', { line: 0, column: 10 }, SIMPLE_SCHEMA)
30+
expect(result.candidates.length).toEqual(0)
31+
})
32+
33+
test("complete ColumnName", () => {
34+
const result = complete('SELECT TABLE1.C FROM TABLE1', { line: 0, column: 15 }, SIMPLE_SCHEMA)
35+
expect(result.candidates.length).toEqual(2)
36+
const expected = [
37+
expect.objectContaining({ label: 'COLUMN1' }),
38+
expect.objectContaining({ label: 'COLUMN2' }),
39+
]
40+
expect(result.candidates).toEqual(expect.arrayContaining(expected))
41+
})
42+
43+
test("complete ColumnName with previous back tick column", () => {
44+
const result = complete('SELECT `COLUMN2`, TABLE1.C FROM TABLE1', { line: 0, column: 26 }, SIMPLE_SCHEMA)
45+
expect(result.candidates.length).toEqual(2)
46+
expect(result.candidates[0].label).toEqual('COLUMN1')
47+
expect(result.candidates[1].label).toEqual('COLUMN2')
48+
})
49+
50+
test("complete ColumnName: cursor on dot", () => {
51+
const result = complete('SELECT TABLE1. FROM TABLE1', { line: 0, column: 14 }, SIMPLE_SCHEMA)
52+
expect(result.candidates.length).toEqual(2)
53+
expect(result.candidates[0].label).toEqual('COLUMN1')
54+
expect(result.candidates[1].label).toEqual('COLUMN2')
55+
})
56+
57+
test("complete ColumnName:cursor on dot:multi line", () => {
58+
const result = complete('SELECT *\nFROM TABLE1\nWHERE TABLE1.', { line: 2, column: 13 }, SIMPLE_SCHEMA)
59+
expect(result.candidates.length).toEqual(2)
60+
expect(result.candidates[0].label).toEqual('COLUMN1')
61+
expect(result.candidates[1].label).toEqual('COLUMN2')
62+
})
63+
64+
test("complete ColumnName:cursor on dot:using alias", () => {
65+
const result = complete('SELECT *\nFROM TABLE1 t\nWHERE t.', { line: 2, column: 8 }, SIMPLE_SCHEMA)
66+
expect(result.candidates.length).toEqual(2)
67+
expect(result.candidates[0].label).toEqual('COLUMN1')
68+
expect(result.candidates[1].label).toEqual('COLUMN2')
69+
})
70+
71+
test("complete ColumnName:cursor on dot:using alias", () => {
72+
const result = complete('SELECT t. FROM TABLE1 as t', { line: 0, column: 9 }, SIMPLE_SCHEMA)
73+
expect(result.candidates.length).toEqual(2)
74+
expect(result.candidates[0].label).toEqual('COLUMN1')
75+
expect(result.candidates[1].label).toEqual('COLUMN2')
76+
})
77+
78+
test("complete ColumnName:cursor on first char:using alias", () => {
79+
const result = complete('SELECT t.C FROM TABLE1 as t', { line: 0, column: 10 }, SIMPLE_SCHEMA)
80+
expect(result.candidates.length).toEqual(2)
81+
expect(result.candidates[0].label).toEqual('COLUMN1')
82+
expect(result.candidates[1].label).toEqual('COLUMN2')
83+
})
84+
85+
test("complete ColumnName:cursor on first char:using back tick", () => {
86+
const result = complete('SELECT `t`.C FROM TABLE1 as t', { line: 0, column: 12 }, SIMPLE_SCHEMA)
87+
expect(result.candidates.length).toEqual(0)
88+
})
89+
90+
// TODO: Implement completion
91+
test.skip("complete ColumnName with back quoted table", () => {
92+
const result = complete('SELECT "TABLE1". FROM "TABLE1"', { line: 0, column: 16 }, SIMPLE_SCHEMA)
93+
expect(result.candidates.length).toEqual(2)
94+
expect(result.candidates[0].label).toEqual('COLUMN1')
95+
expect(result.candidates[1].label).toEqual('COLUMN2')
96+
})
97+
})
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { complete } from '../../src/complete'
2+
3+
const SIMPLE_SCHEMA = {
4+
tables: [
5+
{
6+
catalog: null,
7+
database: null,
8+
tableName: 'TABLE1',
9+
columns: [
10+
{ columnName: 'COLUMN1', description: '' },
11+
{ columnName: 'COLUMN2', description: '' }
12+
]
13+
}
14+
],
15+
functions: [
16+
{
17+
name: 'array_concat()',
18+
description: 'desc1'
19+
},
20+
{
21+
name: 'array_contains()',
22+
description: 'desc2'
23+
}
24+
]
25+
}
26+
27+
describe('TableName completion', () => {
28+
test("complete function keyword", () => {
29+
const result = complete('SELECT arr', { line: 0, column: 10 }, SIMPLE_SCHEMA)
30+
expect(result.candidates.length).toEqual(2)
31+
expect(result.candidates[0].label).toEqual('array_concat()')
32+
expect(result.candidates[1].label).toEqual('array_contains()')
33+
})
34+
35+
test("complete function keyword", () => {
36+
const result = complete('SELECT ARR', { line: 0, column: 10 }, SIMPLE_SCHEMA)
37+
expect(result.candidates.length).toEqual(2)
38+
expect(result.candidates[0].label).toEqual('ARRAY_CONCAT()')
39+
expect(result.candidates[1].label).toEqual('ARRAY_CONTAINS()')
40+
})
41+
42+
test("complete TableName", () => {
43+
const result = complete('SELECT T FROM TABLE1', { line: 0, column: 8 }, SIMPLE_SCHEMA)
44+
expect(result.candidates.length).toEqual(1)
45+
expect(result.candidates[0].label).toEqual('TABLE1')
46+
})
47+
48+
test("complete alias", () => {
49+
const result = complete('SELECT ta FROM TABLE1 as tab', { line: 0, column: 9 }, SIMPLE_SCHEMA)
50+
expect(result.candidates.length).toEqual(1)
51+
expect(result.candidates[0].label).toEqual('tab')
52+
})
53+
test("complete SELECT star", () => {
54+
const result = complete('SELECT FROM TABLE1', { line: 0, column: 6 }, SIMPLE_SCHEMA)
55+
expect(result.candidates.length).toEqual(2)
56+
expect(result.candidates[0].label).toEqual('Select all columns from TABLE1')
57+
expect(result.candidates[0].insertText).toEqual('SELECT\nTABLE1.COLUMN1,\nTABLE1.COLUMN2')
58+
expect(result.candidates[1].label).toEqual('SELECT')
59+
})
60+
61+
// This is difficult because we can't parse the statement to get
62+
// at the column names
63+
test.skip("complete partial SELECT star", () => {
64+
const result = complete('SELEC FROM TABLE1', { line: 0, column: 5 }, SIMPLE_SCHEMA)
65+
expect(result.candidates.length).toEqual(2)
66+
expect(result.candidates[0].label).toEqual('SELECT')
67+
expect(result.candidates[1].label).toEqual('Select all columns from TABLE1')
68+
expect(result.candidates[1].insertText).toEqual('SELECT\nTABLE1.COLUMN1,\nTABLE1.COLUMN2')
69+
})
70+
71+
test("complete SELECT star passed select ", () => {
72+
const result = complete('SELECT FROM TABLE1', { line: 0, column: 7 }, SIMPLE_SCHEMA)
73+
expect(result.candidates.length).toEqual(13)
74+
const expected = [
75+
expect.objectContaining({ label: 'Select all columns from TABLE1', insertText: 'TABLE1.COLUMN1,\nTABLE1.COLUMN2' }),
76+
]
77+
expect(result.candidates).toEqual(expect.arrayContaining(expected))
78+
})
79+
})

0 commit comments

Comments
 (0)