fix(editor): skip duplicate table aliases
This commit is contained in:
1 parent
0650428d1c
commit
02e1b943e8
2 files changed
+102
-2
No files matched your search
@@ -1158,6 +1158,7 @@ export interface SqlCompletionContext {
|
||||
deleteTarget?: { table: string; schema?: string };
|
||||
oracleTableFunctionContext?: boolean;
|
||||
autoAliasTableCompletions: boolean;
|
||||
tableAliasAfterCursor?: boolean;
|
||||
contextKind: SqlCompletionContextKind;
|
||||
}
|
||||
|
||||
@@ -1286,7 +1287,7 @@ class SqlCompletionProvider {
|
||||
}
|
||||
|
||||
const emptyTableNameCompletion = !context.prefix && (context.suggestTables || context.exclusiveTableSuggestions);
|
||||
if (!pendingJoinKeyword && !emptyTableNameCompletion && context.referencedTables.length > 0 && !context.suggestColumns && !context.insertTable) {
|
||||
if (!pendingJoinKeyword && !emptyTableNameCompletion && !context.tableAliasAfterCursor && context.referencedTables.length > 0 && !context.suggestColumns && !context.insertTable) {
|
||||
this.items.push(...buildAliasItems(context, this.databaseType));
|
||||
}
|
||||
|
||||
@@ -1617,6 +1618,50 @@ function isCallRoutineContext(beforeToken: string): boolean {
|
||||
return /\bcall\s+(?:[A-Za-z_][\w$]*\.)?$/i.test(beforeToken) || /\bcall\s+(?:[A-Za-z_][\w$]*\.)?[A-Za-z_][\w$]*$/i.test(beforeToken);
|
||||
}
|
||||
|
||||
const SQL_IDENTIFIER_CONTINUE_CHAR = /[$_\u200c\u200d\p{ID_Continue}]/u;
|
||||
|
||||
function hasTableAliasAfterCursor(sql: string, cursor: number): boolean {
|
||||
if (hasAliasMarkerAt(sql, cursor, false)) return true;
|
||||
let pos = cursor;
|
||||
while (pos < sql.length) {
|
||||
const codePoint = sql.codePointAt(pos);
|
||||
if (codePoint === undefined) break;
|
||||
const char = String.fromCodePoint(codePoint);
|
||||
if (char !== "." && !SQL_IDENTIFIER_CONTINUE_CHAR.test(char)) break;
|
||||
// Advance by the full code point so supplementary Unicode identifiers
|
||||
// do not leave the scan between UTF-16 surrogate halves.
|
||||
pos += char.length;
|
||||
}
|
||||
if (sql[pos] === '"' || sql[pos] === "`" || sql[pos] === "]") pos++;
|
||||
return hasAliasMarkerAt(sql, pos, true);
|
||||
}
|
||||
|
||||
function hasAliasMarkerAt(sql: string, pos: number, allowImplicitAlias: boolean): boolean {
|
||||
const following = sql.slice(skipSqlWhitespaceAndComments(sql, pos));
|
||||
if (/^as\b/i.test(following)) return true;
|
||||
if (/^(?:"[^"]+"|`[^`]+`|\[[^\]]+\])/.test(following)) return true;
|
||||
if (!allowImplicitAlias) return false;
|
||||
const implicitAlias = /^([A-Za-z_][\w$]*)/.exec(following)?.[1]?.toLowerCase();
|
||||
return !!implicitAlias && !isUnsafeSqlAlias(implicitAlias);
|
||||
}
|
||||
|
||||
function skipSqlWhitespaceAndComments(sql: string, pos: number): number {
|
||||
for (;;) {
|
||||
while (pos < sql.length && /\s/.test(sql[pos])) pos++;
|
||||
if (sql.startsWith("--", pos)) {
|
||||
const newline = sql.indexOf("\n", pos + 2);
|
||||
if (newline === -1) return sql.length;
|
||||
pos = newline + 1;
|
||||
} else if (sql.startsWith("/*", pos)) {
|
||||
const end = sql.indexOf("*/", pos + 2);
|
||||
if (end === -1) return sql.length;
|
||||
pos = end + 2;
|
||||
} else {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getSqlCompletionContext(sql: string, cursor: number): SqlCompletionContext {
|
||||
// Extract the full statement at cursor position for referenced tables
|
||||
const fullStatement = extractStatementAt(sql, cursor);
|
||||
@@ -1664,7 +1709,8 @@ export function getSqlCompletionContext(sql: string, cursor: number): SqlComplet
|
||||
|
||||
const afterTableTrigger = TABLE_TRIGGER_KEYWORDS.has(lastWord) || (JOIN_MODIFIERS.has(lastWord) && isFollowedByJoin(beforeToken)) || isInTableListContext(beforeToken);
|
||||
const exclusiveTableSuggestions = EXCLUSIVE_TABLE_TRIGGER_KEYWORDS.has(lastWord) || (JOIN_MODIFIERS.has(lastWord) && isFollowedByJoin(beforeToken)) || isInTableListContext(beforeToken);
|
||||
const autoAliasTableCompletions = lastWord === "from" || lastWord === "join" || (JOIN_MODIFIERS.has(lastWord) && isFollowedByJoin(beforeToken)) || isInTableListContext(beforeToken);
|
||||
const tableAliasAfterCursor = hasTableAliasAfterCursor(sql, cursor);
|
||||
const autoAliasTableCompletions = (lastWord === "from" || lastWord === "join" || (JOIN_MODIFIERS.has(lastWord) && isFollowedByJoin(beforeToken)) || isInTableListContext(beforeToken)) && !tableAliasAfterCursor;
|
||||
const exclusiveColumnSuggestions = !!qualifier && !exclusiveTableSuggestions && !insertInfo;
|
||||
const activePrefixIsCte = cteDefs.some((cte) => normalizeIdentifierPart(cte.name) === normalizeIdentifierPart(prefix));
|
||||
if (exclusiveTableSuggestions && prefix && !activePrefixIsCte && referencedTables.length > 1) {
|
||||
@@ -1728,6 +1774,7 @@ export function getSqlCompletionContext(sql: string, cursor: number): SqlComplet
|
||||
deleteTarget: deleteInfo?.target,
|
||||
oracleTableFunctionContext,
|
||||
autoAliasTableCompletions,
|
||||
tableAliasAfterCursor,
|
||||
contextKind,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user