fix(kingbase): honor connection identifier quotes in exports

This commit is contained in:
dienaso authored and GitHub committed 2026-08-18 12:43:31 +08:00
1 parent cb09a5c75b
commit 9fc7721590
18 files changed
+313 -8

No files matched your search

@@ -426,6 +426,7 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
}
return buildDataGridCopyInsertStatement({
databaseType: databaseType.value,
identifierQuote: options.identifierQuote?.value,
tableMeta: tableMeta.value,
columns: data.columns,
columnTypes: data.columnTypes,
@@ -1250,6 +1251,7 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
const exportData = sqlInsertExportData(result);
const content = await formatSqlInsert({
databaseType: databaseType.value,
identifierQuote: options.identifierQuote?.value,
schema: tableMeta.value?.schema,
tableName: tableMeta.value?.tableName || "table_name",
columns: exportData.columns,
@@ -1271,6 +1273,7 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
const exportData = sqlInsertExportData(result);
const content = await formatSqlInsert({
databaseType: databaseType.value,
identifierQuote: options.identifierQuote?.value,
schema: tableMeta.value?.schema,
tableName: tableMeta.value?.tableName || "table_name",
columns: exportData.columns,
+1
View File
@@ -4310,6 +4310,7 @@ export interface QueryResultExportRequest {
exportColumnTypes?: Array<string | null | undefined>;
numericColumnRightAlign?: boolean;
columnComments?: Array<string | null> | null;
identifierQuote?: string;
}
export async function startTableExport(request: TableExportRequest, onProgress: (progress: TableExportProgress) => void): Promise<TableExportProgress> {
@@ -36,6 +36,7 @@ export interface DataGridSaveStatementOptions {
export interface DataGridCopyUpdateStatementOptions {
databaseType?: DatabaseType;
identifierQuote?: string;
tableMeta: DataGridTableMeta;
columns: string[];
sourceColumns?: Array<string | undefined>;
@@ -46,6 +47,7 @@ export type DataGridCopyInsertMode = "merged" | "row-by-row";
export interface DataGridCopyInsertStatementOptions {
databaseType?: DatabaseType;
identifierQuote?: string;
tableMeta?: DataGridTableMeta;
columns: string[];
columnTypes?: Array<string | null | undefined>;
@@ -29,6 +29,7 @@ export function formatTsv(columns: string[], rows: ExportCellValue[][]): string
export interface FormatSqlInsertOptions {
databaseType?: DatabaseType;
identifierQuote?: string;
schema?: string;
tableName?: string;
qualifiedTableName?: string;
@@ -0,0 +1,79 @@
import { createPinia, setActivePinia } from "pinia";
import { beforeEach, describe, expect, it, vi } from "vitest";
const mocks = vi.hoisted(() => ({
ensureConnected: vi.fn(),
getConfig: vi.fn(),
connectionIdentifierQuote: vi.fn(),
}));
vi.mock("@/lib/backend/api", () => ({
saveOpenTabsState: vi.fn().mockResolvedValue(undefined),
}));
vi.mock("@/stores/connectionStore", () => ({
useConnectionStore: () => ({
ensureConnected: mocks.ensureConnected,
getConfig: mocks.getConfig,
connectionIdentifierQuote: mocks.connectionIdentifierQuote,
}),
}));
vi.mock("@/stores/settingsStore", () => ({
useSettingsStore: () => ({
editorSettings: {
exportBatchSize: 1000,
exportRowLimitEnabled: false,
exportRowLimit: 100_000,
globalQueryTimeoutSecs: 30,
queryExportKeysetOptimizationEnabled: true,
numericColumnRightAlign: true,
},
}),
}));
function installLocalStorage() {
const data = new Map<string, string>();
vi.stubGlobal("localStorage", {
getItem: vi.fn((key: string) => data.get(key) ?? null),
setItem: vi.fn((key: string, value: string) => data.set(key, value)),
removeItem: vi.fn((key: string) => data.delete(key)),
});
}
describe("queryStore query result export", () => {
beforeEach(() => {
vi.clearAllMocks();
installLocalStorage();
setActivePinia(createPinia());
mocks.ensureConnected.mockResolvedValue(undefined);
mocks.getConfig.mockReturnValue({ id: "kingbase-1", name: "Kingbase", db_type: "kingbase", database: "app", query_timeout_secs: 30 });
mocks.connectionIdentifierQuote.mockReturnValue("[");
});
it("passes the live connection identifier quote to backend SQL export", async () => {
const { useQueryStore } = await import("@/stores/queryStore");
const store = useQueryStore();
const tabId = store.createTab("kingbase-1", "app", "Query");
const tab = store.tabs.find((item) => item.id === tabId)!;
tab.sql = "SELECT select FROM audit_log";
tab.lastExecutedSql = tab.sql;
tab.result = {
columns: ["select"],
rows: [["value"]],
affected_rows: 0,
execution_time_ms: 1,
};
const request = await store.buildQueryResultExportRequest(tabId, {
exportId: "export-1",
filePath: "audit.sql",
format: "sql",
exportTableName: "audit_log",
exportColumnTypes: ["text"],
});
expect(request?.identifierQuote).toBe("[");
expect(mocks.connectionIdentifierQuote).toHaveBeenCalledWith("kingbase-1");
});
});
+2
View File
@@ -6084,6 +6084,7 @@ export const useQueryStore = defineStore("query", () => {
exportTableName: options.exportTableName,
exportColumnTypes: options.exportColumnTypes,
numericColumnRightAlign: settings.numericColumnRightAlign,
identifierQuote: connStore.connectionIdentifierQuote(location.connectionId),
};
}
@@ -6119,6 +6120,7 @@ export const useQueryStore = defineStore("query", () => {
executionId: uuid(),
numericColumnRightAlign: settings.numericColumnRightAlign,
columnComments,
identifierQuote: connStore.connectionIdentifierQuote(tab.connectionId),
};
const tracker = useExportTracker();