Load types for selected db
BIN
src/assets/mariadb-icon.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/mssql-icon.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
src/assets/mysql-icon.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
src/assets/postgres-icon.png
Normal file
After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 207 KiB |
BIN
src/assets/sqlite-icon.png
Normal file
After Width: | Height: | Size: 24 KiB |
@ -1,4 +1,4 @@
|
||||
import { Action, ObjectType, sqlDataTypes } from "../../../data/constants";
|
||||
import { Action, ObjectType } from "../../../data/constants";
|
||||
import { Row, Col, Input, Button, Popover, Select } from "@douyinfe/semi-ui";
|
||||
import { IconMore, IconKeyStroked } from "@douyinfe/semi-icons";
|
||||
import { getSize, hasCheck, hasPrecision, isSized } from "../../../utils/toSQL";
|
||||
@ -6,11 +6,12 @@ import { useTables, useTypes, useUndoRedo } from "../../../hooks";
|
||||
import { useState } from "react";
|
||||
import FieldDetails from "./FieldDetails";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { dbToTypes } from "../../../data/datatypes";
|
||||
|
||||
export default function TableField({ data, tid, index }) {
|
||||
const { updateField } = useTables();
|
||||
const { types } = useTypes();
|
||||
const { tables } = useTables();
|
||||
const { tables, database } = useTables();
|
||||
const { t } = useTranslation();
|
||||
const { setUndoStack, setRedoStack } = useUndoRedo();
|
||||
const [editField, setEditField] = useState({});
|
||||
@ -50,7 +51,7 @@ export default function TableField({ data, tid, index }) {
|
||||
<Select
|
||||
className="w-full"
|
||||
optionList={[
|
||||
...sqlDataTypes.map((value) => ({
|
||||
...dbToTypes[database].map((value) => ({
|
||||
label: value,
|
||||
value: value,
|
||||
})),
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useState } from "react";
|
||||
import { Action, ObjectType, sqlDataTypes } from "../../../data/constants";
|
||||
import { Action, ObjectType } from "../../../data/constants";
|
||||
import {
|
||||
Row,
|
||||
Col,
|
||||
@ -12,11 +12,13 @@ import {
|
||||
} from "@douyinfe/semi-ui";
|
||||
import { IconDeleteStroked, IconMore } from "@douyinfe/semi-icons";
|
||||
import { isSized, hasPrecision, getSize } from "../../../utils/toSQL";
|
||||
import { useUndoRedo, useTypes } from "../../../hooks";
|
||||
import { useUndoRedo, useTypes, useTables } from "../../../hooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { dbToTypes } from "../../../data/datatypes";
|
||||
|
||||
export default function TypeField({ data, tid, fid }) {
|
||||
const { types, updateType } = useTypes();
|
||||
const { database } = useTables();
|
||||
const { setUndoStack, setRedoStack } = useUndoRedo();
|
||||
const [editField, setEditField] = useState({});
|
||||
const { t } = useTranslation();
|
||||
@ -62,7 +64,7 @@ export default function TypeField({ data, tid, fid }) {
|
||||
<Select
|
||||
className="w-full"
|
||||
optionList={[
|
||||
...sqlDataTypes.map((value) => ({
|
||||
...dbToTypes[database].map((value) => ({
|
||||
label: value,
|
||||
value: value,
|
||||
})),
|
||||
|
@ -17,6 +17,9 @@ import {
|
||||
useSaveState,
|
||||
} from "../hooks";
|
||||
import FloatingControls from "./FloatingControls";
|
||||
import { Modal } from "@douyinfe/semi-ui";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { databases } from "../data/databases";
|
||||
|
||||
export default function WorkSpace() {
|
||||
const [id, setId] = useState(0);
|
||||
@ -24,6 +27,8 @@ export default function WorkSpace() {
|
||||
const [resize, setResize] = useState(false);
|
||||
const [width, setWidth] = useState(340);
|
||||
const [lastSaved, setLastSaved] = useState("");
|
||||
const [showSelectDbModal, setShowSelectDbModal] = useState(false);
|
||||
const [selectedDb, setSelectedDb] = useState("");
|
||||
const { layout } = useLayout();
|
||||
const { settings } = useSettings();
|
||||
const { types, setTypes } = useTypes();
|
||||
@ -32,8 +37,10 @@ export default function WorkSpace() {
|
||||
const { notes, setNotes } = useNotes();
|
||||
const { saveState, setSaveState } = useSaveState();
|
||||
const { transform, setTransform } = useTransform();
|
||||
const { tables, relationships, setTables, setRelationships } = useTables();
|
||||
const { tables, relationships, setTables, setRelationships, setDatabase } =
|
||||
useTables();
|
||||
const { undoStack, redoStack, setUndoStack, setRedoStack } = useUndoRedo();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleResize = (e) => {
|
||||
if (!resize) return;
|
||||
@ -130,6 +137,9 @@ export default function WorkSpace() {
|
||||
.last()
|
||||
.then((d) => {
|
||||
if (d) {
|
||||
if (!d.database) {
|
||||
setShowSelectDbModal(true);
|
||||
}
|
||||
setId(d.id);
|
||||
setTitle(d.name);
|
||||
setTables(d.tables);
|
||||
@ -154,6 +164,9 @@ export default function WorkSpace() {
|
||||
.get(id)
|
||||
.then((diagram) => {
|
||||
if (diagram) {
|
||||
if (!diagram.database) {
|
||||
setShowSelectDbModal(true);
|
||||
}
|
||||
setId(diagram.id);
|
||||
setTitle(diagram.name);
|
||||
setTables(diagram.tables);
|
||||
@ -304,6 +317,46 @@ export default function WorkSpace() {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Modal
|
||||
centered
|
||||
size="medium"
|
||||
closable={false}
|
||||
hasCancel={false}
|
||||
title={t("pick_db")}
|
||||
okText={t("confirm")}
|
||||
onOk={() => {
|
||||
setDatabase(selectedDb);
|
||||
setShowSelectDbModal(false);
|
||||
}}
|
||||
visible={showSelectDbModal}
|
||||
>
|
||||
<div className="grid grid-cols-3 gap-4 place-content-center">
|
||||
{databases.map((x) => (
|
||||
<div
|
||||
key={x.name}
|
||||
onClick={() => setSelectedDb(x.label)}
|
||||
className={`space-y-3 py-3 px-4 rounded-md border-2 ${
|
||||
settings.mode === "dark"
|
||||
? "bg-zinc-700 hover:bg-zinc-600"
|
||||
: "bg-zinc-100 hover:bg-zinc-200"
|
||||
} ${selectedDb === x.label ? "border-zinc-400" : "border-transparent"}`}
|
||||
>
|
||||
<div className="font-semibold">{x.name}</div>
|
||||
{x.image && (
|
||||
<img
|
||||
src={x.image}
|
||||
className="h-10"
|
||||
style={{
|
||||
filter:
|
||||
"opacity(0.4) drop-shadow(0 0 0 white) drop-shadow(0 0 0 white)",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div className="text-xs">{x.description}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ export const TablesContext = createContext(null);
|
||||
|
||||
export default function TablesContextProvider({ children }) {
|
||||
const { t } = useTranslation();
|
||||
const [database, setDatabase] = useState("");
|
||||
const [tables, setTables] = useState([]);
|
||||
const [relationships, setRelationships] = useState([]);
|
||||
const { transform } = useTransform();
|
||||
@ -261,6 +262,8 @@ export default function TablesContextProvider({ children }) {
|
||||
setRelationships,
|
||||
addRelationship,
|
||||
deleteRelationship,
|
||||
database,
|
||||
setDatabase,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
@ -1,31 +1,5 @@
|
||||
import i18n from "../i18n/i18n";
|
||||
|
||||
export const sqlDataTypes = [
|
||||
"INT",
|
||||
"SMALLINT",
|
||||
"BIGINT",
|
||||
"DECIMAL",
|
||||
"NUMERIC",
|
||||
"FLOAT",
|
||||
"DOUBLE",
|
||||
"REAL",
|
||||
"CHAR",
|
||||
"VARCHAR",
|
||||
"TEXT",
|
||||
"DATE",
|
||||
"TIME",
|
||||
"TIMESTAMP",
|
||||
"DATETIME",
|
||||
"BOOLEAN",
|
||||
"BINARY",
|
||||
"VARBINARY",
|
||||
"BLOB",
|
||||
"JSON",
|
||||
"UUID",
|
||||
"ENUM",
|
||||
"SET",
|
||||
];
|
||||
|
||||
export const tableThemes = [
|
||||
"#f03c3c",
|
||||
"#ff4f81",
|
||||
|
40
src/data/databases.js
Normal file
@ -0,0 +1,40 @@
|
||||
import mysqlImage from "../assets/mysql-icon.png";
|
||||
import postgresImage from "../assets/postgres-icon.png";
|
||||
import sqliteImage from "../assets/sqlite-icon.png";
|
||||
import mariadbImage from "../assets/mariadb-icon.png";
|
||||
import mssqlImage from "../assets/mssql-icon.png";
|
||||
|
||||
export const databases = [
|
||||
{
|
||||
name: "MySQL",
|
||||
label: "mysql",
|
||||
image: mysqlImage,
|
||||
},
|
||||
{
|
||||
name: "PostgreSQL",
|
||||
label: "postgresql",
|
||||
image: postgresImage,
|
||||
},
|
||||
{
|
||||
name: "SQLite",
|
||||
label: "sqlite",
|
||||
image: sqliteImage,
|
||||
},
|
||||
{
|
||||
name: "MariaDB",
|
||||
label: "mariadb",
|
||||
image: mariadbImage,
|
||||
},
|
||||
{
|
||||
name: "MSSQL",
|
||||
label: "mssql",
|
||||
image: mssqlImage,
|
||||
},
|
||||
{
|
||||
name: "Generic",
|
||||
label: "generic",
|
||||
image: null,
|
||||
description:
|
||||
"Generic diagrams can be exported to any SQL flavor but support few data types.",
|
||||
},
|
||||
];
|
290
src/data/datatypes.js
Normal file
@ -0,0 +1,290 @@
|
||||
export const defaultTypes = [
|
||||
"INT",
|
||||
"SMALLINT",
|
||||
"BIGINT",
|
||||
"DECIMAL",
|
||||
"NUMERIC",
|
||||
"FLOAT",
|
||||
"DOUBLE",
|
||||
"REAL",
|
||||
"CHAR",
|
||||
"VARCHAR",
|
||||
"TEXT",
|
||||
"DATE",
|
||||
"TIME",
|
||||
"TIMESTAMP",
|
||||
"DATETIME",
|
||||
"BOOLEAN",
|
||||
"BINARY",
|
||||
"VARBINARY",
|
||||
"BLOB",
|
||||
"JSON",
|
||||
"UUID",
|
||||
"ENUM",
|
||||
"SET",
|
||||
];
|
||||
|
||||
export const mysqlTypes = [
|
||||
// Numeric Data Types
|
||||
"TINYINT",
|
||||
"SMALLINT",
|
||||
"MEDIUMINT",
|
||||
"INT",
|
||||
"INTEGER",
|
||||
"BIGINT",
|
||||
"DECIMAL",
|
||||
"NUMERIC",
|
||||
"FLOAT",
|
||||
"DOUBLE",
|
||||
"BIT",
|
||||
"BOOLEAN",
|
||||
|
||||
// Date and Time Data Types
|
||||
"DATE",
|
||||
"DATETIME",
|
||||
"TIMESTAMP",
|
||||
"TIME",
|
||||
"YEAR",
|
||||
|
||||
// String Data Types
|
||||
"CHAR",
|
||||
"VARCHAR",
|
||||
"BINARY",
|
||||
"VARBINARY",
|
||||
"TINYBLOB",
|
||||
"BLOB",
|
||||
"MEDIUMBLOB",
|
||||
"LONGBLOB",
|
||||
"TINYTEXT",
|
||||
"TEXT",
|
||||
"MEDIUMTEXT",
|
||||
"LONGTEXT",
|
||||
"ENUM",
|
||||
"SET",
|
||||
|
||||
// Spatial Data Types
|
||||
"GEOMETRY",
|
||||
"POINT",
|
||||
"LINESTRING",
|
||||
"POLYGON",
|
||||
"MULTIPOINT",
|
||||
"MULTILINESTRING",
|
||||
"MULTIPOLYGON",
|
||||
"GEOMETRYCOLLECTION",
|
||||
|
||||
// JSON Data Type
|
||||
"JSON",
|
||||
];
|
||||
|
||||
export const postgresTypes = [
|
||||
// Numeric Data Types
|
||||
"SMALLINT",
|
||||
"INTEGER",
|
||||
"BIGINT",
|
||||
"DECIMAL",
|
||||
"NUMERIC",
|
||||
"REAL",
|
||||
"DOUBLE PRECISION",
|
||||
"SMALLSERIAL",
|
||||
"SERIAL",
|
||||
"BIGSERIAL",
|
||||
"MONEY",
|
||||
|
||||
// Character Types
|
||||
"CHARACTER",
|
||||
"CHAR",
|
||||
"VARCHAR",
|
||||
"TEXT",
|
||||
|
||||
// Binary Data Types
|
||||
"BYTEA",
|
||||
|
||||
// Date and Time Types
|
||||
"DATE",
|
||||
"TIME",
|
||||
"TIMESTAMP",
|
||||
"TIMESTAMPTZ",
|
||||
"INTERVAL",
|
||||
|
||||
// Boolean Type
|
||||
"BOOLEAN",
|
||||
|
||||
// Enumerated Types
|
||||
"ENUM",
|
||||
|
||||
// Geometric Types
|
||||
"POINT",
|
||||
"LINE",
|
||||
"LSEG",
|
||||
"BOX",
|
||||
"PATH",
|
||||
"POLYGON",
|
||||
"CIRCLE",
|
||||
|
||||
// Network Address Types
|
||||
"CIDR",
|
||||
"INET",
|
||||
"MACADDR",
|
||||
"MACADDR8",
|
||||
|
||||
// Bit String Types
|
||||
"BIT",
|
||||
"VARBIT",
|
||||
|
||||
// Text Search Types
|
||||
"TSVECTOR",
|
||||
"TSQUERY",
|
||||
|
||||
// JSON Types
|
||||
"JSON",
|
||||
"JSONB",
|
||||
|
||||
// UUID Type
|
||||
"UUID",
|
||||
|
||||
// XML Type
|
||||
"XML",
|
||||
|
||||
// Arrays
|
||||
"ARRAY",
|
||||
];
|
||||
|
||||
export const sqliteTypes = [
|
||||
// Numeric Data Types
|
||||
"INTEGER",
|
||||
"REAL",
|
||||
|
||||
// Text Data Types
|
||||
"TEXT",
|
||||
|
||||
// Blob Data Type
|
||||
"BLOB",
|
||||
|
||||
// Affinity Types
|
||||
"NUMERIC",
|
||||
|
||||
// Boolean Type (Alias of INTEGER)
|
||||
"BOOLEAN",
|
||||
|
||||
// Date and Time Types (Recommended to store as TEXT)
|
||||
"DATE",
|
||||
"DATETIME",
|
||||
"TIME",
|
||||
"TIMESTAMP",
|
||||
];
|
||||
|
||||
export const mariadbTypes = [
|
||||
// Numeric Data Types
|
||||
"TINYINT",
|
||||
"SMALLINT",
|
||||
"MEDIUMINT",
|
||||
"INT",
|
||||
"INTEGER",
|
||||
"BIGINT",
|
||||
"DECIMAL",
|
||||
"NUMERIC",
|
||||
"FLOAT",
|
||||
"DOUBLE",
|
||||
"BIT",
|
||||
"BOOLEAN",
|
||||
|
||||
// Date and Time Data Types
|
||||
"DATE",
|
||||
"DATETIME",
|
||||
"TIMESTAMP",
|
||||
"TIME",
|
||||
"YEAR",
|
||||
|
||||
// String Data Types
|
||||
"CHAR",
|
||||
"VARCHAR",
|
||||
"BINARY",
|
||||
"VARBINARY",
|
||||
"TINYBLOB",
|
||||
"BLOB",
|
||||
"MEDIUMBLOB",
|
||||
"LONGBLOB",
|
||||
"TINYTEXT",
|
||||
"TEXT",
|
||||
"MEDIUMTEXT",
|
||||
"LONGTEXT",
|
||||
"ENUM",
|
||||
"SET",
|
||||
|
||||
// Spatial Data Types
|
||||
"GEOMETRY",
|
||||
"POINT",
|
||||
"LINESTRING",
|
||||
"POLYGON",
|
||||
"MULTIPOINT",
|
||||
"MULTILINESTRING",
|
||||
"MULTIPOLYGON",
|
||||
"GEOMETRYCOLLECTION",
|
||||
|
||||
// JSON Data Type
|
||||
"JSON",
|
||||
];
|
||||
|
||||
export const mssqlTypes = [
|
||||
// Exact Numeric Data Types
|
||||
"BIGINT",
|
||||
"INT",
|
||||
"SMALLINT",
|
||||
"TINYINT",
|
||||
"BIT",
|
||||
"DECIMAL",
|
||||
"NUMERIC",
|
||||
"MONEY",
|
||||
"SMALLMONEY",
|
||||
|
||||
// Approximate Numeric Data Types
|
||||
"FLOAT",
|
||||
"REAL",
|
||||
|
||||
// Date and Time Data Types
|
||||
"DATE",
|
||||
"TIME",
|
||||
"DATETIME",
|
||||
"DATETIME2",
|
||||
"DATETIMEOFFSET",
|
||||
"SMALLDATETIME",
|
||||
"TIMESTAMP",
|
||||
|
||||
// Character Strings
|
||||
"CHAR",
|
||||
"VARCHAR",
|
||||
"TEXT",
|
||||
|
||||
// Unicode Character Strings
|
||||
"NCHAR",
|
||||
"NVARCHAR",
|
||||
"NTEXT",
|
||||
|
||||
// Binary Data Types
|
||||
"BINARY",
|
||||
"VARBINARY",
|
||||
"IMAGE",
|
||||
|
||||
// Other Data Types
|
||||
"UNIQUEIDENTIFIER",
|
||||
"XML",
|
||||
"CURSOR",
|
||||
"TABLE",
|
||||
"SQL_VARIANT",
|
||||
|
||||
// JSON Data Type
|
||||
"JSON", // Note: JSON is not a native type in MSSQL; it uses NVARCHAR to store JSON data
|
||||
];
|
||||
|
||||
const dbToTypesBase = {
|
||||
generic: defaultTypes,
|
||||
mysql: mysqlTypes,
|
||||
postgresql: postgresTypes,
|
||||
sqlite: sqliteTypes,
|
||||
mssql: mssqlTypes,
|
||||
mariadb: mariadbTypes,
|
||||
};
|
||||
|
||||
export const dbToTypes = new Proxy(dbToTypesBase, {
|
||||
get: (target, prop) => (prop in target ? target[prop] : []),
|
||||
});
|
@ -197,7 +197,7 @@ export default function LandingPage() {
|
||||
/>
|
||||
<img
|
||||
src={sql_server_icon}
|
||||
className="opacity-70 hover:opacity-100 transition-all duration-300 h-24"
|
||||
className="opacity-70 hover:opacity-100 transition-all duration-300 h-16"
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-16 mb-2 text-2xl font-bold text-center">
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { sqlDataTypes } from "../data/constants";
|
||||
import { defaultTypes } from "../data/datatypes";
|
||||
import { isFunction, isKeyword, strHasQuotes } from "./utils";
|
||||
|
||||
export function getJsonType(f) {
|
||||
if (!sqlDataTypes.includes(f.type)) {
|
||||
if (!defaultTypes.includes(f.type)) {
|
||||
return '{ "type" : "object", additionalProperties : true }';
|
||||
}
|
||||
switch (f.type) {
|
||||
@ -50,7 +50,7 @@ export function getTypeString(field, dbms = "mysql", baseType = false) {
|
||||
if (field.type === "SET" || field.type === "ENUM") {
|
||||
return `${field.type}(${field.values.map((v) => `"${v}"`).join(", ")})`;
|
||||
}
|
||||
if (!sqlDataTypes.includes(field.type)) {
|
||||
if (!defaultTypes.includes(field.type)) {
|
||||
return "JSON";
|
||||
}
|
||||
return field.type;
|
||||
@ -173,7 +173,7 @@ export function jsonToMySQL(obj) {
|
||||
field.default !== "" ? ` DEFAULT ${parseDefault(field)}` : ""
|
||||
}${
|
||||
field.check === "" || !hasCheck(field.type)
|
||||
? !sqlDataTypes.includes(field.type)
|
||||
? !defaultTypes.includes(field.type)
|
||||
? ` CHECK(\n\t\tJSON_SCHEMA_VALID("${generateSchema(
|
||||
obj.types.find(
|
||||
(t) => t.name === field.type.toLowerCase(),
|
||||
@ -414,7 +414,7 @@ export function jsonToMariaDB(obj) {
|
||||
field.default !== "" ? ` DEFAULT ${parseDefault(field)}` : ""
|
||||
}${
|
||||
field.check === "" || !hasCheck(field.type)
|
||||
? !sqlDataTypes.includes(field.type)
|
||||
? !defaultTypes.includes(field.type)
|
||||
? ` CHECK(\n\t\tJSON_SCHEMA_VALID('${generateSchema(
|
||||
obj.types.find(
|
||||
(t) => t.name === field.type.toLowerCase(),
|
||||
|