Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions src/components/EditorHeader/Modal/Modal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -102,16 +102,41 @@ export default function Modal({
const parseSQLAndLoadDiagram = () => {
const targetDatabase = database === DB.GENERIC ? importDb : database;

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,
`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;
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,
});
}
Expand Down
2 changes: 2 additions & 0 deletions src/data/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ export const SIDESHEET = {
VERSIONS: 2,
};

export const EMPTY_ENUM_PLACEHOLDER = "_placeholder";

export const DB = {
MYSQL: "mysql",
POSTGRES: "postgresql",
Expand Down
20 changes: 13 additions & 7 deletions src/utils/exportSQL/postgres.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { escapeQuotes, exportFieldComment, parseDefault } from "./shared";
import { EMPTY_ENUM_PLACEHOLDER } from "../../data/constants";
import {
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
Expand Down
4 changes: 2 additions & 2 deletions src/utils/importSQL/postgres.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)) {
Expand Down
Loading