fix(sqlserver): support Unicode table references in completion

This commit is contained in:
guoyongchang 2026-08-05 02:51:45 +08:00 committed by GitHub
parent e61e3935c8
commit fb0aafa04b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 38 additions and 2 deletions

View File

@ -2512,9 +2512,10 @@ function extractReferencedTables(sql: string, databaseType?: DatabaseType): SqlC
]);
// STRAIGHT_JOIN is a standalone MySQL table introducer, not a modifier followed by JOIN.
const identifier = '(?:"[^"]+"|`[^`]+`|\\[[^\\]]+\\]|[A-Za-z_][\\w$@#]*)';
const unquotedIdentifier = databaseType === "sqlserver" ? "[_\\p{ID_Start}][$@#_\\u200c\\u200d\\p{ID_Continue}]*" : "[A-Za-z_][\\w$@#]*";
const identifier = `(?:"[^"]+"|\`[^\`]+\`|\\[[^\\]]+\\]|${unquotedIdentifier})`;
const qualifiedSeparator = databaseType === "sqlserver" ? `\\.(?:${identifier}|\\.${identifier})` : `\\.${identifier}`;
const pattern = new RegExp(`\\b(?:from|join|straight_join|update|apply)\\s+(${identifier}(?:${qualifiedSeparator}){0,3})(?:\\s+(?:as\\s+)?([A-Za-z_][\\w$]*))?`, "gi");
const pattern = new RegExp(`\\b(?:from|join|straight_join|update|apply)\\s+(${identifier}(?:${qualifiedSeparator}){0,3})(?:\\s+(?:as\\s+)?([A-Za-z_][\\w$]*))?`, databaseType === "sqlserver" ? "giu" : "gi");
const referenced: SqlCompletionReferencedTable[] = [];
let match: RegExpExecArray | null;
while ((match = pattern.exec(sql)) !== null) {

View File

@ -2,6 +2,7 @@ import { strict as assert } from "node:assert";
import { test } from "vitest";
import {
buildSqlCompletionItems,
buildSqlCompletionItemsFromContext,
getSqlFunctionSignatureHelp,
getSqlCompletionResultValidFor,
isSqlCommentContext,
@ -496,6 +497,40 @@ test("suggests SQL Server tables for unquoted Chinese prefixes", () => {
assert.equal(shouldAutoOpenSqlCompletion(sql, sql.length), true);
});
test("suggests SQL Server columns for an aliased unquoted Chinese table", () => {
const sql = "SELECT * FROM 大客户报废物资 AS tb2 WHERE ";
const options = { databaseType: "sqlserver" as const, dialect: "sqlserver" as const };
const legacy = getSqlCompletionContext(sql, sql.length, options);
const semantic = buildSqlSemanticModel(sql, sql.length, options);
const context = sqlCompletionContextFromSemantic(semantic, legacy);
const items = buildSqlCompletionItemsFromContext(context, {
...options,
tables: [{ name: "大客户报废物资", schema: "dbo", type: "table" }],
columnsByTable: new Map([
[
"dbo.大客户报废物资",
[
{ name: "物资编号", table: "大客户报废物资", schema: "dbo" },
{ name: "客户名称", table: "大客户报废物资", schema: "dbo" },
],
],
]),
});
assert.equal(context.referencedTables.length, 1);
assert.equal(context.referencedTables[0]?.name, "大客户报废物资");
assert.equal(context.referencedTables[0]?.alias, "tb2");
assert.equal(context.suggestColumns, true);
assert.equal(shouldAutoOpenSqlCompletion(sql, sql.length, options), true);
assert.deepEqual(
items
.filter((item) => item.type === "column")
.map((item) => item.label)
.sort(),
["客户名称", "物资编号"],
);
});
test("preserves Unicode prefixes through the semantic completion context", () => {
const sql = "select * from dbo.客户";
const legacy = getSqlCompletionContext(sql, sql.length);