Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions backend/windmill-api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20606,6 +20606,8 @@ components:
type: string
required:
- path
extra_args:
type: string

DataTableSettings:
type: object
Expand Down
5 changes: 5 additions & 0 deletions backend/windmill-common/src/workspaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ pub async fn get_datatable_resource_from_db_unchecked(
pub struct Ducklake {
pub catalog: DucklakeCatalog,
pub storage: DucklakeStorage,
#[serde(skip_serializing_if = "Option::is_none")]
pub extra_args: Option<String>,
}

#[derive(Deserialize, Serialize, Debug)]
Expand Down Expand Up @@ -244,6 +246,8 @@ pub struct DucklakeWithConnData {
pub catalog: DucklakeCatalog,
pub catalog_resource: serde_json::Value,
pub storage: DucklakeStorage,
#[serde(skip_serializing_if = "Option::is_none")]
pub extra_args: Option<String>,
}

pub async fn get_ducklake_from_db_unchecked(
Expand Down Expand Up @@ -287,6 +291,7 @@ pub async fn get_ducklake_from_db_unchecked(
catalog_resource,
catalog: ducklake.catalog,
storage: ducklake.storage,
extra_args: ducklake.extra_args,
};
Ok(ducklake)
}
Expand Down
6 changes: 6 additions & 0 deletions backend/windmill-worker/src/duckdb_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,12 @@ async fn transform_attach_ducklake(
} else {
format!(", OVERRIDE_DATA_PATH TRUE{extra_args}")
};
let extra_args = if let Some(default_extra_args) = ducklake.extra_args {
// premise : extra_args is always non empty (and doesn't end with a comma given it's valid)
format!("{},{}", extra_args, default_extra_args)
} else {
extra_args
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice implementation! The approach of appending default extra_args after the OVERRIDE_DATA_PATH handling is correct. The comment explaining the premise is helpful.

One minor consideration: if the user provides conflicting extra_args (e.g., the same argument is set in both the ducklake default and the inline ATTACH statement), DuckDB will either:

  1. Use the last value specified
  2. Throw an error for certain arguments

This is probably acceptable behavior since the user can always remove the default extra_args if they want to override them inline. Just something to note in documentation if not already covered.


let attach_str = format!(
"ATTACH 'ducklake:{db_type}:{db_conn_str}' AS {alias_name} (DATA_PATH 's3://{storage}/{data_path}'{extra_args});",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
storage?: string
path: string
}
extra_args?: string
}[]
}

Expand Down Expand Up @@ -42,15 +43,16 @@

s.ducklakes[ducklake.name] = {
catalog: ducklake.catalog,
storage: ducklake.storage
storage: ducklake.storage,
extra_args: ducklake.extra_args || undefined
}
}
return s
}
</script>

<script>
import { Plus } from 'lucide-svelte'
import { Plus, SettingsIcon } from 'lucide-svelte'

import Button from '../common/button/Button.svelte'

Expand Down Expand Up @@ -81,6 +83,7 @@
import { isCustomInstanceDbEnabled } from './utils.svelte'
import { resource } from 'runed'
import CustomInstanceDbSelect from './CustomInstanceDbSelect.svelte'
import Label from '../Label.svelte'

const DEFAULT_DUCKLAKE_CATALOG_NAME = 'ducklake_catalog'

Expand Down Expand Up @@ -316,29 +319,56 @@
</div>
</Cell>
<Cell class="w-12">
{#if ducklakeIsDirty[ducklake.name]}
<Popover
openOnHover
contentClasses="p-2 text-sm text-secondary italic"
class="cursor-not-allowed"
>
<div class="flex gap-2">
<Popover contentClasses="p-4" enableFlyTransition closeOnOtherPopoverOpen>
<svelte:fragment slot="trigger">
<ExploreAssetButton
class="h-9"
asset={{ kind: 'ducklake', path: ducklake.name }}
{dbManagerDrawer}
disabled
/>
<div class="relative">
<Button variant="default" iconOnly size="sm" endIcon={{ icon: SettingsIcon }} />
{#if ducklake.extra_args}
<div
class="absolute -top-0.5 -right-0.5 w-2 h-2 bg-accent rounded-full border border-surface"
></div>
{/if}
</div>
</svelte:fragment>
<svelte:fragment slot="content">
<Label
label="Extra args"
tooltip="Additional arguments to pass in the ATTACH command. The argument list is substituted as-is. Separate them with commas."
>
<TextInput
bind:value={ducklake.extra_args}
class="min-w-96"
underlyingInputEl="textarea"
inputProps={{ placeholder: "METADATA_SCHEMA 'schema', ENCRYPTED true" }}
/>
</Label>
</svelte:fragment>
<svelte:fragment slot="content">Please save settings first</svelte:fragment>
</Popover>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good use of a Popover with a settings icon to keep the main UI clean while providing access to advanced options. The implementation is clean and follows the project patterns well.

Minor UX suggestion: Consider adding a visual indicator (e.g., a small dot on the settings icon) when extra_args has a value, so users know at a glance that extra args are configured. This would help avoid surprises when someone modifies a ducklake without realizing it has default extra args set.

{:else}
<ExploreAssetButton
class="h-9"
asset={{ kind: 'ducklake', path: ducklake.name }}
{dbManagerDrawer}
/>
{/if}
{#if ducklakeIsDirty[ducklake.name]}
<Popover
openOnHover
contentClasses="p-2 text-sm text-secondary italic"
class="cursor-not-allowed"
>
<svelte:fragment slot="trigger">
<ExploreAssetButton
class="h-9"
asset={{ kind: 'ducklake', path: ducklake.name }}
{dbManagerDrawer}
disabled
/>
</svelte:fragment>
<svelte:fragment slot="content">Please save settings first</svelte:fragment>
</Popover>
{:else}
<ExploreAssetButton
class="h-9"
asset={{ kind: 'ducklake', path: ducklake.name }}
{dbManagerDrawer}
/>
{/if}
</div>
</Cell>
<Cell class="w-12">
<CloseButton small on:close={() => removeDucklake(ducklakeIndex)} />
Expand Down