@query-farm/vgi 0.21.0 → 0.23.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.
@@ -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, overloadContext(request.bind_call));
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, overloadContext(request.bind_call));
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, overloadContext(request.bind_call));
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, overloadContext(bindCall));
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] ?? "");
@@ -5377,8 +5398,13 @@ function defineAggregate(config) {
5377
5398
 
5378
5399
  // src/protocol/handlers/aggregate.ts
5379
5400
  function registerAggregateMethods(protocol, registry) {
5380
- function resolveAggregate(name) {
5381
- const func = registry.get(name, { arguments: new Arguments, inputSchema: null, isScalar: false });
5401
+ function resolveAggregate(name, schemaName) {
5402
+ const func = registry.get(name, {
5403
+ arguments: new Arguments,
5404
+ inputSchema: null,
5405
+ isScalar: false,
5406
+ schemaName: schemaName ?? null
5407
+ });
5382
5408
  if (!func || func.kind !== "aggregate") {
5383
5409
  throw new Error(`Function '${name}' is not an aggregate function`);
5384
5410
  }
@@ -5390,7 +5416,7 @@ function registerAggregateMethods(protocol, registry) {
5390
5416
  handler: async (params) => {
5391
5417
  const innerParams = unwrapRequest(params.request);
5392
5418
  const functionName = innerParams.function_name;
5393
- const cfg = resolveAggregate(functionName);
5419
+ const cfg = resolveAggregate(functionName, innerParams.schema_name ?? null);
5394
5420
  const argBytes = toUint8Array(innerParams.arguments);
5395
5421
  const args = deserializeArguments(argBytes);
5396
5422
  const inputSchema = innerParams.input_schema ? deserializeSchema(toUint8Array(innerParams.input_schema)) : null;
@@ -5423,7 +5449,7 @@ function registerAggregateMethods(protocol, registry) {
5423
5449
  const innerParams = unwrapRequest(params.request);
5424
5450
  const functionName = innerParams.function_name;
5425
5451
  const executionId = toUint8Array(innerParams.execution_id);
5426
- const cfg = resolveAggregate(functionName);
5452
+ const cfg = resolveAggregate(functionName, innerParams.schema_name ?? null);
5427
5453
  const batch = readSingleBatch(toUint8Array(innerParams.input_batch));
5428
5454
  if (!batch || batch.numRows === 0)
5429
5455
  return wrapResult({}, schema2([]));
@@ -5476,7 +5502,7 @@ function registerAggregateMethods(protocol, registry) {
5476
5502
  const innerParams = unwrapRequest(params.request);
5477
5503
  const functionName = innerParams.function_name;
5478
5504
  const executionId = toUint8Array(innerParams.execution_id);
5479
- const cfg = resolveAggregate(functionName);
5505
+ const cfg = resolveAggregate(functionName, innerParams.schema_name ?? null);
5480
5506
  const batch = readSingleBatch(toUint8Array(innerParams.merge_batch));
5481
5507
  if (!batch || batch.numRows === 0)
5482
5508
  return wrapResult({}, schema2([]));
@@ -5521,7 +5547,7 @@ function registerAggregateMethods(protocol, registry) {
5521
5547
  const innerParams = unwrapRequest(params.request);
5522
5548
  const functionName = innerParams.function_name;
5523
5549
  const executionId = toUint8Array(innerParams.execution_id);
5524
- const cfg = resolveAggregate(functionName);
5550
+ const cfg = resolveAggregate(functionName, innerParams.schema_name ?? null);
5525
5551
  const outputSchema = deserializeSchema(toUint8Array(innerParams.output_schema));
5526
5552
  const gidBatch = readSingleBatch(toUint8Array(innerParams.group_ids_batch));
5527
5553
  const groupIds = [];
@@ -6324,11 +6350,12 @@ function splitLenPrefixed(buf, count) {
6324
6350
 
6325
6351
  // src/protocol/handlers/table-buffering.ts
6326
6352
  function registerTableBufferingMethods(protocol, registry, signingKey) {
6327
- function resolveBuffering(name) {
6353
+ function resolveBuffering(name, schemaName) {
6328
6354
  const func = registry.get(name, {
6329
6355
  arguments: new Arguments,
6330
6356
  inputSchema: null,
6331
- isScalar: false
6357
+ isScalar: false,
6358
+ schemaName: schemaName ?? null
6332
6359
  });
6333
6360
  if (!func || func.kind !== "table_buffering") {
6334
6361
  throw new Error(`Function '${name}' is not a table_buffering function`);
@@ -6341,7 +6368,7 @@ function registerTableBufferingMethods(protocol, registry, signingKey) {
6341
6368
  const rawAttach = inner.attach_opaque_data ? toUint8Array(inner.attach_opaque_data) : null;
6342
6369
  const attach = rawAttach && rawAttach.length > 0 ? await openAttach(rawAttach, ctx?.auth, signingKey) : rawAttach;
6343
6370
  const transactionId = inner.transaction_id ? toUint8Array(inner.transaction_id) : null;
6344
- const func = resolveBuffering(functionName);
6371
+ const func = resolveBuffering(functionName, inner.schema_name ?? null);
6345
6372
  const bound = new BoundStorage(storage, executionId);
6346
6373
  const payload = await bound.stateGet(FrameworkNS.BUFFERING_INIT, BoundStorage.packIntKey(-1));
6347
6374
  if (payload == null) {
@@ -6497,6 +6524,10 @@ function isPromise(v) {
6497
6524
  }
6498
6525
 
6499
6526
  class CatalogInterface {
6527
+ catalogNameForAttach(_attachOpaqueData) {
6528
+ const names = this.catalogs();
6529
+ return names.length === 1 ? names[0] : null;
6530
+ }
6500
6531
  create(name, onConflict, options) {
6501
6532
  throw new CatalogReadOnlyError("create");
6502
6533
  }
@@ -7231,7 +7262,8 @@ function buildVgiProtocol(config) {
7231
7262
  registerFunctionMethods(protocol, {
7232
7263
  registry: config.registry,
7233
7264
  recoverExchangeState: config.recoverExchangeState,
7234
- signingKey: config.signingKey
7265
+ signingKey: config.signingKey,
7266
+ catalogInterface: config.catalogInterface
7235
7267
  });
7236
7268
  registerAggregateMethods(protocol, config.registry);
7237
7269
  registerTableBufferingMethods(protocol, config.registry, config.signingKey);
@@ -7280,6 +7312,7 @@ var CACHE_STALE_WHILE_REVALIDATE_KEY = "vgi.cache.stale_while_revalidate";
7280
7312
  var CACHE_STALE_IF_ERROR_KEY = "vgi.cache.stale_if_error";
7281
7313
  var CACHE_NOT_MODIFIED_KEY = "vgi.cache.not_modified";
7282
7314
  var CACHE_PARTITION_SCOPE_KEY = "vgi.cache.partition_scope";
7315
+ var CACHE_PER_VALUE_KEY = "vgi.cache.per_value";
7283
7316
  var CACHE_IF_NONE_MATCH_KEY = "vgi.cache.if_none_match";
7284
7317
  var CACHE_IF_MODIFIED_SINCE_KEY = "vgi.cache.if_modified_since";
7285
7318
  var CACHE_SCOPE_CATALOG = "catalog";
@@ -7318,6 +7351,8 @@ function cacheControlMetadata(cc, extra) {
7318
7351
  md.set(CACHE_NOT_MODIFIED_KEY, "1");
7319
7352
  if (cc.partitionScope)
7320
7353
  md.set(CACHE_PARTITION_SCOPE_KEY, "1");
7354
+ if (cc.perValue)
7355
+ md.set(CACHE_PER_VALUE_KEY, "1");
7321
7356
  return md;
7322
7357
  }
7323
7358
 
@@ -8088,6 +8123,17 @@ class ReadOnlyCatalogInterface extends CatalogInterface {
8088
8123
  super();
8089
8124
  this._descriptor = descriptor;
8090
8125
  this._registry = registry;
8126
+ for (const sch of descriptor.schemas ?? []) {
8127
+ for (const fn of sch.functions ?? [])
8128
+ registry.registerInSchema(fn, sch.name, descriptor.name);
8129
+ for (const tbl of sch.tables ?? []) {
8130
+ for (const key of ["function", "insertFunction", "updateFunction", "deleteFunction"]) {
8131
+ const fn = tbl[key];
8132
+ if (fn)
8133
+ registry.registerInSchema(fn, sch.name, descriptor.name);
8134
+ }
8135
+ }
8136
+ }
8091
8137
  }
8092
8138
  catalogs() {
8093
8139
  return [this._descriptor.name];
@@ -8710,6 +8756,13 @@ class CompositeCatalogInterface extends CatalogInterface {
8710
8756
  }
8711
8757
  return route;
8712
8758
  }
8759
+ catalogNameForAttach(attachOpaqueData) {
8760
+ try {
8761
+ return this._route(attachOpaqueData).catalogNameForAttach(attachOpaqueData);
8762
+ } catch {
8763
+ return null;
8764
+ }
8765
+ }
8713
8766
  catalogs() {
8714
8767
  const all = [];
8715
8768
  for (const b of this._backends)
@@ -8938,9 +8991,17 @@ function filterByArgumentTypes(candidates, args, inputSchema, isScalar) {
8938
8991
  const maxScore = Math.max(...scored.map((s) => s.score));
8939
8992
  return scored.filter((s) => s.score === maxScore).map((s) => s.func);
8940
8993
  }
8994
+ function schemaKey(schemaName, functionName) {
8995
+ return `${schemaName.toLowerCase()}\x00${functionName}`;
8996
+ }
8997
+ function catalogKey(catalogName, schemaName, functionName) {
8998
+ return `${catalogName.toLowerCase()}\x00${schemaKey(schemaName, functionName)}`;
8999
+ }
8941
9000
 
8942
9001
  class FunctionRegistry {
8943
9002
  _functions = new Map;
9003
+ _bySchema = new Map;
9004
+ _byCatalog = new Map;
8944
9005
  register(func) {
8945
9006
  const name = func.meta.name;
8946
9007
  if (!this._functions.has(name)) {
@@ -8948,11 +9009,57 @@ class FunctionRegistry {
8948
9009
  }
8949
9010
  this._functions.get(name).push(func);
8950
9011
  }
9012
+ registerInSchema(func, schemaName, catalogName) {
9013
+ const add = (map3, key) => {
9014
+ const bucket = map3.get(key);
9015
+ if (!bucket) {
9016
+ map3.set(key, [func]);
9017
+ return;
9018
+ }
9019
+ if (!bucket.includes(func))
9020
+ bucket.push(func);
9021
+ };
9022
+ add(this._bySchema, schemaKey(schemaName, func.meta.name));
9023
+ if (catalogName) {
9024
+ add(this._byCatalog, catalogKey(catalogName, schemaName, func.meta.name));
9025
+ }
9026
+ }
9027
+ schemasFor(functionName) {
9028
+ const out = [];
9029
+ for (const key of this._bySchema.keys()) {
9030
+ const [schema3, name] = key.split("\x00");
9031
+ if (name === functionName)
9032
+ out.push(schema3);
9033
+ }
9034
+ return out.sort();
9035
+ }
8951
9036
  get(name, context) {
8952
- const candidates = this._functions.get(name);
9037
+ let candidates = this._functions.get(name);
9038
+ const catalogName = context?.catalogName;
9039
+ const schemaName = context?.schemaName;
9040
+ if (catalogName && schemaName) {
9041
+ const scoped = this._byCatalog.get(catalogKey(catalogName, schemaName, name));
9042
+ if (scoped && scoped.length > 0) {
9043
+ return this._disambiguate(name, scoped, context);
9044
+ }
9045
+ }
9046
+ if (schemaName) {
9047
+ const scoped = this._bySchema.get(schemaKey(schemaName, name));
9048
+ if (scoped && scoped.length > 0) {
9049
+ candidates = scoped;
9050
+ } else if (candidates && candidates.length > 0) {
9051
+ const schemas = this.schemasFor(name);
9052
+ if (schemas.length > 0) {
9053
+ throw new Error(`Function '${name}' is not registered in schema '${schemaName}'. ` + `It is available in: [${schemas.join(", ")}]`);
9054
+ }
9055
+ }
9056
+ }
8953
9057
  if (!candidates || candidates.length === 0) {
8954
9058
  throw new FunctionNotFoundError(name, this.names());
8955
9059
  }
9060
+ return this._disambiguate(name, candidates, context);
9061
+ }
9062
+ _disambiguate(name, candidates, context) {
8956
9063
  if (candidates.length === 1) {
8957
9064
  return candidates[0];
8958
9065
  }
@@ -9580,4 +9687,4 @@ export {
9580
9687
  Arguments
9581
9688
  };
9582
9689
 
9583
- //# debugId=702D54392090E98D64756E2164756E21
9690
+ //# debugId=938A6404CE5CDC7964756E2164756E21