kitcn 0.32.0 → 0.32.2

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/orm/index.js CHANGED
@@ -1322,6 +1322,20 @@ const DEFAULT_RELATION_FAN_OUT_MAX_KEYS = 1e3;
1322
1322
  * satisfies the limit.
1323
1323
  */
1324
1324
  const RELATION_FILTER_STREAM_CHUNK = 32;
1325
+ /**
1326
+ * Marks a relation config that only exists to answer "does a matching child
1327
+ * exist?" for a `where` clause. The lowered load may stop at the first
1328
+ * surviving child, but it must not widen the window it walks to find one --
1329
+ * that window is what decides the answer, so changing it would change results
1330
+ * rather than just their cost.
1331
+ *
1332
+ * A symbol, not a field: the emitted object is fed to the same relation loader
1333
+ * that serves a caller's `with`, and nothing a caller can write should be able
1334
+ * to claim this.
1335
+ */
1336
+ const RELATION_EXISTENCE_PROBE = Symbol("kitcn.relationExistenceProbe");
1337
+ /** Lowering a subtree with this set emits no existence probes anywhere in it. */
1338
+ const NO_PROBE_RELATIONS = /* @__PURE__ */ new Set();
1325
1339
  const DEFAULT_AGGREGATE_CARTESIAN_MAX_KEYS = 4096;
1326
1340
  const DEFAULT_AGGREGATE_WORK_BUDGET = 16384;
1327
1341
  const PUBLIC_ID_FIELD = "id";
@@ -1619,6 +1633,20 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
1619
1633
  * intervening write would make it stale.
1620
1634
  */
1621
1635
  _documentByNormalizedId = /* @__PURE__ */ new Map();
1636
+ /**
1637
+ * Single target documents resolved by an eq-pinned key during one execution,
1638
+ * keyed on the read itself: table, index, join columns and their values.
1639
+ *
1640
+ * `_documentByNormalizedId` only covers a join on the primary id. A relation
1641
+ * joined on any other column resolves its target with `.first()` instead, and
1642
+ * the same one-row-at-a-time membership predicate re-issues that read once per
1643
+ * drain. The index is fixed for the whole relation and the key is pinned by
1644
+ * `eq`, so the first row is a pure function of this key within an execution.
1645
+ *
1646
+ * Same scope and staleness argument as `_documentByNormalizedId`: not handed
1647
+ * to the next run by `_forExecution`, so an intervening write is still seen.
1648
+ */
1649
+ _firstDocumentByFieldKey = /* @__PURE__ */ new Map();
1622
1650
  constructor(schema, tableConfig, edgeMetadata, db, config, mode, _allEdges, rls, relationLoading, vectorSearchProvider, configuredIndex, countIndexReadiness) {
1623
1651
  super();
1624
1652
  this.schema = schema;
@@ -2391,7 +2419,47 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
2391
2419
  }
2392
2420
  }
2393
2421
  }
2422
+ /**
2423
+ * Relation keys the filter tree mentions exactly once, across every OR/AND/NOT
2424
+ * branch at this table level.
2425
+ *
2426
+ * `_mergeWithConfig` collapses the whole tree into one load per relation key,
2427
+ * so a key two branches disagree about has to be loaded the way both branches
2428
+ * can read. Only a key with a single occurrence has one predicate to satisfy,
2429
+ * and only then can that predicate be pushed into the read plan.
2430
+ *
2431
+ * Relation values are not descended into: they belong to the target table and
2432
+ * get their own count when that level is lowered.
2433
+ */
2434
+ _collectSingleOccurrenceRelations(filter, tableConfig) {
2435
+ const counts = /* @__PURE__ */ new Map();
2436
+ const walk = (node) => {
2437
+ if (!this._isRecord(node)) return;
2438
+ for (const [key, value] of Object.entries(node)) {
2439
+ if (value === void 0) continue;
2440
+ if (key === "OR" || key === "AND") {
2441
+ if (!Array.isArray(value)) continue;
2442
+ for (const sub of value) walk(sub);
2443
+ continue;
2444
+ }
2445
+ if (key === "NOT") {
2446
+ walk(value);
2447
+ continue;
2448
+ }
2449
+ if (!tableConfig.relations[key]) continue;
2450
+ counts.set(key, (counts.get(key) ?? 0) + 1);
2451
+ }
2452
+ };
2453
+ walk(filter);
2454
+ const single = /* @__PURE__ */ new Set();
2455
+ for (const [key, count] of counts) if (count === 1) single.add(key);
2456
+ return single;
2457
+ }
2394
2458
  _buildFilterWithConfig(filter, tableConfig) {
2459
+ if (!this._isRecord(filter)) return {};
2460
+ return this._buildFilterWithConfigForLevel(filter, tableConfig, this._collectSingleOccurrenceRelations(filter, tableConfig));
2461
+ }
2462
+ _buildFilterWithConfigForLevel(filter, tableConfig, probeEligible) {
2395
2463
  if (!this._isRecord(filter)) return {};
2396
2464
  const result = {};
2397
2465
  const entries = Object.entries(filter);
@@ -2401,27 +2469,36 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
2401
2469
  if (key === "OR" || key === "AND") {
2402
2470
  if (!Array.isArray(value) || value.length === 0) continue;
2403
2471
  for (const sub of value) {
2404
- const nested = this._buildFilterWithConfig(sub, tableConfig);
2472
+ const nested = this._buildFilterWithConfigForLevel(sub, tableConfig, probeEligible);
2405
2473
  this._mergeWithConfig(result, nested);
2406
2474
  }
2407
2475
  continue;
2408
2476
  }
2409
2477
  if (key === "NOT") {
2410
- const nested = this._buildFilterWithConfig(value, tableConfig);
2478
+ const nested = this._buildFilterWithConfigForLevel(value, tableConfig, probeEligible);
2411
2479
  this._mergeWithConfig(result, nested);
2412
2480
  continue;
2413
2481
  }
2414
2482
  this._assertNoLegacyPublicFieldName(key);
2415
2483
  const relation = tableConfig.relations[key];
2416
2484
  if (!relation) continue;
2485
+ const probe = relation.relationType !== "one" && probeEligible.has(key) ? { [RELATION_EXISTENCE_PROBE]: true } : void 0;
2417
2486
  if (typeof value === "boolean") {
2418
- result[key] = true;
2487
+ result[key] = probe ?? true;
2419
2488
  continue;
2420
2489
  }
2421
2490
  const targetTableConfig = this._getTableConfigByDbName(relation.targetTableName);
2422
2491
  if (!targetTableConfig) continue;
2423
- const nested = this._buildFilterWithConfig(value, targetTableConfig);
2424
- result[key] = Object.keys(nested).length > 0 ? { with: nested } : true;
2492
+ const nested = this._buildFilterWithConfigForLevel(value, targetTableConfig, probe ? this._collectSingleOccurrenceRelations(value, targetTableConfig) : NO_PROBE_RELATIONS);
2493
+ const hasNested = Object.keys(nested).length > 0;
2494
+ if (!probe) {
2495
+ result[key] = hasNested ? { with: nested } : true;
2496
+ continue;
2497
+ }
2498
+ const emitted = { ...probe };
2499
+ if (Object.keys(value).length > 0) emitted.where = value;
2500
+ if (hasNested) emitted.with = nested;
2501
+ result[key] = emitted;
2425
2502
  }
2426
2503
  return result;
2427
2504
  }
@@ -4637,18 +4714,75 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
4637
4714
  if (!this._allEdges) return [];
4638
4715
  return this._allEdges.filter((edge) => edge.sourceTable === tableName);
4639
4716
  }
4717
+ /**
4718
+ * A memo entry is a snapshot, so every caller has to get its own document.
4719
+ *
4720
+ * Relation loaders write nested `with` results and `extras` straight onto the
4721
+ * target they were handed, and `hydrateDateFieldsForRead` copies every own key
4722
+ * it finds. Two loads that share one entry would therefore publish each
4723
+ * other's fields — a relation asked for as `true` coming back carrying a
4724
+ * nested relation only the `where` requested. Those writes are all top-level,
4725
+ * so a shallow copy is exactly as much isolation as they need.
4726
+ */
4727
+ _ownedCopy(doc) {
4728
+ return doc === null || doc === void 0 ? null : { ...doc };
4729
+ }
4640
4730
  async _getById(tableName, id) {
4641
4731
  if (id === null || id === void 0) return null;
4642
4732
  const normalizedId = this.db.normalizeId(tableName, id);
4643
4733
  if (normalizedId === null) return null;
4644
4734
  const existing = this._documentByNormalizedId.get(normalizedId);
4645
- if (existing) return await existing;
4735
+ if (existing) return this._ownedCopy(await existing);
4646
4736
  const pending = Promise.resolve(this.db.get(normalizedId)).catch((error) => {
4647
4737
  this._documentByNormalizedId.delete(normalizedId);
4648
4738
  throw error;
4649
4739
  });
4650
4740
  this._documentByNormalizedId.set(normalizedId, pending);
4651
- return await pending;
4741
+ return this._ownedCopy(await pending);
4742
+ }
4743
+ /**
4744
+ * Identity of one `_firstByFields` read, or null when the join values cannot
4745
+ * be encoded losslessly.
4746
+ *
4747
+ * `JSON.stringify` alone is not safe here. It renders every `ArrayBuffer` as
4748
+ * `{}` and `NaN`/`Infinity`/`-Infinity` as `null`, so two distinct join values
4749
+ * would share one entry, and it throws outright on `int64`. The relation
4750
+ * loader's own per-batch key map cannot catch that, because the residual
4751
+ * relation `where` hands it one row at a time — a map of one never compares
4752
+ * two values. This key is the only thing that tells them apart.
4753
+ *
4754
+ * `convexToJson` is the same wire encoding the client uses for query keys, so
4755
+ * every Convex value round-trips distinctly. Anything it rejects is not a
4756
+ * Convex value and simply goes unmemoized.
4757
+ */
4758
+ _firstByFieldsMemoKey(tableName, fields, values, indexName) {
4759
+ try {
4760
+ return JSON.stringify([
4761
+ tableName,
4762
+ indexName,
4763
+ fields,
4764
+ values.map((value) => convexToJson(value))
4765
+ ]);
4766
+ } catch {
4767
+ return null;
4768
+ }
4769
+ }
4770
+ /**
4771
+ * `_getById` for a relation joined on something other than the primary id:
4772
+ * resolve one target document by an eq-pinned key, memoized per execution.
4773
+ */
4774
+ async _firstByFields(tableName, fields, values, indexName) {
4775
+ const read = () => this._queryByFields(this.db.query(tableName), fields, values, indexName).first();
4776
+ const key = this._firstByFieldsMemoKey(tableName, fields, values, indexName);
4777
+ if (key === null) return await read();
4778
+ const existing = this._firstDocumentByFieldKey.get(key);
4779
+ if (existing) return this._ownedCopy(await existing);
4780
+ const pending = Promise.resolve(read()).catch((error) => {
4781
+ this._firstDocumentByFieldKey.delete(key);
4782
+ throw error;
4783
+ });
4784
+ this._firstDocumentByFieldKey.set(key, pending);
4785
+ return this._ownedCopy(await pending);
4652
4786
  }
4653
4787
  _getRelationConcurrency() {
4654
4788
  const value = this.relationLoading?.concurrency;
@@ -4800,7 +4934,7 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
4800
4934
  const resolveTargetMatch = async (values) => {
4801
4935
  let target = null;
4802
4936
  if (useGetById) target = await this._getById(edge.targetTable, values[0]);
4803
- else target = await this._queryByFields(this.db.query(edge.targetTable), targetFields, values, targetIndexName).first();
4937
+ else target = await this._firstByFields(edge.targetTable, targetFields, values, targetIndexName);
4804
4938
  if (!target) return false;
4805
4939
  return this._evaluateTableFilter(target, targetTableConfig, whereRecord);
4806
4940
  };
@@ -4902,7 +5036,7 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
4902
5036
  const fetched = await this._mapWithConcurrency(entries, async ([key, values]) => {
4903
5037
  let target = null;
4904
5038
  if (useGetById) target = await this._getById(edge.targetTable, values[0]);
4905
- else target = await this._queryByFields(this.db.query(edge.targetTable), targetFields, values, indexName).first();
5039
+ else target = await this._firstByFields(edge.targetTable, targetFields, values, indexName);
4906
5040
  return {
4907
5041
  key,
4908
5042
  target
@@ -4955,9 +5089,10 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
4955
5089
  * parents in the round.
4956
5090
  */
4957
5091
  async _readBoundedThroughLinks(params) {
4958
- const { applyTargetFilters, edge, enforceTargetKeyCap, entries, fetchLimit, fetchTargets, targetFields, throughIndexName, throughTableConfig } = params;
5092
+ const { applyAmbientTargetFilters, applyConfigTargetFilter, edge, enforceTargetKeyCap, entries, fetchLimit, fetchTargets, scanLimit, targetFields, throughIndexName, throughTableConfig } = params;
4959
5093
  const throughTargetFields = edge.through.targetFields;
4960
5094
  const cursors = entries.map(([key, values]) => ({
5095
+ ambientLinks: 0,
4961
5096
  buffered: [],
4962
5097
  exhausted: false,
4963
5098
  iterator: this._queryByFields(this.db.query(edge.through.table), edge.through.sourceFields, values, throughIndexName)[Symbol.asyncIterator](),
@@ -4984,10 +5119,12 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
4984
5119
  };
4985
5120
  /** Target key -> the surviving document, absent when it did not survive. */
4986
5121
  const survivorByKey = /* @__PURE__ */ new Map();
5122
+ /** Target keys that cleared the ambient filters, survivors or not. */
5123
+ const ambientKeys = /* @__PURE__ */ new Set();
4987
5124
  const resolvedKeys = /* @__PURE__ */ new Set();
4988
5125
  const survivors = [];
4989
5126
  while (true) {
4990
- const active = cursors.filter((cursor) => cursor.links.length < fetchLimit && !(cursor.exhausted && cursor.buffered.length === 0));
5127
+ const active = cursors.filter((cursor) => cursor.links.length < fetchLimit && (scanLimit === void 0 || cursor.ambientLinks < scanLimit) && !(cursor.exhausted && cursor.buffered.length === 0));
4991
5128
  if (active.length === 0) break;
4992
5129
  const candidatesPerCursor = await this._mapWithConcurrency(active, async (cursor) => {
4993
5130
  const need = fetchLimit - cursor.links.length;
@@ -5006,7 +5143,12 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
5006
5143
  enforceTargetKeyCap(resolvedKeys.size + newKeys.size);
5007
5144
  const fetched = await fetchTargets(Array.from(newKeys.entries()));
5008
5145
  for (const key of newKeys.keys()) resolvedKeys.add(key);
5009
- const surviving = await applyTargetFilters(fetched.map((entry) => entry.target).filter((target) => !!target));
5146
+ const ambientTargets = await applyAmbientTargetFilters(fetched.map((entry) => entry.target).filter((target) => !!target));
5147
+ for (const target of ambientTargets) {
5148
+ const key = this._buildRelationKey(target, targetFields);
5149
+ if (key) ambientKeys.add(key);
5150
+ }
5151
+ const surviving = await applyConfigTargetFilter(ambientTargets);
5010
5152
  for (const target of surviving) {
5011
5153
  const key = this._buildRelationKey(target, targetFields);
5012
5154
  if (!key || survivorByKey.has(key)) continue;
@@ -5018,8 +5160,11 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
5018
5160
  const cursor = active[i];
5019
5161
  for (const link of candidatesPerCursor[i]) {
5020
5162
  if (cursor.links.length >= fetchLimit) break;
5163
+ if (scanLimit !== void 0 && cursor.ambientLinks >= scanLimit) break;
5021
5164
  const key = this._buildRelationKey(link, throughTargetFields);
5022
- if (!key || !survivorByKey.has(key)) continue;
5165
+ if (!key) continue;
5166
+ if (ambientKeys.has(key)) cursor.ambientLinks += 1;
5167
+ if (!survivorByKey.has(key)) continue;
5023
5168
  cursor.links.push(link);
5024
5169
  }
5025
5170
  }
@@ -5072,6 +5217,7 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
5072
5217
  const relationDefinition = tableConfig.relations[relationName];
5073
5218
  const strict = tableConfig.strict !== false;
5074
5219
  const hasPostFetchTargetFilter = this.rls?.mode !== "skip" && isRlsEnabled(targetTableConfig.table) || Boolean(relationDefinition?.where) || Boolean(relationConfig && typeof relationConfig === "object" && "where" in relationConfig && relationConfig.where);
5220
+ const isExistenceProbe = Boolean(relationConfig) && typeof relationConfig === "object" && relationConfig[RELATION_EXISTENCE_PROBE] === true;
5075
5221
  let orderSpecs = [];
5076
5222
  if (relationConfig && typeof relationConfig === "object" && "orderBy" in relationConfig) {
5077
5223
  let orderByValue = relationConfig.orderBy;
@@ -5086,15 +5232,22 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
5086
5232
  if (effectivePerParentLimit === void 0 && !this.allowFullScan) throw new Error(`Relation "${tableConfig.name}.${relationName}" requires limit, allowFullScan: true, or defineSchema(..., { defaults: { defaultLimit } }).`);
5087
5233
  const perParentOffset = relationConfig && typeof relationConfig === "object" && "offset" in relationConfig ? relationConfig.offset : void 0;
5088
5234
  if (perParentOffset !== void 0 && typeof perParentOffset !== "number") throw new Error("Only numeric offset is supported in kitcn ORM.");
5235
+ const probeFetchLimit = isExistenceProbe ? 1 : void 0;
5236
+ const probeScanLimit = isExistenceProbe ? effectivePerParentLimit : void 0;
5237
+ const canBoundPerParentRead = effectivePerParentLimit !== void 0 || isExistenceProbe;
5089
5238
  const applyOffsetAndLimit = (items) => {
5090
5239
  let result = items;
5091
5240
  if (perParentOffset !== void 0 && perParentOffset > 0) result = result.slice(perParentOffset);
5092
5241
  if (effectivePerParentLimit !== void 0) result = result.slice(0, effectivePerParentLimit);
5093
5242
  return result;
5094
5243
  };
5095
- const applyPostFetchTargetFilters = async (candidateTargets) => {
5096
- let filteredTargets = await this._applyRlsSelectFilter(candidateTargets, targetTableConfig);
5097
- if (relationDefinition?.where) filteredTargets = filteredTargets.filter((target) => this._evaluateTableFilter(target, targetTableConfig, relationDefinition.where));
5244
+ const applyAmbientTargetFilters = async (candidateTargets) => {
5245
+ const visibleTargets = await this._applyRlsSelectFilter(candidateTargets, targetTableConfig);
5246
+ if (!relationDefinition?.where) return visibleTargets;
5247
+ return visibleTargets.filter((target) => this._evaluateTableFilter(target, targetTableConfig, relationDefinition.where));
5248
+ };
5249
+ const applyConfigTargetFilter = async (ambientTargets) => {
5250
+ let filteredTargets = ambientTargets;
5098
5251
  if (relationConfig && typeof relationConfig === "object" && "where" in relationConfig) {
5099
5252
  const whereFilter = relationConfig.where;
5100
5253
  if (typeof whereFilter === "function") {
@@ -5107,6 +5260,7 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
5107
5260
  }
5108
5261
  return filteredTargets;
5109
5262
  };
5263
+ const applyPostFetchTargetFilters = async (candidateTargets) => applyConfigTargetFilter(await applyAmbientTargetFilters(candidateTargets));
5110
5264
  let targets = [];
5111
5265
  let throughBySourceKey;
5112
5266
  let targetFiltersApplied = false;
@@ -5134,21 +5288,23 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
5134
5288
  return await this._mapWithConcurrency(keyEntries, async ([key, values]) => {
5135
5289
  let target = null;
5136
5290
  if (useGetById) target = await this._getById(edge.targetTable, values[0]);
5137
- else target = await this._queryByFields(this.db.query(edge.targetTable), targetFields, values, indexName).first();
5291
+ else target = await this._firstByFields(edge.targetTable, targetFields, values, indexName);
5138
5292
  return {
5139
5293
  key,
5140
5294
  target
5141
5295
  };
5142
5296
  });
5143
5297
  };
5144
- if (orderSpecs.length === 0 && effectivePerParentLimit !== void 0) {
5298
+ if (orderSpecs.length === 0 && canBoundPerParentRead) {
5145
5299
  const bounded = await this._readBoundedThroughLinks({
5146
- applyTargetFilters: applyPostFetchTargetFilters,
5300
+ applyAmbientTargetFilters,
5301
+ applyConfigTargetFilter,
5147
5302
  edge,
5148
5303
  enforceTargetKeyCap,
5149
5304
  entries,
5150
- fetchLimit: Math.max(perParentOffset ?? 0, 0) + effectivePerParentLimit,
5305
+ fetchLimit: probeFetchLimit ?? Math.max(perParentOffset ?? 0, 0) + effectivePerParentLimit,
5151
5306
  fetchTargets: fetchThroughTargets,
5307
+ scanLimit: probeScanLimit,
5152
5308
  targetFields,
5153
5309
  throughIndexName,
5154
5310
  throughTableConfig
@@ -5188,22 +5344,25 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
5188
5344
  });
5189
5345
  const orderServedByIndex = orderSpecs.length === 0 || orderPushdownDirection !== null;
5190
5346
  const applyPushdownOrder = (query) => orderPushdownDirection ? query.order(orderPushdownDirection) : query;
5191
- const streamPostFetchTargetFilters = orderServedByIndex && hasPostFetchTargetFilter && effectivePerParentLimit !== void 0;
5347
+ const streamPostFetchTargetFilters = orderServedByIndex && hasPostFetchTargetFilter && canBoundPerParentRead;
5192
5348
  targetFiltersApplied = streamPostFetchTargetFilters;
5193
5349
  targets = (await this._mapWithConcurrency(entries, async ([, values]) => {
5194
5350
  const query = this._queryByFields(this.db.query(edge.targetTable), targetFields, values, indexName);
5195
- if (orderServedByIndex && !hasPostFetchTargetFilter && effectivePerParentLimit !== void 0) {
5196
- const fetchLimit = (perParentOffset ?? 0) + (effectivePerParentLimit ?? 0);
5351
+ if (orderServedByIndex && !hasPostFetchTargetFilter && canBoundPerParentRead) {
5352
+ const fetchLimit = probeFetchLimit ?? (perParentOffset ?? 0) + (effectivePerParentLimit ?? 0);
5197
5353
  return await applyPushdownOrder(query).take(fetchLimit);
5198
5354
  }
5199
5355
  if (streamPostFetchTargetFilters) {
5200
5356
  const visibleTargets = [];
5201
- const fetchLimit = Math.max(perParentOffset ?? 0, 0) + (effectivePerParentLimit ?? 0);
5357
+ const fetchLimit = probeFetchLimit ?? Math.max(perParentOffset ?? 0, 0) + (effectivePerParentLimit ?? 0);
5202
5358
  let batch = [];
5359
+ let ambientSeen = 0;
5203
5360
  const drain = async () => {
5204
5361
  if (batch.length === 0) return;
5205
- const filtered = await applyPostFetchTargetFilters(batch);
5362
+ const ambientTargets = await applyAmbientTargetFilters(batch);
5206
5363
  batch = [];
5364
+ ambientSeen += ambientTargets.length;
5365
+ const filtered = await applyConfigTargetFilter(ambientTargets);
5207
5366
  for (const row of filtered) {
5208
5367
  if (visibleTargets.length >= fetchLimit) return;
5209
5368
  visibleTargets.push(row);
@@ -5215,6 +5374,7 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
5215
5374
  if (batch.length < chunk) continue;
5216
5375
  await drain();
5217
5376
  if (visibleTargets.length >= fetchLimit) break;
5377
+ if (probeScanLimit !== void 0 && ambientSeen >= probeScanLimit) break;
5218
5378
  }
5219
5379
  if (visibleTargets.length < fetchLimit) await drain();
5220
5380
  return visibleTargets;
@@ -1,3 +1,3 @@
1
- import { C as MigrationStep, D as defineMigration, E as buildMigrationPlan, O as defineMigrationSet, S as MigrationStateMap, T as MigrationWriteMode, _ as MigrationManifestEntry, a as MAX_STATUS_RUN_LIMIT, b as MigrationRunStatus, c as MigrationRunChunkArgs, d as MigrationAppliedState, f as MigrationDefinition, g as MigrationDriftIssue, h as MigrationDocContext, k as detectMigrationDrift, l as MigrationStatusArgs, m as MigrationDoc, o as MigrationCancelArgs, p as MigrationDirection, s as MigrationRunArgs, u as createMigrationHandlers, v as MigrationMigrateOne, w as MigrationTableName, x as MigrationSet, y as MigrationPlan } from "../../capabilities-CD-Ij91k.js";
2
- import { Ct as migrationCapability, dt as MIGRATION_STORAGE_TABLE_NAMES, ft as injectMigrationStorageTables, lt as MIGRATION_RUN_TABLE, mt as migrationStorageTables, pt as migrationExtension, ut as MIGRATION_STATE_TABLE } from "../../where-clause-compiler-FDJTqLDC.js";
1
+ import { C as MigrationStep, D as defineMigration, E as buildMigrationPlan, O as defineMigrationSet, S as MigrationStateMap, T as MigrationWriteMode, _ as MigrationManifestEntry, a as MAX_STATUS_RUN_LIMIT, b as MigrationRunStatus, c as MigrationRunChunkArgs, d as MigrationAppliedState, f as MigrationDefinition, g as MigrationDriftIssue, h as MigrationDocContext, k as detectMigrationDrift, l as MigrationStatusArgs, m as MigrationDoc, o as MigrationCancelArgs, p as MigrationDirection, s as MigrationRunArgs, u as createMigrationHandlers, v as MigrationMigrateOne, w as MigrationTableName, x as MigrationSet, y as MigrationPlan } from "../../capabilities-BJm_VSDT.js";
2
+ import { Ct as migrationCapability, dt as MIGRATION_STORAGE_TABLE_NAMES, ft as injectMigrationStorageTables, lt as MIGRATION_RUN_TABLE, mt as migrationStorageTables, pt as migrationExtension, ut as MIGRATION_STATE_TABLE } from "../../where-clause-compiler-Dgf4lrO-.js";
3
3
  export { MAX_STATUS_RUN_LIMIT, MIGRATION_RUN_TABLE, MIGRATION_STATE_TABLE, MIGRATION_STORAGE_TABLE_NAMES, type MigrationAppliedState, type MigrationCancelArgs, type MigrationDefinition, type MigrationDirection, type MigrationDoc, type MigrationDocContext, type MigrationDriftIssue, type MigrationManifestEntry, type MigrationMigrateOne, type MigrationPlan, type MigrationRunArgs, type MigrationRunChunkArgs, type MigrationRunStatus, type MigrationSet, type MigrationStateMap, type MigrationStatusArgs, type MigrationStep, type MigrationTableName, type MigrationWriteMode, buildMigrationPlan, createMigrationHandlers, defineMigration, defineMigrationSet, detectMigrationDrift, injectMigrationStorageTables, migrationCapability, migrationExtension, migrationStorageTables };