fix(structure): keep Oracle case-sensitive identifiers quoted when quoting off
This commit is contained in:
8 files changed
+140
-12
No files matched your search
@@ -142,6 +142,22 @@ describe("omitDdlIdentifierQuotes", () => {
|
||||
const ddl = 'ALTER TABLE "SYSTEM"."TEST" RENAME COLUMN "ABCD" TO "AbCd";';
|
||||
expect(formatGeneratedDdlIdentifierQuotes(ddl, "oracle", true)).toBe(ddl);
|
||||
});
|
||||
|
||||
it("keeps case-sensitive Oracle identifiers quoted when the edited table preserves case (#9649)", () => {
|
||||
const ddl = 'ALTER TABLE "DBX_TEST"."T_9649" MODIFY ("cName" VARCHAR2(120 BYTE));\nALTER TABLE "DBX_TEST"."T_9649" ADD ("cNabcs" clob);\nCOMMENT ON COLUMN "DBX_TEST"."T_9649"."cName" IS \'中文名\';';
|
||||
const expected = 'ALTER TABLE DBX_TEST.T_9649 MODIFY ("cName" VARCHAR2(120 BYTE));\nALTER TABLE DBX_TEST.T_9649 ADD ("cNabcs" clob);\nCOMMENT ON COLUMN DBX_TEST.T_9649."cName" IS \'中文名\';';
|
||||
expect(formatGeneratedDdlIdentifierQuotes(ddl, "oracle", false, { preserveCaseSensitiveIdentifiers: true })).toBe(expected);
|
||||
});
|
||||
|
||||
it("still folds plain Oracle identifiers while preserving case-sensitive ones (#9649)", () => {
|
||||
const ddl = 'ALTER TABLE "SYSTEM"."TEST" ADD ("ID" NUMBER(10), "NEW_COL" VARCHAR2(20), "with space" VARCHAR2(20));';
|
||||
expect(formatGeneratedDdlIdentifierQuotes(ddl, "oracle", false, { preserveCaseSensitiveIdentifiers: true })).toBe('ALTER TABLE SYSTEM.TEST ADD (ID NUMBER(10), NEW_COL VARCHAR2(20), "with space" VARCHAR2(20));');
|
||||
});
|
||||
|
||||
it("ignores the case-preservation option for dialects that keep their own rules", () => {
|
||||
const ddl = 'ALTER TABLE "user_login_log" ADD "status" INT;';
|
||||
expect(formatGeneratedDdlIdentifierQuotes(ddl, "dameng", false, { preserveCaseSensitiveIdentifiers: true })).toBe(ddl);
|
||||
});
|
||||
});
|
||||
|
||||
describe("ddlFormatDialectFor", () => {
|
||||
|
||||
@@ -64,25 +64,38 @@ export function omitDdlIdentifierQuotes(sql: string, dialect: SqlFormatDialect):
|
||||
|
||||
const SIMPLE_ORACLE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_$#]*$/;
|
||||
|
||||
export interface GeneratedDdlIdentifierQuoteOptions {
|
||||
/**
|
||||
* Set by structure editors whose edited table already stores a lowercase or
|
||||
* mixed-case identifier. Oracle folds bare identifiers to uppercase, so
|
||||
* unquoting `"cName"` turns the statement into `CNAME` — a different column,
|
||||
* which fails with ORA-00904 or silently creates a differently-cased column.
|
||||
* Preserving the case keeps quotes on every name that would change identity
|
||||
* while plain names keep the folding behaviour requested in #8997.
|
||||
*/
|
||||
preserveCaseSensitiveIdentifiers?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the identifier-quoting preference to SQL generated by a structure
|
||||
* editor. Oracle folds bare identifiers to uppercase, so safe quoted names
|
||||
* are uppercased before their quotes are removed. Dameng keeps its stricter
|
||||
* case-sensitive identifier rules through omitDdlIdentifierQuotes instead.
|
||||
*/
|
||||
export function formatGeneratedDdlIdentifierQuotes(sql: string, dialect: SqlFormatDialect, quoteIdentifiers: boolean): string {
|
||||
export function formatGeneratedDdlIdentifierQuotes(sql: string, dialect: SqlFormatDialect, quoteIdentifiers: boolean, options: GeneratedDdlIdentifierQuoteOptions = {}): string {
|
||||
if (quoteIdentifiers) return sql;
|
||||
if (dialect !== "oracle") return omitDdlIdentifierQuotes(sql, dialect);
|
||||
|
||||
const preserveCaseSensitive = options.preserveCaseSensitiveIdentifiers === true;
|
||||
const tokens = tokenizeSqlSemantic(sql, dialect);
|
||||
const replacements: Array<{ start: number; end: number; value: string }> = [];
|
||||
|
||||
for (const token of tokens) {
|
||||
if (token.kind !== "quoted_identifier") continue;
|
||||
const identifier = unquoteSqlSemanticIdentifier(token);
|
||||
if (SIMPLE_ORACLE_IDENTIFIER.test(identifier) && !requiresOracleIdentifierQuote(identifier.toUpperCase())) {
|
||||
replacements.push({ start: token.span.start, end: token.span.end, value: identifier.toUpperCase() });
|
||||
}
|
||||
if (!SIMPLE_ORACLE_IDENTIFIER.test(identifier) || requiresOracleIdentifierQuote(identifier.toUpperCase())) continue;
|
||||
if (preserveCaseSensitive && identifier !== identifier.toUpperCase()) continue;
|
||||
replacements.push({ start: token.span.start, end: token.span.end, value: identifier.toUpperCase() });
|
||||
}
|
||||
|
||||
let result = sql;
|
||||
|
||||
Reference in new issue
Block a user