fix(sqlserver): preserve unqualified table schema for editing
This commit is contained in:
6 files changed
+167
-13
No files matched your search
@@ -687,6 +687,76 @@ describe("queryStore hidden primary key editing", () => {
|
||||
expect(tab.queryEditabilityReason).toBeUndefined();
|
||||
});
|
||||
|
||||
it("keeps SQL Server updates unqualified when the SELECT source is unqualified", async () => {
|
||||
getConnectionConfig.mockReturnValue({ id: "sqlserver-1", name: "SQL Server 2008", db_type: "sqlserver", database: "cdc", query_timeout_secs: 30 });
|
||||
getColumns.mockResolvedValue([
|
||||
{ name: "id", data_type: "int", is_nullable: false, column_default: null, is_primary_key: true, extra: null },
|
||||
{ name: "a4", data_type: "nvarchar(100)", is_nullable: true, column_default: null, is_primary_key: false, extra: null },
|
||||
]);
|
||||
analyzeEditableQueryEditability.mockResolvedValue({
|
||||
editable: true,
|
||||
analysis: {
|
||||
schema: undefined,
|
||||
tableName: "yb_ty_qtxx",
|
||||
selectStar: true,
|
||||
columns: [{ sourceName: undefined, star: true, resultName: "*", expression: "*" }],
|
||||
},
|
||||
});
|
||||
executeMulti.mockResolvedValue([
|
||||
{
|
||||
columns: ["id", "a4"],
|
||||
rows: [[1, "德谷胰岛素利拉鲁肽"]],
|
||||
affected_rows: 0,
|
||||
execution_time_ms: 1,
|
||||
},
|
||||
]);
|
||||
|
||||
const { useQueryStore } = await import("@/stores/queryStore");
|
||||
const store = useQueryStore();
|
||||
const tabId = store.createTab("sqlserver-1", "cdc", "Query", "query", "cdc");
|
||||
|
||||
await store.executeTabSql(tabId, "select * from yb_ty_qtxx where a4 like N'%德谷胰岛素利拉鲁%'");
|
||||
|
||||
const tab = store.tabs.find((item) => item.id === tabId)!;
|
||||
await vi.waitFor(() => expect(tab.tableMeta).toBeDefined());
|
||||
expect(getColumns).toHaveBeenCalledWith("sqlserver-1", "cdc", "", "yb_ty_qtxx", undefined);
|
||||
expect(tab.tableMeta?.database).toBe("cdc");
|
||||
expect(tab.tableMeta?.schema).toBeUndefined();
|
||||
});
|
||||
|
||||
it("preserves an explicitly qualified SQL Server update source", async () => {
|
||||
getConnectionConfig.mockReturnValue({ id: "sqlserver-1", name: "SQL Server 2008", db_type: "sqlserver", database: "cdc", query_timeout_secs: 30 });
|
||||
analyzeEditableQueryEditability.mockResolvedValue({
|
||||
editable: true,
|
||||
analysis: {
|
||||
schema: "sales",
|
||||
tableName: "yb_ty_qtxx",
|
||||
selectStar: true,
|
||||
columns: [{ sourceName: undefined, star: true, resultName: "*", expression: "*" }],
|
||||
},
|
||||
});
|
||||
executeMulti.mockResolvedValue([
|
||||
{
|
||||
columns: ["id", "a4"],
|
||||
rows: [[1, "德谷胰岛素利拉鲁肽"]],
|
||||
affected_rows: 0,
|
||||
execution_time_ms: 1,
|
||||
},
|
||||
]);
|
||||
|
||||
const { useQueryStore } = await import("@/stores/queryStore");
|
||||
const store = useQueryStore();
|
||||
const tabId = store.createTab("sqlserver-1", "cdc", "Query", "query", "cdc");
|
||||
|
||||
await store.executeTabSql(tabId, "select * from sales.yb_ty_qtxx");
|
||||
|
||||
const tab = store.tabs.find((item) => item.id === tabId)!;
|
||||
await vi.waitFor(() => expect(tab.tableMeta).toBeDefined());
|
||||
expect(getColumns).toHaveBeenCalledWith("sqlserver-1", "cdc", "sales", "yb_ty_qtxx", undefined);
|
||||
expect(tab.tableMeta?.database).toBe("cdc");
|
||||
expect(tab.tableMeta?.schema).toBe("sales");
|
||||
});
|
||||
|
||||
it("appends only the missing part of a composite primary key", async () => {
|
||||
getColumns.mockResolvedValue([
|
||||
{ name: "tenant_id", data_type: "int", is_nullable: false, column_default: null, is_primary_key: true, extra: null },
|
||||
|
||||
@@ -2771,6 +2771,7 @@ export const useQueryStore = defineStore("query", () => {
|
||||
source: EditableQuerySource;
|
||||
analysis: EditableQueryInfo;
|
||||
request: TableMetadataRequest;
|
||||
writeSchema?: string;
|
||||
};
|
||||
|
||||
interface EditableQueryExecutionPreparation {
|
||||
@@ -2794,7 +2795,11 @@ export const useQueryStore = defineStore("query", () => {
|
||||
// with a qualified source.
|
||||
const qualifiedSourceDatabase = dbType === "sqlserver" ? source.catalog : connectionUsesDatabaseObjectTreeMode(conn) ? source.schema : undefined;
|
||||
const metadataDatabase = qualifiedSourceDatabase || executionDatabase || conn?.database || tab.database;
|
||||
let schema = source.schema || tab.schema;
|
||||
// SQL Server does not apply the query tab's selected schema to an
|
||||
// unqualified object reference. Resolve metadata through the login's
|
||||
// default schema (with the driver's dbo fallback) so metadata and writes
|
||||
// target the same object as the original SELECT.
|
||||
let schema = source.schema || (dbType === "sqlserver" ? "" : tab.schema);
|
||||
if (!schema) {
|
||||
if (dbType === "postgres" || dbType === "kwdb") schema = "public";
|
||||
else schema = "";
|
||||
@@ -2802,7 +2807,7 @@ export const useQueryStore = defineStore("query", () => {
|
||||
// Oracle-family connection databases are service names, not schemas. When
|
||||
// the query does not qualify a schema, let the driver resolve the current
|
||||
// login user's schema instead of looking up metadata under the service name.
|
||||
const resolvedSchema = ORACLE_LIKE_METADATA_TYPES.has(dbType) && !schema ? "" : metadataSchemaForConnection(conn, metadataDatabase, schema || undefined);
|
||||
const resolvedSchema = (dbType === "sqlserver" && !source.schema) || (ORACLE_LIKE_METADATA_TYPES.has(dbType) && !schema) ? "" : metadataSchemaForConnection(conn, metadataDatabase, schema || undefined);
|
||||
const metadataSchema = normalizeOracleLikeMetadataIdentifier(dbType, resolvedSchema || undefined, source.schema ? source.schemaQuoted : false) || "";
|
||||
const metadataTableName = normalizeOracleLikeMetadataIdentifier(dbType, source.tableName, source.tableNameQuoted)!;
|
||||
const metadataCatalog = normalizeOracleLikeMetadataIdentifier(dbType, source.catalog, source.catalogQuoted);
|
||||
@@ -2812,10 +2817,14 @@ export const useQueryStore = defineStore("query", () => {
|
||||
schema: metadataSchema || undefined,
|
||||
tableName: metadataTableName,
|
||||
};
|
||||
// Keep SQL Server writes unqualified unless the SELECT source explicitly
|
||||
// named a schema, so SELECT and UPDATE resolve the same object.
|
||||
const writeSchema = dbType === "sqlserver" && !source.schema ? undefined : metadataSchema || undefined;
|
||||
const knownTableType = tab.tableMeta?.tableName.toLowerCase() === metadataTableName.toLowerCase() && normalizeOptionalSchema(tab.tableMeta.schema) === normalizeOptionalSchema(metadataSchema) ? tab.tableMeta.tableType : undefined;
|
||||
return {
|
||||
source: metadataSource,
|
||||
analysis: normalizeOracleLikeQueryAnalysis(dbType, cloneAnalysisForSource(analysis, metadataSource), metadataSchema || undefined, metadataTableName),
|
||||
writeSchema,
|
||||
request: {
|
||||
connectionId: tab.connectionId!,
|
||||
database: metadataDatabase,
|
||||
@@ -2836,7 +2845,7 @@ export const useQueryStore = defineStore("query", () => {
|
||||
tableMeta: {
|
||||
catalog: target.request.catalog,
|
||||
database: target.request.database,
|
||||
schema: target.request.schema || undefined,
|
||||
schema: target.writeSchema,
|
||||
tableName: target.request.tableName,
|
||||
tableType: metadata.tableType,
|
||||
columns: metadata.columns,
|
||||
|
||||
Reference in new issue
Block a user