Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
4587f4d
alter table pure logic from fred pr
diegoimbert Jan 5, 2026
ab0a3cc
rename table op
diegoimbert Jan 5, 2026
3e05e0c
stateful logic ok
diegoimbert Jan 5, 2026
14608de
nit
diegoimbert Jan 5, 2026
2111490
fix null access
diegoimbert Jan 5, 2026
e5f77ba
inspect
diegoimbert Jan 5, 2026
6b03c32
Merge branch 'di/db-manager-broken-null-access' into di/db-manager-up…
diegoimbert Jan 5, 2026
4cc39f3
create data from real schema + more fred fixes
diegoimbert Jan 5, 2026
eb29893
pk and fk constraint name
diegoimbert Jan 5, 2026
8be0c6b
primary and foreign keys alter support
diegoimbert Jan 5, 2026
dff3303
fix array types
diegoimbert Jan 5, 2026
2185796
defaultValue fix
diegoimbert Jan 5, 2026
9935ffc
better UI feedback
diegoimbert Jan 5, 2026
296a5e8
nit error props
diegoimbert Jan 5, 2026
35a6281
sort operations
diegoimbert Jan 5, 2026
ef949f5
fix tests
diegoimbert Jan 5, 2026
64bddf4
update fk when renaming a column
diegoimbert Jan 5, 2026
3d015b7
normalize fk to old col names
diegoimbert Jan 5, 2026
86d27b8
compare old pk col names
diegoimbert Jan 5, 2026
9ae50be
nit fix changes count
diegoimbert Jan 5, 2026
e724ef1
nits + only compare pk and fk initial names
diegoimbert Jan 5, 2026
ba0edbe
tests
diegoimbert Jan 5, 2026
fb5fb7a
Merge branch 'main' into di/db-manager-update-table
diegoimbert Jan 5, 2026
bd576c3
nit
diegoimbert Jan 5, 2026
66e3475
Refactor
diegoimbert Jan 5, 2026
994e6e0
prepare for other dbs
diegoimbert Jan 5, 2026
0ed7337
fix ci
diegoimbert Jan 6, 2026
0bb7885
Use col defs instead of a whole new query
diegoimbert Jan 6, 2026
21d3c55
fetch pk and fk infos
diegoimbert Jan 6, 2026
1888045
nit improvements
diegoimbert Jan 6, 2026
c448118
MS SQL DB Manager Fixes
diegoimbert Jan 6, 2026
f9fab6d
Fix primary key fetching for MS SQL
diegoimbert Jan 6, 2026
c0beb84
extract render functions
diegoimbert Jan 6, 2026
80b9ae0
Fix DROP default for MS SQL Server
diegoimbert Jan 6, 2026
9b98317
fix unsortable datatype error in MS SQL select
diegoimbert Jan 6, 2026
908d631
bigquery nits
diegoimbert Jan 6, 2026
275fba8
MySQL fixes
diegoimbert Jan 6, 2026
42258d1
nit
diegoimbert Jan 6, 2026
1806d32
refactor fetchTableRelationalKeys
diegoimbert Jan 6, 2026
82b6c9d
stash
diegoimbert Jan 6, 2026
2776069
fetch primary keys correctly in snowflake
diegoimbert Jan 6, 2026
2294793
fix drop constraint quotes in snowflake
diegoimbert Jan 6, 2026
aa89244
fix primary key not enforced on bigquery
diegoimbert Jan 6, 2026
fb01819
nit
diegoimbert Jan 6, 2026
061e163
Merge branch 'main' into di/db-manager-update-table
diegoimbert Jan 6, 2026
41564b1
nit
diegoimbert Jan 6, 2026
03dec3f
nit
diegoimbert Jan 6, 2026
70db942
nit
diegoimbert Jan 6, 2026
ac9dbc2
nit tests
diegoimbert Jan 6, 2026
d75ee29
nit console log
diegoimbert Jan 6, 2026
ff937dd
Update frontend/src/lib/components/apps/components/display/dbtable/qu…
diegoimbert Jan 6, 2026
790928f
nit
diegoimbert Jan 6, 2026
dd0b4e3
nit
diegoimbert Jan 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 124 additions & 18 deletions frontend/src/lib/components/DBManager.svelte
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
<script lang="ts">
import { type DBSchema } from '$lib/stores'
import { ChevronDownIcon, MoreVertical, Plus, Table2, Trash2Icon } from 'lucide-svelte'
import {
ChevronDownIcon,
EditIcon,
Loader2,
MoreVertical,
Plus,
Table2,
Trash2Icon
} from 'lucide-svelte'
import { Pane, Splitpanes } from 'svelte-splitpanes'
import { ClearableInput, Drawer, DrawerContent } from './common'
import { sendUserToast } from '$lib/toast'
import { type ColumnDef } from './apps/components/display/dbtable/utils'
import { type ColumnDef, type DbFeatures } from './apps/components/display/dbtable/utils'
import DBTable from './DBTable.svelte'
import type { IDbSchemaOps, IDbTableOps } from './dbOps'
import DropdownV2 from './DropdownV2.svelte'
Expand All @@ -16,6 +24,12 @@
import Select from './select/Select.svelte'
import { safeSelectItems } from './select/utils.svelte'
import type { Snippet } from 'svelte'
import {
dbSupportsTransactionalDdl,
diffTableEditorValues
} from './apps/components/display/dbtable/queries/alterTable'
import { resource } from 'runed'
import { capitalize, pluralize } from '$lib/utils'

/** Represents a selected table with its schema */
export interface SelectedTable {
Expand All @@ -42,6 +56,7 @@
selectedTables?: SelectedTable[]
/** Tables that are already added and should show as disabled */
disabledTables?: SelectedTable[]
features?: DbFeatures
}
let {
dbType,
Expand All @@ -58,7 +73,8 @@
dbSelector,
multiSelectMode = false,
selectedTables = $bindable([]),
disabledTables = []
disabledTables = [],
features
}: Props = $props()

// Helper to check if a table is selected in multi-select mode
Expand Down Expand Up @@ -187,7 +203,24 @@
| (ConfirmationModal['$$prop_def'] & { onConfirm: () => void })
| undefined = $state()

let dbTableEditorState: { open: boolean } = $state({ open: false })
let dbTableEditorState:
| { open: boolean; alterTableKey?: undefined }
| { open: true; alterTableKey: string } = $state({
open: false
})
let dbTableEditorAlterTableData = resource(
() => dbTableEditorState.alterTableKey,
async (table) => {
if (!table) return
let tableKey2 =
dbSupportsSchemas && selected.schemaKey ? `${selected.schemaKey}.${table}` : table
return await dbSchemaOps.onFetchTableEditorDefinition({
table: table,
getColDefs: () => getColDefs(tableKey2)
})
}
)

let newSchemaDialogOpen = $state(false)
let newSchemaName = $state('')

Expand Down Expand Up @@ -297,7 +330,9 @@
<span class="truncate text-ellipsis grow text-left text-tertiary text-xs"
>{schemaKey}</span
>
<span class="text-2xs text-tertiary mr-2 group-hover:hidden">{schemaTables.length}</span>
<span class="text-2xs text-tertiary mr-2 group-hover:hidden">
{schemaTables.length}
</span>
<!-- Delete schema button (on hover) -->
<button
class="hidden group-hover:flex p-1 hover:bg-red-100 dark:hover:bg-red-900/30 rounded transition-colors mr-1"
Expand Down Expand Up @@ -331,7 +366,8 @@
{#each schemaTables as tableKey}
{@const isDisabled = isTableDisabled(schemaKey, tableKey)}
{@const isChecked = isTableSelected(schemaKey, tableKey) || isDisabled}
{@const isCurrentPreview = selected.schemaKey === schemaKey && selected.tableKey === tableKey}
{@const isCurrentPreview =
selected.schemaKey === schemaKey && selected.tableKey === tableKey}
<div
class={'group w-full text-sm font-normal flex gap-2 items-center h-8 cursor-pointer pl-7 pr-1 ' +
(isCurrentPreview ? 'bg-gray-500/25' : 'hover:bg-gray-500/10') +
Expand Down Expand Up @@ -439,6 +475,16 @@
askingForConfirmation = undefined
}
})
},
{
displayName: 'Alter table',
icon: EditIcon,
action: () => {
dbTableEditorState = {
open: true,
alterTableKey: tableKey
}
}
}
]}
class="w-fit"
Expand Down Expand Up @@ -490,18 +536,78 @@
open={dbTableEditorState.open}
on:close={() => (dbTableEditorState = { open: false })}
>
<DrawerContent on:close={() => (dbTableEditorState = { open: false })} title="Create a new table">
<DbTableEditor
{dbSchema}
currentSchema={selected.schemaKey}
onConfirm={async (values) => {
await dbSchemaOps.onCreate({ values, schema: selected.schemaKey })
refresh?.()
dbTableEditorState = { open: false }
}}
{dbType}
previewSql={(values) => dbSchemaOps.previewCreateSql({ values, schema: selected.schemaKey })}
/>
<DrawerContent
on:close={() => (dbTableEditorState = { open: false })}
title={dbTableEditorState.alterTableKey
? `Alter ${dbTableEditorState.alterTableKey}`
: 'Create a new table'}
>
{#key dbTableEditorState.alterTableKey}
{#if !dbTableEditorState.alterTableKey || dbTableEditorAlterTableData.current}
<DbTableEditor
{features}
{dbSchema}
currentSchema={selected.schemaKey}
initialValues={dbTableEditorAlterTableData.current}
onConfirm={async ({ values }) => {
if (dbTableEditorState.alterTableKey && dbTableEditorAlterTableData.current) {
let diff = diffTableEditorValues(dbTableEditorAlterTableData.current, values)
await dbSchemaOps.onAlter({ schema: selected.schemaKey, values: diff })
} else {
await dbSchemaOps.onCreate({ values, schema: selected.schemaKey })
}
refresh?.()
sendUserToast(
dbTableEditorState.alterTableKey
? dbTableEditorState.alterTableKey + ' updated!'
: values.name + ' created!'
)
dbTableEditorState = { open: false }
}}
{dbType}
computePreview={({ values }) => {
if (dbTableEditorState.alterTableKey && dbTableEditorAlterTableData.current) {
let diff = diffTableEditorValues(dbTableEditorAlterTableData.current, values)
let queries = dbSchemaOps.previewAlterSql({
values: diff,
schema: selected.schemaKey
})
let alert = !dbSupportsTransactionalDdl(dbType)
? {
title: capitalize(dbType) + ' does not support transactional DDL',
body: 'Any of these statements failing may leave your database in an intermediate state.'
}
: undefined
return { sql: queries.join('\n'), ...(alert ? { alert } : {}) }
} else {
return { sql: dbSchemaOps.previewCreateSql({ values, schema: selected.schemaKey }) }
}
}}
computeBtnProps={({ values }) => {
if (dbTableEditorState.alterTableKey && dbTableEditorAlterTableData.current) {
let diff = diffTableEditorValues(dbTableEditorAlterTableData.current, values)
let queries = dbSchemaOps.previewAlterSql({
values: diff,
schema: selected.schemaKey
})
if (!queries.length) {
return { text: 'No changes detected', disabled: true }
}
return {
text: `Alter table (${pluralize(queries.length, 'change')} detected)`
}
} else {
return { text: 'Create table' }
}
}}
/>
{:else if dbTableEditorAlterTableData.loading}
<Loader2 class="animate-spin" size={32} />
{:else}
<p class="text-sm text-tertiary">Failed to load table definition.</p>
<p>{dbTableEditorAlterTableData.error}</p>
{/if}
{/key}
</DrawerContent>
</Drawer>

Expand Down
9 changes: 7 additions & 2 deletions frontend/src/lib/components/DBManagerContent.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
import { dbSchemas, workspaceStore, type DBSchema } from '$lib/stores'
import { sendUserToast, sortArray } from '$lib/utils'
import { Loader2 } from 'lucide-svelte'
import { dbSupportsSchemas, type TableMetadata } from './apps/components/display/dbtable/utils'
import {
dbSupportsSchemas,
getDbFeatures,
type TableMetadata
} from './apps/components/display/dbtable/utils'
import DbManager from './DBManager.svelte'
import {
dbSchemaOpsWithPreviewScripts,
Expand Down Expand Up @@ -191,7 +195,7 @@
{/if}
</div>
<DbManager
dbSupportsSchemas={input.type == 'database' && dbSupportsSchemas(input.resourceType)}
dbSupportsSchemas={input?.type == 'database' && dbSupportsSchemas(input.resourceType)}
{dbSchema}
{getColDefs}
dbTableOpsFactory={({ colDefs, tableKey }) =>
Expand All @@ -215,6 +219,7 @@
{multiSelectMode}
bind:selectedTables
{disabledTables}
features={getDbFeatures(input)}
/>
</Pane>
{#if showRepl}
Expand Down
Loading