8000 fix(query): expression bindings unify; reorder switch and plan-independence test (#596) by adityamukho · Pull Request #601 · project-minigraf/minigraf · GitHub
[go: up one dir, main page]

Skip to content

fix(query): expression bindings unify; reorder switch and plan-independence test (#596) - #601

Merged
adityamukho merged 3 commits into
v3from
feat/596-unify
Oct 15, 2026
Merged

adityamukho merged 3 commits into
v3from
feat/596-unify

Conversation

@adityamukho
Copy link
Copy Markdown
Collaborator

PR 1 of 3 for #596 / #594 (plan: docs/superpowers/plans/2026-10-15-594-596-plan-independence.md, spec: docs/superpowers/specs/2026-10-15-plan-independent-answers-design.md). #596 is closed by hand after merge (v3 does not fire closing keywords).

What changes

  • Expression bindings unify (Expression binding a variable a pattern also binds depends on plan order #596, breaking for v3.0.0). [(f …) ?x] whose ?x another clause binds keeps only the rows where the result equals ?x's value, with the streaming engine 3/9: IndexNestedLoopJoin and HashJoin (#473) #545 join equality (IEEE == floats, keyword = ref of the entity it names, int ≠ float, NaN ≠ anything). Applies to the executor's two plan loops, or branches and not bodies (apply_expr_clauses), the evaluator (recursive and stratified paths, evaluate_not_join) and the engine's Step::Bind (Out::New / Check / Replace). One helper, executor::apply_expr, replaces five copies of the overwrite logic.
  • First binder in the text gives the value. Binders now records expressions by :where position, so an expression earlier in the text than the pattern that bound the variable gives its value (matters only for keyword vs ref and -0.0 vs 0.0).
  • Test-only reorder switch. optimizer::reorder() replaces every #[cfg(not(feature = "wasm"))] reordering site: pattern selectivity sort, not/not-join cost sorts (planner, deferred, stratified evaluator), or/or-join branch sorts and the perf: short-circuit or/or-join branch evaluation using cost model #250 short-circuits, and the engine's HashJoin build side (switch off: build on the inner pattern; wasm keeps the cost choice). Release builds compile a constant. minigraf::__reorder(bool) -> ReorderGuard is #[doc(hidden)] and exists only under test-oracle.

Tests

Local: cargo test 1514 (1504 passed, 10 ignored); cargo test --features test-oracle 1510 passed, 11 ignored; cargo test --features wasm passes; clippy clean with --all-features, default, wasm, test-oracle, wasm32 browser, wasm32-wasip1. Codex review: no findings.

Docs

CHANGELOG (Breaking changes + Tests; the #545 entry's expression sentence now points to the new entry), CLAUDE.md, README, TEST_COVERAGE. Docs site: project-minigraf/minigraf-docs PR (expression clauses, @since v3.0.0).

Plan notes

The plan adds PR 3: drop the wasm gate so every build reorders and keep the wasm feature as a deprecated no-op (no first-party build enables it; minigraf-wasm uses browser, and wasm.yml builds wasm32 without it).

🤖 Generated with Claude Code

https://claude.ai/code/session_01HyLscCUuJ1GQpdAeX79EdR

adityamukho and others added 3 commits October 15, 2026 09:43
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HyLscCUuJ1GQpdAeX79EdR
optimizer::reorder() replaces every cfg(not(feature = "wasm")) reordering
site: pattern selectivity sort, not/not-join cost sorts, or/or-join branch
sorts and their #250 short-circuits, and the engine's HashJoin build side
(off: build on the inner pattern). Release builds compile a constant. Under
cfg(test) or test-oracle a thread-local switch turns it off;
minigraf::__reorder exposes it to integration tests (test-oracle only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HyLscCUuJ1GQpdAeX79EdR
[(f …) ?x] used to overwrite ?x wherever the planner ran it, so when a
pattern also bound ?x the answer depended on the plan (native vs the wasm
feature). It now keeps only the rows where its result equals ?x's value,
with the join equality of #545 (IEEE == floats, keyword equals the ref of
the entity it names, int never equals float, NaN equals nothing), in the
executor's plan loops, or branches, not bodies, the evaluator and the
engine's Step::Bind (Out::New/Check/Replace). Binders records expressions
by text position: the first binder in :where gives the value.

tests/plan_independence_test.rs (test-oracle) runs a query matrix with
reordering on and off through execute and a cursor; the model-based and
property tests rerun every query with reordering off. Gates the #250
short-circuit tests to non-wasm (they already failed under --features wasm).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HyLscCUuJ1GQpdAeX79EdR
@codecov
codecov Bot commented Oct 15, 2026
Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.30435% with 10 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/query/datalog/executor.rs 90.47% 6 Missing ⚠️
src/query/datalog/evaluator.rs 81.81% 2 Missing ⚠️
src/query/datalog/optimizer.rs 85.71% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@adityamukho
adityamukho merged commit 3a5fdac into v3 Oct 15, 2026
25 checks passed
@adityamukho
adityamukho deleted the feat/596-unify branch October 15, 2026 04:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0