Quote and escape identifiers with spaces or non-ascii chars in dbml (#582)

Co-authored-by: Lopes Lenny <lenny.lopes@litecom.ch>
This commit is contained in:
Lenny Lopes
2025-09-17 11:45:48 +02:00
committed by GitHub
parent c5e0415ea3
commit 283df0a4e4

View File

@@ -4,6 +4,18 @@ import i18n from "../../i18n/i18n";
import { escapeQuotes } from "../exportSQL/shared"; import { escapeQuotes } from "../exportSQL/shared";
import { isFunction, isKeyword } from "../utils"; import { isFunction, isKeyword } from "../utils";
const IDENT_SAFE_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
function escapeIdentifier(s) {
return String(s).replace(/\\/g, "\\\\").replace(/"/g, '\\"');
}
function quoteIdentifier(name) {
if (name == null) return name;
const s = String(name);
return IDENT_SAFE_RE.test(s) ? s : `"${escapeIdentifier(s)}"`;
}
function parseDefaultDbml(field, database) { function parseDefaultDbml(field, database) {
if (isFunction(field.default)) { if (isFunction(field.default)) {
return `\`${field.default}\``; return `\`${field.default}\``;
@@ -96,7 +108,7 @@ export function toDBML(diagram) {
(f) => f.id === rel.endFieldId, (f) => f.id === rel.endFieldId,
); );
return `Ref ${rel.name} {\n\t${startTableName}.${startFieldName} ${cardinality(rel)} ${endTableName}.${endFieldName} [ delete: ${rel.deleteConstraint.toLowerCase()}, update: ${rel.updateConstraint.toLowerCase()} ]\n}`; return `Ref ${rel.name} {\n\t${quoteIdentifier(startTableName)}.${quoteIdentifier(startFieldName)} ${cardinality(rel)} ${quoteIdentifier(endTableName)}.${quoteIdentifier(endFieldName)} [ delete: ${rel.deleteConstraint.toLowerCase()}, update: ${rel.updateConstraint.toLowerCase()} ]\n}`;
}; };
let enumDefinitions = ""; let enumDefinitions = "";
@@ -107,7 +119,7 @@ export function toDBML(diagram) {
(field.type === "ENUM" || field.type === "SET") && (field.type === "ENUM" || field.type === "SET") &&
Array.isArray(field.values) Array.isArray(field.values)
) { ) {
enumDefinitions += `enum ${field.name}_${field.values.join("_")}_t {\n\t${field.values.join("\n\t")}\n}\n\n`; enumDefinitions += `enum ${quoteIdentifier(`${field.name}_${field.values.join("_")}_t`)} {\n\t${field.values.map((v) => quoteIdentifier(v)).join("\n\t")}\n}\n\n`;
} }
} }
} }
@@ -115,17 +127,17 @@ export function toDBML(diagram) {
return `${diagram.enums return `${diagram.enums
.map( .map(
(en) => (en) =>
`enum ${en.name} {\n${en.values.map((v) => `\t${v}`).join("\n")}\n}\n\n`, `enum ${quoteIdentifier(en.name)} {\n${en.values.map((v) => `\t${quoteIdentifier(v)}`).join("\n")}\n}\n\n`,
) )
.join("\n\n")}${enumDefinitions}${diagram.tables .join("\n\n")}${enumDefinitions}${diagram.tables
.map( .map(
(table) => (table) =>
`Table ${table.name} [headercolor: ${table.color}] {\n${table.fields `Table ${quoteIdentifier(table.name)} [headercolor: ${table.color}] {\n${table.fields
.map( .map(
(field) => (field) =>
`\t${field.name} ${ `\t${quoteIdentifier(field.name)} ${
field.type === "ENUM" || field.type === "SET" field.type === "ENUM" || field.type === "SET"
? `${field.name}_${field.values.join("_")}_t` ? quoteIdentifier(`${field.name}_${field.values.join("_")}_t`)
: field.type.toLowerCase() : field.type.toLowerCase()
}${fieldSize( }${fieldSize(
field, field,
@@ -138,7 +150,9 @@ export function toDBML(diagram) {
table.indices table.indices
.map( .map(
(index) => (index) =>
`\t\t(${index.fields.join(", ")}) [ name: '${ `\t\t(${index.fields
.map((f) => quoteIdentifier(f))
.join(", ")}) [ name: '${
index.name index.name
}'${index.unique ? ", unique" : ""} ]`, }'${index.unique ? ", unique" : ""} ]`,
) )