From ef74db9b48a13e1f902ce0eea3c0b5a24ba45ecc Mon Sep 17 00:00:00 2001 From: Martin Neupauer Date: Fri, 1 Mar 2019 12:28:39 -0500 Subject: SERVER-39903 notablescan parameter should be ignored for internally used namespaces (cherry picked from commit 18593fe22c55b7a51c44f04a39d30573b0b01873) --- jstests/noPassthrough/ignore_notablescan.js | 36 +++++++++++++++++++++++++++++ src/mongo/db/query/get_executor.cpp | 6 ++--- 2 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 jstests/noPassthrough/ignore_notablescan.js diff --git a/jstests/noPassthrough/ignore_notablescan.js b/jstests/noPassthrough/ignore_notablescan.js new file mode 100644 index 00000000000..9b7b0f8d379 --- /dev/null +++ b/jstests/noPassthrough/ignore_notablescan.js @@ -0,0 +1,36 @@ +// Test that 'notablescan' parameter does not affect queries internal namespaces. +// @tags: [uses_transactions] +(function() { + "use strict"; + + const dbName = "test"; + const collName = "coll"; + + const rst = new ReplSetTest({nodes: 1, nodeOptions: {setParameter: {notablescan: true}}}); + rst.startSet(); + rst.initiate(); + + const configDB = rst.getPrimary().getDB("config"); + const session = rst.getPrimary().getDB(dbName).getMongo().startSession(); + const primaryDB = session.getDatabase(dbName); + + // Implicitly create the collection outside of the transaction. + assert.writeOK(primaryDB.getCollection(collName).insert({x: 1})); + + // Run a transaction so the 'config.transactions' collection is implicitly created. + session.startTransaction(); + assert.writeOK(primaryDB.getCollection(collName).insert({x: 2})); + session.commitTransaction(); + + // Run a predicate query that would fail if we did not ignore the 'notablescan' flag. + assert.eq(configDB.transactions.find({any_nonexistent_field: {$exists: true}}).itcount(), 0); + + // Run the same query against the user created collection honoring the 'notablescan' flag. + // This will cause the query to fail as there is no viable query plan. Unfortunately, + // the reported query error code is the cryptic 'BadValue'. + assert.commandFailedWithCode( + primaryDB.runCommand({find: collName, filter: {any_nonexistent_field: {$exists: true}}}), + ErrorCodes.BadValue); + + rst.stopSet(); +}()); diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp index fc44f7fd459..4f7f4477081 100644 --- a/src/mongo/db/query/get_executor.cpp +++ b/src/mongo/db/query/get_executor.cpp @@ -167,10 +167,10 @@ void fillOutPlannerParams(OperationContext* opCtx, // overrides this behavior by not outputting a collscan even if there are no indexed // solutions. if (storageGlobalParams.noTableScan.load()) { - const string& ns = canonicalQuery->ns(); + const auto& nss = canonicalQuery->nss(); // There are certain cases where we ignore this restriction: - bool ignore = canonicalQuery->getQueryObj().isEmpty() || - (string::npos != ns.find(".system.")) || (0 == ns.find("local.")); + bool ignore = + canonicalQuery->getQueryObj().isEmpty() || nss.isSystem() || nss.isOnInternalDb(); if (!ignore) { plannerParams->options |= QueryPlannerParams::NO_TABLE_SCAN; } -- cgit v1.2.1