diff --git a/apps/desktop/src/App.vue b/apps/desktop/src/App.vue index 0e2cb5454..baf6f498c 100644 --- a/apps/desktop/src/App.vue +++ b/apps/desktop/src/App.vue @@ -920,12 +920,12 @@ onUnmounted(() => { @object-schema-change="(schema) => activeTab && queryStore.updateSchema(activeTab.id, schema)" @structure-editor-saved=" activeTab && - onStructureEditorSaved(onReloadData, toast, { - connectionId: activeTab.connectionId, - database: activeTab.database, - schema: activeTab.schema, - tableName: activeTab.structureTableName || '', - }) + onStructureEditorSaved(onReloadData, toast, { + connectionId: activeTab.connectionId, + database: activeTab.database, + schema: activeTab.schema, + tableName: activeTab.structureTableName || '', + }) " @structure-editor-close="activeTab && queryStore.closeTab(activeTab.id)" /> diff --git a/apps/desktop/src/components/layout/AppTabBar.vue b/apps/desktop/src/components/layout/AppTabBar.vue index f79c7b25b..243efd6d0 100644 --- a/apps/desktop/src/components/layout/AppTabBar.vue +++ b/apps/desktop/src/components/layout/AppTabBar.vue @@ -120,7 +120,8 @@ function tabColorStyle(tab: QueryTab) { } function tabIconClass(tab: QueryTab) { - if (tab.mode === "data" || tab.mode === "objects" || tab.mode === "structure") return "text-emerald-600 dark:text-emerald-400"; + if (tab.mode === "data" || tab.mode === "objects" || tab.mode === "structure") + return "text-emerald-600 dark:text-emerald-400"; return "text-blue-600 dark:text-blue-400"; } diff --git a/apps/desktop/src/components/structure/TableStructureEditor.vue b/apps/desktop/src/components/structure/TableStructureEditor.vue index 7c17b5d1d..616337ed5 100644 --- a/apps/desktop/src/components/structure/TableStructureEditor.vue +++ b/apps/desktop/src/components/structure/TableStructureEditor.vue @@ -208,22 +208,11 @@ async function loadStructure(silent = false) { errorMessage.value = ""; try { await store.ensureConnected(props.connectionId); - const nextColumns = await api.getColumns( - props.connectionId, - props.database, - targetSchema.value, - props.tableName, - ); + const nextColumns = await api.getColumns(props.connectionId, props.database, targetSchema.value, props.tableName); const [nextIndexes, nextForeignKeys, nextTriggers] = await Promise.all([ - api - .listIndexes(props.connectionId, props.database, targetSchema.value, props.tableName) - .catch(() => []), - api - .listForeignKeys(props.connectionId, props.database, targetSchema.value, props.tableName) - .catch(() => []), - api - .listTriggers(props.connectionId, props.database, targetSchema.value, props.tableName) - .catch(() => []), + api.listIndexes(props.connectionId, props.database, targetSchema.value, props.tableName).catch(() => []), + api.listForeignKeys(props.connectionId, props.database, targetSchema.value, props.tableName).catch(() => []), + api.listTriggers(props.connectionId, props.database, targetSchema.value, props.tableName).catch(() => []), ]); columns.value = createColumnDrafts(nextColumns); indexes.value = createIndexDrafts(nextIndexes); @@ -406,15 +395,7 @@ onMounted(() => { }); watch( - [ - isCreateMode, - databaseType, - () => props.schema, - () => props.tableName, - newTableName, - columns, - indexes, - ], + [isCreateMode, databaseType, () => props.schema, () => props.tableName, newTableName, columns, indexes], () => { void refreshSqlPreview(); }, @@ -442,9 +423,7 @@ watch(
- + @@ -584,7 +567,11 @@ watch( type="checkbox" class="h-3.5 w-3.5" :disabled="isPrimaryKeyDisabled(column)" - @change="() => { if (column.isPrimaryKey) column.isNullable = false; }" + @change=" + () => { + if (column.isPrimaryKey) column.isNullable = false; + } + " /> @@ -828,9 +815,7 @@ watch( - {{ - index.includedColumns.join(", ") - }} + {{ index.includedColumns.join(", ") }} - + {{ t("structureEditor.primary") }} @@ -895,11 +876,7 @@ watch( {{ t("structureEditor.emptyReadonly") }}
-
+
{{ trigger.name }}
{{ trigger.timing }} {{ trigger.event }}
@@ -912,7 +889,11 @@ watch(
{{ t("structureEditor.sqlPreview") }} - + {{ t("structureEditor.ready") }} @@ -936,7 +917,8 @@ watch(
+            v-html="highlightedSql"
+          />
           
{{ t("structureEditor.noChanges") }}
diff --git a/apps/desktop/src/composables/useNavigationTargets.ts b/apps/desktop/src/composables/useNavigationTargets.ts index 8d349e595..c21e508ff 100644 --- a/apps/desktop/src/composables/useNavigationTargets.ts +++ b/apps/desktop/src/composables/useNavigationTargets.ts @@ -126,7 +126,11 @@ export function useNavigationTargets(dialogs: { ) { if (!context.tableName) { try { - await connectionStore.refreshObjectListTreeNode(context.connectionId, context.database, context.schema || undefined); + await connectionStore.refreshObjectListTreeNode( + context.connectionId, + context.database, + context.schema || undefined, + ); } catch {} return; } diff --git a/apps/desktop/src/lib/sqlHighlighter.ts b/apps/desktop/src/lib/sqlHighlighter.ts index 3a9b32171..e6f8ca044 100644 --- a/apps/desktop/src/lib/sqlHighlighter.ts +++ b/apps/desktop/src/lib/sqlHighlighter.ts @@ -15,9 +15,7 @@ type ShikiHighlighter = Awaited | undefined; -export async function createShikiSqlHighlighter( - options: ShikiSqlHighlighterOptions, -): Promise { +export async function createShikiSqlHighlighter(options: ShikiSqlHighlighterOptions): Promise { const highlighter = await getShikiSqlHighlighter(); return (content, appearance = options.appearance()) => highlighter.codeToHtml(content, { @@ -33,13 +31,7 @@ function getShikiSqlHighlighter(): Promise { } async function loadShikiSqlHighlighter(): Promise { - const [ - { createHighlighterCore }, - { createJavaScriptRegexEngine }, - githubDark, - githubLight, - sql, - ] = await Promise.all([ + const [{ createHighlighterCore }, { createJavaScriptRegexEngine }, githubDark, githubLight, sql] = await Promise.all([ import("shiki/core"), import("shiki/engine/javascript"), import("shiki/themes/github-dark.mjs"), diff --git a/apps/desktop/src/lib/tableStructureEditorState.ts b/apps/desktop/src/lib/tableStructureEditorState.ts index 0b538deca..6e5bad353 100644 --- a/apps/desktop/src/lib/tableStructureEditorState.ts +++ b/apps/desktop/src/lib/tableStructureEditorState.ts @@ -3,73 +3,229 @@ import type { EditableStructureColumn, EditableStructureIndex } from "./tableStr export const DATA_TYPE_OPTIONS: Record = { mysql: [ - "tinyint", "smallint", "mediumint", "int", "integer", "bigint", - "float", "double", "double precision", "real", - "decimal", "numeric", - "bit", "boolean", "bool", "serial", - "char", "varchar", "tinytext", "text", "mediumtext", "longtext", - "binary", "varbinary", "tinyblob", "blob", "mediumblob", "longblob", - "enum", "set", - "date", "datetime", "timestamp", "time", "year", + "tinyint", + "smallint", + "mediumint", + "int", + "integer", + "bigint", + "float", + "double", + "double precision", + "real", + "decimal", + "numeric", + "bit", + "boolean", + "bool", + "serial", + "char", + "varchar", + "tinytext", + "text", + "mediumtext", + "longtext", + "binary", + "varbinary", + "tinyblob", + "blob", + "mediumblob", + "longblob", + "enum", + "set", + "date", + "datetime", + "timestamp", + "time", + "year", "json", - "geometry", "point", "linestring", "polygon", "multipoint", "multilinestring", "multipolygon", "geometrycollection", + "geometry", + "point", + "linestring", + "polygon", + "multipoint", + "multilinestring", + "multipolygon", + "geometrycollection", ], postgres: [ - "smallint", "int2", "integer", "int", "int4", "bigint", "int8", - "smallserial", "serial", "bigserial", - "decimal", "numeric", "real", "float", "float4", "double precision", "float8", "money", - "boolean", "bool", - "char", "character", "varchar", "character varying", "text", + "smallint", + "int2", + "integer", + "int", + "int4", + "bigint", + "int8", + "smallserial", + "serial", + "bigserial", + "decimal", + "numeric", + "real", + "float", + "float4", + "double precision", + "float8", + "money", + "boolean", + "bool", + "char", + "character", + "varchar", + "character varying", + "text", "bytea", - "date", "time", "time without time zone", "time with time zone", "timetz", "timestamp", "timestamp without time zone", "timestamp with time zone", "timestamptz", "interval", + "date", + "time", + "time without time zone", + "time with time zone", + "timetz", + "timestamp", + "timestamp without time zone", + "timestamp with time zone", + "timestamptz", + "interval", "uuid", - "json", "jsonb", "xml", - "bit", "bit varying", "varbit", - "tsvector", "tsquery", - "cidr", "inet", "macaddr", "macaddr8", - "point", "line", "lseg", "box", "path", "polygon", "circle", - "int4range", "int8range", "numrange", "tsrange", "tstzrange", "daterange", + "json", + "jsonb", + "xml", + "bit", + "bit varying", + "varbit", + "tsvector", + "tsquery", + "cidr", + "inet", + "macaddr", + "macaddr8", + "point", + "line", + "lseg", + "box", + "path", + "polygon", + "circle", + "int4range", + "int8range", + "numrange", + "tsrange", + "tstzrange", + "daterange", "oid", ], - sqlite: [ - "integer", "real", "text", "blob", "numeric", - ], + sqlite: ["integer", "real", "text", "blob", "numeric"], sqlserver: [ "bit", - "tinyint", "smallint", "int", "integer", "bigint", - "decimal", "numeric", "float", "real", "money", "smallmoney", - "char", "nchar", "varchar", "nvarchar", "text", "ntext", - "date", "time", "datetime", "datetime2", "smalldatetime", "datetimeoffset", "timestamp", - "binary", "varbinary", "image", - "uniqueidentifier", "xml", "sql_variant", "hierarchyid", - "geography", "geometry", + "tinyint", + "smallint", + "int", + "integer", + "bigint", + "decimal", + "numeric", + "float", + "real", + "money", + "smallmoney", + "char", + "nchar", + "varchar", + "nvarchar", + "text", + "ntext", + "date", + "time", + "datetime", + "datetime2", + "smalldatetime", + "datetimeoffset", + "timestamp", + "binary", + "varbinary", + "image", + "uniqueidentifier", + "xml", + "sql_variant", + "hierarchyid", + "geography", + "geometry", ], oracle: [ - "number", "integer", "float", "binary_float", "binary_double", - "char", "nchar", "varchar2", "nvarchar2", - "clob", "nclob", "long", - "date", "timestamp", "timestamp with time zone", "timestamp with local time zone", - "interval year to month", "interval day to second", - "raw", "long raw", "blob", "bfile", - "boolean", "json", "vector", - "rowid", "urowid", - "xmltype", "sdo_geometry", + "number", + "integer", + "float", + "binary_float", + "binary_double", + "char", + "nchar", + "varchar2", + "nvarchar2", + "clob", + "nclob", + "long", + "date", + "timestamp", + "timestamp with time zone", + "timestamp with local time zone", + "interval year to month", + "interval day to second", + "raw", + "long raw", + "blob", + "bfile", + "boolean", + "json", + "vector", + "rowid", + "urowid", + "xmltype", + "sdo_geometry", ], clickhouse: [ - "Int8", "Int16", "Int32", "Int64", "Int128", "Int256", - "UInt8", "UInt16", "UInt32", "UInt64", "UInt128", "UInt256", - "Float16", "Float32", "Float64", - "Decimal", "Decimal32", "Decimal64", "Decimal128", "Decimal256", + "Int8", + "Int16", + "Int32", + "Int64", + "Int128", + "Int256", + "UInt8", + "UInt16", + "UInt32", + "UInt64", + "UInt128", + "UInt256", + "Float16", + "Float32", + "Float64", + "Decimal", + "Decimal32", + "Decimal64", + "Decimal128", + "Decimal256", "Bool", - "String", "FixedString", - "Date", "Date32", "DateTime", "DateTime64", + "String", + "FixedString", + "Date", + "Date32", + "DateTime", + "DateTime64", "UUID", - "IPv4", "IPv6", - "Enum8", "Enum16", - "Array", "Map", "Tuple", "Nested", - "Nullable", "LowCardinality", - "SimpleAggregateFunction", "AggregateFunction", - "Point", "Ring", "Polygon", "MultiPolygon", + "IPv4", + "IPv6", + "Enum8", + "Enum16", + "Array", + "Map", + "Tuple", + "Nested", + "Nullable", + "LowCardinality", + "SimpleAggregateFunction", + "AggregateFunction", + "Point", + "Ring", + "Polygon", + "MultiPolygon", "JSON", ], }; diff --git a/apps/desktop/src/stores/queryStore.ts b/apps/desktop/src/stores/queryStore.ts index 9a7d11cdf..ccd34ed96 100644 --- a/apps/desktop/src/stores/queryStore.ts +++ b/apps/desktop/src/stores/queryStore.ts @@ -209,7 +209,9 @@ export const useQueryStore = defineStore("query", () => { return existing.id; } - const title = resolvedTableName ? t("structureEditor.editTabTitle", { tableName: resolvedTableName }) : t("structureEditor.createTitle"); + const title = resolvedTableName + ? t("structureEditor.editTabTitle", { tableName: resolvedTableName }) + : t("structureEditor.createTitle"); const id = uuid(); const tab: QueryTab = { id, diff --git a/crates/dbx-core/src/table_structure_sql.rs b/crates/dbx-core/src/table_structure_sql.rs index d280ad4a6..ce7156cbf 100644 --- a/crates/dbx-core/src/table_structure_sql.rs +++ b/crates/dbx-core/src/table_structure_sql.rs @@ -494,12 +494,8 @@ fn build_primary_key_sql( .map(|c| c.name.as_str()) .collect(); - let new_pk_names: Vec<&str> = options - .columns - .iter() - .filter(|c| !c.marked_for_drop && c.is_primary_key) - .map(|c| c.name.as_str()) - .collect(); + let new_pk_names: Vec<&str> = + options.columns.iter().filter(|c| !c.marked_for_drop && c.is_primary_key).map(|c| c.name.as_str()).collect(); if old_pk_names == new_pk_names { return Vec::new(); @@ -520,10 +516,7 @@ fn build_primary_key_sql( StructureDialect::Postgres => { let raw_table = options.table_name.split('.').last().unwrap_or(&options.table_name); let pk_name = format!("{}_pkey", clean(raw_table)); - statements.push(format!( - "ALTER TABLE {table} DROP CONSTRAINT {};", - quote_ident(dialect, &pk_name) - )); + statements.push(format!("ALTER TABLE {table} DROP CONSTRAINT {};", quote_ident(dialect, &pk_name))); } StructureDialect::Mysql => { statements.push(format!("ALTER TABLE {table} DROP PRIMARY KEY;")); @@ -533,11 +526,7 @@ fn build_primary_key_sql( } if !new_pk_names.is_empty() { - let pk_list = new_pk_names - .iter() - .map(|n| quote_ident(dialect, n)) - .collect::>() - .join(", "); + let pk_list = new_pk_names.iter().map(|n| quote_ident(dialect, n)).collect::>().join(", "); statements.push(format!("ALTER TABLE {table} ADD PRIMARY KEY ({pk_list});")); } @@ -1590,10 +1579,7 @@ mod tests { }); assert_eq!(result.warnings, Vec::::new()); - assert_eq!( - result.statements, - vec!["ALTER TABLE \"public\".\"users\" ADD PRIMARY KEY (\"id\");"] - ); + assert_eq!(result.statements, vec!["ALTER TABLE \"public\".\"users\" ADD PRIMARY KEY (\"id\");"]); } #[test] @@ -1621,10 +1607,7 @@ mod tests { }); assert_eq!(result.warnings, Vec::::new()); - assert_eq!( - result.statements, - vec!["ALTER TABLE \"public\".\"users\" DROP CONSTRAINT \"users_pkey\";"] - ); + assert_eq!(result.statements, vec!["ALTER TABLE \"public\".\"users\" DROP CONSTRAINT \"users_pkey\";"]); } #[test] @@ -1670,10 +1653,7 @@ mod tests { assert_eq!(result.warnings, Vec::::new()); assert_eq!( result.statements, - vec![ - "ALTER TABLE `users` DROP PRIMARY KEY;", - "ALTER TABLE `users` ADD PRIMARY KEY (`uuid`);", - ] + vec!["ALTER TABLE `users` DROP PRIMARY KEY;", "ALTER TABLE `users` ADD PRIMARY KEY (`uuid`);",] ); }