@rocicorp/zero 0.7.2024120704 → 0.8.2024121001

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.
@@ -9641,6 +9641,9 @@ function defined(arr) {
9641
9641
  }
9642
9642
  return defined2;
9643
9643
  }
9644
+ function areEqual(arr1, arr2) {
9645
+ return arr1.length === arr2.length && arr1.every((e, i) => e === arr2[i]);
9646
+ }
9644
9647
 
9645
9648
  // ../zero-protocol/src/data.ts
9646
9649
  var valueSchema = valita_exports.union(jsonSchema, valita_exports.undefined());
@@ -9988,14 +9991,21 @@ var Exists = class {
9988
9991
  #relationshipName;
9989
9992
  #storage;
9990
9993
  #not;
9994
+ #parentJoinKey;
9995
+ #skipCache;
9991
9996
  #output;
9992
- constructor(input, storage, relationshipName, type) {
9997
+ constructor(input, storage, relationshipName, parentJoinKey, type) {
9993
9998
  this.#input = input;
9994
9999
  this.#relationshipName = relationshipName;
9995
10000
  this.#input.setOutput(this);
9996
10001
  this.#storage = storage;
9997
10002
  assert(this.#input.getSchema().relationships[relationshipName]);
9998
10003
  this.#not = type === "NOT EXISTS";
10004
+ this.#parentJoinKey = parentJoinKey;
10005
+ this.#skipCache = areEqual(
10006
+ parentJoinKey,
10007
+ this.#input.getSchema().primaryKey
10008
+ );
9999
10009
  }
10000
10010
  setOutput(output) {
10001
10011
  this.#output = output;
@@ -10048,6 +10058,7 @@ var Exists = class {
10048
10058
  let size = this.#getSize(change.row);
10049
10059
  if (size !== void 0) {
10050
10060
  size++;
10061
+ this.#setCachedSize(change.row, size);
10051
10062
  this.#setSize(change.row, size);
10052
10063
  } else {
10053
10064
  size = this.#fetchSize(change.row);
@@ -10071,6 +10082,7 @@ var Exists = class {
10071
10082
  if (size !== void 0) {
10072
10083
  assert(size > 0);
10073
10084
  size--;
10085
+ this.#setCachedSize(change.row, size);
10074
10086
  this.#setSize(change.row, size);
10075
10087
  } else {
10076
10088
  size = this.#fetchSize(change.row);
@@ -10122,8 +10134,26 @@ var Exists = class {
10122
10134
  #setSize(row, size) {
10123
10135
  this.#storage.set(this.#makeSizeStorageKey(row), size);
10124
10136
  }
10137
+ #setCachedSize(row, size) {
10138
+ if (this.#skipCache) {
10139
+ return;
10140
+ }
10141
+ this.#storage.set(this.#makeCacheStorageKey(row), size);
10142
+ }
10143
+ #getCachedSize(row) {
10144
+ if (this.#skipCache) {
10145
+ return void 0;
10146
+ }
10147
+ return this.#storage.get(this.#makeCacheStorageKey(row));
10148
+ }
10125
10149
  #delSize(row) {
10126
10150
  this.#storage.del(this.#makeSizeStorageKey(row));
10151
+ if (!this.#skipCache) {
10152
+ const cacheKey = this.#makeCacheStorageKey(row);
10153
+ if (first(this.#storage.scan({ prefix: `${cacheKey}/` })) === void 0) {
10154
+ this.#storage.del(cacheKey);
10155
+ }
10156
+ }
10127
10157
  }
10128
10158
  #getOrFetchSize(row) {
10129
10159
  const size = this.#getSize(row);
@@ -10133,12 +10163,18 @@ var Exists = class {
10133
10163
  return this.#fetchSize(row);
10134
10164
  }
10135
10165
  #fetchSize(row) {
10166
+ const cachedSize = this.#getCachedSize(row);
10167
+ if (cachedSize !== void 0) {
10168
+ this.#setSize(row, cachedSize);
10169
+ return cachedSize;
10170
+ }
10136
10171
  const relationship = this.#fetchNodeForRow(row).relationships[this.#relationshipName];
10137
10172
  assert(relationship);
10138
10173
  let size = 0;
10139
10174
  for (const _relatedNode of relationship) {
10140
10175
  size++;
10141
10176
  }
10177
+ this.#setCachedSize(row, size);
10142
10178
  this.#setSize(row, size);
10143
10179
  return size;
10144
10180
  }
@@ -10158,12 +10194,22 @@ var Exists = class {
10158
10194
  );
10159
10195
  return fetched;
10160
10196
  }
10197
+ #makeCacheStorageKey(row) {
10198
+ return `row/${JSON.stringify(
10199
+ this.#getKeyValues(row, this.#parentJoinKey)
10200
+ )}`;
10201
+ }
10161
10202
  #makeSizeStorageKey(row) {
10162
- const primaryKey = [];
10163
- for (const key of this.#input.getSchema().primaryKey) {
10164
- primaryKey.push(normalizeUndefined(row[key]));
10203
+ return `row/${this.#skipCache ? "" : JSON.stringify(this.#getKeyValues(row, this.#parentJoinKey))}/${JSON.stringify(
10204
+ this.#getKeyValues(row, this.#input.getSchema().primaryKey)
10205
+ )}`;
10206
+ }
10207
+ #getKeyValues(row, def) {
10208
+ const values = [];
10209
+ for (const key of def) {
10210
+ values.push(normalizeUndefined(row[key]));
10165
10211
  }
10166
- return JSON.stringify(["size", primaryKey]);
10212
+ return values;
10167
10213
  }
10168
10214
  };
10169
10215
 
@@ -11430,12 +11476,56 @@ function applyAnd(input, condition, appliedFilters, delegate) {
11430
11476
  return input;
11431
11477
  }
11432
11478
  function applyOr(input, condition, appliedFilters, delegate) {
11479
+ const [subqueryConditions, otherConditions] = groupSubqueryConditions(condition);
11480
+ if (subqueryConditions.length === 0) {
11481
+ return otherConditions.length > 0 ? new Filter(
11482
+ input,
11483
+ appliedFilters ? "push-only" : "all",
11484
+ createPredicate({
11485
+ type: "or",
11486
+ conditions: otherConditions
11487
+ })
11488
+ ) : new FanIn(new FanOut(input), []);
11489
+ }
11433
11490
  const fanOut = new FanOut(input);
11434
- const branches = condition.conditions.map(
11491
+ const branches = subqueryConditions.map(
11435
11492
  (subCondition) => applyWhere(fanOut, subCondition, appliedFilters, delegate)
11436
11493
  );
11494
+ if (otherConditions.length > 0) {
11495
+ branches.push(
11496
+ new Filter(
11497
+ fanOut,
11498
+ appliedFilters ? "push-only" : "all",
11499
+ createPredicate({
11500
+ type: "or",
11501
+ conditions: otherConditions
11502
+ })
11503
+ )
11504
+ );
11505
+ }
11437
11506
  return new FanIn(fanOut, branches);
11438
11507
  }
11508
+ function groupSubqueryConditions(condition) {
11509
+ const partitioned = [[], []];
11510
+ for (const subCondition of condition.conditions) {
11511
+ if (isNotAndDoesNotContainSubquery(subCondition)) {
11512
+ partitioned[1].push(subCondition);
11513
+ } else {
11514
+ partitioned[0].push(subCondition);
11515
+ }
11516
+ }
11517
+ return partitioned;
11518
+ }
11519
+ function isNotAndDoesNotContainSubquery(condition) {
11520
+ if (condition.type === "correlatedSubquery") {
11521
+ return false;
11522
+ }
11523
+ if (condition.type === "and") {
11524
+ return condition.conditions.every(isNotAndDoesNotContainSubquery);
11525
+ }
11526
+ assert(condition.type !== "or", "where conditions are expected to be in DNF");
11527
+ return true;
11528
+ }
11439
11529
  function applySimpleCondition(input, condition, appliedFilters) {
11440
11530
  return new Filter(
11441
11531
  input,
@@ -11468,6 +11558,7 @@ function applyCorrelatedSubqueryCondition(input, condition, delegate) {
11468
11558
  input,
11469
11559
  delegate.createStorage(),
11470
11560
  must(condition.related.subquery.alias),
11561
+ condition.related.correlation.parentField,
11471
11562
  condition.op
11472
11563
  );
11473
11564
  }
@@ -11478,7 +11569,10 @@ function gatherCorrelatedSubqueryQueriesFromCondition(condition) {
11478
11569
  assert(condition2.op === "EXISTS" || condition2.op === "NOT EXISTS");
11479
11570
  csqs.push({
11480
11571
  ...condition2.related,
11481
- subquery: { ...condition2.related.subquery, limit: EXISTS_LIMIT }
11572
+ subquery: {
11573
+ ...condition2.related.subquery,
11574
+ limit: condition2.related.system === "permissions" ? PERMISSIONS_EXISTS_LIMIT : EXISTS_LIMIT
11575
+ }
11482
11576
  });
11483
11577
  return;
11484
11578
  }
@@ -11495,6 +11589,7 @@ function gatherCorrelatedSubqueryQueriesFromCondition(condition) {
11495
11589
  return csqs;
11496
11590
  }
11497
11591
  var EXISTS_LIMIT = 3;
11592
+ var PERMISSIONS_EXISTS_LIMIT = 1;
11498
11593
  function assertOrderingIncludesPK(ordering, pk) {
11499
11594
  const orderingFields = ordering.map(([field]) => field);
11500
11595
  const missingFields = pk.filter((pkField) => !orderingFields.includes(pkField));
@@ -14373,14 +14468,7 @@ var MemorySource = class {
14373
14468
  overlay = this.#overlay;
14374
14469
  }
14375
14470
  }
14376
- const { constraint } = req;
14377
- const matchesConstraint = constraint ? (row) => constraintMatchesRow(constraint, row) : (_) => true;
14378
14471
  const startAt = req.start?.row;
14379
- if (startAt) {
14380
- if (req.constraint) {
14381
- assert(matchesConstraint(startAt), "Start row must match constraint");
14382
- }
14383
- }
14384
14472
  let scanStart;
14385
14473
  if (req.constraint) {
14386
14474
  scanStart = {};
@@ -15300,7 +15388,7 @@ function makeMessage(message, context, logLevel) {
15300
15388
  }
15301
15389
 
15302
15390
  // ../zero-client/src/client/version.ts
15303
- var version2 = "0.7.2024120704+564733";
15391
+ var version2 = "0.8.2024121001+ae95b1";
15304
15392
 
15305
15393
  // ../zero-client/src/client/log-options.ts
15306
15394
  var LevelFilterLogSink = class {
@@ -17299,4 +17387,4 @@ export {
17299
17387
  escapeLike,
17300
17388
  Zero
17301
17389
  };
17302
- //# sourceMappingURL=chunk-O2GO2VH4.js.map
17390
+ //# sourceMappingURL=chunk-AXKEBKDH.js.map