@query-farm/vgi 0.17.0 → 0.19.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.
Files changed (40) hide show
  1. package/dist/arrow/impl-arrowjs/index.d.ts +1 -0
  2. package/dist/arrow/impl-arrowjs/metadata.d.ts +12 -0
  3. package/dist/arrow/impl-flechette/index.d.ts +1 -0
  4. package/dist/arrow/impl-flechette/metadata.d.ts +13 -0
  5. package/dist/arrow/index.d.ts +1 -1
  6. package/dist/catalog/descriptors.d.ts +13 -7
  7. package/dist/client-entry.js +16 -5
  8. package/dist/client-entry.js.map +9 -8
  9. package/dist/functions/scalar.d.ts +10 -0
  10. package/dist/functions/table-in-out.d.ts +121 -0
  11. package/dist/functions/types.d.ts +12 -0
  12. package/dist/generated/vgi-client.d.ts +3 -1
  13. package/dist/index.core.d.ts +1 -1
  14. package/dist/index.js +310 -21
  15. package/dist/index.js.map +16 -15
  16. package/dist/protocol/types.d.ts +12 -0
  17. package/dist/serve-entry.js +14 -4
  18. package/dist/serve-entry.js.map +8 -7
  19. package/dist/worker-cf-entry.js +188 -26
  20. package/dist/worker-cf-entry.js.map +14 -13
  21. package/dist/worker.d.ts +1 -1
  22. package/package.json +3 -3
  23. package/src/arrow/impl-arrowjs/index.ts +1 -0
  24. package/src/arrow/impl-arrowjs/metadata.ts +20 -0
  25. package/src/arrow/impl-flechette/index.ts +1 -0
  26. package/src/arrow/impl-flechette/metadata.ts +25 -0
  27. package/src/arrow/index.ts +2 -0
  28. package/src/catalog/descriptors.ts +13 -7
  29. package/src/catalog/read-only.ts +31 -14
  30. package/src/client/client.ts +1 -0
  31. package/src/functions/registry.ts +53 -5
  32. package/src/functions/scalar.ts +17 -1
  33. package/src/functions/table-in-out.ts +480 -4
  34. package/src/functions/types.ts +12 -0
  35. package/src/generated/vgi-client.ts +4 -2
  36. package/src/generated/vgi-protocol-schemas.ts +3 -2
  37. package/src/index.core.ts +11 -1
  38. package/src/protocol/serializers/init.ts +7 -0
  39. package/src/protocol/types.ts +12 -0
  40. package/src/worker.ts +1 -1
@@ -1586,6 +1586,14 @@ function projectBatch(projectionIds, batch) {
1586
1586
  }
1587
1587
  var init_project = () => {};
1588
1588
 
1589
+ // src/arrow/impl-arrowjs/metadata.ts
1590
+ import { RecordBatch as RecordBatch4 } from "@query-farm/apache-arrow";
1591
+ function withBatchMetadata(batch, metadata) {
1592
+ const a = batch;
1593
+ return new RecordBatch4(a.schema, a.data, metadata);
1594
+ }
1595
+ var init_metadata = () => {};
1596
+
1589
1597
  // src/arrow/impl-arrowjs/ipc.ts
1590
1598
  import {
1591
1599
  Schema as Schema4,
@@ -1634,7 +1642,7 @@ import {
1634
1642
  Field as Field3,
1635
1643
  Null,
1636
1644
  makeData as makeData5,
1637
- RecordBatch as RecordBatch5,
1645
+ RecordBatch as RecordBatch6,
1638
1646
  Struct as Struct5,
1639
1647
  SparseUnion,
1640
1648
  Schema as Schema5,
@@ -1746,7 +1754,7 @@ function assemble(columnNames, minData, maxData, hasNull, hasNotNull, distinctCo
1746
1754
  ];
1747
1755
  const structType = new Struct5(schema2.fields);
1748
1756
  const data = makeData5({ type: structType, length: n, children, nullCount: 0 });
1749
- return new RecordBatch5(schema2, data);
1757
+ return new RecordBatch6(schema2, data);
1750
1758
  }
1751
1759
  var init_statistics = __esm(() => {
1752
1760
  init_registry();
@@ -1756,6 +1764,7 @@ var init_statistics = __esm(() => {
1756
1764
  // src/arrow/impl-arrowjs/index.ts
1757
1765
  var exports_impl_arrowjs = {};
1758
1766
  __export(exports_impl_arrowjs, {
1767
+ withBatchMetadata: () => withBatchMetadata,
1759
1768
  utf8: () => utf8,
1760
1769
  union: () => union,
1761
1770
  uint8: () => uint8,
@@ -1830,6 +1839,7 @@ var init_impl_arrowjs = __esm(() => {
1830
1839
  init_filter();
1831
1840
  init_project();
1832
1841
  init_canonical();
1842
+ init_metadata();
1833
1843
  init_ipc();
1834
1844
  init_statistics();
1835
1845
  backend = { name: "arrow-js" };
@@ -1928,6 +1938,7 @@ var init_branded = __esm(() => {
1928
1938
  // src/arrow/index.ts
1929
1939
  var exports_arrow = {};
1930
1940
  __export(exports_arrow, {
1941
+ withBatchMetadata: () => withBatchMetadata,
1931
1942
  utf8: () => utf82,
1932
1943
  union: () => union2,
1933
1944
  uint8: () => uint82,
@@ -2975,6 +2986,7 @@ var INIT_REQUEST_SCHEMA = schema2([
2975
2986
  field2("phase", utf82(), true),
2976
2987
  field2("execution_id", binary2(), true),
2977
2988
  field2("init_opaque_data", binary2(), true),
2989
+ field2("substream_id", binary2(), true),
2978
2990
  field2("order_by_column_name", utf82(), true),
2979
2991
  field2("order_by_direction", utf82(), true),
2980
2992
  field2("order_by_null_order", utf82(), true),
@@ -3039,6 +3051,7 @@ function deserializeInitRequest(params) {
3039
3051
  finalize_state_id: params.finalize_state_id ? toUint8Array2(params.finalize_state_id) : null,
3040
3052
  execution_id: params.execution_id ? toUint8Array2(params.execution_id) : null,
3041
3053
  init_opaque_data: params.init_opaque_data ? toUint8Array2(params.init_opaque_data) : null,
3054
+ substream_id: params.substream_id ? toUint8Array2(params.substream_id) : null,
3042
3055
  order_by_column_name: parseEnum(decodeDictValue(params.order_by_column_name)) ?? null,
3043
3056
  order_by_direction: parseDirection(decodeDictValue(params.order_by_direction)),
3044
3057
  order_by_null_order: parseNullOrder(decodeDictValue(params.order_by_null_order)),
@@ -3175,7 +3188,7 @@ var TableInfoSchema = schema2([
3175
3188
  field2("cardinality_max", int642(), false),
3176
3189
  field2("column_statistics", binary2(), false),
3177
3190
  field2("bind_result", binary2(), false),
3178
- field2("required_field_filter_paths", list2(field2("item", utf82(), true)), false)
3191
+ field2("required_filters", list2(field2("item", list2(field2("item", utf82(), true)), true)), false)
3179
3192
  ]);
3180
3193
  var ViewInfoSchema = schema2([
3181
3194
  field2("comment", utf82(), true),
@@ -3215,6 +3228,7 @@ var FunctionInfoSchema = schema2([
3215
3228
  field2("source_order_dependent", bool2(), false),
3216
3229
  field2("sink_order_dependent", bool2(), false),
3217
3230
  field2("requires_input_batch_index", bool2(), false),
3231
+ field2("input_from_args", bool2(), false),
3218
3232
  field2("required_settings", list2(field2("item", utf82(), true)), false),
3219
3233
  field2("required_secrets", list2(field2("item", struct2([field2("secret_type", utf82(), false), field2("scope", utf82(), true), field2("secret_name", utf82(), true)]), true)), false)
3220
3234
  ]);
@@ -7210,6 +7224,58 @@ function createVgiFetch(opts) {
7210
7224
  }
7211
7225
  // src/functions/scalar.ts
7212
7226
  init_arrow();
7227
+
7228
+ // src/cache-control.ts
7229
+ var CACHE_TTL_KEY = "vgi.cache.ttl";
7230
+ var CACHE_EXPIRES_KEY = "vgi.cache.expires";
7231
+ var CACHE_NO_STORE_KEY = "vgi.cache.no_store";
7232
+ var CACHE_SCOPE_KEY = "vgi.cache.scope";
7233
+ var CACHE_ETAG_KEY = "vgi.cache.etag";
7234
+ var CACHE_LAST_MODIFIED_KEY = "vgi.cache.last_modified";
7235
+ var CACHE_REVALIDATABLE_KEY = "vgi.cache.revalidatable";
7236
+ var CACHE_STALE_WHILE_REVALIDATE_KEY = "vgi.cache.stale_while_revalidate";
7237
+ var CACHE_STALE_IF_ERROR_KEY = "vgi.cache.stale_if_error";
7238
+ var CACHE_NOT_MODIFIED_KEY = "vgi.cache.not_modified";
7239
+ var CACHE_IF_NONE_MATCH_KEY = "vgi.cache.if_none_match";
7240
+ var CACHE_IF_MODIFIED_SINCE_KEY = "vgi.cache.if_modified_since";
7241
+ var CACHE_SCOPE_CATALOG = "catalog";
7242
+ var CACHE_SCOPE_TRANSACTION = "transaction";
7243
+ var VALID_SCOPES = [CACHE_SCOPE_CATALOG, CACHE_SCOPE_TRANSACTION];
7244
+ function cacheControlMetadata(cc, extra) {
7245
+ const scope = cc.scope ?? CACHE_SCOPE_CATALOG;
7246
+ if (!VALID_SCOPES.includes(scope)) {
7247
+ throw new Error(`CacheControl.scope must be one of ${VALID_SCOPES.join(", ")}, got ${JSON.stringify(scope)}`);
7248
+ }
7249
+ for (const name of ["ttl", "staleWhileRevalidate", "staleIfError"]) {
7250
+ const value = cc[name];
7251
+ if (value !== undefined && value < 0) {
7252
+ throw new Error(`CacheControl.${name} must be >= 0, got ${value}`);
7253
+ }
7254
+ }
7255
+ const md = new Map(extra ?? []);
7256
+ if (cc.ttl !== undefined)
7257
+ md.set(CACHE_TTL_KEY, String(cc.ttl));
7258
+ if (cc.expires !== undefined)
7259
+ md.set(CACHE_EXPIRES_KEY, cc.expires);
7260
+ if (cc.noStore)
7261
+ md.set(CACHE_NO_STORE_KEY, "1");
7262
+ md.set(CACHE_SCOPE_KEY, scope);
7263
+ if (cc.etag !== undefined)
7264
+ md.set(CACHE_ETAG_KEY, cc.etag);
7265
+ if (cc.lastModified !== undefined)
7266
+ md.set(CACHE_LAST_MODIFIED_KEY, cc.lastModified);
7267
+ if (cc.revalidatable)
7268
+ md.set(CACHE_REVALIDATABLE_KEY, "1");
7269
+ if (cc.staleWhileRevalidate !== undefined)
7270
+ md.set(CACHE_STALE_WHILE_REVALIDATE_KEY, String(cc.staleWhileRevalidate));
7271
+ if (cc.staleIfError !== undefined)
7272
+ md.set(CACHE_STALE_IF_ERROR_KEY, String(cc.staleIfError));
7273
+ if (cc.notModified)
7274
+ md.set(CACHE_NOT_MODIFIED_KEY, "1");
7275
+ return md;
7276
+ }
7277
+
7278
+ // src/functions/scalar.ts
7213
7279
  function defineScalarFunction(config) {
7214
7280
  const repr = config.repr ?? "rich";
7215
7281
  const specs = [];
@@ -7356,7 +7422,7 @@ function defineScalarFunction(config) {
7356
7422
  if (outputBatch.numRows !== input.numRows) {
7357
7423
  throw new RowCountMismatchError(input.numRows, outputBatch.numRows);
7358
7424
  }
7359
- out.emit(outputBatch);
7425
+ out.emit(outputBatch, config.cacheControl ? cacheControlMetadata(config.cacheControl) : undefined);
7360
7426
  }
7361
7427
  };
7362
7428
  }
@@ -7366,12 +7432,6 @@ function defineScalarFunction(config) {
7366
7432
  init_arrow();
7367
7433
  init_registry();
7368
7434
  init_storage();
7369
-
7370
- // src/cache-control.ts
7371
- var CACHE_IF_NONE_MATCH_KEY = "vgi.cache.if_none_match";
7372
- var CACHE_IF_MODIFIED_SINCE_KEY = "vgi.cache.if_modified_since";
7373
-
7374
- // src/functions/table.ts
7375
7435
  function base64Decode(s) {
7376
7436
  const bin = globalThis.atob ? globalThis.atob(s) : Buffer.from(s, "base64").toString("binary");
7377
7437
  const out = new Uint8Array(bin.length);
@@ -7762,7 +7822,8 @@ function defineTableInOutFunction(config) {
7762
7822
  settings,
7763
7823
  secrets,
7764
7824
  pushdownFilters,
7765
- storage: boundStorage
7825
+ storage: boundStorage,
7826
+ substreamId: request.substream_id ?? null
7766
7827
  };
7767
7828
  const phase = request.phase;
7768
7829
  if (phase === "FINALIZE" /* FINALIZE */) {
@@ -7805,7 +7866,14 @@ function defineTableInOutFunction(config) {
7805
7866
  inputSchema: request.bind_call.input_schema ?? undefined,
7806
7867
  exchangeInit: () => ({ state, processParams }),
7807
7868
  exchangeFn: async (eState, input, out) => {
7808
- const wrappedOut = config.autoApplyFilters && pushdownFilters ? new FilteringOutputCollector(out, pushdownFilters) : out;
7869
+ applyRevalidationValidators(eState.processParams, input);
7870
+ let wrappedOut = makeMetadataBakingCollector(out);
7871
+ if (projIds) {
7872
+ wrappedOut = makeSchemaReconcilingCollector(wrappedOut, outputSchema);
7873
+ }
7874
+ if (config.autoApplyFilters && pushdownFilters) {
7875
+ wrappedOut = new FilteringOutputCollector(wrappedOut, pushdownFilters);
7876
+ }
7809
7877
  await processFn(eState.processParams, eState.state, input, wrappedOut);
7810
7878
  if (eState.state != null) {
7811
7879
  const serialized = serializeUserState(eState.state);
@@ -7818,6 +7886,62 @@ function defineTableInOutFunction(config) {
7818
7886
  }
7819
7887
  };
7820
7888
  }
7889
+ function applyRevalidationValidators(params, input) {
7890
+ const md = input?.metadata;
7891
+ params.ifNoneMatch = md?.get(CACHE_IF_NONE_MATCH_KEY);
7892
+ params.ifModifiedSince = md?.get(CACHE_IF_MODIFIED_SINCE_KEY);
7893
+ }
7894
+ function makeMetadataBakingCollector(inner) {
7895
+ return new Proxy(inner, {
7896
+ get(target, prop, receiver) {
7897
+ if (prop === "emit") {
7898
+ return function(batchOrColumns, metadata) {
7899
+ if (batchOrColumns && typeof batchOrColumns.getChild === "function" && metadata && metadata.size > 0) {
7900
+ const batch = batchOrColumns;
7901
+ const merged = new Map(batch.metadata ?? []);
7902
+ for (const [k, v2] of metadata)
7903
+ merged.set(k, v2);
7904
+ return target.emit(withBatchMetadata(batch, merged), merged);
7905
+ }
7906
+ return target.emit(batchOrColumns, metadata);
7907
+ };
7908
+ }
7909
+ const v = Reflect.get(target, prop, receiver);
7910
+ return typeof v === "function" ? v.bind(target) : v;
7911
+ }
7912
+ });
7913
+ }
7914
+ function makeSchemaReconcilingCollector(inner, targetSchema) {
7915
+ function reconcile(batch) {
7916
+ const batchFields = batch.schema.fields;
7917
+ if (batchFields.length === targetSchema.fields.length && targetSchema.fields.every((f, i) => batchFields[i].name === f.name)) {
7918
+ return batch;
7919
+ }
7920
+ const ids = [];
7921
+ for (const f of targetSchema.fields) {
7922
+ const idx = batchFields.findIndex((bf) => bf.name === f.name);
7923
+ if (idx < 0) {
7924
+ throw new Error(`emitted batch is missing projected output column '${f.name}' ` + `(emitted: [${batchFields.map((bf) => bf.name).join(", ")}])`);
7925
+ }
7926
+ ids.push(idx);
7927
+ }
7928
+ return projectBatch(ids, batch);
7929
+ }
7930
+ return new Proxy(inner, {
7931
+ get(target, prop, receiver) {
7932
+ if (prop === "emit") {
7933
+ return function(batchOrColumns, metadata) {
7934
+ if (batchOrColumns && typeof batchOrColumns.getChild === "function") {
7935
+ return target.emit(reconcile(batchOrColumns), metadata);
7936
+ }
7937
+ return target.emit(batchOrColumns, metadata);
7938
+ };
7939
+ }
7940
+ const v = Reflect.get(target, prop, receiver);
7941
+ return typeof v === "function" ? v.bind(target) : v;
7942
+ }
7943
+ });
7944
+ }
7821
7945
  // src/catalog/read-only.ts
7822
7946
  init_arrow();
7823
7947
 
@@ -8058,16 +8182,21 @@ class ReadOnlyCatalogInterface extends CatalogInterface {
8058
8182
  const uniqueIndices = resolveIndexGroups(colSchema, t.unique);
8059
8183
  const pkIndices = resolveIndexGroups(colSchema, t.primaryKey);
8060
8184
  const fkBytes = serializeForeignKeys(t.foreignKey, name);
8061
- const requiredFieldFilterPaths = t.requiredFieldFilterPaths ?? [];
8062
- if (requiredFieldFilterPaths.length > 0) {
8185
+ const requiredFilters = t.requiredFilters ?? [];
8186
+ if (requiredFilters.length > 0) {
8063
8187
  const columnNames = new Set(colSchema.fields.map((f) => f.name));
8064
- for (const path2 of requiredFieldFilterPaths) {
8065
- if (!path2) {
8066
- throw new Error(`Table '${t.name}': requiredFieldFilterPaths must not contain empty strings`);
8188
+ for (const group of requiredFilters) {
8189
+ if (!group || group.length === 0) {
8190
+ throw new Error(`Table '${t.name}': requiredFilters must not contain empty groups`);
8067
8191
  }
8068
- const head = path2.split(".", 1)[0];
8069
- if (!columnNames.has(head)) {
8070
- throw new Error(`Table '${t.name}': requiredFieldFilterPaths path '${path2}' references ` + `unknown column '${head}'. Available columns: ${[...columnNames].sort().join(", ")}`);
8192
+ for (const path2 of group) {
8193
+ if (!path2) {
8194
+ throw new Error(`Table '${t.name}': requiredFilters must not contain empty strings`);
8195
+ }
8196
+ const head = path2.split(".", 1)[0];
8197
+ if (!columnNames.has(head)) {
8198
+ throw new Error(`Table '${t.name}': requiredFilters path '${path2}' references ` + `unknown column '${head}'. Available columns: ${[...columnNames].sort().join(", ")}`);
8199
+ }
8071
8200
  }
8072
8201
  }
8073
8202
  }
@@ -8093,7 +8222,7 @@ class ReadOnlyCatalogInterface extends CatalogInterface {
8093
8222
  delete_function: null,
8094
8223
  cardinality_estimate: t.inlinedCardinality ? Number(t.inlinedCardinality.estimate) : null,
8095
8224
  cardinality_max: t.inlinedCardinality ? Number(t.inlinedCardinality.max) : null,
8096
- required_field_filter_paths: requiredFieldFilterPaths
8225
+ required_filters: requiredFilters
8097
8226
  };
8098
8227
  }));
8099
8228
  }
@@ -8180,6 +8309,7 @@ class ReadOnlyCatalogInterface extends CatalogInterface {
8180
8309
  source_order_dependent: f.kind === "table_buffering" && f.meta.sourceOrderDependent === true,
8181
8310
  sink_order_dependent: f.kind === "table_buffering" && f.meta.sinkOrderDependent === true,
8182
8311
  requires_input_batch_index: f.kind === "table_buffering" && f.meta.requiresInputBatchIndex === true,
8312
+ input_from_args: f.kind === "table_in_out" && f.meta.inputFromArgs === true,
8183
8313
  required_settings: meta.requiredSettings,
8184
8314
  required_secrets: requiredSecrets.map((s) => ({
8185
8315
  secret_type: s.secret_type,
@@ -8724,10 +8854,27 @@ function filterByArgumentTypes(candidates, args, inputSchema, isScalar) {
8724
8854
  } else {
8725
8855
  const posSpecs = specs.filter((s) => typeof s.position === "number" && !s.isTableInput).sort((a, b) => a.position - b.position);
8726
8856
  const posTypes = [];
8727
- const argsSchema = args.argumentsSchema;
8728
- for (let i = 0;i < args.positional.length; i++) {
8729
- const field3 = argsSchema?.fields.find((f) => f.name === `positional_${i}`);
8730
- posTypes.push(field3 ? field3.type : null);
8857
+ if (func.meta.inputFromArgs) {
8858
+ if (inputSchema) {
8859
+ let varArgsSpec = null;
8860
+ for (const spec of posSpecs) {
8861
+ if (spec.isVarargs)
8862
+ varArgsSpec = spec;
8863
+ const pos = spec.position;
8864
+ posTypes.push(pos < inputSchema.fields.length ? inputSchema.fields[pos].type : null);
8865
+ }
8866
+ if (varArgsSpec) {
8867
+ for (let i = varArgsSpec.position + 1;i < inputSchema.fields.length; i++) {
8868
+ posTypes.push(inputSchema.fields[i].type);
8869
+ }
8870
+ }
8871
+ }
8872
+ } else {
8873
+ const argsSchema = args.argumentsSchema;
8874
+ for (let i = 0;i < args.positional.length; i++) {
8875
+ const field3 = argsSchema?.fields.find((f) => f.name === `positional_${i}`);
8876
+ posTypes.push(field3 ? field3.type : null);
8877
+ }
8731
8878
  }
8732
8879
  const r = scoreTypes(posSpecs, posTypes);
8733
8880
  score += r.score;
@@ -8786,6 +8933,21 @@ class FunctionRegistry {
8786
8933
  const posSpecs = func.argumentSpecs.filter((s) => typeof s.position === "number" && !s.isTableInput);
8787
8934
  const hasVarargs = posSpecs.some((s) => s.isVarargs);
8788
8935
  const nonVarargs = posSpecs.filter((s) => !s.isVarargs).length;
8936
+ if (func.meta.inputFromArgs) {
8937
+ const numInputCols = context.inputSchema?.fields.length ?? 0;
8938
+ if (hasVarargs) {
8939
+ if (numInputCols < nonVarargs)
8940
+ return false;
8941
+ } else if (numInputCols !== posSpecs.length) {
8942
+ return false;
8943
+ }
8944
+ const validNamed = new Set(func.argumentSpecs.filter((s) => typeof s.position === "string").map((s) => s.position));
8945
+ for (const key of args.named.keys()) {
8946
+ if (!validNamed.has(key))
8947
+ return false;
8948
+ }
8949
+ return true;
8950
+ }
8789
8951
  if (hasVarargs) {
8790
8952
  return numArgs >= nonVarargs;
8791
8953
  }
@@ -9369,4 +9531,4 @@ export {
9369
9531
  Arguments
9370
9532
  };
9371
9533
 
9372
- //# debugId=C67D053F70399BE264756E2164756E21
9534
+ //# debugId=9CBEC1BA4EDD0C8364756E2164756E21