Add OR (disjunction) to egglog rule bodies - #1
Conversation
Applies the disjunction feature to the egglog subtree: a rule query may contain (OR (branch) (branch) ...), where each branch is a conjunction of facts; the rule matches when any branch matches, and only variables common to every branch (or bound by the surrounding conjunction) may be used outside the OR. Correlated branches are supported and compile to a fused, deduplicating, seminaive/delta-driven union node in the core-relations free-join engine. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
| } | ||
| } | ||
| JoinStage::Union { branches } => { | ||
| // Fused disjunction. Enumerate every branch independently — each |
There was a problem hiding this comment.
This extra materialization step is going to hurt performance I think.
maybe this'd be a good fallback, but we probably want to recognize the special case where all of the branches come from the same function, and we can build a special index to evaluate all branches at once.
For the general case, it may be better to simply "duplicate" the plan implicitly (i.e. just have each branch terminate in the action, not in a materialization).
ezrosent
left a comment
There was a problem hiding this comment.
This + other comment are more high-level feedback. It'd be good to ask claude about benchmarking this against:
- a fast path with a custom index
- a slow path that just desugars
Rather than doing this materialization path.
| /// the one deduplicating materialization and the shared action — so a row | ||
| /// matched via several branches is still processed once. | ||
| /// | ||
| /// Requires a cached union plan whose sole block-0 stage is a `Union` (as |
There was a problem hiding this comment.
I don't think that core-relations should know about semi-naive... why can't we add semi-naive constraints to each disjunct in the OR in egglog-bridge?
Draft. Adds disjunction (
OR) to egglog rule bodies. All changes are confined to theegglog/subtree (subtree base7e926c6e).A rule query may contain
(OR (branch) (branch) ...), where each branch is a conjunction of facts; the rule matches when any branch matches. Only variables common to every branch — or bound by the surrounding conjunction — may be used outside theOR. Correlated branches (referencing the surrounding query) are supported and compile to a fused, deduplicating, seminaive/delta-driven union node in thecore-relationsfree-join engine (not rule-splitting, not an egglog→egglog rewrite).GenericFact::Or+ parser; typecheck resolves branches (branch-local renaming, common-variable interface rule).JoinStage::Unionincore-relations; union-aware seminaive expansion inegglog-bridge; dedup on the output tuple.Verified on the underlying egglog tree:
tests/disjunction.rs17/17 (incl. dedup-once and delta-driven proofs), full.eggharness 747/747,make nitsclean.egglog-experimentalis unaffected (it depends on a git-pinned egglog rev, not this subtree).🤖 Generated with Claude Code