From a3cf62ed1602385f338becb339653c351f048fde Mon Sep 17 00:00:00 2001 From: Korcakov Roman <9306861+Yaksinikos@users.noreply.github.com> Date: Tue, 19 May 2026 22:13:01 +0200 Subject: [PATCH 1/4] fixing partial #540 (added enum placeholder on export ) --- src/components/EditorHeader/Modal/Modal.jsx | 14 +++++++++++--- src/data/constants.js | 2 ++ src/utils/exportSQL/postgres.js | 21 ++++++++++++++------- src/utils/exportSQL/shared.js | 5 +++++ src/utils/importSQL/postgres.js | 2 +- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/components/EditorHeader/Modal/Modal.jsx b/src/components/EditorHeader/Modal/Modal.jsx index fb7ff8f01..94586e6c4 100644 --- a/src/components/EditorHeader/Modal/Modal.jsx +++ b/src/components/EditorHeader/Modal/Modal.jsx @@ -4,7 +4,7 @@ import { Parser } from "node-sql-parser"; import { Parser as OracleParser } from "oracle-sql-parser"; import { useState } from "react"; import { useTranslation } from "react-i18next"; -import { DB, MODAL, STATUS } from "../../../data/constants"; +import { DB, EMPTY_ENUM_PLACEHOLDER, MODAL, STATUS } from "../../../data/constants"; import { databases } from "../../../data/databases"; import { useAreas, @@ -102,16 +102,24 @@ export default function Modal({ const parseSQLAndLoadDiagram = () => { const targetDatabase = database === DB.GENERIC ? importDb : database; + let normalizedSql = importSource.src; + if (targetDatabase === DB.POSTGRES) { + normalizedSql = normalizedSql.replace( + /CREATE\s+TYPE\s+"([^"]+)"\s+AS\s+ENUM\s*\(\s*\)\s*;/gi, + `CREATE TYPE "$1" AS ENUM ('${EMPTY_ENUM_PLACEHOLDER}');`, + ); + } + let ast = null; try { if (targetDatabase === DB.ORACLESQL) { const oracleParser = new OracleParser(); - ast = oracleParser.parse(importSource.src); + ast = oracleParser.parse(normalizedSql); } else { const parser = new Parser(); - ast = parser.astify(importSource.src, { + ast = parser.astify(normalizedSql, { database: targetDatabase, }); } diff --git a/src/data/constants.js b/src/data/constants.js index c56a68f68..02e363d36 100644 --- a/src/data/constants.js +++ b/src/data/constants.js @@ -103,6 +103,8 @@ export const SIDESHEET = { VERSIONS: 2, }; +export const EMPTY_ENUM_PLACEHOLDER = "_placeholder"; + export const DB = { MYSQL: "mysql", POSTGRES: "postgresql", diff --git a/src/utils/exportSQL/postgres.js b/src/utils/exportSQL/postgres.js index 3dc6c0e13..63e9affdf 100644 --- a/src/utils/exportSQL/postgres.js +++ b/src/utils/exportSQL/postgres.js @@ -1,14 +1,21 @@ -import { escapeQuotes, exportFieldComment, parseDefault } from "./shared"; +import { EMPTY_ENUM_PLACEHOLDER } from "../../data/constants"; +import { + enumValuesForExport, + escapeQuotes, + exportFieldComment, + parseDefault, +} from "./shared"; import { dbToTypes } from "../../data/datatypes"; export function toPostgres(diagram) { const enumStatements = diagram.enums - .map( - (e) => - `CREATE TYPE "${e.name}" AS ENUM (\n${e.values - .map((v) => `\t'${v}'`) - .join(",\n")}\n);\n`, - ) + .map((e) => { + const values = + e.values?.length > 0 ? e.values : [EMPTY_ENUM_PLACEHOLDER]; + return `CREATE TYPE "${e.name}" AS ENUM (\n${values + .map((v) => `\t'${escapeQuotes(v)}'`) + .join(",\n")}\n);\n`; + }) .join("\n"); const typeStatements = diagram.types diff --git a/src/utils/exportSQL/shared.js b/src/utils/exportSQL/shared.js index 64100bc7f..5cbd52305 100644 --- a/src/utils/exportSQL/shared.js +++ b/src/utils/exportSQL/shared.js @@ -1,8 +1,13 @@ +import { EMPTY_ENUM_PLACEHOLDER } from "../../data/constants"; import { isFunction, isKeyword } from "../utils"; import { DB } from "../../data/constants"; import { dbToTypes } from "../../data/datatypes"; +export function enumValuesForExport(values) { + return values?.length > 0 ? values : [EMPTY_ENUM_PLACEHOLDER]; +} + export function parseDefault(field, database = DB.GENERIC) { if ( isFunction(field.default) || diff --git a/src/utils/importSQL/postgres.js b/src/utils/importSQL/postgres.js index 66103769c..ec7d11f14 100644 --- a/src/utils/importSQL/postgres.js +++ b/src/utils/importSQL/postgres.js @@ -257,7 +257,7 @@ export function fromPostgres(ast, diagramDb = DB.GENERIC) { if (e.resource === "enum") { const newEnum = { name: e.name.name, - values: e.create_definitions.value.map((x) => x.value), + values: (e.create_definitions?.value ?? []).map((x) => x.value), }; enums.push(newEnum); } else if (Array.isArray(e.create_definitions)) { From f6644e0d50efa591930702b62cfb127a88ed2338 Mon Sep 17 00:00:00 2001 From: Korcakov Roman <9306861+Yaksinikos@users.noreply.github.com> Date: Tue, 19 May 2026 22:28:20 +0200 Subject: [PATCH 2/4] trying to fix initial #540 issue by implicating generated_by_default and fixing enum issue by forcing to export them before usage; --- src/components/EditorHeader/Modal/Modal.jsx | 12 ++++++++++++ src/utils/importSQL/postgres.js | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/components/EditorHeader/Modal/Modal.jsx b/src/components/EditorHeader/Modal/Modal.jsx index 94586e6c4..b1c09ec33 100644 --- a/src/components/EditorHeader/Modal/Modal.jsx +++ b/src/components/EditorHeader/Modal/Modal.jsx @@ -104,10 +104,22 @@ export default function Modal({ let normalizedSql = importSource.src; if (targetDatabase === DB.POSTGRES) { + // Fix empty ENUM () which crashes node-sql-parser normalizedSql = normalizedSql.replace( /CREATE\s+TYPE\s+"([^"]+)"\s+AS\s+ENUM\s*\(\s*\)\s*;/gi, `CREATE TYPE "$1" AS ENUM ('${EMPTY_ENUM_PLACEHOLDER}');`, ); + + // Hoist CREATE TYPE statements to the top so enum types are + // defined before any table that references them + const typeStatements = + normalizedSql.match(/CREATE\s+TYPE\s+[^;]+;/gi) || []; + if (typeStatements.length > 0) { + const rest = normalizedSql + .replace(/CREATE\s+TYPE\s+[^;]+;/gi, '') + .trim(); + normalizedSql = [...typeStatements, rest].filter(Boolean).join('\n'); + } } let ast = null; diff --git a/src/utils/importSQL/postgres.js b/src/utils/importSQL/postgres.js index ec7d11f14..d7fdb0bf7 100644 --- a/src/utils/importSQL/postgres.js +++ b/src/utils/importSQL/postgres.js @@ -65,7 +65,7 @@ export function fromPostgres(ast, diagramDb = DB.GENERIC) { field.unique = false; if (d.unique) field.unique = true; field.increment = false; - if (d.auto_increment) field.increment = true; + if (d.auto_increment || d.generated_by_default) field.increment = true; field.notNull = false; if (d.nullable) field.notNull = true; field.primary = false; From a950854c32f363177ec73b8ec064e82a53f601d4 Mon Sep 17 00:00:00 2001 From: Korcakov Roman <9306861+Yaksinikos@users.noreply.github.com> Date: Tue, 19 May 2026 22:42:35 +0200 Subject: [PATCH 3/4] added comments ignoring for PostgreSQL; --- src/components/EditorHeader/Modal/Modal.jsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/EditorHeader/Modal/Modal.jsx b/src/components/EditorHeader/Modal/Modal.jsx index b1c09ec33..85d414f3c 100644 --- a/src/components/EditorHeader/Modal/Modal.jsx +++ b/src/components/EditorHeader/Modal/Modal.jsx @@ -104,6 +104,11 @@ export default function Modal({ let normalizedSql = importSource.src; if (targetDatabase === DB.POSTGRES) { + // Strip block comments /* ... */ + normalizedSql = normalizedSql.replace(/\/\*[\s\S]*?\*\//g, ''); + // Strip line comments -- ... + normalizedSql = normalizedSql.replace(/--.*$/gm, ''); + // Fix empty ENUM () which crashes node-sql-parser normalizedSql = normalizedSql.replace( /CREATE\s+TYPE\s+"([^"]+)"\s+AS\s+ENUM\s*\(\s*\)\s*;/gi, From 0ddcfdbdef7d3bb3391ee82d696eca10494ec342 Mon Sep 17 00:00:00 2001 From: Korcakov Roman <9306861+Yaksinikos@users.noreply.github.com> Date: Tue, 19 May 2026 22:50:20 +0200 Subject: [PATCH 4/4] remove obsolete function --- src/utils/exportSQL/postgres.js | 1 - src/utils/exportSQL/shared.js | 5 ----- 2 files changed, 6 deletions(-) diff --git a/src/utils/exportSQL/postgres.js b/src/utils/exportSQL/postgres.js index 63e9affdf..20dd36ba5 100644 --- a/src/utils/exportSQL/postgres.js +++ b/src/utils/exportSQL/postgres.js @@ -1,6 +1,5 @@ import { EMPTY_ENUM_PLACEHOLDER } from "../../data/constants"; import { - enumValuesForExport, escapeQuotes, exportFieldComment, parseDefault, diff --git a/src/utils/exportSQL/shared.js b/src/utils/exportSQL/shared.js index 5cbd52305..64100bc7f 100644 --- a/src/utils/exportSQL/shared.js +++ b/src/utils/exportSQL/shared.js @@ -1,13 +1,8 @@ -import { EMPTY_ENUM_PLACEHOLDER } from "../../data/constants"; import { isFunction, isKeyword } from "../utils"; import { DB } from "../../data/constants"; import { dbToTypes } from "../../data/datatypes"; -export function enumValuesForExport(values) { - return values?.length > 0 ? values : [EMPTY_ENUM_PLACEHOLDER]; -} - export function parseDefault(field, database = DB.GENERIC) { if ( isFunction(field.default) ||