Skip to content

Commit cfe7f22

Browse files
authored
fix: Don't include columns when completing FROM statements. (#22)
1 parent 3111377 commit cfe7f22

File tree

2 files changed

+54
-10
lines changed

2 files changed

+54
-10
lines changed

packages/server/src/complete/complete.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -255,20 +255,13 @@ class Completer {
255255
this.addCandidatesForExpectedLiterals(expectedLiteralNodes)
256256
this.addCandidatesForFunctions()
257257

258-
const { addedSome: addedSomeScopedColumnCandidates } =
259-
this.addCandidatesForScopedColumns(fromNodes, schemaAndSubqueries)
260-
if (!addedSomeScopedColumnCandidates) {
261-
this.addCandidatesForUnscopedColumns(fromNodes, schemaAndSubqueries)
262-
}
263-
264-
this.addCandidatesForAliases(fromNodes)
265-
258+
// Detect FROM clause context BEFORE adding column suggestions
266259
const fromNodesContainingCursor = fromNodes.filter((tableNode) =>
267260
isPosInLocation(tableNode.location, this.pos)
268261
)
269262
const isCursorInsideFromClause = fromNodesContainingCursor.length > 0
270263

271-
// Check if cursor is right after FROM keyword (no table typed yet)
264+
// Check if cursor is right after FROM keyword or typing a table name
272265
const afterFromClause = parsedFromClause.after?.trim().toUpperCase() || ''
273266
const isCursorAfterFromKeyword =
274267
afterFromClause === 'FROM' ||
@@ -277,7 +270,21 @@ class Completer {
277270
afterFromClause
278271
)
279272

280-
if (isCursorInsideFromClause || isCursorAfterFromKeyword) {
273+
const isTypingTableName =
274+
isCursorInsideFromClause || isCursorAfterFromKeyword
275+
276+
if (!isTypingTableName) {
277+
const { addedSome: addedSomeScopedColumnCandidates } =
278+
this.addCandidatesForScopedColumns(fromNodes, schemaAndSubqueries)
279+
280+
if (!addedSomeScopedColumnCandidates) {
281+
this.addCandidatesForUnscopedColumns(fromNodes, schemaAndSubqueries)
282+
}
283+
}
284+
285+
this.addCandidatesForAliases(fromNodes)
286+
287+
if (isTypingTableName) {
281288
// add table candidates if the cursor is inside a FROM clause, JOIN clause,
282289
// or right after FROM/JOIN keyword waiting for a table name
283290
this.addCandidatesForTables(schemaAndSubqueries, true)

packages/server/test/complete/complete_table.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,41 @@ describe('TableName completion', () => {
112112
]
113113
expect(result.candidates).toEqual(expect.arrayContaining(expected))
114114
})
115+
116+
test('complete table name after FROM keyword with partial input', () => {
117+
const schema = {
118+
tables: [
119+
{
120+
catalog: null,
121+
database: null,
122+
tableName: 'notes',
123+
columns: [{ columnName: 'id', description: '' }],
124+
},
125+
{
126+
catalog: null,
127+
database: null,
128+
tableName: 'users',
129+
columns: [{ columnName: 'name', description: '' }],
130+
},
131+
],
132+
functions: [],
133+
}
134+
135+
const result = complete(
136+
'SELECT * FROM not',
137+
{ line: 0, column: 17 },
138+
schema
139+
)
140+
141+
// Should suggest table names
142+
const labels = result.candidates.map((c) => c.label)
143+
expect(labels).toContain('notes')
144+
145+
// Should NOT include any column suggestions (even if qualified)
146+
expect(labels).not.toEqual(expect.arrayContaining(['id', 'name']))
147+
148+
// All candidates should be tables (CompletionItemKind.Constant = 21)
149+
const TABLE_KIND = 21
150+
expect(result.candidates.every((c) => c.kind === TABLE_KIND)).toBe(true)
151+
})
115152
})

0 commit comments

Comments
 (0)