Export sqlite
This commit is contained in:
parent
9c31e2be52
commit
73dff50f14
@ -29,7 +29,7 @@ import {
|
||||
jsonToSQLite,
|
||||
jsonToMariaDB,
|
||||
jsonToSQLServer,
|
||||
} from "../../utils/toSQL";
|
||||
} from "../../utils/exportSQL/generic";
|
||||
import {
|
||||
ObjectType,
|
||||
Action,
|
||||
@ -37,6 +37,7 @@ import {
|
||||
State,
|
||||
MODAL,
|
||||
SIDESHEET,
|
||||
DB,
|
||||
} from "../../data/constants";
|
||||
import jsPDF from "jspdf";
|
||||
import { useHotkeys } from "react-hotkeys-hook";
|
||||
@ -62,6 +63,7 @@ import LayoutDropdown from "./LayoutDropdown";
|
||||
import Sidesheet from "./SideSheet/Sidesheet";
|
||||
import Modal from "./Modal/Modal";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { exportSQL } from "../../utils/exportSQL";
|
||||
|
||||
export default function ControlPanel({
|
||||
diagramId,
|
||||
@ -851,6 +853,7 @@ export default function ControlPanel({
|
||||
function: () => {},
|
||||
},
|
||||
export_source: {
|
||||
...(database === DB.GENERIC && {
|
||||
children: [
|
||||
{
|
||||
MySQL: () => {
|
||||
@ -933,7 +936,22 @@ export default function ControlPanel({
|
||||
},
|
||||
},
|
||||
],
|
||||
function: () => {},
|
||||
}),
|
||||
function: () => {
|
||||
if (database === DB.GENERIC) return;
|
||||
setModal(MODAL.CODE);
|
||||
const src = exportSQL({
|
||||
tables: tables,
|
||||
references: relationships,
|
||||
types: types,
|
||||
database: database,
|
||||
});
|
||||
setExportData((prev) => ({
|
||||
...prev,
|
||||
data: src,
|
||||
extension: "sql",
|
||||
}));
|
||||
},
|
||||
},
|
||||
exit: {
|
||||
function: () => {
|
||||
|
@ -98,6 +98,7 @@ export const defaultTypes = {
|
||||
isSized: true,
|
||||
hasPrecision: false,
|
||||
defaultSize: 1,
|
||||
hasQuotes: true,
|
||||
},
|
||||
VARCHAR: {
|
||||
type: "VARCHAR",
|
||||
@ -111,6 +112,7 @@ export const defaultTypes = {
|
||||
isSized: true,
|
||||
hasPrecision: false,
|
||||
defaultSize: 255,
|
||||
hasQuotes: true,
|
||||
},
|
||||
TEXT: {
|
||||
type: "TEXT",
|
||||
@ -119,16 +121,7 @@ export const defaultTypes = {
|
||||
isSized: true,
|
||||
hasPrecision: false,
|
||||
defaultSize: 65535,
|
||||
},
|
||||
DATE: {
|
||||
type: "DATE",
|
||||
checkDefault: (field) => {
|
||||
return /^\d{4}-\d{2}-\d{2}$/.test(field.default);
|
||||
},
|
||||
hasCheck: false,
|
||||
isSized: false,
|
||||
hasPrecision: false,
|
||||
defaultSize: null,
|
||||
hasQuotes: true,
|
||||
},
|
||||
TIME: {
|
||||
type: "TIME",
|
||||
@ -139,6 +132,7 @@ export const defaultTypes = {
|
||||
isSized: false,
|
||||
hasPrecision: false,
|
||||
defaultSize: null,
|
||||
hasQuotes: true,
|
||||
},
|
||||
TIMESTAMP: {
|
||||
type: "TIMESTAMP",
|
||||
@ -157,6 +151,18 @@ export const defaultTypes = {
|
||||
isSized: false,
|
||||
hasPrecision: false,
|
||||
defaultSize: null,
|
||||
hasQuotes: true,
|
||||
},
|
||||
DATE: {
|
||||
type: "DATE",
|
||||
checkDefault: (field) => {
|
||||
return /^\d{4}-\d{2}-\d{2}$/.test(field.default);
|
||||
},
|
||||
hasCheck: false,
|
||||
isSized: false,
|
||||
hasPrecision: false,
|
||||
defaultSize: null,
|
||||
hasQuotes: true,
|
||||
},
|
||||
DATETIME: {
|
||||
type: "DATETIME",
|
||||
@ -175,6 +181,7 @@ export const defaultTypes = {
|
||||
isSized: false,
|
||||
hasPrecision: false,
|
||||
defaultSize: null,
|
||||
hasQuotes: true,
|
||||
},
|
||||
BOOLEAN: {
|
||||
type: "BOOLEAN",
|
||||
@ -200,6 +207,7 @@ export const defaultTypes = {
|
||||
isSized: true,
|
||||
hasPrecision: false,
|
||||
defaultSize: 1,
|
||||
hasQuotes: true,
|
||||
},
|
||||
VARBINARY: {
|
||||
type: "VARBINARY",
|
||||
@ -212,6 +220,7 @@ export const defaultTypes = {
|
||||
isSized: true,
|
||||
hasPrecision: false,
|
||||
defaultSize: 255,
|
||||
hasQuotes: true,
|
||||
},
|
||||
BLOB: {
|
||||
type: "BLOB",
|
||||
@ -246,6 +255,7 @@ export const defaultTypes = {
|
||||
isSized: false,
|
||||
hasPrecision: false,
|
||||
defaultSize: null,
|
||||
hasQuotes: true,
|
||||
},
|
||||
SET: {
|
||||
type: "SET",
|
||||
@ -356,16 +366,126 @@ export const postgresTypes = {
|
||||
};
|
||||
|
||||
export const sqliteTypes = {
|
||||
INTEGER: { type: "INTEGER", checkDefault: (field) => {} },
|
||||
REAL: { type: "REAL", checkDefault: (field) => {} },
|
||||
TEXT: { type: "TEXT", checkDefault: (field) => {} },
|
||||
BLOB: { type: "BLOB", checkDefault: (field) => {} },
|
||||
NUMERIC: { type: "NUMERIC", checkDefault: (field) => {} },
|
||||
BOOLEAN: { type: "BOOLEAN", checkDefault: (field) => {} },
|
||||
DATE: { type: "DATE", checkDefault: (field) => {} },
|
||||
DATETIME: { type: "DATETIME", checkDefault: (field) => {} },
|
||||
TIME: { type: "TIME", checkDefault: (field) => {} },
|
||||
TIMESTAMP: { type: "TIMESTAMP", checkDefault: (field) => {} },
|
||||
INT: {
|
||||
type: "INT",
|
||||
checkDefault: (field) => {
|
||||
return intRegex.test(field.default);
|
||||
},
|
||||
hasCheck: true,
|
||||
isSized: false,
|
||||
hasPrecision: false,
|
||||
defaultSize: null,
|
||||
},
|
||||
REAL: {
|
||||
type: "REAL",
|
||||
checkDefault: (field) => {
|
||||
return doubleRegex.test(field.default);
|
||||
},
|
||||
hasCheck: true,
|
||||
isSized: false,
|
||||
hasPrecision: true,
|
||||
defaultSize: null,
|
||||
},
|
||||
TEXT: {
|
||||
type: "TEXT",
|
||||
checkDefault: (field) => false,
|
||||
hasCheck: false,
|
||||
isSized: true,
|
||||
hasPrecision: false,
|
||||
defaultSize: 65535,
|
||||
hasQuotes: true,
|
||||
},
|
||||
BLOB: {
|
||||
type: "BLOB",
|
||||
checkDefault: (field) => false,
|
||||
isSized: false,
|
||||
hasCheck: false,
|
||||
hasPrecision: false,
|
||||
defaultSize: null,
|
||||
},
|
||||
NUMERIC: {
|
||||
type: "NUMERIC",
|
||||
checkDefault: (field) => {
|
||||
return doubleRegex.test(field.default);
|
||||
},
|
||||
hasCheck: true,
|
||||
isSized: false,
|
||||
hasPrecision: true,
|
||||
defaultSize: null,
|
||||
},
|
||||
BOOLEAN: {
|
||||
type: "BOOLEAN",
|
||||
checkDefault: (field) => {
|
||||
return (
|
||||
field.default.trim().toLowerCase() === "false" ||
|
||||
field.default.trim().toLowerCase() === "true"
|
||||
);
|
||||
},
|
||||
hasCheck: false,
|
||||
isSized: false,
|
||||
hasPrecision: false,
|
||||
defaultSize: null,
|
||||
},
|
||||
TIME: {
|
||||
type: "TIME",
|
||||
checkDefault: (field) => {
|
||||
return /^(?:[01]?\d|2[0-3]):[0-5]?\d:[0-5]?\d$/.test(field.default);
|
||||
},
|
||||
hasCheck: false,
|
||||
isSized: false,
|
||||
hasPrecision: false,
|
||||
defaultSize: null,
|
||||
hasQuotes: true,
|
||||
},
|
||||
TIMESTAMP: {
|
||||
type: "TIMESTAMP",
|
||||
checkDefault: (field) => {
|
||||
if (field.default.toUpperCase() === "CURRENT_TIMESTAMP") {
|
||||
return true;
|
||||
}
|
||||
if (!/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(field.default)) {
|
||||
return false;
|
||||
}
|
||||
const content = field.default.split(" ");
|
||||
const date = content[0].split("-");
|
||||
return parseInt(date[0]) >= 1970 && parseInt(date[0]) <= 2038;
|
||||
},
|
||||
hasCheck: false,
|
||||
isSized: false,
|
||||
hasPrecision: false,
|
||||
defaultSize: null,
|
||||
hasQuotes: true,
|
||||
},
|
||||
DATE: {
|
||||
type: "DATE",
|
||||
checkDefault: (field) => {
|
||||
return /^\d{4}-\d{2}-\d{2}$/.test(field.default);
|
||||
},
|
||||
hasCheck: false,
|
||||
isSized: false,
|
||||
hasPrecision: false,
|
||||
defaultSize: null,
|
||||
hasQuotes: true,
|
||||
},
|
||||
DATETIME: {
|
||||
type: "DATETIME",
|
||||
checkDefault: (field) => {
|
||||
if (field.default.toUpperCase() === "CURRENT_TIMESTAMP") {
|
||||
return true;
|
||||
}
|
||||
if (!/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(field.default)) {
|
||||
return false;
|
||||
}
|
||||
const c = field.default.split(" ");
|
||||
const d = c[0].split("-");
|
||||
return parseInt(d[0]) >= 1000 && parseInt(d[0]) <= 9999;
|
||||
},
|
||||
hasCheck: false,
|
||||
isSized: false,
|
||||
hasPrecision: false,
|
||||
defaultSize: null,
|
||||
hasQuotes: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const mariadbTypes = {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { dbToTypes, defaultTypes } from "../data/datatypes";
|
||||
import { isFunction, isKeyword, strHasQuotes } from "./utils";
|
||||
import { dbToTypes, defaultTypes } from "../../data/datatypes";
|
||||
import { parseDefault } from "./shared";
|
||||
|
||||
export function getJsonType(f) {
|
||||
if (!Object.keys(defaultTypes).includes(f.type)) {
|
||||
@ -137,33 +137,6 @@ export function getTypeString(
|
||||
}
|
||||
}
|
||||
|
||||
export function hasQuotes(type) {
|
||||
return [
|
||||
"CHAR",
|
||||
"VARCHAR",
|
||||
"BINARY",
|
||||
"VARBINARY",
|
||||
"ENUM",
|
||||
"DATE",
|
||||
"TIME",
|
||||
"TIMESTAMP",
|
||||
"DATETIME",
|
||||
].includes(type);
|
||||
}
|
||||
|
||||
export function parseDefault(field) {
|
||||
if (
|
||||
strHasQuotes(field.default) ||
|
||||
isFunction(field.default) ||
|
||||
isKeyword(field.default) ||
|
||||
!hasQuotes(field.type)
|
||||
) {
|
||||
return field.default;
|
||||
}
|
||||
|
||||
return `'${field.default}'`;
|
||||
}
|
||||
|
||||
export function jsonToMySQL(obj) {
|
||||
return `${obj.tables
|
||||
.map(
|
||||
@ -178,7 +151,7 @@ export function jsonToMySQL(obj) {
|
||||
}\` ${getTypeString(field, obj.database)}${field.notNull ? " NOT NULL" : ""}${
|
||||
field.increment ? " AUTO_INCREMENT" : ""
|
||||
}${field.unique ? " UNIQUE" : ""}${
|
||||
field.default !== "" ? ` DEFAULT ${parseDefault(field)}` : ""
|
||||
field.default !== "" ? ` DEFAULT ${parseDefault(field, obj.database)}` : ""
|
||||
}${
|
||||
field.check === "" ||
|
||||
!dbToTypes[obj.database][field.type].hasCheck
|
||||
@ -277,7 +250,7 @@ export function jsonToPostgreSQL(obj) {
|
||||
}" ${getTypeString(field, obj.database, "postgres")}${
|
||||
field.notNull ? " NOT NULL" : ""
|
||||
}${
|
||||
field.default !== "" ? ` DEFAULT ${parseDefault(field)}` : ""
|
||||
field.default !== "" ? ` DEFAULT ${parseDefault(field, obj.database)}` : ""
|
||||
}${
|
||||
field.check === "" ||
|
||||
!dbToTypes[obj.database][field.type].hasCheck
|
||||
@ -378,7 +351,7 @@ export function jsonToSQLite(obj) {
|
||||
field.name
|
||||
}" ${getSQLiteType(field)}${field.notNull ? " NOT NULL" : ""}${
|
||||
field.unique ? " UNIQUE" : ""
|
||||
}${field.default !== "" ? ` DEFAULT ${parseDefault(field)}` : ""}${
|
||||
}${field.default !== "" ? ` DEFAULT ${parseDefault(field, obj.database)}` : ""}${
|
||||
field.check === "" ||
|
||||
!dbToTypes[obj.database][field.type].hasCheck
|
||||
? ""
|
||||
@ -424,7 +397,7 @@ export function jsonToMariaDB(obj) {
|
||||
}\` ${getTypeString(field, obj.database)}${field.notNull ? " NOT NULL" : ""}${
|
||||
field.increment ? " AUTO_INCREMENT" : ""
|
||||
}${field.unique ? " UNIQUE" : ""}${
|
||||
field.default !== "" ? ` DEFAULT ${parseDefault(field)}` : ""
|
||||
field.default !== "" ? ` DEFAULT ${parseDefault(field, obj.database)}` : ""
|
||||
}${
|
||||
field.check === "" ||
|
||||
!dbToTypes[obj.database][field.type].hasCheck
|
||||
@ -498,7 +471,7 @@ export function jsonToSQLServer(obj) {
|
||||
}${field.increment ? " IDENTITY" : ""}${
|
||||
field.unique ? " UNIQUE" : ""
|
||||
}${
|
||||
field.default !== "" ? ` DEFAULT ${parseDefault(field)}` : ""
|
||||
field.default !== "" ? ` DEFAULT ${parseDefault(field, obj.database)}` : ""
|
||||
}${
|
||||
field.check === "" ||
|
||||
!dbToTypes[obj.database][field.type].hasCheck
|
19
src/utils/exportSQL/index.js
Normal file
19
src/utils/exportSQL/index.js
Normal file
@ -0,0 +1,19 @@
|
||||
import { DB } from "../../data/constants";
|
||||
import { toSqlite } from "./sqlite";
|
||||
|
||||
export function exportSQL(diagram) {
|
||||
switch (diagram.database) {
|
||||
case DB.SQLITE:
|
||||
return toSqlite(diagram);
|
||||
case DB.MYSQL:
|
||||
return "hi from mysql";
|
||||
case DB.POSTGRES:
|
||||
return "hi from postgres";
|
||||
case DB.MARIADB:
|
||||
return "hi from mariadb";
|
||||
case DB.MSSQL:
|
||||
return "hi from mssql";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
16
src/utils/exportSQL/shared.js
Normal file
16
src/utils/exportSQL/shared.js
Normal file
@ -0,0 +1,16 @@
|
||||
import { DB } from "../../data/constants";
|
||||
import { dbToTypes } from "../../data/datatypes";
|
||||
import { isFunction, isKeyword, strHasQuotes } from "../utils";
|
||||
|
||||
export function parseDefault(field, database = DB.GENERIC) {
|
||||
if (
|
||||
strHasQuotes(field.default) ||
|
||||
isFunction(field.default) ||
|
||||
isKeyword(field.default) ||
|
||||
!dbToTypes[database][field.type].hasQuotes
|
||||
) {
|
||||
return field.default;
|
||||
}
|
||||
|
||||
return `'${field.default}'`;
|
||||
}
|
62
src/utils/exportSQL/sqlite.js
Normal file
62
src/utils/exportSQL/sqlite.js
Normal file
@ -0,0 +1,62 @@
|
||||
import { dbToTypes } from "../../data/datatypes";
|
||||
import { parseDefault } from "./shared";
|
||||
|
||||
export function toSqlite(diagram) {
|
||||
return diagram.tables
|
||||
.map((table) => {
|
||||
const inlineFK = getInlineFK(table, diagram);
|
||||
return `${
|
||||
table.comment === "" ? "" : `/* ${table.comment} */\n`
|
||||
}CREATE TABLE IF NOT EXISTS "${table.name}" (\n${table.fields
|
||||
.map(
|
||||
(field) =>
|
||||
`${field.comment === "" ? "" : `\t-- ${field.comment}\n`}\t"${
|
||||
field.name
|
||||
}" ${field.type}${field.notNull ? " NOT NULL" : ""}${
|
||||
field.unique ? " UNIQUE" : ""
|
||||
}${field.default !== "" ? ` DEFAULT ${parseDefault(field, diagram.database)}` : ""}${
|
||||
field.check === "" ||
|
||||
!dbToTypes[diagram.database][field.type].hasCheck
|
||||
? ""
|
||||
: ` CHECK(${field.check})`
|
||||
}`,
|
||||
)
|
||||
.join(",\n")}${
|
||||
table.fields.filter((f) => f.primary).length > 0
|
||||
? `,\n\tPRIMARY KEY(${table.fields
|
||||
.filter((f) => f.primary)
|
||||
.map((f) => `"${f.name}"`)
|
||||
.join(", ")})${inlineFK !== "" ? ",\n" : ""}`
|
||||
: ""
|
||||
}\t${inlineFK}\n);\n${
|
||||
table.indices.length > 0
|
||||
? `${table.indices
|
||||
.map(
|
||||
(i) =>
|
||||
`\nCREATE ${i.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS "${
|
||||
i.name
|
||||
}"\nON "${table.name}" (${i.fields
|
||||
.map((f) => `"${f}"`)
|
||||
.join(", ")});`,
|
||||
)
|
||||
.join("\n")}`
|
||||
: ""
|
||||
}`;
|
||||
})
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
export function getInlineFK(table, obj) {
|
||||
let fk = "";
|
||||
obj.references.forEach((r) => {
|
||||
if (fk !== "") return;
|
||||
if (r.startTableId === table.id) {
|
||||
fk = `FOREIGN KEY ("${table.fields[r.startFieldId].name}") REFERENCES "${
|
||||
obj.tables[r.endTableId].name
|
||||
}"("${
|
||||
obj.tables[r.endTableId].fields[r.endFieldId].name
|
||||
}")\n\tON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()}`;
|
||||
}
|
||||
});
|
||||
return fk;
|
||||
}
|
Loading…
Reference in New Issue
Block a user