diff options
-rw-r--r-- | jstests/core/index_filter_commands.js | 27 | ||||
-rw-r--r-- | src/mongo/db/query/explain.cpp | 16 |
2 files changed, 43 insertions, 0 deletions
diff --git a/jstests/core/index_filter_commands.js b/jstests/core/index_filter_commands.js index dddc69a688d..048e1cd8178 100644 --- a/jstests/core/index_filter_commands.js +++ b/jstests/core/index_filter_commands.js @@ -145,3 +145,30 @@ assert(!planCacheContains(shape), 'plan cache for query shape not flushed after print('Plan details before setting filter = ' + tojson(planBeforeSetFilter.details, '', true)); print('Plan details after setting filter = ' + tojson(planAfterSetFilter.details, '', true)); + +// +// Tests for the 'indexFilterSet' explain field. +// + +// No filter. +t.getPlanCache().clear(); +assert.eq(false, t.find({z: 1}).explain('queryPlanner').queryPlanner.indexFilterSet); +assert.eq(false, t.find(queryA1, projectionA1).sort(sortA1) + .explain('queryPlanner').queryPlanner.indexFilterSet); + +// With one filter set. +assert.commandWorked(t.runCommand('planCacheSetFilter', {query: {z: 1}, indexes: [{z: 1}]})); +assert.eq(true, t.find({z: 1}).explain('queryPlanner').queryPlanner.indexFilterSet); +assert.eq(false, t.find(queryA1, projectionA1).sort(sortA1) + .explain('queryPlanner').queryPlanner.indexFilterSet); + +// With two filters set. +assert.commandWorked(t.runCommand('planCacheSetFilter', { + query: queryA1, + projection: projectionA1, + sort: sortA1, + indexes: [indexA1B1, indexA1C1] +})); +assert.eq(true, t.find({z: 1}).explain('queryPlanner').queryPlanner.indexFilterSet); +assert.eq(true, t.find(queryA1, projectionA1).sort(sortA1) + .explain('queryPlanner').queryPlanner.indexFilterSet); diff --git a/src/mongo/db/query/explain.cpp b/src/mongo/db/query/explain.cpp index 7e25107e926..cbaaf0bb8e2 100644 --- a/src/mongo/db/query/explain.cpp +++ b/src/mongo/db/query/explain.cpp @@ -35,6 +35,7 @@ #include "mongo/db/query/get_executor.h" #include "mongo/db/query/plan_executor.h" #include "mongo/db/query/query_planner.h" +#include "mongo/db/query/query_settings.h" #include "mongo/db/query/stage_builder.h" #include "mongo/db/exec/working_set_common.h" #include "mongo/db/server_options.h" @@ -488,6 +489,21 @@ namespace mongo { plannerBob.append("plannerVersion", QueryPlanner::kPlannerVersion); plannerBob.append("namespace", exec->ns()); + // Find whether there is an index filter set for the query shape. The 'indexFilterSet' + // field will always be false in the case of EOF or idhack plans. + bool indexFilterSet = false; + if (exec->collection() && exec->getCanonicalQuery()) { + const Collection* collection = exec->collection(); + QuerySettings* querySettings = collection->infoCache()->getQuerySettings(); + AllowedIndices* allowedIndicesRaw; + if (querySettings->getAllowedIndices(*exec->getCanonicalQuery(), &allowedIndicesRaw)) { + // Found an index filter set on the query shape. + boost::scoped_ptr<AllowedIndices> allowedIndices(allowedIndicesRaw); + indexFilterSet = true; + } + } + plannerBob.append("indexFilterSet", indexFilterSet); + // In general we should have a canonical query, but sometimes we may avoid // creating a canonical query as an optimization (specifically, the update system // does not canonicalize for idhack updates). In these cases, 'query' is NULL. |