fix: fix DB Manager not working with db resources with 4+ path segments (#7809)

* support more than 3 path segments

* Fix explore db resource not working with 4+ path segments

* don't assume 3 segments

* ?table= syntax impl

* update parsers

* more nit fixes

* fix sql query

* claude nit

* Update SQLx metadata

---------

Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
This commit is contained in:
Diego Imbert
2026-02-05 15:00:15 +01:00
committed by GitHub
parent 6673507824
commit 5cdecd795c
17 changed files with 167 additions and 162 deletions

View File

@@ -57,7 +57,6 @@
)
export function openDrawer(nInput: DbInput) {
console.log('Opening DB Manager with input:', nInput)
input = nInput
if (isDatatableInput) {
datatables.refetch()

View File

@@ -58,8 +58,7 @@
{btnClasses}
on:click={async () => {
if (asset.kind === 'resource' && isDbType(_resourceMetadata?.resource_type)) {
let resourcePath = asset.path.split('/').slice(0, 3).join('/')
let specificTable = asset.path.split('/')[3] as string | undefined
let [resourcePath, specificTable] = asset.path.split('?table=')
dbManagerDrawer?.openDrawer({
type: 'database',
resourceType: _resourceMetadata.resource_type,

View File

@@ -29,10 +29,8 @@
onClick
}: Props = $props()
let resourceDataCacheValue = $derived.by(() => {
let truncatedPath = asset.path.split('/').slice(0, 3).join('/')
return resourceDataCache[truncatedPath]
})
let truncatedPath = asset.path.split('?table=')[0]
let resourceDataCacheValue = $derived(resourceDataCache[truncatedPath])
</script>
<div class="flex gap-2 items-center">
@@ -42,7 +40,7 @@
variant="default"
unifiedSize="md"
iconOnly
on:click={() => (resourceEditorDrawer?.initEdit(asset.path), onClick?.())}
on:click={() => (resourceEditorDrawer?.initEdit(truncatedPath), onClick?.())}
/>
{/if}
{#if (asset.kind === 'resource' && resourceDataCacheValue === undefined) || ducklakeNotFound || datatableNotFound}

View File

@@ -84,7 +84,7 @@
for (const asset of assets) {
if (asset.kind == 'resource') {
let truncatedPath = asset.path.split('/').slice(0, 3).join('/')
let truncatedPath = asset.path.split('?table=')[0]
if (truncatedPath in resourceDataCache) continue
resourceDataCache[truncatedPath] = undefined // avoid fetching multiple times because of async
ResourceService.getResource({ path: truncatedPath, workspace: $workspaceStore! })
@@ -195,7 +195,11 @@
formatAssetKind({
...asset,
...(asset.kind === 'resource'
? { metadata: { resource_type: resourceDataCache[asset.path] } }
? {
metadata: {
resource_type: resourceDataCache[asset.path.split('?table=')[0]]
}
}
: {})
})}
</span>

View File

@@ -53,7 +53,7 @@
$effect(() => {
for (const asset of assets.value ?? []) {
if (asset.kind == 'resource') {
let truncatedPath = asset.path.split('/').slice(0, 3).join('/')
let truncatedPath = asset.path.split('?table=')[0]
if (truncatedPath in resourceDataCache) continue
resourceDataCache[truncatedPath] = undefined // avoid fetching multiple times because of async
ResourceService.getResource({ path: truncatedPath, workspace: $workspaceStore! })
@@ -78,7 +78,7 @@
{formatAssetKind({
...asset,
...(asset.kind === 'resource'
? { metadata: { resource_type: resourceDataCache[asset.path] } }
? { metadata: { resource_type: resourceDataCache[asset.path.split('?table=')[0]] } }
: {})
})}
</span>

View File

@@ -31,7 +31,11 @@ export function formatAsset(asset: Asset): string {
}
export function formatShortAssetPath(asset: Asset): string {
return asset.path.split('/').pop() || asset.path
if (asset.kind === 'datatable' && asset.path === 'main') return 'Main data table'
if (asset.kind === 'ducklake' && asset.path === 'main') return 'Main ducklake'
const s = asset.path.split('/').pop() || asset.path
if (s.includes('?table=')) return s.split('?table=')[1]
return s
}
export function getAssetUsagePageUri(usage: AssetUsage) {

View File

@@ -75,7 +75,7 @@
) ?? []
for (const asset of assets) {
if (asset.kind == 'resource') {
let truncatedPath = asset.path.split('/').slice(0, 3).join('/')
let truncatedPath = asset.path.split('?table=')[0]
if (truncatedPath in resMetadataCache) continue
resMetadataCache[truncatedPath] = undefined // avoid fetching multiple times because of async
ResourceService.getResource({ path: truncatedPath, workspace: $workspaceStore! })

View File

@@ -250,7 +250,7 @@
const isSelected = $derived(assetEq(flowGraphAssetsCtx?.val.selectedAsset, data.asset))
const cachedResourceMetadata = $derived.by(() => {
if (data.asset.kind !== 'resource') return undefined
let truncatedPath = data.asset.path.split('/').slice(0, 3).join('/')
let truncatedPath = data.asset.path.split('?table=')[0]
return flowGraphAssetsCtx?.val.resourceMetadataCache[truncatedPath]
})
const usageCount = $derived(flowGraphAssetsCtx?.val.computeAssetsCount?.(data.asset))

View File

@@ -1,5 +1,4 @@
//regex that match path starting with u/ or f/ and with at least 2 /
const pathRegex = /\b(u|f)\/[^\/\s]+\/[^\/\s]+\b/g
const pathRegex = /\b(u|f)(\/[^\/\s]+){2,}\b/g
export function processMessage(message: string | undefined): string {
let msg = !message