fix(sqlserver): preserve double-dot completion targets
This commit is contained in:
1 parent
e1052333c1
commit
00927ac435
5 files changed
+115
-12
No files matched your search
@@ -134,6 +134,56 @@ describe("semantic SQL completion candidates", () => {
|
||||
expect(context.qualifierParts).toEqual(["DatabaseB", "OUT", "orders"]);
|
||||
expect(items.filter((item) => item.type === "column").map((item) => item.label)).toEqual(["target_marker"]);
|
||||
});
|
||||
|
||||
it("completes SQL Server tables from the database dbo schema after a double dot", () => {
|
||||
const { context, items } = semanticCompletion(
|
||||
"SELECT * FROM BarDB..|",
|
||||
{
|
||||
tables: [{ name: "orders", database: "BarDB", schema: "dbo", type: "table" }],
|
||||
},
|
||||
{ databaseType: "sqlserver", dialect: "sqlserver" },
|
||||
);
|
||||
|
||||
expect(context).toMatchObject({
|
||||
prefix: "",
|
||||
qualifier: "BarDB.dbo",
|
||||
qualifierParts: ["BarDB", "dbo"],
|
||||
});
|
||||
expect(items.filter((item) => item.type === "table")).toEqual([expect.objectContaining({ label: "orders", apply: "orders" })]);
|
||||
});
|
||||
|
||||
it("completes SQL Server alias columns from the exact double-dot metadata target", () => {
|
||||
const columnsByTable = new Map<string, SqlCompletionColumn[]>([
|
||||
["FooDB.dbo.orders", [{ name: "wrong_database", table: "orders", schema: "dbo" }]],
|
||||
["BarDB.sales.orders", [{ name: "wrong_schema", table: "orders", schema: "sales" }]],
|
||||
["BarDB.dbo.orders", [{ name: "target_marker", table: "orders", schema: "dbo" }]],
|
||||
]);
|
||||
const { model, context, items } = semanticCompletion("SELECT * FROM BarDB..orders AS o WHERE o.|", { columnsByTable }, { databaseType: "sqlserver", dialect: "sqlserver" });
|
||||
|
||||
expect(model.rowSources).toEqual([
|
||||
expect.objectContaining({
|
||||
name: "orders",
|
||||
qualifierParts: ["BarDB", "dbo"],
|
||||
alias: "o",
|
||||
metadataTarget: { database: "BarDB", schema: "dbo", table: "orders" },
|
||||
}),
|
||||
]);
|
||||
expect(context.referencedTables).toEqual([expect.objectContaining({ name: "orders", database: "BarDB", schema: "dbo", alias: "o" })]);
|
||||
expect(items.filter((item) => item.type === "column").map((item) => item.label)).toEqual(["target_marker"]);
|
||||
});
|
||||
|
||||
it("completes unqualified SQL Server columns from the exact double-dot metadata target", () => {
|
||||
const columnsByTable = new Map<string, SqlCompletionColumn[]>([
|
||||
["FooDB.dbo.orders", [{ name: "wrong_database", table: "orders", schema: "dbo" }]],
|
||||
["BarDB.sales.orders", [{ name: "wrong_schema", table: "orders", schema: "sales" }]],
|
||||
["BarDB.dbo.orders", [{ name: "target_marker", table: "orders", schema: "dbo" }]],
|
||||
]);
|
||||
const { context, items } = semanticCompletion("SELECT * FROM BarDB..orders WHERE tar|", { columnsByTable }, { databaseType: "sqlserver", dialect: "sqlserver" });
|
||||
|
||||
expect(context.referencedTables).toEqual([expect.objectContaining({ name: "orders", database: "BarDB", schema: "dbo" })]);
|
||||
expect(items.filter((item) => item.type === "column").map((item) => item.label)).toEqual(["target_marker"]);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["MySQL ORDER BY", "SELECT * FROM t LIMIT 100 or|", "mysql", "mysql", "ORDER BY"],
|
||||
["PostgreSQL ON CONFLICT", "INSERT INTO t VALUES (1) on|", "postgres", "postgres", "ON CONFLICT"],
|
||||
|
||||
@@ -440,6 +440,13 @@ describe("sqlCompletion scoped context classification", () => {
|
||||
expect(context.referencedTables).toEqual(expect.arrayContaining([expect.objectContaining({ schema: "dbo", name: "Users", alias: "u" }), expect.objectContaining({ name: "Orders", alias: "o" })]));
|
||||
});
|
||||
|
||||
it("preserves SQL Server database and omitted schema in legacy table references", () => {
|
||||
const sql = "SELECT * FROM BarDB..orders AS o WHERE o.";
|
||||
const context = getSqlCompletionContext(sql, sql.length, { databaseType: "sqlserver" });
|
||||
|
||||
expect(context.referencedTables).toEqual([expect.objectContaining({ database: "BarDB", schema: "dbo", name: "orders", alias: "o" })]);
|
||||
});
|
||||
|
||||
it("treats schema-qualified table prefixes in FROM as table completion input", () => {
|
||||
const sql = "SELECT * FROM dws_game_sdk_base.di";
|
||||
const context = getSqlCompletionContext(sql, sql.length);
|
||||
|
||||
@@ -82,6 +82,38 @@ describe("sqlCompletionLookupTarget", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("routes a SQL Server double-dot qualifier to the database's dbo schema", () => {
|
||||
const sql = "select * from BarDB..ord";
|
||||
const completionContext = getSqlCompletionContext(sql, sql.length, { databaseType: "sqlserver" });
|
||||
|
||||
expect(completionContext).toMatchObject({
|
||||
prefix: "ord",
|
||||
qualifier: "BarDB.dbo",
|
||||
qualifierParts: ["BarDB", "dbo"],
|
||||
});
|
||||
expect(
|
||||
resolveSqlCompletionTableLookupTarget({
|
||||
currentDatabase: "FooDB",
|
||||
currentSchema: "sales",
|
||||
supportsDatabaseQualifier: false,
|
||||
supportsDatabaseSchemaQualifier: true,
|
||||
knownDatabases: ["FooDB", "BarDB"],
|
||||
completionContext,
|
||||
}),
|
||||
).toEqual({
|
||||
database: "BarDB",
|
||||
schema: "dbo",
|
||||
filter: "ord",
|
||||
qualifierDatabase: "BarDB",
|
||||
});
|
||||
});
|
||||
|
||||
it.each(["postgres", "trino", "prestosql"] as const)("does not apply SQL Server double-dot semantics to %s", (databaseType) => {
|
||||
const sql = "select * from BarDB..ord";
|
||||
|
||||
expect(getSqlCompletionContext(sql, sql.length, { databaseType }).qualifierParts).toBeUndefined();
|
||||
});
|
||||
|
||||
it("keeps PostgreSQL schema completion in the current database", () => {
|
||||
const target = resolveSqlCompletionTableLookupTarget({
|
||||
currentDatabase: "app",
|
||||
|
||||
Reference in new issue
Block a user