mirror of
https://github.com/drawdb-io/drawdb.git
synced 2025-05-24 18:39:12 +00:00
feat: add db engines conversions for postresql, mysql, sqlite
This commit is contained in:
parent
3d6a4fcbb5
commit
a1d6c829a2
@ -74,6 +74,7 @@ import { isRtl } from "../../i18n/utils/rtl";
|
||||
import { jsonToDocumentation } from "../../utils/exportAs/documentation";
|
||||
import { IdContext } from "../Workspace";
|
||||
import DatabasesSwitcher from "./DatabasesSwitcher";
|
||||
import { convertTableSchema } from "../../utils/typesMappings";
|
||||
|
||||
export default function ControlPanel({
|
||||
diagramId,
|
||||
@ -109,6 +110,7 @@ export default function ControlPanel({
|
||||
deleteRelationship,
|
||||
database,
|
||||
} = useDiagram();
|
||||
const [prevDatabase, setPrevDatabase] = useState(database);
|
||||
const { enums, setEnums, deleteEnum, addEnum, updateEnum } = useEnums();
|
||||
const { types, addType, deleteType, updateType, setTypes } = useTypes();
|
||||
const { notes, setNotes, updateNote, addNote, deleteNote } = useNotes();
|
||||
@ -925,8 +927,9 @@ export default function ControlPanel({
|
||||
function: () => {
|
||||
if (database === DB.GENERIC) return;
|
||||
setModal(MODAL.CODE);
|
||||
const newTables = tables.map(table => convertTableSchema(table, prevDatabase, database));
|
||||
const src = exportSQL({
|
||||
tables: tables,
|
||||
tables: newTables,
|
||||
references: relationships,
|
||||
types: types,
|
||||
database: database,
|
||||
@ -1645,6 +1648,7 @@ export default function ControlPanel({
|
||||
<DatabasesSwitcher
|
||||
setLastSaved={setLastSaved}
|
||||
diagramId={diagramId}
|
||||
setPrevDatabase={setPrevDatabase}
|
||||
/>
|
||||
<div
|
||||
className="text-xl me-1"
|
||||
|
@ -4,9 +4,9 @@ import { DB, State } from "../../data/constants";
|
||||
import { useDiagram, useSaveState } from "../../hooks";
|
||||
import { db } from "../../data/db";
|
||||
|
||||
const databasesWithoutGeneric = Object.keys(databases).filter(db => databases[db].label !== DB.GENERIC);
|
||||
const databasesWithoutGeneric = Object.keys(databases).filter(db => ![DB.GENERIC, DB.MARIADB, DB.MSSQL].includes(databases[db].label));
|
||||
|
||||
export default function DatabasesSwitcher({ setLastSaved, diagramId }) {
|
||||
export default function DatabasesSwitcher({ setLastSaved, diagramId, setPrevDatabase }) {
|
||||
const { database, setDatabase } = useDiagram();
|
||||
const { setSaveState } = useSaveState();
|
||||
|
||||
@ -57,6 +57,7 @@ export default function DatabasesSwitcher({ setLastSaved, diagramId }) {
|
||||
}).then(() => {
|
||||
setSaveState(State.SAVED);
|
||||
setLastSaved(new Date().toLocaleString());
|
||||
setPrevDatabase(database);
|
||||
setDatabase(selectedDb);
|
||||
});
|
||||
};
|
||||
|
220
src/utils/typesMappings.js
Normal file
220
src/utils/typesMappings.js
Normal file
@ -0,0 +1,220 @@
|
||||
import { DB } from "../data/constants";
|
||||
|
||||
function mapDataTypes(fromDb, toDb) {
|
||||
if (!fromDb || !toDb) {
|
||||
throw new Error("Please provide both from/to database names.");
|
||||
}
|
||||
|
||||
fromDb = fromDb.toLowerCase();
|
||||
toDb = toDb.toLowerCase();
|
||||
|
||||
if (fromDb === toDb || [fromDb, toDb].includes(DB.GENERIC)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const typeMapping = {
|
||||
postgresql: {
|
||||
mysql: {
|
||||
"SMALLINT": "TINYINT",
|
||||
"INTEGER": "INT",
|
||||
"BIGINT": "BIGINT",
|
||||
"SERIAL": "INT AUTO_INCREMENT",
|
||||
"BIGSERIAL": "BIGINT AUTO_INCREMENT",
|
||||
"DECIMAL": "DECIMAL",
|
||||
"NUMERIC": "DECIMAL",
|
||||
"REAL": "FLOAT",
|
||||
"DOUBLE PRECISION": "DOUBLE",
|
||||
"MONEY": "DECIMAL(19,4)",
|
||||
"VARCHAR": "VARCHAR",
|
||||
"CHAR": "CHAR",
|
||||
"TEXT": "TEXT",
|
||||
"BYTEA": "BLOB",
|
||||
"BOOLEAN": "TINYINT(1)",
|
||||
"DATE": "DATE",
|
||||
"TIME": "TIME",
|
||||
"TIMETZ": "TIME",
|
||||
"TIMESTAMP": "DATETIME",
|
||||
"TIMESTAMPTZ": "DATETIME",
|
||||
"INTERVAL": "TIME",
|
||||
"UUID": "CHAR(36)",
|
||||
"JSON": "JSON",
|
||||
"JSONB": "JSON",
|
||||
"XML": "TEXT",
|
||||
},
|
||||
sqlite: {
|
||||
"SMALLINT": "INTEGER",
|
||||
"INTEGER": "INTEGER",
|
||||
"BIGINT": "INTEGER",
|
||||
"SERIAL": "INTEGER PRIMARY KEY AUTOINCREMENT",
|
||||
"BIGSERIAL": "INTEGER",
|
||||
"DECIMAL": "REAL",
|
||||
"NUMERIC": "REAL",
|
||||
"REAL": "REAL",
|
||||
"DOUBLE PRECISION": "REAL",
|
||||
"MONEY": "REAL",
|
||||
"VARCHAR": "TEXT",
|
||||
"CHAR": "TEXT",
|
||||
"TEXT": "TEXT",
|
||||
"BYTEA": "BLOB",
|
||||
"BOOLEAN": "INTEGER",
|
||||
"DATE": "TEXT",
|
||||
"TIME": "TEXT",
|
||||
"TIMETZ": "TEXT",
|
||||
"TIMESTAMP": "TEXT",
|
||||
"TIMESTAMPTZ": "TEXT",
|
||||
"INTERVAL": "TEXT",
|
||||
"UUID": "TEXT",
|
||||
"JSON": "TEXT",
|
||||
"JSONB": "TEXT",
|
||||
"XML": "TEXT",
|
||||
},
|
||||
},
|
||||
mysql: {
|
||||
postgresql: {
|
||||
"TINYINT": "SMALLINT",
|
||||
"SMALLINT": "SMALLINT",
|
||||
"MEDIUMINT": "INTEGER",
|
||||
"INT": "INTEGER",
|
||||
"BIGINT": "BIGINT",
|
||||
"FLOAT": "REAL",
|
||||
"DOUBLE": "DOUBLE PRECISION",
|
||||
"DECIMAL": "DECIMAL",
|
||||
"NUMERIC": "NUMERIC",
|
||||
"VARCHAR": "VARCHAR",
|
||||
"CHAR": "CHAR",
|
||||
"TEXT": "TEXT",
|
||||
"BLOB": "BYTEA",
|
||||
"TINYBLOB": "BYTEA",
|
||||
"MEDIUMBLOB": "BYTEA",
|
||||
"LONGBLOB": "BYTEA",
|
||||
"BIT": "BOOLEAN",
|
||||
"BOOLEAN": "BOOLEAN",
|
||||
"DATE": "DATE",
|
||||
"TIME": "TIME",
|
||||
"DATETIME": "TIMESTAMP",
|
||||
"TIMESTAMP": "TIMESTAMP",
|
||||
"YEAR": "DATE",
|
||||
"JSON": "JSON",
|
||||
"ENUM": "VARCHAR",
|
||||
"SET": "TEXT",
|
||||
"POINT": "POINT",
|
||||
"LINESTRING": "LINE",
|
||||
"POLYGON": "POLYGON"
|
||||
},
|
||||
sqlite: {
|
||||
"TINYINT": "INTEGER",
|
||||
"SMALLINT": "INTEGER",
|
||||
"MEDIUMINT": "INTEGER",
|
||||
"INT": "INTEGER",
|
||||
"BIGINT": "INTEGER",
|
||||
"FLOAT": "REAL",
|
||||
"DOUBLE": "REAL",
|
||||
"DECIMAL": "REAL",
|
||||
"NUMERIC": "REAL",
|
||||
"VARCHAR(n)": "TEXT",
|
||||
"CHAR(n)": "TEXT",
|
||||
"TEXT": "TEXT",
|
||||
"BLOB": "BLOB",
|
||||
"TINYBLOB": "BLOB",
|
||||
"MEDIUMBLOB": "BLOB",
|
||||
"LONGBLOB": "BLOB",
|
||||
"BIT": "INTEGER",
|
||||
"BOOLEAN": "INTEGER",
|
||||
"DATE": "TEXT",
|
||||
"TIME": "TEXT",
|
||||
"DATETIME": "TEXT",
|
||||
"TIMESTAMP": "TEXT",
|
||||
"YEAR": "TEXT",
|
||||
"JSON": "TEXT",
|
||||
"ENUM": "TEXT",
|
||||
"SET": "TEXT",
|
||||
"POINT": "TEXT",
|
||||
"LINESTRING": "TEXT",
|
||||
"POLYGON": "TEXT"
|
||||
},
|
||||
},
|
||||
sqlite: {
|
||||
postgresql: {
|
||||
"INTEGER": "INTEGER",
|
||||
"REAL": "DOUBLE PRECISION",
|
||||
"TEXT": "TEXT",
|
||||
"BLOB": "BYTEA",
|
||||
"BOOLEAN": "BOOLEAN",
|
||||
"DATE": "DATE",
|
||||
"TIME": "TIME",
|
||||
"DATETIME": "TIMESTAMP",
|
||||
"NUMERIC": "NUMERIC",
|
||||
"VARCHAR": "VARCHAR",
|
||||
"CHAR": "CHAR",
|
||||
"JSON": "JSON",
|
||||
"POINT": "POINT",
|
||||
"LINESTRING": "LINE",
|
||||
"POLYGON": "POLYGON",
|
||||
},
|
||||
mysql: {
|
||||
"INTEGER": "INTEGER",
|
||||
"REAL": "DOUBLE",
|
||||
"TEXT": "TEXT",
|
||||
"BLOB": "BLOB",
|
||||
"BOOLEAN": "TINYINT(1)",
|
||||
"DATE": "DATE",
|
||||
"TIME": "TIME",
|
||||
"DATETIME": "DATETIME",
|
||||
"NUMERIC": "DECIMAL",
|
||||
"VARCHAR": "VARCHAR",
|
||||
"CHAR": "CHAR",
|
||||
"JSON": "JSON",
|
||||
"POINT": "POINT",
|
||||
"LINESTRING": "LINESTRING",
|
||||
"POLYGON": "POLYGON",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (typeMapping[fromDb] && typeMapping[fromDb][toDb]) {
|
||||
return typeMapping[fromDb][toDb];
|
||||
} else {
|
||||
return ''; // Unsupported data type mapping
|
||||
}
|
||||
}
|
||||
|
||||
export function convertTableSchema(table, fromDb, toDb) {
|
||||
|
||||
return {
|
||||
...table,
|
||||
fields: table.fields.map(field => {
|
||||
let mappedType = mapDataTypes(fromDb, toDb)?.[field.type];
|
||||
|
||||
// Handle ENUM values if they exist
|
||||
if (field.type === "ENUM" && [DB.POSTGRES, DB.SQLITE].includes(toDb)) {
|
||||
mappedType = toDb === DB.POSTGRES ? "VARCHAR" : "TEXT";
|
||||
|
||||
if (field.values?.length) {
|
||||
field.check = `${field.name} IN (${field.values.join(", ")})`;
|
||||
}
|
||||
}
|
||||
|
||||
if (field.type === "VARCHAR" && field.check && DB.MYSQL === toDb) {
|
||||
mappedType = `ENUM`;
|
||||
const regex = /\(([^)]+)\)/;
|
||||
const match = field.check.match(regex);
|
||||
|
||||
if (match) {
|
||||
field.values = match[1].split(',').map(value => value.trim());
|
||||
mappedType += `(${field.values.join(", ")})`;
|
||||
}
|
||||
}
|
||||
|
||||
if (DB.POSTGRES === toDb && field.increment) {
|
||||
mappedType = `SERIAL`;
|
||||
}
|
||||
|
||||
return {
|
||||
...field,
|
||||
type: mappedType || field.type,
|
||||
// Remove MySQL-specific properties if necessary
|
||||
values: field.values || undefined
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user