From 8e85ba4e291e9dd9fcd9ce0819ead9b782491612 Mon Sep 17 00:00:00 2001 From: Vlasislav Kashin <99754299+vloldik@users.noreply.github.com> Date: Wed, 15 Oct 2025 00:25:22 +0300 Subject: [PATCH] Add basic schema support for DDL export --- src/utils/exportSQL/postgres.js | 46 ++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/utils/exportSQL/postgres.js b/src/utils/exportSQL/postgres.js index 3dc6c0e1..159cec40 100644 --- a/src/utils/exportSQL/postgres.js +++ b/src/utils/exportSQL/postgres.js @@ -1,11 +1,36 @@ import { escapeQuotes, exportFieldComment, parseDefault } from "./shared"; import { dbToTypes } from "../../data/datatypes"; +const getSchemaAndName = (ident) => { + if (ident.includes('.')) { + return ident.split('.', 2) + } + + return ["public", ident] +} + +/** + * @param {string} ident + */ +const formatWithSchema = (ident) => { + const [schema, name] = getSchemaAndName(ident) + return `"${schema}"."${name}"` +} + export function toPostgres(diagram) { + const schemas = new Set() + const schemaSources = [...diagram.types, ...diagram.enums, ...diagram.tables] + schemaSources.forEach((v) => { + const [schema] = getSchemaAndName(v.name) + schemas.add(schema) + }) + const schemaStatements = [...schemas].map((s) => { + return `CREATE SCHEMA IF NOT EXISTS "${s}"` + }).join(";\n") + ";\n\n" const enumStatements = diagram.enums .map( (e) => - `CREATE TYPE "${e.name}" AS ENUM (\n${e.values + `CREATE TYPE ${formatWithSchema(e.name)} AS ENUM (\n${e.values .map((v) => `\t'${v}'`) .join(",\n")}\n);\n`, ) @@ -14,11 +39,11 @@ export function toPostgres(diagram) { const typeStatements = diagram.types .map( (type) => - `CREATE TYPE ${type.name} AS (\n${type.fields + `CREATE TYPE ${formatWithSchema(type.name)} AS (\n${type.fields .map((f) => `\t${f.name} ${f.type}`) .join(",\n")}\n);\n\n${ type.comment?.trim() - ? `COMMENT ON TYPE "${type.name}" IS '${escapeQuotes(type.comment)}';\n` + ? `COMMENT ON TYPE ${formatWithSchema(type.name)} IS '${escapeQuotes(type.comment)}';\n` : "" }`, ) @@ -28,7 +53,7 @@ export function toPostgres(diagram) { .map((table) => { const inheritsClause = Array.isArray(table.inherits) && table.inherits.length > 0 - ? `\n) INHERITS (${table.inherits.map((parent) => `"${parent}"`).join(", ")})` + ? `\n) INHERITS (${table.inherits.map((parent) => formatWithSchema(parent)).join(", ")})` : "\n)"; const fieldDefinitions = table.fields @@ -41,7 +66,7 @@ export function toPostgres(diagram) { }${field.isArray ? " ARRAY" : ""}${field.notNull ? " NOT NULL" : ""}${ field.unique ? " UNIQUE" : "" }${field.increment ? " GENERATED BY DEFAULT AS IDENTITY" : ""}${ - field.default?.trim() + field.default && field.default?.trim() ? ` DEFAULT ${parseDefault(field, diagram.database)}` : "" }${ @@ -61,12 +86,12 @@ export function toPostgres(diagram) { const commentStatements = [ table.comment?.trim() - ? `COMMENT ON TABLE "${table.name}" IS '${escapeQuotes(table.comment)}';` + ? `COMMENT ON TABLE ${formatWithSchema(table.name)} IS '${escapeQuotes(table.comment)}';` : "", ...table.fields .map((field) => field.comment?.trim() - ? `COMMENT ON COLUMN "${table.name}"."${field.name}" IS '${escapeQuotes(field.comment)}';` + ? `COMMENT ON COLUMN ${formatWithSchema(table.name)}."${field.name}" IS '${escapeQuotes(field.comment)}';` : "", ) .filter(Boolean), @@ -75,13 +100,13 @@ export function toPostgres(diagram) { const indexStatements = table.indices .map( (i) => - `CREATE ${i.unique ? "UNIQUE " : ""}INDEX "${i.name}"\nON "${table.name}" (${i.fields + `CREATE ${i.unique ? "UNIQUE " : ""}INDEX "${i.name}"\nON ${formatWithSchema(table.name)} (${i.fields .map((f) => `"${f}"`) .join(", ")});`, ) .join("\n"); - return `CREATE TABLE IF NOT EXISTS "${table.name}" (\n${fieldDefinitions}${primaryKeyClause}${inheritsClause};\n\n${commentStatements}\n${indexStatements}`; + return `CREATE TABLE IF NOT EXISTS ${formatWithSchema(table.name)} (\n${fieldDefinitions}${primaryKeyClause}${inheritsClause};\n\n${commentStatements}\n${indexStatements}`; }) .join("\n\n"); @@ -96,12 +121,13 @@ export function toPostgres(diagram) { if (!startTable || !endTable || !startField || !endField) return ""; - return `ALTER TABLE "${startTable.name}"\nADD FOREIGN KEY("${startField.name}") REFERENCES "${endTable.name}"("${endField.name}")\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};`; + return `ALTER TABLE ${formatWithSchema(startTable.name)}\nADD FOREIGN KEY("${startField.name}") REFERENCES ${formatWithSchema(endTable.name)}("${endField.name}")\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};`; }) .filter(Boolean) .join("\n"); return [ + schemaStatements, enumStatements, enumStatements.trim() && typeStatements ? "\n" + typeStatements