@rocicorp/zero 0.25.0-canary.9 → 0.25.1

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 (517) hide show
  1. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  2. package/out/analyze-query/src/run-ast.d.ts +1 -1
  3. package/out/analyze-query/src/run-ast.d.ts.map +1 -1
  4. package/out/analyze-query/src/run-ast.js +10 -8
  5. package/out/analyze-query/src/run-ast.js.map +1 -1
  6. package/out/otel/src/log-options.d.ts +1 -1
  7. package/out/otel/src/log-options.d.ts.map +1 -1
  8. package/out/otel/src/log-options.js +0 -1
  9. package/out/otel/src/log-options.js.map +1 -1
  10. package/out/replicache/src/persist/idb-databases-store.d.ts +1 -0
  11. package/out/replicache/src/persist/idb-databases-store.d.ts.map +1 -1
  12. package/out/replicache/src/persist/idb-databases-store.js +13 -2
  13. package/out/replicache/src/persist/idb-databases-store.js.map +1 -1
  14. package/out/shared/src/deep-merge.d.ts +6 -4
  15. package/out/shared/src/deep-merge.d.ts.map +1 -1
  16. package/out/shared/src/deep-merge.js +2 -1
  17. package/out/shared/src/deep-merge.js.map +1 -1
  18. package/out/shared/src/iterables.d.ts +0 -1
  19. package/out/shared/src/iterables.d.ts.map +1 -1
  20. package/out/shared/src/iterables.js +0 -34
  21. package/out/shared/src/iterables.js.map +1 -1
  22. package/out/shared/src/options-types.d.ts +113 -0
  23. package/out/shared/src/options-types.d.ts.map +1 -0
  24. package/out/shared/src/options.d.ts +2 -111
  25. package/out/shared/src/options.d.ts.map +1 -1
  26. package/out/shared/src/options.js.map +1 -1
  27. package/out/shared/src/record-proxy.d.ts +13 -0
  28. package/out/shared/src/record-proxy.d.ts.map +1 -0
  29. package/out/shared/src/record-proxy.js +59 -0
  30. package/out/shared/src/record-proxy.js.map +1 -0
  31. package/out/z2s/src/compiler.d.ts.map +1 -1
  32. package/out/z2s/src/compiler.js +4 -2
  33. package/out/z2s/src/compiler.js.map +1 -1
  34. package/out/zero/package.json.js +1 -1
  35. package/out/zero/src/adapters/drizzle.d.ts +1 -1
  36. package/out/zero/src/adapters/drizzle.d.ts.map +1 -1
  37. package/out/zero/src/adapters/drizzle.js +4 -1
  38. package/out/zero/src/bindings.d.ts +2 -0
  39. package/out/zero/src/bindings.d.ts.map +1 -0
  40. package/out/zero/src/bindings.js +27 -0
  41. package/out/zero/src/bindings.js.map +1 -0
  42. package/out/zero/src/pg.js +7 -5
  43. package/out/zero/src/react.js +2 -4
  44. package/out/zero/src/react.js.map +1 -1
  45. package/out/zero/src/server.js +7 -5
  46. package/out/zero/src/solid.js +2 -2
  47. package/out/zero/src/zero-cache-dev.js +11 -5
  48. package/out/zero/src/zero-cache-dev.js.map +1 -1
  49. package/out/zero/src/zero.js +6 -6
  50. package/out/zero-cache/src/auth/read-authorizer.d.ts +1 -1
  51. package/out/zero-cache/src/auth/read-authorizer.d.ts.map +1 -1
  52. package/out/zero-cache/src/auth/read-authorizer.js +1 -1
  53. package/out/zero-cache/src/auth/read-authorizer.js.map +1 -1
  54. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  55. package/out/zero-cache/src/auth/write-authorizer.js +25 -17
  56. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  57. package/out/zero-cache/src/config/zero-config.d.ts +40 -4
  58. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  59. package/out/zero-cache/src/config/zero-config.js +58 -19
  60. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  61. package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
  62. package/out/zero-cache/src/db/transaction-pool.js +3 -6
  63. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  64. package/out/zero-cache/src/scripts/deploy-permissions.js +6 -3
  65. package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
  66. package/out/zero-cache/src/scripts/permissions.d.ts.map +1 -1
  67. package/out/zero-cache/src/scripts/permissions.js +11 -13
  68. package/out/zero-cache/src/scripts/permissions.js.map +1 -1
  69. package/out/zero-cache/src/server/anonymous-otel-start.d.ts +10 -1
  70. package/out/zero-cache/src/server/anonymous-otel-start.d.ts.map +1 -1
  71. package/out/zero-cache/src/server/anonymous-otel-start.js +34 -18
  72. package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
  73. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  74. package/out/zero-cache/src/server/change-streamer.js +2 -8
  75. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  76. package/out/zero-cache/src/server/otel-diag-logger.d.ts.map +1 -1
  77. package/out/zero-cache/src/server/otel-diag-logger.js +1 -21
  78. package/out/zero-cache/src/server/otel-diag-logger.js.map +1 -1
  79. package/out/zero-cache/src/server/otel-start.d.ts.map +1 -1
  80. package/out/zero-cache/src/server/otel-start.js +1 -5
  81. package/out/zero-cache/src/server/otel-start.js.map +1 -1
  82. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  83. package/out/zero-cache/src/server/syncer.js +7 -1
  84. package/out/zero-cache/src/server/syncer.js.map +1 -1
  85. package/out/zero-cache/src/services/analyze.d.ts +2 -2
  86. package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
  87. package/out/zero-cache/src/services/analyze.js +55 -42
  88. package/out/zero-cache/src/services/analyze.js.map +1 -1
  89. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  90. package/out/zero-cache/src/services/change-source/pg/change-source.js +62 -42
  91. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  92. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts.map +1 -1
  93. package/out/zero-cache/src/services/change-source/pg/schema/published.js +3 -2
  94. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  95. package/out/zero-cache/src/services/change-source/protocol/current/control.d.ts +1 -0
  96. package/out/zero-cache/src/services/change-source/protocol/current/control.d.ts.map +1 -1
  97. package/out/zero-cache/src/services/change-source/protocol/current/control.js +5 -1
  98. package/out/zero-cache/src/services/change-source/protocol/current/control.js.map +1 -1
  99. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +2 -0
  100. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
  101. package/out/zero-cache/src/services/change-source/protocol/current/json.d.ts +8 -0
  102. package/out/zero-cache/src/services/change-source/protocol/current/json.d.ts.map +1 -0
  103. package/out/zero-cache/src/services/change-source/protocol/current/json.js +19 -0
  104. package/out/zero-cache/src/services/change-source/protocol/current/json.js.map +1 -0
  105. package/out/zero-cache/src/services/change-source/protocol/current.d.ts +1 -0
  106. package/out/zero-cache/src/services/change-source/protocol/current.d.ts.map +1 -1
  107. package/out/zero-cache/src/services/change-source/protocol/current.js +3 -0
  108. package/out/zero-cache/src/services/change-source/protocol/current.js.map +1 -1
  109. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +0 -2
  110. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  111. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +0 -5
  112. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  113. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  114. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +8 -1
  115. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  116. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  117. package/out/zero-cache/src/services/change-streamer/storer.js +2 -3
  118. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  119. package/out/zero-cache/src/services/http-service.d.ts +0 -1
  120. package/out/zero-cache/src/services/http-service.d.ts.map +1 -1
  121. package/out/zero-cache/src/services/http-service.js +0 -4
  122. package/out/zero-cache/src/services/http-service.js.map +1 -1
  123. package/out/zero-cache/src/services/litestream/commands.js +3 -2
  124. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  125. package/out/zero-cache/src/services/mutagen/pusher.d.ts +4 -4
  126. package/out/zero-cache/src/services/replicator/replication-status.d.ts +2 -0
  127. package/out/zero-cache/src/services/replicator/replication-status.d.ts.map +1 -1
  128. package/out/zero-cache/src/services/replicator/replication-status.js +14 -1
  129. package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
  130. package/out/zero-cache/src/services/run-ast.d.ts +1 -1
  131. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  132. package/out/zero-cache/src/services/run-ast.js +5 -1
  133. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  134. package/out/zero-cache/src/services/view-syncer/active-users-gauge.d.ts +2 -1
  135. package/out/zero-cache/src/services/view-syncer/active-users-gauge.d.ts.map +1 -1
  136. package/out/zero-cache/src/services/view-syncer/active-users-gauge.js +26 -13
  137. package/out/zero-cache/src/services/view-syncer/active-users-gauge.js.map +1 -1
  138. package/out/zero-cache/src/services/view-syncer/cvr-purger.d.ts +1 -1
  139. package/out/zero-cache/src/services/view-syncer/cvr-purger.d.ts.map +1 -1
  140. package/out/zero-cache/src/services/view-syncer/cvr-purger.js +39 -15
  141. package/out/zero-cache/src/services/view-syncer/cvr-purger.js.map +1 -1
  142. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +4 -1
  143. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  144. package/out/zero-cache/src/services/view-syncer/cvr-store.js +31 -9
  145. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  146. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +3 -0
  147. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  148. package/out/zero-cache/src/services/view-syncer/cvr.js +11 -0
  149. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  150. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +1 -1
  151. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  152. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +11 -11
  153. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  154. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +81 -27
  155. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  156. package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts +1 -0
  157. package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts.map +1 -1
  158. package/out/zero-cache/src/services/view-syncer/schema/cvr.js +23 -10
  159. package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
  160. package/out/zero-cache/src/services/view-syncer/schema/init.d.ts.map +1 -1
  161. package/out/zero-cache/src/services/view-syncer/schema/init.js +31 -1
  162. package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
  163. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +2 -2
  164. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  165. package/out/zero-cache/src/services/view-syncer/snapshotter.js +19 -4
  166. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  167. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +2 -1
  168. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  169. package/out/zero-cache/src/services/view-syncer/view-syncer.js +31 -29
  170. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  171. package/out/zero-cache/src/workers/connect-params.d.ts +1 -0
  172. package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
  173. package/out/zero-cache/src/workers/connect-params.js +2 -0
  174. package/out/zero-cache/src/workers/connect-params.js.map +1 -1
  175. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  176. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +2 -0
  177. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  178. package/out/zero-client/src/client/bindings.d.ts +12 -42
  179. package/out/zero-client/src/client/bindings.d.ts.map +1 -1
  180. package/out/zero-client/src/client/connection-manager.d.ts +3 -3
  181. package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
  182. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  183. package/out/zero-client/src/client/connection.d.ts.map +1 -1
  184. package/out/zero-client/src/client/connection.js +8 -1
  185. package/out/zero-client/src/client/connection.js.map +1 -1
  186. package/out/zero-client/src/client/crud-impl.d.ts +11 -0
  187. package/out/zero-client/src/client/crud-impl.d.ts.map +1 -0
  188. package/out/zero-client/src/client/crud-impl.js +102 -0
  189. package/out/zero-client/src/client/crud-impl.js.map +1 -0
  190. package/out/zero-client/src/client/crud.d.ts +10 -42
  191. package/out/zero-client/src/client/crud.d.ts.map +1 -1
  192. package/out/zero-client/src/client/crud.js +28 -110
  193. package/out/zero-client/src/client/crud.js.map +1 -1
  194. package/out/zero-client/src/client/custom.d.ts +11 -6
  195. package/out/zero-client/src/client/custom.d.ts.map +1 -1
  196. package/out/zero-client/src/client/custom.js +12 -53
  197. package/out/zero-client/src/client/custom.js.map +1 -1
  198. package/out/zero-client/src/client/delete-clients-manager.d.ts +1 -1
  199. package/out/zero-client/src/client/delete-clients-manager.d.ts.map +1 -1
  200. package/out/zero-client/src/client/delete-clients-manager.js +30 -3
  201. package/out/zero-client/src/client/delete-clients-manager.js.map +1 -1
  202. package/out/zero-client/src/client/error.d.ts +6 -1
  203. package/out/zero-client/src/client/error.d.ts.map +1 -1
  204. package/out/zero-client/src/client/error.js +2 -2
  205. package/out/zero-client/src/client/error.js.map +1 -1
  206. package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
  207. package/out/zero-client/src/client/ivm-branch.js +20 -13
  208. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  209. package/out/zero-client/src/client/make-mutate-property.d.ts +6 -9
  210. package/out/zero-client/src/client/make-mutate-property.d.ts.map +1 -1
  211. package/out/zero-client/src/client/make-mutate-property.js +5 -10
  212. package/out/zero-client/src/client/make-mutate-property.js.map +1 -1
  213. package/out/zero-client/src/client/make-replicache-mutators.d.ts +2 -2
  214. package/out/zero-client/src/client/make-replicache-mutators.d.ts.map +1 -1
  215. package/out/zero-client/src/client/make-replicache-mutators.js +16 -11
  216. package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -1
  217. package/out/zero-client/src/client/mutator-proxy.d.ts +3 -2
  218. package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
  219. package/out/zero-client/src/client/mutator-proxy.js +16 -5
  220. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  221. package/out/zero-client/src/client/options.d.ts +5 -4
  222. package/out/zero-client/src/client/options.d.ts.map +1 -1
  223. package/out/zero-client/src/client/options.js.map +1 -1
  224. package/out/zero-client/src/client/version.js +1 -1
  225. package/out/zero-client/src/client/zero.d.ts +27 -13
  226. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  227. package/out/zero-client/src/client/zero.js +81 -40
  228. package/out/zero-client/src/client/zero.js.map +1 -1
  229. package/out/zero-client/src/mod.d.ts +17 -16
  230. package/out/zero-client/src/mod.d.ts.map +1 -1
  231. package/out/zero-events/src/status.d.ts +1 -1
  232. package/out/zero-events/src/status.d.ts.map +1 -1
  233. package/out/zero-protocol/src/analyze-query-result.d.ts +2 -2
  234. package/out/zero-protocol/src/analyze-query-result.js +2 -2
  235. package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
  236. package/out/zero-protocol/src/down.d.ts +2 -2
  237. package/out/zero-protocol/src/inspect-down.d.ts +6 -6
  238. package/out/zero-protocol/src/inspect-up.d.ts +4 -4
  239. package/out/zero-protocol/src/inspect-up.js +1 -1
  240. package/out/zero-protocol/src/inspect-up.js.map +1 -1
  241. package/out/zero-protocol/src/protocol-version.d.ts +1 -1
  242. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  243. package/out/zero-protocol/src/protocol-version.js +1 -1
  244. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  245. package/out/zero-protocol/src/up.d.ts +1 -1
  246. package/out/zero-react/src/bindings.d.ts +2 -0
  247. package/out/zero-react/src/bindings.d.ts.map +1 -0
  248. package/out/zero-react/src/mod.d.ts +1 -10
  249. package/out/zero-react/src/mod.d.ts.map +1 -1
  250. package/out/zero-react/src/{use-zero-connection-state.d.ts → use-connection-state.d.ts} +3 -3
  251. package/out/zero-react/src/use-connection-state.d.ts.map +1 -0
  252. package/out/zero-react/src/{use-zero-connection-state.js → use-connection-state.js} +3 -3
  253. package/out/zero-react/src/use-connection-state.js.map +1 -0
  254. package/out/zero-react/src/use-query.d.ts +4 -10
  255. package/out/zero-react/src/use-query.d.ts.map +1 -1
  256. package/out/zero-react/src/use-query.js +26 -21
  257. package/out/zero-react/src/use-query.js.map +1 -1
  258. package/out/zero-react/src/use-zero-online.d.ts +1 -1
  259. package/out/zero-react/src/use-zero-online.js.map +1 -1
  260. package/out/zero-react/src/zero-provider.d.ts +17 -10
  261. package/out/zero-react/src/zero-provider.d.ts.map +1 -1
  262. package/out/zero-react/src/zero-provider.js +19 -1
  263. package/out/zero-react/src/zero-provider.js.map +1 -1
  264. package/out/zero-react/src/zero.d.ts +2 -0
  265. package/out/zero-react/src/zero.d.ts.map +1 -0
  266. package/out/zero-schema/src/compiled-permissions.d.ts +22 -2
  267. package/out/zero-schema/src/compiled-permissions.d.ts.map +1 -1
  268. package/out/zero-schema/src/compiled-permissions.js +7 -6
  269. package/out/zero-schema/src/compiled-permissions.js.map +1 -1
  270. package/out/zero-schema/src/permissions.d.ts +11 -8
  271. package/out/zero-schema/src/permissions.d.ts.map +1 -1
  272. package/out/zero-schema/src/permissions.js +2 -8
  273. package/out/zero-schema/src/permissions.js.map +1 -1
  274. package/out/zero-schema/src/schema-config.d.ts +0 -5
  275. package/out/zero-schema/src/schema-config.d.ts.map +1 -1
  276. package/out/zero-schema/src/schema-config.js +1 -1
  277. package/out/zero-schema/src/schema-config.js.map +1 -1
  278. package/out/zero-server/src/custom.d.ts +41 -14
  279. package/out/zero-server/src/custom.d.ts.map +1 -1
  280. package/out/zero-server/src/custom.js +129 -37
  281. package/out/zero-server/src/custom.js.map +1 -1
  282. package/out/zero-server/src/mod.d.ts +1 -1
  283. package/out/zero-server/src/mod.d.ts.map +1 -1
  284. package/out/zero-server/src/process-mutations.d.ts +10 -6
  285. package/out/zero-server/src/process-mutations.d.ts.map +1 -1
  286. package/out/zero-server/src/process-mutations.js +9 -18
  287. package/out/zero-server/src/process-mutations.js.map +1 -1
  288. package/out/zero-server/src/push-processor.d.ts.map +1 -1
  289. package/out/zero-server/src/push-processor.js +10 -8
  290. package/out/zero-server/src/push-processor.js.map +1 -1
  291. package/out/zero-server/src/queries/process-queries.d.ts +14 -2
  292. package/out/zero-server/src/queries/process-queries.d.ts.map +1 -1
  293. package/out/zero-server/src/queries/process-queries.js +18 -15
  294. package/out/zero-server/src/queries/process-queries.js.map +1 -1
  295. package/out/zero-server/src/zql-database.d.ts +6 -6
  296. package/out/zero-server/src/zql-database.d.ts.map +1 -1
  297. package/out/zero-server/src/zql-database.js +5 -17
  298. package/out/zero-server/src/zql-database.js.map +1 -1
  299. package/out/zero-solid/src/bindings.d.ts +2 -0
  300. package/out/zero-solid/src/bindings.d.ts.map +1 -0
  301. package/out/zero-solid/src/mod.d.ts +1 -8
  302. package/out/zero-solid/src/mod.d.ts.map +1 -1
  303. package/out/zero-solid/src/solid-view.d.ts +3 -5
  304. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  305. package/out/zero-solid/src/solid-view.js +9 -6
  306. package/out/zero-solid/src/solid-view.js.map +1 -1
  307. package/out/zero-solid/src/{use-zero-connection-state.d.ts → use-connection-state.d.ts} +3 -3
  308. package/out/zero-solid/src/use-connection-state.d.ts.map +1 -0
  309. package/out/zero-solid/src/{use-zero-connection-state.js → use-connection-state.js} +3 -3
  310. package/out/zero-solid/src/use-connection-state.js.map +1 -0
  311. package/out/zero-solid/src/use-query.d.ts +3 -6
  312. package/out/zero-solid/src/use-query.d.ts.map +1 -1
  313. package/out/zero-solid/src/use-query.js +44 -11
  314. package/out/zero-solid/src/use-query.js.map +1 -1
  315. package/out/zero-solid/src/use-zero-online.d.ts +1 -1
  316. package/out/zero-solid/src/use-zero-online.js.map +1 -1
  317. package/out/zero-solid/src/use-zero.d.ts +19 -9
  318. package/out/zero-solid/src/use-zero.d.ts.map +1 -1
  319. package/out/zero-solid/src/use-zero.js +17 -1
  320. package/out/zero-solid/src/use-zero.js.map +1 -1
  321. package/out/zero-solid/src/zero.d.ts +2 -0
  322. package/out/zero-solid/src/zero.d.ts.map +1 -0
  323. package/out/zero-types/src/default-types.d.ts +38 -0
  324. package/out/zero-types/src/default-types.d.ts.map +1 -0
  325. package/out/zero-types/src/schema.d.ts +4 -4
  326. package/out/zql/src/builder/builder.d.ts.map +1 -1
  327. package/out/zql/src/builder/builder.js +1 -13
  328. package/out/zql/src/builder/builder.js.map +1 -1
  329. package/out/zql/src/error.js +1 -10
  330. package/out/zql/src/error.js.map +1 -1
  331. package/out/zql/src/ivm/array-view.d.ts +2 -2
  332. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  333. package/out/zql/src/ivm/array-view.js +4 -1
  334. package/out/zql/src/ivm/array-view.js.map +1 -1
  335. package/out/zql/src/ivm/data.d.ts +7 -2
  336. package/out/zql/src/ivm/data.d.ts.map +1 -1
  337. package/out/zql/src/ivm/data.js +0 -8
  338. package/out/zql/src/ivm/data.js.map +1 -1
  339. package/out/zql/src/ivm/exists.d.ts +6 -4
  340. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  341. package/out/zql/src/ivm/exists.js +60 -91
  342. package/out/zql/src/ivm/exists.js.map +1 -1
  343. package/out/zql/src/ivm/fan-in.d.ts +5 -3
  344. package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
  345. package/out/zql/src/ivm/fan-in.js +12 -5
  346. package/out/zql/src/ivm/fan-in.js.map +1 -1
  347. package/out/zql/src/ivm/fan-out.d.ts +4 -2
  348. package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
  349. package/out/zql/src/ivm/fan-out.js +16 -6
  350. package/out/zql/src/ivm/fan-out.js.map +1 -1
  351. package/out/zql/src/ivm/filter-operators.d.ts +13 -11
  352. package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
  353. package/out/zql/src/ivm/filter-operators.js +27 -24
  354. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  355. package/out/zql/src/ivm/filter-push.d.ts +2 -1
  356. package/out/zql/src/ivm/filter-push.d.ts.map +1 -1
  357. package/out/zql/src/ivm/filter-push.js +5 -5
  358. package/out/zql/src/ivm/filter-push.js.map +1 -1
  359. package/out/zql/src/ivm/filter.d.ts +4 -2
  360. package/out/zql/src/ivm/filter.d.ts.map +1 -1
  361. package/out/zql/src/ivm/filter.js +10 -4
  362. package/out/zql/src/ivm/filter.js.map +1 -1
  363. package/out/zql/src/ivm/flipped-join.d.ts +1 -2
  364. package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
  365. package/out/zql/src/ivm/flipped-join.js +133 -103
  366. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  367. package/out/zql/src/ivm/join-utils.d.ts +9 -2
  368. package/out/zql/src/ivm/join-utils.d.ts.map +1 -1
  369. package/out/zql/src/ivm/join-utils.js +20 -0
  370. package/out/zql/src/ivm/join-utils.js.map +1 -1
  371. package/out/zql/src/ivm/join.d.ts +3 -16
  372. package/out/zql/src/ivm/join.d.ts.map +1 -1
  373. package/out/zql/src/ivm/join.js +62 -128
  374. package/out/zql/src/ivm/join.js.map +1 -1
  375. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
  376. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
  377. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +4 -4
  378. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  379. package/out/zql/src/ivm/memory-source.d.ts +7 -6
  380. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  381. package/out/zql/src/ivm/memory-source.js +39 -28
  382. package/out/zql/src/ivm/memory-source.js.map +1 -1
  383. package/out/zql/src/ivm/operator.d.ts +15 -12
  384. package/out/zql/src/ivm/operator.d.ts.map +1 -1
  385. package/out/zql/src/ivm/operator.js +8 -0
  386. package/out/zql/src/ivm/operator.js.map +1 -1
  387. package/out/zql/src/ivm/push-accumulated.d.ts +2 -2
  388. package/out/zql/src/ivm/push-accumulated.d.ts.map +1 -1
  389. package/out/zql/src/ivm/push-accumulated.js +8 -8
  390. package/out/zql/src/ivm/push-accumulated.js.map +1 -1
  391. package/out/zql/src/ivm/skip.d.ts +2 -3
  392. package/out/zql/src/ivm/skip.d.ts.map +1 -1
  393. package/out/zql/src/ivm/skip.js +14 -11
  394. package/out/zql/src/ivm/skip.js.map +1 -1
  395. package/out/zql/src/ivm/source.d.ts +15 -7
  396. package/out/zql/src/ivm/source.d.ts.map +1 -1
  397. package/out/zql/src/ivm/stream.d.ts +2 -0
  398. package/out/zql/src/ivm/stream.d.ts.map +1 -1
  399. package/out/zql/src/ivm/stream.js +5 -14
  400. package/out/zql/src/ivm/stream.js.map +1 -1
  401. package/out/zql/src/ivm/take.d.ts +2 -3
  402. package/out/zql/src/ivm/take.d.ts.map +1 -1
  403. package/out/zql/src/ivm/take.js +168 -140
  404. package/out/zql/src/ivm/take.js.map +1 -1
  405. package/out/zql/src/ivm/union-fan-in.d.ts +4 -4
  406. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  407. package/out/zql/src/ivm/union-fan-in.js +74 -15
  408. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  409. package/out/zql/src/ivm/union-fan-out.d.ts +2 -3
  410. package/out/zql/src/ivm/union-fan-out.d.ts.map +1 -1
  411. package/out/zql/src/ivm/union-fan-out.js +3 -6
  412. package/out/zql/src/ivm/union-fan-out.js.map +1 -1
  413. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  414. package/out/zql/src/ivm/view-apply-change.js +4 -4
  415. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  416. package/out/zql/src/ivm/view.d.ts +2 -2
  417. package/out/zql/src/ivm/view.d.ts.map +1 -1
  418. package/out/zql/src/mutate/crud.d.ts +116 -0
  419. package/out/zql/src/mutate/crud.d.ts.map +1 -0
  420. package/out/zql/src/mutate/crud.js +41 -0
  421. package/out/zql/src/mutate/crud.js.map +1 -0
  422. package/out/zql/src/mutate/custom.d.ts +24 -62
  423. package/out/zql/src/mutate/custom.d.ts.map +1 -1
  424. package/out/zql/src/mutate/custom.js +1 -5
  425. package/out/zql/src/mutate/custom.js.map +1 -1
  426. package/out/zql/src/mutate/mutator-registry.d.ts +43 -73
  427. package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
  428. package/out/zql/src/mutate/mutator-registry.js +25 -34
  429. package/out/zql/src/mutate/mutator-registry.js.map +1 -1
  430. package/out/zql/src/mutate/mutator.d.ts +60 -64
  431. package/out/zql/src/mutate/mutator.d.ts.map +1 -1
  432. package/out/zql/src/mutate/mutator.js +8 -9
  433. package/out/zql/src/mutate/mutator.js.map +1 -1
  434. package/out/zql/src/planner/planner-builder.d.ts +2 -1
  435. package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
  436. package/out/zql/src/planner/planner-builder.js +5 -5
  437. package/out/zql/src/planner/planner-builder.js.map +1 -1
  438. package/out/zql/src/planner/planner-debug.d.ts +3 -3
  439. package/out/zql/src/planner/planner-debug.js.map +1 -1
  440. package/out/zql/src/planner/planner-graph.d.ts +3 -1
  441. package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
  442. package/out/zql/src/planner/planner-graph.js +5 -5
  443. package/out/zql/src/planner/planner-graph.js.map +1 -1
  444. package/out/zql/src/planner/planner-join.d.ts.map +1 -1
  445. package/out/zql/src/planner/planner-join.js +3 -1
  446. package/out/zql/src/planner/planner-join.js.map +1 -1
  447. package/out/zql/src/query/create-builder.d.ts +4 -1
  448. package/out/zql/src/query/create-builder.d.ts.map +1 -1
  449. package/out/zql/src/query/create-builder.js +24 -36
  450. package/out/zql/src/query/create-builder.js.map +1 -1
  451. package/out/zql/src/query/expression.d.ts +5 -5
  452. package/out/zql/src/query/expression.d.ts.map +1 -1
  453. package/out/zql/src/query/expression.js.map +1 -1
  454. package/out/zql/src/query/measure-push-operator.d.ts +2 -3
  455. package/out/zql/src/query/measure-push-operator.d.ts.map +1 -1
  456. package/out/zql/src/query/measure-push-operator.js +2 -5
  457. package/out/zql/src/query/measure-push-operator.js.map +1 -1
  458. package/out/zql/src/query/query-delegate-base.d.ts +12 -6
  459. package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
  460. package/out/zql/src/query/query-delegate-base.js +132 -2
  461. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  462. package/out/zql/src/query/query-delegate.d.ts +6 -6
  463. package/out/zql/src/query/query-delegate.d.ts.map +1 -1
  464. package/out/zql/src/query/query-impl.d.ts +27 -28
  465. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  466. package/out/zql/src/query/query-impl.js +41 -168
  467. package/out/zql/src/query/query-impl.js.map +1 -1
  468. package/out/zql/src/query/query-internals.d.ts +6 -6
  469. package/out/zql/src/query/query-internals.d.ts.map +1 -1
  470. package/out/zql/src/query/query-internals.js +2 -2
  471. package/out/zql/src/query/query-internals.js.map +1 -1
  472. package/out/zql/src/query/query-registry.d.ts +108 -122
  473. package/out/zql/src/query/query-registry.d.ts.map +1 -1
  474. package/out/zql/src/query/query-registry.js +43 -53
  475. package/out/zql/src/query/query-registry.js.map +1 -1
  476. package/out/zql/src/query/query.d.ts +63 -37
  477. package/out/zql/src/query/query.d.ts.map +1 -1
  478. package/out/zql/src/query/runnable-query-impl.d.ts +22 -0
  479. package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -0
  480. package/out/zql/src/query/runnable-query-impl.js +60 -0
  481. package/out/zql/src/query/runnable-query-impl.js.map +1 -0
  482. package/out/zql/src/query/schema-query.d.ts +2 -1
  483. package/out/zql/src/query/schema-query.d.ts.map +1 -1
  484. package/out/zql/src/query/static-query.d.ts +2 -15
  485. package/out/zql/src/query/static-query.d.ts.map +1 -1
  486. package/out/zql/src/query/static-query.js +10 -37
  487. package/out/zql/src/query/static-query.js.map +1 -1
  488. package/out/zqlite/src/internal/sql-inline.d.ts +13 -0
  489. package/out/zqlite/src/internal/sql-inline.d.ts.map +1 -0
  490. package/out/zqlite/src/internal/sql-inline.js +45 -0
  491. package/out/zqlite/src/internal/sql-inline.js.map +1 -0
  492. package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -1
  493. package/out/zqlite/src/sqlite-cost-model.js +2 -2
  494. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  495. package/out/zqlite/src/table-source.d.ts +10 -3
  496. package/out/zqlite/src/table-source.d.ts.map +1 -1
  497. package/out/zqlite/src/table-source.js +42 -23
  498. package/out/zqlite/src/table-source.js.map +1 -1
  499. package/package.json +9 -5
  500. package/out/zero-client/src/client/bindings.js +0 -33
  501. package/out/zero-client/src/client/bindings.js.map +0 -1
  502. package/out/zero-react/src/components/inspector.d.ts +0 -9
  503. package/out/zero-react/src/components/inspector.d.ts.map +0 -1
  504. package/out/zero-react/src/components/inspector.js +0 -38
  505. package/out/zero-react/src/components/inspector.js.map +0 -1
  506. package/out/zero-react/src/components/mark-icon.d.ts +0 -3
  507. package/out/zero-react/src/components/mark-icon.d.ts.map +0 -1
  508. package/out/zero-react/src/components/mark-icon.js +0 -28
  509. package/out/zero-react/src/components/mark-icon.js.map +0 -1
  510. package/out/zero-react/src/components/zero-inspector.d.ts +0 -8
  511. package/out/zero-react/src/components/zero-inspector.d.ts.map +0 -1
  512. package/out/zero-react/src/components/zero-inspector.js +0 -44
  513. package/out/zero-react/src/components/zero-inspector.js.map +0 -1
  514. package/out/zero-react/src/use-zero-connection-state.d.ts.map +0 -1
  515. package/out/zero-react/src/use-zero-connection-state.js.map +0 -1
  516. package/out/zero-solid/src/use-zero-connection-state.d.ts.map +0 -1
  517. package/out/zero-solid/src/use-zero-connection-state.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"builder.js","sources":["../../../../../zql/src/builder/builder.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport type {JSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {PlannerException} from '../error.ts';\nimport type {\n AST,\n ColumnReference,\n CompoundKey,\n Condition,\n Conjunction,\n CorrelatedSubquery,\n CorrelatedSubqueryCondition,\n Disjunction,\n LiteralValue,\n Ordering,\n Parameter,\n SimpleCondition,\n ValuePosition,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport {Exists} from '../ivm/exists.ts';\nimport {FanIn} from '../ivm/fan-in.ts';\nimport {FanOut} from '../ivm/fan-out.ts';\nimport {\n buildFilterPipeline,\n type FilterInput,\n} from '../ivm/filter-operators.ts';\nimport {Filter} from '../ivm/filter.ts';\nimport {FlippedJoin} from '../ivm/flipped-join.ts';\nimport {Join} from '../ivm/join.ts';\nimport type {Input, InputBase, Storage} from '../ivm/operator.ts';\nimport {Skip} from '../ivm/skip.ts';\nimport type {Source, SourceInput} from '../ivm/source.ts';\nimport {Take} from '../ivm/take.ts';\nimport {UnionFanIn} from '../ivm/union-fan-in.ts';\nimport {UnionFanOut} from '../ivm/union-fan-out.ts';\nimport {planQuery} from '../planner/planner-builder.ts';\nimport type {ConnectionCostModel} from '../planner/planner-connection.ts';\nimport {completeOrdering} from '../query/complete-ordering.ts';\nimport type {PlanDebugger} from '../planner/planner-debug.ts';\nimport type {DebugDelegate} from './debug-delegate.ts';\nimport {createPredicate, type NoSubqueryCondition} from './filter.ts';\n\nexport type StaticQueryParameters = {\n authData: Record<string, JSONValue>;\n preMutationRow?: Row | undefined;\n};\n\n/**\n * Interface required of caller to buildPipeline. Connects to constructed\n * pipeline to delegate environment to provide sources and storage.\n */\nexport interface BuilderDelegate {\n readonly applyFiltersAnyway?: boolean | undefined;\n debug?: DebugDelegate | undefined;\n\n /**\n * When true, allows NOT EXISTS conditions in queries.\n * Defaults to false.\n *\n * We only set this to true on the server.\n * The client-side query engine cannot support NOT EXISTS because:\n * 1. Zero only syncs a subset of data to the client\n * 2. On the client, we can't distinguish between a row not existing vs.\n * a row not being synced to the client\n * 3. NOT EXISTS requires complete knowledge of what doesn't exist\n */\n readonly enableNotExists?: boolean | undefined;\n\n /**\n * Called once for each source needed by the AST.\n * Might be called multiple times with same tableName. It is OK to return\n * same storage instance in that case.\n */\n getSource(tableName: string): Source | undefined;\n\n /**\n * Called once for each operator that requires storage. Should return a new\n * unique storage object for each call.\n */\n createStorage(name: string): Storage;\n\n decorateInput(input: Input, name: string): Input;\n\n addEdge(source: InputBase, dest: InputBase): void;\n\n decorateFilterInput(input: FilterInput, name: string): FilterInput;\n\n decorateSourceInput(input: SourceInput, queryID: string): Input;\n\n /**\n * The AST is mapped on-the-wire between client and server names.\n *\n * There is no \"wire\" for zqlite tests so this function is provided\n * to allow tests to remap the AST.\n */\n mapAst?: ((ast: AST) => AST) | undefined;\n}\n\n/**\n * Builds a pipeline from an AST. Caller must provide a delegate to create source\n * and storage interfaces as necessary.\n *\n * Usage:\n *\n * ```ts\n * class MySink implements Output {\n * readonly #input: Input;\n *\n * constructor(input: Input) {\n * this.#input = input;\n * input.setOutput(this);\n * }\n *\n * push(change: Change, _: Operator) {\n * console.log(change);\n * }\n * }\n *\n * const input = buildPipeline(ast, myDelegate, hash(ast));\n * const sink = new MySink(input);\n * ```\n */\nexport function buildPipeline(\n ast: AST,\n delegate: BuilderDelegate,\n queryID: string,\n costModel?: ConnectionCostModel,\n lc?: LogContext,\n planDebugger?: PlanDebugger,\n): Input {\n ast = delegate.mapAst ? delegate.mapAst(ast) : ast;\n ast = completeOrdering(\n ast,\n tableName => must(delegate.getSource(tableName)).tableSchema.primaryKey,\n );\n if (costModel) {\n try {\n ast = planQuery(ast, costModel, planDebugger);\n } catch (e) {\n // If the planner fails (e.g., too many joins), fall back to the\n // unoptimized query rather than failing the entire query.\n if (e instanceof PlannerException) {\n const message = `Query planner failed (${e.kind}), falling back to unoptimized query: ${e.message}`;\n lc?.warn?.(message);\n } else {\n // Re-throw unexpected errors\n throw e;\n }\n }\n }\n return buildPipelineInternal(ast, delegate, queryID, '');\n}\n\nexport function bindStaticParameters(\n ast: AST,\n staticQueryParameters: StaticQueryParameters | undefined,\n) {\n const visit = (node: AST): AST => ({\n ...node,\n where: node.where ? bindCondition(node.where) : undefined,\n related: node.related?.map(sq => ({\n ...sq,\n subquery: visit(sq.subquery),\n })),\n });\n\n function bindCondition(condition: Condition): Condition {\n if (condition.type === 'simple') {\n return {\n ...condition,\n left: bindValue(condition.left),\n right: bindValue(condition.right) as Exclude<\n ValuePosition,\n ColumnReference\n >,\n };\n }\n if (condition.type === 'correlatedSubquery') {\n return {\n ...condition,\n related: {\n ...condition.related,\n subquery: visit(condition.related.subquery),\n },\n };\n }\n return {\n ...condition,\n conditions: condition.conditions.map(bindCondition),\n };\n }\n\n const bindValue = (value: ValuePosition): ValuePosition => {\n if (isParameter(value)) {\n const anchor = must(\n staticQueryParameters,\n 'Static query params do not exist',\n )[value.anchor];\n const resolvedValue = resolveField(anchor, value.field);\n return {\n type: 'literal',\n value: resolvedValue as LiteralValue,\n };\n }\n return value;\n };\n\n return visit(ast);\n}\n\nfunction resolveField(\n anchor: Record<string, JSONValue> | Row | undefined,\n field: string | string[],\n): unknown {\n if (anchor === undefined) {\n return null;\n }\n\n if (Array.isArray(field)) {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n return field.reduce((acc, f) => (acc as any)?.[f], anchor) ?? null;\n }\n\n return anchor[field] ?? null;\n}\n\nfunction isParameter(value: ValuePosition): value is Parameter {\n return value.type === 'static';\n}\n\nconst EXISTS_LIMIT = 3;\nconst PERMISSIONS_EXISTS_LIMIT = 1;\n\n/**\n * Checks if a condition tree contains any NOT EXISTS operations.\n * Recursively checks AND/OR branches but does not recurse into nested subqueries\n * (those are checked when buildPipelineInternal processes them).\n */\nexport function assertNoNotExists(condition: Condition): void {\n switch (condition.type) {\n case 'simple':\n return;\n\n case 'correlatedSubquery':\n if (condition.op === 'NOT EXISTS') {\n throw new Error(\n 'not(exists()) is not supported on the client - see https://bugs.rocicorp.dev/issue/3438',\n );\n }\n return;\n\n case 'and':\n case 'or':\n for (const c of condition.conditions) {\n assertNoNotExists(c);\n }\n return;\n default:\n unreachable(condition);\n }\n}\n\nfunction buildPipelineInternal(\n ast: AST,\n delegate: BuilderDelegate,\n queryID: string,\n name: string,\n partitionKey?: CompoundKey,\n): Input {\n const source = delegate.getSource(ast.table);\n if (!source) {\n throw new Error(`Source not found: ${ast.table}`);\n }\n ast = uniquifyCorrelatedSubqueryConditionAliases(ast);\n\n if (!delegate.enableNotExists && ast.where) {\n assertNoNotExists(ast.where);\n }\n\n const csqConditions = gatherCorrelatedSubqueryQueryConditions(ast.where);\n const splitEditKeys: Set<string> = partitionKey\n ? new Set(partitionKey)\n : new Set();\n const aliases = new Set<string>();\n for (const csq of csqConditions) {\n aliases.add(csq.related.subquery.alias || '');\n for (const key of csq.related.correlation.parentField) {\n splitEditKeys.add(key);\n }\n }\n if (ast.related) {\n for (const csq of ast.related) {\n for (const key of csq.correlation.parentField) {\n splitEditKeys.add(key);\n }\n }\n }\n const conn = source.connect(\n must(ast.orderBy),\n ast.where,\n splitEditKeys,\n delegate.debug,\n );\n\n let end: Input = delegate.decorateSourceInput(conn, queryID);\n end = delegate.decorateInput(end, `${name}:source(${ast.table})`);\n const {fullyAppliedFilters} = conn;\n\n if (ast.start) {\n const skip = new Skip(end, ast.start);\n delegate.addEdge(end, skip);\n end = delegate.decorateInput(skip, `${name}:skip)`);\n }\n\n for (const csqCondition of csqConditions) {\n // flipped EXISTS are handled in applyWhere\n if (!csqCondition.flip) {\n end = applyCorrelatedSubQuery(\n {\n ...csqCondition.related,\n subquery: {\n ...csqCondition.related.subquery,\n limit:\n csqCondition.related.system === 'permissions'\n ? PERMISSIONS_EXISTS_LIMIT\n : EXISTS_LIMIT,\n },\n },\n delegate,\n queryID,\n end,\n name,\n true,\n );\n }\n }\n\n if (ast.where && (!fullyAppliedFilters || delegate.applyFiltersAnyway)) {\n end = applyWhere(end, ast.where, delegate, name);\n }\n\n if (ast.limit !== undefined) {\n const takeName = `${name}:take`;\n const take = new Take(\n end,\n delegate.createStorage(takeName),\n ast.limit,\n partitionKey,\n );\n delegate.addEdge(end, take);\n end = delegate.decorateInput(take, takeName);\n }\n\n if (ast.related) {\n for (const csq of ast.related) {\n end = applyCorrelatedSubQuery(csq, delegate, queryID, end, name, false);\n }\n }\n\n return end;\n}\n\nfunction applyWhere(\n input: Input,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n): Input {\n if (!conditionIncludesFlippedSubqueryAtAnyLevel(condition)) {\n return buildFilterPipeline(input, delegate, filterInput =>\n applyFilter(filterInput, condition, delegate, name),\n );\n }\n\n return applyFilterWithFlips(input, condition, delegate, name);\n}\n\nfunction applyFilterWithFlips(\n input: Input,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n): Input {\n let end = input;\n assert(condition.type !== 'simple', 'Simple conditions cannot have flips');\n\n switch (condition.type) {\n case 'and': {\n const [withFlipped, withoutFlipped] = partitionBranches(\n condition.conditions,\n conditionIncludesFlippedSubqueryAtAnyLevel,\n );\n if (withoutFlipped.length > 0) {\n end = buildFilterPipeline(input, delegate, filterInput =>\n applyAnd(\n filterInput,\n {\n type: 'and',\n conditions: withoutFlipped,\n },\n delegate,\n name,\n ),\n );\n }\n assert(withFlipped.length > 0, 'Impossible to have no flips here');\n for (const cond of withFlipped) {\n end = applyFilterWithFlips(end, cond, delegate, name);\n }\n break;\n }\n case 'or': {\n const [withFlipped, withoutFlipped] = partitionBranches(\n condition.conditions,\n conditionIncludesFlippedSubqueryAtAnyLevel,\n );\n assert(withFlipped.length > 0, 'Impossible to have no flips here');\n\n const ufo = new UnionFanOut(end);\n delegate.addEdge(end, ufo);\n end = delegate.decorateInput(ufo, `${name}:ufo`);\n\n const branches: Input[] = [];\n if (withoutFlipped.length > 0) {\n branches.push(\n buildFilterPipeline(end, delegate, filterInput =>\n applyOr(\n filterInput,\n {\n type: 'or',\n conditions: withoutFlipped,\n },\n delegate,\n name,\n ),\n ),\n );\n }\n\n for (const cond of withFlipped) {\n branches.push(applyFilterWithFlips(end, cond, delegate, name));\n }\n\n const ufi = new UnionFanIn(ufo, branches);\n for (const branch of branches) {\n delegate.addEdge(branch, ufi);\n }\n end = delegate.decorateInput(ufi, `${name}:ufi`);\n\n break;\n }\n case 'correlatedSubquery': {\n const sq = condition.related;\n const child = buildPipelineInternal(\n sq.subquery,\n delegate,\n '',\n `${name}.${sq.subquery.alias}`,\n sq.correlation.childField,\n );\n const flippedJoin = new FlippedJoin({\n parent: end,\n child,\n parentKey: sq.correlation.parentField,\n childKey: sq.correlation.childField,\n relationshipName: must(\n sq.subquery.alias,\n 'Subquery must have an alias',\n ),\n hidden: sq.hidden ?? false,\n system: sq.system ?? 'client',\n });\n delegate.addEdge(end, flippedJoin);\n delegate.addEdge(child, flippedJoin);\n end = delegate.decorateInput(\n flippedJoin,\n `${name}:flipped-join(${sq.subquery.alias})`,\n );\n break;\n }\n }\n\n return end;\n}\n\nfunction applyFilter(\n input: FilterInput,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n) {\n switch (condition.type) {\n case 'and':\n return applyAnd(input, condition, delegate, name);\n case 'or':\n return applyOr(input, condition, delegate, name);\n case 'correlatedSubquery':\n return applyCorrelatedSubqueryCondition(input, condition, delegate, name);\n case 'simple':\n return applySimpleCondition(input, delegate, condition);\n }\n}\n\nfunction applyAnd(\n input: FilterInput,\n condition: Conjunction,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n for (const subCondition of condition.conditions) {\n input = applyFilter(input, subCondition, delegate, name);\n }\n return input;\n}\n\nexport function applyOr(\n input: FilterInput,\n condition: Disjunction,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n const [subqueryConditions, otherConditions] =\n groupSubqueryConditions(condition);\n // if there are no subquery conditions, no fan-in / fan-out is needed\n if (subqueryConditions.length === 0) {\n const filter = new Filter(\n input,\n createPredicate({\n type: 'or',\n conditions: otherConditions,\n }),\n );\n delegate.addEdge(input, filter);\n return filter;\n }\n\n const fanOut = new FanOut(input);\n delegate.addEdge(input, fanOut);\n const branches = subqueryConditions.map(subCondition =>\n applyFilter(fanOut, subCondition, delegate, name),\n );\n if (otherConditions.length > 0) {\n const filter = new Filter(\n fanOut,\n createPredicate({\n type: 'or',\n conditions: otherConditions,\n }),\n );\n delegate.addEdge(fanOut, filter);\n branches.push(filter);\n }\n const ret = new FanIn(fanOut, branches);\n for (const branch of branches) {\n delegate.addEdge(branch, ret);\n }\n fanOut.setFanIn(ret);\n return ret;\n}\n\nexport function groupSubqueryConditions(condition: Disjunction) {\n const partitioned: [\n subqueryConditions: Condition[],\n otherConditions: NoSubqueryCondition[],\n ] = [[], []];\n for (const subCondition of condition.conditions) {\n if (isNotAndDoesNotContainSubquery(subCondition)) {\n partitioned[1].push(subCondition);\n } else {\n partitioned[0].push(subCondition);\n }\n }\n return partitioned;\n}\n\nexport function isNotAndDoesNotContainSubquery(\n condition: Condition,\n): condition is NoSubqueryCondition {\n if (condition.type === 'correlatedSubquery') {\n return false;\n }\n if (condition.type === 'simple') {\n return true;\n }\n return condition.conditions.every(isNotAndDoesNotContainSubquery);\n}\n\nfunction applySimpleCondition(\n input: FilterInput,\n delegate: BuilderDelegate,\n condition: SimpleCondition,\n): FilterInput {\n const filter = new Filter(input, createPredicate(condition));\n delegate.decorateFilterInput(\n filter,\n `${valuePosName(condition.left)}:${condition.op}:${valuePosName(condition.right)}`,\n );\n delegate.addEdge(input, filter);\n return filter;\n}\n\nfunction valuePosName(left: ValuePosition) {\n switch (left.type) {\n case 'static':\n return left.field;\n case 'literal':\n return left.value;\n case 'column':\n return left.name;\n }\n}\n\nfunction applyCorrelatedSubQuery(\n sq: CorrelatedSubquery,\n delegate: BuilderDelegate,\n queryID: string,\n end: Input,\n name: string,\n fromCondition: boolean,\n) {\n // TODO: we only omit the join if the CSQ if from a condition since\n // we want to create an empty array for `related` fields that are `limit(0)`\n if (sq.subquery.limit === 0 && fromCondition) {\n return end;\n }\n\n assert(sq.subquery.alias, 'Subquery must have an alias');\n const child = buildPipelineInternal(\n sq.subquery,\n delegate,\n queryID,\n `${name}.${sq.subquery.alias}`,\n sq.correlation.childField,\n );\n\n const joinName = `${name}:join(${sq.subquery.alias})`;\n const join = new Join({\n parent: end,\n child,\n storage: delegate.createStorage(joinName),\n parentKey: sq.correlation.parentField,\n childKey: sq.correlation.childField,\n relationshipName: sq.subquery.alias,\n hidden: sq.hidden ?? false,\n system: sq.system ?? 'client',\n });\n delegate.addEdge(end, join);\n delegate.addEdge(child, join);\n return delegate.decorateInput(join, joinName);\n}\n\nfunction applyCorrelatedSubqueryCondition(\n input: FilterInput,\n condition: CorrelatedSubqueryCondition,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n assert(condition.op === 'EXISTS' || condition.op === 'NOT EXISTS');\n if (condition.related.subquery.limit === 0) {\n if (condition.op === 'EXISTS') {\n const filter = new Filter(input, () => false);\n delegate.addEdge(input, filter);\n return filter;\n }\n const filter = new Filter(input, () => true);\n delegate.addEdge(input, filter);\n return filter;\n }\n const existsName = `${name}:exists(${condition.related.subquery.alias})`;\n const exists = new Exists(\n input,\n delegate.createStorage(existsName),\n must(condition.related.subquery.alias),\n condition.related.correlation.parentField,\n condition.op,\n );\n delegate.addEdge(input, exists);\n return delegate.decorateFilterInput(exists, existsName);\n}\n\nfunction gatherCorrelatedSubqueryQueryConditions(\n condition: Condition | undefined,\n) {\n const csqs: CorrelatedSubqueryCondition[] = [];\n const gather = (condition: Condition) => {\n if (condition.type === 'correlatedSubquery') {\n csqs.push(condition);\n return;\n }\n if (condition.type === 'and' || condition.type === 'or') {\n for (const c of condition.conditions) {\n gather(c);\n }\n return;\n }\n };\n if (condition) {\n gather(condition);\n }\n return csqs;\n}\n\nexport function assertOrderingIncludesPK(\n ordering: Ordering,\n pk: PrimaryKey,\n): void {\n // oxlint-disable-next-line unicorn/prefer-set-has -- Array is more appropriate here for small collections\n const orderingFields = ordering.map(([field]) => field);\n const missingFields = pk.filter(pkField => !orderingFields.includes(pkField));\n\n if (missingFields.length > 0) {\n throw new Error(\n `Ordering must include all primary key fields. Missing: ${missingFields.join(\n ', ',\n )}. ZQL automatically appends primary key fields to the ordering if they are missing \n so a common cause of this error is a casing mismatch between Postgres and ZQL.\n E.g., \"userid\" vs \"userID\".\n You may want to add double-quotes around your Postgres column names to prevent Postgres from lower-casing them:\n https://www.postgresql.org/docs/current/sql-syntax-lexical.htm`,\n );\n }\n}\n\nfunction uniquifyCorrelatedSubqueryConditionAliases(ast: AST): AST {\n if (!ast.where) {\n return ast;\n }\n const {where} = ast;\n if (where.type !== 'and' && where.type !== 'or') {\n return ast;\n }\n\n let count = 0;\n const uniquifyCorrelatedSubquery = (csqc: CorrelatedSubqueryCondition) => ({\n ...csqc,\n related: {\n ...csqc.related,\n subquery: {\n ...csqc.related.subquery,\n alias: (csqc.related.subquery.alias ?? '') + '_' + count++,\n },\n },\n });\n\n const uniquify = (cond: Condition): Condition => {\n if (cond.type === 'simple') {\n return cond;\n } else if (cond.type === 'correlatedSubquery') {\n return uniquifyCorrelatedSubquery(cond);\n }\n const conditions = [];\n for (const c of cond.conditions) {\n conditions.push(uniquify(c));\n }\n return {\n type: cond.type,\n conditions,\n };\n };\n\n const result = {\n ...ast,\n where: uniquify(where),\n };\n return result;\n}\n\nexport function conditionIncludesFlippedSubqueryAtAnyLevel(\n cond: Condition,\n): boolean {\n if (cond.type === 'correlatedSubquery') {\n return !!cond.flip;\n }\n if (cond.type === 'and' || cond.type === 'or') {\n return cond.conditions.some(c =>\n conditionIncludesFlippedSubqueryAtAnyLevel(c),\n );\n }\n return false;\n}\n\nexport function partitionBranches(\n conditions: readonly Condition[],\n predicate: (c: Condition) => boolean,\n) {\n const matched: Condition[] = [];\n const notMatched: Condition[] = [];\n for (const c of conditions) {\n if (predicate(c)) {\n matched.push(c);\n } else {\n notMatched.push(c);\n }\n }\n return [matched, notMatched] as const;\n}\n"],"names":["filter","condition"],"mappings":"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"}
1
+ {"version":3,"file":"builder.js","sources":["../../../../../zql/src/builder/builder.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport type {JSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {\n AST,\n ColumnReference,\n CompoundKey,\n Condition,\n Conjunction,\n CorrelatedSubquery,\n CorrelatedSubqueryCondition,\n Disjunction,\n LiteralValue,\n Ordering,\n Parameter,\n SimpleCondition,\n ValuePosition,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport {Exists} from '../ivm/exists.ts';\nimport {FanIn} from '../ivm/fan-in.ts';\nimport {FanOut} from '../ivm/fan-out.ts';\nimport {\n buildFilterPipeline,\n type FilterInput,\n} from '../ivm/filter-operators.ts';\nimport {Filter} from '../ivm/filter.ts';\nimport {FlippedJoin} from '../ivm/flipped-join.ts';\nimport {Join} from '../ivm/join.ts';\nimport type {Input, InputBase, Storage} from '../ivm/operator.ts';\nimport {Skip} from '../ivm/skip.ts';\nimport type {Source, SourceInput} from '../ivm/source.ts';\nimport {Take} from '../ivm/take.ts';\nimport {UnionFanIn} from '../ivm/union-fan-in.ts';\nimport {UnionFanOut} from '../ivm/union-fan-out.ts';\nimport {planQuery} from '../planner/planner-builder.ts';\nimport type {ConnectionCostModel} from '../planner/planner-connection.ts';\nimport {completeOrdering} from '../query/complete-ordering.ts';\nimport type {PlanDebugger} from '../planner/planner-debug.ts';\nimport type {DebugDelegate} from './debug-delegate.ts';\nimport {createPredicate, type NoSubqueryCondition} from './filter.ts';\n\nexport type StaticQueryParameters = {\n authData: Record<string, JSONValue>;\n preMutationRow?: Row | undefined;\n};\n\n/**\n * Interface required of caller to buildPipeline. Connects to constructed\n * pipeline to delegate environment to provide sources and storage.\n */\nexport interface BuilderDelegate {\n readonly applyFiltersAnyway?: boolean | undefined;\n debug?: DebugDelegate | undefined;\n\n /**\n * When true, allows NOT EXISTS conditions in queries.\n * Defaults to false.\n *\n * We only set this to true on the server.\n * The client-side query engine cannot support NOT EXISTS because:\n * 1. Zero only syncs a subset of data to the client\n * 2. On the client, we can't distinguish between a row not existing vs.\n * a row not being synced to the client\n * 3. NOT EXISTS requires complete knowledge of what doesn't exist\n */\n readonly enableNotExists?: boolean | undefined;\n\n /**\n * Called once for each source needed by the AST.\n * Might be called multiple times with same tableName. It is OK to return\n * same storage instance in that case.\n */\n getSource(tableName: string): Source | undefined;\n\n /**\n * Called once for each operator that requires storage. Should return a new\n * unique storage object for each call.\n */\n createStorage(name: string): Storage;\n\n decorateInput(input: Input, name: string): Input;\n\n addEdge(source: InputBase, dest: InputBase): void;\n\n decorateFilterInput(input: FilterInput, name: string): FilterInput;\n\n decorateSourceInput(input: SourceInput, queryID: string): Input;\n\n /**\n * The AST is mapped on-the-wire between client and server names.\n *\n * There is no \"wire\" for zqlite tests so this function is provided\n * to allow tests to remap the AST.\n */\n mapAst?: ((ast: AST) => AST) | undefined;\n}\n\n/**\n * Builds a pipeline from an AST. Caller must provide a delegate to create source\n * and storage interfaces as necessary.\n *\n * Usage:\n *\n * ```ts\n * class MySink implements Output {\n * readonly #input: Input;\n *\n * constructor(input: Input) {\n * this.#input = input;\n * input.setOutput(this);\n * }\n *\n * push(change: Change, _: Operator) {\n * console.log(change);\n * }\n * }\n *\n * const input = buildPipeline(ast, myDelegate, hash(ast));\n * const sink = new MySink(input);\n * ```\n */\nexport function buildPipeline(\n ast: AST,\n delegate: BuilderDelegate,\n queryID: string,\n costModel?: ConnectionCostModel,\n lc?: LogContext,\n planDebugger?: PlanDebugger,\n): Input {\n ast = delegate.mapAst ? delegate.mapAst(ast) : ast;\n ast = completeOrdering(\n ast,\n tableName => must(delegate.getSource(tableName)).tableSchema.primaryKey,\n );\n if (costModel) {\n ast = planQuery(ast, costModel, planDebugger, lc);\n }\n return buildPipelineInternal(ast, delegate, queryID, '');\n}\n\nexport function bindStaticParameters(\n ast: AST,\n staticQueryParameters: StaticQueryParameters | undefined,\n) {\n const visit = (node: AST): AST => ({\n ...node,\n where: node.where ? bindCondition(node.where) : undefined,\n related: node.related?.map(sq => ({\n ...sq,\n subquery: visit(sq.subquery),\n })),\n });\n\n function bindCondition(condition: Condition): Condition {\n if (condition.type === 'simple') {\n return {\n ...condition,\n left: bindValue(condition.left),\n right: bindValue(condition.right) as Exclude<\n ValuePosition,\n ColumnReference\n >,\n };\n }\n if (condition.type === 'correlatedSubquery') {\n return {\n ...condition,\n related: {\n ...condition.related,\n subquery: visit(condition.related.subquery),\n },\n };\n }\n return {\n ...condition,\n conditions: condition.conditions.map(bindCondition),\n };\n }\n\n const bindValue = (value: ValuePosition): ValuePosition => {\n if (isParameter(value)) {\n const anchor = must(\n staticQueryParameters,\n 'Static query params do not exist',\n )[value.anchor];\n const resolvedValue = resolveField(anchor, value.field);\n return {\n type: 'literal',\n value: resolvedValue as LiteralValue,\n };\n }\n return value;\n };\n\n return visit(ast);\n}\n\nfunction resolveField(\n anchor: Record<string, JSONValue> | Row | undefined,\n field: string | string[],\n): unknown {\n if (anchor === undefined) {\n return null;\n }\n\n if (Array.isArray(field)) {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n return field.reduce((acc, f) => (acc as any)?.[f], anchor) ?? null;\n }\n\n return anchor[field] ?? null;\n}\n\nfunction isParameter(value: ValuePosition): value is Parameter {\n return value.type === 'static';\n}\n\nconst EXISTS_LIMIT = 3;\nconst PERMISSIONS_EXISTS_LIMIT = 1;\n\n/**\n * Checks if a condition tree contains any NOT EXISTS operations.\n * Recursively checks AND/OR branches but does not recurse into nested subqueries\n * (those are checked when buildPipelineInternal processes them).\n */\nexport function assertNoNotExists(condition: Condition): void {\n switch (condition.type) {\n case 'simple':\n return;\n\n case 'correlatedSubquery':\n if (condition.op === 'NOT EXISTS') {\n throw new Error(\n 'not(exists()) is not supported on the client - see https://bugs.rocicorp.dev/issue/3438',\n );\n }\n return;\n\n case 'and':\n case 'or':\n for (const c of condition.conditions) {\n assertNoNotExists(c);\n }\n return;\n default:\n unreachable(condition);\n }\n}\n\nfunction buildPipelineInternal(\n ast: AST,\n delegate: BuilderDelegate,\n queryID: string,\n name: string,\n partitionKey?: CompoundKey,\n): Input {\n const source = delegate.getSource(ast.table);\n if (!source) {\n throw new Error(`Source not found: ${ast.table}`);\n }\n ast = uniquifyCorrelatedSubqueryConditionAliases(ast);\n\n if (!delegate.enableNotExists && ast.where) {\n assertNoNotExists(ast.where);\n }\n\n const csqConditions = gatherCorrelatedSubqueryQueryConditions(ast.where);\n const splitEditKeys: Set<string> = partitionKey\n ? new Set(partitionKey)\n : new Set();\n const aliases = new Set<string>();\n for (const csq of csqConditions) {\n aliases.add(csq.related.subquery.alias || '');\n for (const key of csq.related.correlation.parentField) {\n splitEditKeys.add(key);\n }\n }\n if (ast.related) {\n for (const csq of ast.related) {\n for (const key of csq.correlation.parentField) {\n splitEditKeys.add(key);\n }\n }\n }\n const conn = source.connect(\n must(ast.orderBy),\n ast.where,\n splitEditKeys,\n delegate.debug,\n );\n\n let end: Input = delegate.decorateSourceInput(conn, queryID);\n end = delegate.decorateInput(end, `${name}:source(${ast.table})`);\n const {fullyAppliedFilters} = conn;\n\n if (ast.start) {\n const skip = new Skip(end, ast.start);\n delegate.addEdge(end, skip);\n end = delegate.decorateInput(skip, `${name}:skip)`);\n }\n\n for (const csqCondition of csqConditions) {\n // flipped EXISTS are handled in applyWhere\n if (!csqCondition.flip) {\n end = applyCorrelatedSubQuery(\n {\n ...csqCondition.related,\n subquery: {\n ...csqCondition.related.subquery,\n limit:\n csqCondition.related.system === 'permissions'\n ? PERMISSIONS_EXISTS_LIMIT\n : EXISTS_LIMIT,\n },\n },\n delegate,\n queryID,\n end,\n name,\n true,\n );\n }\n }\n\n if (ast.where && (!fullyAppliedFilters || delegate.applyFiltersAnyway)) {\n end = applyWhere(end, ast.where, delegate, name);\n }\n\n if (ast.limit !== undefined) {\n const takeName = `${name}:take`;\n const take = new Take(\n end,\n delegate.createStorage(takeName),\n ast.limit,\n partitionKey,\n );\n delegate.addEdge(end, take);\n end = delegate.decorateInput(take, takeName);\n }\n\n if (ast.related) {\n for (const csq of ast.related) {\n end = applyCorrelatedSubQuery(csq, delegate, queryID, end, name, false);\n }\n }\n\n return end;\n}\n\nfunction applyWhere(\n input: Input,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n): Input {\n if (!conditionIncludesFlippedSubqueryAtAnyLevel(condition)) {\n return buildFilterPipeline(input, delegate, filterInput =>\n applyFilter(filterInput, condition, delegate, name),\n );\n }\n\n return applyFilterWithFlips(input, condition, delegate, name);\n}\n\nfunction applyFilterWithFlips(\n input: Input,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n): Input {\n let end = input;\n assert(condition.type !== 'simple', 'Simple conditions cannot have flips');\n\n switch (condition.type) {\n case 'and': {\n const [withFlipped, withoutFlipped] = partitionBranches(\n condition.conditions,\n conditionIncludesFlippedSubqueryAtAnyLevel,\n );\n if (withoutFlipped.length > 0) {\n end = buildFilterPipeline(input, delegate, filterInput =>\n applyAnd(\n filterInput,\n {\n type: 'and',\n conditions: withoutFlipped,\n },\n delegate,\n name,\n ),\n );\n }\n assert(withFlipped.length > 0, 'Impossible to have no flips here');\n for (const cond of withFlipped) {\n end = applyFilterWithFlips(end, cond, delegate, name);\n }\n break;\n }\n case 'or': {\n const [withFlipped, withoutFlipped] = partitionBranches(\n condition.conditions,\n conditionIncludesFlippedSubqueryAtAnyLevel,\n );\n assert(withFlipped.length > 0, 'Impossible to have no flips here');\n\n const ufo = new UnionFanOut(end);\n delegate.addEdge(end, ufo);\n end = delegate.decorateInput(ufo, `${name}:ufo`);\n\n const branches: Input[] = [];\n if (withoutFlipped.length > 0) {\n branches.push(\n buildFilterPipeline(end, delegate, filterInput =>\n applyOr(\n filterInput,\n {\n type: 'or',\n conditions: withoutFlipped,\n },\n delegate,\n name,\n ),\n ),\n );\n }\n\n for (const cond of withFlipped) {\n branches.push(applyFilterWithFlips(end, cond, delegate, name));\n }\n\n const ufi = new UnionFanIn(ufo, branches);\n for (const branch of branches) {\n delegate.addEdge(branch, ufi);\n }\n end = delegate.decorateInput(ufi, `${name}:ufi`);\n\n break;\n }\n case 'correlatedSubquery': {\n const sq = condition.related;\n const child = buildPipelineInternal(\n sq.subquery,\n delegate,\n '',\n `${name}.${sq.subquery.alias}`,\n sq.correlation.childField,\n );\n const flippedJoin = new FlippedJoin({\n parent: end,\n child,\n parentKey: sq.correlation.parentField,\n childKey: sq.correlation.childField,\n relationshipName: must(\n sq.subquery.alias,\n 'Subquery must have an alias',\n ),\n hidden: sq.hidden ?? false,\n system: sq.system ?? 'client',\n });\n delegate.addEdge(end, flippedJoin);\n delegate.addEdge(child, flippedJoin);\n end = delegate.decorateInput(\n flippedJoin,\n `${name}:flipped-join(${sq.subquery.alias})`,\n );\n break;\n }\n }\n\n return end;\n}\n\nfunction applyFilter(\n input: FilterInput,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n) {\n switch (condition.type) {\n case 'and':\n return applyAnd(input, condition, delegate, name);\n case 'or':\n return applyOr(input, condition, delegate, name);\n case 'correlatedSubquery':\n return applyCorrelatedSubqueryCondition(input, condition, delegate, name);\n case 'simple':\n return applySimpleCondition(input, delegate, condition);\n }\n}\n\nfunction applyAnd(\n input: FilterInput,\n condition: Conjunction,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n for (const subCondition of condition.conditions) {\n input = applyFilter(input, subCondition, delegate, name);\n }\n return input;\n}\n\nexport function applyOr(\n input: FilterInput,\n condition: Disjunction,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n const [subqueryConditions, otherConditions] =\n groupSubqueryConditions(condition);\n // if there are no subquery conditions, no fan-in / fan-out is needed\n if (subqueryConditions.length === 0) {\n const filter = new Filter(\n input,\n createPredicate({\n type: 'or',\n conditions: otherConditions,\n }),\n );\n delegate.addEdge(input, filter);\n return filter;\n }\n\n const fanOut = new FanOut(input);\n delegate.addEdge(input, fanOut);\n const branches = subqueryConditions.map(subCondition =>\n applyFilter(fanOut, subCondition, delegate, name),\n );\n if (otherConditions.length > 0) {\n const filter = new Filter(\n fanOut,\n createPredicate({\n type: 'or',\n conditions: otherConditions,\n }),\n );\n delegate.addEdge(fanOut, filter);\n branches.push(filter);\n }\n const ret = new FanIn(fanOut, branches);\n for (const branch of branches) {\n delegate.addEdge(branch, ret);\n }\n fanOut.setFanIn(ret);\n return ret;\n}\n\nexport function groupSubqueryConditions(condition: Disjunction) {\n const partitioned: [\n subqueryConditions: Condition[],\n otherConditions: NoSubqueryCondition[],\n ] = [[], []];\n for (const subCondition of condition.conditions) {\n if (isNotAndDoesNotContainSubquery(subCondition)) {\n partitioned[1].push(subCondition);\n } else {\n partitioned[0].push(subCondition);\n }\n }\n return partitioned;\n}\n\nexport function isNotAndDoesNotContainSubquery(\n condition: Condition,\n): condition is NoSubqueryCondition {\n if (condition.type === 'correlatedSubquery') {\n return false;\n }\n if (condition.type === 'simple') {\n return true;\n }\n return condition.conditions.every(isNotAndDoesNotContainSubquery);\n}\n\nfunction applySimpleCondition(\n input: FilterInput,\n delegate: BuilderDelegate,\n condition: SimpleCondition,\n): FilterInput {\n const filter = new Filter(input, createPredicate(condition));\n delegate.decorateFilterInput(\n filter,\n `${valuePosName(condition.left)}:${condition.op}:${valuePosName(condition.right)}`,\n );\n delegate.addEdge(input, filter);\n return filter;\n}\n\nfunction valuePosName(left: ValuePosition) {\n switch (left.type) {\n case 'static':\n return left.field;\n case 'literal':\n return left.value;\n case 'column':\n return left.name;\n }\n}\n\nfunction applyCorrelatedSubQuery(\n sq: CorrelatedSubquery,\n delegate: BuilderDelegate,\n queryID: string,\n end: Input,\n name: string,\n fromCondition: boolean,\n) {\n // TODO: we only omit the join if the CSQ if from a condition since\n // we want to create an empty array for `related` fields that are `limit(0)`\n if (sq.subquery.limit === 0 && fromCondition) {\n return end;\n }\n\n assert(sq.subquery.alias, 'Subquery must have an alias');\n const child = buildPipelineInternal(\n sq.subquery,\n delegate,\n queryID,\n `${name}.${sq.subquery.alias}`,\n sq.correlation.childField,\n );\n\n const joinName = `${name}:join(${sq.subquery.alias})`;\n const join = new Join({\n parent: end,\n child,\n parentKey: sq.correlation.parentField,\n childKey: sq.correlation.childField,\n relationshipName: sq.subquery.alias,\n hidden: sq.hidden ?? false,\n system: sq.system ?? 'client',\n });\n delegate.addEdge(end, join);\n delegate.addEdge(child, join);\n return delegate.decorateInput(join, joinName);\n}\n\nfunction applyCorrelatedSubqueryCondition(\n input: FilterInput,\n condition: CorrelatedSubqueryCondition,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n assert(condition.op === 'EXISTS' || condition.op === 'NOT EXISTS');\n if (condition.related.subquery.limit === 0) {\n if (condition.op === 'EXISTS') {\n const filter = new Filter(input, () => false);\n delegate.addEdge(input, filter);\n return filter;\n }\n const filter = new Filter(input, () => true);\n delegate.addEdge(input, filter);\n return filter;\n }\n const existsName = `${name}:exists(${condition.related.subquery.alias})`;\n const exists = new Exists(\n input,\n must(condition.related.subquery.alias),\n condition.related.correlation.parentField,\n condition.op,\n );\n delegate.addEdge(input, exists);\n return delegate.decorateFilterInput(exists, existsName);\n}\n\nfunction gatherCorrelatedSubqueryQueryConditions(\n condition: Condition | undefined,\n) {\n const csqs: CorrelatedSubqueryCondition[] = [];\n const gather = (condition: Condition) => {\n if (condition.type === 'correlatedSubquery') {\n csqs.push(condition);\n return;\n }\n if (condition.type === 'and' || condition.type === 'or') {\n for (const c of condition.conditions) {\n gather(c);\n }\n return;\n }\n };\n if (condition) {\n gather(condition);\n }\n return csqs;\n}\n\nexport function assertOrderingIncludesPK(\n ordering: Ordering,\n pk: PrimaryKey,\n): void {\n // oxlint-disable-next-line unicorn/prefer-set-has -- Array is more appropriate here for small collections\n const orderingFields = ordering.map(([field]) => field);\n const missingFields = pk.filter(pkField => !orderingFields.includes(pkField));\n\n if (missingFields.length > 0) {\n throw new Error(\n `Ordering must include all primary key fields. Missing: ${missingFields.join(\n ', ',\n )}. ZQL automatically appends primary key fields to the ordering if they are missing \n so a common cause of this error is a casing mismatch between Postgres and ZQL.\n E.g., \"userid\" vs \"userID\".\n You may want to add double-quotes around your Postgres column names to prevent Postgres from lower-casing them:\n https://www.postgresql.org/docs/current/sql-syntax-lexical.htm`,\n );\n }\n}\n\nfunction uniquifyCorrelatedSubqueryConditionAliases(ast: AST): AST {\n if (!ast.where) {\n return ast;\n }\n const {where} = ast;\n if (where.type !== 'and' && where.type !== 'or') {\n return ast;\n }\n\n let count = 0;\n const uniquifyCorrelatedSubquery = (csqc: CorrelatedSubqueryCondition) => ({\n ...csqc,\n related: {\n ...csqc.related,\n subquery: {\n ...csqc.related.subquery,\n alias: (csqc.related.subquery.alias ?? '') + '_' + count++,\n },\n },\n });\n\n const uniquify = (cond: Condition): Condition => {\n if (cond.type === 'simple') {\n return cond;\n } else if (cond.type === 'correlatedSubquery') {\n return uniquifyCorrelatedSubquery(cond);\n }\n const conditions = [];\n for (const c of cond.conditions) {\n conditions.push(uniquify(c));\n }\n return {\n type: cond.type,\n conditions,\n };\n };\n\n const result = {\n ...ast,\n where: uniquify(where),\n };\n return result;\n}\n\nexport function conditionIncludesFlippedSubqueryAtAnyLevel(\n cond: Condition,\n): boolean {\n if (cond.type === 'correlatedSubquery') {\n return !!cond.flip;\n }\n if (cond.type === 'and' || cond.type === 'or') {\n return cond.conditions.some(c =>\n conditionIncludesFlippedSubqueryAtAnyLevel(c),\n );\n }\n return false;\n}\n\nexport function partitionBranches(\n conditions: readonly Condition[],\n predicate: (c: Condition) => boolean,\n) {\n const matched: Condition[] = [];\n const notMatched: Condition[] = [];\n for (const c of conditions) {\n if (predicate(c)) {\n matched.push(c);\n } else {\n notMatched.push(c);\n }\n }\n return [matched, notMatched] as const;\n}\n"],"names":["filter","condition"],"mappings":"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"}
@@ -4,16 +4,7 @@ class NotImplementedError extends Error {
4
4
  this.name = "NotImplementedError";
5
5
  }
6
6
  }
7
- class PlannerException extends Error {
8
- kind;
9
- constructor(kind, message) {
10
- super(message);
11
- this.name = "PlannerException";
12
- this.kind = kind;
13
- }
14
- }
15
7
  export {
16
- NotImplementedError,
17
- PlannerException
8
+ NotImplementedError
18
9
  };
19
10
  //# sourceMappingURL=error.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"error.js","sources":["../../../../zql/src/error.ts"],"sourcesContent":["export class NotImplementedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NotImplementedError';\n }\n}\n\nexport type PlannerExceptionKind = 'max_flippable_joins';\n\nexport class PlannerException extends Error {\n readonly kind: PlannerExceptionKind;\n\n constructor(kind: PlannerExceptionKind, message: string) {\n super(message);\n this.name = 'PlannerException';\n this.kind = kind;\n }\n}\n"],"names":[],"mappings":"AAAO,MAAM,4BAA4B,MAAM;AAAA,EAC7C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAIO,MAAM,yBAAyB,MAAM;AAAA,EACjC;AAAA,EAET,YAAY,MAA4B,SAAiB;AACvD,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,EACd;AACF;"}
1
+ {"version":3,"file":"error.js","sources":["../../../../zql/src/error.ts"],"sourcesContent":["export class NotImplementedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NotImplementedError';\n }\n}\n\nexport type PlannerExceptionKind = 'max_flippable_joins';\n\nexport class PlannerException extends Error {\n readonly kind: PlannerExceptionKind;\n\n constructor(kind: PlannerExceptionKind, message: string) {\n super(message);\n this.name = 'PlannerException';\n this.kind = kind;\n }\n}\n"],"names":[],"mappings":"AAAO,MAAM,4BAA4B,MAAM;AAAA,EAC7C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;"}
@@ -2,7 +2,7 @@ import type { ErroredQuery } from '../../../zero-protocol/src/custom-queries.ts'
2
2
  import type { TTL } from '../query/ttl.ts';
3
3
  import type { Listener, TypedView } from '../query/typed-view.ts';
4
4
  import type { Change } from './change.ts';
5
- import type { Input, Output } from './operator.ts';
5
+ import { type Input, type Output } from './operator.ts';
6
6
  import type { Format, View } from './view.ts';
7
7
  /**
8
8
  * Implements a materialized view of the output of an operator.
@@ -22,7 +22,7 @@ export declare class ArrayView<V extends View> implements Output, TypedView<V> {
22
22
  get data(): V;
23
23
  addListener(listener: Listener<V>): () => void;
24
24
  destroy(): void;
25
- push(change: Change): void;
25
+ push(change: Change): readonly never[];
26
26
  flush(): void;
27
27
  updateTTL(ttl: TTL): void;
28
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"array-view.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/array-view.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,8CAA8C,CAAC;AAC/E,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,iBAAiB,CAAC;AACzC,OAAO,KAAK,EAAC,QAAQ,EAAc,SAAS,EAAC,MAAM,wBAAwB,CAAC;AAC5E,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAC,KAAK,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;AAGjD,OAAO,KAAK,EAAQ,MAAM,EAAE,IAAI,EAAC,MAAM,WAAW,CAAC;AAEnD;;;;;;;;;;GAUG;AACH,qBAAa,SAAS,CAAC,CAAC,SAAS,IAAI,CAAE,YAAW,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;;IAUpE,SAAS,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;gBAQlC,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,IAAI,GAAG,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,EAClD,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI;IA6B/B,IAAI,IAAI,IACmB,CAAC,CAC3B;IAED,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IAqBjC,OAAO;IAkBP,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK1B,KAAK;IAQL,SAAS,CAAC,GAAG,EAAE,GAAG;CAGnB"}
1
+ {"version":3,"file":"array-view.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/array-view.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,8CAA8C,CAAC;AAC/E,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,iBAAiB,CAAC;AACzC,OAAO,KAAK,EAAC,QAAQ,EAAc,SAAS,EAAC,MAAM,wBAAwB,CAAC;AAC5E,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EAAa,KAAK,KAAK,EAAE,KAAK,MAAM,EAAC,MAAM,eAAe,CAAC;AAGlE,OAAO,KAAK,EAAQ,MAAM,EAAE,IAAI,EAAC,MAAM,WAAW,CAAC;AAEnD;;;;;;;;;;GAUG;AACH,qBAAa,SAAS,CAAC,CAAC,SAAS,IAAI,CAAE,YAAW,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;;IAUpE,SAAS,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;gBAQlC,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,IAAI,GAAG,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,EAClD,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI;IA6B/B,IAAI,IAAI,IACmB,CAAC,CAC3B;IAED,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IAqBjC,OAAO;IAkBP,IAAI,CAAC,MAAM,EAAE,MAAM;IAMnB,KAAK;IAQL,SAAS,CAAC,GAAG,EAAE,GAAG;CAGnB"}
@@ -1,4 +1,6 @@
1
1
  import { assert } from "../../../shared/src/asserts.js";
2
+ import { emptyArray } from "../../../shared/src/sentinels.js";
3
+ import { skipYields } from "./operator.js";
2
4
  import { applyChange } from "./view-apply-change.js";
3
5
  class ArrayView {
4
6
  #input;
@@ -61,7 +63,7 @@ class ArrayView {
61
63
  }
62
64
  #hydrate() {
63
65
  this.#dirty = true;
64
- for (const node of this.#input.fetch({})) {
66
+ for (const node of skipYields(this.#input.fetch({}))) {
65
67
  applyChange(
66
68
  this.#root,
67
69
  { type: "add", node },
@@ -75,6 +77,7 @@ class ArrayView {
75
77
  push(change) {
76
78
  this.#dirty = true;
77
79
  applyChange(this.#root, change, this.#schema, "", this.#format);
80
+ return emptyArray;
78
81
  }
79
82
  flush() {
80
83
  if (!this.#dirty) {
@@ -1 +1 @@
1
- {"version":3,"file":"array-view.js","sources":["../../../../../zql/src/ivm/array-view.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {Immutable} from '../../../shared/src/immutable.ts';\nimport type {ErroredQuery} from '../../../zero-protocol/src/custom-queries.ts';\nimport type {TTL} from '../query/ttl.ts';\nimport type {Listener, ResultType, TypedView} from '../query/typed-view.ts';\nimport type {Change} from './change.ts';\nimport type {Input, Output} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {applyChange} from './view-apply-change.ts';\nimport type {Entry, Format, View} from './view.ts';\n\n/**\n * Implements a materialized view of the output of an operator.\n *\n * It might seem more efficient to use an immutable b-tree for the\n * materialization, but it's not so clear. Inserts in the middle are\n * asymptotically slower in an array, but can often be done with zero\n * allocations, where changes to the b-tree will often require several allocs.\n *\n * Also the plain array view is more convenient for consumers since you can dump\n * it into console to see what it is, rather than having to iterate it.\n */\nexport class ArrayView<V extends View> implements Output, TypedView<V> {\n readonly #input: Input;\n readonly #listeners = new Set<Listener<V>>();\n readonly #schema: SourceSchema;\n readonly #format: Format;\n\n // Synthetic \"root\" entry that has a single \"\" relationship, so that we can\n // treat all changes, including the root change, generically.\n readonly #root: Entry;\n\n onDestroy: (() => void) | undefined;\n\n #dirty = false;\n #resultType: ResultType = 'unknown';\n #error: ErroredQuery | undefined;\n readonly #updateTTL: (ttl: TTL) => void;\n\n constructor(\n input: Input,\n format: Format,\n queryComplete: true | ErroredQuery | Promise<true>,\n updateTTL: (ttl: TTL) => void,\n ) {\n this.#input = input;\n this.#schema = input.getSchema();\n this.#format = format;\n this.#updateTTL = updateTTL;\n this.#root = {'': format.singular ? undefined : []};\n input.setOutput(this);\n\n if (queryComplete === true) {\n this.#resultType = 'complete';\n } else if ('error' in queryComplete) {\n this.#resultType = 'error';\n this.#error = queryComplete;\n } else {\n void queryComplete\n .then(() => {\n this.#resultType = 'complete';\n this.#fireListeners();\n })\n .catch(e => {\n this.#resultType = 'error';\n this.#error = e;\n this.#fireListeners();\n });\n }\n this.#hydrate();\n }\n\n get data() {\n return this.#root[''] as V;\n }\n\n addListener(listener: Listener<V>) {\n assert(!this.#listeners.has(listener), 'Listener already registered');\n this.#listeners.add(listener);\n\n this.#fireListener(listener);\n\n return () => {\n this.#listeners.delete(listener);\n };\n }\n\n #fireListeners() {\n for (const listener of this.#listeners) {\n this.#fireListener(listener);\n }\n }\n\n #fireListener(listener: Listener<V>) {\n listener(this.data as Immutable<V>, this.#resultType, this.#error);\n }\n\n destroy() {\n this.onDestroy?.();\n }\n\n #hydrate() {\n this.#dirty = true;\n for (const node of this.#input.fetch({})) {\n applyChange(\n this.#root,\n {type: 'add', node},\n this.#schema,\n '',\n this.#format,\n );\n }\n this.flush();\n }\n\n push(change: Change): void {\n this.#dirty = true;\n applyChange(this.#root, change, this.#schema, '', this.#format);\n }\n\n flush() {\n if (!this.#dirty) {\n return;\n }\n this.#dirty = false;\n this.#fireListeners();\n }\n\n updateTTL(ttl: TTL) {\n this.#updateTTL(ttl);\n }\n}\n"],"names":[],"mappings":";;AAsBO,MAAM,UAA0D;AAAA,EAC5D;AAAA,EACA,iCAAiB,IAAA;AAAA,EACjB;AAAA,EACA;AAAA;AAAA;AAAA,EAIA;AAAA,EAET;AAAA,EAEA,SAAS;AAAA,EACT,cAA0B;AAAA,EAC1B;AAAA,EACS;AAAA,EAET,YACE,OACA,QACA,eACA,WACA;AACA,SAAK,SAAS;AACd,SAAK,UAAU,MAAM,UAAA;AACrB,SAAK,UAAU;AACf,SAAK,aAAa;AAClB,SAAK,QAAQ,EAAC,IAAI,OAAO,WAAW,SAAY,GAAC;AACjD,UAAM,UAAU,IAAI;AAEpB,QAAI,kBAAkB,MAAM;AAC1B,WAAK,cAAc;AAAA,IACrB,WAAW,WAAW,eAAe;AACnC,WAAK,cAAc;AACnB,WAAK,SAAS;AAAA,IAChB,OAAO;AACL,WAAK,cACF,KAAK,MAAM;AACV,aAAK,cAAc;AACnB,aAAK,eAAA;AAAA,MACP,CAAC,EACA,MAAM,CAAA,MAAK;AACV,aAAK,cAAc;AACnB,aAAK,SAAS;AACd,aAAK,eAAA;AAAA,MACP,CAAC;AAAA,IACL;AACA,SAAK,SAAA;AAAA,EACP;AAAA,EAEA,IAAI,OAAO;AACT,WAAO,KAAK,MAAM,EAAE;AAAA,EACtB;AAAA,EAEA,YAAY,UAAuB;AACjC,WAAO,CAAC,KAAK,WAAW,IAAI,QAAQ,GAAG,6BAA6B;AACpE,SAAK,WAAW,IAAI,QAAQ;AAE5B,SAAK,cAAc,QAAQ;AAE3B,WAAO,MAAM;AACX,WAAK,WAAW,OAAO,QAAQ;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,iBAAiB;AACf,eAAW,YAAY,KAAK,YAAY;AACtC,WAAK,cAAc,QAAQ;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,cAAc,UAAuB;AACnC,aAAS,KAAK,MAAsB,KAAK,aAAa,KAAK,MAAM;AAAA,EACnE;AAAA,EAEA,UAAU;AACR,SAAK,YAAA;AAAA,EACP;AAAA,EAEA,WAAW;AACT,SAAK,SAAS;AACd,eAAW,QAAQ,KAAK,OAAO,MAAM,CAAA,CAAE,GAAG;AACxC;AAAA,QACE,KAAK;AAAA,QACL,EAAC,MAAM,OAAO,KAAA;AAAA,QACd,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MAAA;AAAA,IAET;AACA,SAAK,MAAA;AAAA,EACP;AAAA,EAEA,KAAK,QAAsB;AACzB,SAAK,SAAS;AACd,gBAAY,KAAK,OAAO,QAAQ,KAAK,SAAS,IAAI,KAAK,OAAO;AAAA,EAChE;AAAA,EAEA,QAAQ;AACN,QAAI,CAAC,KAAK,QAAQ;AAChB;AAAA,IACF;AACA,SAAK,SAAS;AACd,SAAK,eAAA;AAAA,EACP;AAAA,EAEA,UAAU,KAAU;AAClB,SAAK,WAAW,GAAG;AAAA,EACrB;AACF;"}
1
+ {"version":3,"file":"array-view.js","sources":["../../../../../zql/src/ivm/array-view.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {Immutable} from '../../../shared/src/immutable.ts';\nimport {emptyArray} from '../../../shared/src/sentinels.ts';\nimport type {ErroredQuery} from '../../../zero-protocol/src/custom-queries.ts';\nimport type {TTL} from '../query/ttl.ts';\nimport type {Listener, ResultType, TypedView} from '../query/typed-view.ts';\nimport type {Change} from './change.ts';\nimport {skipYields, type Input, type Output} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {applyChange} from './view-apply-change.ts';\nimport type {Entry, Format, View} from './view.ts';\n\n/**\n * Implements a materialized view of the output of an operator.\n *\n * It might seem more efficient to use an immutable b-tree for the\n * materialization, but it's not so clear. Inserts in the middle are\n * asymptotically slower in an array, but can often be done with zero\n * allocations, where changes to the b-tree will often require several allocs.\n *\n * Also the plain array view is more convenient for consumers since you can dump\n * it into console to see what it is, rather than having to iterate it.\n */\nexport class ArrayView<V extends View> implements Output, TypedView<V> {\n readonly #input: Input;\n readonly #listeners = new Set<Listener<V>>();\n readonly #schema: SourceSchema;\n readonly #format: Format;\n\n // Synthetic \"root\" entry that has a single \"\" relationship, so that we can\n // treat all changes, including the root change, generically.\n readonly #root: Entry;\n\n onDestroy: (() => void) | undefined;\n\n #dirty = false;\n #resultType: ResultType = 'unknown';\n #error: ErroredQuery | undefined;\n readonly #updateTTL: (ttl: TTL) => void;\n\n constructor(\n input: Input,\n format: Format,\n queryComplete: true | ErroredQuery | Promise<true>,\n updateTTL: (ttl: TTL) => void,\n ) {\n this.#input = input;\n this.#schema = input.getSchema();\n this.#format = format;\n this.#updateTTL = updateTTL;\n this.#root = {'': format.singular ? undefined : []};\n input.setOutput(this);\n\n if (queryComplete === true) {\n this.#resultType = 'complete';\n } else if ('error' in queryComplete) {\n this.#resultType = 'error';\n this.#error = queryComplete;\n } else {\n void queryComplete\n .then(() => {\n this.#resultType = 'complete';\n this.#fireListeners();\n })\n .catch(e => {\n this.#resultType = 'error';\n this.#error = e;\n this.#fireListeners();\n });\n }\n this.#hydrate();\n }\n\n get data() {\n return this.#root[''] as V;\n }\n\n addListener(listener: Listener<V>) {\n assert(!this.#listeners.has(listener), 'Listener already registered');\n this.#listeners.add(listener);\n\n this.#fireListener(listener);\n\n return () => {\n this.#listeners.delete(listener);\n };\n }\n\n #fireListeners() {\n for (const listener of this.#listeners) {\n this.#fireListener(listener);\n }\n }\n\n #fireListener(listener: Listener<V>) {\n listener(this.data as Immutable<V>, this.#resultType, this.#error);\n }\n\n destroy() {\n this.onDestroy?.();\n }\n\n #hydrate() {\n this.#dirty = true;\n for (const node of skipYields(this.#input.fetch({}))) {\n applyChange(\n this.#root,\n {type: 'add', node},\n this.#schema,\n '',\n this.#format,\n );\n }\n this.flush();\n }\n\n push(change: Change) {\n this.#dirty = true;\n applyChange(this.#root, change, this.#schema, '', this.#format);\n return emptyArray;\n }\n\n flush() {\n if (!this.#dirty) {\n return;\n }\n this.#dirty = false;\n this.#fireListeners();\n }\n\n updateTTL(ttl: TTL) {\n this.#updateTTL(ttl);\n }\n}\n"],"names":[],"mappings":";;;;AAuBO,MAAM,UAA0D;AAAA,EAC5D;AAAA,EACA,iCAAiB,IAAA;AAAA,EACjB;AAAA,EACA;AAAA;AAAA;AAAA,EAIA;AAAA,EAET;AAAA,EAEA,SAAS;AAAA,EACT,cAA0B;AAAA,EAC1B;AAAA,EACS;AAAA,EAET,YACE,OACA,QACA,eACA,WACA;AACA,SAAK,SAAS;AACd,SAAK,UAAU,MAAM,UAAA;AACrB,SAAK,UAAU;AACf,SAAK,aAAa;AAClB,SAAK,QAAQ,EAAC,IAAI,OAAO,WAAW,SAAY,GAAC;AACjD,UAAM,UAAU,IAAI;AAEpB,QAAI,kBAAkB,MAAM;AAC1B,WAAK,cAAc;AAAA,IACrB,WAAW,WAAW,eAAe;AACnC,WAAK,cAAc;AACnB,WAAK,SAAS;AAAA,IAChB,OAAO;AACL,WAAK,cACF,KAAK,MAAM;AACV,aAAK,cAAc;AACnB,aAAK,eAAA;AAAA,MACP,CAAC,EACA,MAAM,CAAA,MAAK;AACV,aAAK,cAAc;AACnB,aAAK,SAAS;AACd,aAAK,eAAA;AAAA,MACP,CAAC;AAAA,IACL;AACA,SAAK,SAAA;AAAA,EACP;AAAA,EAEA,IAAI,OAAO;AACT,WAAO,KAAK,MAAM,EAAE;AAAA,EACtB;AAAA,EAEA,YAAY,UAAuB;AACjC,WAAO,CAAC,KAAK,WAAW,IAAI,QAAQ,GAAG,6BAA6B;AACpE,SAAK,WAAW,IAAI,QAAQ;AAE5B,SAAK,cAAc,QAAQ;AAE3B,WAAO,MAAM;AACX,WAAK,WAAW,OAAO,QAAQ;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,iBAAiB;AACf,eAAW,YAAY,KAAK,YAAY;AACtC,WAAK,cAAc,QAAQ;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,cAAc,UAAuB;AACnC,aAAS,KAAK,MAAsB,KAAK,aAAa,KAAK,MAAM;AAAA,EACnE;AAAA,EAEA,UAAU;AACR,SAAK,YAAA;AAAA,EACP;AAAA,EAEA,WAAW;AACT,SAAK,SAAS;AACd,eAAW,QAAQ,WAAW,KAAK,OAAO,MAAM,CAAA,CAAE,CAAC,GAAG;AACpD;AAAA,QACE,KAAK;AAAA,QACL,EAAC,MAAM,OAAO,KAAA;AAAA,QACd,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MAAA;AAAA,IAET;AACA,SAAK,MAAA;AAAA,EACP;AAAA,EAEA,KAAK,QAAgB;AACnB,SAAK,SAAS;AACd,gBAAY,KAAK,OAAO,QAAQ,KAAK,SAAS,IAAI,KAAK,OAAO;AAC9D,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ;AACN,QAAI,CAAC,KAAK,QAAQ;AAChB;AAAA,IACF;AACA,SAAK,SAAS;AACd,SAAK,eAAA;AAAA,EACP;AAAA,EAEA,UAAU,KAAU;AAClB,SAAK,WAAW,GAAG;AAAA,EACrB;AACF;"}
@@ -7,7 +7,12 @@ import type { Stream } from './stream.ts';
7
7
  */
8
8
  export type Node = {
9
9
  row: Row;
10
- relationships: Record<string, () => Stream<Node>>;
10
+ /**
11
+ * Relationships are generated lazily as read.
12
+ * The stream may contain 'yield' to indicate the operator has yielded control.
13
+ * See {@linkcode Operator.fetch} for more details about yields.
14
+ */
15
+ relationships: Record<string, () => Stream<Node | 'yield'>>;
11
16
  };
12
17
  /**
13
18
  * Compare two values. The values must be of the same type. This function
@@ -38,5 +43,5 @@ export declare function makeComparator(order: Ordering, reverse?: boolean): Comp
38
43
  * semantic for your application.
39
44
  */
40
45
  export declare function valuesEqual(a: Value, b: Value): boolean;
41
- export declare function drainStreams(node: Node): void;
46
+ export declare function drainStreams(node: Node | 'yield'): void;
42
47
  //# sourceMappingURL=data.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/data.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,mCAAmC,CAAC;AAChE,OAAO,KAAK,EAAC,GAAG,EAAE,KAAK,EAAC,MAAM,oCAAoC,CAAC;AACnE,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC;;;GAGG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB,GAAG,EAAE,GAAG,CAAC;IACT,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;CACnD,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,MAAM,CAkCxD;AAED,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAExD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,KAAK,GAAG,eAAe,CAE5D;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,KAAK,MAAM,CAAC;AAEtD,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,UAAU,CAa7E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,OAAO,CAMvD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,QAMtC"}
1
+ {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/data.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,mCAAmC,CAAC;AAChE,OAAO,KAAK,EAAC,GAAG,EAAE,KAAK,EAAC,MAAM,oCAAoC,CAAC;AACnE,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC;;;GAGG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB,GAAG,EAAE,GAAG,CAAC;IACT;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC;CAC7D,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,MAAM,CAkCxD;AAED,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAExD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,KAAK,GAAG,eAAe,CAE5D;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,KAAK,MAAM,CAAC;AAEtD,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,UAAU,CAa7E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,OAAO,CAMvD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,QAShD"}
@@ -48,16 +48,8 @@ function valuesEqual(a, b) {
48
48
  }
49
49
  return a === b;
50
50
  }
51
- function drainStreams(node) {
52
- for (const stream of Object.values(node.relationships)) {
53
- for (const node2 of stream()) {
54
- drainStreams(node2);
55
- }
56
- }
57
- }
58
51
  export {
59
52
  compareValues,
60
- drainStreams,
61
53
  makeComparator,
62
54
  normalizeUndefined,
63
55
  valuesEqual
@@ -1 +1 @@
1
- {"version":3,"file":"data.js","sources":["../../../../../zql/src/ivm/data.ts"],"sourcesContent":["import {compareUTF8} from 'compare-utf8';\nimport {\n assertBoolean,\n assertNumber,\n assertString,\n} from '../../../shared/src/asserts.ts';\nimport type {Ordering} from '../../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport type {Stream} from './stream.ts';\n\n/**\n * A row flowing through the pipeline, plus its relationships.\n * Relationships are generated lazily as read.\n */\nexport type Node = {\n row: Row;\n relationships: Record<string, () => Stream<Node>>;\n};\n\n/**\n * Compare two values. The values must be of the same type. This function\n * throws at runtime if the types differ.\n *\n * Note, this function considers `null === null` and\n * `undefined === undefined`. This is different than SQL. In join code,\n * null must be treated separately.\n *\n * See: https://github.com/rocicorp/mono/pull/2116/files#r1704811479\n *\n * @returns < 0 if a < b, 0 if a === b, > 0 if a > b\n */\nexport function compareValues(a: Value, b: Value): number {\n a = normalizeUndefined(a);\n b = normalizeUndefined(b);\n\n if (a === b) {\n return 0;\n }\n if (a === null) {\n return -1;\n }\n if (b === null) {\n return 1;\n }\n if (typeof a === 'boolean') {\n assertBoolean(b);\n return a ? 1 : -1;\n }\n if (typeof a === 'number') {\n assertNumber(b);\n return a - b;\n }\n if (typeof a === 'string') {\n assertString(b);\n // We compare all strings in Zero as UTF-8. This is the default on SQLite\n // and we need to match it. See:\n // https://blog.replicache.dev/blog/replicache-11-adventures-in-text-encoding.\n //\n // TODO: We could change this since SQLite supports UTF-16. Microbenchmark\n // to see if there's a big win.\n //\n // https://www.sqlite.org/c3ref/create_collation.html\n return compareUTF8(a, b);\n }\n throw new Error(`Unsupported type: ${a}`);\n}\n\nexport type NormalizedValue = Exclude<Value, undefined>;\n\n/**\n * We allow undefined to be passed for the convenience of developers, but we\n * treat it equivalently to null. It's better for perf to not create an copy\n * of input values, so we just normalize at use when necessary.\n */\nexport function normalizeUndefined(v: Value): NormalizedValue {\n return v ?? null;\n}\n\nexport type Comparator = (r1: Row, r2: Row) => number;\n\nexport function makeComparator(order: Ordering, reverse?: boolean): Comparator {\n return (a, b) => {\n // Skip destructuring here since it is hot code.\n for (const ord of order) {\n const field = ord[0];\n const comp = compareValues(a[field], b[field]);\n if (comp !== 0) {\n const result = ord[1] === 'asc' ? comp : -comp;\n return reverse ? -result : result;\n }\n }\n return 0;\n };\n}\n\n/**\n * Determine if two values are equal. Note that unlike compareValues() above,\n * this function treats `null` as unequal to itself (and same for `undefined`).\n * This is required to make joins work correctly, but may not be the right\n * semantic for your application.\n */\nexport function valuesEqual(a: Value, b: Value): boolean {\n // oxlint-disable-next-line eqeqeq\n if (a == null || b == null) {\n return false;\n }\n return a === b;\n}\n\nexport function drainStreams(node: Node) {\n for (const stream of Object.values(node.relationships)) {\n for (const node of stream()) {\n drainStreams(node);\n }\n }\n}\n"],"names":["node"],"mappings":";;AA+BO,SAAS,cAAc,GAAU,GAAkB;AACxD,MAAI,mBAAmB,CAAC;AACxB,MAAI,mBAAmB,CAAC;AAExB,MAAI,MAAM,GAAG;AACX,WAAO;AAAA,EACT;AACA,MAAI,MAAM,MAAM;AACd,WAAO;AAAA,EACT;AACA,MAAI,MAAM,MAAM;AACd,WAAO;AAAA,EACT;AACA,MAAI,OAAO,MAAM,WAAW;AAC1B,kBAAc,CAAC;AACf,WAAO,IAAI,IAAI;AAAA,EACjB;AACA,MAAI,OAAO,MAAM,UAAU;AACzB,iBAAa,CAAC;AACd,WAAO,IAAI;AAAA,EACb;AACA,MAAI,OAAO,MAAM,UAAU;AACzB,iBAAa,CAAC;AASd,WAAO,YAAY,GAAG,CAAC;AAAA,EACzB;AACA,QAAM,IAAI,MAAM,qBAAqB,CAAC,EAAE;AAC1C;AASO,SAAS,mBAAmB,GAA2B;AAC5D,SAAO,KAAK;AACd;AAIO,SAAS,eAAe,OAAiB,SAA+B;AAC7E,SAAO,CAAC,GAAG,MAAM;AAEf,eAAW,OAAO,OAAO;AACvB,YAAM,QAAQ,IAAI,CAAC;AACnB,YAAM,OAAO,cAAc,EAAE,KAAK,GAAG,EAAE,KAAK,CAAC;AAC7C,UAAI,SAAS,GAAG;AACd,cAAM,SAAS,IAAI,CAAC,MAAM,QAAQ,OAAO,CAAC;AAC1C,eAAO,UAAU,CAAC,SAAS;AAAA,MAC7B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAQO,SAAS,YAAY,GAAU,GAAmB;AAEvD,MAAI,KAAK,QAAQ,KAAK,MAAM;AAC1B,WAAO;AAAA,EACT;AACA,SAAO,MAAM;AACf;AAEO,SAAS,aAAa,MAAY;AACvC,aAAW,UAAU,OAAO,OAAO,KAAK,aAAa,GAAG;AACtD,eAAWA,SAAQ,UAAU;AAC3B,mBAAaA,KAAI;AAAA,IACnB;AAAA,EACF;AACF;"}
1
+ {"version":3,"file":"data.js","sources":["../../../../../zql/src/ivm/data.ts"],"sourcesContent":["import {compareUTF8} from 'compare-utf8';\nimport {\n assertBoolean,\n assertNumber,\n assertString,\n} from '../../../shared/src/asserts.ts';\nimport type {Ordering} from '../../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport type {Stream} from './stream.ts';\n\n/**\n * A row flowing through the pipeline, plus its relationships.\n * Relationships are generated lazily as read.\n */\nexport type Node = {\n row: Row;\n /**\n * Relationships are generated lazily as read.\n * The stream may contain 'yield' to indicate the operator has yielded control.\n * See {@linkcode Operator.fetch} for more details about yields.\n */\n relationships: Record<string, () => Stream<Node | 'yield'>>;\n};\n\n/**\n * Compare two values. The values must be of the same type. This function\n * throws at runtime if the types differ.\n *\n * Note, this function considers `null === null` and\n * `undefined === undefined`. This is different than SQL. In join code,\n * null must be treated separately.\n *\n * See: https://github.com/rocicorp/mono/pull/2116/files#r1704811479\n *\n * @returns < 0 if a < b, 0 if a === b, > 0 if a > b\n */\nexport function compareValues(a: Value, b: Value): number {\n a = normalizeUndefined(a);\n b = normalizeUndefined(b);\n\n if (a === b) {\n return 0;\n }\n if (a === null) {\n return -1;\n }\n if (b === null) {\n return 1;\n }\n if (typeof a === 'boolean') {\n assertBoolean(b);\n return a ? 1 : -1;\n }\n if (typeof a === 'number') {\n assertNumber(b);\n return a - b;\n }\n if (typeof a === 'string') {\n assertString(b);\n // We compare all strings in Zero as UTF-8. This is the default on SQLite\n // and we need to match it. See:\n // https://blog.replicache.dev/blog/replicache-11-adventures-in-text-encoding.\n //\n // TODO: We could change this since SQLite supports UTF-16. Microbenchmark\n // to see if there's a big win.\n //\n // https://www.sqlite.org/c3ref/create_collation.html\n return compareUTF8(a, b);\n }\n throw new Error(`Unsupported type: ${a}`);\n}\n\nexport type NormalizedValue = Exclude<Value, undefined>;\n\n/**\n * We allow undefined to be passed for the convenience of developers, but we\n * treat it equivalently to null. It's better for perf to not create an copy\n * of input values, so we just normalize at use when necessary.\n */\nexport function normalizeUndefined(v: Value): NormalizedValue {\n return v ?? null;\n}\n\nexport type Comparator = (r1: Row, r2: Row) => number;\n\nexport function makeComparator(order: Ordering, reverse?: boolean): Comparator {\n return (a, b) => {\n // Skip destructuring here since it is hot code.\n for (const ord of order) {\n const field = ord[0];\n const comp = compareValues(a[field], b[field]);\n if (comp !== 0) {\n const result = ord[1] === 'asc' ? comp : -comp;\n return reverse ? -result : result;\n }\n }\n return 0;\n };\n}\n\n/**\n * Determine if two values are equal. Note that unlike compareValues() above,\n * this function treats `null` as unequal to itself (and same for `undefined`).\n * This is required to make joins work correctly, but may not be the right\n * semantic for your application.\n */\nexport function valuesEqual(a: Value, b: Value): boolean {\n // oxlint-disable-next-line eqeqeq\n if (a == null || b == null) {\n return false;\n }\n return a === b;\n}\n\nexport function drainStreams(node: Node | 'yield') {\n if (node === 'yield') {\n return;\n }\n for (const stream of Object.values(node.relationships)) {\n for (const node of stream()) {\n drainStreams(node);\n }\n }\n}\n"],"names":[],"mappings":";;AAoCO,SAAS,cAAc,GAAU,GAAkB;AACxD,MAAI,mBAAmB,CAAC;AACxB,MAAI,mBAAmB,CAAC;AAExB,MAAI,MAAM,GAAG;AACX,WAAO;AAAA,EACT;AACA,MAAI,MAAM,MAAM;AACd,WAAO;AAAA,EACT;AACA,MAAI,MAAM,MAAM;AACd,WAAO;AAAA,EACT;AACA,MAAI,OAAO,MAAM,WAAW;AAC1B,kBAAc,CAAC;AACf,WAAO,IAAI,IAAI;AAAA,EACjB;AACA,MAAI,OAAO,MAAM,UAAU;AACzB,iBAAa,CAAC;AACd,WAAO,IAAI;AAAA,EACb;AACA,MAAI,OAAO,MAAM,UAAU;AACzB,iBAAa,CAAC;AASd,WAAO,YAAY,GAAG,CAAC;AAAA,EACzB;AACA,QAAM,IAAI,MAAM,qBAAqB,CAAC,EAAE;AAC1C;AASO,SAAS,mBAAmB,GAA2B;AAC5D,SAAO,KAAK;AACd;AAIO,SAAS,eAAe,OAAiB,SAA+B;AAC7E,SAAO,CAAC,GAAG,MAAM;AAEf,eAAW,OAAO,OAAO;AACvB,YAAM,QAAQ,IAAI,CAAC;AACnB,YAAM,OAAO,cAAc,EAAE,KAAK,GAAG,EAAE,KAAK,CAAC;AAC7C,UAAI,SAAS,GAAG;AACd,cAAM,SAAS,IAAI,CAAC,MAAM,QAAQ,OAAO,CAAC;AAC1C,eAAO,UAAU,CAAC,SAAS;AAAA,MAC7B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAQO,SAAS,YAAY,GAAU,GAAmB;AAEvD,MAAI,KAAK,QAAQ,KAAK,MAAM;AAC1B,WAAO;AAAA,EACT;AACA,SAAO,MAAM;AACf;"}
@@ -2,19 +2,21 @@ import type { CompoundKey } from '../../../zero-protocol/src/ast.ts';
2
2
  import { type Change } from './change.ts';
3
3
  import { type Node } from './data.ts';
4
4
  import { type FilterInput, type FilterOperator, type FilterOutput } from './filter-operators.ts';
5
- import { type Storage } from './operator.ts';
6
5
  import type { SourceSchema } from './schema.ts';
6
+ import { type Stream } from './stream.ts';
7
7
  /**
8
8
  * The Exists operator filters data based on whether or not a relationship is
9
9
  * non-empty.
10
10
  */
11
11
  export declare class Exists implements FilterOperator {
12
12
  #private;
13
- constructor(input: FilterInput, storage: Storage, relationshipName: string, parentJoinKey: CompoundKey, type: 'EXISTS' | 'NOT EXISTS');
13
+ constructor(input: FilterInput, relationshipName: string, parentJoinKey: CompoundKey, type: 'EXISTS' | 'NOT EXISTS', cacheHitCountsForTesting?: Map<string, number>);
14
14
  setFilterOutput(output: FilterOutput): void;
15
- filter(node: Node, cleanup: boolean): boolean;
15
+ beginFilter(): void;
16
+ endFilter(): void;
17
+ filter(node: Node): Generator<'yield', boolean>;
16
18
  destroy(): void;
17
19
  getSchema(): SourceSchema;
18
- push(change: Change): void;
20
+ push(change: Change): Stream<'yield'>;
19
21
  }
20
22
  //# sourceMappingURL=exists.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"exists.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/exists.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EAAqB,KAAK,IAAI,EAAuB,MAAM,WAAW,CAAC;AAC9E,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAC,KAAK,OAAO,EAAC,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAyB9C;;;GAGG;AACH,qBAAa,MAAO,YAAW,cAAc;;gBAqBzC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,OAAO,EAChB,gBAAgB,EAAE,MAAM,EACxB,aAAa,EAAE,WAAW,EAC1B,IAAI,EAAE,QAAQ,GAAG,YAAY;IAoB/B,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAI3C,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO;IAQ7C,OAAO,IAAI,IAAI;IAIf,SAAS,IAAI,YAAY;IAIzB,IAAI,CAAC,MAAM,EAAE,MAAM;CA4NpB"}
1
+ {"version":3,"file":"exists.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/exists.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EAAqB,KAAK,IAAI,EAAuB,MAAM,WAAW,CAAC;AAC9E,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC;;;GAGG;AACH,qBAAa,MAAO,YAAW,cAAc;;gBAqBzC,KAAK,EAAE,WAAW,EAClB,gBAAgB,EAAE,MAAM,EACxB,aAAa,EAAE,WAAW,EAC1B,IAAI,EAAE,QAAQ,GAAG,YAAY,EAC7B,wBAAwB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAqBhD,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAI3C,WAAW;IAIX,SAAS;IAKR,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC;IAqBhD,OAAO,IAAI,IAAI;IAIf,SAAS,IAAI,YAAY;IAIxB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;CA+JvC"}
@@ -2,14 +2,14 @@ import { areEqual } from "../../../shared/src/arrays.js";
2
2
  import { assert, unreachable } from "../../../shared/src/asserts.js";
3
3
  import { normalizeUndefined } from "./data.js";
4
4
  import { throwFilterOutput } from "./filter-operators.js";
5
- import { first } from "./stream.js";
6
5
  class Exists {
7
6
  #input;
8
7
  #relationshipName;
9
- #storage;
10
8
  #not;
11
9
  #parentJoinKey;
12
10
  #noSizeReuse;
11
+ #cache;
12
+ #cacheHitCountsForTesting;
13
13
  #output = throwFilterOutput;
14
14
  /**
15
15
  * This instance variable is `true` when this operator is processing a `push`,
@@ -20,11 +20,12 @@ class Exists {
20
20
  * Node at a time.
21
21
  */
22
22
  #inPush = false;
23
- constructor(input, storage, relationshipName, parentJoinKey, type) {
23
+ constructor(input, relationshipName, parentJoinKey, type, cacheHitCountsForTesting) {
24
24
  this.#input = input;
25
25
  this.#relationshipName = relationshipName;
26
26
  this.#input.setFilterOutput(this);
27
- this.#storage = storage;
27
+ this.#cache = /* @__PURE__ */ new Map();
28
+ this.#cacheHitCountsForTesting = cacheHitCountsForTesting;
28
29
  assert(
29
30
  this.#input.getSchema().relationships[relationshipName],
30
31
  `Input schema missing ${relationshipName}`
@@ -39,11 +40,29 @@ class Exists {
39
40
  setFilterOutput(output) {
40
41
  this.#output = output;
41
42
  }
42
- filter(node, cleanup) {
43
- const result = this.#filter(node) && this.#output.filter(node, cleanup);
44
- if (cleanup) {
45
- this.#delSize(node);
43
+ beginFilter() {
44
+ this.#output.beginFilter();
45
+ }
46
+ endFilter() {
47
+ this.#cache = /* @__PURE__ */ new Map();
48
+ this.#output.endFilter();
49
+ }
50
+ *filter(node) {
51
+ let exists;
52
+ if (!this.#noSizeReuse && !this.#inPush) {
53
+ const key = this.#getCacheKey(node, this.#parentJoinKey);
54
+ exists = this.#cache.get(key);
55
+ if (exists === void 0) {
56
+ exists = yield* this.#fetchExists(node);
57
+ this.#cache.set(key, exists);
58
+ } else if (this.#cacheHitCountsForTesting) {
59
+ this.#cacheHitCountsForTesting.set(
60
+ key,
61
+ (this.#cacheHitCountsForTesting.get(key) ?? 0) + 1
62
+ );
63
+ }
46
64
  }
65
+ const result = (yield* this.#filter(node, exists)) && (yield* this.#output.filter(node));
47
66
  return result;
48
67
  }
49
68
  destroy() {
@@ -52,7 +71,7 @@ class Exists {
52
71
  getSchema() {
53
72
  return this.#input.getSchema();
54
73
  }
55
- push(change) {
74
+ *push(change) {
56
75
  assert(!this.#inPush, "Unexpected re-entrancy");
57
76
  this.#inPush = true;
58
77
  try {
@@ -60,36 +79,22 @@ class Exists {
60
79
  // add, remove and edit cannot change the size of the
61
80
  // this.#relationshipName relationship, so simply #pushWithFilter
62
81
  case "add":
63
- case "edit": {
64
- this.#pushWithFilter(change);
65
- return;
66
- }
82
+ case "edit":
67
83
  case "remove": {
68
- const size = this.#getSize(change.node);
69
- if (size === void 0) {
70
- return;
71
- }
72
- this.#pushWithFilter(change, size);
73
- this.#delSize(change.node);
84
+ yield* this.#pushWithFilter(change);
74
85
  return;
75
86
  }
76
87
  case "child":
77
88
  if (change.child.relationshipName !== this.#relationshipName || change.child.change.type === "edit" || change.child.change.type === "child") {
78
- this.#pushWithFilter(change);
89
+ yield* this.#pushWithFilter(change);
79
90
  return;
80
91
  }
81
92
  switch (change.child.change.type) {
82
93
  case "add": {
83
- let size = this.#getSize(change.node);
84
- if (size !== void 0) {
85
- size++;
86
- this.#setSize(change.node, size);
87
- } else {
88
- size = this.#fetchSize(change.node);
89
- }
94
+ const size = yield* this.#fetchSize(change.node);
90
95
  if (size === 1) {
91
96
  if (this.#not) {
92
- this.#output.push(
97
+ yield* this.#output.push(
93
98
  {
94
99
  type: "remove",
95
100
  node: {
@@ -103,7 +108,7 @@ class Exists {
103
108
  this
104
109
  );
105
110
  } else {
106
- this.#output.push(
111
+ yield* this.#output.push(
107
112
  {
108
113
  type: "add",
109
114
  node: change.node
@@ -112,22 +117,15 @@ class Exists {
112
117
  );
113
118
  }
114
119
  } else {
115
- this.#pushWithFilter(change, size);
120
+ yield* this.#pushWithFilter(change, size > 0);
116
121
  }
117
122
  return;
118
123
  }
119
124
  case "remove": {
120
- let size = this.#getSize(change.node);
121
- if (size !== void 0) {
122
- assert(size > 0);
123
- size--;
124
- this.#setSize(change.node, size);
125
- } else {
126
- size = this.#fetchSize(change.node);
127
- }
125
+ const size = yield* this.#fetchSize(change.node);
128
126
  if (size === 0) {
129
127
  if (this.#not) {
130
- this.#output.push(
128
+ yield* this.#output.push(
131
129
  {
132
130
  type: "add",
133
131
  node: change.node
@@ -135,7 +133,7 @@ class Exists {
135
133
  this
136
134
  );
137
135
  } else {
138
- this.#output.push(
136
+ yield* this.#output.push(
139
137
  {
140
138
  type: "remove",
141
139
  node: {
@@ -152,7 +150,7 @@ class Exists {
152
150
  );
153
151
  }
154
152
  } else {
155
- this.#pushWithFilter(change, size);
153
+ yield* this.#pushWithFilter(change, size > 0);
156
154
  }
157
155
  return;
158
156
  }
@@ -174,70 +172,41 @@ class Exists {
174
172
  * relationship with this.#relationshipName (this computed size is also
175
173
  * stored).
176
174
  */
177
- #filter(node, size) {
178
- const exists = (size ?? this.#getOrFetchSize(node)) > 0;
175
+ *#filter(node, exists) {
176
+ exists = exists ?? (yield* this.#fetchExists(node));
179
177
  return this.#not ? !exists : exists;
180
178
  }
179
+ #getCacheKey(node, def) {
180
+ const values = [];
181
+ for (const key of def) {
182
+ values.push(normalizeUndefined(node.row[key]));
183
+ }
184
+ return JSON.stringify(values);
185
+ }
181
186
  /**
182
187
  * Pushes a change if this.#filter is true for its row.
183
188
  */
184
- #pushWithFilter(change, size) {
185
- if (this.#filter(change.node, size)) {
186
- this.#output.push(change, this);
189
+ *#pushWithFilter(change, exists) {
190
+ if (yield* this.#filter(change.node, exists)) {
191
+ yield* this.#output.push(change, this);
187
192
  }
188
193
  }
189
- #getSize(node) {
190
- return this.#storage.get(this.#makeSizeStorageKey(node));
191
- }
192
- #setSize(node, size) {
193
- this.#storage.set(this.#makeSizeStorageKey(node), size);
194
- }
195
- #delSize(node) {
196
- this.#storage.del(this.#makeSizeStorageKey(node));
197
- }
198
- #getOrFetchSize(node) {
199
- const size = this.#getSize(node);
200
- if (size !== void 0) {
201
- return size;
202
- }
203
- return this.#fetchSize(node);
194
+ *#fetchExists(node) {
195
+ return (yield* this.#fetchSize(node)) > 0;
204
196
  }
205
- #fetchSize(node) {
206
- if (!this.#noSizeReuse && !this.#inPush) {
207
- const cachedSizeEntry = first(
208
- this.#storage.scan({
209
- prefix: this.#makeSizeStorageKeyPrefix(node)
210
- })
211
- );
212
- if (cachedSizeEntry !== void 0) {
213
- this.#setSize(node, cachedSizeEntry[1]);
214
- return cachedSizeEntry[1];
215
- }
216
- }
197
+ *#fetchSize(node) {
217
198
  const relationship = node.relationships[this.#relationshipName];
218
199
  assert(relationship);
219
200
  let size = 0;
220
- for (const _relatedNode of relationship()) {
221
- size++;
201
+ for (const n of relationship()) {
202
+ if (n === "yield") {
203
+ yield "yield";
204
+ } else {
205
+ size++;
206
+ }
222
207
  }
223
- this.#setSize(node, size);
224
208
  return size;
225
209
  }
226
- #makeSizeStorageKeyPrefix(node) {
227
- return `row/${this.#noSizeReuse ? "" : JSON.stringify(this.#getKeyValues(node, this.#parentJoinKey))}/`;
228
- }
229
- #makeSizeStorageKey(node) {
230
- return `${this.#makeSizeStorageKeyPrefix(node)}${JSON.stringify(
231
- this.#getKeyValues(node, this.#input.getSchema().primaryKey)
232
- )}`;
233
- }
234
- #getKeyValues(node, def) {
235
- const values = [];
236
- for (const key of def) {
237
- values.push(normalizeUndefined(node.row[key]));
238
- }
239
- return values;
240
- }
241
210
  }
242
211
  export {
243
212
  Exists