-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Critical - P2
-
Affects Version/s: 3.6.18, 4.0.19, 4.2.8, 4.4.0-rc10
-
Component/s: Querying
-
Fully Compatible
-
ALL
-
v4.4, v4.2, v4.0, v3.6
-
-
Query 2020-06-29, Query 2020-07-13, Query 2020-07-27
-
8
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Given a compound index with a non-simple collation, a point-query on a prefix field together with a sort on a suffix field can result in a IXSCAN query plan that incorrectly sorts according to the collation. This issue has existed at least since version 3.6.
The attached reproduction script describes the problem. A query which does not specify a collation (or which explicitly specifies a different collation) may still use an index which has a non-matching collation if the query predicates are non-string values. We then call QueryPlannerAnalysis::analyzeSort to determine whether we need to perform an in-memory sort. As part of this process we call QueryPlannerAnalysis::explodeForSort to see whether the plan can be rewritten as a SORT_MERGE. Unfortunately, this method does not enforce the constraint that an index with a different collation than the query cannot provide a sort.
Incorrect execution plan example:
db.c.find({a: 1}).sort({b: 1}).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.c",
"indexFilterSet" : false,
"parsedQuery" : {
"a" : {
"$eq" : 1
}
},
"queryHash" : "E97AE8CA",
"planCacheKey" : "35AFA63E",
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "SORT_MERGE",
"sortPattern" : {
"b" : 1
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"a" : 1,
"b" : 1
},
"indexName" : "a_1_b_1",
"collation" : {
"locale" : "en",
"caseLevel" : false,
"caseFirst" : "off",
"strength" : 1,
"numericOrdering" : false,
"alternate" : "non-ignorable",
"maxVariable" : "punct",
"normalization" : false,
"backwards" : false,
"version" : "57.1"
},
"isMultiKey" : false,
"multiKeyPaths" : {
"a" : [ ],
"b" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"a" : [
"[1.0, 1.0]"
],
"b" : [
"[MinKey, MaxKey]"
]
}
}
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "redshirt",
"port" : 27017,
"version" : "0.0.0",
"gitVersion" : "unknown"
},
"ok" : 1
}
Incorrect output example. Note that the results are sorted on case-insensitive value of field "b".
> db.c.find({a: 1}).sort({b: 1})
{ "_id" : ObjectId("5eecc3ecb4eefa8f13223f2c"), "a" : 1, "b" : "aa" }
{ "_id" : ObjectId("5eecc3f3b4eefa8f13223f2d"), "a" : 1, "b" : "AA" }
{ "_id" : ObjectId("5eecc3f7b4eefa8f13223f2e"), "a" : 1, "b" : "BB" }
{ "_id" : ObjectId("5eecc3f9b4eefa8f13223f2f"), "a" : 1, "b" : "bb" }
- related to
-
SERVER-50173 [v4.4] Remove explode_for_sort_collation.js from backports list of test suite sharding_multiversion
-
- Closed
-