@query-farm/vgi 0.6.0
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/LICENSE +134 -0
- package/README.md +494 -0
- package/dist/__dbg.test-d.d.ts +1 -0
- package/dist/arguments/argument-spec.d.ts +51 -0
- package/dist/arguments/arguments.d.ts +13 -0
- package/dist/arrow/codec/branded.d.ts +83 -0
- package/dist/arrow/codec/registry.d.ts +29 -0
- package/dist/arrow/codec/repr.d.ts +23 -0
- package/dist/arrow/codec/type-descriptors.d.ts +109 -0
- package/dist/arrow/impl-arrowjs/build.d.ts +19 -0
- package/dist/arrow/impl-arrowjs/canonical.d.ts +15 -0
- package/dist/arrow/impl-arrowjs/empty.d.ts +7 -0
- package/dist/arrow/impl-arrowjs/filter.d.ts +11 -0
- package/dist/arrow/impl-arrowjs/index.d.ts +11 -0
- package/dist/arrow/impl-arrowjs/ipc.d.ts +24 -0
- package/dist/arrow/impl-arrowjs/iterate.d.ts +39 -0
- package/dist/arrow/impl-arrowjs/project.d.ts +10 -0
- package/dist/arrow/impl-arrowjs/schema.d.ts +62 -0
- package/dist/arrow/impl-arrowjs/statistics.d.ts +13 -0
- package/dist/arrow/impl-flechette/build.d.ts +14 -0
- package/dist/arrow/impl-flechette/canonical.d.ts +18 -0
- package/dist/arrow/impl-flechette/empty.d.ts +9 -0
- package/dist/arrow/impl-flechette/filter.d.ts +10 -0
- package/dist/arrow/impl-flechette/index.d.ts +11 -0
- package/dist/arrow/impl-flechette/ipc.d.ts +33 -0
- package/dist/arrow/impl-flechette/iterate.d.ts +29 -0
- package/dist/arrow/impl-flechette/message-meta.d.ts +10 -0
- package/dist/arrow/impl-flechette/normalize-type.d.ts +11 -0
- package/dist/arrow/impl-flechette/project.d.ts +3 -0
- package/dist/arrow/impl-flechette/schema.d.ts +47 -0
- package/dist/arrow/impl-flechette/statistics.d.ts +13 -0
- package/dist/arrow/index.d.ts +11 -0
- package/dist/arrow/predicates.d.ts +47 -0
- package/dist/arrow/repr.test-d.d.ts +52 -0
- package/dist/arrow/schema-types.d.ts +71 -0
- package/dist/arrow/types.d.ts +57 -0
- package/dist/catalog/attach-option.d.ts +33 -0
- package/dist/catalog/attach-options.d.ts +30 -0
- package/dist/catalog/composite.d.ts +33 -0
- package/dist/catalog/descriptors.d.ts +154 -0
- package/dist/catalog/interface.d.ts +239 -0
- package/dist/catalog/read-only.d.ts +33 -0
- package/dist/client/client.d.ts +189 -0
- package/dist/client/errors.d.ts +26 -0
- package/dist/client/helpers.d.ts +12 -0
- package/dist/client/protocol.d.ts +16 -0
- package/dist/client/types.d.ts +125 -0
- package/dist/client-entry.d.ts +11 -0
- package/dist/client-entry.js +48 -0
- package/dist/client-entry.js.map +9 -0
- package/dist/codec/asd.d.ts +25 -0
- package/dist/crypto.d.ts +36 -0
- package/dist/errors.d.ts +24 -0
- package/dist/filter-pushdown/collector.d.ts +32 -0
- package/dist/filter-pushdown/deserialize.d.ts +16 -0
- package/dist/filter-pushdown/evaluate.d.ts +51 -0
- package/dist/filter-pushdown/index.d.ts +4 -0
- package/dist/filter-pushdown/types.d.ts +84 -0
- package/dist/functions/aggregate.d.ts +129 -0
- package/dist/functions/copy-from.d.ts +81 -0
- package/dist/functions/copy-to.d.ts +121 -0
- package/dist/functions/registry.d.ts +16 -0
- package/dist/functions/scalar.d.ts +98 -0
- package/dist/functions/storage-cf-do.d.ts +47 -0
- package/dist/functions/storage.d.ts +86 -0
- package/dist/functions/table-buffering.d.ts +99 -0
- package/dist/functions/table-in-out.d.ts +64 -0
- package/dist/functions/table.d.ts +118 -0
- package/dist/functions/types.d.ts +157 -0
- package/dist/generated/vgi-client.d.ts +466 -0
- package/dist/generated/vgi-protocol-schemas.d.ts +115 -0
- package/dist/index.core.d.ts +42 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +10888 -0
- package/dist/index.js.map +85 -0
- package/dist/metadata/resolve.d.ts +3 -0
- package/dist/metadata/serialize.d.ts +12 -0
- package/dist/metadata/types.d.ts +47 -0
- package/dist/protocol/dispatch.d.ts +23 -0
- package/dist/protocol/handlers/aggregate.d.ts +3 -0
- package/dist/protocol/handlers/catalog/admin.d.ts +3 -0
- package/dist/protocol/handlers/catalog/index.d.ts +3 -0
- package/dist/protocol/handlers/catalog/index_methods.d.ts +3 -0
- package/dist/protocol/handlers/catalog/macro.d.ts +3 -0
- package/dist/protocol/handlers/catalog/shared.d.ts +70 -0
- package/dist/protocol/handlers/catalog/table.d.ts +3 -0
- package/dist/protocol/handlers/catalog/view.d.ts +3 -0
- package/dist/protocol/handlers/function.d.ts +8 -0
- package/dist/protocol/handlers/shared.d.ts +31 -0
- package/dist/protocol/handlers/table-buffering.d.ts +3 -0
- package/dist/protocol/serialize.d.ts +4 -0
- package/dist/protocol/serializers/arguments.d.ts +3 -0
- package/dist/protocol/serializers/bind.d.ts +9 -0
- package/dist/protocol/serializers/cardinality.d.ts +7 -0
- package/dist/protocol/serializers/init.d.ts +9 -0
- package/dist/protocol/serializers/shared.d.ts +12 -0
- package/dist/protocol/state-serializer.d.ts +23 -0
- package/dist/protocol/types.d.ts +129 -0
- package/dist/secrets/helpers.d.ts +15 -0
- package/dist/types.d.ts +52 -0
- package/dist/util/arrow/index.d.ts +1 -0
- package/dist/util/bytes.d.ts +2 -0
- package/dist/util/statistics.d.ts +7 -0
- package/dist/worker-cf-entry.d.ts +30 -0
- package/dist/worker-cf-entry.js +8767 -0
- package/dist/worker-cf-entry.js.map +74 -0
- package/dist/worker.d.ts +36 -0
- package/package.json +96 -0
- package/src/arguments/argument-spec.ts +200 -0
- package/src/arguments/arguments.ts +81 -0
- package/src/arrow/codec/branded.ts +206 -0
- package/src/arrow/codec/registry.ts +674 -0
- package/src/arrow/codec/repr.ts +181 -0
- package/src/arrow/codec/type-descriptors.ts +137 -0
- package/src/arrow/impl-arrowjs/build.ts +88 -0
- package/src/arrow/impl-arrowjs/canonical.ts +509 -0
- package/src/arrow/impl-arrowjs/empty.ts +72 -0
- package/src/arrow/impl-arrowjs/filter.ts +53 -0
- package/src/arrow/impl-arrowjs/index.ts +54 -0
- package/src/arrow/impl-arrowjs/ipc.ts +67 -0
- package/src/arrow/impl-arrowjs/iterate.ts +159 -0
- package/src/arrow/impl-arrowjs/project.ts +73 -0
- package/src/arrow/impl-arrowjs/schema.ts +256 -0
- package/src/arrow/impl-arrowjs/statistics.ts +185 -0
- package/src/arrow/impl-flechette/build.ts +65 -0
- package/src/arrow/impl-flechette/canonical.ts +289 -0
- package/src/arrow/impl-flechette/empty.ts +20 -0
- package/src/arrow/impl-flechette/filter.ts +42 -0
- package/src/arrow/impl-flechette/index.ts +54 -0
- package/src/arrow/impl-flechette/ipc.ts +110 -0
- package/src/arrow/impl-flechette/iterate.ts +121 -0
- package/src/arrow/impl-flechette/message-meta.ts +175 -0
- package/src/arrow/impl-flechette/normalize-type.ts +99 -0
- package/src/arrow/impl-flechette/project.ts +64 -0
- package/src/arrow/impl-flechette/schema.ts +202 -0
- package/src/arrow/impl-flechette/statistics.ts +198 -0
- package/src/arrow/index.ts +129 -0
- package/src/arrow/predicates.ts +66 -0
- package/src/arrow/repr.test-d.ts +189 -0
- package/src/arrow/schema-types.ts +213 -0
- package/src/arrow/types.ts +74 -0
- package/src/catalog/attach-option.ts +107 -0
- package/src/catalog/attach-options.ts +79 -0
- package/src/catalog/composite.ts +180 -0
- package/src/catalog/descriptors.ts +164 -0
- package/src/catalog/interface.ts +721 -0
- package/src/catalog/read-only.ts +909 -0
- package/src/client/client.ts +1348 -0
- package/src/client/errors.ts +69 -0
- package/src/client/helpers.ts +56 -0
- package/src/client/protocol.ts +33 -0
- package/src/client/types.ts +140 -0
- package/src/client-entry.ts +112 -0
- package/src/codec/asd.ts +147 -0
- package/src/crypto.ts +143 -0
- package/src/errors.ts +61 -0
- package/src/filter-pushdown/collector.ts +147 -0
- package/src/filter-pushdown/deserialize.ts +253 -0
- package/src/filter-pushdown/evaluate.ts +591 -0
- package/src/filter-pushdown/index.ts +28 -0
- package/src/filter-pushdown/types.ts +91 -0
- package/src/functions/aggregate.ts +384 -0
- package/src/functions/copy-from.ts +282 -0
- package/src/functions/copy-to.ts +319 -0
- package/src/functions/registry.ts +258 -0
- package/src/functions/scalar.ts +356 -0
- package/src/functions/storage-cf-do.ts +303 -0
- package/src/functions/storage.ts +521 -0
- package/src/functions/table-buffering.ts +562 -0
- package/src/functions/table-in-out.ts +373 -0
- package/src/functions/table.ts +521 -0
- package/src/functions/types.ts +192 -0
- package/src/generated/vgi-client.ts +560 -0
- package/src/generated/vgi-protocol-schemas.ts +864 -0
- package/src/index.core.ts +267 -0
- package/src/index.ts +11 -0
- package/src/metadata/resolve.ts +109 -0
- package/src/metadata/serialize.ts +242 -0
- package/src/metadata/types.ts +60 -0
- package/src/protocol/dispatch.ts +52 -0
- package/src/protocol/handlers/aggregate.ts +355 -0
- package/src/protocol/handlers/catalog/admin.ts +368 -0
- package/src/protocol/handlers/catalog/index.ts +25 -0
- package/src/protocol/handlers/catalog/index_methods.ts +65 -0
- package/src/protocol/handlers/catalog/macro.ts +114 -0
- package/src/protocol/handlers/catalog/shared.ts +291 -0
- package/src/protocol/handlers/catalog/table.ts +401 -0
- package/src/protocol/handlers/catalog/view.ts +119 -0
- package/src/protocol/handlers/function.ts +302 -0
- package/src/protocol/handlers/shared.ts +80 -0
- package/src/protocol/handlers/table-buffering.ts +207 -0
- package/src/protocol/serialize.ts +23 -0
- package/src/protocol/serializers/arguments.ts +160 -0
- package/src/protocol/serializers/bind.ts +212 -0
- package/src/protocol/serializers/cardinality.ts +45 -0
- package/src/protocol/serializers/init.ts +247 -0
- package/src/protocol/serializers/shared.ts +46 -0
- package/src/protocol/state-serializer.ts +181 -0
- package/src/protocol/types.ts +153 -0
- package/src/secrets/helpers.ts +70 -0
- package/src/types.ts +71 -0
- package/src/util/arrow/index.ts +23 -0
- package/src/util/bytes.ts +14 -0
- package/src/util/statistics.ts +40 -0
- package/src/worker-cf-entry.ts +172 -0
- package/src/worker.ts +212 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { type VgiBatch, type VgiDataType } from "../arrow/index.js";
|
|
2
|
+
import type { BindRequest } from "../protocol/types.js";
|
|
3
|
+
import type { FunctionExample } from "./types.js";
|
|
4
|
+
import { type TableBufferingParams, type TableBufferingVgiFunction } from "./table-buffering.js";
|
|
5
|
+
/**
|
|
6
|
+
* A single secret to resolve via the two-phase secret bind, returned from a COPY
|
|
7
|
+
* format's `onSecrets` hook. Mirrors a vgi-python `SecretLookupEntry`.
|
|
8
|
+
*/
|
|
9
|
+
export interface CopySecretLookup {
|
|
10
|
+
/** DuckDB secret type to resolve (e.g. `"s3"`, `"vgi_example"`). */
|
|
11
|
+
secretType: string;
|
|
12
|
+
/** Optional scope for longest-prefix matching — typically the COPY path. */
|
|
13
|
+
scope?: string;
|
|
14
|
+
/** Optional secret name for name-based lookup. */
|
|
15
|
+
name?: string;
|
|
16
|
+
}
|
|
17
|
+
/** Declaration of a single COPY option (a named function argument). */
|
|
18
|
+
export interface CopyToOption {
|
|
19
|
+
/** Arrow type of the option value (e.g. `utf8()`, `int64()`). */
|
|
20
|
+
type: VgiDataType;
|
|
21
|
+
/** Per-option description, surfaced by `vgi_copy_formats()`. */
|
|
22
|
+
doc?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Default value. When omitted the option is REQUIRED — the worker throws a
|
|
25
|
+
* clear error at COPY bind if the user does not supply it. Mirrors
|
|
26
|
+
* vgi-python's `Arg(..., default=...)` (no default => required).
|
|
27
|
+
*/
|
|
28
|
+
default?: unknown;
|
|
29
|
+
/**
|
|
30
|
+
* Optional allowed value set, validated worker-side at bind. Mirrors
|
|
31
|
+
* vgi-python's `Arg(..., choices=[...])`.
|
|
32
|
+
*/
|
|
33
|
+
choices?: unknown[];
|
|
34
|
+
/**
|
|
35
|
+
* Optional inclusive lower bound for numeric options, validated worker-side at
|
|
36
|
+
* bind. Mirrors vgi-python's `Arg(..., ge=...)`.
|
|
37
|
+
*/
|
|
38
|
+
ge?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Optional inclusive upper bound for numeric options, validated worker-side at
|
|
41
|
+
* bind. Mirrors vgi-python's `Arg(..., le=...)`.
|
|
42
|
+
*/
|
|
43
|
+
le?: number;
|
|
44
|
+
}
|
|
45
|
+
/** Parameters for the per-batch `write` hook. */
|
|
46
|
+
export interface CopyToWriteParams<TArgs = Record<string, unknown>> {
|
|
47
|
+
/** One input batch from the COPY source. */
|
|
48
|
+
batch: VgiBatch;
|
|
49
|
+
/** Parsed COPY options (defaults applied). */
|
|
50
|
+
options: TArgs;
|
|
51
|
+
/** Destination path from the `COPY ... TO 'path'` statement. */
|
|
52
|
+
filePath: string;
|
|
53
|
+
/** Full buffering parameters (settings, secrets, storage, executionId). */
|
|
54
|
+
params: TableBufferingParams<TArgs>;
|
|
55
|
+
}
|
|
56
|
+
/** Parameters for the terminal `close` hook. */
|
|
57
|
+
export interface CopyToCloseParams<TArgs = Record<string, unknown>> {
|
|
58
|
+
/** Parsed COPY options (defaults applied). */
|
|
59
|
+
options: TArgs;
|
|
60
|
+
/** Destination path from the `COPY ... TO 'path'` statement. */
|
|
61
|
+
filePath: string;
|
|
62
|
+
/** Full buffering parameters (settings, secrets, storage, executionId). */
|
|
63
|
+
params: TableBufferingParams<TArgs>;
|
|
64
|
+
}
|
|
65
|
+
export interface CopyToFunctionConfig<TArgs = Record<string, unknown>> {
|
|
66
|
+
/** Handler name (the function's registered name; `Meta.name`). */
|
|
67
|
+
name: string;
|
|
68
|
+
/** SQL `FORMAT` identifier users type, e.g. `COPY t TO 'x' (FORMAT myfmt)`. */
|
|
69
|
+
format: string;
|
|
70
|
+
/** Function description (intrinsic documentation; `Meta.description`). */
|
|
71
|
+
description?: string;
|
|
72
|
+
/** Optional free-text comment surfaced by `vgi_copy_formats()`. */
|
|
73
|
+
comment?: string | null;
|
|
74
|
+
/** COPY direction; only `"to"` is supported here. */
|
|
75
|
+
direction?: string;
|
|
76
|
+
/**
|
|
77
|
+
* When true, the writer requires rows in source order — discovery advertises
|
|
78
|
+
* `ordered=true` and the extension uses a single-threaded sink
|
|
79
|
+
* (`REGULAR_COPY_TO_FILE`) so one worker receives every batch in source
|
|
80
|
+
* order. Mirrors vgi-python's `Meta.sink_order_dependent`.
|
|
81
|
+
*/
|
|
82
|
+
ordered?: boolean;
|
|
83
|
+
/** COPY options, keyed by option name. The `file_path` is NOT an option. */
|
|
84
|
+
options?: Record<string, CopyToOption>;
|
|
85
|
+
categories?: string[];
|
|
86
|
+
tags?: Record<string, string>;
|
|
87
|
+
examples?: FunctionExample[];
|
|
88
|
+
requiredSettings?: string[];
|
|
89
|
+
requiredSecrets?: string[];
|
|
90
|
+
/**
|
|
91
|
+
* Optional secret-bind hook: forward CREATE SECRET credentials for
|
|
92
|
+
* secret-backed cloud writes (S3/GCS/HTTP/…). Called during bind (only on the
|
|
93
|
+
* first pass); return the secrets to resolve — typically scoped by the
|
|
94
|
+
* destination `filePath`. The framework's two-phase secret bind resolves each
|
|
95
|
+
* lookup from the caller's SecretManager and surfaces the resolved values on
|
|
96
|
+
* `params.secrets` at `write`/`close` time. Mirrors vgi-python's
|
|
97
|
+
* `CopyToFunction.on_secrets`.
|
|
98
|
+
*/
|
|
99
|
+
onSecrets?: (params: {
|
|
100
|
+
options: TArgs;
|
|
101
|
+
filePath: string;
|
|
102
|
+
bindCall: BindRequest;
|
|
103
|
+
}) => CopySecretLookup[] | void;
|
|
104
|
+
/** Persist one input `batch` to a shard (called per sink batch). */
|
|
105
|
+
write: (params: CopyToWriteParams<TArgs>) => void | Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Write the destination and close it, once (called on the coordinator). Read
|
|
108
|
+
* the shards persisted by `write` and perform the terminal write. Called even
|
|
109
|
+
* for empty input. Return the row count (informational).
|
|
110
|
+
*/
|
|
111
|
+
close: (params: CopyToCloseParams<TArgs>) => number | void | Promise<number | void>;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Define a custom `COPY ... TO` format writer, returned as a
|
|
115
|
+
* `TableBufferingVgiFunction` (kind `"table_buffering"`) carrying the
|
|
116
|
+
* `copyToFormat` metadata marker. Register it in the catalog's function list
|
|
117
|
+
* like any function; the catalog's `copyFromFormats()` introspection picks it
|
|
118
|
+
* up and advertises the format (direction `"to"`). The worker's
|
|
119
|
+
* `table_buffering_process` / `table_buffering_combine` RPCs drive write/close.
|
|
120
|
+
*/
|
|
121
|
+
export declare function defineCopyToFunction<TArgs = Record<string, unknown>>(config: CopyToFunctionConfig<TArgs>): TableBufferingVgiFunction;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { VgiSchema } from "../arrow/index.js";
|
|
2
|
+
import type { VgiFunction } from "./types.js";
|
|
3
|
+
import type { Arguments } from "../arguments/arguments.js";
|
|
4
|
+
export interface OverloadContext {
|
|
5
|
+
arguments?: Arguments;
|
|
6
|
+
inputSchema?: VgiSchema | null;
|
|
7
|
+
isScalar?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare class FunctionRegistry {
|
|
10
|
+
private _functions;
|
|
11
|
+
register(func: VgiFunction): void;
|
|
12
|
+
get(name: string, context?: OverloadContext): VgiFunction;
|
|
13
|
+
has(name: string): boolean;
|
|
14
|
+
names(): string[];
|
|
15
|
+
all(): VgiFunction[];
|
|
16
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { type VgiSchema, type VgiBatch, type VgiDataType, type ValueFor, type Repr } from "../arrow/index.js";
|
|
2
|
+
import type { AuthContext } from "@query-farm/vgi-rpc";
|
|
3
|
+
import { FunctionStability, NullHandling } from "../types.js";
|
|
4
|
+
import type { BindRequest } from "../protocol/types.js";
|
|
5
|
+
import type { VgiFunction, FunctionExample } from "./types.js";
|
|
6
|
+
export interface ScalarBindParameters {
|
|
7
|
+
/** Constant argument values (resolved at bind time) */
|
|
8
|
+
constArgs: Record<string, any>;
|
|
9
|
+
/** Schema of all arguments including columnar params */
|
|
10
|
+
argumentsSchema: VgiSchema;
|
|
11
|
+
/** Settings from DuckDB */
|
|
12
|
+
settings: Record<string, any>;
|
|
13
|
+
/** Secrets from DuckDB */
|
|
14
|
+
secrets: Record<string, Record<string, any>>;
|
|
15
|
+
/** Original bind request — exposes attach_opaque_data, transaction_opaque_data, function_type, etc. */
|
|
16
|
+
bindCall: BindRequest;
|
|
17
|
+
}
|
|
18
|
+
/** Ordered parameter definition for scalar functions. */
|
|
19
|
+
export interface ScalarParameterDef {
|
|
20
|
+
name: string;
|
|
21
|
+
type: VgiDataType;
|
|
22
|
+
/** If true, this is a constant parameter (scalar value resolved at bind time). */
|
|
23
|
+
const?: boolean;
|
|
24
|
+
/** If true, this parameter accepts variable number of arguments. */
|
|
25
|
+
varargs?: boolean;
|
|
26
|
+
/** Human-readable per-argument description (surfaced as `vgi_doc`). */
|
|
27
|
+
doc?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The typed compute row for a scalar function: one property per declared
|
|
31
|
+
* columnar param, valued in the representation (`rich` / `raw`) selected by the
|
|
32
|
+
* function's `repr`. (Provided as a convenience type for authors who build rows
|
|
33
|
+
* out of the input batch.)
|
|
34
|
+
*/
|
|
35
|
+
export type ScalarComputeRow<P extends Record<string, VgiDataType>, M extends Repr> = {
|
|
36
|
+
[K in keyof P]: ValueFor<P[K], M> | null;
|
|
37
|
+
};
|
|
38
|
+
/** A single output value for a scalar function under representation `M`. */
|
|
39
|
+
export type ScalarOutputValue<R extends VgiDataType, M extends Repr> = ValueFor<R, M> | null;
|
|
40
|
+
/**
|
|
41
|
+
* Accepted compute return shapes: an array (or iterable) of output values in
|
|
42
|
+
* the declared representation, or a pre-built VgiBatch. The representation is
|
|
43
|
+
* enforced statically — returning a `Date` under `repr: 'raw'` (which expects a
|
|
44
|
+
* branded `Date32`/`Date64Ms`), or a branded value under `repr: 'rich'` (which
|
|
45
|
+
* expects a `Date`), is a COMPILE error.
|
|
46
|
+
*/
|
|
47
|
+
export type ScalarComputeResult<R extends VgiDataType, M extends Repr> = Array<ScalarOutputValue<R, M>> | Iterable<ScalarOutputValue<R, M>> | VgiBatch;
|
|
48
|
+
export interface ScalarFunctionConfig<P extends Record<string, VgiDataType> = Record<string, VgiDataType>, R extends VgiDataType = VgiDataType, M extends Repr = "rich"> {
|
|
49
|
+
name: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
/** Columnar params (receive Arrow arrays at process time) */
|
|
52
|
+
params?: P;
|
|
53
|
+
/** Constant params (receive scalar values resolved at bind time) */
|
|
54
|
+
constParams?: Record<string, VgiDataType>;
|
|
55
|
+
/**
|
|
56
|
+
* Per-argument descriptions keyed by param name, surfaced as `vgi_doc` field
|
|
57
|
+
* metadata (and via the extension's `vgi_function_arguments()`). Applies to
|
|
58
|
+
* `params` and `constParams`; for the ordered `parameters` list use each
|
|
59
|
+
* entry's `doc` field instead.
|
|
60
|
+
*/
|
|
61
|
+
argDocs?: Record<string, string>;
|
|
62
|
+
/**
|
|
63
|
+
* Ordered parameter list. When provided, overrides `params` and `constParams`.
|
|
64
|
+
* Use this when parameters need non-default ordering (e.g. const, param, const).
|
|
65
|
+
*/
|
|
66
|
+
parameters?: ScalarParameterDef[];
|
|
67
|
+
/** Output type (static) */
|
|
68
|
+
returns?: R;
|
|
69
|
+
/** Dynamic output type at bind time */
|
|
70
|
+
outputType?: (params: ScalarBindParameters) => VgiDataType | Promise<VgiDataType>;
|
|
71
|
+
/**
|
|
72
|
+
* Value representation for compute I/O. `'rich'` (default) uses JS `Date` for
|
|
73
|
+
* date32/date64 and plain number/bigint elsewhere. `'raw'` uses the branded
|
|
74
|
+
* unit-carrying aliases (Date32, TimestampMicros, UnscaledDecimal, …). The
|
|
75
|
+
* choice flows into compute()'s statically-checked return type and selects
|
|
76
|
+
* the runtime converter used to build the output column.
|
|
77
|
+
*/
|
|
78
|
+
repr?: M;
|
|
79
|
+
/**
|
|
80
|
+
* Process: receives the columnar input batch + const values, returns the
|
|
81
|
+
* output column as an array/iterable of values (statically typed from
|
|
82
|
+
* `returns` and `repr`) or a pre-built VgiBatch.
|
|
83
|
+
*/
|
|
84
|
+
compute: (batch: VgiBatch, consts: Record<string, any>, info: {
|
|
85
|
+
settings: Record<string, any>;
|
|
86
|
+
secrets: Record<string, Record<string, any>>;
|
|
87
|
+
auth: AuthContext;
|
|
88
|
+
}) => ScalarComputeResult<NoInfer<R>, NoInfer<M>>;
|
|
89
|
+
stability?: FunctionStability;
|
|
90
|
+
nullHandling?: NullHandling;
|
|
91
|
+
examples?: FunctionExample[];
|
|
92
|
+
categories?: string[];
|
|
93
|
+
tags?: Record<string, string>;
|
|
94
|
+
maxWorkers?: number;
|
|
95
|
+
requiredSettings?: string[];
|
|
96
|
+
requiredSecrets?: string[];
|
|
97
|
+
}
|
|
98
|
+
export declare function defineScalarFunction<P extends Record<string, VgiDataType> = Record<string, VgiDataType>, R extends VgiDataType = VgiDataType, M extends Repr = "rich">(config: ScalarFunctionConfig<P, R, M>): VgiFunction;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { FunctionStorage } from "./storage.js";
|
|
2
|
+
/** Minimal fetch signature satisfied by both the global `fetch` and a
|
|
3
|
+
* Cloudflare service-binding Fetcher (`env.<BINDING>`). */
|
|
4
|
+
export type FetchLike = (input: string, init?: {
|
|
5
|
+
method?: string;
|
|
6
|
+
headers?: Record<string, string>;
|
|
7
|
+
body?: string;
|
|
8
|
+
}) => Promise<Response>;
|
|
9
|
+
export declare class FunctionStorageCfDo implements FunctionStorage {
|
|
10
|
+
private readonly _baseUrl;
|
|
11
|
+
private readonly _token;
|
|
12
|
+
/** Per-attach routing key (att-<hex uuid>); "" until pinned via forShard. */
|
|
13
|
+
private readonly _shardKey;
|
|
14
|
+
/** Fetch implementation. Defaults to the global `fetch`; pass a Cloudflare
|
|
15
|
+
* service-binding Fetcher (env.<BINDING>) when the storage worker lives on
|
|
16
|
+
* the same account/zone — a same-zone public-URL fetch is rejected (CF
|
|
17
|
+
* error 1042), but a service binding routes worker-to-worker directly. */
|
|
18
|
+
private readonly _fetch;
|
|
19
|
+
constructor(opts: {
|
|
20
|
+
url: string;
|
|
21
|
+
token?: string | null;
|
|
22
|
+
shardKey?: string;
|
|
23
|
+
fetch?: FetchLike;
|
|
24
|
+
});
|
|
25
|
+
/** Build an instance from environment variables. */
|
|
26
|
+
static fromEnv(): FunctionStorageCfDo;
|
|
27
|
+
/**
|
|
28
|
+
* Return a view of this backend pinned to one shard key, so callers can route
|
|
29
|
+
* per logical ATTACH. Shares the URL/token; only the shard key differs.
|
|
30
|
+
*/
|
|
31
|
+
forShard(shardKey: string): FunctionStorageCfDo;
|
|
32
|
+
workerPut(executionId: Uint8Array, workerId: number, state: Uint8Array): Promise<void>;
|
|
33
|
+
workerCollect(executionId: Uint8Array): Promise<Uint8Array[]>;
|
|
34
|
+
workerScan(executionId: Uint8Array): Promise<Array<[number, Uint8Array]>>;
|
|
35
|
+
queuePush(executionId: Uint8Array, items: Uint8Array[]): Promise<number>;
|
|
36
|
+
queuePop(executionId: Uint8Array): Promise<Uint8Array | null>;
|
|
37
|
+
queueClear(executionId: Uint8Array): Promise<number>;
|
|
38
|
+
stateGet(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array): Promise<Uint8Array | null>;
|
|
39
|
+
statePut(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, value: Uint8Array): Promise<void>;
|
|
40
|
+
stateAppend(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, item: Uint8Array): Promise<number>;
|
|
41
|
+
stateLogScan(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, afterId?: number, limit?: number | null): Promise<Array<[number, Uint8Array]>>;
|
|
42
|
+
executionClear(scopeId: Uint8Array): Promise<number>;
|
|
43
|
+
private _statePutMany;
|
|
44
|
+
/** Drive state_scan / state_drain across pages. attemptId is null for scan. */
|
|
45
|
+
private _statePaged;
|
|
46
|
+
private _post;
|
|
47
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export declare class UnknownInvocationError extends Error {
|
|
2
|
+
constructor(message?: string | Uint8Array);
|
|
3
|
+
}
|
|
4
|
+
export interface FunctionStorage {
|
|
5
|
+
workerPut(executionId: Uint8Array, workerId: number, state: Uint8Array): Promise<void>;
|
|
6
|
+
workerCollect(executionId: Uint8Array): Promise<Uint8Array[]>;
|
|
7
|
+
workerScan(executionId: Uint8Array): Promise<Array<[number, Uint8Array]>>;
|
|
8
|
+
queuePush(executionId: Uint8Array, items: Uint8Array[]): Promise<number>;
|
|
9
|
+
queuePop(executionId: Uint8Array): Promise<Uint8Array | null>;
|
|
10
|
+
queueClear(executionId: Uint8Array): Promise<number>;
|
|
11
|
+
stateGet(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array): Promise<Uint8Array | null>;
|
|
12
|
+
statePut(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, value: Uint8Array): Promise<void>;
|
|
13
|
+
stateAppend(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, item: Uint8Array): Promise<number>;
|
|
14
|
+
stateLogScan(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, afterId?: number, limit?: number | null): Promise<Array<[number, Uint8Array]>>;
|
|
15
|
+
/** Wipe all state + log rows for a scope across every namespace. */
|
|
16
|
+
executionClear(scopeId: Uint8Array): Promise<number>;
|
|
17
|
+
/** Optional cleanup hook. Implementations holding a connection should release it here. */
|
|
18
|
+
close?(): Promise<void> | void;
|
|
19
|
+
}
|
|
20
|
+
export declare const FrameworkNS: {
|
|
21
|
+
readonly BUFFERING_INIT: Uint8Array<ArrayBufferLike>;
|
|
22
|
+
readonly STREAMING_FINALIZE: Uint8Array<ArrayBufferLike>;
|
|
23
|
+
};
|
|
24
|
+
/** Encode an int as 8-byte little-endian, matching Python's pack_int_key. */
|
|
25
|
+
export declare function packIntKey(i: number | bigint): Uint8Array;
|
|
26
|
+
export declare class FunctionStorageSqlite implements FunctionStorage {
|
|
27
|
+
readonly dbPath: string;
|
|
28
|
+
private _db;
|
|
29
|
+
constructor(dbPath?: string);
|
|
30
|
+
close(): void;
|
|
31
|
+
private _ensureTables;
|
|
32
|
+
stateGet(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array): Promise<Uint8Array | null>;
|
|
33
|
+
statePut(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, value: Uint8Array): Promise<void>;
|
|
34
|
+
stateAppend(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, item: Uint8Array): Promise<number>;
|
|
35
|
+
stateLogScan(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, afterId?: number, limit?: number | null): Promise<Array<[number, Uint8Array]>>;
|
|
36
|
+
executionClear(scopeId: Uint8Array): Promise<number>;
|
|
37
|
+
workerPut(executionId: Uint8Array, workerId: number, state: Uint8Array): Promise<void>;
|
|
38
|
+
workerCollect(executionId: Uint8Array): Promise<Uint8Array[]>;
|
|
39
|
+
workerScan(executionId: Uint8Array): Promise<Array<[number, Uint8Array]>>;
|
|
40
|
+
queuePush(executionId: Uint8Array, items: Uint8Array[]): Promise<number>;
|
|
41
|
+
queuePop(executionId: Uint8Array): Promise<Uint8Array | null>;
|
|
42
|
+
queueClear(executionId: Uint8Array): Promise<number>;
|
|
43
|
+
}
|
|
44
|
+
export declare class BoundStorage {
|
|
45
|
+
private _base;
|
|
46
|
+
private _executionId;
|
|
47
|
+
constructor(storage: FunctionStorage, executionId: Uint8Array);
|
|
48
|
+
put(state: Uint8Array): Promise<void>;
|
|
49
|
+
collect(): Promise<Uint8Array[]>;
|
|
50
|
+
workerScan(): Promise<Array<[number, Uint8Array]>>;
|
|
51
|
+
queuePush(items: Uint8Array[]): Promise<number>;
|
|
52
|
+
queuePop(): Promise<Uint8Array | null>;
|
|
53
|
+
queueClear(): Promise<number>;
|
|
54
|
+
stateGet(ns: Uint8Array, key: Uint8Array): Promise<Uint8Array | null>;
|
|
55
|
+
statePut(ns: Uint8Array, key: Uint8Array, value: Uint8Array): Promise<void>;
|
|
56
|
+
stateAppend(ns: Uint8Array, key: Uint8Array, item: Uint8Array): Promise<number>;
|
|
57
|
+
stateLogScan(ns: Uint8Array, key: Uint8Array, afterId?: number, limit?: number | null): Promise<Array<[number, Uint8Array]>>;
|
|
58
|
+
executionClear(): Promise<number>;
|
|
59
|
+
static packIntKey(i: number | bigint): Uint8Array;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Resolve the FunctionStorage backend from environment variables.
|
|
63
|
+
*
|
|
64
|
+
* Mirrors vgi-python's `_resolve_storage` in `vgi/function.py`.
|
|
65
|
+
*
|
|
66
|
+
* `VGI_WORKER_SHARED_STORAGE` selects the backend (default: `sqlite`):
|
|
67
|
+
* - `memory` — `FunctionStorageSqlite` at `:memory:`. Process-local
|
|
68
|
+
* with no cross-process coordination — single-process
|
|
69
|
+
* deployments only. Ignores `VGI_WORKER_SQLITE_PATH`.
|
|
70
|
+
* - `sqlite` — `FunctionStorageSqlite`. Honors `VGI_WORKER_SQLITE_PATH`
|
|
71
|
+
* (including `:memory:`).
|
|
72
|
+
* - `cloudflare-do` — `FunctionStorageCfDo`. Requires `VGI_CF_DO_URL`;
|
|
73
|
+
* optional `VGI_CF_DO_TOKEN` for bearer auth.
|
|
74
|
+
*/
|
|
75
|
+
export declare function resolveStorageFromEnv(): FunctionStorage;
|
|
76
|
+
/**
|
|
77
|
+
* Override the default backend used by the `storage` singleton. Call once at
|
|
78
|
+
* worker startup to inject a pre-built backend that env-driven selection can't
|
|
79
|
+
* construct — notably a `FunctionStorageCfDo` wired to a Cloudflare
|
|
80
|
+
* service-binding Fetcher (the binding lives on `env`, not `process.env`, and a
|
|
81
|
+
* same-zone public-URL fetch is rejected with CF error 1042). Takes precedence
|
|
82
|
+
* over `VGI_WORKER_SHARED_STORAGE`.
|
|
83
|
+
*/
|
|
84
|
+
export declare function setStorage(impl: FunctionStorage): void;
|
|
85
|
+
/** Default FunctionStorage instance. Backend is selected via env on first access. */
|
|
86
|
+
export declare const storage: FunctionStorage;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { type VgiSchema, type VgiDataType, type VgiBatch } from "../arrow/index.js";
|
|
2
|
+
import type { OutputCollector } from "@query-farm/vgi-rpc";
|
|
3
|
+
import type { BindRequest, InitRequest, GlobalInitResponse } from "../protocol/types.js";
|
|
4
|
+
import type { TableCardinality } from "../types.js";
|
|
5
|
+
import type { VgiFunction, FunctionExample } from "./types.js";
|
|
6
|
+
import { FunctionStability } from "../types.js";
|
|
7
|
+
import { BoundStorage } from "./storage.js";
|
|
8
|
+
export interface TableBufferingBindParams<TArgs = Record<string, any>> {
|
|
9
|
+
args: TArgs;
|
|
10
|
+
bindCall: BindRequest;
|
|
11
|
+
settings: Record<string, any>;
|
|
12
|
+
secrets: Record<string, Record<string, any>>;
|
|
13
|
+
/** True on the second bind pass, after the connector resolved the secrets
|
|
14
|
+
* requested via the onBind `lookupSecret*` return fields on the first pass. */
|
|
15
|
+
resolvedSecretsProvided: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface TableBufferingParams<TArgs = Record<string, any>> {
|
|
18
|
+
args: TArgs;
|
|
19
|
+
initCall: InitRequest;
|
|
20
|
+
outputSchema: VgiSchema;
|
|
21
|
+
settings: Record<string, any>;
|
|
22
|
+
secrets: Record<string, Record<string, any>>;
|
|
23
|
+
/** Shared cross-process storage scoped by execution_id. */
|
|
24
|
+
storage: BoundStorage;
|
|
25
|
+
/** Stable across coordinator + secondary workers for one DuckDB execution. */
|
|
26
|
+
executionId: Uint8Array;
|
|
27
|
+
/** Catalog attach identity (plaintext bytes). */
|
|
28
|
+
attachId: Uint8Array;
|
|
29
|
+
/** Hex/raw VGI transaction id, or null. */
|
|
30
|
+
transactionId: Uint8Array | null;
|
|
31
|
+
function_name: string;
|
|
32
|
+
/** Per-chunk batch_index when requiresInputBatchIndex=true; else null. */
|
|
33
|
+
batchIndex: number | null;
|
|
34
|
+
/** In-band log sink for the unary process()/combine() RPCs. */
|
|
35
|
+
clientLog: (level: string, message: string) => void;
|
|
36
|
+
}
|
|
37
|
+
export interface TableBufferingConfig<TArgs = Record<string, any>, TState = any> {
|
|
38
|
+
name: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
args?: Record<string, VgiDataType>;
|
|
41
|
+
namedArgs?: Record<string, VgiDataType>;
|
|
42
|
+
argDefaults?: Record<string, any>;
|
|
43
|
+
/** Bind: default passes through input schema. May be async. Return non-empty
|
|
44
|
+
* `lookupSecret*` lists on the first pass to request DuckDB secrets; the
|
|
45
|
+
* connector then re-binds with `resolvedSecretsProvided` and the resolved
|
|
46
|
+
* values are available in the process/finalize params' `secrets`. */
|
|
47
|
+
onBind?: (params: TableBufferingBindParams<TArgs>) => {
|
|
48
|
+
outputSchema: VgiSchema;
|
|
49
|
+
opaqueData?: Uint8Array;
|
|
50
|
+
lookupSecretTypes?: string[];
|
|
51
|
+
lookupScopes?: string[];
|
|
52
|
+
lookupNames?: string[];
|
|
53
|
+
} | Promise<{
|
|
54
|
+
outputSchema: VgiSchema;
|
|
55
|
+
opaqueData?: Uint8Array;
|
|
56
|
+
lookupSecretTypes?: string[];
|
|
57
|
+
lookupScopes?: string[];
|
|
58
|
+
lookupNames?: string[];
|
|
59
|
+
}>;
|
|
60
|
+
/** Sink: ingest one batch, return an opaque state_id. */
|
|
61
|
+
process: (batch: VgiBatch, params: TableBufferingParams<TArgs>) => Uint8Array | Promise<Uint8Array>;
|
|
62
|
+
/** Combine: group/merge state_ids, return finalize_state_ids. */
|
|
63
|
+
combine: (stateIds: Uint8Array[], params: TableBufferingParams<TArgs>) => Uint8Array[] | Promise<Uint8Array[]>;
|
|
64
|
+
/** Build the initial per-tick finalize state for a finalize_state_id. */
|
|
65
|
+
initialFinalizeState?: (finalizeStateId: Uint8Array, params: TableBufferingParams<TArgs>) => TState | Promise<TState>;
|
|
66
|
+
/** Source tick: emit one batch via out.emit / signal EOS via out.finish. */
|
|
67
|
+
finalize: (params: TableBufferingParams<TArgs>, finalizeStateId: Uint8Array, state: TState, out: OutputCollector) => void | Promise<void>;
|
|
68
|
+
cardinality?: (params: TableBufferingBindParams<TArgs>) => TableCardinality | Promise<TableCardinality>;
|
|
69
|
+
projectionPushdown?: boolean;
|
|
70
|
+
filterPushdown?: boolean;
|
|
71
|
+
autoApplyFilters?: boolean;
|
|
72
|
+
/** Force ParallelSink=false in the C++ operator (single-thread ingest). */
|
|
73
|
+
sinkOrderDependent?: boolean;
|
|
74
|
+
/** Force serial Source drain in finalize_queue order. */
|
|
75
|
+
sourceOrderDependent?: boolean;
|
|
76
|
+
/** Thread DuckDB's per-chunk batch_index into every process() call. */
|
|
77
|
+
requiresInputBatchIndex?: boolean;
|
|
78
|
+
stability?: FunctionStability;
|
|
79
|
+
examples?: FunctionExample[];
|
|
80
|
+
categories?: string[];
|
|
81
|
+
tags?: Record<string, string>;
|
|
82
|
+
maxWorkers?: number;
|
|
83
|
+
requiredSettings?: string[];
|
|
84
|
+
requiredSecrets?: string[];
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* A table_buffering VgiFunction also carries its callback config so the
|
|
88
|
+
* protocol's unary handlers (process/combine/destructor) can reach it.
|
|
89
|
+
*/
|
|
90
|
+
export interface TableBufferingVgiFunction extends VgiFunction {
|
|
91
|
+
bufferingConfig: TableBufferingConfig<any, any>;
|
|
92
|
+
bufferingExtractArgs: (request: BindRequest) => any;
|
|
93
|
+
}
|
|
94
|
+
export declare function defineTableBufferingFunction<TArgs = Record<string, any>, TState = any>(config: TableBufferingConfig<TArgs, TState>): TableBufferingVgiFunction;
|
|
95
|
+
export declare function encodeBufferingInit(request: InitRequest, response: GlobalInitResponse): Uint8Array;
|
|
96
|
+
export declare function decodeBufferingInit(payload: Uint8Array): {
|
|
97
|
+
request: InitRequest;
|
|
98
|
+
response: GlobalInitResponse;
|
|
99
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type VgiSchema, type VgiDataType, type VgiBatch } from "../arrow/index.js";
|
|
2
|
+
import type { OutputCollector } from "@query-farm/vgi-rpc";
|
|
3
|
+
import type { BindRequest, InitRequest, GlobalInitResponse } from "../protocol/types.js";
|
|
4
|
+
import type { VgiFunction, FunctionExample } from "./types.js";
|
|
5
|
+
import { type PushdownFilters } from "../filter-pushdown/index.js";
|
|
6
|
+
import { FunctionStability } from "../types.js";
|
|
7
|
+
import { BoundStorage } from "./storage.js";
|
|
8
|
+
export interface TableInOutBindParams<TArgs = Record<string, any>> {
|
|
9
|
+
args: TArgs;
|
|
10
|
+
bindCall: BindRequest;
|
|
11
|
+
settings: Record<string, any>;
|
|
12
|
+
secrets: Record<string, Record<string, any>>;
|
|
13
|
+
}
|
|
14
|
+
export interface TableInOutProcessParams<TArgs = Record<string, any>> {
|
|
15
|
+
args: TArgs;
|
|
16
|
+
initCall: InitRequest;
|
|
17
|
+
initResponse: GlobalInitResponse;
|
|
18
|
+
outputSchema: VgiSchema;
|
|
19
|
+
settings: Record<string, any>;
|
|
20
|
+
secrets: Record<string, Record<string, any>>;
|
|
21
|
+
pushdownFilters?: PushdownFilters;
|
|
22
|
+
/** Shared storage for cross-phase and cross-worker data (SQLite-backed). */
|
|
23
|
+
storage: BoundStorage;
|
|
24
|
+
}
|
|
25
|
+
export interface TableInOutConfig<TArgs = Record<string, any>, TState = null> {
|
|
26
|
+
name: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
args?: Record<string, VgiDataType>;
|
|
29
|
+
/** Named arguments (optional, DuckDB passes by name) */
|
|
30
|
+
namedArgs?: Record<string, VgiDataType>;
|
|
31
|
+
/** Argument defaults */
|
|
32
|
+
argDefaults?: Record<string, any>;
|
|
33
|
+
/** Bind: default passes through input schema. May be async. */
|
|
34
|
+
onBind?: (params: TableInOutBindParams<TArgs>) => {
|
|
35
|
+
outputSchema: VgiSchema;
|
|
36
|
+
opaqueData?: Uint8Array;
|
|
37
|
+
} | Promise<{
|
|
38
|
+
outputSchema: VgiSchema;
|
|
39
|
+
opaqueData?: Uint8Array;
|
|
40
|
+
}>;
|
|
41
|
+
onInit?: (params: {
|
|
42
|
+
args: TArgs;
|
|
43
|
+
initCall: InitRequest;
|
|
44
|
+
outputSchema: VgiSchema;
|
|
45
|
+
executionId: Uint8Array;
|
|
46
|
+
}) => GlobalInitResponse | Promise<GlobalInitResponse>;
|
|
47
|
+
initialState?: (params: TableInOutProcessParams<TArgs>) => TState;
|
|
48
|
+
/** Process: transform input batch, emit output via out */
|
|
49
|
+
process?: (params: TableInOutProcessParams<TArgs>, state: TState, batch: VgiBatch, out: OutputCollector) => void | Promise<void>;
|
|
50
|
+
/** Finalize: emit final batches after all input processed.
|
|
51
|
+
* Receives all worker states collected from storage (matches Python's finish(params, states)). */
|
|
52
|
+
finalize?: (params: TableInOutProcessParams<TArgs>, states: TState[]) => VgiBatch[] | Promise<VgiBatch[]>;
|
|
53
|
+
projectionPushdown?: boolean;
|
|
54
|
+
filterPushdown?: boolean;
|
|
55
|
+
autoApplyFilters?: boolean;
|
|
56
|
+
stability?: FunctionStability;
|
|
57
|
+
examples?: FunctionExample[];
|
|
58
|
+
categories?: string[];
|
|
59
|
+
tags?: Record<string, string>;
|
|
60
|
+
maxWorkers?: number;
|
|
61
|
+
requiredSettings?: string[];
|
|
62
|
+
requiredSecrets?: string[];
|
|
63
|
+
}
|
|
64
|
+
export declare function defineTableInOutFunction<TArgs = Record<string, any>, TState = null>(config: TableInOutConfig<TArgs, TState>): VgiFunction;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { type VgiSchema, type VgiDataType } from "../arrow/index.js";
|
|
2
|
+
import type { OutputCollector } from "@query-farm/vgi-rpc";
|
|
3
|
+
import type { BindRequest, InitRequest, GlobalInitResponse, TableCardinality } from "../protocol/types.js";
|
|
4
|
+
import type { VgiFunction, FunctionExample } from "./types.js";
|
|
5
|
+
import { type PushdownFilters } from "../filter-pushdown/index.js";
|
|
6
|
+
import type { ColumnStatistics } from "../util/statistics.js";
|
|
7
|
+
import { FunctionStability, type NullHandling, type OrderPreservation, type OrderDependence, type DistinctDependence } from "../types.js";
|
|
8
|
+
import { BoundStorage } from "./storage.js";
|
|
9
|
+
export interface TableBindParams<TArgs = Record<string, any>> {
|
|
10
|
+
args: TArgs;
|
|
11
|
+
bindCall: BindRequest;
|
|
12
|
+
settings: Record<string, any>;
|
|
13
|
+
secrets: Record<string, Record<string, any>>;
|
|
14
|
+
resolvedSecretsProvided: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface TableProcessParams<TArgs = Record<string, any>> {
|
|
17
|
+
args: TArgs;
|
|
18
|
+
initCall: InitRequest;
|
|
19
|
+
initResponse: GlobalInitResponse;
|
|
20
|
+
outputSchema: VgiSchema;
|
|
21
|
+
settings: Record<string, any>;
|
|
22
|
+
secrets: Record<string, Record<string, any>>;
|
|
23
|
+
pushdownFilters?: PushdownFilters;
|
|
24
|
+
storage?: BoundStorage;
|
|
25
|
+
/**
|
|
26
|
+
* AT (TIMESTAMP|VERSION) clause for this scan, or `undefined` when the scan
|
|
27
|
+
* has no AT clause. Carried on the per-scan bind embedded in the init request
|
|
28
|
+
* (`initCall.bind_call.at_unit` / `.at_value`), so function-backed tables can
|
|
29
|
+
* read time travel at init alongside their pushdown filters. Mirrors
|
|
30
|
+
* vgi-python's `ProcessParams.at_unit` / `.at_value`. See `BindRequest.at_unit`.
|
|
31
|
+
*/
|
|
32
|
+
atUnit?: string;
|
|
33
|
+
atValue?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface TableFunctionConfig<TArgs = Record<string, any>, TState = null> {
|
|
36
|
+
name: string;
|
|
37
|
+
description?: string;
|
|
38
|
+
/** Argument schema (positional args) */
|
|
39
|
+
args?: Record<string, VgiDataType>;
|
|
40
|
+
/** Argument docs */
|
|
41
|
+
argDocs?: Record<string, string>;
|
|
42
|
+
/** Argument defaults */
|
|
43
|
+
argDefaults?: Record<string, any>;
|
|
44
|
+
/** Names of args that accept variable number of arguments */
|
|
45
|
+
varargs?: string[];
|
|
46
|
+
/** Bind: return output schema. May be async — handlers `await` the result. */
|
|
47
|
+
onBind: (params: TableBindParams<TArgs>) => {
|
|
48
|
+
outputSchema: VgiSchema;
|
|
49
|
+
opaqueData?: Uint8Array;
|
|
50
|
+
lookupSecretTypes?: string[];
|
|
51
|
+
lookupScopes?: string[];
|
|
52
|
+
lookupNames?: string[];
|
|
53
|
+
} | Promise<{
|
|
54
|
+
outputSchema: VgiSchema;
|
|
55
|
+
opaqueData?: Uint8Array;
|
|
56
|
+
lookupSecretTypes?: string[];
|
|
57
|
+
lookupScopes?: string[];
|
|
58
|
+
lookupNames?: string[];
|
|
59
|
+
}>;
|
|
60
|
+
/** Init (optional). May be async — common when storage is HTTP-backed. */
|
|
61
|
+
onInit?: (params: {
|
|
62
|
+
args: TArgs;
|
|
63
|
+
initCall: InitRequest;
|
|
64
|
+
outputSchema: VgiSchema;
|
|
65
|
+
executionId: Uint8Array;
|
|
66
|
+
storage: BoundStorage;
|
|
67
|
+
}) => GlobalInitResponse | Promise<GlobalInitResponse>;
|
|
68
|
+
/** State factory */
|
|
69
|
+
initialState?: (params: TableProcessParams<TArgs>) => TState;
|
|
70
|
+
/** Process: emit batches via out, call out.finish() when done */
|
|
71
|
+
process: (params: TableProcessParams<TArgs>, state: TState, out: OutputCollector) => void | Promise<void>;
|
|
72
|
+
/** Cardinality hints */
|
|
73
|
+
cardinality?: (params: TableBindParams<TArgs>) => TableCardinality | Promise<TableCardinality>;
|
|
74
|
+
/**
|
|
75
|
+
* Per-column statistics for the function's output. Returned to DuckDB via
|
|
76
|
+
* the `table_function_statistics` RPC; the optimizer uses min/max to
|
|
77
|
+
* eliminate impossible filters at plan time (folding scans to
|
|
78
|
+
* EMPTY_RESULT). Return `null` or an empty array when bounds are unknown.
|
|
79
|
+
*/
|
|
80
|
+
statistics?: (params: TableBindParams<TArgs>) => ColumnStatistics[] | null;
|
|
81
|
+
/**
|
|
82
|
+
* Per-execution diagnostics surfaced under EXPLAIN ANALYZE. DuckDB calls
|
|
83
|
+
* this once per parallel scan thread at pipeline FinishSource via the
|
|
84
|
+
* `table_function_dynamic_to_string` RPC. Return ordered key→value
|
|
85
|
+
* strings; the C++ extension merges these with the intrinsic keys
|
|
86
|
+
* (Function, Rows Read, Threads). The framework provides a BoundStorage
|
|
87
|
+
* keyed by the global execution_id so process() can persist counters
|
|
88
|
+
* that this callback then reads back — see profiling_demo for the
|
|
89
|
+
* canonical pattern.
|
|
90
|
+
*/
|
|
91
|
+
dynamicToString?: (params: TableBindParams<TArgs>, executionId: Uint8Array, storage: BoundStorage) => Record<string, string> | Promise<Record<string, string>>;
|
|
92
|
+
projectionPushdown?: boolean;
|
|
93
|
+
filterPushdown?: boolean;
|
|
94
|
+
samplingPushdown?: boolean;
|
|
95
|
+
/** Opt in to DuckDB's late-materialization SEMI-join rewrite; requires a
|
|
96
|
+
* UNIQUE, snapshot-stable rowid column. FunctionInfo.late_materialization. */
|
|
97
|
+
lateMaterialization?: boolean;
|
|
98
|
+
supportedExpressionFilters?: string[];
|
|
99
|
+
autoApplyFilters?: boolean;
|
|
100
|
+
stability?: FunctionStability;
|
|
101
|
+
examples?: FunctionExample[];
|
|
102
|
+
categories?: string[];
|
|
103
|
+
tags?: Record<string, string>;
|
|
104
|
+
maxWorkers?: number;
|
|
105
|
+
requiredSettings?: string[];
|
|
106
|
+
requiredSecrets?: string[];
|
|
107
|
+
/** Row-order preservation behavior; flows to DuckDB's
|
|
108
|
+
* TableFunction::order_preservation_type. */
|
|
109
|
+
preservesOrder?: OrderPreservation;
|
|
110
|
+
nullHandling?: NullHandling;
|
|
111
|
+
orderDependent?: OrderDependence;
|
|
112
|
+
distinctDependent?: DistinctDependence;
|
|
113
|
+
/** Emit per-batch `vgi_batch_index`; FunctionInfo.supports_batch_index. */
|
|
114
|
+
supportsBatchIndex?: boolean;
|
|
115
|
+
/** Hive-style partition-columns mode; FunctionInfo.partition_kind. */
|
|
116
|
+
partitionKind?: "NOT_PARTITIONED" | "SINGLE_VALUE_PARTITIONS" | "OVERLAPPING_PARTITIONS" | "DISJOINT_PARTITIONS";
|
|
117
|
+
}
|
|
118
|
+
export declare function defineTableFunction<TArgs = Record<string, any>, TState = null>(config: TableFunctionConfig<TArgs, TState>): VgiFunction;
|