fix(ddl): resolve DDL view formatting dialect by database type

This commit is contained in:
zipg authored and GitHub committed 2026-09-20 12:16:25 +08:00
1 parent b040600e47
commit b0cac9f714
3 files changed
+45 -4

No files matched your search

+27 -1
View File
@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { formatGeneratedDdlIdentifierQuotes, omitDdlDatabaseQualifier, omitDdlIdentifierQuotes } from "@/lib/sql/ddlDisplay";
import { ddlFormatDialectFor, formatGeneratedDdlIdentifierQuotes, omitDdlDatabaseQualifier, omitDdlIdentifierQuotes } from "@/lib/sql/ddlDisplay";
describe("omitDdlDatabaseQualifier", () => {
it("drops the schema qualifier from Oracle table DDL without touching tablespace references", () => {
@@ -109,3 +109,29 @@ describe("omitDdlIdentifierQuotes", () => {
expect(formatGeneratedDdlIdentifierQuotes(ddl, "oracle", true)).toBe(ddl);
});
});
describe("ddlFormatDialectFor", () => {
it("prefers the effective database type over an Oracle-like connection's MySQL highlighting dialect", () => {
expect(ddlFormatDialectFor({ databaseType: "oracle", highlightDialect: "mysql" })).toBe("oracle");
expect(ddlFormatDialectFor({ databaseType: "dameng", highlightDialect: "mysql" })).toBe("dameng");
expect(ddlFormatDialectFor({ databaseType: "kingbase", highlightDialect: "mysql" })).toBe("postgres");
});
it("honors an explicit formatter dialect first", () => {
expect(ddlFormatDialectFor({ formatDialect: "sqlserver", databaseType: "oracle", highlightDialect: "mysql" })).toBe("sqlserver");
});
it("keeps the highlighting dialect when the database type has no dedicated formatter dialect", () => {
expect(ddlFormatDialectFor({ databaseType: "db2", highlightDialect: "mysql" })).toBe("mysql");
expect(ddlFormatDialectFor({ highlightDialect: "postgres" })).toBe("postgres");
expect(ddlFormatDialectFor({})).toBe("generic");
});
it("keeps case-sensitive quoted Oracle names quoted in the DDL view", () => {
const ddl = 'CREATE TABLE "SYSTEM"."TEST" ("id" VARCHAR2(32), "cName" VARCHAR2(100))';
const highlightDialect = "mysql";
const resolved = ddlFormatDialectFor({ databaseType: "oracle", highlightDialect });
expect(omitDdlIdentifierQuotes(ddl, highlightDialect)).toBe("CREATE TABLE SYSTEM.TEST (id VARCHAR2(32), cName VARCHAR2(100))");
expect(omitDdlIdentifierQuotes(ddl, resolved)).toBe('CREATE TABLE SYSTEM.TEST ("id" VARCHAR2(32), "cName" VARCHAR2(100))');
});
});
+16 -1
View File
@@ -1,7 +1,7 @@
import { requiresDamengIdentifierQuote, requiresMysqlIdentifierQuote, requiresOracleIdentifierQuote, requiresPostgresIdentifierQuote } from "@/lib/sql/sqlIdentifier";
import { tokenIsIdentifier, tokenizeSqlSemantic, unquoteSqlSemanticIdentifier } from "@/lib/sql/semantic/tokens";
import type { SqlSemanticToken } from "@/lib/sql/semantic/types";
import type { SqlFormatDialect } from "@/lib/sql/sqlFormatter";
import { sqlFormatDialectForDbType, type SqlFormatDialect } from "@/lib/sql/sqlFormatter";
import { dropsSchemaQualifier } from "@/lib/table/tableSelectSql";
import type { DatabaseType } from "@/types/database";
@@ -28,6 +28,21 @@ function canRenderUnquoted(identifier: string, dialect: SqlFormatDialect): boole
}
}
/**
* Resolve the dialect used to read and rewrite DDL text. Callers that only
* know the connection's syntax-highlighting dialect (which collapses every
* Oracle-like database onto MySQL) must not have that value decide identifier
* quoting rules: a case-sensitive Oracle/Dameng name such as `"cName"` would
* lose its quotes. The effective database type wins, the highlighting dialect
* stays as the fallback for unmapped types.
*/
export function ddlFormatDialectFor(options: { formatDialect?: SqlFormatDialect; databaseType?: DatabaseType; highlightDialect?: SqlFormatDialect }): SqlFormatDialect {
if (options.formatDialect) return options.formatDialect;
const fromDatabaseType = options.databaseType ? sqlFormatDialectForDbType(options.databaseType) : undefined;
if (fromDatabaseType && fromDatabaseType !== "generic") return fromDatabaseType;
return options.highlightDialect ?? fromDatabaseType ?? "generic";
}
/** Removes dialect identifier quotes from safe names while preserving strings, comments, and unsafe names. */
export function omitDdlIdentifierQuotes(sql: string, dialect: SqlFormatDialect): string {
const tokens = tokenizeSqlSemantic(sql, dialect === "sqlserver" ? "sqlserver" : dialect);