@rocicorp/zero 1.11.0-canary.8 → 1.11.0-canary.9

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 (268) hide show
  1. package/out/analyze-query/src/analyze-cli.js +2 -2
  2. package/out/analyze-query/src/analyze-cli.js.map +1 -1
  3. package/out/replicache/src/dag/gc.d.ts.map +1 -1
  4. package/out/replicache/src/dag/gc.js +2 -1
  5. package/out/replicache/src/dag/gc.js.map +1 -1
  6. package/out/replicache/src/dag/invalid-ref-count-error.d.ts +12 -0
  7. package/out/replicache/src/dag/invalid-ref-count-error.d.ts.map +1 -0
  8. package/out/replicache/src/dag/invalid-ref-count-error.js +19 -0
  9. package/out/replicache/src/dag/invalid-ref-count-error.js.map +1 -0
  10. package/out/replicache/src/dag/store-impl.d.ts +12 -2
  11. package/out/replicache/src/dag/store-impl.d.ts.map +1 -1
  12. package/out/replicache/src/dag/store-impl.js +22 -8
  13. package/out/replicache/src/dag/store-impl.js.map +1 -1
  14. package/out/replicache/src/db/rebase.d.ts +14 -2
  15. package/out/replicache/src/db/rebase.d.ts.map +1 -1
  16. package/out/replicache/src/db/rebase.js +27 -5
  17. package/out/replicache/src/db/rebase.js.map +1 -1
  18. package/out/replicache/src/persist/collect-idb-databases.d.ts +10 -5
  19. package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
  20. package/out/replicache/src/persist/collect-idb-databases.js +16 -9
  21. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  22. package/out/replicache/src/persist/persist.d.ts.map +1 -1
  23. package/out/replicache/src/persist/persist.js +12 -5
  24. package/out/replicache/src/persist/persist.js.map +1 -1
  25. package/out/replicache/src/persist/refresh.js +6 -2
  26. package/out/replicache/src/persist/refresh.js.map +1 -1
  27. package/out/replicache/src/replicache-impl.d.ts +7 -3
  28. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  29. package/out/replicache/src/replicache-impl.js +98 -11
  30. package/out/replicache/src/replicache-impl.js.map +1 -1
  31. package/out/replicache/src/replicache-options.d.ts +9 -0
  32. package/out/replicache/src/replicache-options.d.ts.map +1 -1
  33. package/out/shared/src/iterables.d.ts +2 -0
  34. package/out/shared/src/iterables.d.ts.map +1 -1
  35. package/out/shared/src/iterables.js +18 -1
  36. package/out/shared/src/iterables.js.map +1 -1
  37. package/out/shared/src/ring-buffer.d.ts +8 -0
  38. package/out/shared/src/ring-buffer.d.ts.map +1 -1
  39. package/out/shared/src/ring-buffer.js +22 -1
  40. package/out/shared/src/ring-buffer.js.map +1 -1
  41. package/out/zero/package.js +2 -3
  42. package/out/zero/package.js.map +1 -1
  43. package/out/zero-cache/src/config/zero-config.js +2 -2
  44. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  45. package/out/zero-cache/src/server/change-streamer.js +1 -1
  46. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  47. package/out/zero-cache/src/server/inspector-delegate.d.ts +18 -2
  48. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  49. package/out/zero-cache/src/server/inspector-delegate.js +20 -7
  50. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  51. package/out/zero-cache/src/services/change-source/custom/change-source.js +2 -2
  52. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  53. package/out/zero-cache/src/services/change-source/pg/backfill-resume.d.ts +156 -0
  54. package/out/zero-cache/src/services/change-source/pg/backfill-resume.d.ts.map +1 -0
  55. package/out/zero-cache/src/services/change-source/pg/backfill-resume.js +15 -0
  56. package/out/zero-cache/src/services/change-source/pg/backfill-resume.js.map +1 -0
  57. package/out/zero-cache/src/services/change-source/pg/change-source-init.d.ts +15 -0
  58. package/out/zero-cache/src/services/change-source/pg/change-source-init.d.ts.map +1 -0
  59. package/out/zero-cache/src/services/change-source/pg/change-source-init.js +99 -0
  60. package/out/zero-cache/src/services/change-source/pg/change-source-init.js.map +1 -0
  61. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +14 -16
  62. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  63. package/out/zero-cache/src/services/change-source/pg/change-source.js +33 -126
  64. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  65. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +16 -1
  66. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  67. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +8 -4
  68. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  69. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.d.ts +16 -0
  70. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.d.ts.map +1 -0
  71. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js +113 -0
  72. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js.map +1 -0
  73. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +1 -15
  74. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -1
  75. package/out/zero-cache/src/services/change-source/pg/replication-slots.js +18 -21
  76. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  77. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +3 -3
  78. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  79. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +8 -9
  80. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  81. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts +17 -1
  82. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts.map +1 -1
  83. package/out/zero-cache/src/services/change-streamer/upstream-acker.js +19 -3
  84. package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -1
  85. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts.map +1 -1
  86. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js +1 -0
  87. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js.map +1 -1
  88. package/out/zero-cache/src/services/replicator/change-processor.js +1 -0
  89. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  90. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts +14 -1
  91. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts.map +1 -1
  92. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +30 -4
  93. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
  94. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +1 -1
  95. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
  96. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +2 -2
  97. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  98. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  99. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +6 -10
  100. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  101. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  102. package/out/zero-cache/src/services/view-syncer/view-syncer.js +14 -4
  103. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  104. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  105. package/out/zero-cache/src/types/streams.js +1 -1
  106. package/out/zero-cache/src/types/streams.js.map +1 -1
  107. package/out/zero-cache/src/workers/connection.js +3 -3
  108. package/out/zero-cache/src/workers/connection.js.map +1 -1
  109. package/out/zero-cache/src/workers/syncer.js +2 -2
  110. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  111. package/out/zero-client/src/client/connection-manager.d.ts +20 -0
  112. package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
  113. package/out/zero-client/src/client/connection-manager.js +32 -14
  114. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  115. package/out/zero-client/src/client/connection-status-enum.d.ts +2 -0
  116. package/out/zero-client/src/client/connection-status-enum.d.ts.map +1 -1
  117. package/out/zero-client/src/client/connection-status-enum.js +3 -1
  118. package/out/zero-client/src/client/connection-status-enum.js.map +1 -1
  119. package/out/zero-client/src/client/connection.d.ts +6 -0
  120. package/out/zero-client/src/client/connection.d.ts.map +1 -1
  121. package/out/zero-client/src/client/connection.js +2 -1
  122. package/out/zero-client/src/client/connection.js.map +1 -1
  123. package/out/zero-client/src/client/context.d.ts +8 -11
  124. package/out/zero-client/src/client/context.d.ts.map +1 -1
  125. package/out/zero-client/src/client/context.js +11 -15
  126. package/out/zero-client/src/client/context.js.map +1 -1
  127. package/out/zero-client/src/client/custom.js +2 -2
  128. package/out/zero-client/src/client/custom.js.map +1 -1
  129. package/out/zero-client/src/client/error.js +1 -1
  130. package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
  131. package/out/zero-client/src/client/mutator-proxy.js +2 -1
  132. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  133. package/out/zero-client/src/client/options.d.ts +3 -0
  134. package/out/zero-client/src/client/options.d.ts.map +1 -1
  135. package/out/zero-client/src/client/options.js.map +1 -1
  136. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  137. package/out/zero-client/src/client/query-manager.js +42 -6
  138. package/out/zero-client/src/client/query-manager.js.map +1 -1
  139. package/out/zero-client/src/client/version.js +1 -1
  140. package/out/zero-client/src/client/zero-rep.d.ts +1 -0
  141. package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
  142. package/out/zero-client/src/client/zero-rep.js +7 -5
  143. package/out/zero-client/src/client/zero-rep.js.map +1 -1
  144. package/out/zero-client/src/client/zero.d.ts +9 -3
  145. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  146. package/out/zero-client/src/client/zero.js +48 -11
  147. package/out/zero-client/src/client/zero.js.map +1 -1
  148. package/out/zero-client/src/types/query-result.d.ts +2 -0
  149. package/out/zero-client/src/types/query-result.d.ts.map +1 -1
  150. package/out/zero-react/src/use-query.d.ts +5 -4
  151. package/out/zero-react/src/use-query.d.ts.map +1 -1
  152. package/out/zero-react/src/use-query.js +12 -1
  153. package/out/zero-react/src/use-query.js.map +1 -1
  154. package/out/zero-server/src/adapters/drizzle.d.ts +2 -1
  155. package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
  156. package/out/zero-server/src/adapters/drizzle.js +12 -7
  157. package/out/zero-server/src/adapters/drizzle.js.map +1 -1
  158. package/out/zero-server/src/adapters/kysely.d.ts +2 -1
  159. package/out/zero-server/src/adapters/kysely.d.ts.map +1 -1
  160. package/out/zero-server/src/adapters/kysely.js +8 -2
  161. package/out/zero-server/src/adapters/kysely.js.map +1 -1
  162. package/out/zero-server/src/adapters/pg.d.ts +1 -0
  163. package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
  164. package/out/zero-server/src/adapters/pg.js +8 -2
  165. package/out/zero-server/src/adapters/pg.js.map +1 -1
  166. package/out/zero-server/src/adapters/postgresjs.d.ts +1 -0
  167. package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
  168. package/out/zero-server/src/adapters/postgresjs.js +7 -1
  169. package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
  170. package/out/zero-server/src/adapters/prisma.d.ts +3 -2
  171. package/out/zero-server/src/adapters/prisma.d.ts.map +1 -1
  172. package/out/zero-server/src/adapters/prisma.js +8 -2
  173. package/out/zero-server/src/adapters/prisma.js.map +1 -1
  174. package/out/zero-server/src/custom.d.ts +5 -1
  175. package/out/zero-server/src/custom.d.ts.map +1 -1
  176. package/out/zero-server/src/custom.js +6 -3
  177. package/out/zero-server/src/custom.js.map +1 -1
  178. package/out/zero-server/src/mod.d.ts +1 -1
  179. package/out/zero-server/src/mod.d.ts.map +1 -1
  180. package/out/zero-server/src/pg-query-executor.d.ts +2 -2
  181. package/out/zero-server/src/pg-query-executor.d.ts.map +1 -1
  182. package/out/zero-server/src/pg-query-executor.js +2 -2
  183. package/out/zero-server/src/pg-query-executor.js.map +1 -1
  184. package/out/zero-server/src/schema.d.ts +2 -2
  185. package/out/zero-server/src/schema.d.ts.map +1 -1
  186. package/out/zero-server/src/schema.js +2 -2
  187. package/out/zero-server/src/schema.js.map +1 -1
  188. package/out/zero-server/src/zql-database.d.ts +21 -1
  189. package/out/zero-server/src/zql-database.d.ts.map +1 -1
  190. package/out/zero-server/src/zql-database.js +33 -2
  191. package/out/zero-server/src/zql-database.js.map +1 -1
  192. package/out/zero-solid/src/solid-view.d.ts +10 -0
  193. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  194. package/out/zero-solid/src/solid-view.js +27 -0
  195. package/out/zero-solid/src/solid-view.js.map +1 -1
  196. package/out/zql/src/ivm/array-view.d.ts +10 -0
  197. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  198. package/out/zql/src/ivm/array-view.js +20 -8
  199. package/out/zql/src/ivm/array-view.js.map +1 -1
  200. package/out/zql/src/ivm/cap.d.ts.map +1 -1
  201. package/out/zql/src/ivm/cap.js +5 -3
  202. package/out/zql/src/ivm/cap.js.map +1 -1
  203. package/out/zql/src/ivm/deferred-input.d.ts.map +1 -1
  204. package/out/zql/src/ivm/deferred-input.js +3 -2
  205. package/out/zql/src/ivm/deferred-input.js.map +1 -1
  206. package/out/zql/src/ivm/exists.d.ts +1 -1
  207. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  208. package/out/zql/src/ivm/exists.js.map +1 -1
  209. package/out/zql/src/ivm/fan-in.d.ts +2 -2
  210. package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
  211. package/out/zql/src/ivm/fan-in.js +6 -5
  212. package/out/zql/src/ivm/fan-in.js.map +1 -1
  213. package/out/zql/src/ivm/fan-out.d.ts +2 -2
  214. package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
  215. package/out/zql/src/ivm/fan-out.js.map +1 -1
  216. package/out/zql/src/ivm/filter-operators.d.ts +6 -6
  217. package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
  218. package/out/zql/src/ivm/filter-operators.js +10 -8
  219. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  220. package/out/zql/src/ivm/filter.d.ts +2 -2
  221. package/out/zql/src/ivm/filter.d.ts.map +1 -1
  222. package/out/zql/src/ivm/filter.js +7 -4
  223. package/out/zql/src/ivm/filter.js.map +1 -1
  224. package/out/zql/src/ivm/flipped-join.js +2 -2
  225. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  226. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
  227. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
  228. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +6 -4
  229. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  230. package/out/zql/src/ivm/memory-source.d.ts +2 -2
  231. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  232. package/out/zql/src/ivm/memory-source.js +9 -9
  233. package/out/zql/src/ivm/memory-source.js.map +1 -1
  234. package/out/zql/src/ivm/take.d.ts.map +1 -1
  235. package/out/zql/src/ivm/take.js +3 -4
  236. package/out/zql/src/ivm/take.js.map +1 -1
  237. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  238. package/out/zql/src/ivm/union-fan-in.js +9 -7
  239. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  240. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  241. package/out/zql/src/ivm/view-apply-change.js +3 -3
  242. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  243. package/out/zql/src/mutate/custom.d.ts +24 -1
  244. package/out/zql/src/mutate/custom.d.ts.map +1 -1
  245. package/out/zql/src/mutate/custom.js.map +1 -1
  246. package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
  247. package/out/zql/src/mutate/mutator-registry.js +2 -2
  248. package/out/zql/src/mutate/mutator-registry.js.map +1 -1
  249. package/out/zql/src/query/query-delegate-base.d.ts +2 -0
  250. package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
  251. package/out/zql/src/query/query-delegate-base.js +55 -28
  252. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  253. package/out/zql/src/query/query-delegate.d.ts +11 -1
  254. package/out/zql/src/query/query-delegate.d.ts.map +1 -1
  255. package/out/zql/src/query/query-impl.d.ts +1 -0
  256. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  257. package/out/zql/src/query/query-impl.js.map +1 -1
  258. package/out/zql/src/query/query.d.ts +7 -1
  259. package/out/zql/src/query/query.d.ts.map +1 -1
  260. package/out/zql/src/query/runnable-query-impl.d.ts +1 -0
  261. package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
  262. package/out/zql/src/query/runnable-query-impl.js.map +1 -1
  263. package/out/zql/src/query/typed-view.d.ts +1 -1
  264. package/out/zql/src/query/typed-view.d.ts.map +1 -1
  265. package/out/zqlite/src/table-source.d.ts.map +1 -1
  266. package/out/zqlite/src/table-source.js +7 -5
  267. package/out/zqlite/src/table-source.js.map +1 -1
  268. package/package.json +2 -3
@@ -1,4 +1,5 @@
1
1
  import { assert } from "../../../shared/src/asserts.js";
2
+ import { emptyIterator } from "../../../shared/src/iterables.js";
2
3
  import { emptyArray, identity } from "../../../shared/src/sentinels.js";
3
4
  import "./data.js";
4
5
  import { throwFilterOutput } from "./filter-operators.js";
@@ -46,19 +47,19 @@ var FanIn = class {
46
47
  endFilter() {
47
48
  this.#output.endFilter();
48
49
  }
49
- *filter(node) {
50
- return yield* this.#output.filter(node);
50
+ filter(node) {
51
+ return this.#output.filter(node);
51
52
  }
52
53
  push(change) {
53
54
  this.#accumulatedPushes.push(change);
54
55
  return emptyArray;
55
56
  }
56
- *fanOutDonePushingToAllBranches(fanOutChangeType) {
57
+ fanOutDonePushingToAllBranches(fanOutChangeType) {
57
58
  if (this.#inputs.length === 0) {
58
59
  assert(this.#accumulatedPushes.length === 0, "If there are no inputs then fan-in should not receive any pushes.");
59
- return;
60
+ return emptyIterator;
60
61
  }
61
- yield* pushAccumulatedChanges(this.#accumulatedPushes, this.#output, this, fanOutChangeType, identity, identity);
62
+ return pushAccumulatedChanges(this.#accumulatedPushes, this.#output, this, fanOutChangeType, identity, identity);
62
63
  }
63
64
  };
64
65
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"fan-in.js","names":["#inputs","#schema","#output","#accumulatedPushes"],"sources":["../../../../../zql/src/ivm/fan-in.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport {emptyArray, identity} from '../../../shared/src/sentinels.ts';\nimport type {ChangeType} from './change-type.ts';\nimport {type Change} from './change.ts';\nimport {type Node} from './data.ts';\nimport type {FanOut} from './fan-out.ts';\nimport {\n throwFilterOutput,\n type FilterInput,\n type FilterOperator,\n type FilterOutput,\n} from './filter-operators.ts';\nimport {pushAccumulatedChanges} from './push-accumulated.ts';\nimport type {SourceSchema} from './schema.ts';\n\n/**\n * The FanIn operator merges multiple streams into one.\n * It eliminates duplicates and must be paired with a fan-out operator\n * somewhere upstream of the fan-in.\n *\n * issue\n * |\n * fan-out\n * / \\\n * a b\n * \\ /\n * fan-in\n * |\n */\nexport class FanIn implements FilterOperator {\n readonly #inputs: readonly FilterInput[];\n readonly #schema: SourceSchema;\n #output: FilterOutput = throwFilterOutput;\n #accumulatedPushes: Change[] = [];\n\n constructor(fanOut: FanOut, inputs: FilterInput[]) {\n this.#inputs = inputs;\n this.#schema = fanOut.getSchema();\n for (const input of inputs) {\n input.setFilterOutput(this);\n assert(this.#schema === input.getSchema(), `Schema mismatch in fan-in`);\n }\n }\n\n setFilterOutput(output: FilterOutput): void {\n this.#output = output;\n }\n\n destroy(): void {\n for (const input of this.#inputs) {\n input.destroy();\n }\n }\n\n getSchema() {\n return this.#schema;\n }\n\n beginFilter(): void {\n this.#output.beginFilter();\n }\n\n endFilter(): void {\n this.#output.endFilter();\n }\n\n *filter(node: Node): Generator<'yield', boolean> {\n return yield* this.#output.filter(node);\n }\n\n push(change: Change) {\n this.#accumulatedPushes.push(change);\n return emptyArray;\n }\n\n *fanOutDonePushingToAllBranches(fanOutChangeType: ChangeType) {\n if (this.#inputs.length === 0) {\n assert(\n this.#accumulatedPushes.length === 0,\n 'If there are no inputs then fan-in should not receive any pushes.',\n );\n return;\n }\n\n yield* pushAccumulatedChanges(\n this.#accumulatedPushes,\n this.#output,\n this,\n fanOutChangeType,\n identity,\n identity,\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA6BA,IAAa,QAAb,MAA6C;CAC3C;CACA;CACA,UAAwB;CACxB,qBAA+B,CAAC;CAEhC,YAAY,QAAgB,QAAuB;EACjD,KAAKA,UAAU;EACf,KAAKC,UAAU,OAAO,UAAU;EAChC,KAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,gBAAgB,IAAI;GAC1B,OAAO,KAAKA,YAAY,MAAM,UAAU,GAAG,2BAA2B;EACxE;CACF;CAEA,gBAAgB,QAA4B;EAC1C,KAAKC,UAAU;CACjB;CAEA,UAAgB;EACd,KAAK,MAAM,SAAS,KAAKF,SACvB,MAAM,QAAQ;CAElB;CAEA,YAAY;EACV,OAAO,KAAKC;CACd;CAEA,cAAoB;EAClB,KAAKC,QAAQ,YAAY;CAC3B;CAEA,YAAkB;EAChB,KAAKA,QAAQ,UAAU;CACzB;CAEA,CAAC,OAAO,MAAyC;EAC/C,OAAO,OAAO,KAAKA,QAAQ,OAAO,IAAI;CACxC;CAEA,KAAK,QAAgB;EACnB,KAAKC,mBAAmB,KAAK,MAAM;EACnC,OAAO;CACT;CAEA,CAAC,+BAA+B,kBAA8B;EAC5D,IAAI,KAAKH,QAAQ,WAAW,GAAG;GAC7B,OACE,KAAKG,mBAAmB,WAAW,GACnC,mEACF;GACA;EACF;EAEA,OAAO,uBACL,KAAKA,oBACL,KAAKD,SACL,MACA,kBACA,UACA,QACF;CACF;AACF"}
1
+ {"version":3,"file":"fan-in.js","names":["#inputs","#schema","#output","#accumulatedPushes"],"sources":["../../../../../zql/src/ivm/fan-in.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport {emptyIterator} from '../../../shared/src/iterables.ts';\nimport {emptyArray, identity} from '../../../shared/src/sentinels.ts';\nimport type {ChangeType} from './change-type.ts';\nimport {type Change} from './change.ts';\nimport {type Node} from './data.ts';\nimport type {FanOut} from './fan-out.ts';\nimport {\n throwFilterOutput,\n type FilterInput,\n type FilterOperator,\n type FilterOutput,\n} from './filter-operators.ts';\nimport {pushAccumulatedChanges} from './push-accumulated.ts';\nimport type {SourceSchema} from './schema.ts';\n\n/**\n * The FanIn operator merges multiple streams into one.\n * It eliminates duplicates and must be paired with a fan-out operator\n * somewhere upstream of the fan-in.\n *\n * issue\n * |\n * fan-out\n * / \\\n * a b\n * \\ /\n * fan-in\n * |\n */\nexport class FanIn implements FilterOperator {\n readonly #inputs: readonly FilterInput[];\n readonly #schema: SourceSchema;\n #output: FilterOutput = throwFilterOutput;\n #accumulatedPushes: Change[] = [];\n\n constructor(fanOut: FanOut, inputs: FilterInput[]) {\n this.#inputs = inputs;\n this.#schema = fanOut.getSchema();\n for (const input of inputs) {\n input.setFilterOutput(this);\n assert(this.#schema === input.getSchema(), `Schema mismatch in fan-in`);\n }\n }\n\n setFilterOutput(output: FilterOutput): void {\n this.#output = output;\n }\n\n destroy(): void {\n for (const input of this.#inputs) {\n input.destroy();\n }\n }\n\n getSchema() {\n return this.#schema;\n }\n\n beginFilter(): void {\n this.#output.beginFilter();\n }\n\n endFilter(): void {\n this.#output.endFilter();\n }\n\n filter(node: Node): IterableIterator<'yield', boolean> {\n return this.#output.filter(node);\n }\n\n push(change: Change) {\n this.#accumulatedPushes.push(change);\n return emptyArray;\n }\n\n fanOutDonePushingToAllBranches(fanOutChangeType: ChangeType) {\n if (this.#inputs.length === 0) {\n assert(\n this.#accumulatedPushes.length === 0,\n 'If there are no inputs then fan-in should not receive any pushes.',\n );\n return emptyIterator;\n }\n\n return pushAccumulatedChanges(\n this.#accumulatedPushes,\n this.#output,\n this,\n fanOutChangeType,\n identity,\n identity,\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA8BA,IAAa,QAAb,MAA6C;CAC3C;CACA;CACA,UAAwB;CACxB,qBAA+B,CAAC;CAEhC,YAAY,QAAgB,QAAuB;EACjD,KAAKA,UAAU;EACf,KAAKC,UAAU,OAAO,UAAU;EAChC,KAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,gBAAgB,IAAI;GAC1B,OAAO,KAAKA,YAAY,MAAM,UAAU,GAAG,2BAA2B;EACxE;CACF;CAEA,gBAAgB,QAA4B;EAC1C,KAAKC,UAAU;CACjB;CAEA,UAAgB;EACd,KAAK,MAAM,SAAS,KAAKF,SACvB,MAAM,QAAQ;CAElB;CAEA,YAAY;EACV,OAAO,KAAKC;CACd;CAEA,cAAoB;EAClB,KAAKC,QAAQ,YAAY;CAC3B;CAEA,YAAkB;EAChB,KAAKA,QAAQ,UAAU;CACzB;CAEA,OAAO,MAAgD;EACrD,OAAO,KAAKA,QAAQ,OAAO,IAAI;CACjC;CAEA,KAAK,QAAgB;EACnB,KAAKC,mBAAmB,KAAK,MAAM;EACnC,OAAO;CACT;CAEA,+BAA+B,kBAA8B;EAC3D,IAAI,KAAKH,QAAQ,WAAW,GAAG;GAC7B,OACE,KAAKG,mBAAmB,WAAW,GACnC,mEACF;GACA,OAAO;EACT;EAEA,OAAO,uBACL,KAAKA,oBACL,KAAKD,SACL,MACA,kBACA,UACA,QACF;CACF;AACF"}
@@ -16,7 +16,7 @@ export declare class FanOut implements FilterOperator {
16
16
  getSchema(): import("./schema.ts").SourceSchema;
17
17
  beginFilter(): void;
18
18
  endFilter(): void;
19
- filter(node: Node): Generator<'yield', boolean>;
20
- push(change: Change): Generator<"yield", void, any>;
19
+ filter(node: Node): IterableIterator<'yield', boolean>;
20
+ push(change: Change): Generator<any, void, any>;
21
21
  }
22
22
  //# sourceMappingURL=fan-out.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fan-out.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/fan-out.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,YAAY,EACb,MAAM,uBAAuB,CAAC;AAE/B;;;;GAIG;AACH,qBAAa,MAAO,YAAW,cAAc;;IAM3C,YAAY,KAAK,EAAE,WAAW,EAG7B;IAED,QAAQ,CAAC,KAAK,EAAE,KAAK,QAEpB;IAED,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAE1C;IAED,OAAO,IAAI,IAAI,CASd;IAED,SAAS,uCAER;IAED,WAAW,IAAI,IAAI,CAIlB;IAED,SAAS,IAAI,IAAI,CAIhB;IAEA,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAS/C;IAEA,IAAI,CAAC,MAAM,EAAE,MAAM,iCAQnB;CACF"}
1
+ {"version":3,"file":"fan-out.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/fan-out.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,YAAY,EACb,MAAM,uBAAuB,CAAC;AAE/B;;;;GAIG;AACH,qBAAa,MAAO,YAAW,cAAc;;IAM3C,YAAY,KAAK,EAAE,WAAW,EAG7B;IAED,QAAQ,CAAC,KAAK,EAAE,KAAK,QAEpB;IAED,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAE1C;IAED,OAAO,IAAI,IAAI,CASd;IAED,SAAS,uCAER;IAED,WAAW,IAAI,IAAI,CAIlB;IAED,SAAS,IAAI,IAAI,CAIhB;IAEA,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAStD;IAEA,IAAI,CAAC,MAAM,EAAE,MAAM,6BAQnB;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"fan-out.js","names":["#input","#outputs","#fanIn","#destroyCount"],"sources":["../../../../../zql/src/ivm/fan-out.ts"],"sourcesContent":["import {must} from '../../../shared/src/must.ts';\nimport {ChangeIndex} from './change-index.ts';\nimport type {Change} from './change.ts';\nimport type {Node} from './data.ts';\nimport type {FanIn} from './fan-in.ts';\nimport type {\n FilterInput,\n FilterOperator,\n FilterOutput,\n} from './filter-operators.ts';\n\n/**\n * Forks a stream into multiple streams.\n * Is meant to be paired with a `FanIn` operator which will\n * later merge the forks back together.\n */\nexport class FanOut implements FilterOperator {\n readonly #input: FilterInput;\n readonly #outputs: FilterOutput[] = [];\n #fanIn: FanIn | undefined;\n #destroyCount: number = 0;\n\n constructor(input: FilterInput) {\n this.#input = input;\n input.setFilterOutput(this);\n }\n\n setFanIn(fanIn: FanIn) {\n this.#fanIn = fanIn;\n }\n\n setFilterOutput(output: FilterOutput): void {\n this.#outputs.push(output);\n }\n\n destroy(): void {\n if (this.#destroyCount < this.#outputs.length) {\n ++this.#destroyCount;\n if (this.#destroyCount === this.#outputs.length) {\n this.#input.destroy();\n }\n } else {\n throw new Error('FanOut already destroyed once for each output');\n }\n }\n\n getSchema() {\n return this.#input.getSchema();\n }\n\n beginFilter(): void {\n for (const output of this.#outputs) {\n output.beginFilter();\n }\n }\n\n endFilter(): void {\n for (const output of this.#outputs) {\n output.endFilter();\n }\n }\n\n *filter(node: Node): Generator<'yield', boolean> {\n let result = false;\n for (const output of this.#outputs) {\n result = (yield* output.filter(node)) || result;\n if (result) {\n return true;\n }\n }\n return result;\n }\n\n *push(change: Change) {\n for (const out of this.#outputs) {\n yield* out.push(change, this);\n }\n yield* must(\n this.#fanIn,\n 'fan-out must have a corresponding fan-in set!',\n ).fanOutDonePushingToAllBranches(change[ChangeIndex.TYPE]);\n }\n}\n"],"mappings":";;;;;;;AAgBA,IAAa,SAAb,MAA8C;CAC5C;CACA,WAAoC,CAAC;CACrC;CACA,gBAAwB;CAExB,YAAY,OAAoB;EAC9B,KAAKA,SAAS;EACd,MAAM,gBAAgB,IAAI;CAC5B;CAEA,SAAS,OAAc;EACrB,KAAKE,SAAS;CAChB;CAEA,gBAAgB,QAA4B;EAC1C,KAAKD,SAAS,KAAK,MAAM;CAC3B;CAEA,UAAgB;EACd,IAAI,KAAKE,gBAAgB,KAAKF,SAAS,QAAQ;GAC7C,EAAE,KAAKE;GACP,IAAI,KAAKA,kBAAkB,KAAKF,SAAS,QACvC,KAAKD,OAAO,QAAQ;EAExB,OACE,MAAM,IAAI,MAAM,+CAA+C;CAEnE;CAEA,YAAY;EACV,OAAO,KAAKA,OAAO,UAAU;CAC/B;CAEA,cAAoB;EAClB,KAAK,MAAM,UAAU,KAAKC,UACxB,OAAO,YAAY;CAEvB;CAEA,YAAkB;EAChB,KAAK,MAAM,UAAU,KAAKA,UACxB,OAAO,UAAU;CAErB;CAEA,CAAC,OAAO,MAAyC;EAC/C,IAAI,SAAS;EACb,KAAK,MAAM,UAAU,KAAKA,UAAU;GAClC,UAAU,OAAO,OAAO,OAAO,IAAI,MAAM;GACzC,IAAI,QACF,OAAO;EAEX;EACA,OAAO;CACT;CAEA,CAAC,KAAK,QAAgB;EACpB,KAAK,MAAM,OAAO,KAAKA,UACrB,OAAO,IAAI,KAAK,QAAQ,IAAI;EAE9B,OAAO,KACL,KAAKC,QACL,+CACF,EAAE,+BAA+B,OAAO,EAAiB;CAC3D;AACF"}
1
+ {"version":3,"file":"fan-out.js","names":["#input","#outputs","#fanIn","#destroyCount"],"sources":["../../../../../zql/src/ivm/fan-out.ts"],"sourcesContent":["import {must} from '../../../shared/src/must.ts';\nimport {ChangeIndex} from './change-index.ts';\nimport type {Change} from './change.ts';\nimport type {Node} from './data.ts';\nimport type {FanIn} from './fan-in.ts';\nimport type {\n FilterInput,\n FilterOperator,\n FilterOutput,\n} from './filter-operators.ts';\n\n/**\n * Forks a stream into multiple streams.\n * Is meant to be paired with a `FanIn` operator which will\n * later merge the forks back together.\n */\nexport class FanOut implements FilterOperator {\n readonly #input: FilterInput;\n readonly #outputs: FilterOutput[] = [];\n #fanIn: FanIn | undefined;\n #destroyCount: number = 0;\n\n constructor(input: FilterInput) {\n this.#input = input;\n input.setFilterOutput(this);\n }\n\n setFanIn(fanIn: FanIn) {\n this.#fanIn = fanIn;\n }\n\n setFilterOutput(output: FilterOutput): void {\n this.#outputs.push(output);\n }\n\n destroy(): void {\n if (this.#destroyCount < this.#outputs.length) {\n ++this.#destroyCount;\n if (this.#destroyCount === this.#outputs.length) {\n this.#input.destroy();\n }\n } else {\n throw new Error('FanOut already destroyed once for each output');\n }\n }\n\n getSchema() {\n return this.#input.getSchema();\n }\n\n beginFilter(): void {\n for (const output of this.#outputs) {\n output.beginFilter();\n }\n }\n\n endFilter(): void {\n for (const output of this.#outputs) {\n output.endFilter();\n }\n }\n\n *filter(node: Node): IterableIterator<'yield', boolean> {\n let result = false;\n for (const output of this.#outputs) {\n result = (yield* output.filter(node)) || result;\n if (result) {\n return true;\n }\n }\n return result;\n }\n\n *push(change: Change) {\n for (const out of this.#outputs) {\n yield* out.push(change, this);\n }\n yield* must(\n this.#fanIn,\n 'fan-out must have a corresponding fan-in set!',\n ).fanOutDonePushingToAllBranches(change[ChangeIndex.TYPE]);\n }\n}\n"],"mappings":";;;;;;;AAgBA,IAAa,SAAb,MAA8C;CAC5C;CACA,WAAoC,CAAC;CACrC;CACA,gBAAwB;CAExB,YAAY,OAAoB;EAC9B,KAAKA,SAAS;EACd,MAAM,gBAAgB,IAAI;CAC5B;CAEA,SAAS,OAAc;EACrB,KAAKE,SAAS;CAChB;CAEA,gBAAgB,QAA4B;EAC1C,KAAKD,SAAS,KAAK,MAAM;CAC3B;CAEA,UAAgB;EACd,IAAI,KAAKE,gBAAgB,KAAKF,SAAS,QAAQ;GAC7C,EAAE,KAAKE;GACP,IAAI,KAAKA,kBAAkB,KAAKF,SAAS,QACvC,KAAKD,OAAO,QAAQ;EAExB,OACE,MAAM,IAAI,MAAM,+CAA+C;CAEnE;CAEA,YAAY;EACV,OAAO,KAAKA,OAAO,UAAU;CAC/B;CAEA,cAAoB;EAClB,KAAK,MAAM,UAAU,KAAKC,UACxB,OAAO,YAAY;CAEvB;CAEA,YAAkB;EAChB,KAAK,MAAM,UAAU,KAAKA,UACxB,OAAO,UAAU;CAErB;CAEA,CAAC,OAAO,MAAgD;EACtD,IAAI,SAAS;EACb,KAAK,MAAM,UAAU,KAAKA,UAAU;GAClC,UAAU,OAAO,OAAO,OAAO,IAAI,MAAM;GACzC,IAAI,QACF,OAAO;EAEX;EACA,OAAO;CACT;CAEA,CAAC,KAAK,QAAgB;EACpB,KAAK,MAAM,OAAO,KAAKA,UACrB,OAAO,IAAI,KAAK,QAAQ,IAAI;EAE9B,OAAO,KACL,KAAKC,QACL,+CACF,EAAE,+BAA+B,OAAO,EAAiB;CAC3D;AACF"}
@@ -29,7 +29,7 @@ export interface FilterInput extends InputBase {
29
29
  }
30
30
  export interface FilterOutput extends Output {
31
31
  beginFilter(): void;
32
- filter(node: Node): Generator<'yield', boolean>;
32
+ filter(node: Node): IterableIterator<'yield', boolean>;
33
33
  endFilter(): void;
34
34
  }
35
35
  export interface FilterOperator extends FilterInput, FilterOutput {
@@ -42,11 +42,11 @@ export interface FilterOperator extends FilterInput, FilterOutput {
42
42
  export declare const throwFilterOutput: FilterOutput;
43
43
  export declare class FilterStart implements FilterInput, Output {
44
44
  #private;
45
- constructor(input: Input, condition?: NoSubqueryCondition | undefined);
45
+ constructor(input: Input, condition?: NoSubqueryCondition);
46
46
  setFilterOutput(output: FilterOutput): void;
47
47
  destroy(): void;
48
48
  getSchema(): SourceSchema;
49
- push(change: Change): Generator<"yield", void, any>;
49
+ push(change: Change): Stream<"yield">;
50
50
  fetch(req: FetchRequest): Stream<Node | 'yield'>;
51
51
  }
52
52
  export declare class FilterEnd implements Input, FilterOutput {
@@ -55,11 +55,11 @@ export declare class FilterEnd implements Input, FilterOutput {
55
55
  fetch(req: FetchRequest): Stream<Node | 'yield'>;
56
56
  beginFilter(): void;
57
57
  endFilter(): void;
58
- filter(_node: Node): Generator<never, boolean, unknown>;
58
+ filter(_node: Node): IterableIterator<any, boolean>;
59
59
  setOutput(output: Output): void;
60
60
  destroy(): void;
61
61
  getSchema(): SourceSchema;
62
- push(change: Change): Generator<"yield", void, any>;
62
+ push(change: Change): Stream<"yield">;
63
63
  }
64
- export declare function buildFilterPipeline(input: Input, delegate: BuilderDelegate, pipeline: (filterInput: FilterInput) => FilterInput, condition?: NoSubqueryCondition | undefined): Input;
64
+ export declare function buildFilterPipeline(input: Input, delegate: BuilderDelegate, pipeline: (filterInput: FilterInput) => FilterInput, condition?: NoSubqueryCondition): Input;
65
65
  //# sourceMappingURL=filter-operators.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"filter-operators.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/filter-operators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EAAC,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAC,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;AAC1E,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,+CAA+C;IAC/C,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,YAAa,SAAQ,MAAM;IAI1C,WAAW,IAAI,IAAI,CAAC;IACpB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,SAAS,IAAI,IAAI,CAAC;CACnB;AAED,MAAM,WAAW,cAAe,SAAQ,WAAW,EAAE,YAAY;CAAG;AAEpE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,YAW/B,CAAC;AAEF,qBAAa,WAAY,YAAW,WAAW,EAAE,MAAM;;IAKrD,YAAY,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,mBAAmB,GAAG,SAAS,EAIpE;IAED,eAAe,CAAC,MAAM,EAAE,YAAY,QAEnC;IAED,OAAO,IAAI,IAAI,CAEd;IAED,SAAS,IAAI,YAAY,CAExB;IAEA,IAAI,CAAC,MAAM,EAAE,MAAM,iCAEnB;IAEA,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,CAoBhD;CACF;AAeD,qBAAa,SAAU,YAAW,KAAK,EAAE,YAAY;;IAMnD,YAAY,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAIjD;IAEA,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,CAIhD;IAED,WAAW,SAAK;IAChB,SAAS,SAAK;IAEb,MAAM,CAAC,KAAK,EAAE,IAAI,sCAElB;IAED,SAAS,CAAC,MAAM,EAAE,MAAM,QAEvB;IAED,OAAO,IAAI,IAAI,CAEd;IAED,SAAS,IAAI,YAAY,CAExB;IAEA,IAAI,CAAC,MAAM,EAAE,MAAM,iCAEnB;CACF;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,eAAe,EACzB,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,WAAW,EACnD,SAAS,CAAC,EAAE,mBAAmB,GAAG,SAAS,GAC1C,KAAK,CAQP"}
1
+ {"version":3,"file":"filter-operators.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/filter-operators.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EAAC,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAC,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;AAC1E,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,+CAA+C;IAC/C,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,YAAa,SAAQ,MAAM;IAI1C,WAAW,IAAI,IAAI,CAAC;IACpB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACvD,SAAS,IAAI,IAAI,CAAC;CACnB;AAED,MAAM,WAAW,cAAe,SAAQ,WAAW,EAAE,YAAY;CAAG;AAEpE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,YAa/B,CAAC;AAEF,qBAAa,WAAY,YAAW,WAAW,EAAE,MAAM;;IAKrD,YAAY,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,mBAAmB,EAIxD;IAED,eAAe,CAAC,MAAM,EAAE,YAAY,QAEnC;IAED,OAAO,IAAI,IAAI,CAEd;IAED,SAAS,IAAI,YAAY,CAExB;IAED,IAAI,CAAC,MAAM,EAAE,MAAM,mBAElB;IAEA,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,CAoBhD;CACF;AAeD,qBAAa,SAAU,YAAW,KAAK,EAAE,YAAY;;IAMnD,YAAY,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAIjD;IAED,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,CAE/C;IAED,WAAW,SAAK;IAChB,SAAS,SAAK;IAEd,MAAM,CAAC,KAAK,EAAE,IAAI,kCAEjB;IAED,SAAS,CAAC,MAAM,EAAE,MAAM,QAEvB;IAED,OAAO,IAAI,IAAI,CAEd;IAED,SAAS,IAAI,YAAY,CAExB;IAED,IAAI,CAAC,MAAM,EAAE,MAAM,mBAElB;CACF;AAID,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,eAAe,EACzB,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,WAAW,EACnD,SAAS,CAAC,EAAE,mBAAmB,GAC9B,KAAK,CAQP"}
@@ -1,3 +1,4 @@
1
+ import { makeEmptyIteratorWithReturn } from "../../../shared/src/iterables.js";
1
2
  import "./data.js";
2
3
  //#region ../zql/src/ivm/filter-operators.ts
3
4
  /**
@@ -33,8 +34,8 @@ var FilterStart = class {
33
34
  getSchema() {
34
35
  return this.#input.getSchema();
35
36
  }
36
- *push(change) {
37
- yield* this.#output.push(change, this);
37
+ push(change) {
38
+ return this.#output.push(change, this);
38
39
  }
39
40
  *fetch(req) {
40
41
  const mergedFilter = mergeFilters(req.filter, this.#condition);
@@ -73,13 +74,13 @@ var FilterEnd = class {
73
74
  this.#input = input;
74
75
  input.setFilterOutput(this);
75
76
  }
76
- *fetch(req) {
77
- for (const node of this.#start.fetch(req)) yield node;
77
+ fetch(req) {
78
+ return this.#start.fetch(req);
78
79
  }
79
80
  beginFilter() {}
80
81
  endFilter() {}
81
- *filter(_node) {
82
- return true;
82
+ filter(_node) {
83
+ return returnTrueEmptyIterator;
83
84
  }
84
85
  setOutput(output) {
85
86
  this.#output = output;
@@ -90,10 +91,11 @@ var FilterEnd = class {
90
91
  getSchema() {
91
92
  return this.#input.getSchema();
92
93
  }
93
- *push(change) {
94
- yield* this.#output.push(change, this);
94
+ push(change) {
95
+ return this.#output.push(change, this);
95
96
  }
96
97
  };
98
+ var returnTrueEmptyIterator = makeEmptyIteratorWithReturn(true);
97
99
  function buildFilterPipeline(input, delegate, pipeline, condition) {
98
100
  const filterStart = new FilterStart(input, condition);
99
101
  delegate.addEdge(input, filterStart);
@@ -1 +1 @@
1
- {"version":3,"file":"filter-operators.js","names":["#input","#condition","#output","#start"],"sources":["../../../../../zql/src/ivm/filter-operators.ts"],"sourcesContent":["import type {BuilderDelegate} from '../builder/builder.ts';\nimport type {NoSubqueryCondition} from '../builder/filter.ts';\nimport type {Change} from './change.ts';\nimport {type Node} from './data.ts';\nimport type {FetchRequest, Input, InputBase, Output} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {type Stream} from './stream.ts';\n\n/**\n * The `where` clause of a ZQL query is implemented using a sub-graph of\n * `FilterOperators`. This sub-graph starts with a `FilterStart` operator,\n * that adapts from the normal `Operator` `Output`, to the\n * `FilterOperator` `FilterInput`, and ends with a `FilterEnd` operator that\n * adapts from a `FilterOperator` `FilterOutput` to a normal `Operator` `Input`.\n * `FilterOperator`'s do not have `fetch` instead they have a\n * `filter(node: Node): boolean` method.\n * They also have `push` which is just like normal `Operator` push.\n * Not having a `fetch` means these `FilterOperator`'s cannot modify\n * `Node` `row`s or `relationship`s, but they shouldn't, they should just\n * filter.\n *\n * This `FilterOperator` abstraction enables much more efficient processing of\n * `fetch` for `where` clauses containing OR conditions.\n *\n * See https://github.com/rocicorp/mono/pull/4339\n */\n\nexport interface FilterInput extends InputBase {\n /** Tell the input where to send its output. */\n setFilterOutput(output: FilterOutput): void;\n}\n\nexport interface FilterOutput extends Output {\n // Lets the operator know that we're in a loop of filtering\n // nodes. E.g., so the operator can cache results for the\n // duration of the loop.\n beginFilter(): void;\n filter(node: Node): Generator<'yield', boolean>;\n endFilter(): void;\n}\n\nexport interface FilterOperator extends FilterInput, FilterOutput {}\n\n/**\n * An implementation of FilterOutput that throws if push or filter is called.\n * It is used as the initial value for for an operator's output before it is\n * set.\n */\nexport const throwFilterOutput: FilterOutput = {\n *push(_change: Change): Stream<'yield'> {\n throw new Error('Output not set');\n },\n\n *filter(_node: Node): Generator<'yield', boolean> {\n throw new Error('Output not set');\n },\n\n beginFilter() {},\n endFilter() {},\n};\n\nexport class FilterStart implements FilterInput, Output {\n readonly #input: Input;\n readonly #condition: NoSubqueryCondition | undefined;\n #output: FilterOutput = throwFilterOutput;\n\n constructor(input: Input, condition?: NoSubqueryCondition | undefined) {\n this.#input = input;\n this.#condition = condition;\n input.setOutput(this);\n }\n\n setFilterOutput(output: FilterOutput) {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *push(change: Change) {\n yield* this.#output.push(change, this);\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n const mergedFilter = mergeFilters(req.filter, this.#condition);\n const childReq =\n mergedFilter === req.filter ? req : {...req, filter: mergedFilter};\n this.#output.beginFilter();\n try {\n for (const node of this.#input.fetch(childReq)) {\n if (node === 'yield') {\n yield node;\n continue;\n }\n if (yield* this.#output.filter(node)) {\n yield node;\n }\n }\n } finally {\n // finally is important if an exception is thrown or\n // if the stream is not fully consumed.\n this.#output.endFilter();\n }\n }\n}\n\nfunction mergeFilters(\n reqFilter: NoSubqueryCondition | undefined,\n ownCondition: NoSubqueryCondition | undefined,\n): NoSubqueryCondition | undefined {\n if (!ownCondition) {\n return reqFilter;\n }\n if (!reqFilter) {\n return ownCondition;\n }\n return {type: 'and', conditions: [reqFilter, ownCondition]};\n}\n\nexport class FilterEnd implements Input, FilterOutput {\n readonly #start: FilterStart;\n readonly #input: FilterInput;\n\n #output: Output = throwFilterOutput;\n\n constructor(start: FilterStart, input: FilterInput) {\n this.#start = start;\n this.#input = input;\n input.setFilterOutput(this);\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n for (const node of this.#start.fetch(req)) {\n yield node;\n }\n }\n\n beginFilter() {}\n endFilter() {}\n\n *filter(_node: Node) {\n return true;\n }\n\n setOutput(output: Output) {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *push(change: Change) {\n yield* this.#output.push(change, this);\n }\n}\n\nexport function buildFilterPipeline(\n input: Input,\n delegate: BuilderDelegate,\n pipeline: (filterInput: FilterInput) => FilterInput,\n condition?: NoSubqueryCondition | undefined,\n): Input {\n const filterStart = new FilterStart(input, condition);\n delegate.addEdge(input, filterStart);\n const middle = pipeline(filterStart);\n delegate.addEdge(filterStart, middle);\n const filterEnd = new FilterEnd(filterStart, middle);\n delegate.addEdge(middle, filterEnd);\n return filterEnd;\n}\n"],"mappings":";;;;;;;AAgDA,IAAa,oBAAkC;CAC7C,CAAC,KAAK,SAAkC;EACtC,MAAM,IAAI,MAAM,gBAAgB;CAClC;CAEA,CAAC,OAAO,OAA0C;EAChD,MAAM,IAAI,MAAM,gBAAgB;CAClC;CAEA,cAAc,CAAC;CACf,YAAY,CAAC;AACf;AAEA,IAAa,cAAb,MAAwD;CACtD;CACA;CACA,UAAwB;CAExB,YAAY,OAAc,WAA6C;EACrE,KAAKA,SAAS;EACd,KAAKC,aAAa;EAClB,MAAM,UAAU,IAAI;CACtB;CAEA,gBAAgB,QAAsB;EACpC,KAAKC,UAAU;CACjB;CAEA,UAAgB;EACd,KAAKF,OAAO,QAAQ;CACtB;CAEA,YAA0B;EACxB,OAAO,KAAKA,OAAO,UAAU;CAC/B;CAEA,CAAC,KAAK,QAAgB;EACpB,OAAO,KAAKE,QAAQ,KAAK,QAAQ,IAAI;CACvC;CAEA,CAAC,MAAM,KAA2C;EAChD,MAAM,eAAe,aAAa,IAAI,QAAQ,KAAKD,UAAU;EAC7D,MAAM,WACJ,iBAAiB,IAAI,SAAS,MAAM;GAAC,GAAG;GAAK,QAAQ;EAAY;EACnE,KAAKC,QAAQ,YAAY;EACzB,IAAI;GACF,KAAK,MAAM,QAAQ,KAAKF,OAAO,MAAM,QAAQ,GAAG;IAC9C,IAAI,SAAS,SAAS;KACpB,MAAM;KACN;IACF;IACA,IAAI,OAAO,KAAKE,QAAQ,OAAO,IAAI,GACjC,MAAM;GAEV;EACF,UAAU;GAGR,KAAKA,QAAQ,UAAU;EACzB;CACF;AACF;AAEA,SAAS,aACP,WACA,cACiC;CACjC,IAAI,CAAC,cACH,OAAO;CAET,IAAI,CAAC,WACH,OAAO;CAET,OAAO;EAAC,MAAM;EAAO,YAAY,CAAC,WAAW,YAAY;CAAC;AAC5D;AAEA,IAAa,YAAb,MAAsD;CACpD;CACA;CAEA,UAAkB;CAElB,YAAY,OAAoB,OAAoB;EAClD,KAAKC,SAAS;EACd,KAAKH,SAAS;EACd,MAAM,gBAAgB,IAAI;CAC5B;CAEA,CAAC,MAAM,KAA2C;EAChD,KAAK,MAAM,QAAQ,KAAKG,OAAO,MAAM,GAAG,GACtC,MAAM;CAEV;CAEA,cAAc,CAAC;CACf,YAAY,CAAC;CAEb,CAAC,OAAO,OAAa;EACnB,OAAO;CACT;CAEA,UAAU,QAAgB;EACxB,KAAKD,UAAU;CACjB;CAEA,UAAgB;EACd,KAAKF,OAAO,QAAQ;CACtB;CAEA,YAA0B;EACxB,OAAO,KAAKA,OAAO,UAAU;CAC/B;CAEA,CAAC,KAAK,QAAgB;EACpB,OAAO,KAAKE,QAAQ,KAAK,QAAQ,IAAI;CACvC;AACF;AAEA,SAAgB,oBACd,OACA,UACA,UACA,WACO;CACP,MAAM,cAAc,IAAI,YAAY,OAAO,SAAS;CACpD,SAAS,QAAQ,OAAO,WAAW;CACnC,MAAM,SAAS,SAAS,WAAW;CACnC,SAAS,QAAQ,aAAa,MAAM;CACpC,MAAM,YAAY,IAAI,UAAU,aAAa,MAAM;CACnD,SAAS,QAAQ,QAAQ,SAAS;CAClC,OAAO;AACT"}
1
+ {"version":3,"file":"filter-operators.js","names":["#input","#condition","#output","#start"],"sources":["../../../../../zql/src/ivm/filter-operators.ts"],"sourcesContent":["import {makeEmptyIteratorWithReturn} from '../../../shared/src/iterables.ts';\nimport type {BuilderDelegate} from '../builder/builder.ts';\nimport type {NoSubqueryCondition} from '../builder/filter.ts';\nimport type {Change} from './change.ts';\nimport {type Node} from './data.ts';\nimport type {FetchRequest, Input, InputBase, Output} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {type Stream} from './stream.ts';\n\n/**\n * The `where` clause of a ZQL query is implemented using a sub-graph of\n * `FilterOperators`. This sub-graph starts with a `FilterStart` operator,\n * that adapts from the normal `Operator` `Output`, to the\n * `FilterOperator` `FilterInput`, and ends with a `FilterEnd` operator that\n * adapts from a `FilterOperator` `FilterOutput` to a normal `Operator` `Input`.\n * `FilterOperator`'s do not have `fetch` instead they have a\n * `filter(node: Node): boolean` method.\n * They also have `push` which is just like normal `Operator` push.\n * Not having a `fetch` means these `FilterOperator`'s cannot modify\n * `Node` `row`s or `relationship`s, but they shouldn't, they should just\n * filter.\n *\n * This `FilterOperator` abstraction enables much more efficient processing of\n * `fetch` for `where` clauses containing OR conditions.\n *\n * See https://github.com/rocicorp/mono/pull/4339\n */\n\nexport interface FilterInput extends InputBase {\n /** Tell the input where to send its output. */\n setFilterOutput(output: FilterOutput): void;\n}\n\nexport interface FilterOutput extends Output {\n // Lets the operator know that we're in a loop of filtering\n // nodes. E.g., so the operator can cache results for the\n // duration of the loop.\n beginFilter(): void;\n filter(node: Node): IterableIterator<'yield', boolean>;\n endFilter(): void;\n}\n\nexport interface FilterOperator extends FilterInput, FilterOutput {}\n\n/**\n * An implementation of FilterOutput that throws if push or filter is called.\n * It is used as the initial value for for an operator's output before it is\n * set.\n */\nexport const throwFilterOutput: FilterOutput = {\n // oxlint-disable-next-line require-yield\n *push(_change: Change): Stream<'yield'> {\n throw new Error('Output not set');\n },\n\n // oxlint-disable-next-line require-yield\n *filter(_node: Node): IterableIterator<'yield', boolean> {\n throw new Error('Output not set');\n },\n\n beginFilter() {},\n endFilter() {},\n};\n\nexport class FilterStart implements FilterInput, Output {\n readonly #input: Input;\n readonly #condition: NoSubqueryCondition | undefined;\n #output: FilterOutput = throwFilterOutput;\n\n constructor(input: Input, condition?: NoSubqueryCondition) {\n this.#input = input;\n this.#condition = condition;\n input.setOutput(this);\n }\n\n setFilterOutput(output: FilterOutput) {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n push(change: Change) {\n return this.#output.push(change, this);\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n const mergedFilter = mergeFilters(req.filter, this.#condition);\n const childReq =\n mergedFilter === req.filter ? req : {...req, filter: mergedFilter};\n this.#output.beginFilter();\n try {\n for (const node of this.#input.fetch(childReq)) {\n if (node === 'yield') {\n yield node;\n continue;\n }\n if (yield* this.#output.filter(node)) {\n yield node;\n }\n }\n } finally {\n // finally is important if an exception is thrown or\n // if the stream is not fully consumed.\n this.#output.endFilter();\n }\n }\n}\n\nfunction mergeFilters(\n reqFilter: NoSubqueryCondition | undefined,\n ownCondition: NoSubqueryCondition | undefined,\n): NoSubqueryCondition | undefined {\n if (!ownCondition) {\n return reqFilter;\n }\n if (!reqFilter) {\n return ownCondition;\n }\n return {type: 'and', conditions: [reqFilter, ownCondition]};\n}\n\nexport class FilterEnd implements Input, FilterOutput {\n readonly #start: FilterStart;\n readonly #input: FilterInput;\n\n #output: Output = throwFilterOutput;\n\n constructor(start: FilterStart, input: FilterInput) {\n this.#start = start;\n this.#input = input;\n input.setFilterOutput(this);\n }\n\n fetch(req: FetchRequest): Stream<Node | 'yield'> {\n return this.#start.fetch(req);\n }\n\n beginFilter() {}\n endFilter() {}\n\n filter(_node: Node) {\n return returnTrueEmptyIterator;\n }\n\n setOutput(output: Output) {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n push(change: Change) {\n return this.#output.push(change, this);\n }\n}\n\nconst returnTrueEmptyIterator = makeEmptyIteratorWithReturn(true);\n\nexport function buildFilterPipeline(\n input: Input,\n delegate: BuilderDelegate,\n pipeline: (filterInput: FilterInput) => FilterInput,\n condition?: NoSubqueryCondition,\n): Input {\n const filterStart = new FilterStart(input, condition);\n delegate.addEdge(input, filterStart);\n const middle = pipeline(filterStart);\n delegate.addEdge(filterStart, middle);\n const filterEnd = new FilterEnd(filterStart, middle);\n delegate.addEdge(middle, filterEnd);\n return filterEnd;\n}\n"],"mappings":";;;;;;;;AAiDA,IAAa,oBAAkC;CAE7C,CAAC,KAAK,SAAkC;EACtC,MAAM,IAAI,MAAM,gBAAgB;CAClC;CAGA,CAAC,OAAO,OAAiD;EACvD,MAAM,IAAI,MAAM,gBAAgB;CAClC;CAEA,cAAc,CAAC;CACf,YAAY,CAAC;AACf;AAEA,IAAa,cAAb,MAAwD;CACtD;CACA;CACA,UAAwB;CAExB,YAAY,OAAc,WAAiC;EACzD,KAAKA,SAAS;EACd,KAAKC,aAAa;EAClB,MAAM,UAAU,IAAI;CACtB;CAEA,gBAAgB,QAAsB;EACpC,KAAKC,UAAU;CACjB;CAEA,UAAgB;EACd,KAAKF,OAAO,QAAQ;CACtB;CAEA,YAA0B;EACxB,OAAO,KAAKA,OAAO,UAAU;CAC/B;CAEA,KAAK,QAAgB;EACnB,OAAO,KAAKE,QAAQ,KAAK,QAAQ,IAAI;CACvC;CAEA,CAAC,MAAM,KAA2C;EAChD,MAAM,eAAe,aAAa,IAAI,QAAQ,KAAKD,UAAU;EAC7D,MAAM,WACJ,iBAAiB,IAAI,SAAS,MAAM;GAAC,GAAG;GAAK,QAAQ;EAAY;EACnE,KAAKC,QAAQ,YAAY;EACzB,IAAI;GACF,KAAK,MAAM,QAAQ,KAAKF,OAAO,MAAM,QAAQ,GAAG;IAC9C,IAAI,SAAS,SAAS;KACpB,MAAM;KACN;IACF;IACA,IAAI,OAAO,KAAKE,QAAQ,OAAO,IAAI,GACjC,MAAM;GAEV;EACF,UAAU;GAGR,KAAKA,QAAQ,UAAU;EACzB;CACF;AACF;AAEA,SAAS,aACP,WACA,cACiC;CACjC,IAAI,CAAC,cACH,OAAO;CAET,IAAI,CAAC,WACH,OAAO;CAET,OAAO;EAAC,MAAM;EAAO,YAAY,CAAC,WAAW,YAAY;CAAC;AAC5D;AAEA,IAAa,YAAb,MAAsD;CACpD;CACA;CAEA,UAAkB;CAElB,YAAY,OAAoB,OAAoB;EAClD,KAAKC,SAAS;EACd,KAAKH,SAAS;EACd,MAAM,gBAAgB,IAAI;CAC5B;CAEA,MAAM,KAA2C;EAC/C,OAAO,KAAKG,OAAO,MAAM,GAAG;CAC9B;CAEA,cAAc,CAAC;CACf,YAAY,CAAC;CAEb,OAAO,OAAa;EAClB,OAAO;CACT;CAEA,UAAU,QAAgB;EACxB,KAAKD,UAAU;CACjB;CAEA,UAAgB;EACd,KAAKF,OAAO,QAAQ;CACtB;CAEA,YAA0B;EACxB,OAAO,KAAKA,OAAO,UAAU;CAC/B;CAEA,KAAK,QAAgB;EACnB,OAAO,KAAKE,QAAQ,KAAK,QAAQ,IAAI;CACvC;AACF;AAEA,IAAM,0BAA0B,4BAA4B,IAAI;AAEhE,SAAgB,oBACd,OACA,UACA,UACA,WACO;CACP,MAAM,cAAc,IAAI,YAAY,OAAO,SAAS;CACpD,SAAS,QAAQ,OAAO,WAAW;CACnC,MAAM,SAAS,SAAS,WAAW;CACnC,SAAS,QAAQ,aAAa,MAAM;CACpC,MAAM,YAAY,IAAI,UAAU,aAAa,MAAM;CACnD,SAAS,QAAQ,QAAQ,SAAS;CAClC,OAAO;AACT"}
@@ -13,10 +13,10 @@ export declare class Filter implements FilterOperator {
13
13
  constructor(input: FilterInput, predicate: (row: Row) => boolean);
14
14
  beginFilter(): void;
15
15
  endFilter(): void;
16
- filter(node: Node): Generator<'yield', boolean>;
16
+ filter(node: Node): IterableIterator<'yield', boolean>;
17
17
  setFilterOutput(output: FilterOutput): void;
18
18
  destroy(): void;
19
19
  getSchema(): SourceSchema;
20
- push(change: Change): Generator<"yield", void, any>;
20
+ push(change: Change): import("./stream.ts").Stream<"yield">;
21
21
  }
22
22
  //# sourceMappingURL=filter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAC5D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EAAC,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAE9C;;;;GAIG;AACH,qBAAa,MAAO,YAAW,cAAc;;IAM3C,YAAY,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,EAI/D;IAED,WAAW,IAAI,IAAI,CAElB;IAED,SAAS,IAAI,IAAI,CAEhB;IAEA,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAE/C;IAED,eAAe,CAAC,MAAM,EAAE,YAAY,QAEnC;IAED,OAAO,IAAI,IAAI,CAEd;IAED,SAAS,IAAI,YAAY,CAExB;IAEA,IAAI,CAAC,MAAM,EAAE,MAAM,iCAEnB;CACF"}
1
+ {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/filter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAC5D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EAAC,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAE9C;;;;GAIG;AACH,qBAAa,MAAO,YAAW,cAAc;;IAM3C,YAAY,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,EAI/D;IAED,WAAW,IAAI,IAAI,CAElB;IAED,SAAS,IAAI,IAAI,CAEhB;IAED,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAKrD;IAED,eAAe,CAAC,MAAM,EAAE,YAAY,QAEnC;IAED,OAAO,IAAI,IAAI,CAEd;IAED,SAAS,IAAI,YAAY,CAExB;IAED,IAAI,CAAC,MAAM,EAAE,MAAM,yCAElB;CACF"}
@@ -1,3 +1,4 @@
1
+ import { makeEmptyIteratorWithReturn } from "../../../shared/src/iterables.js";
1
2
  import "./data.js";
2
3
  import { throwFilterOutput } from "./filter-operators.js";
3
4
  import { filterPush } from "./filter-push.js";
@@ -22,8 +23,9 @@ var Filter = class {
22
23
  endFilter() {
23
24
  this.#output.endFilter();
24
25
  }
25
- *filter(node) {
26
- return this.#predicate(node.row) && (yield* this.#output.filter(node));
26
+ filter(node) {
27
+ if (this.#predicate(node.row)) return this.#output.filter(node);
28
+ return emptyIteratorReturnFalse;
27
29
  }
28
30
  setFilterOutput(output) {
29
31
  this.#output = output;
@@ -34,10 +36,11 @@ var Filter = class {
34
36
  getSchema() {
35
37
  return this.#input.getSchema();
36
38
  }
37
- *push(change) {
38
- yield* filterPush(change, this.#output, this, this.#predicate);
39
+ push(change) {
40
+ return filterPush(change, this.#output, this, this.#predicate);
39
41
  }
40
42
  };
43
+ var emptyIteratorReturnFalse = makeEmptyIteratorWithReturn(false);
41
44
  //#endregion
42
45
  export { Filter };
43
46
 
@@ -1 +1 @@
1
- {"version":3,"file":"filter.js","names":["#input","#predicate","#output"],"sources":["../../../../../zql/src/ivm/filter.ts"],"sourcesContent":["import type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {Change} from './change.ts';\nimport {type Node} from './data.ts';\nimport {\n throwFilterOutput,\n type FilterInput,\n type FilterOperator,\n type FilterOutput,\n} from './filter-operators.ts';\nimport {filterPush} from './filter-push.ts';\nimport type {SourceSchema} from './schema.ts';\n\n/**\n * The Filter operator filters data through a predicate. It is stateless.\n *\n * The predicate must be pure.\n */\nexport class Filter implements FilterOperator {\n readonly #input: FilterInput;\n readonly #predicate: (row: Row) => boolean;\n\n #output: FilterOutput = throwFilterOutput;\n\n constructor(input: FilterInput, predicate: (row: Row) => boolean) {\n this.#input = input;\n this.#predicate = predicate;\n input.setFilterOutput(this);\n }\n\n beginFilter(): void {\n this.#output.beginFilter();\n }\n\n endFilter(): void {\n this.#output.endFilter();\n }\n\n *filter(node: Node): Generator<'yield', boolean> {\n return this.#predicate(node.row) && (yield* this.#output.filter(node));\n }\n\n setFilterOutput(output: FilterOutput) {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *push(change: Change) {\n yield* filterPush(change, this.#output, this, this.#predicate);\n }\n}\n"],"mappings":";;;;;;;;;AAiBA,IAAa,SAAb,MAA8C;CAC5C;CACA;CAEA,UAAwB;CAExB,YAAY,OAAoB,WAAkC;EAChE,KAAKA,SAAS;EACd,KAAKC,aAAa;EAClB,MAAM,gBAAgB,IAAI;CAC5B;CAEA,cAAoB;EAClB,KAAKC,QAAQ,YAAY;CAC3B;CAEA,YAAkB;EAChB,KAAKA,QAAQ,UAAU;CACzB;CAEA,CAAC,OAAO,MAAyC;EAC/C,OAAO,KAAKD,WAAW,KAAK,GAAG,MAAM,OAAO,KAAKC,QAAQ,OAAO,IAAI;CACtE;CAEA,gBAAgB,QAAsB;EACpC,KAAKA,UAAU;CACjB;CAEA,UAAgB;EACd,KAAKF,OAAO,QAAQ;CACtB;CAEA,YAA0B;EACxB,OAAO,KAAKA,OAAO,UAAU;CAC/B;CAEA,CAAC,KAAK,QAAgB;EACpB,OAAO,WAAW,QAAQ,KAAKE,SAAS,MAAM,KAAKD,UAAU;CAC/D;AACF"}
1
+ {"version":3,"file":"filter.js","names":["#input","#predicate","#output"],"sources":["../../../../../zql/src/ivm/filter.ts"],"sourcesContent":["import {makeEmptyIteratorWithReturn} from '../../../shared/src/iterables.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {Change} from './change.ts';\nimport {type Node} from './data.ts';\nimport {\n throwFilterOutput,\n type FilterInput,\n type FilterOperator,\n type FilterOutput,\n} from './filter-operators.ts';\nimport {filterPush} from './filter-push.ts';\nimport type {SourceSchema} from './schema.ts';\n\n/**\n * The Filter operator filters data through a predicate. It is stateless.\n *\n * The predicate must be pure.\n */\nexport class Filter implements FilterOperator {\n readonly #input: FilterInput;\n readonly #predicate: (row: Row) => boolean;\n\n #output: FilterOutput = throwFilterOutput;\n\n constructor(input: FilterInput, predicate: (row: Row) => boolean) {\n this.#input = input;\n this.#predicate = predicate;\n input.setFilterOutput(this);\n }\n\n beginFilter(): void {\n this.#output.beginFilter();\n }\n\n endFilter(): void {\n this.#output.endFilter();\n }\n\n filter(node: Node): IterableIterator<'yield', boolean> {\n if (this.#predicate(node.row)) {\n return this.#output.filter(node);\n }\n return emptyIteratorReturnFalse;\n }\n\n setFilterOutput(output: FilterOutput) {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n push(change: Change) {\n return filterPush(change, this.#output, this, this.#predicate);\n }\n}\n\nconst emptyIteratorReturnFalse = makeEmptyIteratorWithReturn(false);\n"],"mappings":";;;;;;;;;;AAkBA,IAAa,SAAb,MAA8C;CAC5C;CACA;CAEA,UAAwB;CAExB,YAAY,OAAoB,WAAkC;EAChE,KAAKA,SAAS;EACd,KAAKC,aAAa;EAClB,MAAM,gBAAgB,IAAI;CAC5B;CAEA,cAAoB;EAClB,KAAKC,QAAQ,YAAY;CAC3B;CAEA,YAAkB;EAChB,KAAKA,QAAQ,UAAU;CACzB;CAEA,OAAO,MAAgD;EACrD,IAAI,KAAKD,WAAW,KAAK,GAAG,GAC1B,OAAO,KAAKC,QAAQ,OAAO,IAAI;EAEjC,OAAO;CACT;CAEA,gBAAgB,QAAsB;EACpC,KAAKA,UAAU;CACjB;CAEA,UAAgB;EACd,KAAKF,OAAO,QAAQ;CACtB;CAEA,YAA0B;EACxB,OAAO,KAAKA,OAAO,UAAU;CAC/B;CAEA,KAAK,QAAgB;EACnB,OAAO,WAAW,QAAQ,KAAKE,SAAS,MAAM,KAAKD,UAAU;CAC/D;AACF;AAEA,IAAM,2BAA2B,4BAA4B,KAAK"}
@@ -147,13 +147,13 @@ var FlippedJoin = class {
147
147
  yield* this.#yieldParentWithOverlay(node, relatedChildNodes);
148
148
  }
149
149
  }
150
- *#fetchChunked(req, incomingMultis, computedMulti, compare) {
150
+ #fetchChunked(req, incomingMultis, computedMulti, compare) {
151
151
  const chunkStreams = [];
152
152
  for (let i = 0; i < computedMulti.length; i += multiConstraintChunkSize) chunkStreams.push(this.#parent.fetch({
153
153
  ...req,
154
154
  multiConstraints: [...incomingMultis, computedMulti.slice(i, i + multiConstraintChunkSize)]
155
155
  }));
156
- yield* mergeSortedStreams(chunkStreams, compare);
156
+ return mergeSortedStreams(chunkStreams, compare);
157
157
  }
158
158
  *#yieldParentWithOverlay(minParentNode, relatedChildNodes) {
159
159
  let overlaidRelatedChildNodes = relatedChildNodes;
@@ -1 +1 @@
1
- {"version":3,"file":"flipped-join.js","names":["#parent","#child","#parentKey","#childKey","#relationshipName","#schema","#pushParent","#pushChild","#output","#inprogressChildChange","#fetchBatched","#fetchChunked","#yieldParentWithOverlay","#inprogressChildChangePosition","#pushChildChange"],"sources":["../../../../../zql/src/ivm/flipped-join.ts"],"sourcesContent":["import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport {binarySearch} from '../../../shared/src/binary-search.ts';\nimport type {CompoundKey, System} from '../../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport {ChangeIndex} from './change-index.ts';\nimport {ChangeType} from './change-type.ts';\nimport {\n makeAddChange,\n makeChildChange,\n makeEditChange,\n makeRemoveChange,\n type Change,\n} from './change.ts';\nimport {constraintsAreCompatible, type Constraint} from './constraint.ts';\nimport type {Node} from './data.ts';\nimport {\n buildJoinConstraint,\n generateWithOverlayNoYield,\n isJoinMatch,\n rowEqualsForCompoundKey,\n} from './join-utils.ts';\nimport {mergeSortedStreams} from './memory-source.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type MultiConstraint,\n type Output,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {type Stream} from './stream.ts';\n\n/**\n * Maximum number of entries sent in a single batched `parent.fetch`\n * call. Larger child-node sets are split into multiple fetches whose\n * sorted streams are merged in JS.\n *\n * Why bound this:\n * - **Bounded fetch on early termination.** `mergeSortedStreams` primes\n * one row from every chunk before yielding the first output, so all\n * chunks open their cursors up front. Smaller chunks cap the\n * worst-case overfetch when downstream `Take` consumes only a few\n * rows — at chunk N, we may waste up to ~N index seeks before\n * `.return()` propagates.\n * - **Parameter limit.** Well under SQLite's default\n * `SQLITE_MAX_VARIABLE_NUMBER` (32766). Compound keys multiply the\n * parameter count by key length, so we leave headroom.\n *\n * Tested 64/128/256; 256 had the best worst-case across planner suites\n * and perf tests.\n *\n * We should, however, start doing shadow tests of the planner\n * against cloudzero queries.\n */\nconst MULTI_CONSTRAINT_CHUNK_SIZE = 256;\n\n// Mutable test seam — production code reads this via the getter.\nlet multiConstraintChunkSize: number = MULTI_CONSTRAINT_CHUNK_SIZE;\n\nexport function getMultiConstraintChunkSize(): number {\n return multiConstraintChunkSize;\n}\n\n/** Test only. Returns a restore function. */\nexport function setMultiConstraintChunkSizeForTest(size: number): () => void {\n const prev = multiConstraintChunkSize;\n multiConstraintChunkSize = size;\n return () => {\n multiConstraintChunkSize = prev;\n };\n}\n\ntype Args = {\n parent: Input;\n child: Input;\n // The nth key in childKey corresponds to the nth key in parentKey.\n parentKey: CompoundKey;\n childKey: CompoundKey;\n\n relationshipName: string;\n hidden: boolean;\n system: System;\n};\n\n/**\n * An *inner* join which fetches nodes from its child input first and then\n * fetches their related nodes from its parent input. Output nodes are the\n * nodes from parent input (in parent input order), which have at least one\n * related child. These output nodes have a new relationship added to them,\n * which has the name `relationshipName`. The value of the relationship is a\n * stream of related nodes from the child input (in child input order).\n */\nexport class FlippedJoin implements Input {\n readonly #parent: Input;\n readonly #child: Input;\n readonly #parentKey: CompoundKey;\n readonly #childKey: CompoundKey;\n readonly #relationshipName: string;\n readonly #schema: SourceSchema;\n\n #output: Output = throwOutput;\n\n #inprogressChildChange: Change | undefined;\n #inprogressChildChangePosition: Row | undefined;\n\n constructor({\n parent,\n child,\n parentKey,\n childKey,\n relationshipName,\n hidden,\n system,\n }: Args) {\n assert(parent !== child, 'Parent and child must be different operators');\n assert(\n parentKey.length === childKey.length,\n 'The parentKey and childKey keys must have same length',\n );\n this.#parent = parent;\n this.#child = child;\n this.#parentKey = parentKey;\n this.#childKey = childKey;\n this.#relationshipName = relationshipName;\n\n const parentSchema = parent.getSchema();\n const childSchema = child.getSchema();\n this.#schema = {\n ...parentSchema,\n relationships: {\n ...parentSchema.relationships,\n [relationshipName]: {\n ...childSchema,\n isHidden: hidden,\n system,\n },\n },\n };\n\n parent.setOutput({\n push: (change: Change) => this.#pushParent(change),\n });\n child.setOutput({\n push: (change: Change) => this.#pushChild(change),\n });\n }\n\n destroy(): void {\n this.#child.destroy();\n this.#parent.destroy();\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n getSchema(): SourceSchema {\n return this.#schema;\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n // Translate constraints for the parent on parts of the join key to\n // constraints for the child.\n const childConstraint: Record<string, Value> = {};\n let hasChildConstraint = false;\n if (req.constraint) {\n for (const [key, value] of Object.entries(req.constraint)) {\n const index = this.#parentKey.indexOf(key);\n if (index !== -1) {\n hasChildConstraint = true;\n childConstraint[this.#childKey[index]] = value;\n }\n }\n }\n\n const childNodes: Node[] = [];\n for (const node of this.#child.fetch(\n hasChildConstraint ? {constraint: childConstraint} : {},\n )) {\n if (node === 'yield') {\n yield node;\n continue;\n }\n childNodes.push(node);\n }\n\n // FlippedJoin's split-push change overlay logic is largely\n // the same as Join's with the exception of remove. For remove,\n // the change is undone here, and then re-applied to parents with order\n // less than or equal to change.position below. This is necessary\n // because if the removed node was the last related child, the\n // related parents with position greater than change.position\n // (which should not yet have the node removed), would not even\n // be fetched here, and would be absent from the output all together.\n if (this.#inprogressChildChange?.[ChangeIndex.TYPE] === ChangeType.REMOVE) {\n const removedNode = this.#inprogressChildChange[ChangeIndex.NODE];\n const compare = this.#child.getSchema().compareRows;\n const insertPos = binarySearch(childNodes.length, i =>\n compare(removedNode.row, childNodes[i].row),\n );\n childNodes.splice(insertPos, 0, removedNode);\n }\n\n yield* this.#fetchBatched(req, childNodes);\n }\n\n /**\n * Fetches parents for `childNodes` in batched calls, using\n * `multiConstraint` so the source can issue one query per chunk (e.g.\n * SQL `IN` with index-aware seek) instead of N per-child cursors.\n *\n * Multi-constraint values are split into chunks of `CHUNK_SIZE`, so\n * SQL `IN` lists stay bounded — predictable plans, statement-cache\n * hits across calls of the same chunk size, well below SQLite's\n * parameter limit.\n *\n * Within each chunk, the source returns parents in `compareRows` order.\n * Across chunks, we merge with `mergeSortedStreams` so the overall\n * stream is also in order. Note: the merge primes one row from every\n * chunk before yielding the first output, so all chunks open their\n * cursors up front. Early termination downstream then prevents any\n * further work on un-advanced chunks (cursors get `.return()`'d via\n * `mergeSortedStreams`'s finally block).\n *\n * Replaces the previous split between `#fetchMergeSort` and\n * `#fetchQuicksort`. The unique-vs-not distinction is no longer needed:\n * the source handles cardinality (single index seek for each value) and\n * ordering (SQL `ORDER BY` / index walk).\n */\n *#fetchBatched(\n req: FetchRequest,\n childNodes: Node[],\n ): Stream<Node | 'yield'> {\n const parentReqConstraint = req.constraint;\n const parentKey = this.#parentKey;\n const childKey = this.#childKey;\n\n // Build (deduped) multi-constraint and a key→child-indexes map. Same\n // parent-key value across multiple children groups them together.\n const computedMulti: Constraint[] = [];\n const childIndexesByKey = new Map<string, number[]>();\n for (let i = 0; i < childNodes.length; i++) {\n const constraintFromChild = buildJoinConstraint(\n childNodes[i].row,\n childKey,\n parentKey,\n );\n if (\n !constraintFromChild ||\n (parentReqConstraint &&\n !constraintsAreCompatible(constraintFromChild, parentReqConstraint))\n ) {\n continue;\n }\n const key = canonicalKey(constraintFromChild, parentKey);\n const existing = childIndexesByKey.get(key);\n if (existing === undefined) {\n childIndexesByKey.set(key, [i]);\n computedMulti.push(constraintFromChild);\n } else {\n existing.push(i);\n }\n }\n\n if (computedMulti.length === 0) {\n return;\n }\n\n // Source returns parents in compareRows order within each chunk.\n // Merge across chunks to yield a globally ordered stream.\n const compareRows = this.#schema.compareRows;\n const compare: (a: Node, b: Node) => number = req.reverse\n ? (a, b) => compareRows(b.row, a.row)\n : (a, b) => compareRows(a.row, b.row);\n\n // Append our computed multi to whatever req.multiConstraints already\n // contained — chained FlippedJoins each contribute one entry, so the\n // source ANDs them all (e.g. `assigneeID IN (…) AND creatorID IN (…)`).\n const incoming = req.multiConstraints ?? [];\n const parentStream =\n computedMulti.length <= multiConstraintChunkSize\n ? this.#parent.fetch({\n ...req,\n multiConstraints: [...incoming, computedMulti],\n })\n : this.#fetchChunked(req, incoming, computedMulti, compare);\n\n for (const node of parentStream) {\n if (node === 'yield') {\n yield 'yield';\n continue;\n }\n const key = canonicalKey(node.row, parentKey);\n const idxs = childIndexesByKey.get(key);\n if (idxs === undefined) {\n // This row's parent-key doesn't match any of our computed\n // multi-constraint entries. Happens when our parent is an\n // intermediate operator (e.g. a chained FlippedJoin) that passes\n // multiConstraints through unchanged instead of filtering — see\n // FetchRequest.multiConstraints contract. The lookup miss here\n // performs the required filter, so just skip the row.\n continue;\n }\n // Children retain their original input order within the group\n // because we appended to `idxs` in iteration order.\n const relatedChildNodes: Node[] = idxs.map(i => childNodes[i]);\n yield* this.#yieldParentWithOverlay(node, relatedChildNodes);\n }\n }\n\n *#fetchChunked(\n req: FetchRequest,\n incomingMultis: readonly MultiConstraint[],\n computedMulti: MultiConstraint,\n compare: (a: Node, b: Node) => number,\n ): Stream<Node | 'yield'> {\n const chunkStreams: Stream<Node | 'yield'>[] = [];\n for (let i = 0; i < computedMulti.length; i += multiConstraintChunkSize) {\n chunkStreams.push(\n this.#parent.fetch({\n ...req,\n multiConstraints: [\n ...incomingMultis,\n computedMulti.slice(i, i + multiConstraintChunkSize),\n ],\n }),\n );\n }\n yield* mergeSortedStreams(chunkStreams, compare);\n }\n\n *#yieldParentWithOverlay(\n minParentNode: Node,\n relatedChildNodes: Node[],\n ): Stream<Node> {\n let overlaidRelatedChildNodes = relatedChildNodes;\n if (\n this.#inprogressChildChange &&\n this.#inprogressChildChangePosition &&\n isJoinMatch(\n this.#inprogressChildChange[ChangeIndex.NODE].row,\n this.#childKey,\n minParentNode.row,\n this.#parentKey,\n )\n ) {\n const hasInprogressChildChangeBeenPushedForMinParentNode =\n this.#parent\n .getSchema()\n .compareRows(\n minParentNode.row,\n this.#inprogressChildChangePosition,\n ) <= 0;\n if (this.#inprogressChildChange[ChangeIndex.TYPE] === ChangeType.REMOVE) {\n if (hasInprogressChildChangeBeenPushedForMinParentNode) {\n // Remove from relatedChildNodes since the removed child\n // was inserted into childNodes above.\n overlaidRelatedChildNodes = relatedChildNodes.filter(\n n => n !== this.#inprogressChildChange?.[ChangeIndex.NODE],\n );\n }\n } else if (!hasInprogressChildChangeBeenPushedForMinParentNode) {\n overlaidRelatedChildNodes = [\n ...generateWithOverlayNoYield(\n relatedChildNodes,\n this.#inprogressChildChange,\n this.#child.getSchema(),\n ),\n ];\n }\n }\n\n // yield node if after the overlay it still has relationship nodes\n if (overlaidRelatedChildNodes.length > 0) {\n yield {\n ...minParentNode,\n relationships: {\n ...minParentNode.relationships,\n [this.#relationshipName]: () => overlaidRelatedChildNodes,\n },\n };\n }\n }\n\n *#pushChild(change: Change): Stream<'yield'> {\n switch (change[ChangeIndex.TYPE]) {\n case ChangeType.ADD:\n case ChangeType.REMOVE:\n yield* this.#pushChildChange(change);\n break;\n case ChangeType.EDIT: {\n assert(\n rowEqualsForCompoundKey(\n change[ChangeIndex.OLD_NODE].row,\n change[ChangeIndex.NODE].row,\n this.#childKey,\n ),\n `Child edit must not change relationship.`,\n );\n yield* this.#pushChildChange(change, true);\n break;\n }\n case ChangeType.CHILD:\n yield* this.#pushChildChange(change, true);\n break;\n }\n }\n\n *#pushChildChange(change: Change, exists?: boolean): Stream<'yield'> {\n this.#inprogressChildChange = change;\n this.#inprogressChildChangePosition = undefined;\n try {\n const constraint = buildJoinConstraint(\n change[ChangeIndex.NODE].row,\n this.#childKey,\n this.#parentKey,\n );\n const parentNodeStream = constraint\n ? this.#parent.fetch({constraint})\n : [];\n for (const parentNode of parentNodeStream) {\n if (parentNode === 'yield') {\n yield 'yield';\n continue;\n }\n this.#inprogressChildChange = change;\n this.#inprogressChildChangePosition = parentNode.row;\n const childNodeStream = () => {\n const constraint = buildJoinConstraint(\n parentNode.row,\n this.#parentKey,\n this.#childKey,\n );\n return constraint ? this.#child.fetch({constraint}) : [];\n };\n if (!exists) {\n for (const childNode of childNodeStream()) {\n if (childNode === 'yield') {\n yield 'yield';\n continue;\n }\n if (\n this.#child\n .getSchema()\n .compareRows(childNode.row, change[ChangeIndex.NODE].row) !== 0\n ) {\n exists = true;\n break;\n }\n }\n }\n if (exists) {\n yield* this.#output.push(\n makeChildChange(\n {\n ...parentNode,\n relationships: {\n ...parentNode.relationships,\n [this.#relationshipName]: childNodeStream,\n },\n },\n {\n relationshipName: this.#relationshipName,\n change,\n },\n ),\n this,\n );\n } else {\n const newNode = {\n ...parentNode,\n relationships: {\n ...parentNode.relationships,\n [this.#relationshipName]: () => [change[ChangeIndex.NODE]],\n },\n };\n yield* this.#output.push(\n change[ChangeIndex.TYPE] === ChangeType.ADD\n ? makeAddChange(newNode)\n : makeRemoveChange(newNode),\n this,\n );\n }\n }\n } finally {\n this.#inprogressChildChange = undefined;\n }\n }\n\n *#pushParent(change: Change): Stream<'yield'> {\n const childNodeStream = (node: Node) => () => {\n const constraint = buildJoinConstraint(\n node.row,\n this.#parentKey,\n this.#childKey,\n );\n return constraint ? this.#child.fetch({constraint}) : [];\n };\n\n const flip = (node: Node) => ({\n ...node,\n relationships: {\n ...node.relationships,\n [this.#relationshipName]: childNodeStream(node),\n },\n });\n\n // If no related child don't push as this is an inner join.\n let hasRelatedChild = false;\n for (const node of childNodeStream(change[ChangeIndex.NODE])()) {\n if (node === 'yield') {\n yield 'yield';\n continue;\n } else {\n hasRelatedChild = true;\n break;\n }\n }\n if (!hasRelatedChild) {\n return;\n }\n\n switch (change[ChangeIndex.TYPE]) {\n case ChangeType.ADD:\n yield* this.#output.push(\n makeAddChange(flip(change[ChangeIndex.NODE])),\n this,\n );\n break;\n case ChangeType.REMOVE:\n yield* this.#output.push(\n makeRemoveChange(flip(change[ChangeIndex.NODE])),\n this,\n );\n break;\n case ChangeType.CHILD: {\n yield* this.#output.push(\n makeChildChange(\n flip(change[ChangeIndex.NODE]),\n change[ChangeIndex.CHILD_DATA],\n ),\n this,\n );\n break;\n }\n case ChangeType.EDIT: {\n assert(\n rowEqualsForCompoundKey(\n change[ChangeIndex.OLD_NODE].row,\n change[ChangeIndex.NODE].row,\n this.#parentKey,\n ),\n `Parent edit must not change relationship.`,\n );\n yield* this.#output.push(\n makeEditChange(\n flip(change[ChangeIndex.NODE]),\n flip(change[ChangeIndex.OLD_NODE]),\n ),\n this,\n );\n break;\n }\n default:\n unreachable(change);\n }\n }\n}\n\n// Test seam with a widened record type — canonicalValue handles bigint\n// at runtime (zqlite's safeIntegers) but `Value` doesn't list it.\nexport function canonicalKeyForTest(\n record: Record<string, Value | bigint | undefined>,\n keys: CompoundKey,\n): string {\n return canonicalKey(record as Record<string, Value | undefined>, keys);\n}\n\n/**\n * Canonical string key over `keys` of `record`, used by `#fetchBatched`\n * both to dedupe `multiConstraint` entries (record = Constraint) and to\n * map each returned parent row back to the children that referenced its\n * parent-key tuple (record = Row).\n */\nfunction canonicalKey(\n record: Record<string, Value | undefined>,\n keys: CompoundKey,\n): string {\n if (keys.length === 1) {\n return canonicalValue(record[keys[0]]);\n }\n let s = '';\n for (let i = 0; i < keys.length; i++) {\n if (i > 0) s += '\\x00';\n s += canonicalValue(record[keys[i]]);\n }\n return s;\n}\n\nfunction canonicalValue(v: Value | bigint | undefined): string {\n // Tag by type so we don't conflate e.g. `1` (number) with `\"1\"` (string).\n // Bigint shows up at runtime when zqlite's safeIntegers is on, even\n // though the static `Value` type doesn't list it.\n if (v === null || v === undefined) return 'n';\n const t = typeof v;\n if (t === 'string') return 's' + (v as string);\n if (t === 'number') return 'd' + (v as number);\n if (t === 'bigint') return 'b' + (v as bigint).toString();\n if (t === 'boolean') return v ? 't' : 'f';\n return 'j' + JSON.stringify(v);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"flipped-join.js","names":["#parent","#child","#parentKey","#childKey","#relationshipName","#schema","#pushParent","#pushChild","#output","#inprogressChildChange","#fetchBatched","#fetchChunked","#yieldParentWithOverlay","#inprogressChildChangePosition","#pushChildChange"],"sources":["../../../../../zql/src/ivm/flipped-join.ts"],"sourcesContent":["import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport {binarySearch} from '../../../shared/src/binary-search.ts';\nimport type {CompoundKey, System} from '../../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport {ChangeIndex} from './change-index.ts';\nimport {ChangeType} from './change-type.ts';\nimport {\n makeAddChange,\n makeChildChange,\n makeEditChange,\n makeRemoveChange,\n type Change,\n} from './change.ts';\nimport {constraintsAreCompatible, type Constraint} from './constraint.ts';\nimport type {Node} from './data.ts';\nimport {\n buildJoinConstraint,\n generateWithOverlayNoYield,\n isJoinMatch,\n rowEqualsForCompoundKey,\n} from './join-utils.ts';\nimport {mergeSortedStreams} from './memory-source.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type MultiConstraint,\n type Output,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {type Stream} from './stream.ts';\n\n/**\n * Maximum number of entries sent in a single batched `parent.fetch`\n * call. Larger child-node sets are split into multiple fetches whose\n * sorted streams are merged in JS.\n *\n * Why bound this:\n * - **Bounded fetch on early termination.** `mergeSortedStreams` primes\n * one row from every chunk before yielding the first output, so all\n * chunks open their cursors up front. Smaller chunks cap the\n * worst-case overfetch when downstream `Take` consumes only a few\n * rows — at chunk N, we may waste up to ~N index seeks before\n * `.return()` propagates.\n * - **Parameter limit.** Well under SQLite's default\n * `SQLITE_MAX_VARIABLE_NUMBER` (32766). Compound keys multiply the\n * parameter count by key length, so we leave headroom.\n *\n * Tested 64/128/256; 256 had the best worst-case across planner suites\n * and perf tests.\n *\n * We should, however, start doing shadow tests of the planner\n * against cloudzero queries.\n */\nconst MULTI_CONSTRAINT_CHUNK_SIZE = 256;\n\n// Mutable test seam — production code reads this via the getter.\nlet multiConstraintChunkSize: number = MULTI_CONSTRAINT_CHUNK_SIZE;\n\nexport function getMultiConstraintChunkSize(): number {\n return multiConstraintChunkSize;\n}\n\n/** Test only. Returns a restore function. */\nexport function setMultiConstraintChunkSizeForTest(size: number): () => void {\n const prev = multiConstraintChunkSize;\n multiConstraintChunkSize = size;\n return () => {\n multiConstraintChunkSize = prev;\n };\n}\n\ntype Args = {\n parent: Input;\n child: Input;\n // The nth key in childKey corresponds to the nth key in parentKey.\n parentKey: CompoundKey;\n childKey: CompoundKey;\n\n relationshipName: string;\n hidden: boolean;\n system: System;\n};\n\n/**\n * An *inner* join which fetches nodes from its child input first and then\n * fetches their related nodes from its parent input. Output nodes are the\n * nodes from parent input (in parent input order), which have at least one\n * related child. These output nodes have a new relationship added to them,\n * which has the name `relationshipName`. The value of the relationship is a\n * stream of related nodes from the child input (in child input order).\n */\nexport class FlippedJoin implements Input {\n readonly #parent: Input;\n readonly #child: Input;\n readonly #parentKey: CompoundKey;\n readonly #childKey: CompoundKey;\n readonly #relationshipName: string;\n readonly #schema: SourceSchema;\n\n #output: Output = throwOutput;\n\n #inprogressChildChange: Change | undefined;\n #inprogressChildChangePosition: Row | undefined;\n\n constructor({\n parent,\n child,\n parentKey,\n childKey,\n relationshipName,\n hidden,\n system,\n }: Args) {\n assert(parent !== child, 'Parent and child must be different operators');\n assert(\n parentKey.length === childKey.length,\n 'The parentKey and childKey keys must have same length',\n );\n this.#parent = parent;\n this.#child = child;\n this.#parentKey = parentKey;\n this.#childKey = childKey;\n this.#relationshipName = relationshipName;\n\n const parentSchema = parent.getSchema();\n const childSchema = child.getSchema();\n this.#schema = {\n ...parentSchema,\n relationships: {\n ...parentSchema.relationships,\n [relationshipName]: {\n ...childSchema,\n isHidden: hidden,\n system,\n },\n },\n };\n\n parent.setOutput({\n push: (change: Change) => this.#pushParent(change),\n });\n child.setOutput({\n push: (change: Change) => this.#pushChild(change),\n });\n }\n\n destroy(): void {\n this.#child.destroy();\n this.#parent.destroy();\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n getSchema(): SourceSchema {\n return this.#schema;\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n // Translate constraints for the parent on parts of the join key to\n // constraints for the child.\n const childConstraint: Record<string, Value> = {};\n let hasChildConstraint = false;\n if (req.constraint) {\n for (const [key, value] of Object.entries(req.constraint)) {\n const index = this.#parentKey.indexOf(key);\n if (index !== -1) {\n hasChildConstraint = true;\n childConstraint[this.#childKey[index]] = value;\n }\n }\n }\n\n const childNodes: Node[] = [];\n for (const node of this.#child.fetch(\n hasChildConstraint ? {constraint: childConstraint} : {},\n )) {\n if (node === 'yield') {\n yield node;\n continue;\n }\n childNodes.push(node);\n }\n\n // FlippedJoin's split-push change overlay logic is largely\n // the same as Join's with the exception of remove. For remove,\n // the change is undone here, and then re-applied to parents with order\n // less than or equal to change.position below. This is necessary\n // because if the removed node was the last related child, the\n // related parents with position greater than change.position\n // (which should not yet have the node removed), would not even\n // be fetched here, and would be absent from the output all together.\n if (this.#inprogressChildChange?.[ChangeIndex.TYPE] === ChangeType.REMOVE) {\n const removedNode = this.#inprogressChildChange[ChangeIndex.NODE];\n const compare = this.#child.getSchema().compareRows;\n const insertPos = binarySearch(childNodes.length, i =>\n compare(removedNode.row, childNodes[i].row),\n );\n childNodes.splice(insertPos, 0, removedNode);\n }\n\n yield* this.#fetchBatched(req, childNodes);\n }\n\n /**\n * Fetches parents for `childNodes` in batched calls, using\n * `multiConstraint` so the source can issue one query per chunk (e.g.\n * SQL `IN` with index-aware seek) instead of N per-child cursors.\n *\n * Multi-constraint values are split into chunks of `CHUNK_SIZE`, so\n * SQL `IN` lists stay bounded — predictable plans, statement-cache\n * hits across calls of the same chunk size, well below SQLite's\n * parameter limit.\n *\n * Within each chunk, the source returns parents in `compareRows` order.\n * Across chunks, we merge with `mergeSortedStreams` so the overall\n * stream is also in order. Note: the merge primes one row from every\n * chunk before yielding the first output, so all chunks open their\n * cursors up front. Early termination downstream then prevents any\n * further work on un-advanced chunks (cursors get `.return()`'d via\n * `mergeSortedStreams`'s finally block).\n *\n * Replaces the previous split between `#fetchMergeSort` and\n * `#fetchQuicksort`. The unique-vs-not distinction is no longer needed:\n * the source handles cardinality (single index seek for each value) and\n * ordering (SQL `ORDER BY` / index walk).\n */\n *#fetchBatched(\n req: FetchRequest,\n childNodes: Node[],\n ): Stream<Node | 'yield'> {\n const parentReqConstraint = req.constraint;\n const parentKey = this.#parentKey;\n const childKey = this.#childKey;\n\n // Build (deduped) multi-constraint and a key→child-indexes map. Same\n // parent-key value across multiple children groups them together.\n const computedMulti: Constraint[] = [];\n const childIndexesByKey = new Map<string, number[]>();\n for (let i = 0; i < childNodes.length; i++) {\n const constraintFromChild = buildJoinConstraint(\n childNodes[i].row,\n childKey,\n parentKey,\n );\n if (\n !constraintFromChild ||\n (parentReqConstraint &&\n !constraintsAreCompatible(constraintFromChild, parentReqConstraint))\n ) {\n continue;\n }\n const key = canonicalKey(constraintFromChild, parentKey);\n const existing = childIndexesByKey.get(key);\n if (existing === undefined) {\n childIndexesByKey.set(key, [i]);\n computedMulti.push(constraintFromChild);\n } else {\n existing.push(i);\n }\n }\n\n if (computedMulti.length === 0) {\n return;\n }\n\n // Source returns parents in compareRows order within each chunk.\n // Merge across chunks to yield a globally ordered stream.\n const compareRows = this.#schema.compareRows;\n const compare: (a: Node, b: Node) => number = req.reverse\n ? (a, b) => compareRows(b.row, a.row)\n : (a, b) => compareRows(a.row, b.row);\n\n // Append our computed multi to whatever req.multiConstraints already\n // contained — chained FlippedJoins each contribute one entry, so the\n // source ANDs them all (e.g. `assigneeID IN (…) AND creatorID IN (…)`).\n const incoming = req.multiConstraints ?? [];\n const parentStream =\n computedMulti.length <= multiConstraintChunkSize\n ? this.#parent.fetch({\n ...req,\n multiConstraints: [...incoming, computedMulti],\n })\n : this.#fetchChunked(req, incoming, computedMulti, compare);\n\n for (const node of parentStream) {\n if (node === 'yield') {\n yield 'yield';\n continue;\n }\n const key = canonicalKey(node.row, parentKey);\n const idxs = childIndexesByKey.get(key);\n if (idxs === undefined) {\n // This row's parent-key doesn't match any of our computed\n // multi-constraint entries. Happens when our parent is an\n // intermediate operator (e.g. a chained FlippedJoin) that passes\n // multiConstraints through unchanged instead of filtering — see\n // FetchRequest.multiConstraints contract. The lookup miss here\n // performs the required filter, so just skip the row.\n continue;\n }\n // Children retain their original input order within the group\n // because we appended to `idxs` in iteration order.\n const relatedChildNodes: Node[] = idxs.map(i => childNodes[i]);\n yield* this.#yieldParentWithOverlay(node, relatedChildNodes);\n }\n }\n\n #fetchChunked(\n req: FetchRequest,\n incomingMultis: readonly MultiConstraint[],\n computedMulti: MultiConstraint,\n compare: (a: Node, b: Node) => number,\n ): Stream<Node | 'yield'> {\n const chunkStreams: Stream<Node | 'yield'>[] = [];\n for (let i = 0; i < computedMulti.length; i += multiConstraintChunkSize) {\n chunkStreams.push(\n this.#parent.fetch({\n ...req,\n multiConstraints: [\n ...incomingMultis,\n computedMulti.slice(i, i + multiConstraintChunkSize),\n ],\n }),\n );\n }\n return mergeSortedStreams(chunkStreams, compare);\n }\n\n *#yieldParentWithOverlay(\n minParentNode: Node,\n relatedChildNodes: Node[],\n ): Stream<Node> {\n let overlaidRelatedChildNodes = relatedChildNodes;\n if (\n this.#inprogressChildChange &&\n this.#inprogressChildChangePosition &&\n isJoinMatch(\n this.#inprogressChildChange[ChangeIndex.NODE].row,\n this.#childKey,\n minParentNode.row,\n this.#parentKey,\n )\n ) {\n const hasInprogressChildChangeBeenPushedForMinParentNode =\n this.#parent\n .getSchema()\n .compareRows(\n minParentNode.row,\n this.#inprogressChildChangePosition,\n ) <= 0;\n if (this.#inprogressChildChange[ChangeIndex.TYPE] === ChangeType.REMOVE) {\n if (hasInprogressChildChangeBeenPushedForMinParentNode) {\n // Remove from relatedChildNodes since the removed child\n // was inserted into childNodes above.\n overlaidRelatedChildNodes = relatedChildNodes.filter(\n n => n !== this.#inprogressChildChange?.[ChangeIndex.NODE],\n );\n }\n } else if (!hasInprogressChildChangeBeenPushedForMinParentNode) {\n overlaidRelatedChildNodes = [\n ...generateWithOverlayNoYield(\n relatedChildNodes,\n this.#inprogressChildChange,\n this.#child.getSchema(),\n ),\n ];\n }\n }\n\n // yield node if after the overlay it still has relationship nodes\n if (overlaidRelatedChildNodes.length > 0) {\n yield {\n ...minParentNode,\n relationships: {\n ...minParentNode.relationships,\n [this.#relationshipName]: () => overlaidRelatedChildNodes,\n },\n };\n }\n }\n\n *#pushChild(change: Change): Stream<'yield'> {\n switch (change[ChangeIndex.TYPE]) {\n case ChangeType.ADD:\n case ChangeType.REMOVE:\n yield* this.#pushChildChange(change);\n break;\n case ChangeType.EDIT: {\n assert(\n rowEqualsForCompoundKey(\n change[ChangeIndex.OLD_NODE].row,\n change[ChangeIndex.NODE].row,\n this.#childKey,\n ),\n `Child edit must not change relationship.`,\n );\n yield* this.#pushChildChange(change, true);\n break;\n }\n case ChangeType.CHILD:\n yield* this.#pushChildChange(change, true);\n break;\n }\n }\n\n *#pushChildChange(change: Change, exists?: boolean): Stream<'yield'> {\n this.#inprogressChildChange = change;\n this.#inprogressChildChangePosition = undefined;\n try {\n const constraint = buildJoinConstraint(\n change[ChangeIndex.NODE].row,\n this.#childKey,\n this.#parentKey,\n );\n const parentNodeStream = constraint\n ? this.#parent.fetch({constraint})\n : [];\n for (const parentNode of parentNodeStream) {\n if (parentNode === 'yield') {\n yield 'yield';\n continue;\n }\n this.#inprogressChildChange = change;\n this.#inprogressChildChangePosition = parentNode.row;\n const childNodeStream = () => {\n const constraint = buildJoinConstraint(\n parentNode.row,\n this.#parentKey,\n this.#childKey,\n );\n return constraint ? this.#child.fetch({constraint}) : [];\n };\n if (!exists) {\n for (const childNode of childNodeStream()) {\n if (childNode === 'yield') {\n yield 'yield';\n continue;\n }\n if (\n this.#child\n .getSchema()\n .compareRows(childNode.row, change[ChangeIndex.NODE].row) !== 0\n ) {\n exists = true;\n break;\n }\n }\n }\n if (exists) {\n yield* this.#output.push(\n makeChildChange(\n {\n ...parentNode,\n relationships: {\n ...parentNode.relationships,\n [this.#relationshipName]: childNodeStream,\n },\n },\n {\n relationshipName: this.#relationshipName,\n change,\n },\n ),\n this,\n );\n } else {\n const newNode = {\n ...parentNode,\n relationships: {\n ...parentNode.relationships,\n [this.#relationshipName]: () => [change[ChangeIndex.NODE]],\n },\n };\n yield* this.#output.push(\n change[ChangeIndex.TYPE] === ChangeType.ADD\n ? makeAddChange(newNode)\n : makeRemoveChange(newNode),\n this,\n );\n }\n }\n } finally {\n this.#inprogressChildChange = undefined;\n }\n }\n\n *#pushParent(change: Change): Stream<'yield'> {\n const childNodeStream = (node: Node) => () => {\n const constraint = buildJoinConstraint(\n node.row,\n this.#parentKey,\n this.#childKey,\n );\n return constraint ? this.#child.fetch({constraint}) : [];\n };\n\n const flip = (node: Node) => ({\n ...node,\n relationships: {\n ...node.relationships,\n [this.#relationshipName]: childNodeStream(node),\n },\n });\n\n // If no related child don't push as this is an inner join.\n let hasRelatedChild = false;\n for (const node of childNodeStream(change[ChangeIndex.NODE])()) {\n if (node === 'yield') {\n yield 'yield';\n continue;\n } else {\n hasRelatedChild = true;\n break;\n }\n }\n if (!hasRelatedChild) {\n return;\n }\n\n switch (change[ChangeIndex.TYPE]) {\n case ChangeType.ADD:\n yield* this.#output.push(\n makeAddChange(flip(change[ChangeIndex.NODE])),\n this,\n );\n break;\n case ChangeType.REMOVE:\n yield* this.#output.push(\n makeRemoveChange(flip(change[ChangeIndex.NODE])),\n this,\n );\n break;\n case ChangeType.CHILD: {\n yield* this.#output.push(\n makeChildChange(\n flip(change[ChangeIndex.NODE]),\n change[ChangeIndex.CHILD_DATA],\n ),\n this,\n );\n break;\n }\n case ChangeType.EDIT: {\n assert(\n rowEqualsForCompoundKey(\n change[ChangeIndex.OLD_NODE].row,\n change[ChangeIndex.NODE].row,\n this.#parentKey,\n ),\n `Parent edit must not change relationship.`,\n );\n yield* this.#output.push(\n makeEditChange(\n flip(change[ChangeIndex.NODE]),\n flip(change[ChangeIndex.OLD_NODE]),\n ),\n this,\n );\n break;\n }\n default:\n unreachable(change);\n }\n }\n}\n\n// Test seam with a widened record type — canonicalValue handles bigint\n// at runtime (zqlite's safeIntegers) but `Value` doesn't list it.\nexport function canonicalKeyForTest(\n record: Record<string, Value | bigint | undefined>,\n keys: CompoundKey,\n): string {\n return canonicalKey(record as Record<string, Value | undefined>, keys);\n}\n\n/**\n * Canonical string key over `keys` of `record`, used by `#fetchBatched`\n * both to dedupe `multiConstraint` entries (record = Constraint) and to\n * map each returned parent row back to the children that referenced its\n * parent-key tuple (record = Row).\n */\nfunction canonicalKey(\n record: Record<string, Value | undefined>,\n keys: CompoundKey,\n): string {\n if (keys.length === 1) {\n return canonicalValue(record[keys[0]]);\n }\n let s = '';\n for (let i = 0; i < keys.length; i++) {\n if (i > 0) s += '\\x00';\n s += canonicalValue(record[keys[i]]);\n }\n return s;\n}\n\nfunction canonicalValue(v: Value | bigint | undefined): string {\n // Tag by type so we don't conflate e.g. `1` (number) with `\"1\"` (string).\n // Bigint shows up at runtime when zqlite's safeIntegers is on, even\n // though the static `Value` type doesn't list it.\n if (v === null || v === undefined) return 'n';\n const t = typeof v;\n if (t === 'string') return 's' + (v as string);\n if (t === 'number') return 'd' + (v as number);\n if (t === 'bigint') return 'b' + (v as bigint).toString();\n if (t === 'boolean') return v ? 't' : 'f';\n return 'j' + JSON.stringify(v);\n}\n"],"mappings":"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"}
@@ -6,5 +6,5 @@ import type { InputBase, Output } from './operator.ts';
6
6
  * should be present based on the row's data. It then splits the change and
7
7
  * pushes the appropriate changes to the output based on the predicate.
8
8
  */
9
- export declare function maybeSplitAndPushEditChange(change: EditChange, predicate: (row: Row) => boolean, output: Output, pusher: InputBase): Generator<"yield", void, any>;
9
+ export declare function maybeSplitAndPushEditChange(change: EditChange, predicate: (row: Row) => boolean, output: Output, pusher: InputBase): import("./stream.ts").Stream<"yield">;
10
10
  //# sourceMappingURL=maybe-split-and-push-edit-change.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"maybe-split-and-push-edit-change.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/maybe-split-and-push-edit-change.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAE5D,OAAO,EAAkC,KAAK,UAAU,EAAC,MAAM,aAAa,CAAC;AAC7E,OAAO,KAAK,EAAC,SAAS,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;AAErD;;;;GAIG;AACH,wBAAiB,2BAA2B,CAC1C,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,EAChC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,SAAS,iCAYlB"}
1
+ {"version":3,"file":"maybe-split-and-push-edit-change.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/maybe-split-and-push-edit-change.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAE5D,OAAO,EAAkC,KAAK,UAAU,EAAC,MAAM,aAAa,CAAC;AAC7E,OAAO,KAAK,EAAC,SAAS,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;AAErD;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,EAChC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,SAAS,yCAgBlB"}
@@ -1,3 +1,4 @@
1
+ import { emptyArray } from "../../../shared/src/sentinels.js";
1
2
  import { makeAddChange, makeRemoveChange } from "./change.js";
2
3
  //#region ../zql/src/ivm/maybe-split-and-push-edit-change.ts
3
4
  /**
@@ -5,12 +6,13 @@ import { makeAddChange, makeRemoveChange } from "./change.js";
5
6
  * should be present based on the row's data. It then splits the change and
6
7
  * pushes the appropriate changes to the output based on the predicate.
7
8
  */
8
- function* maybeSplitAndPushEditChange(change, predicate, output, pusher) {
9
+ function maybeSplitAndPushEditChange(change, predicate, output, pusher) {
9
10
  const oldWasPresent = predicate(change[2].row);
10
11
  const newIsPresent = predicate(change[1].row);
11
- if (oldWasPresent && newIsPresent) yield* output.push(change, pusher);
12
- else if (oldWasPresent && !newIsPresent) yield* output.push(makeRemoveChange(change[2]), pusher);
13
- else if (!oldWasPresent && newIsPresent) yield* output.push(makeAddChange(change[1]), pusher);
12
+ if (oldWasPresent && newIsPresent) return output.push(change, pusher);
13
+ if (oldWasPresent && !newIsPresent) return output.push(makeRemoveChange(change[2]), pusher);
14
+ if (!oldWasPresent && newIsPresent) return output.push(makeAddChange(change[1]), pusher);
15
+ return emptyArray;
14
16
  }
15
17
  //#endregion
16
18
  export { maybeSplitAndPushEditChange };
@@ -1 +1 @@
1
- {"version":3,"file":"maybe-split-and-push-edit-change.js","names":[],"sources":["../../../../../zql/src/ivm/maybe-split-and-push-edit-change.ts"],"sourcesContent":["import type {Row} from '../../../zero-protocol/src/data.ts';\nimport {ChangeIndex} from './change-index.ts';\nimport {makeAddChange, makeRemoveChange, type EditChange} from './change.ts';\nimport type {InputBase, Output} from './operator.ts';\n\n/**\n * This takes an {@linkcode EditChange} and a predicate that determines if a row\n * should be present based on the row's data. It then splits the change and\n * pushes the appropriate changes to the output based on the predicate.\n */\nexport function* maybeSplitAndPushEditChange(\n change: EditChange,\n predicate: (row: Row) => boolean,\n output: Output,\n pusher: InputBase,\n) {\n const oldWasPresent = predicate(change[ChangeIndex.OLD_NODE].row);\n const newIsPresent = predicate(change[ChangeIndex.NODE].row);\n\n if (oldWasPresent && newIsPresent) {\n yield* output.push(change, pusher);\n } else if (oldWasPresent && !newIsPresent) {\n yield* output.push(makeRemoveChange(change[ChangeIndex.OLD_NODE]), pusher);\n } else if (!oldWasPresent && newIsPresent) {\n yield* output.push(makeAddChange(change[ChangeIndex.NODE]), pusher);\n }\n}\n"],"mappings":";;;;;;;AAUA,UAAiB,4BACf,QACA,WACA,QACA,QACA;CACA,MAAM,gBAAgB,UAAU,OAAO,GAAsB,GAAG;CAChE,MAAM,eAAe,UAAU,OAAO,GAAkB,GAAG;CAE3D,IAAI,iBAAiB,cACnB,OAAO,OAAO,KAAK,QAAQ,MAAM;MAC5B,IAAI,iBAAiB,CAAC,cAC3B,OAAO,OAAO,KAAK,iBAAiB,OAAO,EAAqB,GAAG,MAAM;MACpE,IAAI,CAAC,iBAAiB,cAC3B,OAAO,OAAO,KAAK,cAAc,OAAO,EAAiB,GAAG,MAAM;AAEtE"}
1
+ {"version":3,"file":"maybe-split-and-push-edit-change.js","names":[],"sources":["../../../../../zql/src/ivm/maybe-split-and-push-edit-change.ts"],"sourcesContent":["import {emptyArray} from '../../../shared/src/sentinels.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport {ChangeIndex} from './change-index.ts';\nimport {makeAddChange, makeRemoveChange, type EditChange} from './change.ts';\nimport type {InputBase, Output} from './operator.ts';\n\n/**\n * This takes an {@linkcode EditChange} and a predicate that determines if a row\n * should be present based on the row's data. It then splits the change and\n * pushes the appropriate changes to the output based on the predicate.\n */\nexport function maybeSplitAndPushEditChange(\n change: EditChange,\n predicate: (row: Row) => boolean,\n output: Output,\n pusher: InputBase,\n) {\n const oldWasPresent = predicate(change[ChangeIndex.OLD_NODE].row);\n const newIsPresent = predicate(change[ChangeIndex.NODE].row);\n\n if (oldWasPresent && newIsPresent) {\n return output.push(change, pusher);\n }\n if (oldWasPresent && !newIsPresent) {\n return output.push(makeRemoveChange(change[ChangeIndex.OLD_NODE]), pusher);\n }\n if (!oldWasPresent && newIsPresent) {\n return output.push(makeAddChange(change[ChangeIndex.NODE]), pusher);\n }\n\n return emptyArray;\n}\n"],"mappings":";;;;;;;;AAWA,SAAgB,4BACd,QACA,WACA,QACA,QACA;CACA,MAAM,gBAAgB,UAAU,OAAO,GAAsB,GAAG;CAChE,MAAM,eAAe,UAAU,OAAO,GAAkB,GAAG;CAE3D,IAAI,iBAAiB,cACnB,OAAO,OAAO,KAAK,QAAQ,MAAM;CAEnC,IAAI,iBAAiB,CAAC,cACpB,OAAO,OAAO,KAAK,iBAAiB,OAAO,EAAqB,GAAG,MAAM;CAE3E,IAAI,CAAC,iBAAiB,cACpB,OAAO,OAAO,KAAK,cAAc,OAAO,EAAiB,GAAG,MAAM;CAGpE,OAAO;AACT"}
@@ -75,7 +75,7 @@ export declare function generateWithStart(nodes: Iterable<Node | 'yield'>, start
75
75
  * is what #4926 fixed for `generateWithStart`; this parameter is the same
76
76
  * distinction for the overlay's own `startAt` pruning.
77
77
  */
78
- export declare function generateWithOverlay(startAt: Row | undefined, rows: Iterable<Row>, constraint: Constraint | undefined, overlay: Overlay | undefined, lastPushedEpoch: number, compare: Comparator, startAtCompare: Comparator, filterPredicate?: (row: Row) => boolean | undefined, multiConstraints?: readonly MultiConstraint[] | undefined): Generator<{
78
+ export declare function generateWithOverlay(startAt: Row | undefined, rows: Iterable<Row>, constraint: Constraint | undefined, overlay: Overlay | undefined, lastPushedEpoch: number, compare: Comparator, startAtCompare: Comparator, filterPredicate?: (row: Row) => boolean | undefined, multiConstraints?: readonly MultiConstraint[]): Generator<{
79
79
  row: Readonly<Record<string, Value>>;
80
80
  relationships: {};
81
81
  }, void, unknown>;
@@ -94,7 +94,7 @@ export declare function generateWithOverlayInner(rowIterator: Iterable<Row>, ove
94
94
  * No `startAt` or comparator needed. Injects remove/old-edit rows eagerly
95
95
  * at the start, and suppresses add/new-edit rows inline by PK match.
96
96
  */
97
- export declare function generateWithOverlayUnordered(rows: Iterable<Row>, constraint: Constraint | undefined, overlay: Overlay | undefined, lastPushedEpoch: number, primaryKey: PrimaryKey, filterPredicate?: (row: Row) => boolean, multiConstraints?: readonly MultiConstraint[] | undefined): Generator<{
97
+ export declare function generateWithOverlayUnordered(rows: Iterable<Row>, constraint: Constraint | undefined, overlay: Overlay | undefined, lastPushedEpoch: number, primaryKey: PrimaryKey, filterPredicate?: (row: Row) => boolean, multiConstraints?: readonly MultiConstraint[]): Generator<{
98
98
  row: Readonly<Record<string, Value>>;
99
99
  relationships: {};
100
100
  }, void, unknown>;
@@ -1 +1 @@
1
- {"version":3,"file":"memory-source.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/memory-source.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory-source.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/memory-source.ts"],"names":[],"mappings":"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"}
@@ -211,12 +211,12 @@ var MemorySource = class MemorySource {
211
211
  *push(change) {
212
212
  for (const result of this.genPush(change)) if (result === "yield") yield result;
213
213
  }
214
- *genPush(change) {
214
+ genPush(change) {
215
215
  const { data } = this.#getPrimaryIndex();
216
216
  const exists = (row) => data.has(row);
217
217
  const setOverlay = (o) => this.#overlay = o;
218
218
  const writeChange = (c) => this.#writeChange(c);
219
- yield* genPushAndWriteWithSplitEdit(this.#connections, change, exists, setOverlay, writeChange, () => ++this.#pushEpoch);
219
+ return genPushAndWriteWithSplitEdit(this.#connections, change, exists, setOverlay, writeChange, () => ++this.#pushEpoch);
220
220
  }
221
221
  #writeChange(change) {
222
222
  for (const { data } of this.#indexes.values()) switch (change[0]) {
@@ -348,10 +348,10 @@ function* generateWithStart(nodes, start, compare) {
348
348
  * is what #4926 fixed for `generateWithStart`; this parameter is the same
349
349
  * distinction for the overlay's own `startAt` pruning.
350
350
  */
351
- function* generateWithOverlay(startAt, rows, constraint, overlay, lastPushedEpoch, compare, startAtCompare, filterPredicate, multiConstraints) {
351
+ function generateWithOverlay(startAt, rows, constraint, overlay, lastPushedEpoch, compare, startAtCompare, filterPredicate, multiConstraints) {
352
352
  let overlayToApply = void 0;
353
353
  if (overlay && lastPushedEpoch >= overlay.epoch) overlayToApply = overlay;
354
- yield* generateWithOverlayInner(rows, computeOverlays(startAt, constraint, overlayToApply, startAtCompare, filterPredicate, multiConstraints), compare);
354
+ return generateWithOverlayInner(rows, computeOverlays(startAt, constraint, overlayToApply, startAtCompare, filterPredicate, multiConstraints), compare);
355
355
  }
356
356
  function computeOverlays(startAt, constraint, overlay, startAtCompare, filterPredicate, multiConstraints) {
357
357
  let overlays = {
@@ -455,7 +455,7 @@ function* generateWithOverlayInner(rowIterator, overlays, compare) {
455
455
  * No `startAt` or comparator needed. Injects remove/old-edit rows eagerly
456
456
  * at the start, and suppresses add/new-edit rows inline by PK match.
457
457
  */
458
- function* generateWithOverlayUnordered(rows, constraint, overlay, lastPushedEpoch, primaryKey, filterPredicate, multiConstraints) {
458
+ function generateWithOverlayUnordered(rows, constraint, overlay, lastPushedEpoch, primaryKey, filterPredicate, multiConstraints) {
459
459
  let overlayToApply = void 0;
460
460
  if (overlay && lastPushedEpoch >= overlay.epoch) overlayToApply = overlay;
461
461
  let overlays = {
@@ -485,7 +485,7 @@ function* generateWithOverlayUnordered(rows, constraint, overlay, lastPushedEpoc
485
485
  if (constraint) overlays = overlaysForConstraint(overlays, constraint);
486
486
  overlays = applyMultiConstraintsToOverlays(overlays, multiConstraints);
487
487
  if (filterPredicate) overlays = overlaysForFilterPredicate(overlays, filterPredicate);
488
- yield* generateWithOverlayInnerUnordered(rows, overlays, primaryKey);
488
+ return generateWithOverlayInnerUnordered(rows, overlays, primaryKey);
489
489
  }
490
490
  function* generateWithOverlayInnerUnordered(rowIterator, overlays, primaryKey) {
491
491
  if (overlays.add) yield {
@@ -534,8 +534,8 @@ function compareBounds(a, b) {
534
534
  if (typeof b === "symbol") return b === minValue ? 1 : -1;
535
535
  return compareValues(a, b);
536
536
  }
537
- function* generateRows(data, scanStart, reverse) {
538
- yield* data[reverse ? "valuesFromReversed" : "valuesFrom"](scanStart);
537
+ function generateRows(data, scanStart, reverse) {
538
+ return reverse ? data.valuesFromReversed(scanStart) : data.valuesFrom(scanStart);
539
539
  }
540
540
  function stringify(change) {
541
541
  return JSON.stringify(change, (_, v) => typeof v === "bigint" ? v.toString() : v);
@@ -560,7 +560,7 @@ function stringify(change) {
560
560
  */
561
561
  function* mergeSortedStreams(streams, compare) {
562
562
  const iterators = streams.map((s) => s[Symbol.iterator]());
563
- const active = new Array(iterators.length).fill(true);
563
+ const active = Array.from({ length: iterators.length }).fill(true);
564
564
  const heap = [];
565
565
  const siftUp = (start) => {
566
566
  let i = start;