A findAndModify with an equality query on _id, an update, a projection, and no explicit collation will hit an invariant when run on a collection with a non-simple default collation, due to a mismatch between the collator set on the ExpressionContext and the collator parsed by CanonicalQuery from the QueryRequest.
When running findAndModify under the conditions outlined above:
- We parse the update request here. If the request has no explicit collation, the ExpCtx's collator remains nullptr. We attempt to parse the query at this point, but if it is a simple equality on _id then we do not create a CanonicalQuery. This deferred canonicalization is intended to let us subsequently check whether the query is eligible for the IDHACK fast-path.
- We then call getExecutorUpdate. We obtain the collection-default collation and set it on the ParsedUpdate. Because the ParsedUpdate has an ExpressionContext but still has no CanonicalQuery, the collator will only be set on the ExpressionContext.
- We then check whether we can use IDHACK. But because we have a projection, we fail this check and fall through to here, at which point we attempt to canonicalize the query.
- When constructing the QueryRequest for canonicalization, ParsedUpdate sets the (empty) collation directly from the UpdateRequest. CanonicalQuery::canonicalize therefore ends up creating a nullptr collator based on the QueryRequest and comparing it against the collection-default collator set on the ExpressionContext, causing us to hit an invariant.
This bug was introduced in SERVER-45406.
- is caused by
-
SERVER-45406 Provide ExpressionContext in PlanStage layer
- Closed