@rocicorp/zero 0.26.1 → 0.26.2-canary.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.
- package/out/_virtual/_@oxc-project_runtime@0.115.0/helpers/usingCtx.js +57 -0
- package/out/_virtual/_rolldown/runtime.js +27 -0
- package/out/analyze-query/src/bin-analyze.js +195 -283
- package/out/analyze-query/src/bin-analyze.js.map +1 -1
- package/out/analyze-query/src/bin-transform.js +35 -40
- package/out/analyze-query/src/bin-transform.js.map +1 -1
- package/out/analyze-query/src/explain-queries.js +11 -13
- package/out/analyze-query/src/explain-queries.js.map +1 -1
- package/out/analyze-query/src/run-ast.js +68 -103
- package/out/analyze-query/src/run-ast.js.map +1 -1
- package/out/ast-to-zql/src/ast-to-zql.js +105 -153
- package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
- package/out/ast-to-zql/src/bin.js +57 -62
- package/out/ast-to-zql/src/bin.js.map +1 -1
- package/out/ast-to-zql/src/format.js +14 -13
- package/out/ast-to-zql/src/format.js.map +1 -1
- package/out/datadog/src/datadog-log-sink.js +148 -213
- package/out/datadog/src/datadog-log-sink.js.map +1 -1
- package/out/otel/src/enabled.js +9 -11
- package/out/otel/src/enabled.js.map +1 -1
- package/out/otel/src/log-options.js +25 -35
- package/out/otel/src/log-options.js.map +1 -1
- package/out/otel/src/maybe-time.js +13 -14
- package/out/otel/src/maybe-time.js.map +1 -1
- package/out/otel/src/span.js +23 -26
- package/out/otel/src/span.js.map +1 -1
- package/out/otel/src/test-log-config.js +11 -10
- package/out/otel/src/test-log-config.js.map +1 -1
- package/out/otel/src/version.js +6 -5
- package/out/otel/src/version.js.map +1 -1
- package/out/replicache/src/async-iterable-to-array.js +8 -9
- package/out/replicache/src/async-iterable-to-array.js.map +1 -1
- package/out/replicache/src/bg-interval.js +28 -35
- package/out/replicache/src/bg-interval.js.map +1 -1
- package/out/replicache/src/btree/diff.js +6 -5
- package/out/replicache/src/btree/diff.js.map +1 -1
- package/out/replicache/src/btree/node.js +281 -372
- package/out/replicache/src/btree/node.js.map +1 -1
- package/out/replicache/src/btree/read.js +155 -256
- package/out/replicache/src/btree/read.js.map +1 -1
- package/out/replicache/src/btree/splice.js +60 -80
- package/out/replicache/src/btree/splice.js.map +1 -1
- package/out/replicache/src/btree/write.js +134 -158
- package/out/replicache/src/btree/write.js.map +1 -1
- package/out/replicache/src/call-default-fetch.js +28 -32
- package/out/replicache/src/call-default-fetch.js.map +1 -1
- package/out/replicache/src/config.js +2 -0
- package/out/replicache/src/connection-loop-delegates.js +31 -33
- package/out/replicache/src/connection-loop-delegates.js.map +1 -1
- package/out/replicache/src/connection-loop.js +174 -240
- package/out/replicache/src/connection-loop.js.map +1 -1
- package/out/replicache/src/cookies.js +22 -32
- package/out/replicache/src/cookies.js.map +1 -1
- package/out/replicache/src/dag/chunk.js +44 -50
- package/out/replicache/src/dag/chunk.js.map +1 -1
- package/out/replicache/src/dag/gc.js +94 -114
- package/out/replicache/src/dag/gc.js.map +1 -1
- package/out/replicache/src/dag/key.js +9 -11
- package/out/replicache/src/dag/key.js.map +1 -1
- package/out/replicache/src/dag/lazy-store.js +458 -510
- package/out/replicache/src/dag/lazy-store.js.map +1 -1
- package/out/replicache/src/dag/store-impl.js +147 -178
- package/out/replicache/src/dag/store-impl.js.map +1 -1
- package/out/replicache/src/dag/store.js +19 -22
- package/out/replicache/src/dag/store.js.map +1 -1
- package/out/replicache/src/dag/visitor.js +23 -21
- package/out/replicache/src/dag/visitor.js.map +1 -1
- package/out/replicache/src/db/commit.js +209 -283
- package/out/replicache/src/db/commit.js.map +1 -1
- package/out/replicache/src/db/index.js +79 -122
- package/out/replicache/src/db/index.js.map +1 -1
- package/out/replicache/src/db/read.js +44 -60
- package/out/replicache/src/db/read.js.map +1 -1
- package/out/replicache/src/db/rebase.js +22 -77
- package/out/replicache/src/db/rebase.js.map +1 -1
- package/out/replicache/src/db/write.js +162 -296
- package/out/replicache/src/db/write.js.map +1 -1
- package/out/replicache/src/deleted-clients.js +59 -87
- package/out/replicache/src/deleted-clients.js.map +1 -1
- package/out/replicache/src/error-responses.js +18 -26
- package/out/replicache/src/error-responses.js.map +1 -1
- package/out/replicache/src/expo-sqlite.js +2 -0
- package/out/replicache/src/frozen-json.js +74 -108
- package/out/replicache/src/frozen-json.js.map +1 -1
- package/out/replicache/src/get-default-puller.js +34 -46
- package/out/replicache/src/get-default-puller.js.map +1 -1
- package/out/replicache/src/get-default-pusher.js +25 -33
- package/out/replicache/src/get-default-pusher.js.map +1 -1
- package/out/replicache/src/get-kv-store-provider.js +18 -20
- package/out/replicache/src/get-kv-store-provider.js.map +1 -1
- package/out/replicache/src/hash.js +29 -29
- package/out/replicache/src/hash.js.map +1 -1
- package/out/replicache/src/http-request-info.js +9 -8
- package/out/replicache/src/http-request-info.js.map +1 -1
- package/out/replicache/src/impl.js +2 -0
- package/out/replicache/src/index-defs.js +17 -28
- package/out/replicache/src/index-defs.js.map +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.js +52 -50
- package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js +71 -68
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +1 -1
- package/out/replicache/src/kv/idb-store.js +144 -168
- package/out/replicache/src/kv/idb-store.js.map +1 -1
- package/out/replicache/src/kv/mem-store.js +57 -45
- package/out/replicache/src/kv/mem-store.js.map +1 -1
- package/out/replicache/src/kv/op-sqlite/store.js +56 -62
- package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
- package/out/replicache/src/kv/op-sqlite/types.d.ts.map +1 -1
- package/out/replicache/src/kv/op-sqlite/types.js +7 -6
- package/out/replicache/src/kv/op-sqlite/types.js.map +1 -1
- package/out/replicache/src/kv/read-impl.js +26 -25
- package/out/replicache/src/kv/read-impl.js.map +1 -1
- package/out/replicache/src/kv/sqlite-store.js +194 -207
- package/out/replicache/src/kv/sqlite-store.js.map +1 -1
- package/out/replicache/src/kv/throw-if-closed.js +12 -19
- package/out/replicache/src/kv/throw-if-closed.js.map +1 -1
- package/out/replicache/src/kv/write-impl-base.js +44 -56
- package/out/replicache/src/kv/write-impl-base.js.map +1 -1
- package/out/replicache/src/kv/write-impl.js +22 -26
- package/out/replicache/src/kv/write-impl.js.map +1 -1
- package/out/replicache/src/lazy.js +10 -11
- package/out/replicache/src/lazy.js.map +1 -1
- package/out/replicache/src/log-options.js +14 -7
- package/out/replicache/src/log-options.js.map +1 -1
- package/out/replicache/src/make-idb-name.js +14 -9
- package/out/replicache/src/make-idb-name.js.map +1 -1
- package/out/replicache/src/mutation-recovery.js +12 -0
- package/out/replicache/src/mutation-recovery.js.map +1 -0
- package/out/replicache/src/new-client-channel.js +34 -42
- package/out/replicache/src/new-client-channel.js.map +1 -1
- package/out/replicache/src/on-persist-channel.js +26 -29
- package/out/replicache/src/on-persist-channel.js.map +1 -1
- package/out/replicache/src/op-sqlite.js +2 -0
- package/out/replicache/src/patch-operation.js +27 -36
- package/out/replicache/src/patch-operation.js.map +1 -1
- package/out/replicache/src/pending-mutations.js +14 -12
- package/out/replicache/src/pending-mutations.js.map +1 -1
- package/out/replicache/src/persist/client-gc.js +36 -51
- package/out/replicache/src/persist/client-gc.js.map +1 -1
- package/out/replicache/src/persist/client-group-gc.js +29 -36
- package/out/replicache/src/persist/client-group-gc.js.map +1 -1
- package/out/replicache/src/persist/client-groups.js +80 -154
- package/out/replicache/src/persist/client-groups.js.map +1 -1
- package/out/replicache/src/persist/clients.js +212 -307
- package/out/replicache/src/persist/clients.js.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.js +109 -171
- package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
- package/out/replicache/src/persist/gather-mem-only-visitor.js +23 -24
- package/out/replicache/src/persist/gather-mem-only-visitor.js.map +1 -1
- package/out/replicache/src/persist/gather-not-cached-visitor.js +35 -33
- package/out/replicache/src/persist/gather-not-cached-visitor.js.map +1 -1
- package/out/replicache/src/persist/heartbeat.js +31 -41
- package/out/replicache/src/persist/heartbeat.js.map +1 -1
- package/out/replicache/src/persist/idb-databases-store-db-name.js +9 -12
- package/out/replicache/src/persist/idb-databases-store-db-name.js.map +1 -1
- package/out/replicache/src/persist/idb-databases-store.js +78 -97
- package/out/replicache/src/persist/idb-databases-store.js.map +1 -1
- package/out/replicache/src/persist/make-client-id.js +13 -9
- package/out/replicache/src/persist/make-client-id.js.map +1 -1
- package/out/replicache/src/persist/persist.js +113 -174
- package/out/replicache/src/persist/persist.js.map +1 -1
- package/out/replicache/src/persist/refresh.js +94 -183
- package/out/replicache/src/persist/refresh.js.map +1 -1
- package/out/replicache/src/process-scheduler.js +122 -143
- package/out/replicache/src/process-scheduler.js.map +1 -1
- package/out/replicache/src/pusher.js +21 -26
- package/out/replicache/src/pusher.js.map +1 -1
- package/out/replicache/src/replicache-impl.js +844 -1184
- package/out/replicache/src/replicache-impl.js.map +1 -1
- package/out/replicache/src/report-error.js +9 -6
- package/out/replicache/src/report-error.js.map +1 -1
- package/out/replicache/src/request-idle.js +13 -11
- package/out/replicache/src/request-idle.js.map +1 -1
- package/out/replicache/src/scan-iterator.d.ts.map +1 -1
- package/out/replicache/src/scan-iterator.js +108 -135
- package/out/replicache/src/scan-iterator.js.map +1 -1
- package/out/replicache/src/scan-options.js +33 -39
- package/out/replicache/src/scan-options.js.map +1 -1
- package/out/replicache/src/set-interval-with-signal.js +11 -10
- package/out/replicache/src/set-interval-with-signal.js.map +1 -1
- package/out/replicache/src/sqlite.js +2 -0
- package/out/replicache/src/subscriptions.js +222 -338
- package/out/replicache/src/subscriptions.js.map +1 -1
- package/out/replicache/src/sync/diff.js +52 -65
- package/out/replicache/src/sync/diff.js.map +1 -1
- package/out/replicache/src/sync/ids.js +8 -9
- package/out/replicache/src/sync/ids.js.map +1 -1
- package/out/replicache/src/sync/patch.js +34 -45
- package/out/replicache/src/sync/patch.js.map +1 -1
- package/out/replicache/src/sync/pull-error.js +15 -15
- package/out/replicache/src/sync/pull-error.js.map +1 -1
- package/out/replicache/src/sync/pull.js +145 -283
- package/out/replicache/src/sync/pull.js.map +1 -1
- package/out/replicache/src/sync/push.js +64 -79
- package/out/replicache/src/sync/push.js.map +1 -1
- package/out/replicache/src/sync/request-id.js +23 -15
- package/out/replicache/src/sync/request-id.js.map +1 -1
- package/out/replicache/src/sync/sync-head-name.js +6 -5
- package/out/replicache/src/sync/sync-head-name.js.map +1 -1
- package/out/replicache/src/to-error.js +7 -8
- package/out/replicache/src/to-error.js.map +1 -1
- package/out/replicache/src/transaction-closed-error.js +15 -15
- package/out/replicache/src/transaction-closed-error.js.map +1 -1
- package/out/replicache/src/transactions.js +120 -140
- package/out/replicache/src/transactions.js.map +1 -1
- package/out/replicache/src/version.js +9 -5
- package/out/replicache/src/version.js.map +1 -1
- package/out/replicache/src/with-transactions.js +23 -20
- package/out/replicache/src/with-transactions.js.map +1 -1
- package/out/shared/src/abort-error.js +7 -6
- package/out/shared/src/abort-error.js.map +1 -1
- package/out/shared/src/arrays.js +35 -42
- package/out/shared/src/arrays.js.map +1 -1
- package/out/shared/src/asserts.js +21 -45
- package/out/shared/src/asserts.js.map +1 -1
- package/out/shared/src/bigint-json.js +42 -38
- package/out/shared/src/bigint-json.js.map +1 -1
- package/out/shared/src/binary-search.js +27 -18
- package/out/shared/src/binary-search.js.map +1 -1
- package/out/shared/src/broadcast-channel.js +20 -23
- package/out/shared/src/broadcast-channel.js.map +1 -1
- package/out/shared/src/browser-env.js +11 -17
- package/out/shared/src/browser-env.js.map +1 -1
- package/out/shared/src/btree-set.js +419 -481
- package/out/shared/src/btree-set.js.map +1 -1
- package/out/shared/src/cache.js +43 -36
- package/out/shared/src/cache.js.map +1 -1
- package/out/shared/src/centroid.js +24 -26
- package/out/shared/src/centroid.js.map +1 -1
- package/out/shared/src/config.js +6 -6
- package/out/shared/src/config.js.map +1 -1
- package/out/shared/src/custom-key-map.js +54 -58
- package/out/shared/src/custom-key-map.js.map +1 -1
- package/out/shared/src/custom-key-set.js +53 -51
- package/out/shared/src/custom-key-set.js.map +1 -1
- package/out/shared/src/deep-clone.js +30 -41
- package/out/shared/src/deep-clone.js.map +1 -1
- package/out/shared/src/deep-merge.js +25 -24
- package/out/shared/src/deep-merge.js.map +1 -1
- package/out/shared/src/document-visible.js +63 -70
- package/out/shared/src/document-visible.js.map +1 -1
- package/out/shared/src/dotenv.js +7 -3
- package/out/shared/src/dotenv.js.map +1 -1
- package/out/shared/src/error.js +43 -64
- package/out/shared/src/error.js.map +1 -1
- package/out/shared/src/has-own.js +6 -5
- package/out/shared/src/has-own.js.map +1 -1
- package/out/shared/src/hash.js +15 -14
- package/out/shared/src/hash.js.map +1 -1
- package/out/shared/src/iterables.js +34 -47
- package/out/shared/src/iterables.js.map +1 -1
- package/out/shared/src/json-schema.js +25 -30
- package/out/shared/src/json-schema.js.map +1 -1
- package/out/shared/src/json.js +90 -129
- package/out/shared/src/json.js.map +1 -1
- package/out/shared/src/logging-test-utils.js +9 -11
- package/out/shared/src/logging-test-utils.js.map +1 -1
- package/out/shared/src/logging.js +75 -95
- package/out/shared/src/logging.js.map +1 -1
- package/out/shared/src/must.js +7 -8
- package/out/shared/src/must.js.map +1 -1
- package/out/shared/src/navigator.js +6 -5
- package/out/shared/src/navigator.js.map +1 -1
- package/out/shared/src/object-traversal.js +23 -23
- package/out/shared/src/object-traversal.js.map +1 -1
- package/out/shared/src/objects.js +15 -18
- package/out/shared/src/objects.js.map +1 -1
- package/out/shared/src/options.js +225 -302
- package/out/shared/src/options.js.map +1 -1
- package/out/shared/src/parse-big-int.js +12 -11
- package/out/shared/src/parse-big-int.js.map +1 -1
- package/out/shared/src/promise-race.js +21 -17
- package/out/shared/src/promise-race.js.map +1 -1
- package/out/shared/src/queue.js +124 -124
- package/out/shared/src/queue.js.map +1 -1
- package/out/shared/src/rand.js +13 -7
- package/out/shared/src/rand.js.map +1 -1
- package/out/shared/src/random-uint64.js +8 -7
- package/out/shared/src/random-uint64.js.map +1 -1
- package/out/shared/src/random-values.js +8 -11
- package/out/shared/src/random-values.js.map +1 -1
- package/out/shared/src/record-proxy.js +68 -57
- package/out/shared/src/record-proxy.js.map +1 -1
- package/out/shared/src/resolved-promises.js +9 -11
- package/out/shared/src/resolved-promises.js.map +1 -1
- package/out/shared/src/sentinels.js +9 -12
- package/out/shared/src/sentinels.js.map +1 -1
- package/out/shared/src/set-utils.js +41 -63
- package/out/shared/src/set-utils.js.map +1 -1
- package/out/shared/src/size-of-value.js +55 -51
- package/out/shared/src/size-of-value.js.map +1 -1
- package/out/shared/src/sleep.js +50 -45
- package/out/shared/src/sleep.js.map +1 -1
- package/out/shared/src/string-compare.js +8 -11
- package/out/shared/src/string-compare.js.map +1 -1
- package/out/shared/src/subscribable.js +34 -33
- package/out/shared/src/subscribable.js.map +1 -1
- package/out/shared/src/tdigest-schema.js +11 -7
- package/out/shared/src/tdigest-schema.js.map +1 -1
- package/out/shared/src/tdigest.js +197 -270
- package/out/shared/src/tdigest.js.map +1 -1
- package/out/shared/src/valita.js +145 -174
- package/out/shared/src/valita.js.map +1 -1
- package/out/z2s/src/compiler.d.ts.map +1 -1
- package/out/z2s/src/compiler.js +238 -468
- package/out/z2s/src/compiler.js.map +1 -1
- package/out/z2s/src/sql.d.ts +0 -1
- package/out/z2s/src/sql.d.ts.map +1 -1
- package/out/z2s/src/sql.js +149 -194
- package/out/z2s/src/sql.js.map +1 -1
- package/out/zero/package.js +193 -0
- package/out/zero/package.js.map +1 -0
- package/out/zero/src/adapters/drizzle.js +1 -6
- package/out/zero/src/adapters/pg.js +1 -6
- package/out/zero/src/adapters/postgresjs.js +1 -6
- package/out/zero/src/adapters/prisma.js +1 -5
- package/out/zero/src/analyze-query.js +1 -1
- package/out/zero/src/ast-to-zql.js +1 -1
- package/out/zero/src/bindings.js +6 -21
- package/out/zero/src/build-schema.js +5 -1
- package/out/zero/src/build-schema.js.map +1 -1
- package/out/zero/src/change-protocol/v0.js +3 -5
- package/out/zero/src/cli.js +2 -2
- package/out/zero/src/deploy-permissions.js +1 -1
- package/out/zero/src/expo-sqlite.js +2 -4
- package/out/zero/src/op-sqlite.js +2 -4
- package/out/zero/src/pg.js +2 -20
- package/out/zero/src/react-native.js +16 -12
- package/out/zero/src/react-native.js.map +1 -1
- package/out/zero/src/react.js +3 -12
- package/out/zero/src/server/runner/main.js +2 -0
- package/out/zero/src/server.js +2 -17
- package/out/zero/src/solid.js +3 -12
- package/out/zero/src/sqlite.js +2 -6
- package/out/zero/src/transform-query.js +1 -1
- package/out/zero/src/zero-cache-dev.js +124 -151
- package/out/zero/src/zero-cache-dev.js.map +1 -1
- package/out/zero/src/zero-out.js +9 -6
- package/out/zero/src/zero-out.js.map +1 -1
- package/out/zero/src/zero.js +6 -55
- package/out/zero/src/zqlite.js +2 -7
- package/out/zero-cache/src/auth/auth.js +138 -172
- package/out/zero-cache/src/auth/auth.js.map +1 -1
- package/out/zero-cache/src/auth/jwt.js +25 -33
- package/out/zero-cache/src/auth/jwt.js.map +1 -1
- package/out/zero-cache/src/auth/load-permissions.js +54 -62
- package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
- package/out/zero-cache/src/auth/read-authorizer.js +70 -80
- package/out/zero-cache/src/auth/read-authorizer.js.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.js +284 -432
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/network.js +31 -45
- package/out/zero-cache/src/config/network.js.map +1 -1
- package/out/zero-cache/src/config/normalize.js +81 -83
- package/out/zero-cache/src/config/normalize.js.map +1 -1
- package/out/zero-cache/src/config/server-context.js +32 -29
- package/out/zero-cache/src/config/server-context.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +753 -833
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/custom/fetch.js +183 -230
- package/out/zero-cache/src/custom/fetch.js.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.js +93 -99
- package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
- package/out/zero-cache/src/db/create.js +27 -29
- package/out/zero-cache/src/db/create.js.map +1 -1
- package/out/zero-cache/src/db/delete-lite-db.js +11 -7
- package/out/zero-cache/src/db/delete-lite-db.js.map +1 -1
- package/out/zero-cache/src/db/lite-tables.js +118 -158
- package/out/zero-cache/src/db/lite-tables.js.map +1 -1
- package/out/zero-cache/src/db/migration-lite.js +110 -178
- package/out/zero-cache/src/db/migration-lite.js.map +1 -1
- package/out/zero-cache/src/db/migration.js +82 -151
- package/out/zero-cache/src/db/migration.js.map +1 -1
- package/out/zero-cache/src/db/mode-enum.js +8 -9
- package/out/zero-cache/src/db/mode-enum.js.map +1 -1
- package/out/zero-cache/src/db/pg-copy.js +56 -54
- package/out/zero-cache/src/db/pg-copy.js.map +1 -1
- package/out/zero-cache/src/db/pg-to-lite.js +74 -110
- package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
- package/out/zero-cache/src/db/pg-type-parser.js +19 -36
- package/out/zero-cache/src/db/pg-type-parser.js.map +1 -1
- package/out/zero-cache/src/db/run-transaction.js +19 -20
- package/out/zero-cache/src/db/run-transaction.js.map +1 -1
- package/out/zero-cache/src/db/specs.js +42 -78
- package/out/zero-cache/src/db/specs.js.map +1 -1
- package/out/zero-cache/src/db/statements.js +52 -59
- package/out/zero-cache/src/db/statements.js.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.js +376 -400
- package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
- package/out/zero-cache/src/db/warmup.js +13 -24
- package/out/zero-cache/src/db/warmup.js.map +1 -1
- package/out/zero-cache/src/observability/events.js +89 -99
- package/out/zero-cache/src/observability/events.js.map +1 -1
- package/out/zero-cache/src/observability/metrics.js +30 -54
- package/out/zero-cache/src/observability/metrics.js.map +1 -1
- package/out/zero-cache/src/scripts/decommission.js +42 -47
- package/out/zero-cache/src/scripts/decommission.js.map +1 -1
- package/out/zero-cache/src/scripts/deploy-permissions.js +106 -144
- package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
- package/out/zero-cache/src/scripts/permissions.js +86 -107
- package/out/zero-cache/src/scripts/permissions.js.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.js +306 -440
- package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +57 -130
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.js +89 -100
- package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
- package/out/zero-cache/src/server/logging.js +18 -26
- package/out/zero-cache/src/server/logging.js.map +1 -1
- package/out/zero-cache/src/server/main.js +85 -142
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/mutator.js +16 -13
- package/out/zero-cache/src/server/mutator.js.map +1 -1
- package/out/zero-cache/src/server/otel-diag-logger.js +42 -49
- package/out/zero-cache/src/server/otel-diag-logger.js.map +1 -1
- package/out/zero-cache/src/server/otel-log-sink.js +34 -44
- package/out/zero-cache/src/server/otel-log-sink.js.map +1 -1
- package/out/zero-cache/src/server/otel-start.js +43 -51
- package/out/zero-cache/src/server/otel-start.js.map +1 -1
- package/out/zero-cache/src/server/priority-op.js +27 -25
- package/out/zero-cache/src/server/priority-op.js.map +1 -1
- package/out/zero-cache/src/server/reaper.js +32 -43
- package/out/zero-cache/src/server/reaper.js.map +1 -1
- package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/server/replicator.js +41 -57
- package/out/zero-cache/src/server/replicator.js.map +1 -1
- package/out/zero-cache/src/server/runner/main.js +7 -8
- package/out/zero-cache/src/server/runner/main.js.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.js +56 -52
- package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
- package/out/zero-cache/src/server/runner/runtime.js +26 -32
- package/out/zero-cache/src/server/runner/runtime.js.map +1 -1
- package/out/zero-cache/src/server/runner/zero-dispatcher.js +22 -27
- package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
- package/out/zero-cache/src/server/syncer.js +79 -148
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/server/worker-dispatcher.js +84 -113
- package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
- package/out/zero-cache/src/server/worker-urls.d.ts +2 -1
- package/out/zero-cache/src/server/worker-urls.d.ts.map +1 -1
- package/out/zero-cache/src/server/worker-urls.js +14 -18
- package/out/zero-cache/src/server/worker-urls.js.map +1 -1
- package/out/zero-cache/src/server/write-worker.js +2 -0
- package/out/zero-cache/src/services/analyze.js +61 -130
- package/out/zero-cache/src/services/analyze.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js +420 -419
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +111 -114
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/replica-schema.js +80 -148
- package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +154 -216
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js +11 -14
- package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +168 -212
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.js +672 -892
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/decommission.js +19 -23
- package/out/zero-cache/src/services/change-source/pg/decommission.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +258 -411
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js +59 -65
- package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput-parser.js +218 -247
- package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput-parser.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +100 -142
- package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/lsn.js +17 -19
- package/out/zero-cache/src/services/change-source/pg/lsn.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +88 -98
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/init.js +96 -177
- package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/published.js +69 -107
- package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js +151 -212
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/validation.js +22 -53
- package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/control.js +24 -12
- package/out/zero-cache/src/services/change-source/protocol/current/control.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/data.js +180 -290
- package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.js +21 -33
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/json.js +7 -18
- package/out/zero-cache/src/services/change-source/protocol/current/json.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/path.js +24 -5
- package/out/zero-cache/src/services/change-source/protocol/current/path.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/status.js +25 -19
- package/out/zero-cache/src/services/change-source/protocol/current/status.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.js +24 -16
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current.js +51 -46
- package/out/zero-cache/src/services/change-source/protocol/current.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/mod.js +2 -0
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js +165 -171
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/broadcast.js +163 -169
- package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +154 -221
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +340 -299
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.js +17 -24
- package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.js +84 -103
- package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/replica-monitor.js +49 -43
- package/out/zero-cache/src/services/change-streamer/replica-monitor.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/init.js +61 -89
- package/out/zero-cache/src/services/change-streamer/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +20 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.js +131 -109
- package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.js +26 -28
- package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js +434 -513
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js +142 -155
- package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
- package/out/zero-cache/src/services/heapz.js +18 -20
- package/out/zero-cache/src/services/heapz.js.map +1 -1
- package/out/zero-cache/src/services/http-service.js +59 -57
- package/out/zero-cache/src/services/http-service.js.map +1 -1
- package/out/zero-cache/src/services/life-cycle.js +182 -214
- package/out/zero-cache/src/services/life-cycle.js.map +1 -1
- package/out/zero-cache/src/services/limiter/sliding-window-limiter.js +102 -81
- package/out/zero-cache/src/services/limiter/sliding-window-limiter.js.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.js +144 -205
- package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/error.js +10 -14
- package/out/zero-cache/src/services/mutagen/error.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +166 -264
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +372 -487
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.js +483 -592
- package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +4 -2
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js +118 -143
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
- package/out/zero-cache/src/services/replicator/notifier.js +52 -28
- package/out/zero-cache/src/services/replicator/notifier.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.js +105 -128
- package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts +2 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.js +32 -34
- package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/change-log.js +101 -133
- package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/column-metadata.js +145 -174
- package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/constants.js +11 -5
- package/out/zero-cache/src/services/replicator/schema/constants.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/replication-state.js +56 -107
- package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/table-metadata.js +81 -66
- package/out/zero-cache/src/services/replicator/schema/table-metadata.js.map +1 -1
- package/out/zero-cache/src/services/replicator/write-worker-client.d.ts +69 -0
- package/out/zero-cache/src/services/replicator/write-worker-client.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/write-worker-client.js +96 -0
- package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -0
- package/out/zero-cache/src/services/replicator/write-worker.js +68 -0
- package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -0
- package/out/zero-cache/src/services/run-ast.js +79 -120
- package/out/zero-cache/src/services/run-ast.js.map +1 -1
- package/out/zero-cache/src/services/runner.js +39 -41
- package/out/zero-cache/src/services/runner.js.map +1 -1
- package/out/zero-cache/src/services/running-state.js +129 -134
- package/out/zero-cache/src/services/running-state.js.map +1 -1
- package/out/zero-cache/src/services/statz.js +139 -200
- package/out/zero-cache/src/services/statz.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/active-users-gauge.js +46 -49
- package/out/zero-cache/src/services/view-syncer/active-users-gauge.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.js +257 -299
- package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-schema.js +52 -82
- package/out/zero-cache/src/services/view-syncer/client-schema.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-purger.js +85 -107
- package/out/zero-cache/src/services/view-syncer/cvr-purger.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +604 -757
- package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +631 -739
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +60 -40
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js +95 -178
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +572 -722
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js +246 -257
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js +59 -45
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/init.js +121 -189
- package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/types.js +138 -263
- package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +322 -335
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/tracer.js +7 -6
- package/out/zero-cache/src/services/view-syncer/tracer.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/ttl-clock.js +9 -11
- package/out/zero-cache/src/services/view-syncer/ttl-clock.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +1067 -1603
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/error-with-level.js +19 -25
- package/out/zero-cache/src/types/error-with-level.js.map +1 -1
- package/out/zero-cache/src/types/http.js +17 -26
- package/out/zero-cache/src/types/http.js.map +1 -1
- package/out/zero-cache/src/types/lexi-version.js +28 -42
- package/out/zero-cache/src/types/lexi-version.js.map +1 -1
- package/out/zero-cache/src/types/lite.js +101 -121
- package/out/zero-cache/src/types/lite.js.map +1 -1
- package/out/zero-cache/src/types/names.js +6 -5
- package/out/zero-cache/src/types/names.js.map +1 -1
- package/out/zero-cache/src/types/pg-data-type.d.ts +1 -0
- package/out/zero-cache/src/types/pg-data-type.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg-data-type.js +58 -73
- package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
- package/out/zero-cache/src/types/pg-types.js +12 -19
- package/out/zero-cache/src/types/pg-types.js.map +1 -1
- package/out/zero-cache/src/types/pg.js +144 -218
- package/out/zero-cache/src/types/pg.js.map +1 -1
- package/out/zero-cache/src/types/processes.js +95 -90
- package/out/zero-cache/src/types/processes.js.map +1 -1
- package/out/zero-cache/src/types/profiler.js +32 -27
- package/out/zero-cache/src/types/profiler.js.map +1 -1
- package/out/zero-cache/src/types/row-key.js +42 -30
- package/out/zero-cache/src/types/row-key.js.map +1 -1
- package/out/zero-cache/src/types/shards.js +36 -45
- package/out/zero-cache/src/types/shards.js.map +1 -1
- package/out/zero-cache/src/types/sql.js +20 -9
- package/out/zero-cache/src/types/sql.js.map +1 -1
- package/out/zero-cache/src/types/state-version.js +17 -23
- package/out/zero-cache/src/types/state-version.js.map +1 -1
- package/out/zero-cache/src/types/streams.js +234 -270
- package/out/zero-cache/src/types/streams.js.map +1 -1
- package/out/zero-cache/src/types/strings.js +10 -13
- package/out/zero-cache/src/types/strings.js.map +1 -1
- package/out/zero-cache/src/types/subscription.js +266 -226
- package/out/zero-cache/src/types/subscription.js.map +1 -1
- package/out/zero-cache/src/types/url-params.js +30 -39
- package/out/zero-cache/src/types/url-params.js.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.js +62 -75
- package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
- package/out/zero-cache/src/types/ws.js +43 -53
- package/out/zero-cache/src/types/ws.js.map +1 -1
- package/out/zero-cache/src/workers/connect-params.js +42 -43
- package/out/zero-cache/src/workers/connect-params.js.map +1 -1
- package/out/zero-cache/src/workers/connection.js +213 -282
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/mutator.js +22 -21
- package/out/zero-cache/src/workers/mutator.js.map +1 -1
- package/out/zero-cache/src/workers/replicator.d.ts +7 -0
- package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/workers/replicator.js +92 -97
- package/out/zero-cache/src/workers/replicator.js.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js +121 -203
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +147 -201
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/active-clients-manager.js +178 -187
- package/out/zero-client/src/client/active-clients-manager.js.map +1 -1
- package/out/zero-client/src/client/bindings.js +11 -0
- package/out/zero-client/src/client/client-error-kind-enum.js +18 -29
- package/out/zero-client/src/client/client-error-kind-enum.js.map +1 -1
- package/out/zero-client/src/client/connection-manager.js +291 -346
- package/out/zero-client/src/client/connection-manager.js.map +1 -1
- package/out/zero-client/src/client/connection-status-enum.js +20 -15
- package/out/zero-client/src/client/connection-status-enum.js.map +1 -1
- package/out/zero-client/src/client/connection.js +92 -110
- package/out/zero-client/src/client/connection.js.map +1 -1
- package/out/zero-client/src/client/context.js +84 -100
- package/out/zero-client/src/client/context.js.map +1 -1
- package/out/zero-client/src/client/crud-impl.js +56 -88
- package/out/zero-client/src/client/crud-impl.js.map +1 -1
- package/out/zero-client/src/client/crud.js +127 -129
- package/out/zero-client/src/client/crud.js.map +1 -1
- package/out/zero-client/src/client/custom.d.ts.map +1 -1
- package/out/zero-client/src/client/custom.js +50 -74
- package/out/zero-client/src/client/custom.js.map +1 -1
- package/out/zero-client/src/client/delete-clients-manager.js +72 -93
- package/out/zero-client/src/client/delete-clients-manager.js.map +1 -1
- package/out/zero-client/src/client/enable-analytics.js +8 -16
- package/out/zero-client/src/client/enable-analytics.js.map +1 -1
- package/out/zero-client/src/client/error.js +118 -133
- package/out/zero-client/src/client/error.js.map +1 -1
- package/out/zero-client/src/client/http-string.js +7 -7
- package/out/zero-client/src/client/http-string.js.map +1 -1
- package/out/zero-client/src/client/inspector/client-group.js +21 -26
- package/out/zero-client/src/client/inspector/client-group.js.map +1 -1
- package/out/zero-client/src/client/inspector/client.js +23 -26
- package/out/zero-client/src/client/inspector/client.js.map +1 -1
- package/out/zero-client/src/client/inspector/html-dialog-prompt.js +72 -73
- package/out/zero-client/src/client/inspector/html-dialog-prompt.js.map +1 -1
- package/out/zero-client/src/client/inspector/inspector.js +46 -51
- package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
- package/out/zero-client/src/client/inspector/lazy-inspector.js +132 -192
- package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
- package/out/zero-client/src/client/inspector/query.js +72 -77
- package/out/zero-client/src/client/inspector/query.js.map +1 -1
- package/out/zero-client/src/client/ivm-branch.js +118 -145
- package/out/zero-client/src/client/ivm-branch.js.map +1 -1
- package/out/zero-client/src/client/keys.js +15 -31
- package/out/zero-client/src/client/keys.js.map +1 -1
- package/out/zero-client/src/client/log-options.js +43 -57
- package/out/zero-client/src/client/log-options.js.map +1 -1
- package/out/zero-client/src/client/make-mutate-property.js +46 -29
- package/out/zero-client/src/client/make-mutate-property.js.map +1 -1
- package/out/zero-client/src/client/make-replicache-mutators.js +80 -96
- package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -1
- package/out/zero-client/src/client/metric-name-enum.js +11 -15
- package/out/zero-client/src/client/metric-name-enum.js.map +1 -1
- package/out/zero-client/src/client/metrics.js +210 -237
- package/out/zero-client/src/client/metrics.js.map +1 -1
- package/out/zero-client/src/client/mutation-tracker.js +264 -354
- package/out/zero-client/src/client/mutation-tracker.js.map +1 -1
- package/out/zero-client/src/client/mutator-proxy.js +122 -151
- package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
- package/out/zero-client/src/client/options.js +7 -10
- package/out/zero-client/src/client/options.js.map +1 -1
- package/out/zero-client/src/client/query-manager.js +305 -373
- package/out/zero-client/src/client/query-manager.js.map +1 -1
- package/out/zero-client/src/client/reload-error-handler.js +80 -101
- package/out/zero-client/src/client/reload-error-handler.js.map +1 -1
- package/out/zero-client/src/client/server-option.js +30 -59
- package/out/zero-client/src/client/server-option.js.map +1 -1
- package/out/zero-client/src/client/update-needed-reason-type-enum.js +27 -9
- package/out/zero-client/src/client/update-needed-reason-type-enum.js.map +1 -1
- package/out/zero-client/src/client/version.js +9 -5
- package/out/zero-client/src/client/version.js.map +1 -1
- package/out/zero-client/src/client/zero-poke-handler.d.ts +1 -1
- package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-poke-handler.js +205 -293
- package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
- package/out/zero-client/src/client/zero-rep.js +61 -68
- package/out/zero-client/src/client/zero-rep.js.map +1 -1
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +1367 -1834
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-client/src/mod.js +21 -0
- package/out/zero-client/src/util/nanoid.js +13 -18
- package/out/zero-client/src/util/nanoid.js.map +1 -1
- package/out/zero-client/src/util/socket.js +6 -5
- package/out/zero-client/src/util/socket.js.map +1 -1
- package/out/zero-pg/src/mod.js +10 -0
- package/out/zero-protocol/src/analyze-query-result.js +108 -148
- package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
- package/out/zero-protocol/src/application-error.js +36 -34
- package/out/zero-protocol/src/application-error.js.map +1 -1
- package/out/zero-protocol/src/ast.js +236 -309
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/change-desired-queries.js +8 -13
- package/out/zero-protocol/src/change-desired-queries.js.map +1 -1
- package/out/zero-protocol/src/client-schema.js +21 -42
- package/out/zero-protocol/src/client-schema.js.map +1 -1
- package/out/zero-protocol/src/close-connection.js +20 -12
- package/out/zero-protocol/src/close-connection.js.map +1 -1
- package/out/zero-protocol/src/connect.js +37 -52
- package/out/zero-protocol/src/connect.js.map +1 -1
- package/out/zero-protocol/src/custom-queries.js +34 -65
- package/out/zero-protocol/src/custom-queries.js.map +1 -1
- package/out/zero-protocol/src/data.js +6 -9
- package/out/zero-protocol/src/data.js.map +1 -1
- package/out/zero-protocol/src/delete-clients.js +11 -17
- package/out/zero-protocol/src/delete-clients.js.map +1 -1
- package/out/zero-protocol/src/down.js +11 -23
- package/out/zero-protocol/src/down.js.map +1 -1
- package/out/zero-protocol/src/error-kind-enum.js +24 -41
- package/out/zero-protocol/src/error-kind-enum.js.map +1 -1
- package/out/zero-protocol/src/error-origin-enum.js +8 -9
- package/out/zero-protocol/src/error-origin-enum.js.map +1 -1
- package/out/zero-protocol/src/error-reason-enum.js +12 -17
- package/out/zero-protocol/src/error-reason-enum.js.map +1 -1
- package/out/zero-protocol/src/error.js +76 -152
- package/out/zero-protocol/src/error.js.map +1 -1
- package/out/zero-protocol/src/inspect-down.js +51 -74
- package/out/zero-protocol/src/inspect-down.js.map +1 -1
- package/out/zero-protocol/src/inspect-up.js +28 -46
- package/out/zero-protocol/src/inspect-up.js.map +1 -1
- package/out/zero-protocol/src/mutation-id.js +9 -9
- package/out/zero-protocol/src/mutation-id.js.map +1 -1
- package/out/zero-protocol/src/mutation-type-enum.js +7 -7
- package/out/zero-protocol/src/mutation-type-enum.js.map +1 -1
- package/out/zero-protocol/src/mutations-patch.js +21 -16
- package/out/zero-protocol/src/mutations-patch.js.map +1 -1
- package/out/zero-protocol/src/ping.js +8 -9
- package/out/zero-protocol/src/ping.js.map +1 -1
- package/out/zero-protocol/src/poke.js +53 -59
- package/out/zero-protocol/src/poke.js.map +1 -1
- package/out/zero-protocol/src/pong.js +8 -9
- package/out/zero-protocol/src/pong.js.map +1 -1
- package/out/zero-protocol/src/primary-key.js +9 -19
- package/out/zero-protocol/src/primary-key.js.map +1 -1
- package/out/zero-protocol/src/protocol-version.js +5 -11
- package/out/zero-protocol/src/protocol-version.js.map +1 -1
- package/out/zero-protocol/src/pull.js +16 -28
- package/out/zero-protocol/src/pull.js.map +1 -1
- package/out/zero-protocol/src/push.js +162 -209
- package/out/zero-protocol/src/push.js.map +1 -1
- package/out/zero-protocol/src/queries-patch.js +22 -30
- package/out/zero-protocol/src/queries-patch.js.map +1 -1
- package/out/zero-protocol/src/query-hash.js +14 -17
- package/out/zero-protocol/src/query-hash.js.map +1 -1
- package/out/zero-protocol/src/row-patch.js +23 -30
- package/out/zero-protocol/src/row-patch.js.map +1 -1
- package/out/zero-protocol/src/up.js +11 -22
- package/out/zero-protocol/src/up.js.map +1 -1
- package/out/zero-protocol/src/update-auth.js +8 -13
- package/out/zero-protocol/src/update-auth.js.map +1 -1
- package/out/zero-protocol/src/version.js +8 -9
- package/out/zero-protocol/src/version.js.map +1 -1
- package/out/zero-react/src/bindings.js +12 -0
- package/out/zero-react/src/mod.js +5 -0
- package/out/zero-react/src/use-connection-state.js +14 -11
- package/out/zero-react/src/use-connection-state.js.map +1 -1
- package/out/zero-react/src/use-query.js +283 -281
- package/out/zero-react/src/use-query.js.map +1 -1
- package/out/zero-react/src/use-zero-online.js +17 -11
- package/out/zero-react/src/use-zero-online.js.map +1 -1
- package/out/zero-react/src/zero-provider.js +53 -69
- package/out/zero-react/src/zero-provider.js.map +1 -1
- package/out/zero-react/src/zero.js +22 -0
- package/out/zero-schema/src/builder/relationship-builder.js +25 -21
- package/out/zero-schema/src/builder/relationship-builder.js.map +1 -1
- package/out/zero-schema/src/builder/schema-builder.js +51 -79
- package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
- package/out/zero-schema/src/builder/table-builder.js +99 -116
- package/out/zero-schema/src/builder/table-builder.js.map +1 -1
- package/out/zero-schema/src/compiled-permissions.js +21 -25
- package/out/zero-schema/src/compiled-permissions.js.map +1 -1
- package/out/zero-schema/src/name-mapper.js +31 -47
- package/out/zero-schema/src/name-mapper.js.map +1 -1
- package/out/zero-schema/src/permissions.js +94 -181
- package/out/zero-schema/src/permissions.js.map +1 -1
- package/out/zero-schema/src/schema-config.js +26 -32
- package/out/zero-schema/src/schema-config.js.map +1 -1
- package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
- package/out/zero-server/src/adapters/drizzle.js +79 -76
- package/out/zero-server/src/adapters/drizzle.js.map +1 -1
- package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
- package/out/zero-server/src/adapters/pg.js +79 -55
- package/out/zero-server/src/adapters/pg.js.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.js +66 -40
- package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
- package/out/zero-server/src/adapters/prisma.d.ts.map +1 -1
- package/out/zero-server/src/adapters/prisma.js +75 -55
- package/out/zero-server/src/adapters/prisma.js.map +1 -1
- package/out/zero-server/src/custom.d.ts.map +1 -1
- package/out/zero-server/src/custom.js +188 -265
- package/out/zero-server/src/custom.js.map +1 -1
- package/out/zero-server/src/logging.js +6 -5
- package/out/zero-server/src/logging.js.map +1 -1
- package/out/zero-server/src/mod.js +8 -0
- package/out/zero-server/src/pg-query-executor.js +14 -17
- package/out/zero-server/src/pg-query-executor.js.map +1 -1
- package/out/zero-server/src/process-mutations.js +293 -365
- package/out/zero-server/src/process-mutations.js.map +1 -1
- package/out/zero-server/src/push-processor.js +33 -49
- package/out/zero-server/src/push-processor.js.map +1 -1
- package/out/zero-server/src/queries/process-queries.js +106 -96
- package/out/zero-server/src/queries/process-queries.js.map +1 -1
- package/out/zero-server/src/schema.js +98 -144
- package/out/zero-server/src/schema.js.map +1 -1
- package/out/zero-server/src/zql-database.d.ts.map +1 -1
- package/out/zero-server/src/zql-database.js +54 -69
- package/out/zero-server/src/zql-database.js.map +1 -1
- package/out/zero-solid/src/bindings.js +12 -0
- package/out/zero-solid/src/mod.js +5 -0
- package/out/zero-solid/src/solid-view.js +135 -227
- package/out/zero-solid/src/solid-view.js.map +1 -1
- package/out/zero-solid/src/use-connection-state.js +18 -14
- package/out/zero-solid/src/use-connection-state.js.map +1 -1
- package/out/zero-solid/src/use-query.js +55 -100
- package/out/zero-solid/src/use-query.js.map +1 -1
- package/out/zero-solid/src/use-zero-online.js +18 -12
- package/out/zero-solid/src/use-zero-online.js.map +1 -1
- package/out/zero-solid/src/use-zero.js +65 -77
- package/out/zero-solid/src/use-zero.js.map +1 -1
- package/out/zero-solid/src/zero.js +22 -0
- package/out/zero-types/src/format.js +8 -7
- package/out/zero-types/src/format.js.map +1 -1
- package/out/zero-types/src/name-mapper.js +34 -47
- package/out/zero-types/src/name-mapper.js.map +1 -1
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js +315 -476
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/builder/debug-delegate.js +69 -74
- package/out/zql/src/builder/debug-delegate.js.map +1 -1
- package/out/zql/src/builder/filter.js +116 -140
- package/out/zql/src/builder/filter.js.map +1 -1
- package/out/zql/src/builder/like.js +41 -46
- package/out/zql/src/builder/like.js.map +1 -1
- package/out/zql/src/error.js +10 -9
- package/out/zql/src/error.js.map +1 -1
- package/out/zql/src/ivm/array-view.js +89 -91
- package/out/zql/src/ivm/array-view.js.map +1 -1
- package/out/zql/src/ivm/constraint.js +65 -74
- package/out/zql/src/ivm/constraint.js.map +1 -1
- package/out/zql/src/ivm/data.js +61 -48
- package/out/zql/src/ivm/data.js.map +1 -1
- package/out/zql/src/ivm/exists.js +164 -213
- package/out/zql/src/ivm/exists.js.map +1 -1
- package/out/zql/src/ivm/fan-in.js +62 -59
- package/out/zql/src/ivm/fan-in.js.map +1 -1
- package/out/zql/src/ivm/fan-out.js +52 -61
- package/out/zql/src/ivm/fan-out.js.map +1 -1
- package/out/zql/src/ivm/filter-operators.js +91 -96
- package/out/zql/src/ivm/filter-operators.js.map +1 -1
- package/out/zql/src/ivm/filter-push.js +22 -26
- package/out/zql/src/ivm/filter-push.js.map +1 -1
- package/out/zql/src/ivm/filter.js +41 -35
- package/out/zql/src/ivm/filter.js.map +1 -1
- package/out/zql/src/ivm/flipped-join.js +282 -391
- package/out/zql/src/ivm/flipped-join.js.map +1 -1
- package/out/zql/src/ivm/join-utils.js +85 -115
- package/out/zql/src/ivm/join-utils.js.map +1 -1
- package/out/zql/src/ivm/join.js +162 -231
- package/out/zql/src/ivm/join.js.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +21 -25
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
- package/out/zql/src/ivm/memory-source.js +364 -503
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/memory-storage.js +33 -34
- package/out/zql/src/ivm/memory-storage.js.map +1 -1
- package/out/zql/src/ivm/operator.js +13 -15
- package/out/zql/src/ivm/operator.js.map +1 -1
- package/out/zql/src/ivm/push-accumulated.js +267 -270
- package/out/zql/src/ivm/push-accumulated.js.map +1 -1
- package/out/zql/src/ivm/skip.js +91 -104
- package/out/zql/src/ivm/skip.js.map +1 -1
- package/out/zql/src/ivm/stream.js +10 -10
- package/out/zql/src/ivm/stream.js.map +1 -1
- package/out/zql/src/ivm/take.js +422 -569
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js +157 -231
- package/out/zql/src/ivm/union-fan-in.js.map +1 -1
- package/out/zql/src/ivm/union-fan-out.js +38 -43
- package/out/zql/src/ivm/union-fan-out.js.map +1 -1
- package/out/zql/src/ivm/view-apply-change.js +166 -255
- package/out/zql/src/ivm/view-apply-change.js.map +1 -1
- package/out/zql/src/mutate/crud.js +35 -34
- package/out/zql/src/mutate/crud.js.map +1 -1
- package/out/zql/src/mutate/custom.d.ts.map +1 -1
- package/out/zql/src/mutate/custom.js +7 -11
- package/out/zql/src/mutate/custom.js.map +1 -1
- package/out/zql/src/mutate/mutator-registry.js +67 -71
- package/out/zql/src/mutate/mutator-registry.js.map +1 -1
- package/out/zql/src/mutate/mutator.js +26 -25
- package/out/zql/src/mutate/mutator.js.map +1 -1
- package/out/zql/src/planner/planner-builder.js +134 -239
- package/out/zql/src/planner/planner-builder.js.map +1 -1
- package/out/zql/src/planner/planner-connection.js +222 -212
- package/out/zql/src/planner/planner-connection.js.map +1 -1
- package/out/zql/src/planner/planner-constraint.js +15 -7
- package/out/zql/src/planner/planner-constraint.js.map +1 -1
- package/out/zql/src/planner/planner-debug.js +199 -224
- package/out/zql/src/planner/planner-debug.js.map +1 -1
- package/out/zql/src/planner/planner-fan-in.js +146 -162
- package/out/zql/src/planner/planner-fan-in.js.map +1 -1
- package/out/zql/src/planner/planner-fan-out.js +62 -74
- package/out/zql/src/planner/planner-fan-out.js.map +1 -1
- package/out/zql/src/planner/planner-graph.js +302 -334
- package/out/zql/src/planner/planner-graph.js.map +1 -1
- package/out/zql/src/planner/planner-join.js +255 -240
- package/out/zql/src/planner/planner-join.js.map +1 -1
- package/out/zql/src/planner/planner-node.js +10 -6
- package/out/zql/src/planner/planner-node.js.map +1 -1
- package/out/zql/src/planner/planner-source.js +15 -22
- package/out/zql/src/planner/planner-source.js.map +1 -1
- package/out/zql/src/planner/planner-terminus.js +28 -28
- package/out/zql/src/planner/planner-terminus.js.map +1 -1
- package/out/zql/src/query/complete-ordering.js +37 -61
- package/out/zql/src/query/complete-ordering.js.map +1 -1
- package/out/zql/src/query/create-builder.js +14 -22
- package/out/zql/src/query/create-builder.js.map +1 -1
- package/out/zql/src/query/error.js +10 -12
- package/out/zql/src/query/error.js.map +1 -1
- package/out/zql/src/query/escape-like.js +6 -5
- package/out/zql/src/query/escape-like.js.map +1 -1
- package/out/zql/src/query/expression.js +138 -157
- package/out/zql/src/query/expression.js.map +1 -1
- package/out/zql/src/query/measure-push-operator.js +35 -38
- package/out/zql/src/query/measure-push-operator.js.map +1 -1
- package/out/zql/src/query/metrics-delegate.js +7 -7
- package/out/zql/src/query/metrics-delegate.js.map +1 -1
- package/out/zql/src/query/named.js +52 -51
- package/out/zql/src/query/named.js.map +1 -1
- package/out/zql/src/query/query-delegate-base.js +190 -238
- package/out/zql/src/query/query-delegate-base.js.map +1 -1
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +271 -405
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query-internals.js +16 -8
- package/out/zql/src/query/query-internals.js.map +1 -1
- package/out/zql/src/query/query-registry.js +83 -98
- package/out/zql/src/query/query-registry.js.map +1 -1
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/query.js +2 -0
- package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
- package/out/zql/src/query/runnable-query-impl.js +30 -55
- package/out/zql/src/query/runnable-query-impl.js.map +1 -1
- package/out/zql/src/query/static-query.js +7 -14
- package/out/zql/src/query/static-query.js.map +1 -1
- package/out/zql/src/query/ttl.js +45 -67
- package/out/zql/src/query/ttl.js.map +1 -1
- package/out/zql/src/query/validate-input.js +23 -20
- package/out/zql/src/query/validate-input.js.map +1 -1
- package/out/zqlite/src/database-storage.js +99 -103
- package/out/zqlite/src/database-storage.js.map +1 -1
- package/out/zqlite/src/db.js +206 -249
- package/out/zqlite/src/db.js.map +1 -1
- package/out/zqlite/src/explain-queries.js +11 -13
- package/out/zqlite/src/explain-queries.js.map +1 -1
- package/out/zqlite/src/internal/sql-inline.js +54 -37
- package/out/zqlite/src/internal/sql-inline.js.map +1 -1
- package/out/zqlite/src/internal/sql.js +17 -15
- package/out/zqlite/src/internal/sql.js.map +1 -1
- package/out/zqlite/src/internal/statement-cache.js +117 -92
- package/out/zqlite/src/internal/statement-cache.js.map +1 -1
- package/out/zqlite/src/mod.js +5 -0
- package/out/zqlite/src/query-builder.js +81 -172
- package/out/zqlite/src/query-builder.js.map +1 -1
- package/out/zqlite/src/query-delegate.js +45 -55
- package/out/zqlite/src/query-delegate.js.map +1 -1
- package/out/zqlite/src/resolve-scalar-subqueries.js +134 -124
- package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.js +92 -97
- package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
- package/out/zqlite/src/sqlite-stat-fanout.js +304 -286
- package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
- package/out/zqlite/src/table-source.js +281 -455
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +7 -7
- package/out/replicache/src/db/index-operation-enum.js +0 -7
- package/out/replicache/src/db/index-operation-enum.js.map +0 -1
- package/out/replicache/src/db/meta-type-enum.js +0 -7
- package/out/replicache/src/db/meta-type-enum.js.map +0 -1
- package/out/replicache/src/format-version-enum.js +0 -11
- package/out/replicache/src/format-version-enum.js.map +0 -1
- package/out/replicache/src/http-status-unauthorized.js +0 -5
- package/out/replicache/src/http-status-unauthorized.js.map +0 -1
- package/out/replicache/src/invoke-kind-enum.js +0 -7
- package/out/replicache/src/invoke-kind-enum.js.map +0 -1
- package/out/replicache/src/sync/handle-pull-response-result-type-enum.js +0 -9
- package/out/replicache/src/sync/handle-pull-response-result-type-enum.js.map +0 -1
- package/out/zero/package.json.js +0 -9
- package/out/zero/package.json.js.map +0 -1
- package/out/zero/src/adapters/drizzle.js.map +0 -1
- package/out/zero/src/adapters/pg.js.map +0 -1
- package/out/zero/src/adapters/postgresjs.js.map +0 -1
- package/out/zero/src/adapters/prisma.js.map +0 -1
- package/out/zero/src/analyze-query.js.map +0 -1
- package/out/zero/src/ast-to-zql.js.map +0 -1
- package/out/zero/src/bindings.js.map +0 -1
- package/out/zero/src/change-protocol/v0.js.map +0 -1
- package/out/zero/src/cli.js.map +0 -1
- package/out/zero/src/deploy-permissions.js.map +0 -1
- package/out/zero/src/expo-sqlite.js.map +0 -1
- package/out/zero/src/op-sqlite.js.map +0 -1
- package/out/zero/src/pg.js.map +0 -1
- package/out/zero/src/react.js.map +0 -1
- package/out/zero/src/server.js.map +0 -1
- package/out/zero/src/solid.js.map +0 -1
- package/out/zero/src/sqlite.js.map +0 -1
- package/out/zero/src/transform-query.js.map +0 -1
- package/out/zero/src/zero.js.map +0 -1
- package/out/zero/src/zqlite.js.map +0 -1
- package/out/zero-cache/src/db/postgres-replica-identity-enum.js +0 -11
- package/out/zero-cache/src/db/postgres-replica-identity-enum.js.map +0 -1
- package/out/zero-cache/src/db/postgres-type-class-enum.js +0 -17
- package/out/zero-cache/src/db/postgres-type-class-enum.js.map +0 -1
- package/out/zero-cache/src/services/change-streamer/error-type-enum.js +0 -9
- package/out/zero-cache/src/services/change-streamer/error-type-enum.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planner-graph.js","sources":["../../../../../zql/src/planner/planner-graph.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {PlanDebugger} from './planner-debug.ts';\nimport type {PlannerConnection} from './planner-connection.ts';\nimport type {PlannerConstraint} from './planner-constraint.ts';\nimport type {PlannerFanIn} from './planner-fan-in.ts';\nimport type {PlannerFanOut} from './planner-fan-out.ts';\nimport type {PlannerJoin} from './planner-join.ts';\nimport {omitFanout} from './planner-node.ts';\nimport type {PlannerNode} from './planner-node.ts';\nimport {PlannerSource, type ConnectionCostModel} from './planner-source.ts';\nimport type {PlannerTerminus} from './planner-terminus.ts';\n\n/**\n * Captured state of a plan for comparison and restoration.\n */\nexport type PlanState = {\n connections: Array<{limit: number | undefined}>;\n joins: Array<{type: 'semi' | 'flipped'}>;\n fanOuts: Array<{type: 'FO' | 'UFO'}>;\n fanIns: Array<{type: 'FI' | 'UFI'}>;\n connectionConstraints: Array<Map<string, PlannerConstraint | undefined>>;\n};\n\n/**\n * Maximum number of flippable joins to attempt exhaustive enumeration.\n * With n flippable joins, we explore 2^n plans.\n * 10 joins = 1024 plans (~100-200ms), 12 joins = 4096 plans (~400ms - 1 second)\n */\nconst MAX_FLIPPABLE_JOINS = 9;\n\n/**\n * Cached information about FanOut→FanIn relationships.\n * Computed once during planning to avoid redundant BFS traversals.\n */\ntype FOFIInfo = {\n fi: PlannerFanIn | undefined;\n joinsBetween: PlannerJoin[];\n};\n\nexport class PlannerGraph {\n // Sources indexed by table name\n readonly #sources = new Map<string, PlannerSource>();\n\n // The final output node where constraint propagation starts\n #terminus: PlannerTerminus | undefined = undefined;\n\n // Collections of nodes with mutable planning state\n joins: PlannerJoin[] = [];\n fanOuts: PlannerFanOut[] = [];\n fanIns: PlannerFanIn[] = [];\n connections: PlannerConnection[] = [];\n\n /**\n * Reset all planning state back to initial values for another planning pass.\n * Resets only mutable planning state - graph structure is unchanged.\n *\n * This allows replanning the same query graph with different strategies.\n */\n resetPlanningState() {\n for (const j of this.joins) j.reset();\n for (const fo of this.fanOuts) fo.reset();\n for (const fi of this.fanIns) fi.reset();\n for (const c of this.connections) c.reset();\n }\n\n /**\n * Create and register a source (table) in the graph.\n */\n addSource(name: string, model: ConnectionCostModel): PlannerSource {\n assert(\n !this.#sources.has(name),\n `Source ${name} already exists in the graph`,\n );\n const source = new PlannerSource(name, model);\n this.#sources.set(name, source);\n return source;\n }\n\n /**\n * Get a source by table name.\n */\n getSource(name: string): PlannerSource {\n const source = this.#sources.get(name);\n assert(source !== undefined, `Source ${name} not found in the graph`);\n return source;\n }\n\n /**\n * Check if a source exists by table name.\n */\n hasSource(name: string): boolean {\n return this.#sources.has(name);\n }\n\n /**\n * Set the terminus (final output) node of the graph.\n * Constraint propagation starts from this node.\n */\n setTerminus(terminus: PlannerTerminus): void {\n this.#terminus = terminus;\n }\n\n /**\n * Initiate constraint propagation from the terminus node.\n * This sends constraints up through the graph to update\n * connection cost estimates.\n */\n propagateConstraints(planDebugger?: PlanDebugger): void {\n assert(\n this.#terminus !== undefined,\n 'Cannot propagate constraints without a terminus node',\n );\n this.#terminus.propagateConstraints(planDebugger);\n }\n\n /**\n * Calculate total cost of the current plan.\n * Total cost includes both startup cost (one-time, e.g., sorting) and running cost.\n */\n getTotalCost(planDebugger?: PlanDebugger): number {\n const estimate = must(this.#terminus).estimateCost(planDebugger);\n return estimate.cost + estimate.startupCost;\n }\n\n /**\n * Capture a lightweight snapshot of the current planning state.\n * Used for backtracking during multi-start greedy search.\n *\n * Captures mutable state including pinned flags, join types, and\n * constraint maps to avoid needing repropagation on restore.\n *\n * @returns A snapshot that can be restored via restorePlanningSnapshot()\n */\n capturePlanningSnapshot(): PlanState {\n return {\n connections: this.connections.map(c => ({\n limit: c.limit,\n })),\n joins: this.joins.map(j => ({type: j.type})),\n fanOuts: this.fanOuts.map(fo => ({type: fo.type})),\n fanIns: this.fanIns.map(fi => ({type: fi.type})),\n connectionConstraints: this.connections.map(c => c.captureConstraints()),\n };\n }\n\n /**\n * Restore planning state from a previously captured snapshot.\n * Used for backtracking when a planning attempt fails.\n *\n * Restores pinned flags, join types, and constraint maps, eliminating\n * the need for repropagation.\n *\n * @param state - Snapshot created by capturePlanningSnapshot()\n */\n restorePlanningSnapshot(state: PlanState): void {\n this.#validateSnapshotShape(state);\n this.#restoreConnections(state);\n this.#restoreJoins(state);\n this.#restoreFanNodes(state);\n }\n\n /**\n * Validate that snapshot shape matches current graph structure.\n */\n #validateSnapshotShape(state: PlanState): void {\n assert(\n this.connections.length === state.connections.length,\n 'Plan state mismatch: connections',\n );\n assert(\n this.joins.length === state.joins.length,\n 'Plan state mismatch: joins',\n );\n assert(\n this.fanOuts.length === state.fanOuts.length,\n 'Plan state mismatch: fanOuts',\n );\n assert(\n this.fanIns.length === state.fanIns.length,\n 'Plan state mismatch: fanIns',\n );\n assert(\n this.connections.length === state.connectionConstraints.length,\n 'Plan state mismatch: connectionConstraints',\n );\n }\n\n /**\n * Restore connection pinned flags, limits, and constraint maps.\n */\n #restoreConnections(state: PlanState): void {\n for (let i = 0; i < this.connections.length; i++) {\n this.connections[i].limit = state.connections[i].limit;\n this.connections[i].restoreConstraints(state.connectionConstraints[i]);\n }\n }\n\n /**\n * Restore join types and pinned flags.\n */\n #restoreJoins(state: PlanState): void {\n for (let i = 0; i < this.joins.length; i++) {\n const join = this.joins[i];\n const targetState = state.joins[i];\n\n // Reset to initial state first\n join.reset();\n\n // Apply target state\n if (targetState.type === 'flipped' && join.type !== 'flipped') {\n join.flip();\n }\n assert(\n targetState.type === join.type,\n 'join is not in the correct state after reset',\n );\n }\n }\n\n /**\n * Restore FanOut and FanIn types.\n */\n #restoreFanNodes(state: PlanState): void {\n for (let i = 0; i < this.fanOuts.length; i++) {\n const fo = this.fanOuts[i];\n const targetType = state.fanOuts[i].type;\n if (targetType === 'UFO' && fo.type === 'FO') {\n fo.convertToUFO();\n }\n }\n\n for (let i = 0; i < this.fanIns.length; i++) {\n const fi = this.fanIns[i];\n const targetType = state.fanIns[i].type;\n if (targetType === 'UFI' && fi.type === 'FI') {\n fi.convertToUFI();\n }\n }\n }\n\n /**\n * Main planning algorithm using exhaustive join flip enumeration.\n *\n * Enumerates all possible flip patterns for flippable joins (2^n for n flippable joins).\n * Each pattern represents a different query execution plan. We evaluate the cost of each\n * plan and select the one with the lowest cost.\n *\n * Connections are used only for cost estimation - the flip patterns determine the plan.\n * FanOut/FanIn states (FO/UFO and FI/UFI) are automatically derived from join flip states.\n *\n * @param planDebugger - Optional debugger to receive structured events during planning\n * @param lc - Optional logger for warnings\n */\n plan(planDebugger?: PlanDebugger, lc?: LogContext): void {\n // Get all flippable joins\n const flippableJoins = this.joins.filter(j => j.isFlippable());\n\n // Too many flippable joins - skip optimization and run as-is\n if (flippableJoins.length > MAX_FLIPPABLE_JOINS) {\n lc?.warn?.(\n `Query has ${flippableJoins.length} EXISTS checks which would require ` +\n `${2 ** flippableJoins.length} plan evaluations. Skipping optimization.`,\n );\n return;\n }\n\n // Build FO→FI cache once to avoid redundant BFS traversals in each iteration\n const fofiCache = buildFOFICache(this);\n\n const numPatterns =\n flippableJoins.length === 0 ? 0 : 2 ** flippableJoins.length;\n let bestCost = Infinity;\n let bestPlan: PlanState | undefined = undefined;\n let bestAttemptNumber = -1;\n\n // Enumerate all flip patterns\n for (let pattern = 0; pattern < numPatterns; pattern++) {\n // Reset to initial state\n this.resetPlanningState();\n\n if (planDebugger) {\n planDebugger.log({\n type: 'attempt-start',\n attemptNumber: pattern,\n totalAttempts: numPatterns,\n });\n }\n\n // Apply flip pattern (treat pattern as bitmask)\n // Bit i set to 1 means flip join i\n for (let i = 0; i < flippableJoins.length; i++) {\n if (pattern & (1 << i)) {\n flippableJoins[i].flip();\n }\n }\n\n // Derive FO/UFO and FI/UFI states from join flip states\n checkAndConvertFOFI(fofiCache);\n\n // Propagate unlimiting for flipped joins\n propagateUnlimitForFlippedJoins(this);\n\n // Propagate constraints through the graph\n this.propagateConstraints(planDebugger);\n\n if (planDebugger) {\n planDebugger.log({\n type: 'constraints-propagated',\n attemptNumber: pattern,\n connectionConstraints: this.connections.map(c => {\n const constraintCosts = c.getConstraintCostsForDebug();\n const constraintCostsWithoutFanout: Record<\n string,\n Omit<(typeof constraintCosts)[string], 'fanout'>\n > = {};\n for (const [key, cost] of Object.entries(constraintCosts)) {\n constraintCostsWithoutFanout[key] = omitFanout(cost);\n }\n return {\n connection: c.name,\n constraints: c.getConstraintsForDebug(),\n constraintCosts: constraintCostsWithoutFanout,\n };\n }),\n });\n }\n\n // Evaluate this plan\n const totalCost = this.getTotalCost(planDebugger);\n\n if (planDebugger) {\n planDebugger.log({\n type: 'plan-complete',\n attemptNumber: pattern,\n totalCost,\n flipPattern: pattern, // Bitmask of which joins are flipped\n planSnapshot: this.capturePlanningSnapshot(),\n joinStates: this.joins.map(j => {\n const info = j.getDebugInfo();\n return {\n join: info.name,\n type: info.type,\n };\n }),\n });\n }\n\n // Track best plan\n if (totalCost < bestCost) {\n bestCost = totalCost;\n bestPlan = this.capturePlanningSnapshot();\n bestAttemptNumber = pattern;\n }\n }\n\n // Restore best plan\n if (bestPlan) {\n this.restorePlanningSnapshot(bestPlan);\n // Propagate constraints to ensure all derived state is consistent\n this.propagateConstraints(planDebugger);\n\n if (planDebugger) {\n planDebugger.log({\n type: 'best-plan-selected',\n bestAttemptNumber,\n totalCost: bestCost,\n flipPattern: bestAttemptNumber, // The best attempt number is also the flip pattern\n joinStates: this.joins.map(j => ({\n join: j.getName(),\n type: j.type,\n })),\n });\n }\n } else {\n assert(\n numPatterns === 0,\n 'no plan was found but flippable joins did exist!',\n );\n }\n }\n}\n\n/**\n * Build cache of FO→FI relationships and joins between them.\n * Called once at the start of planning to avoid redundant BFS traversals.\n */\nfunction buildFOFICache(graph: PlannerGraph): Map<PlannerFanOut, FOFIInfo> {\n const cache = new Map<PlannerFanOut, FOFIInfo>();\n\n for (const fo of graph.fanOuts) {\n const info = findFIAndJoins(fo);\n cache.set(fo, info);\n }\n\n return cache;\n}\n\n/**\n * Check if any joins downstream of a FanOut (before reaching FanIn) are flipped.\n * If so, convert the FO to UFO and the FI to UFI.\n *\n * This must be called after join flipping and before propagateConstraints.\n */\nfunction checkAndConvertFOFI(fofiCache: Map<PlannerFanOut, FOFIInfo>): void {\n for (const [fo, info] of fofiCache) {\n const hasFlippedJoin = info.joinsBetween.some(j => j.type === 'flipped');\n if (info.fi && hasFlippedJoin) {\n fo.convertToUFO();\n info.fi.convertToUFI();\n }\n }\n}\n\n/**\n * Traverse from a FanOut through its outputs to find the corresponding FanIn\n * and collect all joins along the way.\n */\nfunction findFIAndJoins(fo: PlannerFanOut): FOFIInfo {\n const joinsBetween: PlannerJoin[] = [];\n let fi: PlannerFanIn | undefined = undefined;\n\n // BFS through FO outputs to find FI and collect joins\n const queue: PlannerNode[] = [...fo.outputs];\n const visited = new Set<PlannerNode>();\n\n while (queue.length > 0) {\n const node = must(queue.shift());\n if (visited.has(node)) continue;\n visited.add(node);\n\n switch (node.kind) {\n case 'join':\n joinsBetween.push(node);\n queue.push(node.output);\n break;\n case 'fan-out':\n // Nested FO - traverse its outputs\n queue.push(...node.outputs);\n break;\n case 'fan-in':\n // Found the FI - this is the boundary, don't traverse further\n fi = node;\n break;\n case 'connection':\n // Shouldn't happen in a well-formed graph\n break;\n case 'terminus':\n // Reached the end without finding FI\n break;\n }\n }\n\n return {fi, joinsBetween};\n}\n\n/**\n * Propagate unlimiting to all flipped joins in the graph.\n * When a join is flipped, its child becomes the outer loop and should no longer\n * be limited by EXISTS semantics.\n *\n * This must be called after join flipping and before propagateConstraints.\n */\nfunction propagateUnlimitForFlippedJoins(graph: PlannerGraph): void {\n for (const join of graph.joins) {\n if (join.type === 'flipped') {\n join.propagateUnlimit();\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"planner-graph.js","names":["#sources","#terminus","#validateSnapshotShape","#restoreConnections","#restoreJoins","#restoreFanNodes"],"sources":["../../../../../zql/src/planner/planner-graph.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {PlanDebugger} from './planner-debug.ts';\nimport type {PlannerConnection} from './planner-connection.ts';\nimport type {PlannerConstraint} from './planner-constraint.ts';\nimport type {PlannerFanIn} from './planner-fan-in.ts';\nimport type {PlannerFanOut} from './planner-fan-out.ts';\nimport type {PlannerJoin} from './planner-join.ts';\nimport {omitFanout} from './planner-node.ts';\nimport type {PlannerNode} from './planner-node.ts';\nimport {PlannerSource, type ConnectionCostModel} from './planner-source.ts';\nimport type {PlannerTerminus} from './planner-terminus.ts';\n\n/**\n * Captured state of a plan for comparison and restoration.\n */\nexport type PlanState = {\n connections: Array<{limit: number | undefined}>;\n joins: Array<{type: 'semi' | 'flipped'}>;\n fanOuts: Array<{type: 'FO' | 'UFO'}>;\n fanIns: Array<{type: 'FI' | 'UFI'}>;\n connectionConstraints: Array<Map<string, PlannerConstraint | undefined>>;\n};\n\n/**\n * Maximum number of flippable joins to attempt exhaustive enumeration.\n * With n flippable joins, we explore 2^n plans.\n * 10 joins = 1024 plans (~100-200ms), 12 joins = 4096 plans (~400ms - 1 second)\n */\nconst MAX_FLIPPABLE_JOINS = 9;\n\n/**\n * Cached information about FanOut→FanIn relationships.\n * Computed once during planning to avoid redundant BFS traversals.\n */\ntype FOFIInfo = {\n fi: PlannerFanIn | undefined;\n joinsBetween: PlannerJoin[];\n};\n\nexport class PlannerGraph {\n // Sources indexed by table name\n readonly #sources = new Map<string, PlannerSource>();\n\n // The final output node where constraint propagation starts\n #terminus: PlannerTerminus | undefined = undefined;\n\n // Collections of nodes with mutable planning state\n joins: PlannerJoin[] = [];\n fanOuts: PlannerFanOut[] = [];\n fanIns: PlannerFanIn[] = [];\n connections: PlannerConnection[] = [];\n\n /**\n * Reset all planning state back to initial values for another planning pass.\n * Resets only mutable planning state - graph structure is unchanged.\n *\n * This allows replanning the same query graph with different strategies.\n */\n resetPlanningState() {\n for (const j of this.joins) j.reset();\n for (const fo of this.fanOuts) fo.reset();\n for (const fi of this.fanIns) fi.reset();\n for (const c of this.connections) c.reset();\n }\n\n /**\n * Create and register a source (table) in the graph.\n */\n addSource(name: string, model: ConnectionCostModel): PlannerSource {\n assert(\n !this.#sources.has(name),\n `Source ${name} already exists in the graph`,\n );\n const source = new PlannerSource(name, model);\n this.#sources.set(name, source);\n return source;\n }\n\n /**\n * Get a source by table name.\n */\n getSource(name: string): PlannerSource {\n const source = this.#sources.get(name);\n assert(source !== undefined, `Source ${name} not found in the graph`);\n return source;\n }\n\n /**\n * Check if a source exists by table name.\n */\n hasSource(name: string): boolean {\n return this.#sources.has(name);\n }\n\n /**\n * Set the terminus (final output) node of the graph.\n * Constraint propagation starts from this node.\n */\n setTerminus(terminus: PlannerTerminus): void {\n this.#terminus = terminus;\n }\n\n /**\n * Initiate constraint propagation from the terminus node.\n * This sends constraints up through the graph to update\n * connection cost estimates.\n */\n propagateConstraints(planDebugger?: PlanDebugger): void {\n assert(\n this.#terminus !== undefined,\n 'Cannot propagate constraints without a terminus node',\n );\n this.#terminus.propagateConstraints(planDebugger);\n }\n\n /**\n * Calculate total cost of the current plan.\n * Total cost includes both startup cost (one-time, e.g., sorting) and running cost.\n */\n getTotalCost(planDebugger?: PlanDebugger): number {\n const estimate = must(this.#terminus).estimateCost(planDebugger);\n return estimate.cost + estimate.startupCost;\n }\n\n /**\n * Capture a lightweight snapshot of the current planning state.\n * Used for backtracking during multi-start greedy search.\n *\n * Captures mutable state including pinned flags, join types, and\n * constraint maps to avoid needing repropagation on restore.\n *\n * @returns A snapshot that can be restored via restorePlanningSnapshot()\n */\n capturePlanningSnapshot(): PlanState {\n return {\n connections: this.connections.map(c => ({\n limit: c.limit,\n })),\n joins: this.joins.map(j => ({type: j.type})),\n fanOuts: this.fanOuts.map(fo => ({type: fo.type})),\n fanIns: this.fanIns.map(fi => ({type: fi.type})),\n connectionConstraints: this.connections.map(c => c.captureConstraints()),\n };\n }\n\n /**\n * Restore planning state from a previously captured snapshot.\n * Used for backtracking when a planning attempt fails.\n *\n * Restores pinned flags, join types, and constraint maps, eliminating\n * the need for repropagation.\n *\n * @param state - Snapshot created by capturePlanningSnapshot()\n */\n restorePlanningSnapshot(state: PlanState): void {\n this.#validateSnapshotShape(state);\n this.#restoreConnections(state);\n this.#restoreJoins(state);\n this.#restoreFanNodes(state);\n }\n\n /**\n * Validate that snapshot shape matches current graph structure.\n */\n #validateSnapshotShape(state: PlanState): void {\n assert(\n this.connections.length === state.connections.length,\n 'Plan state mismatch: connections',\n );\n assert(\n this.joins.length === state.joins.length,\n 'Plan state mismatch: joins',\n );\n assert(\n this.fanOuts.length === state.fanOuts.length,\n 'Plan state mismatch: fanOuts',\n );\n assert(\n this.fanIns.length === state.fanIns.length,\n 'Plan state mismatch: fanIns',\n );\n assert(\n this.connections.length === state.connectionConstraints.length,\n 'Plan state mismatch: connectionConstraints',\n );\n }\n\n /**\n * Restore connection pinned flags, limits, and constraint maps.\n */\n #restoreConnections(state: PlanState): void {\n for (let i = 0; i < this.connections.length; i++) {\n this.connections[i].limit = state.connections[i].limit;\n this.connections[i].restoreConstraints(state.connectionConstraints[i]);\n }\n }\n\n /**\n * Restore join types and pinned flags.\n */\n #restoreJoins(state: PlanState): void {\n for (let i = 0; i < this.joins.length; i++) {\n const join = this.joins[i];\n const targetState = state.joins[i];\n\n // Reset to initial state first\n join.reset();\n\n // Apply target state\n if (targetState.type === 'flipped' && join.type !== 'flipped') {\n join.flip();\n }\n assert(\n targetState.type === join.type,\n 'join is not in the correct state after reset',\n );\n }\n }\n\n /**\n * Restore FanOut and FanIn types.\n */\n #restoreFanNodes(state: PlanState): void {\n for (let i = 0; i < this.fanOuts.length; i++) {\n const fo = this.fanOuts[i];\n const targetType = state.fanOuts[i].type;\n if (targetType === 'UFO' && fo.type === 'FO') {\n fo.convertToUFO();\n }\n }\n\n for (let i = 0; i < this.fanIns.length; i++) {\n const fi = this.fanIns[i];\n const targetType = state.fanIns[i].type;\n if (targetType === 'UFI' && fi.type === 'FI') {\n fi.convertToUFI();\n }\n }\n }\n\n /**\n * Main planning algorithm using exhaustive join flip enumeration.\n *\n * Enumerates all possible flip patterns for flippable joins (2^n for n flippable joins).\n * Each pattern represents a different query execution plan. We evaluate the cost of each\n * plan and select the one with the lowest cost.\n *\n * Connections are used only for cost estimation - the flip patterns determine the plan.\n * FanOut/FanIn states (FO/UFO and FI/UFI) are automatically derived from join flip states.\n *\n * @param planDebugger - Optional debugger to receive structured events during planning\n * @param lc - Optional logger for warnings\n */\n plan(planDebugger?: PlanDebugger, lc?: LogContext): void {\n // Get all flippable joins\n const flippableJoins = this.joins.filter(j => j.isFlippable());\n\n // Too many flippable joins - skip optimization and run as-is\n if (flippableJoins.length > MAX_FLIPPABLE_JOINS) {\n lc?.warn?.(\n `Query has ${flippableJoins.length} EXISTS checks which would require ` +\n `${2 ** flippableJoins.length} plan evaluations. Skipping optimization.`,\n );\n return;\n }\n\n // Build FO→FI cache once to avoid redundant BFS traversals in each iteration\n const fofiCache = buildFOFICache(this);\n\n const numPatterns =\n flippableJoins.length === 0 ? 0 : 2 ** flippableJoins.length;\n let bestCost = Infinity;\n let bestPlan: PlanState | undefined = undefined;\n let bestAttemptNumber = -1;\n\n // Enumerate all flip patterns\n for (let pattern = 0; pattern < numPatterns; pattern++) {\n // Reset to initial state\n this.resetPlanningState();\n\n if (planDebugger) {\n planDebugger.log({\n type: 'attempt-start',\n attemptNumber: pattern,\n totalAttempts: numPatterns,\n });\n }\n\n // Apply flip pattern (treat pattern as bitmask)\n // Bit i set to 1 means flip join i\n for (let i = 0; i < flippableJoins.length; i++) {\n if (pattern & (1 << i)) {\n flippableJoins[i].flip();\n }\n }\n\n // Derive FO/UFO and FI/UFI states from join flip states\n checkAndConvertFOFI(fofiCache);\n\n // Propagate unlimiting for flipped joins\n propagateUnlimitForFlippedJoins(this);\n\n // Propagate constraints through the graph\n this.propagateConstraints(planDebugger);\n\n if (planDebugger) {\n planDebugger.log({\n type: 'constraints-propagated',\n attemptNumber: pattern,\n connectionConstraints: this.connections.map(c => {\n const constraintCosts = c.getConstraintCostsForDebug();\n const constraintCostsWithoutFanout: Record<\n string,\n Omit<(typeof constraintCosts)[string], 'fanout'>\n > = {};\n for (const [key, cost] of Object.entries(constraintCosts)) {\n constraintCostsWithoutFanout[key] = omitFanout(cost);\n }\n return {\n connection: c.name,\n constraints: c.getConstraintsForDebug(),\n constraintCosts: constraintCostsWithoutFanout,\n };\n }),\n });\n }\n\n // Evaluate this plan\n const totalCost = this.getTotalCost(planDebugger);\n\n if (planDebugger) {\n planDebugger.log({\n type: 'plan-complete',\n attemptNumber: pattern,\n totalCost,\n flipPattern: pattern, // Bitmask of which joins are flipped\n planSnapshot: this.capturePlanningSnapshot(),\n joinStates: this.joins.map(j => {\n const info = j.getDebugInfo();\n return {\n join: info.name,\n type: info.type,\n };\n }),\n });\n }\n\n // Track best plan\n if (totalCost < bestCost) {\n bestCost = totalCost;\n bestPlan = this.capturePlanningSnapshot();\n bestAttemptNumber = pattern;\n }\n }\n\n // Restore best plan\n if (bestPlan) {\n this.restorePlanningSnapshot(bestPlan);\n // Propagate constraints to ensure all derived state is consistent\n this.propagateConstraints(planDebugger);\n\n if (planDebugger) {\n planDebugger.log({\n type: 'best-plan-selected',\n bestAttemptNumber,\n totalCost: bestCost,\n flipPattern: bestAttemptNumber, // The best attempt number is also the flip pattern\n joinStates: this.joins.map(j => ({\n join: j.getName(),\n type: j.type,\n })),\n });\n }\n } else {\n assert(\n numPatterns === 0,\n 'no plan was found but flippable joins did exist!',\n );\n }\n }\n}\n\n/**\n * Build cache of FO→FI relationships and joins between them.\n * Called once at the start of planning to avoid redundant BFS traversals.\n */\nfunction buildFOFICache(graph: PlannerGraph): Map<PlannerFanOut, FOFIInfo> {\n const cache = new Map<PlannerFanOut, FOFIInfo>();\n\n for (const fo of graph.fanOuts) {\n const info = findFIAndJoins(fo);\n cache.set(fo, info);\n }\n\n return cache;\n}\n\n/**\n * Check if any joins downstream of a FanOut (before reaching FanIn) are flipped.\n * If so, convert the FO to UFO and the FI to UFI.\n *\n * This must be called after join flipping and before propagateConstraints.\n */\nfunction checkAndConvertFOFI(fofiCache: Map<PlannerFanOut, FOFIInfo>): void {\n for (const [fo, info] of fofiCache) {\n const hasFlippedJoin = info.joinsBetween.some(j => j.type === 'flipped');\n if (info.fi && hasFlippedJoin) {\n fo.convertToUFO();\n info.fi.convertToUFI();\n }\n }\n}\n\n/**\n * Traverse from a FanOut through its outputs to find the corresponding FanIn\n * and collect all joins along the way.\n */\nfunction findFIAndJoins(fo: PlannerFanOut): FOFIInfo {\n const joinsBetween: PlannerJoin[] = [];\n let fi: PlannerFanIn | undefined = undefined;\n\n // BFS through FO outputs to find FI and collect joins\n const queue: PlannerNode[] = [...fo.outputs];\n const visited = new Set<PlannerNode>();\n\n while (queue.length > 0) {\n const node = must(queue.shift());\n if (visited.has(node)) continue;\n visited.add(node);\n\n switch (node.kind) {\n case 'join':\n joinsBetween.push(node);\n queue.push(node.output);\n break;\n case 'fan-out':\n // Nested FO - traverse its outputs\n queue.push(...node.outputs);\n break;\n case 'fan-in':\n // Found the FI - this is the boundary, don't traverse further\n fi = node;\n break;\n case 'connection':\n // Shouldn't happen in a well-formed graph\n break;\n case 'terminus':\n // Reached the end without finding FI\n break;\n }\n }\n\n return {fi, joinsBetween};\n}\n\n/**\n * Propagate unlimiting to all flipped joins in the graph.\n * When a join is flipped, its child becomes the outer loop and should no longer\n * be limited by EXISTS semantics.\n *\n * This must be called after join flipping and before propagateConstraints.\n */\nfunction propagateUnlimitForFlippedJoins(graph: PlannerGraph): void {\n for (const join of graph.joins) {\n if (join.type === 'flipped') {\n join.propagateUnlimit();\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,246 +1,261 @@
|
|
|
1
1
|
import { assert } from "../../../shared/src/asserts.js";
|
|
2
|
-
import { mergeConstraints } from "./planner-constraint.js";
|
|
3
2
|
import { omitFanout } from "./planner-node.js";
|
|
3
|
+
import { mergeConstraints } from "./planner-constraint.js";
|
|
4
|
+
//#region ../zql/src/planner/planner-join.ts
|
|
5
|
+
/**
|
|
6
|
+
* Translate constraints for a flipped join from parent space to child space.
|
|
7
|
+
* Matches the runtime behavior of FlippedJoin.fetch() which translates
|
|
8
|
+
* parent constraints to child constraints using index-based key mapping.
|
|
9
|
+
*
|
|
10
|
+
* Example:
|
|
11
|
+
* parentConstraint = {issueID: undefined, projectID: undefined}
|
|
12
|
+
* childConstraint = {id: undefined, projectID: undefined}
|
|
13
|
+
* incomingConstraint = {issueID: 5}
|
|
14
|
+
* result = {id: 5} // issueID at index 0 maps to id at index 0
|
|
15
|
+
*/
|
|
4
16
|
function translateConstraintsForFlippedJoin(incomingConstraint, parentConstraint, childConstraint) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
return Object.keys(translated).length > 0 ? translated : void 0;
|
|
16
|
-
}
|
|
17
|
-
class PlannerJoin {
|
|
18
|
-
kind = "join";
|
|
19
|
-
#parent;
|
|
20
|
-
#child;
|
|
21
|
-
#parentConstraint;
|
|
22
|
-
#childConstraint;
|
|
23
|
-
#flippable;
|
|
24
|
-
planId;
|
|
25
|
-
#output;
|
|
26
|
-
// Set once during graph construction
|
|
27
|
-
// Reset between planning attempts
|
|
28
|
-
#type;
|
|
29
|
-
#initialType;
|
|
30
|
-
constructor(parent, child, parentConstraint, childConstraint, flippable, planId, initialType = "semi") {
|
|
31
|
-
this.#type = initialType;
|
|
32
|
-
this.#initialType = initialType;
|
|
33
|
-
this.#parent = parent;
|
|
34
|
-
this.#child = child;
|
|
35
|
-
this.#childConstraint = childConstraint;
|
|
36
|
-
this.#parentConstraint = parentConstraint;
|
|
37
|
-
this.#flippable = flippable;
|
|
38
|
-
this.planId = planId;
|
|
39
|
-
}
|
|
40
|
-
setOutput(node) {
|
|
41
|
-
this.#output = node;
|
|
42
|
-
}
|
|
43
|
-
get output() {
|
|
44
|
-
assert(this.#output !== void 0, "Output not set");
|
|
45
|
-
return this.#output;
|
|
46
|
-
}
|
|
47
|
-
closestJoinOrSource() {
|
|
48
|
-
return "join";
|
|
49
|
-
}
|
|
50
|
-
flipIfNeeded(input) {
|
|
51
|
-
if (input === this.#child) {
|
|
52
|
-
this.flip();
|
|
53
|
-
} else {
|
|
54
|
-
assert(
|
|
55
|
-
input === this.#parent,
|
|
56
|
-
"Can only flip a join from one of its inputs"
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
flip() {
|
|
61
|
-
assert(this.#type === "semi", "Can only flip a semi-join");
|
|
62
|
-
if (!this.#flippable) {
|
|
63
|
-
throw new UnflippableJoinError(
|
|
64
|
-
"Cannot flip a non-flippable join (e.g., NOT EXISTS)"
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
this.#type = "flipped";
|
|
68
|
-
}
|
|
69
|
-
get type() {
|
|
70
|
-
return this.#type;
|
|
71
|
-
}
|
|
72
|
-
isFlippable() {
|
|
73
|
-
return this.#flippable;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Propagate unlimiting when this join is flipped.
|
|
77
|
-
* When a join is flipped:
|
|
78
|
-
* 1. Child becomes outer loop → produces all rows (unlimited)
|
|
79
|
-
* 2. Parent is fetched once per child row → effectively unlimited
|
|
80
|
-
*
|
|
81
|
-
* Example: If child produces 896 rows, parent is fetched 896 times.
|
|
82
|
-
* Even if each fetch returns 1 row, parent produces 896 total rows.
|
|
83
|
-
*
|
|
84
|
-
* Propagation rules:
|
|
85
|
-
* - Connection: call unlimit()
|
|
86
|
-
* - Semi-join: continue to parent (outer loop)
|
|
87
|
-
* - Flipped join: stop (already unlimited when it was flipped)
|
|
88
|
-
* - Fan-out/Fan-in: propagate to all inputs
|
|
89
|
-
*/
|
|
90
|
-
propagateUnlimit() {
|
|
91
|
-
assert(this.#type === "flipped", "Can only unlimit a flipped join");
|
|
92
|
-
this.#child.propagateUnlimitFromFlippedJoin();
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Called when a parent join is flipped and this join is part of its child subgraph.
|
|
96
|
-
* Continue propagation to parent (the outer loop).
|
|
97
|
-
* If we are hitting a semi-join, the parent drives.
|
|
98
|
-
* If we are hitting a flip-join, well now we have to unlimit its parent too!
|
|
99
|
-
*/
|
|
100
|
-
propagateUnlimitFromFlippedJoin() {
|
|
101
|
-
this.#parent.propagateUnlimitFromFlippedJoin();
|
|
102
|
-
}
|
|
103
|
-
propagateConstraints(branchPattern, constraint, from, planDebugger) {
|
|
104
|
-
planDebugger?.log({
|
|
105
|
-
type: "node-constraint",
|
|
106
|
-
nodeType: "join",
|
|
107
|
-
node: this.getName(),
|
|
108
|
-
branchPattern,
|
|
109
|
-
constraint,
|
|
110
|
-
from: from ? getNodeName(from) : "unknown"
|
|
111
|
-
});
|
|
112
|
-
if (this.#type === "semi") {
|
|
113
|
-
this.#child.propagateConstraints(
|
|
114
|
-
branchPattern,
|
|
115
|
-
this.#childConstraint,
|
|
116
|
-
this,
|
|
117
|
-
planDebugger
|
|
118
|
-
);
|
|
119
|
-
this.#parent.propagateConstraints(
|
|
120
|
-
branchPattern,
|
|
121
|
-
constraint,
|
|
122
|
-
this,
|
|
123
|
-
planDebugger
|
|
124
|
-
);
|
|
125
|
-
} else if (this.#type === "flipped") {
|
|
126
|
-
const translatedConstraint = translateConstraintsForFlippedJoin(
|
|
127
|
-
constraint,
|
|
128
|
-
this.#parentConstraint,
|
|
129
|
-
this.#childConstraint
|
|
130
|
-
);
|
|
131
|
-
this.#child.propagateConstraints(
|
|
132
|
-
branchPattern,
|
|
133
|
-
translatedConstraint,
|
|
134
|
-
this,
|
|
135
|
-
planDebugger
|
|
136
|
-
);
|
|
137
|
-
this.#parent.propagateConstraints(
|
|
138
|
-
branchPattern,
|
|
139
|
-
mergeConstraints(constraint, this.#parentConstraint),
|
|
140
|
-
this,
|
|
141
|
-
planDebugger
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
reset() {
|
|
146
|
-
this.#type = this.#initialType;
|
|
147
|
-
}
|
|
148
|
-
estimateCost(downstreamChildSelectivity, branchPattern, planDebugger) {
|
|
149
|
-
const child = this.#child.estimateCost(1, branchPattern, planDebugger);
|
|
150
|
-
const fanoutFactor = child.fanout(Object.keys(this.#childConstraint));
|
|
151
|
-
const scaledChildSelectivity = 1 - Math.pow(1 - child.selectivity, fanoutFactor.fanout);
|
|
152
|
-
const parent = this.#parent.estimateCost(
|
|
153
|
-
// Selectivity flows up the graph from child to parent
|
|
154
|
-
// so we can determine the total selectivity of all ANDed exists checks.
|
|
155
|
-
this.#type === "flipped" ? 1 * downstreamChildSelectivity : scaledChildSelectivity * downstreamChildSelectivity,
|
|
156
|
-
branchPattern,
|
|
157
|
-
planDebugger
|
|
158
|
-
);
|
|
159
|
-
let costEstimate;
|
|
160
|
-
if (this.type === "semi") {
|
|
161
|
-
costEstimate = {
|
|
162
|
-
startupCost: parent.startupCost,
|
|
163
|
-
scanEst: parent.limit === void 0 ? parent.returnedRows : Math.min(
|
|
164
|
-
parent.returnedRows,
|
|
165
|
-
downstreamChildSelectivity === 0 ? 0 : parent.limit / downstreamChildSelectivity
|
|
166
|
-
),
|
|
167
|
-
cost: parent.cost + parent.scanEst * (child.startupCost + child.cost + child.scanEst),
|
|
168
|
-
returnedRows: parent.returnedRows * child.selectivity,
|
|
169
|
-
selectivity: child.selectivity * parent.selectivity,
|
|
170
|
-
limit: parent.limit,
|
|
171
|
-
fanout: parent.fanout
|
|
172
|
-
};
|
|
173
|
-
} else {
|
|
174
|
-
costEstimate = {
|
|
175
|
-
startupCost: child.startupCost,
|
|
176
|
-
scanEst: parent.limit === void 0 ? parent.returnedRows * child.returnedRows : Math.min(
|
|
177
|
-
parent.returnedRows * child.returnedRows,
|
|
178
|
-
downstreamChildSelectivity === 0 ? 0 : parent.limit / downstreamChildSelectivity
|
|
179
|
-
),
|
|
180
|
-
cost: child.cost + child.scanEst * (parent.startupCost + parent.cost + parent.scanEst),
|
|
181
|
-
// the child selectivity is not relevant here because it has already been taken into account via the flipping.
|
|
182
|
-
// I.e., `child.returnedRows` is the estimated number of rows produced by the child _after_ taking filtering into account.
|
|
183
|
-
returnedRows: parent.returnedRows * child.returnedRows,
|
|
184
|
-
selectivity: parent.selectivity * child.selectivity,
|
|
185
|
-
limit: parent.limit,
|
|
186
|
-
fanout: parent.fanout
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
if (planDebugger) {
|
|
190
|
-
planDebugger.log({
|
|
191
|
-
type: "node-cost",
|
|
192
|
-
nodeType: "join",
|
|
193
|
-
node: this.getName(),
|
|
194
|
-
branchPattern,
|
|
195
|
-
downstreamChildSelectivity,
|
|
196
|
-
costEstimate: omitFanout(costEstimate),
|
|
197
|
-
joinType: this.#type
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
return costEstimate;
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Get a human-readable name for this join for debugging.
|
|
204
|
-
* Format: "parentName ⋈ childName"
|
|
205
|
-
*/
|
|
206
|
-
getName() {
|
|
207
|
-
const parentName = getNodeName(this.#parent);
|
|
208
|
-
const childName = getNodeName(this.#child);
|
|
209
|
-
return `${parentName} ⋈ ${childName}`;
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Get debug information about this join's state.
|
|
213
|
-
*/
|
|
214
|
-
getDebugInfo() {
|
|
215
|
-
return {
|
|
216
|
-
name: this.getName(),
|
|
217
|
-
type: this.#type,
|
|
218
|
-
planId: this.planId
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
class UnflippableJoinError extends Error {
|
|
223
|
-
constructor(message) {
|
|
224
|
-
super(message);
|
|
225
|
-
this.name = "UnflippableJoinError";
|
|
226
|
-
}
|
|
17
|
+
if (!incomingConstraint) return void 0;
|
|
18
|
+
const parentKeys = Object.keys(parentConstraint);
|
|
19
|
+
const childKeys = Object.keys(childConstraint);
|
|
20
|
+
const translated = {};
|
|
21
|
+
for (const [key, value] of Object.entries(incomingConstraint)) {
|
|
22
|
+
const index = parentKeys.indexOf(key);
|
|
23
|
+
if (index !== -1) translated[childKeys[index]] = value;
|
|
24
|
+
}
|
|
25
|
+
return Object.keys(translated).length > 0 ? translated : void 0;
|
|
227
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Semi-join overhead multiplier.
|
|
29
|
+
*
|
|
30
|
+
* Semi-joins represent correlated subqueries (EXISTS checks) which have
|
|
31
|
+
* execution overhead compared to flipped joins, even when logical row counts
|
|
32
|
+
* are identical. This overhead comes from:
|
|
33
|
+
* - Need to execute a separate correlation check for each parent row
|
|
34
|
+
* - Cannot leverage combined constraint checking as effectively as flipped joins
|
|
35
|
+
*
|
|
36
|
+
* A multiplier of 1.5 means semi-joins are estimated to be ~50% more expensive
|
|
37
|
+
* than equivalent flipped joins, which empirically matches observed performance
|
|
38
|
+
* differences in production workloads (e.g., 1.7x in zbugs benchmarks).
|
|
39
|
+
*
|
|
40
|
+
* Flipped joins have a different overhead in that they become unlimited. This
|
|
41
|
+
* is accounted for when propagating unlimits rather than here.
|
|
42
|
+
*/
|
|
43
|
+
/**
|
|
44
|
+
* Represents a join between two data streams (parent and child).
|
|
45
|
+
*
|
|
46
|
+
* # Dual-State Pattern
|
|
47
|
+
* Like all planner nodes, PlannerJoin separates:
|
|
48
|
+
* 1. IMMUTABLE STRUCTURE: Parent/child nodes, constraints, flippability
|
|
49
|
+
* 2. MUTABLE STATE: Join type (semi/flipped), pinned status
|
|
50
|
+
*
|
|
51
|
+
* # Join Flipping
|
|
52
|
+
* A join can be in two states:
|
|
53
|
+
* - 'semi': Parent is outer loop, child is inner (semi-join for EXISTS)
|
|
54
|
+
* - 'flipped': Child is outer loop, parent is inner
|
|
55
|
+
*
|
|
56
|
+
* Flipping is the key optimization: choosing which table scans first.
|
|
57
|
+
* NOT EXISTS joins cannot be flipped (#flippable = false).
|
|
58
|
+
*
|
|
59
|
+
* # Constraint Propagation
|
|
60
|
+
* - Semi-join: Sends childConstraint to child, forwards received constraints to parent
|
|
61
|
+
* - Flipped join: Sends undefined to child, merges parentConstraint with received to parent
|
|
62
|
+
* - Unpinned join: Only forwards constraints to parent (doesn't constrain child yet)
|
|
63
|
+
*
|
|
64
|
+
* # Lifecycle
|
|
65
|
+
* 1. Construct with immutable structure (parent, child, constraints, flippability)
|
|
66
|
+
* 2. Wire to output node during graph construction
|
|
67
|
+
* 3. Planning calls flipIfNeeded() based on connection selection order
|
|
68
|
+
* 4. pin() locks the join type once chosen
|
|
69
|
+
* 5. reset() clears mutable state (type → 'semi', pinned → false)
|
|
70
|
+
*/
|
|
71
|
+
var PlannerJoin = class {
|
|
72
|
+
kind = "join";
|
|
73
|
+
#parent;
|
|
74
|
+
#child;
|
|
75
|
+
#parentConstraint;
|
|
76
|
+
#childConstraint;
|
|
77
|
+
#flippable;
|
|
78
|
+
planId;
|
|
79
|
+
#output;
|
|
80
|
+
#type;
|
|
81
|
+
#initialType;
|
|
82
|
+
constructor(parent, child, parentConstraint, childConstraint, flippable, planId, initialType = "semi") {
|
|
83
|
+
this.#type = initialType;
|
|
84
|
+
this.#initialType = initialType;
|
|
85
|
+
this.#parent = parent;
|
|
86
|
+
this.#child = child;
|
|
87
|
+
this.#childConstraint = childConstraint;
|
|
88
|
+
this.#parentConstraint = parentConstraint;
|
|
89
|
+
this.#flippable = flippable;
|
|
90
|
+
this.planId = planId;
|
|
91
|
+
}
|
|
92
|
+
setOutput(node) {
|
|
93
|
+
this.#output = node;
|
|
94
|
+
}
|
|
95
|
+
get output() {
|
|
96
|
+
assert(this.#output !== void 0, "Output not set");
|
|
97
|
+
return this.#output;
|
|
98
|
+
}
|
|
99
|
+
closestJoinOrSource() {
|
|
100
|
+
return "join";
|
|
101
|
+
}
|
|
102
|
+
flipIfNeeded(input) {
|
|
103
|
+
if (input === this.#child) this.flip();
|
|
104
|
+
else assert(input === this.#parent, "Can only flip a join from one of its inputs");
|
|
105
|
+
}
|
|
106
|
+
flip() {
|
|
107
|
+
assert(this.#type === "semi", "Can only flip a semi-join");
|
|
108
|
+
if (!this.#flippable) throw new UnflippableJoinError("Cannot flip a non-flippable join (e.g., NOT EXISTS)");
|
|
109
|
+
this.#type = "flipped";
|
|
110
|
+
}
|
|
111
|
+
get type() {
|
|
112
|
+
return this.#type;
|
|
113
|
+
}
|
|
114
|
+
isFlippable() {
|
|
115
|
+
return this.#flippable;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Propagate unlimiting when this join is flipped.
|
|
119
|
+
* When a join is flipped:
|
|
120
|
+
* 1. Child becomes outer loop → produces all rows (unlimited)
|
|
121
|
+
* 2. Parent is fetched once per child row → effectively unlimited
|
|
122
|
+
*
|
|
123
|
+
* Example: If child produces 896 rows, parent is fetched 896 times.
|
|
124
|
+
* Even if each fetch returns 1 row, parent produces 896 total rows.
|
|
125
|
+
*
|
|
126
|
+
* Propagation rules:
|
|
127
|
+
* - Connection: call unlimit()
|
|
128
|
+
* - Semi-join: continue to parent (outer loop)
|
|
129
|
+
* - Flipped join: stop (already unlimited when it was flipped)
|
|
130
|
+
* - Fan-out/Fan-in: propagate to all inputs
|
|
131
|
+
*/
|
|
132
|
+
propagateUnlimit() {
|
|
133
|
+
assert(this.#type === "flipped", "Can only unlimit a flipped join");
|
|
134
|
+
this.#child.propagateUnlimitFromFlippedJoin();
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Called when a parent join is flipped and this join is part of its child subgraph.
|
|
138
|
+
* Continue propagation to parent (the outer loop).
|
|
139
|
+
* If we are hitting a semi-join, the parent drives.
|
|
140
|
+
* If we are hitting a flip-join, well now we have to unlimit its parent too!
|
|
141
|
+
*/
|
|
142
|
+
propagateUnlimitFromFlippedJoin() {
|
|
143
|
+
this.#parent.propagateUnlimitFromFlippedJoin();
|
|
144
|
+
}
|
|
145
|
+
propagateConstraints(branchPattern, constraint, from, planDebugger) {
|
|
146
|
+
planDebugger?.log({
|
|
147
|
+
type: "node-constraint",
|
|
148
|
+
nodeType: "join",
|
|
149
|
+
node: this.getName(),
|
|
150
|
+
branchPattern,
|
|
151
|
+
constraint,
|
|
152
|
+
from: from ? getNodeName(from) : "unknown"
|
|
153
|
+
});
|
|
154
|
+
if (this.#type === "semi") {
|
|
155
|
+
this.#child.propagateConstraints(branchPattern, this.#childConstraint, this, planDebugger);
|
|
156
|
+
this.#parent.propagateConstraints(branchPattern, constraint, this, planDebugger);
|
|
157
|
+
} else if (this.#type === "flipped") {
|
|
158
|
+
const translatedConstraint = translateConstraintsForFlippedJoin(constraint, this.#parentConstraint, this.#childConstraint);
|
|
159
|
+
this.#child.propagateConstraints(branchPattern, translatedConstraint, this, planDebugger);
|
|
160
|
+
this.#parent.propagateConstraints(branchPattern, mergeConstraints(constraint, this.#parentConstraint), this, planDebugger);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
reset() {
|
|
164
|
+
this.#type = this.#initialType;
|
|
165
|
+
}
|
|
166
|
+
estimateCost(downstreamChildSelectivity, branchPattern, planDebugger) {
|
|
167
|
+
/**
|
|
168
|
+
* downstreamChildSelectivity accumulates up a parent chain, not
|
|
169
|
+
* up child chains. Child chains represent independent sub-graphs.
|
|
170
|
+
* So we pass 1 for `downstreamChildSelectivity` when estimating child cost.
|
|
171
|
+
* Put another way, downstreamChildSelectivity impacts how many parent
|
|
172
|
+
* rows are returned.
|
|
173
|
+
*/
|
|
174
|
+
const child = this.#child.estimateCost(1, branchPattern, planDebugger);
|
|
175
|
+
const fanoutFactor = child.fanout(Object.keys(this.#childConstraint));
|
|
176
|
+
const scaledChildSelectivity = 1 - Math.pow(1 - child.selectivity, fanoutFactor.fanout);
|
|
177
|
+
/**
|
|
178
|
+
* How selective is the graph from this point forward?
|
|
179
|
+
* If we are _very_ selective then we must scan more parent rows
|
|
180
|
+
* before finding a match.
|
|
181
|
+
* E.g., if childSelectivity = 0.1 and downstreamChildSelectivity = 0.5
|
|
182
|
+
* then we only pass 5% of parent rows (0.1 * 0.5 = 0.05).
|
|
183
|
+
*
|
|
184
|
+
* This is used to estimate how many rows will be pulled from the parent
|
|
185
|
+
* when trying to satisfy downstream constraints and a limit.
|
|
186
|
+
*
|
|
187
|
+
* NOTE: We do not know if the probabilities are correlated so we assume independence.
|
|
188
|
+
* This is a fundamental limitation of the planner.
|
|
189
|
+
*/
|
|
190
|
+
const parent = this.#parent.estimateCost(this.#type === "flipped" ? 1 * downstreamChildSelectivity : scaledChildSelectivity * downstreamChildSelectivity, branchPattern, planDebugger);
|
|
191
|
+
let costEstimate;
|
|
192
|
+
if (this.type === "semi") costEstimate = {
|
|
193
|
+
startupCost: parent.startupCost,
|
|
194
|
+
scanEst: parent.limit === void 0 ? parent.returnedRows : Math.min(parent.returnedRows, downstreamChildSelectivity === 0 ? 0 : parent.limit / downstreamChildSelectivity),
|
|
195
|
+
cost: parent.cost + parent.scanEst * (child.startupCost + child.cost + child.scanEst),
|
|
196
|
+
returnedRows: parent.returnedRows * child.selectivity,
|
|
197
|
+
selectivity: child.selectivity * parent.selectivity,
|
|
198
|
+
limit: parent.limit,
|
|
199
|
+
fanout: parent.fanout
|
|
200
|
+
};
|
|
201
|
+
else costEstimate = {
|
|
202
|
+
startupCost: child.startupCost,
|
|
203
|
+
scanEst: parent.limit === void 0 ? parent.returnedRows * child.returnedRows : Math.min(parent.returnedRows * child.returnedRows, downstreamChildSelectivity === 0 ? 0 : parent.limit / downstreamChildSelectivity),
|
|
204
|
+
cost: child.cost + child.scanEst * (parent.startupCost + parent.cost + parent.scanEst),
|
|
205
|
+
returnedRows: parent.returnedRows * child.returnedRows,
|
|
206
|
+
selectivity: parent.selectivity * child.selectivity,
|
|
207
|
+
limit: parent.limit,
|
|
208
|
+
fanout: parent.fanout
|
|
209
|
+
};
|
|
210
|
+
if (planDebugger) planDebugger.log({
|
|
211
|
+
type: "node-cost",
|
|
212
|
+
nodeType: "join",
|
|
213
|
+
node: this.getName(),
|
|
214
|
+
branchPattern,
|
|
215
|
+
downstreamChildSelectivity,
|
|
216
|
+
costEstimate: omitFanout(costEstimate),
|
|
217
|
+
joinType: this.#type
|
|
218
|
+
});
|
|
219
|
+
return costEstimate;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Get a human-readable name for this join for debugging.
|
|
223
|
+
* Format: "parentName ⋈ childName"
|
|
224
|
+
*/
|
|
225
|
+
getName() {
|
|
226
|
+
return `${getNodeName(this.#parent)} ⋈ ${getNodeName(this.#child)}`;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Get debug information about this join's state.
|
|
230
|
+
*/
|
|
231
|
+
getDebugInfo() {
|
|
232
|
+
return {
|
|
233
|
+
name: this.getName(),
|
|
234
|
+
type: this.#type,
|
|
235
|
+
planId: this.planId
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
var UnflippableJoinError = class extends Error {
|
|
240
|
+
constructor(message) {
|
|
241
|
+
super(message);
|
|
242
|
+
this.name = "UnflippableJoinError";
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* Get a human-readable name for any planner node.
|
|
247
|
+
* Used for debugging and tracing.
|
|
248
|
+
*/
|
|
228
249
|
function getNodeName(node) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
case "fan-in":
|
|
237
|
-
return "FI";
|
|
238
|
-
case "terminus":
|
|
239
|
-
return "terminus";
|
|
240
|
-
}
|
|
250
|
+
switch (node.kind) {
|
|
251
|
+
case "connection": return node.name;
|
|
252
|
+
case "join": return node.getName();
|
|
253
|
+
case "fan-out": return "FO";
|
|
254
|
+
case "fan-in": return "FI";
|
|
255
|
+
case "terminus": return "terminus";
|
|
256
|
+
}
|
|
241
257
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
//# sourceMappingURL=planner-join.js.map
|
|
258
|
+
//#endregion
|
|
259
|
+
export { PlannerJoin };
|
|
260
|
+
|
|
261
|
+
//# sourceMappingURL=planner-join.js.map
|