Skip to content

Commit 8843130

Browse files
fuziontechclaude
andcommitted
Include memory.main in Flight SQL worker session search_path
When a Flight SQL worker session initializes, initSearchPath() sets search_path to '<username>,main'. With DuckLake as the default catalog, 'main' resolves to 'ducklake.main', excluding memory.main where pg_catalog macros (pg_get_userbyid, format_type, etc.) are created. This breaks psql backslash commands (\dt, \d, etc.) on K8s shared warm workers. The non-K8s control plane path doesn't hit this because it leaves search_path unset (empty/default), which lets DuckDB resolve functions across all catalogs. Fix by appending memory.main to the search_path in initSearchPath(). When DuckLake isn't active, memory.main is redundant but harmless. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 9729c52 commit 8843130

3 files changed

Lines changed: 12 additions & 13 deletions

File tree

duckdbservice/service.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -624,13 +624,18 @@ func dropTemporary(ctx context.Context, conn *sql.Conn, query, dropFmt string) {
624624

625625
// initSearchPath sets the DuckDB search_path for a session connection.
626626
// It tries to include the user's schema first; if that schema doesn't exist,
627-
// it falls back to just 'main' (DuckDB's default schema).
627+
// it falls back to just 'main'.
628+
//
629+
// memory.main is always included so that pg_catalog macros (pg_get_userbyid,
630+
// format_type, etc.) remain resolvable when the default catalog is ducklake.
631+
// Without it, DuckDB restricts function resolution to the ducklake catalog
632+
// and psql commands like \dt fail.
628633
func initSearchPath(conn *sql.Conn, username string) {
629-
if _, err := conn.ExecContext(context.Background(), fmt.Sprintf("SET search_path = '%s,main'", username)); err != nil {
634+
if _, err := conn.ExecContext(context.Background(), fmt.Sprintf("SET search_path = '%s,main,memory.main'", username)); err != nil {
630635
slog.Debug("User schema not found, using default search_path.", "user", username)
631636
// Clear the aborted transaction state before retrying.
632637
_, _ = conn.ExecContext(context.Background(), "ROLLBACK")
633-
if _, err := conn.ExecContext(context.Background(), "SET search_path = 'main'"); err != nil {
638+
if _, err := conn.ExecContext(context.Background(), "SET search_path = 'main,memory.main'"); err != nil {
634639
slog.Warn("Failed to set search_path for session.", "user", username, "error", err)
635640
}
636641
}

duckdbservice/service_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ func TestInitSearchPath(t *testing.T) {
2929
if err := conn.QueryRowContext(context.Background(), "SELECT current_setting('search_path')").Scan(&searchPath); err != nil {
3030
t.Fatalf("failed to query search_path: %v", err)
3131
}
32-
if searchPath != "main" {
33-
t.Errorf("expected search_path 'main', got %q", searchPath)
32+
if searchPath != "main,memory.main" {
33+
t.Errorf("expected search_path 'main,memory.main', got %q", searchPath)
3434
}
3535
})
3636

@@ -52,8 +52,8 @@ func TestInitSearchPath(t *testing.T) {
5252
if err := conn.QueryRowContext(context.Background(), "SELECT current_setting('search_path')").Scan(&searchPath); err != nil {
5353
t.Fatalf("failed to query search_path: %v", err)
5454
}
55-
if searchPath != "myuser,main" {
56-
t.Errorf("expected search_path 'myuser,main', got %q", searchPath)
55+
if searchPath != "myuser,main,memory.main" {
56+
t.Errorf("expected search_path 'myuser,main,memory.main', got %q", searchPath)
5757
}
5858
})
5959
}

server/server.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,12 +1265,6 @@ func setDuckLakeDefault(db *sql.DB) error {
12651265
if _, err := db.Exec("USE ducklake"); err != nil {
12661266
return fmt.Errorf("failed to set DuckLake as default catalog: %w", err)
12671267
}
1268-
// Include memory.main in the search path so pg_catalog macros (pg_get_userbyid,
1269-
// format_type, etc.) created in memory.main are resolvable. Without this, psql
1270-
// commands like \dt fail because DuckDB doesn't resolve functions across catalogs.
1271-
if _, err := db.Exec("SET search_path = 'ducklake.main,memory.main'"); err != nil {
1272-
return fmt.Errorf("failed to set search_path for DuckLake: %w", err)
1273-
}
12741268
slog.Info("Set DuckLake as default catalog.")
12751269
return nil
12761270
}

0 commit comments

Comments
 (0)