feat(sqlCompletion): 优化表别名建议功能,避免使用 SQL 关键字 (#2805)

This commit is contained in:
二丫讲梵 authored and GitHub committed 2026-07-08 00:01:24 +08:00
1 parent 8364f468a0
commit 7eff6e544b
2 files changed
+60 -2

No files matched your search

+16 -2
View File
@@ -1,3 +1,4 @@
import { Cassandra, MariaSQL, MSSQL, MySQL, PLSQL, PostgreSQL, SQLite, StandardSQL } from "@codemirror/lang-sql";
import type { DatabaseType, SqlSnippet } from "@/types/database";
import { buildMongoCompletionItemsFromContext, type MongoCompletionItem } from "@/lib/mongo/mongoCompletion";
@@ -1064,6 +1065,15 @@ const SQL_ALIAS_RESERVED_WORDS = new Set([
"with",
]);
const SQL_ALIAS_KEYWORD_WORDS = new Set(sqlAliasKeywordWords(SQL_KEYWORDS.join(" "), StandardSQL.spec.keywords, MySQL.spec.keywords, MariaSQL.spec.keywords, PostgreSQL.spec.keywords, MSSQL.spec.keywords, SQLite.spec.keywords, PLSQL.spec.keywords, Cassandra.spec.keywords));
function sqlAliasKeywordWords(...sources: Array<string | undefined>): string[] {
return sources
.flatMap((source) => (source ?? "").split(/\s+/))
.filter((keyword) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(keyword))
.map((keyword) => keyword.toLowerCase());
}
export interface SqlCompletionTable {
name: string;
schema?: string;
@@ -3045,7 +3055,7 @@ function generateTableCompletionAlias(tableName: string, existing = new Set<stri
const candidates = buildAliasCandidates(tableName);
for (const candidate of candidates.filter(Boolean)) {
if (SQL_ALIAS_RESERVED_WORDS.has(candidate.toLowerCase())) continue;
if (isUnsafeSqlAlias(candidate.toLowerCase())) continue;
if (!existing.has(candidate.toLowerCase())) return candidate;
for (let index = 2; index < 100; index++) {
const numbered = `${candidate}${index}`;
@@ -3081,7 +3091,11 @@ function buildAliasCandidates(tableName: string): string[] {
function aliasConflicts(candidate: string, existing: Set<string>): boolean {
const lower = candidate.toLowerCase();
return existing.has(lower) || SQL_ALIAS_RESERVED_WORDS.has(lower);
return existing.has(lower) || isUnsafeSqlAlias(lower);
}
function isUnsafeSqlAlias(candidate: string): boolean {
return SQL_ALIAS_RESERVED_WORDS.has(candidate) || SQL_ALIAS_KEYWORD_WORDS.has(candidate);
}
function isFollowedByJoin(beforeToken: string): boolean {