Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-19415

PlanCache.listQueryShapes() reports the wrong query predicates for $or queries that use the SubplanStage

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Minor - P4 Minor - P4
    • 3.7.1
    • Affects Version/s: 3.0.0
    • Component/s: Querying
    • Fully Compatible
    • ALL
    • Hide
      db.c.drop();
      db.c.ensureIndex({a: 1});
      db.c.ensureIndex({b: 1});
      db.c.ensureIndex({c: 1});
      db.c.ensureIndex({d: 1});
      
      db.c.insert({a:1, b:0, c:0, d:0});
      db.c.insert({a:0, b:0, c:1, d:0});
      db.c.insert({a:1, b:1, c:1, d:1});
      
      // Run the query that will create the plan cache entries.
      db.c.find({$or: [{a: 1, b: 1}, {c: 1, d: 1}]});
      
      db.c.getPlanCache().listQueryShapes();
      [
      	{
                     // The value of this field is wrong! It should be {a: 1, b: 1}.
      		"query" : {
      			"$or" : [
      				{
      					"a" : 1,
      					"b" : 1
      				},
      				{
      					"c" : 1,
      					"d" : 1
      				}
      			]
      		},
      		"sort" : {
      
      		},
      		"projection" : {
      
      		}
      	},
      	{
                     // The value of this field is wrong! It should be {c: 1, d: 1}.
      		"query" : {
      			"$or" : [
      				{
      					"a" : 1,
      					"b" : 1
      				},
      				{
      					"c" : 1,
      					"d" : 1
      				}
      			]
      		},
      		"sort" : {
      
      		},
      		"projection" : {
      
      		}
      	}
      ]
      
      Show
      db.c.drop(); db.c.ensureIndex({a: 1}); db.c.ensureIndex({b: 1}); db.c.ensureIndex({c: 1}); db.c.ensureIndex({d: 1}); db.c.insert({a:1, b:0, c:0, d:0}); db.c.insert({a:0, b:0, c:1, d:0}); db.c.insert({a:1, b:1, c:1, d:1}); // Run the query that will create the plan cache entries. db.c.find({$or: [{a: 1, b: 1}, {c: 1, d: 1}]}); db.c.getPlanCache().listQueryShapes(); [ { // The value of this field is wrong! It should be {a: 1, b: 1}. "query" : { "$or" : [ { "a" : 1, "b" : 1 }, { "c" : 1, "d" : 1 } ] }, "sort" : { }, "projection" : { } }, { // The value of this field is wrong! It should be {c: 1, d: 1}. "query" : { "$or" : [ { "a" : 1, "b" : 1 }, { "c" : 1, "d" : 1 } ] }, "sort" : { }, "projection" : { } } ]
    • Query 2017-12-18

      Rooted $or queries (i.e. queries that consist of just an or at the top-level, like {$or: [{...}, {...}, ...]}) and contained $or queries (i.e. queries that have an $or which is AND-related with another predicate or predicates, like {p: 1, $or: [{...}, {...}, ...]}) are planned using the special SubplanStage path.

      The SubplanStage reads from and writes to the plan cache on a per-$or clause basis. That is, if you run the query {$or: [{a: 1, b: 1}, {c: 1, d: 1}]} against a server with an empty plan cache, and both clauses are indexed, then the SubplanStage will create two plan cache entries: one for the query {a: 1, b: 1} and another for the query {c: 1, d: 1}. On subsequent executions of the rooted $or query, the plan for each of the two clauses will individually get taken from the plan cache.

      When the SubplanStage creates the plan cache entries for each branch, it erroneously associates the entire rooted $or predicate with each plan cache entry. Instead, it should pass the query predicate {a: 1, b: 1} to the plan cache for the first clause of the $or, and should pass {c: 1, d: 1} for the second clause. This is benign in that the bug is only in the plan cache's diagnostics/reporting, however it could be very confusing for users. See "Steps to Reproduce" for details.

      The code responsible for this bug is already marked with a TODO:

      https://github.com/mongodb/mongo/blob/3f301ac62ea983d864f9a5ad017876171e2f1104/src/mongo/db/query/canonical_query.cpp#L238-L239

      There is a also descriptive test for this behavior which should be modified alongside the fix:

      https://github.com/mongodb/mongo/blob/3f301ac62ea983d864f9a5ad017876171e2f1104/src/mongo/db/query/canonical_query_test.cpp#L522-L524

            Assignee:
            ian.boros@mongodb.com Ian Boros
            Reporter:
            david.storch@mongodb.com David Storch
            Votes:
            1 Vote for this issue
            Watchers:
            8 Start watching this issue

              Created:
              Updated:
              Resolved: