diff --git a/src/assets/oraclesql-icon.png b/src/assets/oraclesql-icon.png new file mode 100644 index 00000000..cdeb3a31 Binary files /dev/null and b/src/assets/oraclesql-icon.png differ diff --git a/src/assets/oraclesql.png b/src/assets/oraclesql.png new file mode 100644 index 00000000..cb7686e4 Binary files /dev/null and b/src/assets/oraclesql.png differ diff --git a/src/components/EditorHeader/ControlPanel.jsx b/src/components/EditorHeader/ControlPanel.jsx index c274878b..c824f65f 100644 --- a/src/components/EditorHeader/ControlPanel.jsx +++ b/src/components/EditorHeader/ControlPanel.jsx @@ -29,6 +29,7 @@ import { jsonToSQLite, jsonToMariaDB, jsonToSQLServer, + jsonToOracleSQL, } from "../../utils/exportSQL/generic"; import { ObjectType, @@ -882,6 +883,22 @@ export default function ControlPanel({ })); }, }, + { + OracleSQL: () => { + setModal(MODAL.CODE); + const src = jsonToOracleSQL({ + tables: tables, + references: relationships, + types: types, + database: database, + }); + setExportData((prev) => ({ + ...prev, + data: src, + extension: "sql", + })); + }, + }, ], }), function: () => { diff --git a/src/data/constants.js b/src/data/constants.js index b07605e1..469a7cc7 100644 --- a/src/data/constants.js +++ b/src/data/constants.js @@ -112,5 +112,6 @@ export const DB = { MSSQL: "transactsql", SQLITE: "sqlite", MARIADB: "mariadb", + ORACLESQL: "oraclesql", GENERIC: "generic", }; diff --git a/src/data/databases.js b/src/data/databases.js index 55c9187c..c32a74d6 100644 --- a/src/data/databases.js +++ b/src/data/databases.js @@ -3,6 +3,7 @@ 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"; +import oraclesqlImage from "../assets/oraclesql-icon.png"; import i18n from "../i18n/i18n"; import { DB } from "./constants"; @@ -40,6 +41,14 @@ export const databases = new Proxy( image: mssqlImage, hasTypes: false, }, + [DB.ORACLESQL]: { + name: "Oracle SQL", + label: DB.ORACLESQL, + image: oraclesqlImage, + hasTypes: false, + hasEnums: false, + hasArrays: false, + }, [DB.GENERIC]: { name: i18n.t("generic"), label: DB.GENERIC, diff --git a/src/data/datatypes.js b/src/data/datatypes.js index 77c0cd72..7da391be 100644 --- a/src/data/datatypes.js +++ b/src/data/datatypes.js @@ -55,6 +55,16 @@ const defaultTypesBase = { isSized: false, hasPrecision: true, }, + NUMBER: { + type: "NUMBER", + checkDefault: (field) => { + return /^-?\d+(\.\d+)?$/.test(field.default); + }, + hasCheck: true, + isSized: false, + hasPrecision: true, + canIncrement: false, + }, FLOAT: { type: "FLOAT", checkDefault: (field) => { @@ -110,6 +120,20 @@ const defaultTypesBase = { defaultSize: 255, hasQuotes: true, }, + VARCHAR2: { + type: "VARCHAR2", + checkDefault: (field) => { + if (strHasQuotes(field.default)) { + return field.default.length - 2 <= field.size; + } + return field.default.length <= field.size; + }, + hasCheck: true, + isSized: true, + hasPrecision: false, + defaultSize: 225, + hasQuotes: true, + }, TEXT: { type: "TEXT", checkDefault: (field) => true, @@ -223,6 +247,22 @@ const defaultTypesBase = { hasPrecision: false, noDefault: true, }, + CLOB: { + type: "CLOB", + checkDefault: (field) => true, + isSized: false, + hasCheck: false, + hasPrecision: false, + noDefault: true, + }, + NCLOB: { + type: "NCLOB", + checkDefault: (field) => true, + isSized: false, + hasCheck: false, + hasPrecision: false, + noDefault: true, + }, JSON: { type: "JSON", checkDefault: (field) => true, @@ -1616,6 +1656,155 @@ export const mssqlTypes = new Proxy(mssqlTypesBase, { get: (target, prop) => (prop in target ? target[prop] : false), }); +const oraclesqlTypesBase = { + NUMBER: { + type: "NUMBER", + checkDefault: (field) => { + return /^-?\d+(\.\d+)?$/.test(field.default); + }, + hasCheck: true, + isSized: false, + hasPrecision: true, + canIncrement: false, + }, + VARCHAR2: { + type: "VARCHAR2", + checkDefault: (field) => { + if (strHasQuotes(field.default)) { + return field.default.length - 2 <= field.size; + } + return field.default.length <= field.size; + }, + hasCheck: true, + isSized: true, + hasPrecision: false, + defaultSize: 4000, + hasQuotes: true, + }, + CHAR: { + type: "CHAR", + checkDefault: (field) => { + if (strHasQuotes(field.default)) { + return field.default.length - 2 <= field.size; + } + return field.default.length <= field.size; + }, + hasCheck: true, + isSized: true, + hasPrecision: false, + defaultSize: 1, + hasQuotes: true, + }, + CLOB: { + type: "CLOB", + checkDefault: (field) => true, + isSized: false, + hasCheck: false, + hasPrecision: false, + noDefault: true, + }, + NCLOB: { + type: "NCLOB", + checkDefault: (field) => true, + isSized: false, + hasCheck: false, + hasPrecision: false, + noDefault: true, + }, + BLOB: { + type: "BLOB", + checkDefault: (field) => true, + isSized: false, + hasCheck: false, + hasPrecision: false, + noDefault: true, + }, + DATE: { + type: "DATE", + checkDefault: (field) => { + return /^\d{4}-\d{2}-\d{2}$/.test(field.default); + }, + hasCheck: false, + isSized: false, + hasPrecision: false, + hasQuotes: true, + }, + TIMESTAMP: { + type: "TIMESTAMP", + checkDefault: (field) => { + if (field.default.toUpperCase() === "CURRENT_TIMESTAMP") { + return true; + } + return /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test( + field.default, + ); + }, + hasCheck: false, + isSized: false, + hasPrecision: true, + hasQuotes: true, + }, + INTERVAL: { + type: "INTERVAL", + checkDefault: (field) => { + return /^INTERVAL\s'\d+'(\s+DAY|HOUR|MINUTE|SECOND)?$/.test( + field.default, + ); + }, + hasCheck: false, + isSized: false, + hasPrecision: false, + hasQuotes: true, + }, + FLOAT: { + type: "FLOAT", + checkDefault: (field) => { + return /^-?\d+(\.\d+)?$/.test(field.default); + }, + hasCheck: true, + isSized: false, + hasPrecision: true, + }, + DOUBLE: { + type: "DOUBLE", + checkDefault: (field) => { + return /^-?\d+(\.\d+)?$/.test(field.default); + }, + hasCheck: true, + isSized: false, + hasPrecision: true, + }, + BOOLEAN: { + type: "BOOLEAN", + checkDefault: (field) => { + return ( + field.default === "0" || + field.default === "1" || + field.default.toUpperCase() === "TRUE" || + field.default.toUpperCase() === "FALSE" + ); + }, + hasCheck: false, + isSized: false, + hasPrecision: false, + }, + RAW: { + type: "RAW", + checkDefault: (field) => { + return /^[0-9A-Fa-f]+$/.test(field.default); + }, + hasCheck: false, + isSized: true, + hasPrecision: false, + defaultSize: 2000, + hasQuotes: false, + }, +}; + +export const oraclesqlTypes = new Proxy(oraclesqlTypesBase, { + get: (target, prop) => (prop in target ? target[prop] : false), +}); + const dbToTypesBase = { [DB.GENERIC]: defaultTypes, [DB.MYSQL]: mysqlTypes, @@ -1623,6 +1812,7 @@ const dbToTypesBase = { [DB.SQLITE]: sqliteTypes, [DB.MSSQL]: mssqlTypes, [DB.MARIADB]: mysqlTypes, + [DB.ORACLESQL]: oraclesqlTypes, }; export const dbToTypes = new Proxy(dbToTypesBase, { diff --git a/src/pages/LandingPage.jsx b/src/pages/LandingPage.jsx index 46c7f1dd..642a3a2d 100644 --- a/src/pages/LandingPage.jsx +++ b/src/pages/LandingPage.jsx @@ -9,6 +9,7 @@ import mysql_icon from "../assets/mysql.png"; import postgres_icon from "../assets/postgres.png"; import sqlite_icon from "../assets/sqlite.png"; import mariadb_icon from "../assets/mariadb.png"; +import oraclesql_icon from "../assets/oraclesql.png"; import sql_server_icon from "../assets/sql-server.png"; import discord from "../assets/discord.png"; import github from "../assets/github.png"; @@ -178,7 +179,7 @@ export default function LandingPage() {