fix(kingbase): honor MySQL-compatible identifier quoting

This commit is contained in:
dienaso authored and GitHub committed 2026-08-13 12:40:50 +08:00
1 parent 6f4f6f373e
commit 7eac5dd610
9 files changed
+150 -46

No files matched your search

+1
View File
@@ -1564,6 +1564,7 @@ async function newQuery() {
targetConnectionId: target.connectionId,
targetDatabase: target.database,
databaseType: effectiveDatabaseTypeForConnection(conn),
identifierQuote: connectionStore.connectionIdentifierQuote?.(target.connectionId),
});
const tabId = queryStore.createTab(conn.id, target.database, undefined, "query", target.schema, initialSql, target.catalog);
if (initialSql) {
@@ -76,6 +76,7 @@ import { isXuguTypeMemberContainer } from "@/lib/sidebar/xuguTypeMembers";
import { isXuguPublicSynonymTreeNode } from "@/lib/sidebar/xuguPublicSynonyms";
import { mysqlObjectTemplateForGroup } from "@/lib/sidebar/mysqlObjectTemplates";
import { buildTableDeleteTemplate, buildTableInsertTemplate, buildTableSelectTemplate, buildTableUpdateTemplate } from "@/lib/table/tableSqlTemplates";
import { qualifiedTableName } from "@/lib/table/tableSelectSql";
import { driverStoreFocusForInstallError } from "@/lib/connection/agentDriverInstallHint";
import {
canCreateConnectionNamespace,
@@ -1540,6 +1541,7 @@ async function generateDdlTemplate() {
const result = await api.getObjectSource(target.connectionId, target.database, schema, target.label, "VIEW");
return buildViewDdl({
databaseType: databaseTypeForNode(target),
identifierQuote: connectionStore.connectionIdentifierQuote?.(target.connectionId),
schema,
name: target.label,
source: result.source,
@@ -3486,7 +3488,17 @@ function createView() {
connectionStore.activeConnectionId = node.connectionId;
const viewName = "new_view";
const effectiveDbType = effectiveDatabaseTypeForConnection(connectionStore.getConfig(node.connectionId));
const viewSqlName = effectiveDbType === "informix" || !node.schema ? viewName : `${node.schema}.${viewName}`;
// Quote the schema/name with the driver-reported identifier quote so
// hyphenated schemas (Kingbase MySQL compat) render as valid identifiers.
const viewSqlName =
effectiveDbType === "informix" || !node.schema
? viewName
: qualifiedTableName({
databaseType: effectiveDbType,
identifierQuote: connectionStore.connectionIdentifierQuote?.(node.connectionId),
schema: node.schema,
tableName: viewName,
});
const tabId = queryStore.createTab(node.connectionId, node.database, t("contextMenu.createView"), "query", node.schema, undefined, node.catalog);
queryStore.updateSql(tabId, `CREATE VIEW ${viewSqlName} AS\nSELECT\n *\nFROM table_name;\n`);
queryStore.setObjectSource(tabId, {
@@ -216,6 +216,15 @@ describe("buildSelectAllSql", () => {
it("qualifies a StarRocks external-catalog table with catalog and database", () => {
expect(buildSelectAllSql("starrocks", { catalog: "paimon_catalog", database: "bi", tableName: "events" })).toBe("SELECT * FROM `paimon_catalog`.`bi`.`events`");
});
it("uses the driver-reported identifier quote for Kingbase MySQL compat mode", () => {
expect(buildSelectAllSql("kingbase", { schema: "audit_schema", tableName: "events" }, "`")).toBe("SELECT * FROM `audit_schema`.`events`");
});
it("uses the driver-reported identifier quote for Kingbase PostgreSQL mode", () => {
expect(buildSelectAllSql("kingbase", { schema: "audit_schema", tableName: "events" }, '"')).toBe('SELECT * FROM "audit_schema"."events"');
});
it("falls back to double quotes for Kingbase when no identifier quote is reported", () => {
expect(buildSelectAllSql("kingbase", { schema: "audit_schema", tableName: "events" })).toBe('SELECT * FROM "audit_schema"."events"');
});
});
describe("isNewQueryPrefillSupported", () => {
+4 -3
View File
@@ -90,6 +90,7 @@ export interface ResolveNewQueryInitialSqlInput extends ResolveNewQueryTableInpu
targetConnectionId: string;
targetDatabase: string;
databaseType?: DatabaseType;
identifierQuote?: string;
}
// Database types whose "table" view does not use standard SQL `SELECT * FROM <table>`
@@ -145,9 +146,9 @@ export function resolveNewQueryTable(input: ResolveNewQueryTableInput): NewQuery
* the same per-dialect identifier quoting and schema/catalog qualification used
* by the table-data view.
*/
export function buildSelectAllSql(databaseType: DatabaseType | undefined, table: Pick<NewQueryTable, "schema" | "catalog" | "tableName"> & Partial<Pick<NewQueryTable, "database">>): string {
export function buildSelectAllSql(databaseType: DatabaseType | undefined, table: Pick<NewQueryTable, "schema" | "catalog" | "tableName"> & Partial<Pick<NewQueryTable, "database">>, identifierQuote?: string): string {
if (databaseType === "victoriametrics") return metricRangeQuery(table.tableName);
const ref = qualifiedTableName({ databaseType, database: table.database, schema: table.schema, catalog: table.catalog, tableName: table.tableName });
const ref = qualifiedTableName({ databaseType, identifierQuote, database: table.database, schema: table.schema, catalog: table.catalog, tableName: table.tableName });
return `SELECT * FROM ${ref}`;
}
@@ -162,5 +163,5 @@ export function resolveNewQueryInitialSql(input: ResolveNewQueryInitialSqlInput)
const table = resolveNewQueryTable(input);
if (!table || table.connectionId !== input.targetConnectionId || table.database !== input.targetDatabase) return undefined;
return buildSelectAllSql(input.databaseType, table);
return buildSelectAllSql(input.databaseType, table, input.identifierQuote);
}
+2
View File
@@ -6,6 +6,8 @@ export type BuildViewDdlInput = {
schema?: string | null;
name: string;
source: string;
/** Driver-reported identifier quote (e.g. `` ` `` for Kingbase MySQL compat). */
identifierQuote?: string;
};
export function buildViewDdl(input: BuildViewDdlInput): Promise<string> {