plan/spec: M3's row is closed

All five steps of the index-types review landed:
the refusal, the recorded corpus, partial indexes, hashed indexes, and
the implication test. `tests/spec/indexes/` is 48/48 and all four
recorded corpora are green -- positional 51, operators 125, indexes 48,
aggregate 70.

The review gets a fourth correction, and it is about method rather than a
fact. §4 asserted the implication rule without saying how to test it; the
answer needed no comparison of its own, because every operator the
partial-filter grammar admits is existential, so running the real matcher
against a stand-in document settles five operators at once.

What the review missed entirely was the gates. A corpus recorded from
mongod can see an implication test that says yes too readily -- documents
go missing -- but not one that never says yes, because no client can
observe which index a read used and this server has no `explain`. Both
numbers are recorded in PLAN §6 and the corpus README so the next change
to this code knows which gate is load-bearing for which direction.

Nothing else in M3 remains. PLAN §6 still carries the items this row
turned up and deliberately left: comparison operators are not
type-bracketed, a dotted path through an empty array reads as absent, a
key-pattern direction may be any non-zero number, three positional
divergences, three operator omissions, and the four older engine items.
This commit was merged in pull request #14.
This commit is contained in:
A.Shakhmatov
2026-08-11 00:36:05 +03:00
parent 7de3e6b666
commit 35c1e6537c
3 changed files with 68 additions and 6 deletions

View File

@@ -154,7 +154,8 @@ list used for its own format change and it holds here for the same reason.
## Outcome
Steps 14 landed in that order. `tests/spec/indexes/` is 42/42.
All five steps landed in that order, which closes M3's row.
`tests/spec/indexes/` is 48/48.
Three things this review got wrong, kept here because the point of writing it
before the code was to find out which parts would not survive contact:
@@ -175,8 +176,22 @@ And one thing the corpus found that this review had no reason to look for:
`find({a: null})` did not match a document with no `a`, index or no index. See
PLAN §6.
Step 5, the implication test, is still open. Until it exists a partial index
is maintained, enforces `unique`, and is never read from.
And one thing §4 asserted without saying how: the implication test itself. It
turned out not to need a comparison of its own. Every operator
`check_partial_filter` admits is *existential* — "some value at this path
satisfies it" — so when the query pins a value, running the real matcher
against a stand-in document holding it settles `$eq`, `$in`, `$type`,
`$exists` and the bounds together. Only two shapes escape that argument (an
array value, whose elements a real document need not have; and null, which
also matches a document with no such field), and only ranges need reasoning
of their own.
The unnoticed half was the gates. A corpus recorded from mongod can see an
implication test that says *yes* too readily — the answer loses documents —
but not one that never says yes at all, because no client can observe which
index a read used. Measured: forcing the test true takes `partial.json` to
23/7; forcing it false leaves it 30/30. The unit test on `plan()` is the only
thing that sees the feature work.
## 6. Not covered