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

Positional projection can result in caching incorrect parameterized plan

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 6.1.0-rc0
    • Affects Version/s: 6.1.0-rc0
    • Component/s: Query Planning
    • Labels:
      None
    • Fully Compatible
    • ALL
    • v6.0
    • Hide

      The second assertion in this repro script fails against a server that has SBE and the SBE plan cache enabled:

      (function() {
      "use strict";
      
      const coll = db.c;
      coll.drop();
      
      assert.commandWorked(coll.insert({"arr": [{"c": 2, "a": {"b": 3}}]}));
      
      // Creates an incorrect SBE plan cache entry.
      assert.eq(0,
                coll.find({"arr": {"$elemMatch": {"c": 99, "a.b": {"$exists": true}}}}, {"arr.$": 1})
                    .itcount());
      
      // Re-uses the incorrect SBE plan cache entry, resulting in missing the matching document.
      assert.eq(
          1,
          coll.find({"arr": {"$elemMatch": {"c": 2, "a.b": {"$exists": true}}}}, {"arr.$": 1}).itcount());
      }());
      
      Show
      The second assertion in this repro script fails against a server that has SBE and the SBE plan cache enabled: (function() { "use strict"; const coll = db.c; coll.drop(); assert.commandWorked(coll.insert({"arr": [{"c": 2, "a": {"b": 3}}]})); // Creates an incorrect SBE plan cache entry. assert.eq(0, coll.find({"arr": {"$elemMatch": {"c": 99, "a.b": {"$exists": true}}}}, {"arr.$": 1}) .itcount()); // Re-uses the incorrect SBE plan cache entry, resulting in missing the matching document. assert.eq( 1, coll.find({"arr": {"$elemMatch": {"c": 2, "a.b": {"$exists": true}}}}, {"arr.$": 1}).itcount()); }());
    • QO 2022-05-16, QO 2022-05-30, QO 2022-06-13

      In order to execute a positional projection, the corresponding match expression must run to find the first matching element of the array. Internally, this is implemented by keeping a MatchExpressionASTNode inside the projection AST. The MatchExpressionASTNode holds onto a copy of the MatchExpression. This match expression is created by re-parsing the BSON representation provided by the user, and it is implemented in such a way that no input parameter markers are added to the resulting MatchExpression tree.

      When the projection is compiled to an SBE plan by the SBE stage builders, the resulting plan inlines any constants in the match expression because it has no parameter markers. This is true even if the match expression was auto-parameterized! Also, note that the MatchExpressionASTNode is an internal construct which is not reflected in the SBE plan cache key – we currently encode the user's projection verbatim into the key, and the positional projection does not syntactically contain the match expression. The consequence is that we have a parameterized plan cache entry which accidentally embeds particular constants into the SBE plan for executing the projection. When this cache entry is reused for a new query with different parameter values, it can result in missing or incorrect query results.

            Assignee:
            denis.grebennicov@mongodb.com Denis Grebennicov
            Reporter:
            david.storch@mongodb.com David Storch
            Votes:
            0 Vote for this issue
            Watchers:
            11 Start watching this issue

              Created:
              Updated:
              Resolved: