@sixb/ducklake 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -60,21 +60,50 @@ export function buildSetPostgresPoolSql(
60
60
  * Render a fully-qualified DuckLake metadata table path.
61
61
  *
62
62
  * PostgreSQL catalogs expose DuckLake metadata tables under the configured
63
- * metadata schema inside the attached metadata catalog. Local catalogs use
64
- * DuckDB's default `main` schema.
63
+ * metadata schema (PostgreSQL's `public` by default) inside the attached
64
+ * metadata catalog. Local catalogs use DuckDB's default `main` schema.
65
65
  */
66
66
  export function duckLakeMetadataTableName(
67
67
  options: Pick<DuckLakeStorageOptions, "alias" | "catalog">,
68
68
  tableName: string
69
69
  ): string {
70
- const schemaName =
71
- options.catalog.type === "postgres" ? (options.catalog.metadataSchema ?? "main") : "main"
72
-
73
70
  return `${quoteIdentifier(duckLakeMetadataCatalog(options))}.${quoteIdentifier(
74
- schemaName
71
+ duckLakeMetadataSchema(options)
75
72
  )}.${quoteIdentifier(tableName)}`
76
73
  }
77
74
 
75
+ /**
76
+ * Render a metadata query that runs where the catalog lives.
77
+ *
78
+ * DuckDB's PostgreSQL scanner pushes comparisons and constant IN lists down to PostgreSQL, but not
79
+ * string matching, so a query that filters on text would copy the whole column into DuckDB. On a
80
+ * PostgreSQL catalog the query therefore runs server-side through `postgres_query`; elsewhere the
81
+ * catalog is local and DuckDB runs it. `build` must produce SQL that both dialects accept.
82
+ */
83
+ export function buildDuckLakeMetadataQuery(
84
+ options: Pick<DuckLakeStorageOptions, "alias" | "catalog">,
85
+ build: (table: (tableName: string) => string) => string
86
+ ): string {
87
+ if (options.catalog.type !== "postgres") {
88
+ return build((tableName) => duckLakeMetadataTableName(options, tableName))
89
+ }
90
+
91
+ // Unqualified names follow the connection's search path, as DuckLake's own writes do.
92
+ const schema = options.catalog.metadataSchema
93
+ const sql = build((tableName) =>
94
+ schema === undefined
95
+ ? quoteIdentifier(tableName)
96
+ : `${quoteIdentifier(schema)}.${quoteIdentifier(tableName)}`
97
+ )
98
+ return `SELECT * FROM postgres_query(${quoteSqlString(duckLakeMetadataCatalog(options))}, ${quoteSqlString(sql)})`
99
+ }
100
+
101
+ function duckLakeMetadataSchema(options: Pick<DuckLakeStorageOptions, "catalog">): string {
102
+ if (options.catalog.type !== "postgres") return "main"
103
+ // Without a metadata schema DuckLake writes to PostgreSQL's default schema.
104
+ return options.catalog.metadataSchema ?? "public"
105
+ }
106
+
78
107
  /**
79
108
  * Quote a SQL identifier after validating it is already identifier-shaped.
80
109
  *