Add $planCacheSetFilter command tests#590
Conversation
|
🤖 Auto-triaged by documentdb-triage-tool. Applied: Reasoningcomponent from path globs (test-coverage); effort from diff stats (978+0 LOC, 4 files); LLM: Adds new test coverage for the $planCacheSetFilter command operator, covering behavior, syntax, and error cases — a meaningful functional test expansion with no schema changes. If a label is wrong, remove it manually and ping |
Signed-off-by: Alina (Xi) Li <Alina.Li@improving.com>
Signed-off-by: Alina (Xi) Li <Alina.Li@improving.com>
Signed-off-by: Alina (Xi) Li <Alina.Li@improving.com>
Signed-off-by: Alina (Xi) Li <Alina.Li@improving.com> use CommandTestCase Signed-off-by: Alina (Xi) Li <Alina.Li@improving.com>
Signed-off-by: Alina (Xi) Li <Alina.Li@improving.com>
Signed-off-by: Alina (Xi) Li <Alina.Li@improving.com>
Signed-off-by: Alina (Xi) Li <Alina.Li@improving.com>
Signed-off-by: Alina (Xi) Li <Alina.Li@improving.com>
Signed-off-by: Alina (Xi) Li <Alina.Li@improving.com>
Signed-off-by: Alina (Xi) Li <Alina.Li@improving.com>
Signed-off-by: Alina (Xi) Li <Alina.Li@improving.com>
616b04d to
712c565
Compare
There was a problem hiding this comment.
Review summary
Reviewer feedback already addressed in 712c565 ✓ (collation_missing_locale and collation_with_locale_and_strength cases added per Rishabh998's comment).
Coverage gaps to add
Effectiveness tests — current tests only verify acceptance and persistence via planCacheListFilters. They do not verify the filter actually constrains plan selection. Pattern: same query, two different filters, two different expected indexes — proves the filter is honored without depending on the planner's natural choice.
- Filter forces specified index — case A. Setup: indexes
{a: 1}and{b: 1}. Filter[{a: 1}]for shape{a: 1}.explain find({a: 1})winning plan uses{a: 1}. - Filter forces specified index — case B (same query, different filter). Same indexes. Filter
[{b: 1}]for shape{a: 1}.explain find({a: 1})winning plan uses{b: 1}. Cases A and B together prove the filter is honored. - Multiple-allowed indexes constrain to the allowed set. Setup: indexes
{a: 1},{a: 1, b: 1},{c: 1}. Filter[{a: 1}, {c: 1}]for shape{a: 1, b: 1}. Winning plan'sindexNamemust be in the allowed set;{a: 1, b: 1}must be excluded. hintis overridden by filter. Setup: indexes{a: 1}and{b: 1}. Filter[{a: 1}]for shape{a: 1}; runfind({a: 1}).hint({b: 1})→ winning plan uses{a: 1}. Pair with inverse (filter[{b: 1}], hint{a: 1}→ uses{b: 1}).- Filter forces COLLSCAN when only an unusable index is allowed. Setup: index
{a: 1}. Filter[{nonexistent_field: 1}]for shape{a: 1}. Winning plan: COLLSCAN. - Filter scoped to exact shape — different shape unaffected. Setup: indexes
{a: 1}and{b: 1}. Filter[{b: 1}]for shape{a: 1}.explain find({a: 1})uses{b: 1}.explain find({a: 1, b: 1})→indexFilterSet: false(don't assert specific index).
Cross-command effectiveness — filter must apply to all commands that take a filter, not just find. Set the filter once, then verify each command honors it via its own explain output:
find— baseline (covered above)count—explain({count: ..., query: ...})winning plan uses the filter-constrained indexaggregatewith$matchas the first stage —explain({aggregate: ..., pipeline: [{$match: ...}, ...]})first-stage plan uses the constrained indexdistinct—explain({distinct: ..., key: ..., query: ...})plan uses the constrained indexupdate(andupdateMany) —explain({update: ..., updates: [{q: ..., u: ...}]})query plan uses the constrained indexdelete(anddeleteMany) —explain({delete: ..., deletes: [{q: ..., limit: ...}]})query plan uses the constrained indexfindAndModify—explain({findAndModify: ..., query: ..., update: ...})plan uses the constrained index
For each command, use the same setup as the find case-A/case-B pattern: filter [{a: 1}] then [{b: 1}] for the same shape, verify each command's winning plan switches indexes. Confirms filters are not silently find-only.
Partial / sparse index interaction:
- Filter to a partial index, query qualifies (predicate implies
partialFilterExpression) — winning plan uses the partial index. - Filter to a partial index, query does NOT qualify — verify engine behavior (COLLSCAN or filter-ignored fallback).
- Same shape, qualifying vs non-qualifying literal values: filter targets partial idx; one literal qualifies, one doesn't; probes whether filter resolution is shape-time or evaluation-time.
- Sparse-index parallel: filter to sparse idx,
$exists: truequalifies,$exists: falsedoes not (different shapes per probe).
Special index types in indexes argument — current core file tests compound, wildcard $**:1, and index_by_name. The following are accepted with ok: 1.0 per MongoDB 8.2 but not covered:
indexes: [{a: "text"}]— text index specindexes: [{geo: "2dsphere"}]— 2dsphere specindexes: [{loc: "2d"}]— 2d specindexes: [{a: "hashed"}]— hashed spec- Mixed type-and-direction compound:
indexes: [{a: 1, geo: "2dsphere"}],indexes: [{a: 1, txt: "text"}]
Index-spec-vs-query mismatch (set-time permissive): MongoDB does not validate at set-time that the index can serve the query.
setFilter({query: {a: 1}}, indexes: [{txt: "text"}])→ accepted withok: 1.0even though text index can't serve{a: 1}. Verify this permissiveness; the actual effectiveness is what matters at query time (covered by the COLLSCAN-fallback effectiveness test).
Out-of-scope (tracked separately)
Comprehensive query-shape equivalence coverage moved to #438 (Add compatibility test for explain). Shape testing belongs once, in the explain tests, not duplicated per consumer. This PR keeps its current 7-test shape sanity coverage. But add comment say the query-shape equivalence should be the same with explain queryHash test. Point full coverage to there.
Verified clean
- Reviewer feedback addressed (locale tests added).
- All parametrize blocks correctly use
lambda v=valuefor late binding. - New
setupfield onCommandTestCasecorrectly invoked afterprepare(). - Tuple-returning
setuplambdas in shape tests run side-effect calls as intended. CappedCollection/ViewCollectionfixtures used correctly.- The
query-planningfolder using a hyphen is pre-existing in main, not introduced by this PR.
This change adds tests for the $planCacheSetFilter command operator.
Add command operator tests for $planCacheSetFilter. Tests database $planCacheSetFilter behavior, syntax, and expected errors.