@query-farm/vgi 0.29.0 → 0.29.1
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.
- package/README.md +26 -1
- package/dist/arguments/argument-spec.d.ts +4 -2
- package/dist/catalog/composite.d.ts +13 -13
- package/dist/catalog/descriptors.d.ts +7 -3
- package/dist/catalog/interface.d.ts +67 -40
- package/dist/catalog/read-only.d.ts +32 -15
- package/dist/client/client.d.ts +36 -29
- package/dist/client/types.d.ts +2 -0
- package/dist/client-entry.d.ts +1 -1
- package/dist/client-entry.js +441 -279
- package/dist/client-entry.js.map +12 -11
- package/dist/filter-pushdown/capabilities.d.ts +3 -0
- package/dist/filter-pushdown/deserialize.d.ts +14 -15
- package/dist/filter-pushdown/evaluate.d.ts +14 -44
- package/dist/filter-pushdown/index.d.ts +2 -2
- package/dist/filter-pushdown/types.d.ts +120 -68
- package/dist/functions/aggregate.d.ts +4 -0
- package/dist/functions/registry.d.ts +5 -5
- package/dist/functions/scalar.d.ts +6 -1
- package/dist/functions/table-buffering.d.ts +9 -0
- package/dist/functions/table-in-out.d.ts +13 -0
- package/dist/functions/table.d.ts +9 -2
- package/dist/functions/types.d.ts +22 -2
- package/dist/generated/vgi-client.d.ts +56 -27
- package/dist/generated/vgi-protocol-schemas.d.ts +15 -0
- package/dist/http/fetch.d.ts +7 -1
- package/dist/index.core.d.ts +2 -1
- package/dist/index.js +2317 -1354
- package/dist/index.js.map +43 -40
- package/dist/metadata/types.d.ts +15 -2
- package/dist/protocol/handlers/shared.d.ts +3 -1
- package/dist/protocol/serializers/splits.d.ts +1 -1
- package/dist/protocol/types.d.ts +9 -3
- package/dist/schema-path.d.ts +7 -0
- package/dist/serve-entry.d.ts +22 -1
- package/dist/serve-entry.js +412 -238
- package/dist/serve-entry.js.map +27 -26
- package/dist/split-token.d.ts +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/worker-cf-entry.js +2030 -1201
- package/dist/worker-cf-entry.js.map +40 -36
- package/dist/worker.d.ts +1 -1
- package/package.json +3 -3
- package/src/arguments/argument-spec.ts +12 -4
- package/src/catalog/composite.ts +26 -26
- package/src/catalog/descriptors.ts +12 -3
- package/src/catalog/interface.ts +98 -48
- package/src/catalog/read-only.ts +124 -67
- package/src/client/client.ts +92 -72
- package/src/client/types.ts +2 -0
- package/src/client-entry.ts +2 -1
- package/src/filter-pushdown/capabilities.ts +13 -0
- package/src/filter-pushdown/collector.ts +22 -35
- package/src/filter-pushdown/deserialize.ts +657 -221
- package/src/filter-pushdown/evaluate.ts +410 -499
- package/src/filter-pushdown/index.ts +16 -2
- package/src/filter-pushdown/types.ts +88 -71
- package/src/functions/aggregate.ts +9 -1
- package/src/functions/registry.ts +24 -22
- package/src/functions/scalar.ts +26 -0
- package/src/functions/table-buffering.ts +46 -7
- package/src/functions/table-in-out.ts +187 -30
- package/src/functions/table.ts +58 -20
- package/src/functions/types.ts +24 -1
- package/src/generated/vgi-client.ts +61 -29
- package/src/generated/vgi-protocol-schemas.ts +225 -54
- package/src/http/fetch.ts +12 -0
- package/src/index.core.ts +2 -0
- package/src/metadata/resolve.ts +43 -1
- package/src/metadata/serialize.ts +43 -5
- package/src/metadata/types.ts +17 -1
- package/src/protocol/dispatch.ts +1 -1
- package/src/protocol/handlers/aggregate.ts +13 -7
- package/src/protocol/handlers/catalog/admin.ts +6 -6
- package/src/protocol/handlers/catalog/index_methods.ts +2 -2
- package/src/protocol/handlers/catalog/macro.ts +4 -4
- package/src/protocol/handlers/catalog/shared.ts +2 -0
- package/src/protocol/handlers/catalog/table.ts +16 -16
- package/src/protocol/handlers/catalog/view.ts +5 -5
- package/src/protocol/handlers/function.ts +2 -2
- package/src/protocol/handlers/shared.ts +12 -3
- package/src/protocol/handlers/table-buffering.ts +4 -4
- package/src/protocol/serializers/bind.ts +15 -6
- package/src/protocol/serializers/splits.ts +4 -2
- package/src/protocol/types.ts +9 -3
- package/src/schema-path.ts +25 -0
- package/src/serve-entry.ts +65 -3
- package/src/split-token.ts +2 -2
- package/src/types.ts +9 -0
- package/src/worker.ts +49 -4
package/dist/worker.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FunctionRegistry } from "./functions/registry.js";
|
|
2
2
|
import type { VgiFunction } from "./functions/types.js";
|
|
3
|
-
import type
|
|
3
|
+
import { type CatalogDescriptor } from "./catalog/descriptors.js";
|
|
4
4
|
import type { CatalogInterface } from "./catalog/interface.js";
|
|
5
5
|
import { ReadOnlyCatalogInterface } from "./catalog/read-only.js";
|
|
6
6
|
export interface WorkerConfig {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@query-farm/vgi",
|
|
3
|
-
"version": "0.29.
|
|
3
|
+
"version": "0.29.1",
|
|
4
4
|
"description": "TypeScript framework for extending DuckDB with user-defined functions via the Vector Gateway Interface (VGI) over Arrow IPC.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": "Query Farm LLC (https://query.farm)",
|
|
@@ -90,12 +90,12 @@
|
|
|
90
90
|
},
|
|
91
91
|
"peerDependencies": {
|
|
92
92
|
"@query-farm/apache-arrow": "^21.1.1",
|
|
93
|
-
"@query-farm/vgi-rpc": ">=0.
|
|
93
|
+
"@query-farm/vgi-rpc": ">=0.23.0 <0.24.0"
|
|
94
94
|
},
|
|
95
95
|
"devDependencies": {
|
|
96
96
|
"@duckdb/node-api": "^1.5.5-r.4",
|
|
97
97
|
"@query-farm/apache-arrow": "^21.1.1",
|
|
98
|
-
"@query-farm/vgi-rpc": "^0.
|
|
98
|
+
"@query-farm/vgi-rpc": "^0.23.0",
|
|
99
99
|
"@types/bun": "latest",
|
|
100
100
|
"typescript": "^7.0.2"
|
|
101
101
|
},
|
|
@@ -120,20 +120,28 @@ export function formatRange(
|
|
|
120
120
|
/**
|
|
121
121
|
* Encode raw {@link ArgumentConstraints} into the pre-computed constraint
|
|
122
122
|
* fields of an {@link ArgumentSpec} (presence-only — absent constraints yield
|
|
123
|
-
* no field).
|
|
123
|
+
* no field). `runtimeDefault`, when present, is authoritative for
|
|
124
|
+
* `defaultJson`, keeping runtime binding and discovery metadata in sync.
|
|
125
|
+
* Mirrors Python's `_constraint_kwargs`.
|
|
124
126
|
*/
|
|
125
127
|
export function constraintSpecFields(
|
|
126
128
|
constraints: ArgumentConstraints | undefined,
|
|
129
|
+
runtimeDefault?: unknown,
|
|
127
130
|
): Pick<ArgumentSpec, "defaultJson" | "choicesJson" | "rangeNotation" | "pattern"> {
|
|
128
131
|
const fields: Pick<
|
|
129
132
|
ArgumentSpec,
|
|
130
133
|
"defaultJson" | "choicesJson" | "rangeNotation" | "pattern"
|
|
131
134
|
> = {};
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
+
// argDefaults is the runtime source of truth. Surface that same value to
|
|
136
|
+
// discovery so callers do not have to duplicate it as
|
|
137
|
+
// argConstraints[name].default. Keep the latter as a backwards-compatible
|
|
138
|
+
// discovery-only fallback for APIs that do not have a runtime default.
|
|
139
|
+
if (runtimeDefault !== undefined) {
|
|
140
|
+
fields.defaultJson = safeJson(runtimeDefault);
|
|
141
|
+
} else if (constraints !== undefined && "default" in constraints && constraints.default !== undefined) {
|
|
135
142
|
fields.defaultJson = safeJson(constraints.default);
|
|
136
143
|
}
|
|
144
|
+
if (constraints === undefined) return fields;
|
|
137
145
|
if (constraints.choices !== undefined) {
|
|
138
146
|
fields.choicesJson = safeJson([...constraints.choices]);
|
|
139
147
|
}
|
package/src/catalog/composite.ts
CHANGED
|
@@ -119,56 +119,56 @@ export class CompositeCatalogInterface extends CatalogInterface {
|
|
|
119
119
|
return await this._route(attachOpaqueData).schemas(attachOpaqueData, transactionOpaqueData);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
override async schemaGet(attachOpaqueData: AttachOpaqueData,
|
|
123
|
-
return await this._route(attachOpaqueData).schemaGet(attachOpaqueData,
|
|
122
|
+
override async schemaGet(attachOpaqueData: AttachOpaqueData, path: string[], transactionOpaqueData?: TransactionOpaqueData): Promise<SchemaInfo | null> {
|
|
123
|
+
return await this._route(attachOpaqueData).schemaGet(attachOpaqueData, path, transactionOpaqueData);
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
override async schemaContentsTables(attachOpaqueData: AttachOpaqueData,
|
|
127
|
-
return await this._route(attachOpaqueData).schemaContentsTables(attachOpaqueData,
|
|
126
|
+
override async schemaContentsTables(attachOpaqueData: AttachOpaqueData, path: string[], transactionOpaqueData?: TransactionOpaqueData): Promise<TableInfo[]> {
|
|
127
|
+
return await this._route(attachOpaqueData).schemaContentsTables(attachOpaqueData, path, transactionOpaqueData);
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
override async schemaContentsViews(attachOpaqueData: AttachOpaqueData,
|
|
131
|
-
return await this._route(attachOpaqueData).schemaContentsViews(attachOpaqueData,
|
|
130
|
+
override async schemaContentsViews(attachOpaqueData: AttachOpaqueData, path: string[], transactionOpaqueData?: TransactionOpaqueData): Promise<ViewInfo[]> {
|
|
131
|
+
return await this._route(attachOpaqueData).schemaContentsViews(attachOpaqueData, path, transactionOpaqueData);
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
override async schemaContentsFunctions(attachOpaqueData: AttachOpaqueData,
|
|
135
|
-
return await this._route(attachOpaqueData).schemaContentsFunctions(attachOpaqueData,
|
|
134
|
+
override async schemaContentsFunctions(attachOpaqueData: AttachOpaqueData, path: string[], type: string, transactionOpaqueData?: TransactionOpaqueData): Promise<FunctionInfo[]> {
|
|
135
|
+
return await this._route(attachOpaqueData).schemaContentsFunctions(attachOpaqueData, path, type, transactionOpaqueData);
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
override async schemaContentsMacros(attachOpaqueData: AttachOpaqueData,
|
|
139
|
-
return await this._route(attachOpaqueData).schemaContentsMacros(attachOpaqueData,
|
|
138
|
+
override async schemaContentsMacros(attachOpaqueData: AttachOpaqueData, path: string[], type: string, transactionOpaqueData?: TransactionOpaqueData): Promise<MacroInfo[]> {
|
|
139
|
+
return await this._route(attachOpaqueData).schemaContentsMacros(attachOpaqueData, path, type, transactionOpaqueData);
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
override async schemaContentsIndexes(attachOpaqueData: AttachOpaqueData,
|
|
143
|
-
return await this._route(attachOpaqueData).schemaContentsIndexes(attachOpaqueData,
|
|
142
|
+
override async schemaContentsIndexes(attachOpaqueData: AttachOpaqueData, path: string[], transactionOpaqueData?: TransactionOpaqueData): Promise<IndexInfo[]> {
|
|
143
|
+
return await this._route(attachOpaqueData).schemaContentsIndexes(attachOpaqueData, path, transactionOpaqueData);
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
override async indexGet(attachOpaqueData: AttachOpaqueData,
|
|
147
|
-
return await this._route(attachOpaqueData).indexGet(attachOpaqueData,
|
|
146
|
+
override async indexGet(attachOpaqueData: AttachOpaqueData, schemaPath: string[], name: string, transactionOpaqueData?: TransactionOpaqueData): Promise<IndexInfo | null> {
|
|
147
|
+
return await this._route(attachOpaqueData).indexGet(attachOpaqueData, schemaPath, name, transactionOpaqueData);
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
override async tableGet(attachOpaqueData: AttachOpaqueData,
|
|
151
|
-
return await this._route(attachOpaqueData).tableGet(attachOpaqueData,
|
|
150
|
+
override async tableGet(attachOpaqueData: AttachOpaqueData, schemaPath: string[], name: string, atUnit?: string, atValue?: string, transactionOpaqueData?: TransactionOpaqueData): Promise<TableInfo | null> {
|
|
151
|
+
return await this._route(attachOpaqueData).tableGet(attachOpaqueData, schemaPath, name, atUnit, atValue, transactionOpaqueData);
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
override async tableScanFunctionGet(attachOpaqueData: AttachOpaqueData,
|
|
155
|
-
return await this._route(attachOpaqueData).tableScanFunctionGet(attachOpaqueData,
|
|
154
|
+
override async tableScanFunctionGet(attachOpaqueData: AttachOpaqueData, schemaPath: string[], name: string, atUnit?: string, atValue?: string, transactionOpaqueData?: TransactionOpaqueData): Promise<any> {
|
|
155
|
+
return await this._route(attachOpaqueData).tableScanFunctionGet(attachOpaqueData, schemaPath, name, atUnit, atValue, transactionOpaqueData);
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
override async tableScanBranchesGet(attachOpaqueData: AttachOpaqueData,
|
|
159
|
-
return await this._route(attachOpaqueData).tableScanBranchesGet(attachOpaqueData,
|
|
158
|
+
override async tableScanBranchesGet(attachOpaqueData: AttachOpaqueData, schemaPath: string[], name: string, atUnit?: string, atValue?: string, transactionOpaqueData?: TransactionOpaqueData): Promise<any> {
|
|
159
|
+
return await this._route(attachOpaqueData).tableScanBranchesGet(attachOpaqueData, schemaPath, name, atUnit, atValue, transactionOpaqueData);
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
override async tableColumnStatisticsGet(attachOpaqueData: AttachOpaqueData,
|
|
163
|
-
return await this._route(attachOpaqueData).tableColumnStatisticsGet(attachOpaqueData,
|
|
162
|
+
override async tableColumnStatisticsGet(attachOpaqueData: AttachOpaqueData, schemaPath: string[], name: string, transactionOpaqueData?: TransactionOpaqueData): Promise<{ bytes: Uint8Array; cacheMaxAgeSeconds: number | null } | null> {
|
|
163
|
+
return await this._route(attachOpaqueData).tableColumnStatisticsGet(attachOpaqueData, schemaPath, name, transactionOpaqueData);
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
override async viewGet(attachOpaqueData: AttachOpaqueData,
|
|
167
|
-
return await this._route(attachOpaqueData).viewGet(attachOpaqueData,
|
|
166
|
+
override async viewGet(attachOpaqueData: AttachOpaqueData, schemaPath: string[], name: string, transactionOpaqueData?: TransactionOpaqueData): Promise<ViewInfo | null> {
|
|
167
|
+
return await this._route(attachOpaqueData).viewGet(attachOpaqueData, schemaPath, name, transactionOpaqueData);
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
override async macroGet(attachOpaqueData: AttachOpaqueData,
|
|
171
|
-
return await this._route(attachOpaqueData).macroGet(attachOpaqueData,
|
|
170
|
+
override async macroGet(attachOpaqueData: AttachOpaqueData, schemaPath: string[], name: string, transactionOpaqueData?: TransactionOpaqueData): Promise<MacroInfo | null> {
|
|
171
|
+
return await this._route(attachOpaqueData).macroGet(attachOpaqueData, schemaPath, name, transactionOpaqueData);
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
override async copyFromFormats(attachOpaqueData: AttachOpaqueData, transactionOpaqueData?: TransactionOpaqueData): Promise<CopyFromFormatInfo[]> {
|
|
@@ -19,7 +19,7 @@ export interface ForeignKeyDef {
|
|
|
19
19
|
columns: string[];
|
|
20
20
|
referencedTable: string;
|
|
21
21
|
referencedColumns: string[];
|
|
22
|
-
|
|
22
|
+
referencedSchemaPath?: string[];
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export type DefaultValue = string | number | boolean | null;
|
|
@@ -137,7 +137,10 @@ export interface IndexDescriptor {
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
export interface SchemaDescriptor {
|
|
140
|
-
|
|
140
|
+
/** Raw identifier components, from the catalog root to this schema. */
|
|
141
|
+
path?: string[];
|
|
142
|
+
/** @deprecated Protocol 1.x compatibility; prefer `path: [name]`. */
|
|
143
|
+
name?: string;
|
|
141
144
|
tables?: TableDescriptor[];
|
|
142
145
|
views?: ViewDescriptor[];
|
|
143
146
|
macros?: MacroDescriptor[];
|
|
@@ -147,6 +150,12 @@ export interface SchemaDescriptor {
|
|
|
147
150
|
tags?: Record<string, string>;
|
|
148
151
|
}
|
|
149
152
|
|
|
153
|
+
export function schemaDescriptorPath(schema: SchemaDescriptor): string[] {
|
|
154
|
+
if (schema.path) return schema.path;
|
|
155
|
+
if (schema.name) return [schema.name];
|
|
156
|
+
throw new Error("SchemaDescriptor requires a non-empty path");
|
|
157
|
+
}
|
|
158
|
+
|
|
150
159
|
export interface SecretTypeDescriptor {
|
|
151
160
|
name: string;
|
|
152
161
|
description: string;
|
|
@@ -180,7 +189,7 @@ export interface CatalogDescriptor {
|
|
|
180
189
|
* records on `catalog_attach.global_functions`.
|
|
181
190
|
*
|
|
182
191
|
* Every entry must also be declared in exactly one of this catalog's
|
|
183
|
-
* schemas — the `FunctionInfo.
|
|
192
|
+
* schemas — the `FunctionInfo.schema_path` it carries is the bind-dispatch
|
|
184
193
|
* key, not a sentinel. Mirrors vgi-python's `Catalog.global_functions`.
|
|
185
194
|
*/
|
|
186
195
|
globalFunctions?: VgiFunction[];
|
package/src/catalog/interface.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// Matching Python's vgi/catalog/catalog_interface.py
|
|
4
4
|
|
|
5
5
|
import { CatalogReadOnlyError } from "../errors.js";
|
|
6
|
+
import { schemaPathsEqual } from "../schema-path.js";
|
|
6
7
|
|
|
7
8
|
export type AttachOpaqueData = Uint8Array;
|
|
8
9
|
export type TransactionOpaqueData = Uint8Array;
|
|
@@ -179,11 +180,20 @@ export interface ScanFunctionResult {
|
|
|
179
180
|
namedArguments: Record<string, unknown>;
|
|
180
181
|
/** DuckDB extensions to load before calling the function. */
|
|
181
182
|
requiredExtensions: string[];
|
|
183
|
+
/**
|
|
184
|
+
* Catalog schema path `functionName` is registered in (protocol 2.0.0). A function
|
|
185
|
+
* name is unique only within a schema, so a client that doesn't know this
|
|
186
|
+
* cannot tell which implementation a colliding name refers to — set it
|
|
187
|
+
* whenever the resolving code already knows the schema. `null` for a
|
|
188
|
+
* pre-1.5.0 peer, or when the resolved function is a native DuckDB function
|
|
189
|
+
* with no VGI-side schema of its own (e.g. `read_parquet`).
|
|
190
|
+
*/
|
|
191
|
+
schemaPath: string[] | null;
|
|
182
192
|
}
|
|
183
193
|
|
|
184
194
|
/**
|
|
185
195
|
* Encode a ScanFunctionResult wire record — the single-row batch shape
|
|
186
|
-
* `{ function_name, arguments, required_extensions }` that
|
|
196
|
+
* `{ function_name, arguments, required_extensions, schema_path }` that
|
|
187
197
|
* `catalog_table_scan_function_get` returns and that a function-backed table
|
|
188
198
|
* inlines into `TableInfo.scan_function`.
|
|
189
199
|
*
|
|
@@ -194,11 +204,15 @@ export interface ScanFunctionResult {
|
|
|
194
204
|
*
|
|
195
205
|
* `argumentsBytes` is the already-serialized inner arguments batch (one column
|
|
196
206
|
* per argument: `arg_<index>` positional, bare name for named).
|
|
207
|
+
*
|
|
208
|
+
* `schemaPath` (protocol 2.0.0) identifies the schema that registers `functionName`;
|
|
209
|
+
* leave it null when the caller has no VGI-side schema to report.
|
|
197
210
|
*/
|
|
198
211
|
export function encodeScanFunctionResult(
|
|
199
212
|
functionName: string,
|
|
200
213
|
argumentsBytes: Uint8Array,
|
|
201
214
|
requiredExtensions: string[] = [],
|
|
215
|
+
schemaPath: string[] | null = null,
|
|
202
216
|
): Uint8Array {
|
|
203
217
|
return serializeBatch(
|
|
204
218
|
batchFromColumns(
|
|
@@ -206,6 +220,7 @@ export function encodeScanFunctionResult(
|
|
|
206
220
|
function_name: [functionName],
|
|
207
221
|
arguments: [argumentsBytes],
|
|
208
222
|
required_extensions: [requiredExtensions],
|
|
223
|
+
schema_path: [schemaPath],
|
|
209
224
|
},
|
|
210
225
|
ScanFunctionResultSchema as any,
|
|
211
226
|
),
|
|
@@ -216,9 +231,10 @@ export function encodeScanFunctionResult(
|
|
|
216
231
|
* Decode a ScanFunctionResult from a wire-shape inner result dict.
|
|
217
232
|
*
|
|
218
233
|
* The wire shape (per ScanFunctionResultSchema) is
|
|
219
|
-
* `{ function_name: utf8, arguments: binary, required_extensions: list<utf8
|
|
220
|
-
* where `arguments` is a serialized single-row batch
|
|
221
|
-
* argument: `arg_<index>` for positional args, the bare
|
|
234
|
+
* `{ function_name: utf8, arguments: binary, required_extensions: list<utf8>,
|
|
235
|
+
* schema_path: list<utf8>? }`, where `arguments` is a serialized single-row batch
|
|
236
|
+
* with one column per argument: `arg_<index>` for positional args, the bare
|
|
237
|
+
* name for named args.
|
|
222
238
|
*/
|
|
223
239
|
export function decodeScanFunctionResult(inner: Record<string, unknown>): ScanFunctionResult {
|
|
224
240
|
const argsBytes = inner.arguments;
|
|
@@ -252,6 +268,13 @@ export function decodeScanFunctionResult(inner: Record<string, unknown>): ScanFu
|
|
|
252
268
|
positionalArguments,
|
|
253
269
|
namedArguments,
|
|
254
270
|
requiredExtensions,
|
|
271
|
+
// Absent for a pre-1.5.0 peer — the column itself won't be on the wire in
|
|
272
|
+
// that case, which reads the same as "present but null".
|
|
273
|
+
schemaPath: inner.schema_path == null
|
|
274
|
+
? null
|
|
275
|
+
: (Array.isArray(inner.schema_path) ? inner.schema_path : [...(inner.schema_path as Iterable<unknown>)])
|
|
276
|
+
.filter((value) => value != null)
|
|
277
|
+
.map(String),
|
|
255
278
|
};
|
|
256
279
|
}
|
|
257
280
|
|
|
@@ -266,11 +289,23 @@ export function decodeScanFunctionResult(inner: Record<string, unknown>): ScanFu
|
|
|
266
289
|
* `ScanBranch` expects, so it passes through untouched.
|
|
267
290
|
*/
|
|
268
291
|
export function singleBranchResult(
|
|
269
|
-
legacy: {
|
|
292
|
+
legacy: {
|
|
293
|
+
function_name: string;
|
|
294
|
+
arguments: unknown;
|
|
295
|
+
required_extensions?: string[];
|
|
296
|
+
schema_path?: string[] | null;
|
|
297
|
+
},
|
|
270
298
|
): { branches: Uint8Array[]; required_extensions: string[] } {
|
|
271
299
|
return {
|
|
272
300
|
branches: [
|
|
273
|
-
encodeScanBranch({
|
|
301
|
+
encodeScanBranch({
|
|
302
|
+
function_name: legacy.function_name,
|
|
303
|
+
arguments: toUint8Array(legacy.arguments),
|
|
304
|
+
// This shim has no independent way to know the function's own schema;
|
|
305
|
+
// propagate whatever `tableScanFunctionGet` already resolved rather
|
|
306
|
+
// than dropping a value the legacy response carries.
|
|
307
|
+
schema_path: legacy.schema_path ?? null,
|
|
308
|
+
}),
|
|
274
309
|
],
|
|
275
310
|
required_extensions: legacy.required_extensions ?? [],
|
|
276
311
|
};
|
|
@@ -296,11 +331,12 @@ function encodeScanBranch(cols: {
|
|
|
296
331
|
branch_filter?: string | null;
|
|
297
332
|
writable?: boolean;
|
|
298
333
|
source_catalog?: string | null;
|
|
299
|
-
|
|
334
|
+
source_schema_path?: string[] | null;
|
|
300
335
|
source_table?: string | null;
|
|
301
336
|
format_name?: string | null;
|
|
302
337
|
format_locations?: string[] | null;
|
|
303
338
|
format_options?: Uint8Array | null;
|
|
339
|
+
schema_path?: string[] | null;
|
|
304
340
|
}): Uint8Array {
|
|
305
341
|
return serializeBatch(
|
|
306
342
|
batchFromColumns(
|
|
@@ -310,11 +346,12 @@ function encodeScanBranch(cols: {
|
|
|
310
346
|
branch_filter: [cols.branch_filter ?? null],
|
|
311
347
|
writable: [cols.writable ?? false],
|
|
312
348
|
source_catalog: [cols.source_catalog ?? null],
|
|
313
|
-
|
|
349
|
+
source_schema_path: [cols.source_schema_path ?? null],
|
|
314
350
|
source_table: [cols.source_table ?? null],
|
|
315
351
|
format_name: [cols.format_name ?? null],
|
|
316
352
|
format_locations: [cols.format_locations ?? null],
|
|
317
353
|
format_options: [cols.format_options ?? null],
|
|
354
|
+
schema_path: [cols.schema_path ?? null],
|
|
318
355
|
},
|
|
319
356
|
ScanBranchSchema as any,
|
|
320
357
|
),
|
|
@@ -354,12 +391,25 @@ export interface ScanBranchInput {
|
|
|
354
391
|
/**
|
|
355
392
|
* Catalog-table branch (lakehouse federation): leave `functionName` empty and
|
|
356
393
|
* set these to scan the base table
|
|
357
|
-
* `sourceCatalog.
|
|
394
|
+
* `sourceCatalog.sourceSchemaPath.sourceTable` in a companion catalog instead of
|
|
358
395
|
* calling a table function.
|
|
359
396
|
*/
|
|
360
397
|
sourceCatalog?: string | null;
|
|
361
|
-
|
|
398
|
+
sourceSchemaPath?: string[] | null;
|
|
362
399
|
sourceTable?: string | null;
|
|
400
|
+
/**
|
|
401
|
+
* Function branch only — the catalog schema that registers `functionName`
|
|
402
|
+
* (protocol 2.0.0). Without it a client has to guess (the table's own
|
|
403
|
+
* schema, then the catalog's default schema) which implementation
|
|
404
|
+
* `functionName` refers to when the same name is registered in more than
|
|
405
|
+
* one schema. Leave unset for a catalog-table or FORMAT branch, and for a
|
|
406
|
+
* branch that delegates straight to a native DuckDB function
|
|
407
|
+
* (`read_parquet`, `read_csv_auto`, `iceberg_scan`, …) — neither has a
|
|
408
|
+
* VGI-side schema of its own to report, which is why the field is optional
|
|
409
|
+
* rather than required. Not to be confused with `sourceSchemaPath` above, which
|
|
410
|
+
* names a catalog-table branch's *source table's* schema.
|
|
411
|
+
*/
|
|
412
|
+
schemaPath?: string[] | null;
|
|
363
413
|
}
|
|
364
414
|
|
|
365
415
|
/**
|
|
@@ -431,11 +481,12 @@ export function buildScanBranchesResult(
|
|
|
431
481
|
branch_filter: branch.branchFilter,
|
|
432
482
|
writable: branch.writable,
|
|
433
483
|
source_catalog: branch.sourceCatalog,
|
|
434
|
-
|
|
484
|
+
source_schema_path: branch.sourceSchemaPath,
|
|
435
485
|
source_table: branch.sourceTable,
|
|
436
486
|
format_name: branch.formatName,
|
|
437
487
|
format_locations: branch.formatLocations,
|
|
438
488
|
format_options: branch.formatOptions,
|
|
489
|
+
schema_path: branch.schemaPath,
|
|
439
490
|
}),
|
|
440
491
|
);
|
|
441
492
|
return {
|
|
@@ -517,18 +568,18 @@ export abstract class CatalogInterface {
|
|
|
517
568
|
}
|
|
518
569
|
schemaGet(
|
|
519
570
|
attachOpaqueData: AttachOpaqueData,
|
|
520
|
-
|
|
571
|
+
path: string[],
|
|
521
572
|
transactionOpaqueData?: TransactionOpaqueData
|
|
522
573
|
): Awaitable<SchemaInfo | null> {
|
|
523
574
|
const all = this.schemas(attachOpaqueData, transactionOpaqueData);
|
|
524
575
|
if (isPromise(all)) {
|
|
525
|
-
return all.then((arr) => arr.find((s) => s.
|
|
576
|
+
return all.then((arr) => arr.find((s) => schemaPathsEqual(s.path, path)) ?? null);
|
|
526
577
|
}
|
|
527
|
-
return all.find((s) => s.
|
|
578
|
+
return all.find((s) => schemaPathsEqual(s.path, path)) ?? null;
|
|
528
579
|
}
|
|
529
580
|
schemaCreate(
|
|
530
581
|
attachOpaqueData: AttachOpaqueData,
|
|
531
|
-
|
|
582
|
+
path: string[],
|
|
532
583
|
comment?: string | null,
|
|
533
584
|
tags?: any,
|
|
534
585
|
transactionOpaqueData?: TransactionOpaqueData
|
|
@@ -537,7 +588,7 @@ export abstract class CatalogInterface {
|
|
|
537
588
|
}
|
|
538
589
|
schemaDrop(
|
|
539
590
|
attachOpaqueData: AttachOpaqueData,
|
|
540
|
-
|
|
591
|
+
path: string[],
|
|
541
592
|
ignoreNotFound?: boolean,
|
|
542
593
|
cascade?: boolean,
|
|
543
594
|
transactionOpaqueData?: TransactionOpaqueData
|
|
@@ -546,21 +597,21 @@ export abstract class CatalogInterface {
|
|
|
546
597
|
}
|
|
547
598
|
schemaContentsTables(
|
|
548
599
|
attachOpaqueData: AttachOpaqueData,
|
|
549
|
-
|
|
600
|
+
path: string[],
|
|
550
601
|
transactionOpaqueData?: TransactionOpaqueData
|
|
551
602
|
): Awaitable<TableInfo[]> {
|
|
552
603
|
return [];
|
|
553
604
|
}
|
|
554
605
|
schemaContentsViews(
|
|
555
606
|
attachOpaqueData: AttachOpaqueData,
|
|
556
|
-
|
|
607
|
+
path: string[],
|
|
557
608
|
transactionOpaqueData?: TransactionOpaqueData
|
|
558
609
|
): Awaitable<ViewInfo[]> {
|
|
559
610
|
return [];
|
|
560
611
|
}
|
|
561
612
|
schemaContentsFunctions(
|
|
562
613
|
attachOpaqueData: AttachOpaqueData,
|
|
563
|
-
|
|
614
|
+
path: string[],
|
|
564
615
|
type: string,
|
|
565
616
|
transactionOpaqueData?: TransactionOpaqueData
|
|
566
617
|
): Awaitable<FunctionInfo[]> {
|
|
@@ -568,7 +619,7 @@ export abstract class CatalogInterface {
|
|
|
568
619
|
}
|
|
569
620
|
tableGet(
|
|
570
621
|
attachOpaqueData: AttachOpaqueData,
|
|
571
|
-
|
|
622
|
+
schemaPath: string[],
|
|
572
623
|
name: string,
|
|
573
624
|
atUnit?: string,
|
|
574
625
|
atValue?: string,
|
|
@@ -578,7 +629,7 @@ export abstract class CatalogInterface {
|
|
|
578
629
|
}
|
|
579
630
|
tableCreate(
|
|
580
631
|
attachOpaqueData: AttachOpaqueData,
|
|
581
|
-
|
|
632
|
+
schemaPath: string[],
|
|
582
633
|
name: string,
|
|
583
634
|
columns: Uint8Array,
|
|
584
635
|
onConflict: string,
|
|
@@ -591,7 +642,7 @@ export abstract class CatalogInterface {
|
|
|
591
642
|
}
|
|
592
643
|
tableDrop(
|
|
593
644
|
attachOpaqueData: AttachOpaqueData,
|
|
594
|
-
|
|
645
|
+
schemaPath: string[],
|
|
595
646
|
name: string,
|
|
596
647
|
ignoreNotFound?: boolean,
|
|
597
648
|
transactionOpaqueData?: TransactionOpaqueData
|
|
@@ -600,7 +651,7 @@ export abstract class CatalogInterface {
|
|
|
600
651
|
}
|
|
601
652
|
tableScanFunctionGet(
|
|
602
653
|
attachOpaqueData: AttachOpaqueData,
|
|
603
|
-
|
|
654
|
+
schemaPath: string[],
|
|
604
655
|
name: string,
|
|
605
656
|
atUnit?: string,
|
|
606
657
|
atValue?: string,
|
|
@@ -616,14 +667,14 @@ export abstract class CatalogInterface {
|
|
|
616
667
|
*/
|
|
617
668
|
tableScanBranchesGet(
|
|
618
669
|
attachOpaqueData: AttachOpaqueData,
|
|
619
|
-
|
|
670
|
+
schemaPath: string[],
|
|
620
671
|
name: string,
|
|
621
672
|
atUnit?: string,
|
|
622
673
|
atValue?: string,
|
|
623
674
|
transactionOpaqueData?: TransactionOpaqueData
|
|
624
675
|
): Awaitable<any> {
|
|
625
676
|
const legacy = this.tableScanFunctionGet(
|
|
626
|
-
attachOpaqueData,
|
|
677
|
+
attachOpaqueData, schemaPath, name, atUnit, atValue, transactionOpaqueData,
|
|
627
678
|
);
|
|
628
679
|
return isPromise(legacy)
|
|
629
680
|
? legacy.then((r) => singleBranchResult(r))
|
|
@@ -639,7 +690,7 @@ export abstract class CatalogInterface {
|
|
|
639
690
|
*/
|
|
640
691
|
tableColumnStatisticsGet(
|
|
641
692
|
attachOpaqueData: AttachOpaqueData,
|
|
642
|
-
|
|
693
|
+
schemaPath: string[],
|
|
643
694
|
name: string,
|
|
644
695
|
transactionOpaqueData?: TransactionOpaqueData,
|
|
645
696
|
): Awaitable<{ bytes: Uint8Array; cacheMaxAgeSeconds: number | null } | null> {
|
|
@@ -647,7 +698,7 @@ export abstract class CatalogInterface {
|
|
|
647
698
|
}
|
|
648
699
|
tableCommentSet(
|
|
649
700
|
attachOpaqueData: AttachOpaqueData,
|
|
650
|
-
|
|
701
|
+
schemaPath: string[],
|
|
651
702
|
name: string,
|
|
652
703
|
comment?: string | null,
|
|
653
704
|
ignoreNotFound?: boolean,
|
|
@@ -657,7 +708,7 @@ export abstract class CatalogInterface {
|
|
|
657
708
|
}
|
|
658
709
|
tableRename(
|
|
659
710
|
attachOpaqueData: AttachOpaqueData,
|
|
660
|
-
|
|
711
|
+
schemaPath: string[],
|
|
661
712
|
name: string,
|
|
662
713
|
newName: string,
|
|
663
714
|
ignoreNotFound?: boolean,
|
|
@@ -667,7 +718,7 @@ export abstract class CatalogInterface {
|
|
|
667
718
|
}
|
|
668
719
|
tableColumnAdd(
|
|
669
720
|
attachOpaqueData: AttachOpaqueData,
|
|
670
|
-
|
|
721
|
+
schemaPath: string[],
|
|
671
722
|
name: string,
|
|
672
723
|
columnName: string,
|
|
673
724
|
columnType: string,
|
|
@@ -679,7 +730,7 @@ export abstract class CatalogInterface {
|
|
|
679
730
|
}
|
|
680
731
|
tableColumnDrop(
|
|
681
732
|
attachOpaqueData: AttachOpaqueData,
|
|
682
|
-
|
|
733
|
+
schemaPath: string[],
|
|
683
734
|
name: string,
|
|
684
735
|
columnName: string,
|
|
685
736
|
ignoreNotFound?: boolean,
|
|
@@ -689,7 +740,7 @@ export abstract class CatalogInterface {
|
|
|
689
740
|
}
|
|
690
741
|
tableColumnRename(
|
|
691
742
|
attachOpaqueData: AttachOpaqueData,
|
|
692
|
-
|
|
743
|
+
schemaPath: string[],
|
|
693
744
|
name: string,
|
|
694
745
|
columnName: string,
|
|
695
746
|
newName: string,
|
|
@@ -700,7 +751,7 @@ export abstract class CatalogInterface {
|
|
|
700
751
|
}
|
|
701
752
|
tableColumnDefaultSet(
|
|
702
753
|
attachOpaqueData: AttachOpaqueData,
|
|
703
|
-
|
|
754
|
+
schemaPath: string[],
|
|
704
755
|
name: string,
|
|
705
756
|
columnName: string,
|
|
706
757
|
defaultValue: string,
|
|
@@ -711,7 +762,7 @@ export abstract class CatalogInterface {
|
|
|
711
762
|
}
|
|
712
763
|
tableColumnDefaultDrop(
|
|
713
764
|
attachOpaqueData: AttachOpaqueData,
|
|
714
|
-
|
|
765
|
+
schemaPath: string[],
|
|
715
766
|
name: string,
|
|
716
767
|
columnName: string,
|
|
717
768
|
ignoreNotFound?: boolean,
|
|
@@ -721,7 +772,7 @@ export abstract class CatalogInterface {
|
|
|
721
772
|
}
|
|
722
773
|
tableColumnTypeChange(
|
|
723
774
|
attachOpaqueData: AttachOpaqueData,
|
|
724
|
-
|
|
775
|
+
schemaPath: string[],
|
|
725
776
|
name: string,
|
|
726
777
|
columnName: string,
|
|
727
778
|
newType: string,
|
|
@@ -732,7 +783,7 @@ export abstract class CatalogInterface {
|
|
|
732
783
|
}
|
|
733
784
|
tableNotNullSet(
|
|
734
785
|
attachOpaqueData: AttachOpaqueData,
|
|
735
|
-
|
|
786
|
+
schemaPath: string[],
|
|
736
787
|
name: string,
|
|
737
788
|
columnName: string,
|
|
738
789
|
ignoreNotFound?: boolean,
|
|
@@ -742,7 +793,7 @@ export abstract class CatalogInterface {
|
|
|
742
793
|
}
|
|
743
794
|
tableNotNullDrop(
|
|
744
795
|
attachOpaqueData: AttachOpaqueData,
|
|
745
|
-
|
|
796
|
+
schemaPath: string[],
|
|
746
797
|
name: string,
|
|
747
798
|
columnName: string,
|
|
748
799
|
ignoreNotFound?: boolean,
|
|
@@ -752,7 +803,7 @@ export abstract class CatalogInterface {
|
|
|
752
803
|
}
|
|
753
804
|
viewGet(
|
|
754
805
|
attachOpaqueData: AttachOpaqueData,
|
|
755
|
-
|
|
806
|
+
schemaPath: string[],
|
|
756
807
|
name: string,
|
|
757
808
|
transactionOpaqueData?: TransactionOpaqueData
|
|
758
809
|
): Awaitable<ViewInfo | null> {
|
|
@@ -760,7 +811,7 @@ export abstract class CatalogInterface {
|
|
|
760
811
|
}
|
|
761
812
|
viewCreate(
|
|
762
813
|
attachOpaqueData: AttachOpaqueData,
|
|
763
|
-
|
|
814
|
+
schemaPath: string[],
|
|
764
815
|
name: string,
|
|
765
816
|
definition: string,
|
|
766
817
|
onConflict: string,
|
|
@@ -770,7 +821,7 @@ export abstract class CatalogInterface {
|
|
|
770
821
|
}
|
|
771
822
|
viewDrop(
|
|
772
823
|
attachOpaqueData: AttachOpaqueData,
|
|
773
|
-
|
|
824
|
+
schemaPath: string[],
|
|
774
825
|
name: string,
|
|
775
826
|
ignoreNotFound?: boolean,
|
|
776
827
|
transactionOpaqueData?: TransactionOpaqueData
|
|
@@ -779,7 +830,7 @@ export abstract class CatalogInterface {
|
|
|
779
830
|
}
|
|
780
831
|
viewRename(
|
|
781
832
|
attachOpaqueData: AttachOpaqueData,
|
|
782
|
-
|
|
833
|
+
schemaPath: string[],
|
|
783
834
|
name: string,
|
|
784
835
|
newName: string,
|
|
785
836
|
ignoreNotFound?: boolean,
|
|
@@ -789,7 +840,7 @@ export abstract class CatalogInterface {
|
|
|
789
840
|
}
|
|
790
841
|
viewCommentSet(
|
|
791
842
|
attachOpaqueData: AttachOpaqueData,
|
|
792
|
-
|
|
843
|
+
schemaPath: string[],
|
|
793
844
|
name: string,
|
|
794
845
|
comment?: string | null,
|
|
795
846
|
ignoreNotFound?: boolean,
|
|
@@ -799,7 +850,7 @@ export abstract class CatalogInterface {
|
|
|
799
850
|
}
|
|
800
851
|
macroGet(
|
|
801
852
|
attachOpaqueData: AttachOpaqueData,
|
|
802
|
-
|
|
853
|
+
schemaPath: string[],
|
|
803
854
|
name: string,
|
|
804
855
|
transactionOpaqueData?: TransactionOpaqueData
|
|
805
856
|
): Awaitable<MacroInfo | null> {
|
|
@@ -807,7 +858,7 @@ export abstract class CatalogInterface {
|
|
|
807
858
|
}
|
|
808
859
|
macroCreate(
|
|
809
860
|
attachOpaqueData: AttachOpaqueData,
|
|
810
|
-
|
|
861
|
+
schemaPath: string[],
|
|
811
862
|
name: string,
|
|
812
863
|
macroType: MacroType,
|
|
813
864
|
parameters: string[],
|
|
@@ -827,7 +878,7 @@ export abstract class CatalogInterface {
|
|
|
827
878
|
}
|
|
828
879
|
macroDrop(
|
|
829
880
|
attachOpaqueData: AttachOpaqueData,
|
|
830
|
-
|
|
881
|
+
schemaPath: string[],
|
|
831
882
|
name: string,
|
|
832
883
|
ignoreNotFound?: boolean,
|
|
833
884
|
transactionOpaqueData?: TransactionOpaqueData
|
|
@@ -836,7 +887,7 @@ export abstract class CatalogInterface {
|
|
|
836
887
|
}
|
|
837
888
|
schemaContentsMacros(
|
|
838
889
|
attachOpaqueData: AttachOpaqueData,
|
|
839
|
-
|
|
890
|
+
path: string[],
|
|
840
891
|
type: string,
|
|
841
892
|
transactionOpaqueData?: TransactionOpaqueData
|
|
842
893
|
): Awaitable<MacroInfo[]> {
|
|
@@ -844,14 +895,14 @@ export abstract class CatalogInterface {
|
|
|
844
895
|
}
|
|
845
896
|
schemaContentsIndexes(
|
|
846
897
|
attachOpaqueData: AttachOpaqueData,
|
|
847
|
-
|
|
898
|
+
path: string[],
|
|
848
899
|
transactionOpaqueData?: TransactionOpaqueData
|
|
849
900
|
): Awaitable<IndexInfo[]> {
|
|
850
901
|
return [];
|
|
851
902
|
}
|
|
852
903
|
indexGet(
|
|
853
904
|
attachOpaqueData: AttachOpaqueData,
|
|
854
|
-
|
|
905
|
+
schemaPath: string[],
|
|
855
906
|
name: string,
|
|
856
907
|
transactionOpaqueData?: TransactionOpaqueData
|
|
857
908
|
): Awaitable<IndexInfo | null> {
|
|
@@ -882,4 +933,3 @@ export abstract class CatalogInterface {
|
|
|
882
933
|
transactionOpaqueData: TransactionOpaqueData
|
|
883
934
|
): Awaitable<void> {}
|
|
884
935
|
}
|
|
885
|
-
|