@query-farm/vgi 0.21.0 → 0.22.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/dist/cache-control.d.ts +26 -0
- package/dist/catalog/composite.d.ts +2 -0
- package/dist/catalog/interface.d.ts +11 -0
- package/dist/client-entry.js +5 -3
- package/dist/client-entry.js.map +5 -5
- package/dist/functions/registry.d.ts +31 -0
- package/dist/functions/scalar.d.ts +7 -3
- package/dist/generated/vgi-client.d.ts +16 -0
- package/dist/index.core.d.ts +1 -1
- package/dist/index.js +120 -16
- package/dist/index.js.map +15 -15
- package/dist/protocol/handlers/function.d.ts +8 -0
- package/dist/protocol/handlers/shared.d.ts +4 -0
- package/dist/protocol/types.d.ts +8 -0
- package/dist/serve-entry.js +35 -13
- package/dist/serve-entry.js.map +8 -8
- package/dist/worker-cf-entry.js +115 -14
- package/dist/worker-cf-entry.js.map +13 -13
- package/dist/worker.d.ts +9 -0
- package/package.json +3 -3
- package/src/cache-control.ts +27 -0
- package/src/catalog/composite.ts +9 -0
- package/src/catalog/interface.ts +15 -0
- package/src/catalog/read-only.ts +13 -0
- package/src/functions/registry.ts +106 -1
- package/src/functions/scalar.ts +10 -5
- package/src/generated/vgi-client.ts +17 -1
- package/src/index.core.ts +1 -0
- package/src/protocol/dispatch.ts +1 -0
- package/src/protocol/handlers/function.ts +29 -8
- package/src/protocol/handlers/shared.ts +25 -1
- package/src/protocol/serializers/bind.ts +7 -0
- package/src/protocol/types.ts +8 -0
- package/src/worker.ts +15 -1
package/dist/worker-cf-entry.js
CHANGED
|
@@ -2935,7 +2935,8 @@ var BIND_REQUEST_SCHEMA = schema2([
|
|
|
2935
2935
|
field2("transaction_opaque_data", binary2(), true),
|
|
2936
2936
|
field2("resolved_secrets_provided", bool2(), false),
|
|
2937
2937
|
field2("at_unit", utf82(), true),
|
|
2938
|
-
field2("at_value", utf82(), true)
|
|
2938
|
+
field2("at_value", utf82(), true),
|
|
2939
|
+
field2("schema_name", utf82(), true)
|
|
2939
2940
|
]);
|
|
2940
2941
|
var COPY_FROM_STRUCT_TYPE = struct2([
|
|
2941
2942
|
field2("format", utf82(), false),
|
|
@@ -3003,6 +3004,7 @@ function deserializeBindRequest(params) {
|
|
|
3003
3004
|
resolved_secrets_provided: params.resolved_secrets_provided ?? false,
|
|
3004
3005
|
at_unit: params.at_unit ? String(params.at_unit) : null,
|
|
3005
3006
|
at_value: params.at_value ? String(params.at_value) : null,
|
|
3007
|
+
schema_name: params.schema_name ? String(params.schema_name) : null,
|
|
3006
3008
|
copy_from: parseCopyFromContext(params.copy_from),
|
|
3007
3009
|
copy_to: parseCopyToContext(params.copy_to)
|
|
3008
3010
|
};
|
|
@@ -3833,11 +3835,21 @@ function wrapResult(values, innerSchema) {
|
|
|
3833
3835
|
const batch = batchFromColumns(Object.fromEntries(a.fields.map((f) => [f.name, [values[f.name] ?? null]])), a);
|
|
3834
3836
|
return { result: serializeBatch(batch) };
|
|
3835
3837
|
}
|
|
3836
|
-
function overloadContext(req) {
|
|
3838
|
+
function overloadContext(req, catalogInterface) {
|
|
3839
|
+
let catalogName = null;
|
|
3840
|
+
if (catalogInterface && req.attach_opaque_data) {
|
|
3841
|
+
try {
|
|
3842
|
+
catalogName = catalogInterface.catalogNameForAttach(req.attach_opaque_data);
|
|
3843
|
+
} catch {
|
|
3844
|
+
catalogName = null;
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3837
3847
|
return {
|
|
3838
3848
|
arguments: req.arguments,
|
|
3839
3849
|
inputSchema: req.input_schema,
|
|
3840
|
-
isScalar: String(req.function_type).toLowerCase() === "scalar"
|
|
3850
|
+
isScalar: String(req.function_type).toLowerCase() === "scalar",
|
|
3851
|
+
schemaName: req.schema_name ?? null,
|
|
3852
|
+
catalogName
|
|
3841
3853
|
};
|
|
3842
3854
|
}
|
|
3843
3855
|
function recoverFinalizeState(request, recoverExchangeState) {
|
|
@@ -4852,7 +4864,7 @@ var columnOpParams = schema2([
|
|
|
4852
4864
|
|
|
4853
4865
|
// src/protocol/handlers/function.ts
|
|
4854
4866
|
function registerFunctionMethods(protocol, config) {
|
|
4855
|
-
const { registry, signingKey } = config;
|
|
4867
|
+
const { registry, signingKey, catalogInterface } = config;
|
|
4856
4868
|
async function stripAttach(attach, ctx) {
|
|
4857
4869
|
if (attach == null)
|
|
4858
4870
|
return null;
|
|
@@ -4861,6 +4873,15 @@ function registerFunctionMethods(protocol, config) {
|
|
|
4861
4873
|
return env;
|
|
4862
4874
|
return openAttach(env, ctx?.auth, signingKey);
|
|
4863
4875
|
}
|
|
4876
|
+
async function strippedContext(bindCall, ctx) {
|
|
4877
|
+
let attach = null;
|
|
4878
|
+
try {
|
|
4879
|
+
attach = await stripAttach(bindCall.attach_opaque_data, ctx);
|
|
4880
|
+
} catch {
|
|
4881
|
+
attach = null;
|
|
4882
|
+
}
|
|
4883
|
+
return overloadContext({ ...bindCall, attach_opaque_data: attach }, catalogInterface);
|
|
4884
|
+
}
|
|
4864
4885
|
const initHeaderSchema = schema2([
|
|
4865
4886
|
field2("execution_id", binary2(), false),
|
|
4866
4887
|
field2("opaque_data", binary2(), true),
|
|
@@ -4877,7 +4898,7 @@ function registerFunctionMethods(protocol, config) {
|
|
|
4877
4898
|
const innerParams = unwrapRequest(params.request);
|
|
4878
4899
|
const request = deserializeBindRequest(innerParams);
|
|
4879
4900
|
request.attach_opaque_data = await stripAttach(request.attach_opaque_data, ctx);
|
|
4880
|
-
const func = registry.get(request.function_name, overloadContext(request));
|
|
4901
|
+
const func = registry.get(request.function_name, overloadContext(request, catalogInterface));
|
|
4881
4902
|
const response = await func.bind(request);
|
|
4882
4903
|
const serialized = serializeBindResponse(response);
|
|
4883
4904
|
return wrapResult(serialized, BindResultSchema);
|
|
@@ -4892,7 +4913,7 @@ function registerFunctionMethods(protocol, config) {
|
|
|
4892
4913
|
const innerParams = unwrapRequest(params.request);
|
|
4893
4914
|
const request = deserializeInitRequest(innerParams);
|
|
4894
4915
|
request.bind_call.attach_opaque_data = await stripAttach(request.bind_call.attach_opaque_data, undefined);
|
|
4895
|
-
const func = registry.get(request.bind_call.function_name, overloadContext(request.bind_call));
|
|
4916
|
+
const func = registry.get(request.bind_call.function_name, overloadContext(request.bind_call, catalogInterface));
|
|
4896
4917
|
const initResponse = await func.globalInit(request);
|
|
4897
4918
|
const accumulatedState = recoverFinalizeState(request, config.recoverExchangeState);
|
|
4898
4919
|
const handlers = func.createStreamHandlers(request, initResponse, accumulatedState);
|
|
@@ -4932,7 +4953,7 @@ function registerFunctionMethods(protocol, config) {
|
|
|
4932
4953
|
const initRequestBatch = deserializeBatch(state.initRequestIpc);
|
|
4933
4954
|
const initRequestDict = batchToScalarDict(initRequestBatch);
|
|
4934
4955
|
const request = deserializeInitRequest(initRequestDict);
|
|
4935
|
-
const func = registry.get(state.functionName,
|
|
4956
|
+
const func = registry.get(state.functionName, await strippedContext(request.bind_call));
|
|
4936
4957
|
const executionId = state.executionId;
|
|
4937
4958
|
const opaqueData = state.opaqueData ?? null;
|
|
4938
4959
|
const initResponse = {
|
|
@@ -4980,7 +5001,7 @@ function registerFunctionMethods(protocol, config) {
|
|
|
4980
5001
|
handler: async (params) => {
|
|
4981
5002
|
const innerParams = unwrapRequest(params.request);
|
|
4982
5003
|
const request = deserializeCardinalityRequest(innerParams);
|
|
4983
|
-
const func = registry.get(request.bind_call.function_name,
|
|
5004
|
+
const func = registry.get(request.bind_call.function_name, await strippedContext(request.bind_call));
|
|
4984
5005
|
let cardResult;
|
|
4985
5006
|
if (func.cardinality) {
|
|
4986
5007
|
cardResult = serializeTableCardinality(await func.cardinality(request));
|
|
@@ -4993,10 +5014,10 @@ function registerFunctionMethods(protocol, config) {
|
|
|
4993
5014
|
protocol.unary("table_function_statistics", {
|
|
4994
5015
|
params: REQUEST_PARAMS_SCHEMA,
|
|
4995
5016
|
result: RESULT_BINARY_NULLABLE_SCHEMA,
|
|
4996
|
-
handler: (params) => {
|
|
5017
|
+
handler: async (params) => {
|
|
4997
5018
|
const innerParams = unwrapRequest(params.request);
|
|
4998
5019
|
const request = deserializeCardinalityRequest(innerParams);
|
|
4999
|
-
const func = registry.get(request.bind_call.function_name,
|
|
5020
|
+
const func = registry.get(request.bind_call.function_name, await strippedContext(request.bind_call));
|
|
5000
5021
|
if (!func.statistics)
|
|
5001
5022
|
return { result: null };
|
|
5002
5023
|
const stats = func.statistics(request);
|
|
@@ -5016,7 +5037,7 @@ function registerFunctionMethods(protocol, config) {
|
|
|
5016
5037
|
const bindCall = deserializeBindRequest(bindParams);
|
|
5017
5038
|
const globalExecutionId = toUint8Array(innerParams.global_execution_id);
|
|
5018
5039
|
const bindOpaqueData = innerParams.bind_opaque_data ? toUint8Array(innerParams.bind_opaque_data) : null;
|
|
5019
|
-
const func = registry.get(bindCall.function_name,
|
|
5040
|
+
const func = registry.get(bindCall.function_name, await strippedContext(bindCall));
|
|
5020
5041
|
const map3 = func.dynamicToString ? await func.dynamicToString({ bindCall, bindOpaqueData, globalExecutionId }) : {};
|
|
5021
5042
|
const keys = Object.keys(map3);
|
|
5022
5043
|
const values = keys.map((k) => map3[k] ?? "");
|
|
@@ -6497,6 +6518,10 @@ function isPromise(v) {
|
|
|
6497
6518
|
}
|
|
6498
6519
|
|
|
6499
6520
|
class CatalogInterface {
|
|
6521
|
+
catalogNameForAttach(_attachOpaqueData) {
|
|
6522
|
+
const names = this.catalogs();
|
|
6523
|
+
return names.length === 1 ? names[0] : null;
|
|
6524
|
+
}
|
|
6500
6525
|
create(name, onConflict, options) {
|
|
6501
6526
|
throw new CatalogReadOnlyError("create");
|
|
6502
6527
|
}
|
|
@@ -7231,7 +7256,8 @@ function buildVgiProtocol(config) {
|
|
|
7231
7256
|
registerFunctionMethods(protocol, {
|
|
7232
7257
|
registry: config.registry,
|
|
7233
7258
|
recoverExchangeState: config.recoverExchangeState,
|
|
7234
|
-
signingKey: config.signingKey
|
|
7259
|
+
signingKey: config.signingKey,
|
|
7260
|
+
catalogInterface: config.catalogInterface
|
|
7235
7261
|
});
|
|
7236
7262
|
registerAggregateMethods(protocol, config.registry);
|
|
7237
7263
|
registerTableBufferingMethods(protocol, config.registry, config.signingKey);
|
|
@@ -7280,6 +7306,7 @@ var CACHE_STALE_WHILE_REVALIDATE_KEY = "vgi.cache.stale_while_revalidate";
|
|
|
7280
7306
|
var CACHE_STALE_IF_ERROR_KEY = "vgi.cache.stale_if_error";
|
|
7281
7307
|
var CACHE_NOT_MODIFIED_KEY = "vgi.cache.not_modified";
|
|
7282
7308
|
var CACHE_PARTITION_SCOPE_KEY = "vgi.cache.partition_scope";
|
|
7309
|
+
var CACHE_PER_VALUE_KEY = "vgi.cache.per_value";
|
|
7283
7310
|
var CACHE_IF_NONE_MATCH_KEY = "vgi.cache.if_none_match";
|
|
7284
7311
|
var CACHE_IF_MODIFIED_SINCE_KEY = "vgi.cache.if_modified_since";
|
|
7285
7312
|
var CACHE_SCOPE_CATALOG = "catalog";
|
|
@@ -7318,6 +7345,8 @@ function cacheControlMetadata(cc, extra) {
|
|
|
7318
7345
|
md.set(CACHE_NOT_MODIFIED_KEY, "1");
|
|
7319
7346
|
if (cc.partitionScope)
|
|
7320
7347
|
md.set(CACHE_PARTITION_SCOPE_KEY, "1");
|
|
7348
|
+
if (cc.perValue)
|
|
7349
|
+
md.set(CACHE_PER_VALUE_KEY, "1");
|
|
7321
7350
|
return md;
|
|
7322
7351
|
}
|
|
7323
7352
|
|
|
@@ -8088,6 +8117,17 @@ class ReadOnlyCatalogInterface extends CatalogInterface {
|
|
|
8088
8117
|
super();
|
|
8089
8118
|
this._descriptor = descriptor;
|
|
8090
8119
|
this._registry = registry;
|
|
8120
|
+
for (const sch of descriptor.schemas ?? []) {
|
|
8121
|
+
for (const fn of sch.functions ?? [])
|
|
8122
|
+
registry.registerInSchema(fn, sch.name, descriptor.name);
|
|
8123
|
+
for (const tbl of sch.tables ?? []) {
|
|
8124
|
+
for (const key of ["function", "insertFunction", "updateFunction", "deleteFunction"]) {
|
|
8125
|
+
const fn = tbl[key];
|
|
8126
|
+
if (fn)
|
|
8127
|
+
registry.registerInSchema(fn, sch.name, descriptor.name);
|
|
8128
|
+
}
|
|
8129
|
+
}
|
|
8130
|
+
}
|
|
8091
8131
|
}
|
|
8092
8132
|
catalogs() {
|
|
8093
8133
|
return [this._descriptor.name];
|
|
@@ -8710,6 +8750,13 @@ class CompositeCatalogInterface extends CatalogInterface {
|
|
|
8710
8750
|
}
|
|
8711
8751
|
return route;
|
|
8712
8752
|
}
|
|
8753
|
+
catalogNameForAttach(attachOpaqueData) {
|
|
8754
|
+
try {
|
|
8755
|
+
return this._route(attachOpaqueData).catalogNameForAttach(attachOpaqueData);
|
|
8756
|
+
} catch {
|
|
8757
|
+
return null;
|
|
8758
|
+
}
|
|
8759
|
+
}
|
|
8713
8760
|
catalogs() {
|
|
8714
8761
|
const all = [];
|
|
8715
8762
|
for (const b of this._backends)
|
|
@@ -8938,9 +8985,17 @@ function filterByArgumentTypes(candidates, args, inputSchema, isScalar) {
|
|
|
8938
8985
|
const maxScore = Math.max(...scored.map((s) => s.score));
|
|
8939
8986
|
return scored.filter((s) => s.score === maxScore).map((s) => s.func);
|
|
8940
8987
|
}
|
|
8988
|
+
function schemaKey(schemaName, functionName) {
|
|
8989
|
+
return `${schemaName.toLowerCase()}\x00${functionName}`;
|
|
8990
|
+
}
|
|
8991
|
+
function catalogKey(catalogName, schemaName, functionName) {
|
|
8992
|
+
return `${catalogName.toLowerCase()}\x00${schemaKey(schemaName, functionName)}`;
|
|
8993
|
+
}
|
|
8941
8994
|
|
|
8942
8995
|
class FunctionRegistry {
|
|
8943
8996
|
_functions = new Map;
|
|
8997
|
+
_bySchema = new Map;
|
|
8998
|
+
_byCatalog = new Map;
|
|
8944
8999
|
register(func) {
|
|
8945
9000
|
const name = func.meta.name;
|
|
8946
9001
|
if (!this._functions.has(name)) {
|
|
@@ -8948,11 +9003,57 @@ class FunctionRegistry {
|
|
|
8948
9003
|
}
|
|
8949
9004
|
this._functions.get(name).push(func);
|
|
8950
9005
|
}
|
|
9006
|
+
registerInSchema(func, schemaName, catalogName) {
|
|
9007
|
+
const add = (map3, key) => {
|
|
9008
|
+
const bucket = map3.get(key);
|
|
9009
|
+
if (!bucket) {
|
|
9010
|
+
map3.set(key, [func]);
|
|
9011
|
+
return;
|
|
9012
|
+
}
|
|
9013
|
+
if (!bucket.includes(func))
|
|
9014
|
+
bucket.push(func);
|
|
9015
|
+
};
|
|
9016
|
+
add(this._bySchema, schemaKey(schemaName, func.meta.name));
|
|
9017
|
+
if (catalogName) {
|
|
9018
|
+
add(this._byCatalog, catalogKey(catalogName, schemaName, func.meta.name));
|
|
9019
|
+
}
|
|
9020
|
+
}
|
|
9021
|
+
schemasFor(functionName) {
|
|
9022
|
+
const out = [];
|
|
9023
|
+
for (const key of this._bySchema.keys()) {
|
|
9024
|
+
const [schema3, name] = key.split("\x00");
|
|
9025
|
+
if (name === functionName)
|
|
9026
|
+
out.push(schema3);
|
|
9027
|
+
}
|
|
9028
|
+
return out.sort();
|
|
9029
|
+
}
|
|
8951
9030
|
get(name, context) {
|
|
8952
|
-
|
|
9031
|
+
let candidates = this._functions.get(name);
|
|
9032
|
+
const catalogName = context?.catalogName;
|
|
9033
|
+
const schemaName = context?.schemaName;
|
|
9034
|
+
if (catalogName && schemaName) {
|
|
9035
|
+
const scoped = this._byCatalog.get(catalogKey(catalogName, schemaName, name));
|
|
9036
|
+
if (scoped && scoped.length > 0) {
|
|
9037
|
+
return this._disambiguate(name, scoped, context);
|
|
9038
|
+
}
|
|
9039
|
+
}
|
|
9040
|
+
if (schemaName) {
|
|
9041
|
+
const scoped = this._bySchema.get(schemaKey(schemaName, name));
|
|
9042
|
+
if (scoped && scoped.length > 0) {
|
|
9043
|
+
candidates = scoped;
|
|
9044
|
+
} else if (candidates && candidates.length > 0) {
|
|
9045
|
+
const schemas = this.schemasFor(name);
|
|
9046
|
+
if (schemas.length > 0) {
|
|
9047
|
+
throw new Error(`Function '${name}' is not registered in schema '${schemaName}'. ` + `It is available in: [${schemas.join(", ")}]`);
|
|
9048
|
+
}
|
|
9049
|
+
}
|
|
9050
|
+
}
|
|
8953
9051
|
if (!candidates || candidates.length === 0) {
|
|
8954
9052
|
throw new FunctionNotFoundError(name, this.names());
|
|
8955
9053
|
}
|
|
9054
|
+
return this._disambiguate(name, candidates, context);
|
|
9055
|
+
}
|
|
9056
|
+
_disambiguate(name, candidates, context) {
|
|
8956
9057
|
if (candidates.length === 1) {
|
|
8957
9058
|
return candidates[0];
|
|
8958
9059
|
}
|
|
@@ -9580,4 +9681,4 @@ export {
|
|
|
9580
9681
|
Arguments
|
|
9581
9682
|
};
|
|
9582
9683
|
|
|
9583
|
-
//# debugId=
|
|
9684
|
+
//# debugId=0DAB6D0BDC711A3364756E2164756E21
|