fix(completion): isolate aliases across SQL statements

This commit is contained in:
zipg authored and GitHub committed 2026-07-28 21:08:24 +08:00
1 parent 88721925f2
commit d24cd98776
6 files changed
+114 -104

No files matched your search

@@ -407,6 +407,13 @@ const cachedInsertValueHintColumnsByTable = new Map<string, string[]>();
const cachedForeignKeysByTable = new Map<string, SqlCompletionForeignKey[]>();
const loadedColumnsByTable = new Set<string>();
function sqlCompletionDialectOptions() {
return {
databaseType: props.databaseType,
dialect: props.syntaxDialect ?? props.dialect,
};
}
function usesOracleSessionCompletionColumns(schema?: string | null): boolean {
return shouldUseOracleSessionCompletionColumns({
databaseType: props.databaseType,
@@ -1780,12 +1787,7 @@ async function resolveSqlHoverTooltip(currentView: EditorViewType, pos: number)
const parts = splitQualifiedIdentifier(identifier);
const name = parts[parts.length - 1] ?? identifier;
const qualifier = parts.length > 1 ? parts[parts.length - 2] : undefined;
const semanticModel = SEMANTIC_SQL_COMPLETION_ENABLED
? buildSqlSemanticModel(sql, pos, {
databaseType: props.databaseType,
dialect: props.syntaxDialect ?? props.dialect,
})
: null;
const semanticModel = SEMANTIC_SQL_COMPLETION_ENABLED ? buildSqlSemanticModel(sql, pos, sqlCompletionDialectOptions()) : null;
const semanticTarget = semanticModel ? resolveSqlSemanticNavigationTarget(semanticModel, parts) : null;
const semanticQualifierIsRowSource = !!qualifier && !!semanticTarget && (semanticTarget.alias?.toLowerCase() === qualifier.toLowerCase() || semanticTarget.source.name.toLowerCase() === qualifier.toLowerCase());
const tableLookupName = semanticTarget && !semanticQualifierIsRowSource ? semanticTarget.name : name;
@@ -1814,7 +1816,7 @@ async function resolveSqlHoverTooltip(currentView: EditorViewType, pos: number)
};
}
const legacyContext = getSqlCompletionContext(sql, pos);
const legacyContext = getSqlCompletionContext(sql, pos, sqlCompletionDialectOptions());
const context = semanticModel ? sqlCompletionContextFromSemantic(semanticModel, legacyContext) : legacyContext;
const candidates = qualifier ? context.referencedTables.filter((rt) => rt.alias?.toLowerCase() === qualifier.toLowerCase() || rt.name.toLowerCase() === qualifier.toLowerCase()) : context.referencedTables;
@@ -2509,7 +2511,7 @@ async function provideSqlCompletions(context: CompletionContext) {
return provideMongoCompletions(currentState, position, explicit);
}
if (props.databaseType === "elasticsearch") {
if (!isSqlLikeCompletionStatement(fullDoc, position)) {
if (!isSqlLikeCompletionStatement(fullDoc, position, sqlCompletionDialectOptions())) {
return provideElasticsearchCompletions(currentState, position, explicit);
}
}
@@ -2522,15 +2524,10 @@ async function provideSqlCompletions(context: CompletionContext) {
try {
if (isSqlCompletionSuppressedContext(fullDoc, position)) return null;
if (!explicit && !shouldAutoOpenSqlCompletion(fullDoc, position)) return null;
if (!explicit && !shouldAutoOpenSqlCompletion(fullDoc, position, sqlCompletionDialectOptions())) return null;
const legacyCompletionContext = getSqlCompletionContext(fullDoc, position);
const semanticModel = SEMANTIC_SQL_COMPLETION_ENABLED
? buildSqlSemanticModel(fullDoc, position, {
databaseType: props.databaseType,
dialect: props.syntaxDialect ?? props.dialect,
})
: null;
const legacyCompletionContext = getSqlCompletionContext(fullDoc, position, sqlCompletionDialectOptions());
const semanticModel = SEMANTIC_SQL_COMPLETION_ENABLED ? buildSqlSemanticModel(fullDoc, position, sqlCompletionDialectOptions()) : null;
const completionContext = semanticModel ? sqlCompletionContextFromSemantic(semanticModel, legacyCompletionContext) : legacyCompletionContext;
if (!hasDatabase) {
@@ -2640,7 +2637,7 @@ function flushImeComposition() {
emit("cursorChange", currentView.state.selection.main.head);
latestSelection = readEditorSelection(currentView);
if (editorIsActive) emitEditorSelection(latestSelection);
if (shouldAutoOpenSqlCompletion(currentView.state.doc.toString(), currentView.state.selection.main.head)) {
if (shouldAutoOpenSqlCompletion(currentView.state.doc.toString(), currentView.state.selection.main.head, sqlCompletionDialectOptions())) {
scheduleSqlCompletionStart(currentView);
}
}
@@ -2649,20 +2646,20 @@ function shouldStartSqlCompletionAfterInput(insertedText: string, removedText: s
const position = currentView.state.selection.main.head;
const fullDoc = currentView.state.doc.toString();
if (!insertedText && removedText) {
const completionContext = getSqlCompletionContext(fullDoc, position);
return isTableNameCompletionContext(completionContext) && shouldAutoOpenSqlCompletion(fullDoc, position);
const completionContext = getSqlCompletionContext(fullDoc, position, sqlCompletionDialectOptions());
return isTableNameCompletionContext(completionContext) && shouldAutoOpenSqlCompletion(fullDoc, position, sqlCompletionDialectOptions());
}
if (insertedText.endsWith(".")) return true;
if (/[,(]$/.test(insertedText)) {
const completionContext = getSqlCompletionContext(fullDoc, position);
const completionContext = getSqlCompletionContext(fullDoc, position, sqlCompletionDialectOptions());
return !!completionContext.insertTable;
}
if (/\s$/.test(insertedText)) {
return shouldAutoOpenSqlCompletion(fullDoc, position);
return shouldAutoOpenSqlCompletion(fullDoc, position, sqlCompletionDialectOptions());
}
if (!/[\w$@]$/.test(insertedText)) return false;
const completionContext = getSqlCompletionContext(fullDoc, position);
return isTableNameCompletionContext(completionContext) || shouldAutoOpenSqlCompletion(fullDoc, position);
const completionContext = getSqlCompletionContext(fullDoc, position, sqlCompletionDialectOptions());
return isTableNameCompletionContext(completionContext) || shouldAutoOpenSqlCompletion(fullDoc, position, sqlCompletionDialectOptions());
}
function buildLocalSqlCompletionResult(completionContext: ReturnType<typeof getSqlCompletionContext>, fullDoc: string, position: number) {