You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
streaming engine 3/9: IndexNestedLoopJoin and HashJoin (#473) #545
Part 3 of 9 of #473. Design: docs/superpowers/specs/2026-10-11-streaming-engine-design.md (branch docs/473-streaming-engine-spec), §6.1, §6.2, §6.3.
IndexNestedLoopJoin probing the inner pattern's index per outer batch
HashJoin on the smaller side when neither side is indexable
Join ordering from the existing selectivity estimates (reordering stays off under wasm)
Float join keys: today the hash-join path compares floats exactly (ValueEq) and the nested-loop path within an epsilon (match_component); settle one rule for both, record changed answers in CHANGELOG.md (§5.4)
Multi-pattern queries move to the new engine; oracle differential tests pass
PRs for this part target v3 and must not use a closing keyword for #473.
Two deviations from spec §6.3, recorded here as the plan asks (docs/superpowers/plans/2026-10-14-545-joins.md):
Decision 3: IndexNestedLoopJoin probes only the entity position. A join is an INLJ only when the inner pattern's entity is a variable the outer rows bind. Every other join is a HashJoin: on the value or attribute position, or with no shared variable (a cross product). There are two reasons. The pending store has EAVT and AEVT but no AVET, so a value probe would read the attribute's whole pending range once per outer row. And a ref probe into the value position must also find the keyword values that name the entity, which no index holds. Effect: join_3_selective (a value join) reads every :manager fact into its table, 2.5 s / 66 MiB at 10M (feat(query): pseudo-attributes across joins and :db/valid-at on the streaming engine (#545) #595).
Activity
Merge pull request #592 from project-minigraf/feat/545-join-rules
docs: joins on the streaming engine, measurements, test counts (#545)
Merge pull request #593 from project-minigraf/feat/545-joins
test(query): pseudo-attribute metadata overwritten by a pattern on an…
docs: pseudo-attributes across joins, measurements at 10M (#545)
adityamukho commentedon Oct 14, 2026
Two deviations from spec §6.3, recorded here as the plan asks (
docs/superpowers/plans/2026-10-14-545-joins.md):IndexNestedLoopJoinprobes only the entity position. A join is an INLJ only when the inner pattern's entity is a variable the outer rows bind. Every other join is aHashJoin: on the value or attribute position, or with no shared variable (a cross product). There are two reasons. The pending store has EAVT and AEVT but no AVET, so a value probe would read the attribute's whole pending range once per outer row. And a ref probe into the value position must also find the keyword values that name the entity, which no index holds. Effect:join_3_selective(a value join) reads every:managerfact into its table, 2.5 s / 66 MiB at 10M (feat(query): pseudo-attributes across joins and :db/valid-at on the streaming engine (#545) #595).PreparedQueryplans per execution, as in streaming engine 2/9: operator core, Scan and oracle harness (#473) #544. Caching the operator tree with bind values as parameters waits for a measurement that shows planning matters.PR status: #592 (join rules) and #593 (engine joins) merged; #595 (pseudo-attributes across joins,
:db/valid-at, 10M measurements) open, with docs-site project-minigraf/minigraf-docs#17. Follow-up: #594 (pseudo-attribute metadata depends on plan order).Merge pull request #595 from project-minigraf/feat/545-pseudo-joins
adityamukho commentedon Oct 14, 2026
Done on v3: #592 (join rules), #593 (engine joins), #595 (pseudo-attributes across joins, :db/valid-at, 10M measurements); docs project-minigraf/minigraf-docs#17. Follow-ups: #594, #596.
fix(types): -0.0 and 0.0 hash alike, so a rule call's 0.0 returns -0.…