diff options
author | Mihai Andrei <mihai.andrei@10gen.com> | 2022-05-16 18:26:54 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-05-16 19:53:36 +0000 |
commit | 40109e237a0ffaf41d26b5465920d12bc6a3f304 (patch) | |
tree | 1622174e485aba3ee9a8810bc8191291bd4b4bd8 | |
parent | 7bd0bb1a99e1a4b1d596a2c834f46067482e8fb3 (diff) | |
download | mongo-40109e237a0ffaf41d26b5465920d12bc6a3f304.tar.gz |
SERVER-66445 Make the classic engine the default execution engine
34 files changed, 323 insertions, 204 deletions
diff --git a/buildscripts/resmokeconfig/suites/clustered_collection_passthrough.yml b/buildscripts/resmokeconfig/suites/clustered_collection_passthrough.yml index e52a1a9d0a4..d1ce985bcdf 100644 --- a/buildscripts/resmokeconfig/suites/clustered_collection_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/clustered_collection_passthrough.yml @@ -92,6 +92,6 @@ executor: set_parameters: enableTestCommands: 1 # SBE is not compatible with clustered collections - internalQueryForceClassicEngine: 1 + internalQueryEnableSlotBasedExecutionEngine: 0 failpoint.clusterAllCollectionsByDefault: "{mode: 'alwaysOn'}" num_nodes: 2 diff --git a/etc/backports_required_for_multiversion_tests.yml b/etc/backports_required_for_multiversion_tests.yml index e4a5b95efcc..06aee61021b 100644 --- a/etc/backports_required_for_multiversion_tests.yml +++ b/etc/backports_required_for_multiversion_tests.yml @@ -230,6 +230,22 @@ last-continuous: test_file: jstests/replsets/initial_sync_with_partial_transaction.js - ticket: SERVER-66389 test_file: jstests/core/where_multiple_plans.js + - ticket: SERVER-66445 + test_file: jstests/concurrency/fsm_workloads/find_flip_sbe_enabled.js + - ticket: SERVER-66445 + test_file: jstests/core/index_stats.js + - ticket: SERVER-66445 + test_file: jstests/core/wildcard_index_cached_plans.js + - ticket: SERVER-66445 + test_file: jstests/core/index_filter_commands_invalidate_plan_cache_entries.js + - ticket: SERVER-66445 + test_file: jstests/core/idhack.js + - ticket: SERVER-66445 + test_file: jstests/core/sbe/sbe_explain_rejected_plans.js + - ticket: SERVER-66445 + test_file: jstests/core/plan_cache_list_shapes.js + - ticket: SERVER-66445 + test_file: jstests/core/plan_cache_list_plans.js # Tests that should only be excluded from particular suites should be listed under that suite. suites: @@ -593,6 +609,22 @@ last-lts: test_file: jstests/replsets/initial_sync_with_partial_transaction.js - ticket: SERVER-66389 test_file: jstests/core/where_multiple_plans.js + - ticket: SERVER-66445 + test_file: jstests/concurrency/fsm_workloads/find_flip_sbe_enabled.js + - ticket: SERVER-66445 + test_file: jstests/core/index_stats.js + - ticket: SERVER-66445 + test_file: jstests/core/wildcard_index_cached_plans.js + - ticket: SERVER-66445 + test_file: jstests/core/index_filter_commands_invalidate_plan_cache_entries.js + - ticket: SERVER-66445 + test_file: jstests/core/idhack.js + - ticket: SERVER-66445 + test_file: jstests/core/sbe/sbe_explain_rejected_plans.js + - ticket: SERVER-66445 + test_file: jstests/core/plan_cache_list_shapes.js + - ticket: SERVER-66445 + test_file: jstests/core/plan_cache_list_plans.js # Tests that should only be excluded from particular suites should be listed under that suite. suites: diff --git a/etc/evergreen.yml b/etc/evergreen.yml index cf370450776..0499efe4806 100644 --- a/etc/evergreen.yml +++ b/etc/evergreen.yml @@ -1616,16 +1616,16 @@ buildvariants: # distros: # - rhel80-large -- &enterprise-rhel-80-64-bit-dynamic-classic-engine - name: enterprise-rhel-80-64-bit-dynamic-classic-engine - display_name: "Shared Library Enterprise RHEL 8.0 (Classic Engine)" +- &enterprise-rhel-80-64-bit-dynamic-sbe-engine + name: enterprise-rhel-80-64-bit-dynamic-sbe-engine + display_name: "Shared Library Enterprise RHEL 8.0 (SBE Engine)" cron: "0 4 * * *" # From the ${project_nightly_cron} parameter. stepback: false modules: - enterprise run_on: - rhel80-small - expansions: &enterprise-rhel-80-64-bit-dynamic-classic-engine-expansions + expansions: &enterprise-rhel-80-64-bit-dynamic-sbe-engine-expansions additional_package_targets: archive-mongocryptd archive-mongocryptd-debug archive-mh archive-mh-debug compile_flags: --ssl MONGO_DISTMOD=rhel80 -j$(grep -c ^processor /proc/cpuinfo) --variables-files=etc/scons/mongodbtoolchain_v3_gcc.vars --link-model=dynamic multiversion_platform: rhel80 @@ -1641,7 +1641,7 @@ buildvariants: burn_in_tag_buildvariants: enterprise-rhel-80-64-bit-inmem linux-64-duroff enterprise-rhel-80-64-bit-multiversion num_scons_link_jobs_available: 0.99 test_flags: >- - --mongodSetParameters="{internalQueryForceClassicEngine: true}" + --mongodSetParameters="{internalQueryEnableSlotBasedExecutionEngine: true}" tasks: - name: .aggfuzzer - name: .aggregation @@ -2334,8 +2334,8 @@ buildvariants: expansions: toolchain_version: v4 -- name: rhel80-debug-asan-classic-engine - display_name: ~ ASAN Enterprise RHEL 8.0 DEBUG (Classic Engine) +- name: rhel80-debug-asan-sbe-engine + display_name: ~ ASAN Enterprise RHEL 8.0 DEBUG (SBE Engine) cron: "0 4 * * *" # From the ${project_nightly_cron} parameter. modules: - enterprise @@ -2350,7 +2350,7 @@ buildvariants: san_options: LSAN_OPTIONS="suppressions=etc/lsan.suppressions:report_objects=1:external_symbolizer_path=/opt/mongodbtoolchain/v3/bin/llvm-symbolizer" ASAN_OPTIONS="detect_leaks=1:check_initialization_order=true:strict_init_order=true:abort_on_error=1:disable_coredump=0:handle_abort=1:external_symbolizer_path=/opt/mongodbtoolchain/v3/bin/llvm-symbolizer" compile_flags: --variables-files=etc/scons/mongodbtoolchain_v3_clang.vars --dbg=on --opt=on --allocator=system --sanitize=address --ssl --ocsp-stapling=off --enable-free-mon=on -j$(grep -c ^processor /proc/cpuinfo) test_flags: >- - --mongodSetParameters="{internalQueryForceClassicEngine: true}" + --mongodSetParameters="{internalQueryEnableSlotBasedExecutionEngine: true}" --excludeWithAnyTags=requires_fast_memory,requires_ocsp_stapling multiversion_platform: rhel80 multiversion_edition: enterprise @@ -2489,8 +2489,8 @@ buildvariants: expansions: toolchain_version: v4 -- name: rhel80-debug-ubsan-classic-engine - display_name: "~ UBSAN Enterprise RHEL 8.0 DEBUG (Classic Engine)" +- name: rhel80-debug-ubsan-sbe-engine + display_name: "~ UBSAN Enterprise RHEL 8.0 DEBUG (SBE Engine)" cron: "0 4 * * *" # From the ${project_nightly_cron} parameter. modules: - enterprise @@ -2505,7 +2505,7 @@ buildvariants: san_options: UBSAN_OPTIONS="print_stacktrace=1:external_symbolizer_path=/opt/mongodbtoolchain/v3/bin/llvm-symbolizer" compile_flags: --variables-files=etc/scons/mongodbtoolchain_v3_clang.vars --dbg=on --opt=on --sanitize=undefined --ssl --ocsp-stapling=off --enable-free-mon=on -j$(grep -c ^processor /proc/cpuinfo) test_flags: >- - --mongodSetParameters="{internalQueryForceClassicEngine: true}" + --mongodSetParameters="{internalQueryEnableSlotBasedExecutionEngine: true}" --excludeWithAnyTags=requires_ocsp_stapling multiversion_platform: rhel80 multiversion_edition: enterprise @@ -3038,18 +3038,18 @@ buildvariants: - windows-vsCurrent-large ### QO & QE Patch-Specific Build Variants ### -- <<: *enterprise-rhel-80-64-bit-dynamic-classic-engine - name: enterprise-rhel-80-64-bit-dynamic-classic-engine-query-patch-only - display_name: "~ Shared Library Enterprise RHEL 8.0 Query Patch Only (Classic Engine)" +- <<: *enterprise-rhel-80-64-bit-dynamic-sbe-engine + name: enterprise-rhel-80-64-bit-dynamic-sbe-engine-query-patch-only + display_name: "~ Shared Library Enterprise RHEL 8.0 Query Patch Only (SBE Engine)" cron: "0 4 * * 0" # From the ${project_weekly_cron} parameter # This is a patch-only variant but we run on mainline to pick up task history. expansions: - <<: *enterprise-rhel-80-64-bit-dynamic-classic-engine-expansions + <<: *enterprise-rhel-80-64-bit-dynamic-sbe-engine-expansions jstestfuzz_num_generated_files: 20 jstestfuzz_concurrent_num_files: 5 target_resmoke_time: 30 max_sub_suites: 3 test_flags: >- - --mongodSetParameters="{internalQueryForceClassicEngine: true}" + --mongodSetParameters="{internalQueryEnableSlotBasedExecutionEngine: true}" --excludeWithAnyTags=resource_intensive # Intentionally derive from SBE to run the SBE tests with all feature flags. diff --git a/etc/generate_subtasks_config.yml b/etc/generate_subtasks_config.yml index 11d08c85b02..059623a13ce 100644 --- a/etc/generate_subtasks_config.yml +++ b/etc/generate_subtasks_config.yml @@ -46,8 +46,8 @@ build_variant_large_distro_exceptions: - ubuntu1604-debug - ubuntu1804-debug-asan - ubuntu1804-debug-asan-all-feature-flags - - ubuntu1804-debug-asan-classic-engine + - ubuntu1804-debug-asan-sbe-engine - ubuntu1804-debug-aubsan-lite-required - ubuntu1804-debug-ubsan - ubuntu1804-debug-ubsan-all-feature-flags - - ubuntu1804-debug-ubsan-classic-engine + - ubuntu1804-debug-ubsan-sbe-engine diff --git a/jstests/concurrency/fsm_workloads/agg_lookup.js b/jstests/concurrency/fsm_workloads/agg_lookup.js index 9395c503d3c..73a930eb35b 100644 --- a/jstests/concurrency/fsm_workloads/agg_lookup.js +++ b/jstests/concurrency/fsm_workloads/agg_lookup.js @@ -74,7 +74,7 @@ var $config = (function() { getParameter: 1, featureFlagShardedLookup: 1, featureFlagSBELookupPushdown: 1, - internalQueryForceClassicEngine: 1 + internalQueryEnableSlotBasedExecutionEngine: 1 }); const isShardedLookupEnabled = getParam.hasOwnProperty("featureFlagShardedLookup") && getParam.featureFlagShardedLookup.value; @@ -97,9 +97,9 @@ var $config = (function() { assertWhenOwnColl.eq(this.numDocs, db[collName].find().itcount()); const isLookupPushdownEnabled = getParam.hasOwnProperty("featureFlagSBELookupPushdown") && - getParam.hasOwnProperty("internalQueryForceClassicEngine") && + getParam.hasOwnProperty("internalQueryEnableSlotBasedExecutionEngine") && getParam.featureFlagSBELookupPushdown.value && - !getParam.internalQueryForceClassicEngine.value; + getParam.internalQueryEnableSlotBasedExecutionEngine.value; this.allowDiskUse = true; // If $lookup pushdown into SBE is enabled, we select a random join algorithm to use and diff --git a/jstests/concurrency/fsm_workloads/find_flip_sbe_enabled.js b/jstests/concurrency/fsm_workloads/find_flip_sbe_enabled.js index 67883f034cc..b284b75b9e8 100644 --- a/jstests/concurrency/fsm_workloads/find_flip_sbe_enabled.js +++ b/jstests/concurrency/fsm_workloads/find_flip_sbe_enabled.js @@ -1,12 +1,10 @@ 'use strict'; /** - * Sets the internalQueryForceClassicEngine flag to true and false, and + * Sets the internalQueryEnableSlotBasedExecutionEngine flag to true and false, and * asserts that find queries using the plan cache produce the correct results. * * @tags: [ - * # Needed as the setParameter for ForceClassicEngine was introduced in 5.1. - * requires_fcv_51, * # Our test infrastructure prevents tests which use the 'setParameter' command from running in * # stepdown suites, since parameters are local to each mongod in the replica set. * does_not_support_stepdowns, @@ -22,10 +20,10 @@ var $config = (function() { function setup(db, collName, cluster) { const originalParamValue = - db.adminCommand({getParameter: 1, internalQueryForceClassicEngine: 1}); + db.adminCommand({getParameter: 1, internalQueryEnableSlotBasedExecutionEngine: 1}); assertAlways.commandWorked(originalParamValue); - assert(originalParamValue.hasOwnProperty("internalQueryForceClassicEngine")); - this.originalParamValue = originalParamValue.internalQueryForceClassicEngine; + assert(originalParamValue.hasOwnProperty("internalQueryEnableSlotBasedExecutionEngine")); + this.originalParamValue = originalParamValue.internalQueryEnableSlotBasedExecutionEngine; const coll = db.getCollection(getCollectionName(collName)); for (let i = 0; i < 10; ++i) { assertAlways.commandWorked( @@ -37,14 +35,14 @@ var $config = (function() { } let states = (function() { - function setForceClassicEngineOn(db, collName) { - assertAlways.commandWorked( - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true})); + function setEnableSlotBasedExecutionEngineOn(db, collName) { + assertAlways.commandWorked(db.adminCommand( + {setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: true})); } - function setForceClassicEngineOff(db, collName) { - assertAlways.commandWorked( - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false})); + function setEnableSlotBasedExecutionEngineOff(db, collName) { + assertAlways.commandWorked(db.adminCommand( + {setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false})); } function runQueriesAndCheckResults(db, collName) { @@ -79,8 +77,8 @@ var $config = (function() { } return { - setForceClassicEngineOn: setForceClassicEngineOn, - setForceClassicEngineOff: setForceClassicEngineOff, + setEnableSlotBasedExecutionEngineOn: setEnableSlotBasedExecutionEngineOn, + setEnableSlotBasedExecutionEngineOff: setEnableSlotBasedExecutionEngineOff, runQueriesAndCheckResults: runQueriesAndCheckResults, createIndex: createIndex, dropIndex: dropIndex @@ -88,36 +86,36 @@ var $config = (function() { })(); let transitions = { - setForceClassicEngineOn: { - setForceClassicEngineOn: 0.1, - setForceClassicEngineOff: 0.1, + setEnableSlotBasedExecutionEngineOn: { + setEnableSlotBasedExecutionEngineOn: 0.1, + setEnableSlotBasedExecutionEngineOff: 0.1, runQueriesAndCheckResults: 0.8 }, - setForceClassicEngineOff: { - setForceClassicEngineOn: 0.1, - setForceClassicEngineOff: 0.1, + setEnableSlotBasedExecutionEngineOff: { + setEnableSlotBasedExecutionEngineOn: 0.1, + setEnableSlotBasedExecutionEngineOff: 0.1, runQueriesAndCheckResults: 0.8 }, runQueriesAndCheckResults: { - setForceClassicEngineOn: 0.1, - setForceClassicEngineOff: 0.1, + setEnableSlotBasedExecutionEngineOn: 0.1, + setEnableSlotBasedExecutionEngineOff: 0.1, runQueriesAndCheckResults: 0.78, createIndex: 0.02, }, createIndex: { - setForceClassicEngineOn: 0.1, - setForceClassicEngineOff: 0.1, + setEnableSlotBasedExecutionEngineOn: 0.1, + setEnableSlotBasedExecutionEngineOff: 0.1, runQueriesAndCheckResults: 0.78, createIndex: 0.01, dropIndex: 0.01 }, dropIndex: { - setForceClassicEngineOn: 0.1, - setForceClassicEngineOff: 0.1, + setEnableSlotBasedExecutionEngineOn: 0.1, + setEnableSlotBasedExecutionEngineOff: 0.1, runQueriesAndCheckResults: 0.78, createIndex: 0.02, } @@ -127,15 +125,15 @@ var $config = (function() { // Restore the original state of the ForceClassicEngine parameter. const setParam = this.originalParamValue; cluster.executeOnMongodNodes(function(db) { - assertAlways.commandWorked( - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: setParam})); + assertAlways.commandWorked(db.adminCommand( + {setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: setParam})); }); } return { threadCount: 10, iterations: 100, - startState: 'setForceClassicEngineOn', + startState: 'setEnableSlotBasedExecutionEngineOn', states: states, transitions: transitions, setup: setup, diff --git a/jstests/core/columnstore_index.js b/jstests/core/columnstore_index.js index e950577f7d3..74a5bda1245 100644 --- a/jstests/core/columnstore_index.js +++ b/jstests/core/columnstore_index.js @@ -16,11 +16,9 @@ "use strict"; load("jstests/libs/analyze_plan.js"); +load("jstests/libs/sbe_util.js"); // For checkSBEEnabled. -const getParamResponse = - assert.commandWorked(db.adminCommand({getParameter: 1, featureFlagColumnstoreIndexes: 1})); -const columnstoreEnabled = getParamResponse.hasOwnProperty("featureFlagColumnstoreIndexes") && - getParamResponse.featureFlagColumnstoreIndexes.value; +const columnstoreEnabled = checkSBEEnabled(db, ["featureFlagColumnstoreIndexes"]); if (!columnstoreEnabled) { jsTestLog("Skipping columnstore index validation test since the feature flag is not enabled."); return; diff --git a/jstests/libs/sbe_util.js b/jstests/libs/sbe_util.js index 2d85bbb4f79..fe623fe6d7e 100644 --- a/jstests/libs/sbe_util.js +++ b/jstests/libs/sbe_util.js @@ -24,8 +24,8 @@ function checkSBEEnabled(theDB, featureFlags = []) { return false; } - // Find a non-mongos node and check whether its forceClassicEngine flag is on. We - // assume either all nodes in the cluster have SBE disabled or none. + // Find a non-mongos node and check whether its SBE flag is on. We assume either + // all nodes in the cluster have SBE disabled or none. for (const node of nodes) { try { const conn = new Mongo(node); @@ -38,16 +38,17 @@ function checkSBEEnabled(theDB, featureFlags = []) { internalQueryForceClassicEngine: 1, internalQueryEnableSlotBasedExecutionEngine: 1 }); - if (getParam.hasOwnProperty("internalQueryForceClassicEngine") && - !getParam.internalQueryForceClassicEngine) { - checkResult = true; - } - // Some versions use a different parameter to enable SBE instead of disabling it. if (getParam.hasOwnProperty("internalQueryEnableSlotBasedExecutionEngine") && getParam.internalQueryEnableSlotBasedExecutionEngine) { checkResult = true; } + // Some versions use a different parameter to disable SBE instead of enabling it. + if (getParam.hasOwnProperty("internalQueryForceClassicEngine") && + !getParam.internalQueryForceClassicEngine) { + checkResult = true; + } + featureFlags.forEach(function(featureFlag) { const featureFlagParam = conn.adminCommand({getParameter: 1, [featureFlag]: 1}); checkResult = checkResult && featureFlagParam.hasOwnProperty(featureFlag) && diff --git a/jstests/noPassthrough/accumulator_bug_fix.js b/jstests/noPassthrough/accumulator_bug_fix.js index 5c044c151f0..73bd312acda 100644 --- a/jstests/noPassthrough/accumulator_bug_fix.js +++ b/jstests/noPassthrough/accumulator_bug_fix.js @@ -26,7 +26,7 @@ // Turns on the classical engine. assert.commandWorked( - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true})); + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false})); const pipeline = [{$group: {_id: "$k", o: accSpec}}, {$group: {_id: "$o"}}]; @@ -75,13 +75,13 @@ // Turns on the classical engine. assert.commandWorked( - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true})); + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false})); const classicRes = assert.commandWorked(db.runCommand(aggCmd)).cursor.firstBatch; assert.eq(classicRes, expectedRes, testDesc); // Turns off the classical engine. assert.commandWorked( - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false})); + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: true})); const sbeRes = assert.commandWorked(db.runCommand(aggCmd)).cursor.firstBatch; assert.eq(sbeRes, expectedRes, testDesc); }; @@ -211,20 +211,20 @@ let verifyShardedAccumulatorResultsOnBothEngine = (testDesc, coll, pipeline, expectedRes) => { // Turns to the classic engine at the shards. - assert.commandWorked( - dbAtShard0.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true})); - assert.commandWorked( - dbAtShard1.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true})); + assert.commandWorked(dbAtShard0.adminCommand( + {setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false})); + assert.commandWorked(dbAtShard1.adminCommand( + {setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false})); // Verifies that the classic engine's results are same as the expected results. const classicRes = coll.aggregate(pipeline).toArray(); assert.eq(classicRes, expectedRes, testDesc); // Turns to the SBE engine at the shards. - assert.commandWorked( - dbAtShard0.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false})); - assert.commandWorked( - dbAtShard1.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false})); + assert.commandWorked(dbAtShard0.adminCommand( + {setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: true})); + assert.commandWorked(dbAtShard1.adminCommand( + {setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: true})); // Verifies that the SBE engine's results are same as the expected results. const sbeRes = coll.aggregate(pipeline).toArray(); diff --git a/jstests/noPassthrough/agg_group.js b/jstests/noPassthrough/agg_group.js index 234237baf72..885c43852d2 100644 --- a/jstests/noPassthrough/agg_group.js +++ b/jstests/noPassthrough/agg_group.js @@ -42,8 +42,8 @@ st.ensurePrimaryShard(db.getName(), st.shard0.shardName); let assertShardedGroupResultsMatch = (coll, pipeline) => { // Turns to the classic engine at the shard before figuring out its result. - assert.commandWorked( - dbAtShard.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true})); + assert.commandWorked(dbAtShard.adminCommand( + {setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false})); // Collects the classic engine's result as the expected result, executing the pipeline at the // mongos. @@ -52,8 +52,8 @@ let assertShardedGroupResultsMatch = (coll, pipeline) => { .cursor.firstBatch; // Turns to the SBE engine at the shard. - assert.commandWorked( - dbAtShard.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false})); + assert.commandWorked(dbAtShard.adminCommand( + {setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: true})); // Verifies that the SBE engine's results are same as the expected results, executing the // pipeline at the mongos. diff --git a/jstests/noPassthrough/profile_operation_metrics.js b/jstests/noPassthrough/profile_operation_metrics.js index 41da73e9e50..5ef83ba6d61 100644 --- a/jstests/noPassthrough/profile_operation_metrics.js +++ b/jstests/noPassthrough/profile_operation_metrics.js @@ -20,13 +20,15 @@ const isDebugBuild = (db) => { return db.adminCommand('buildInfo').debug; }; const isGroupPushdownEnabled = (db) => { - const internalQueryForceClassicEngine = - assert.commandWorked(db.adminCommand({getParameter: 1, internalQueryForceClassicEngine: 1})) - .internalQueryForceClassicEngine; + const internalQueryEnableSlotBasedExecutionEngine = + assert + .commandWorked( + db.adminCommand({getParameter: 1, internalQueryEnableSlotBasedExecutionEngine: 1})) + .internalQueryEnableSlotBasedExecutionEngine; const featureFlagSBEGroupPushdown = assert.commandWorked(db.adminCommand({getParameter: 1, featureFlagSBEGroupPushdown: 1})) .featureFlagSBEGroupPushdown.value; - return !internalQueryForceClassicEngine && featureFlagSBEGroupPushdown; + return internalQueryEnableSlotBasedExecutionEngine && featureFlagSBEGroupPushdown; }; const assertMetricsExist = (profilerEntry) => { diff --git a/jstests/noPassthrough/query_engine_stats.js b/jstests/noPassthrough/query_engine_stats.js index 492b4792efe..3e6b0ebe938 100644 --- a/jstests/noPassthrough/query_engine_stats.js +++ b/jstests/noPassthrough/query_engine_stats.js @@ -107,7 +107,8 @@ function compareQueryEngineCounters(expectedCounters) { } // Start with SBE off. -assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true})); +assert.commandWorked( + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false})); // Run a find command. let expectedCounters = generateExpectedCounters(engine.find.classic); @@ -142,7 +143,8 @@ compareQueryEngineCounters(expectedCounters); verifyProfiler(queryComment, engine.find.classic); // Turn SBE on. -assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false})); +assert.commandWorked( + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: true})); // Run a find command. expectedCounters = generateExpectedCounters(engine.find.sbe); diff --git a/jstests/noPassthrough/query_knobs_validation.js b/jstests/noPassthrough/query_knobs_validation.js index d5636ebadaf..cb76a691934 100644 --- a/jstests/noPassthrough/query_knobs_validation.js +++ b/jstests/noPassthrough/query_knobs_validation.js @@ -216,8 +216,8 @@ assertSetParameterSucceeds("internalQuerySlotBasedExecutionMaxStaticIndexScanInt assertSetParameterFails("internalQuerySlotBasedExecutionMaxStaticIndexScanIntervals", 0); assertSetParameterFails("internalQuerySlotBasedExecutionMaxStaticIndexScanIntervals", -1); -assertSetParameterSucceeds("internalQueryForceClassicEngine", true); -assertSetParameterSucceeds("internalQueryForceClassicEngine", false); +assertSetParameterSucceeds("internalQueryEnableSlotBasedExecutionEngine", true); +assertSetParameterSucceeds("internalQueryEnableSlotBasedExecutionEngine", false); assertSetParameterSucceeds("internalQueryCollectionMaxNoOfDocumentsToChooseHashJoin", 1); assertSetParameterFails("internalQueryCollectionMaxNoOfDocumentsToChooseHashJoin", 0); diff --git a/jstests/noPassthrough/sbe_multiplanner_trial_termination.js b/jstests/noPassthrough/sbe_multiplanner_trial_termination.js index 75739587a9f..2d77b962467 100644 --- a/jstests/noPassthrough/sbe_multiplanner_trial_termination.js +++ b/jstests/noPassthrough/sbe_multiplanner_trial_termination.js @@ -54,7 +54,8 @@ assert.commandWorked(db.adminCommand({setParameter: 1, [worksKnob]: trialLengthF // Force the classic engine and run an "allPlansExecution" verbosity explain. Confirm that the trial // period terminates based on the the "collection fraction" as opposed to // 'internalQueryPlanEvaluationWorks'. -assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true})); +assert.commandWorked( + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false})); let allPlans = getAllPlansExecution("1"); for (let plan of allPlans) { assert(plan.hasOwnProperty("executionStages"), plan); @@ -92,7 +93,8 @@ assert.gt(getParamRes[worksKnobSbe], numDocs); // default value of SBE's works knob exceeds the size of the collection, we expect the number of // reads to exceed the collection size as well. By construction of the test, this also means that // the trial period length exceeds both 'trialLengthFromCollFrac' and 'trialLengthFromWorksKnob'. -assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false})); +assert.commandWorked( + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: true})); allPlans = getAllPlansExecution("2"); verifySbeNumReads(allPlans, numDocs, assert.gt); diff --git a/jstests/noPassthrough/sbe_plan_cache_key_reporting.js b/jstests/noPassthrough/sbe_plan_cache_key_reporting.js index 41e242e872b..5c39ec6362e 100644 --- a/jstests/noPassthrough/sbe_plan_cache_key_reporting.js +++ b/jstests/noPassthrough/sbe_plan_cache_key_reporting.js @@ -42,7 +42,7 @@ function runTestAgainstSbeAndClassicEngines(testToRun) { return ["sbe", "classic"].map((engine) => { setupCollection(); assert.commandWorked(db.adminCommand( - {setParameter: 1, internalQueryForceClassicEngine: engine == "classic"})); + {setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: engine === "sbe"})); return testToRun(engine); }); } @@ -193,9 +193,9 @@ function assertQueryHashAndPlanCacheKey(sbe, classic) { assert.eq(classic.explainVersion, "1", classic); // The query hashes and the plan cache keys ('the keys') are different now because - // 'internalQueryForceClassicEngine' flag is encoded into query shape, once this flag is removed - // from the query shape encoding the keys will be the same until SERVER-61507 is completed, then - // the keys will be different forever. + // 'internalQueryEnableSlotBasedExecutionEngine' flag is encoded into query shape, once this + // flag is removed from the query shape encoding the keys will be the same until SERVER-61507 + // is completed, then the keys will be different forever. assertQueryHashAndPlanCacheKey(sbe.queryPlanner, classic.stages[0]["$cursor"].queryPlanner); })(); @@ -219,9 +219,9 @@ function assertQueryHashAndPlanCacheKey(sbe, classic) { assert.eq(classic.explainVersion, "1", classic); // The query hashes and the plan cache keys ('the keys') are different now because - // 'internalQueryForceClassicEngine' flag is encoded into query shape, once this flag is removed - // from the query shape encoding the keys will be the same until SERVER-61507 is completed, then - // the keys will be different forever. + // 'internalQueryEnableSlotBasedExecutionEngine' flag is encoded into query shape, once this + // flag is removed from the query shape encoding the keys will be the same until SERVER-61507 + // is completed, then the keys will be different forever. assertQueryHashAndPlanCacheKey(sbe.queryPlanner, classic.stages[0]["$cursor"].queryPlanner); })(); diff --git a/jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js b/jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js index df3ac0d3fd9..9c8f6fb5461 100644 --- a/jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js +++ b/jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js @@ -75,7 +75,8 @@ const planCacheSizeAfterSbeStep = getPlanCacheSize(); assert.lt(initialPlanCacheSize, planCacheSizeAfterSbeStep); // Force classic plan cache. -assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true})); +assert.commandWorked( + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false})); // Create a new collection for classic queries so we can easily assess its plan cache. const classicColl = createTestCollection("classic"); diff --git a/jstests/noPassthrough/sbe_plan_cache_size_metric.js b/jstests/noPassthrough/sbe_plan_cache_size_metric.js index 4cec6ba7f78..8e37ac8e26e 100644 --- a/jstests/noPassthrough/sbe_plan_cache_size_metric.js +++ b/jstests/noPassthrough/sbe_plan_cache_size_metric.js @@ -76,7 +76,8 @@ if (isSbePlanCacheEnabled) { // Step 2. Insert an entry to Classic Plan Cache. // Force classic plan cache. - assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true})); + assert.commandWorked( + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false})); assert.eq(1, coll.find(classicQuery).itcount()); assertQueryInPlanCache(coll, classicQuery); // Plan Cache must contain exactly 2 entries. @@ -95,7 +96,7 @@ if (isSbePlanCacheEnabled) { // Step 4. Remove the entry from SBE Plan Cache. // Move back to SBE plan cache. assert.commandWorked( - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false})); + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: true})); // Clean up SBE Plan Cache assert.commandWorked(db.runCommand({planCacheClear: collectionName, query: sbeQuery})); // Assert metric is decremented back to initial value. diff --git a/jstests/noPassthrough/server_status_multiplanner.js b/jstests/noPassthrough/server_status_multiplanner.js index f185cdb7841..10ac1d67e0a 100644 --- a/jstests/noPassthrough/server_status_multiplanner.js +++ b/jstests/noPassthrough/server_status_multiplanner.js @@ -44,7 +44,8 @@ assert.eq(multiPlannerMetrics.histograms.classicMicros[0].lowerBound, 0); // Run with classic engine and verify metrics. { - assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true})); + assert.commandWorked( + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false})); assert.commandWorked(coll.find({a: 1, b: 1, c: 1}).explain()); multiPlannerMetrics = db.serverStatus().metrics.query.multiPlanner; @@ -66,7 +67,7 @@ assert.eq(multiPlannerMetrics.histograms.classicMicros[0].lowerBound, 0); // Run with SBE and verify metrics. { assert.commandWorked( - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false})); + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: true})); assert.commandWorked(coll.find({a: 1, b: 1, c: 1}).explain()); multiPlannerMetrics = db.serverStatus().metrics.query.multiPlanner; diff --git a/jstests/noPassthroughWithMongod/group_pushdown.js b/jstests/noPassthroughWithMongod/group_pushdown.js index 6ef60d7e3c4..30f6bd58bf7 100644 --- a/jstests/noPassthroughWithMongod/group_pushdown.js +++ b/jstests/noPassthroughWithMongod/group_pushdown.js @@ -79,7 +79,7 @@ let assertResultsMatchWithAndWithoutGroupPushdown = function( assertGroupPushdown(coll, pipeline, expectedResults, expectedGroupCountInExplain); // Turn sbe off. - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true}); + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false}); // Sanity check the results when no pushdown happens. let resultNoGroupPushdown = coll.aggregate(pipeline).toArray(); @@ -87,7 +87,7 @@ let assertResultsMatchWithAndWithoutGroupPushdown = function( // Turn sbe on which will allow $group stages that contain supported accumulators to be pushed // down under certain conditions. - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false}); + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: true}); let resultWithGroupPushdown = coll.aggregate(pipeline).toArray(); assert.sameMembers(resultNoGroupPushdown, resultWithGroupPushdown); @@ -100,7 +100,7 @@ let assertResultsMatchWithAndWithoutProjectPushdown = function( {coll: coll, pipeline: pipeline, expectProjectToBePushedDown: expectProjectToBePushedDown}); // Turn sbe off. - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true}); + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false}); // Sanity check the results when no project pushdown happens. let resultNoProjectPushdown = coll.aggregate(pipeline).toArray(); @@ -108,17 +108,17 @@ let assertResultsMatchWithAndWithoutProjectPushdown = function( // Turn sbe on which will allow $group stages that contain supported accumulators to be pushed // down under certain conditions. - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false}); + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: true}); let resultWithProjectPushdown = coll.aggregate(pipeline).toArray(); assert.sameMembers(resultNoProjectPushdown, resultWithProjectPushdown); }; let assertShardedGroupResultsMatch = function(coll, pipeline, expectedGroupCountInExplain = 1) { - const originalClassicEngineStatus = + const originalSBEEngineStatus = assert - .commandWorked( - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true})) + .commandWorked(db.adminCommand( + {setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false})) .was; const cmd = { @@ -131,7 +131,7 @@ let assertShardedGroupResultsMatch = function(coll, pipeline, expectedGroupCount const classicalRes = coll.runCommand(cmd).cursor.firstBatch; assert.commandWorked( - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false})); + db.adminCommand({setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: true})); const explainCmd = { aggregate: coll.getName(), pipeline: pipeline, @@ -147,7 +147,7 @@ let assertShardedGroupResultsMatch = function(coll, pipeline, expectedGroupCount assert.sameMembers(sbeRes, classicalRes); assert.commandWorked(db.adminCommand( - {setParameter: 1, internalQueryForceClassicEngine: originalClassicEngineStatus})); + {setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: originalSBEEngineStatus})); }; // Try a pipeline with no group stage. diff --git a/jstests/sharding/query/lookup_graph_lookup_foreign_becomes_sharded.js b/jstests/sharding/query/lookup_graph_lookup_foreign_becomes_sharded.js index c3924654a74..2c799f31f88 100644 --- a/jstests/sharding/query/lookup_graph_lookup_foreign_becomes_sharded.js +++ b/jstests/sharding/query/lookup_graph_lookup_foreign_becomes_sharded.js @@ -117,11 +117,11 @@ const isShardedLookupEnabled = getShardedLookupParam.hasOwnProperty("featureFlag let res = st.getPrimaryShard(jsTestName()).getDB("admin").adminCommand({ getParameter: 1, featureFlagSBELookupPushdown: 1, - internalQueryForceClassicEngine: 1 + internalQueryEnableSlotBasedExecutionEngine: 1 }); let isSBELookupEnabled = res.ok && res.hasOwnProperty("featureFlagSBELookupPushdown") && - res.hasOwnProperty("internalQueryForceClassicEngine") && - res.featureFlagSBELookupPushdown.value && !res.internalQueryForceClassicEngine; + res.hasOwnProperty("internalQueryEnableSlotBasedExecutionEngine") && + res.featureFlagSBELookupPushdown.value && res.internalQueryEnableSlotBasedExecutionEngine; // Now run a getMore for each of the test cases. The collection has become sharded mid-iteration, so // we should observe the error code associated with the test case. diff --git a/src/mongo/db/commands/plan_cache_clear_command.cpp b/src/mongo/db/commands/plan_cache_clear_command.cpp index daf4bb18937..a3e8fcfc1fb 100644 --- a/src/mongo/db/commands/plan_cache_clear_command.cpp +++ b/src/mongo/db/commands/plan_cache_clear_command.cpp @@ -92,7 +92,7 @@ Status clear(OperationContext* opCtx, // sbe::isQuerySbeCompatible here. const size_t plannerOptions = 0; if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV() && - !cq->getForceClassicEngine() && + cq->getEnableSlotBasedExecutionEngine() && sbe::isQuerySbeCompatible(&collection, cq.get(), plannerOptions)) { cq->setSbeCompatible(true); sbe::getPlanCache(opCtx).remove( diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp index fbba650d37d..ff034ff6cc0 100644 --- a/src/mongo/db/pipeline/pipeline_d.cpp +++ b/src/mongo/db/pipeline/pipeline_d.cpp @@ -110,14 +110,14 @@ namespace { * pipeline to prepare for pushdown of $group and $lookup into the inner query layer so that it * can be executed using SBE. * Group stages are extracted from the pipeline when all of the following conditions are met: - * 0. When the 'internalQueryForceClassicEngine' feature flag is 'false'. + * 0. When the 'internalQueryEnableSlotBasedExecutionEngine' feature flag is 'true'. * 1. When 'allowDiskUse' is false. We currently don't support spilling in the SBE HashAgg * stage. This will change once that is supported when SERVER-58436 is complete. * 2. When the DocumentSourceGroup has 'doingMerge=false', this will change when we implement * hash table spilling in SERVER-58436. * * Lookup stages are extracted from the pipeline when all of the following conditions are met: - * 0. When the 'internalQueryForceClassicEngine' feature flag is 'false'. + * 0. When the 'internalQueryEnableSlotBasedExecutionEngine' feature flag is 'true'. * 1. When the 'featureFlagSBELookupPushdown' feature flag is 'true'. * 2. The $lookup uses only the 'localField'/'foreignField' syntax (no pipelines). * 3. The foreign collection is neither sharded nor a view. @@ -138,7 +138,7 @@ std::vector<std::unique_ptr<InnerPipelineStageInterface>> extractSbeCompatibleSt } // No pushdown if we're using the classic engine. - if (cq->getForceClassicEngine()) { + if (!cq->getEnableSlotBasedExecutionEngine()) { return {}; } diff --git a/src/mongo/db/query/canonical_query.cpp b/src/mongo/db/query/canonical_query.cpp index 2271f4ce494..7df5350daac 100644 --- a/src/mongo/db/query/canonical_query.cpp +++ b/src/mongo/db/query/canonical_query.cpp @@ -195,7 +195,7 @@ Status CanonicalQuery::init(OperationContext* opCtx, _findCommand = std::move(findCommand); _canHaveNoopMatchNodes = canHaveNoopMatchNodes; - _forceClassicEngine = internalQueryForceClassicEngine.load(); + _enableSlotBasedExecutionEngine = internalQueryEnableSlotBasedExecutionEngine.load(); auto validStatus = isValid(root.get(), *_findCommand); if (!validStatus.isOK()) { @@ -545,7 +545,7 @@ CanonicalQuery::QueryShapeString CanonicalQuery::encodeKey() const { // TODO SERVER-61507: remove '_pipeline.empty()' check. Canonical queries with pushed down // $group/$lookup stages are not SBE-compatible until SERVER-61507 is complete. return (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV() && - !_forceClassicEngine && _sbeCompatible && _pipeline.empty()) + _enableSlotBasedExecutionEngine && _sbeCompatible && _pipeline.empty()) ? canonical_query_encoder::encodeSBE(*this) : canonical_query_encoder::encode(*this); } diff --git a/src/mongo/db/query/canonical_query.h b/src/mongo/db/query/canonical_query.h index 99d1eddcb58..9f25a92740b 100644 --- a/src/mongo/db/query/canonical_query.h +++ b/src/mongo/db/query/canonical_query.h @@ -221,8 +221,8 @@ public: return _explain; } - bool getForceClassicEngine() const { - return _forceClassicEngine; + bool getEnableSlotBasedExecutionEngine() const { + return _enableSlotBasedExecutionEngine; } void setSbeCompatible(bool sbeCompatible) { @@ -304,8 +304,8 @@ private: bool _explain = false; - // Determines whether the classic engine must be used. - bool _forceClassicEngine = false; + // Determines whether the SBE engine is enabled. + bool _enableSlotBasedExecutionEngine = false; // True if this query can be executed by the SBE. bool _sbeCompatible = false; diff --git a/src/mongo/db/query/canonical_query_encoder.cpp b/src/mongo/db/query/canonical_query_encoder.cpp index a6a94915e91..bfbaa2544c5 100644 --- a/src/mongo/db/query/canonical_query_encoder.cpp +++ b/src/mongo/db/query/canonical_query_encoder.cpp @@ -667,7 +667,7 @@ CanonicalQuery::QueryShapeString encode(const CanonicalQuery& cq) { // This encoding can be removed once the classic query engine reaches EOL and SBE is used // exclusively for all query execution. - keyBuilder << kEncodeEngineSection << (cq.getForceClassicEngine() ? "f" : "t"); + keyBuilder << kEncodeEngineSection << (cq.getEnableSlotBasedExecutionEngine() ? "t" : "f"); return keyBuilder.str(); } diff --git a/src/mongo/db/query/canonical_query_encoder_test.cpp b/src/mongo/db/query/canonical_query_encoder_test.cpp index 928fdbda8ee..27e8ae74707 100644 --- a/src/mongo/db/query/canonical_query_encoder_test.cpp +++ b/src/mongo/db/query/canonical_query_encoder_test.cpp @@ -40,7 +40,6 @@ #include "mongo/unittest/unittest.h" #include "mongo/util/assert_util.h" - namespace mongo { namespace { @@ -147,103 +146,120 @@ void testComputeSBEKey(const char* queryStr, TEST(CanonicalQueryEncoderTest, ComputeKey) { // Generated cache keys should be treated as opaque to the user. + // The computed key depends on which execution engine is enabled. As such, we disable SBE for + // this test so that the test doesn't break should the default value of + // 'internalQueryEnableSlotBasedExecutionEngine' change in the future. + RAIIServerParameterControllerForTest controllerSBE( + "internalQueryEnableSlotBasedExecutionEngine", false); + // No sorts - testComputeKey("{}", "{}", "{}", "an@t"); - testComputeKey("{$or: [{a: 1}, {b: 2}]}", "{}", "{}", "or[eqa,eqb]@t"); + testComputeKey("{}", "{}", "{}", "an@f"); + testComputeKey("{$or: [{a: 1}, {b: 2}]}", "{}", "{}", "or[eqa,eqb]@f"); testComputeKey( - "{$or: [{a: 1}, {b: 1}, {c: 1}], d: 1}", "{}", "{}", "an[or[eqa,eqb,eqc],eqd]@t"); - testComputeKey("{$or: [{a: 1}, {b: 1}], c: 1, d: 1}", "{}", "{}", "an[or[eqa,eqb],eqc,eqd]@t"); - testComputeKey("{a: 1, b: 1, c: 1}", "{}", "{}", "an[eqa,eqb,eqc]@t"); - testComputeKey("{a: 1, beqc: 1}", "{}", "{}", "an[eqa,eqbeqc]@t"); - testComputeKey("{ap1a: 1}", "{}", "{}", "eqap1a@t"); - testComputeKey("{aab: 1}", "{}", "{}", "eqaab@t"); + "{$or: [{a: 1}, {b: 1}, {c: 1}], d: 1}", "{}", "{}", "an[or[eqa,eqb,eqc],eqd]@f"); + testComputeKey("{$or: [{a: 1}, {b: 1}], c: 1, d: 1}", "{}", "{}", "an[or[eqa,eqb],eqc,eqd]@f"); + testComputeKey("{a: 1, b: 1, c: 1}", "{}", "{}", "an[eqa,eqb,eqc]@f"); + testComputeKey("{a: 1, beqc: 1}", "{}", "{}", "an[eqa,eqbeqc]@f"); + testComputeKey("{ap1a: 1}", "{}", "{}", "eqap1a@f"); + testComputeKey("{aab: 1}", "{}", "{}", "eqaab@f"); // With sort - testComputeKey("{}", "{a: 1}", "{}", "an~aa@t"); - testComputeKey("{}", "{a: -1}", "{}", "an~da@t"); + testComputeKey("{}", "{a: 1}", "{}", "an~aa@f"); + testComputeKey("{}", "{a: -1}", "{}", "an~da@f"); testComputeKey("{$text: {$search: 'search keywords'}}", "{a: {$meta: 'textScore'}}", "{a: {$meta: 'textScore'}}", - "te_fts~ta@t"); - testComputeKey("{a: 1}", "{b: 1}", "{}", "eqa~ab@t"); + "te_fts~ta@f"); + testComputeKey("{a: 1}", "{b: 1}", "{}", "eqa~ab@f"); // With projection - testComputeKey("{}", "{}", "{a: 1}", "an|_id-a@t"); - testComputeKey("{}", "{}", "{a: -1}", "an|_id-a@t"); - testComputeKey("{}", "{}", "{a: -1.0}", "an|_id-a@t"); - testComputeKey("{}", "{}", "{a: true}", "an|_id-a@t"); - testComputeKey("{}", "{}", "{a: 0}", "an@t"); - testComputeKey("{}", "{}", "{a: false}", "an@t"); - testComputeKey("{}", "{}", "{a: 99}", "an|_id-a@t"); - testComputeKey("{}", "{}", "{a: 'foo'}", "an|_id@t"); + testComputeKey("{}", "{}", "{a: 1}", "an|_id-a@f"); + testComputeKey("{}", "{}", "{a: -1}", "an|_id-a@f"); + testComputeKey("{}", "{}", "{a: -1.0}", "an|_id-a@f"); + testComputeKey("{}", "{}", "{a: true}", "an|_id-a@f"); + testComputeKey("{}", "{}", "{a: 0}", "an@f"); + testComputeKey("{}", "{}", "{a: false}", "an@f"); + testComputeKey("{}", "{}", "{a: 99}", "an|_id-a@f"); + testComputeKey("{}", "{}", "{a: 'foo'}", "an|_id@f"); // $slice defaults to exclusion. - testComputeKey("{}", "{}", "{a: {$slice: [3, 5]}}", "an@t"); - testComputeKey("{}", "{}", "{a: {$slice: [3, 5]}, b: 0}", "an@t"); + testComputeKey("{}", "{}", "{a: {$slice: [3, 5]}}", "an@f"); + testComputeKey("{}", "{}", "{a: {$slice: [3, 5]}, b: 0}", "an@f"); // But even when using $slice in an inclusion, the entire document is needed. - testComputeKey("{}", "{}", "{a: {$slice: [3, 5]}, b: 1}", "an@t"); + testComputeKey("{}", "{}", "{a: {$slice: [3, 5]}, b: 1}", "an@f"); - testComputeKey("{}", "{}", "{a: {$elemMatch: {x: 2}}}", "an@t"); - testComputeKey("{}", "{}", "{a: {$elemMatch: {x: 2}}, b: 0}", "an@t"); - testComputeKey("{}", "{}", "{a: {$elemMatch: {x: 2}}, b: 1}", "an@t"); + testComputeKey("{}", "{}", "{a: {$elemMatch: {x: 2}}}", "an@f"); + testComputeKey("{}", "{}", "{a: {$elemMatch: {x: 2}}, b: 0}", "an@f"); + testComputeKey("{}", "{}", "{a: {$elemMatch: {x: 2}}, b: 1}", "an@f"); - testComputeKey("{}", "{}", "{a: {$slice: [3, 5]}, b: {$elemMatch: {x: 2}}}", "an@t"); + testComputeKey("{}", "{}", "{a: {$slice: [3, 5]}, b: {$elemMatch: {x: 2}}}", "an@f"); - testComputeKey("{}", "{}", "{a: ObjectId('507f191e810c19729de860ea')}", "an|_id@t"); + testComputeKey("{}", "{}", "{a: ObjectId('507f191e810c19729de860ea')}", "an|_id@f"); // Since this projection overwrites the entire document, no fields are required. testComputeKey( - "{}", "{}", "{_id: 0, a: ObjectId('507f191e810c19729de860ea'), b: 'foo'}", "an|@t"); - testComputeKey("{a: 1}", "{}", "{'a.$': 1}", "eqa@t"); - testComputeKey("{a: 1}", "{}", "{a: 1}", "eqa|_id-a@t"); + "{}", "{}", "{_id: 0, a: ObjectId('507f191e810c19729de860ea'), b: 'foo'}", "an|@f"); + testComputeKey("{a: 1}", "{}", "{'a.$': 1}", "eqa@f"); + testComputeKey("{a: 1}", "{}", "{a: 1}", "eqa|_id-a@f"); // Projection should be order-insensitive - testComputeKey("{}", "{}", "{a: 1, b: 1}", "an|_id-a-b@t"); - testComputeKey("{}", "{}", "{b: 1, a: 1}", "an|_id-a-b@t"); + testComputeKey("{}", "{}", "{a: 1, b: 1}", "an|_id-a-b@f"); + testComputeKey("{}", "{}", "{b: 1, a: 1}", "an|_id-a-b@f"); // And should escape the separation character. - testComputeKey("{}", "{}", "{'b-1': 1, 'a-2': 1}", "an|_id-a\\-2-b\\-1@t"); + testComputeKey("{}", "{}", "{'b-1': 1, 'a-2': 1}", "an|_id-a\\-2-b\\-1@f"); // And should exclude $-prefixed fields which can be added internally. - testComputeKey("{}", "{x: 1}", "{$sortKey: {$meta: 'sortKey'}}", "an~ax@t"); - testComputeKey("{}", "{}", "{}", "an@t"); + testComputeKey("{}", "{x: 1}", "{$sortKey: {$meta: 'sortKey'}}", "an~ax@f"); + testComputeKey("{}", "{}", "{}", "an@f"); - testComputeKey("{}", "{x: 1}", "{a: 1, $sortKey: {$meta: 'sortKey'}}", "an~ax|_id-a@t"); - testComputeKey("{}", "{}", "{a: 1}", "an|_id-a@t"); + testComputeKey("{}", "{x: 1}", "{a: 1, $sortKey: {$meta: 'sortKey'}}", "an~ax|_id-a@f"); + testComputeKey("{}", "{}", "{a: 1}", "an|_id-a@f"); // With or-elimination and projection - testComputeKey("{$or: [{a: 1}]}", "{}", "{_id: 0, a: 1}", "eqa|a@t"); - testComputeKey("{$or: [{a: 1}]}", "{}", "{'a.$': 1}", "eqa@t"); + testComputeKey("{$or: [{a: 1}]}", "{}", "{_id: 0, a: 1}", "eqa|a@f"); + testComputeKey("{$or: [{a: 1}]}", "{}", "{'a.$': 1}", "eqa@f"); } TEST(CanonicalQueryEncoderTest, EncodeNotEqualNullPredicates) { + // The computed key depends on which execution engine is enabled. As such, we disable SBE for + // this test so that the test doesn't break should the default value of + // 'internalQueryEnableSlotBasedExecutionEngine' change in the future. + RAIIServerParameterControllerForTest controllerSBE( + "internalQueryEnableSlotBasedExecutionEngine", false); + // With '$eq', '$gte', and '$lte' negation comparison to 'null'. - testComputeKey("{a: {$not: {$eq: null}}}", "{}", "{_id: 0, a: 1}", "ntnot_eq_null[eqa]|a@t"); + testComputeKey("{a: {$not: {$eq: null}}}", "{}", "{_id: 0, a: 1}", "ntnot_eq_null[eqa]|a@f"); testComputeKey( - "{a: {$not: {$eq: null}}}", "{a: 1}", "{_id: 0, a: 1}", "ntnot_eq_null[eqa]~aa|a@t"); + "{a: {$not: {$eq: null}}}", "{a: 1}", "{_id: 0, a: 1}", "ntnot_eq_null[eqa]~aa|a@f"); testComputeKey( - "{a: {$not: {$gte: null}}}", "{a: 1}", "{_id: 0, a: 1}", "ntnot_eq_null[gea]~aa|a@t"); + "{a: {$not: {$gte: null}}}", "{a: 1}", "{_id: 0, a: 1}", "ntnot_eq_null[gea]~aa|a@f"); testComputeKey( - "{a: {$not: {$lte: null}}}", "{a: 1}", "{_id: 0, a: 1}", "ntnot_eq_null[lea]~aa|a@t"); + "{a: {$not: {$lte: null}}}", "{a: 1}", "{_id: 0, a: 1}", "ntnot_eq_null[lea]~aa|a@f"); // Same '$eq' negation query with non-'null' argument should have different key. - testComputeKey("{a: {$not: {$eq: true}}}", "{a: 1}", "{_id: 0, a: 1}", "nt[eqa]~aa|a@t"); + testComputeKey("{a: {$not: {$eq: true}}}", "{a: 1}", "{_id: 0, a: 1}", "nt[eqa]~aa|a@f"); } // Delimiters found in user field names or non-standard projection field values // must be escaped. TEST(CanonicalQueryEncoderTest, ComputeKeyEscaped) { + // The computed key depends on which execution engine is enabled. As such, we disable SBE for + // this test so that the test doesn't break should the default value of + // 'internalQueryEnableSlotBasedExecutionEngine' change in the future. + RAIIServerParameterControllerForTest controllerSBE( + "internalQueryEnableSlotBasedExecutionEngine", false); // Field name in query. - testComputeKey("{'a,[]~|-<>': 1}", "{}", "{}", "eqa\\,\\[\\]\\~\\|\\-<>@t"); + testComputeKey("{'a,[]~|-<>': 1}", "{}", "{}", "eqa\\,\\[\\]\\~\\|\\-<>@f"); // Field name in sort. - testComputeKey("{}", "{'a,[]~|-<>': 1}", "{}", "an~aa\\,\\[\\]\\~\\|\\-<>@t"); + testComputeKey("{}", "{'a,[]~|-<>': 1}", "{}", "an~aa\\,\\[\\]\\~\\|\\-<>@f"); // Field name in projection. - testComputeKey("{}", "{}", "{'a,[]~|-<>': 1}", "an|_id-a\\,\\[\\]\\~\\|\\-<>@t"); + testComputeKey("{}", "{}", "{'a,[]~|-<>': 1}", "an|_id-a\\,\\[\\]\\~\\|\\-<>@f"); // String literal provided as value. - testComputeKey("{}", "{}", "{a: 'foo,[]~|-<>'}", "an|_id@t"); + testComputeKey("{}", "{}", "{a: 'foo,[]~|-<>'}", "an|_id@f"); } // Cache keys for $geoWithin queries with legacy and GeoJSON coordinates should @@ -266,17 +282,27 @@ TEST(CanonicalQueryEncoderTest, ComputeKeyGeoWithin) { // GEO_NEAR cache keys should include information on geometry and CRS in addition // to the match type and field name. TEST(CanonicalQueryEncoderTest, ComputeKeyGeoNear) { - testComputeKey("{a: {$near: [0,0], $maxDistance:0.3 }}", "{}", "{}", "gnanrfl@t"); - testComputeKey("{a: {$nearSphere: [0,0], $maxDistance: 0.31 }}", "{}", "{}", "gnanssp@t"); + // The computed key depends on which execution engine is enabled. As such, we disable SBE for + // this test so that the test doesn't break should the default value of + // 'internalQueryEnableSlotBasedExecutionEngine' change in the future. + RAIIServerParameterControllerForTest controllerSBE( + "internalQueryEnableSlotBasedExecutionEngine", false); + + testComputeKey("{a: {$near: [0,0], $maxDistance:0.3 }}", "{}", "{}", "gnanrfl@f"); + testComputeKey("{a: {$nearSphere: [0,0], $maxDistance: 0.31 }}", "{}", "{}", "gnanssp@f"); testComputeKey( "{a: {$geoNear: {$geometry: {type: 'Point', coordinates: [0,0]}," "$maxDistance:100}}}", "{}", "{}", - "gnanrsp@t"); + "gnanrsp@f"); } TEST(CanonicalQueryEncoderTest, ComputeKeyRegexDependsOnFlags) { + // The computed key depends on which execution engine is enabled. As such, we enable SBE for + // this test in order to ensure that we have coverage for both SBE and the classic engine. + RAIIServerParameterControllerForTest controllerSBE( + "internalQueryEnableSlotBasedExecutionEngine", true); testComputeKey("{a: {$regex: \"sometext\"}}", "{}", "{}", "rea@t"); testComputeKey("{a: {$regex: \"sometext\", $options: \"\"}}", "{}", "{}", "rea@t"); @@ -307,61 +333,76 @@ TEST(CanonicalQueryEncoderTest, ComputeKeyRegexDependsOnFlags) { } TEST(CanonicalQueryEncoderTest, ComputeKeyMatchInDependsOnPresenceOfRegexAndFlags) { + // The computed key depends on which execution engine is enabled. As such, we disable SBE for + // this test so that the test doesn't break should the default value of + // 'internalQueryEnableSlotBasedExecutionEngine' change in the future. + RAIIServerParameterControllerForTest controllerSBE( + "internalQueryEnableSlotBasedExecutionEngine", false); + // Test that an $in containing a single regex is unwrapped to $regex. - testComputeKey("{a: {$in: [/foo/]}}", "{}", "{}", "rea@t"); - testComputeKey("{a: {$in: [/foo/i]}}", "{}", "{}", "rea/i/@t"); + testComputeKey("{a: {$in: [/foo/]}}", "{}", "{}", "rea@f"); + testComputeKey("{a: {$in: [/foo/i]}}", "{}", "{}", "rea/i/@f"); // Test that an $in with no regexes does not include any regex information. - testComputeKey("{a: {$in: [1, 'foo']}}", "{}", "{}", "ina@t"); + testComputeKey("{a: {$in: [1, 'foo']}}", "{}", "{}", "ina@f"); // Test that an $in with a regex encodes the presence of the regex. - testComputeKey("{a: {$in: [1, /foo/]}}", "{}", "{}", "ina_re@t"); + testComputeKey("{a: {$in: [1, /foo/]}}", "{}", "{}", "ina_re@f"); // Test that an $in with a regex encodes the presence of the regex and its flags. - testComputeKey("{a: {$in: [1, /foo/is]}}", "{}", "{}", "ina_re/is/@t"); + testComputeKey("{a: {$in: [1, /foo/is]}}", "{}", "{}", "ina_re/is/@f"); // Test that the computed key is invariant to the order of the flags within each regex. - testComputeKey("{a: {$in: [1, /foo/si]}}", "{}", "{}", "ina_re/is/@t"); + testComputeKey("{a: {$in: [1, /foo/si]}}", "{}", "{}", "ina_re/is/@f"); // Test that an $in with multiple regexes encodes all unique flags. - testComputeKey("{a: {$in: [1, /foo/i, /bar/m, /baz/s]}}", "{}", "{}", "ina_re/ims/@t"); + testComputeKey("{a: {$in: [1, /foo/i, /bar/m, /baz/s]}}", "{}", "{}", "ina_re/ims/@f"); // Test that an $in with multiple regexes deduplicates identical flags. testComputeKey( - "{a: {$in: [1, /foo/i, /bar/m, /baz/s, /qux/i, /quux/s]}}", "{}", "{}", "ina_re/ims/@t"); + "{a: {$in: [1, /foo/i, /bar/m, /baz/s, /qux/i, /quux/s]}}", "{}", "{}", "ina_re/ims/@f"); // Test that the computed key is invariant to the ordering of the flags across regexes. testComputeKey("{a: {$in: [1, /foo/ism, /bar/msi, /baz/im, /qux/si, /quux/im]}}", "{}", "{}", - "ina_re/ims/@t"); + "ina_re/ims/@f"); testComputeKey("{a: {$in: [1, /foo/msi, /bar/ism, /baz/is, /qux/mi, /quux/im]}}", "{}", "{}", - "ina_re/ims/@t"); + "ina_re/ims/@f"); // Test that $not-$in-$regex similarly records the presence and flags of any regexes. - testComputeKey("{a: {$not: {$in: [1, 'foo']}}}", "{}", "{}", "nt[ina]@t"); - testComputeKey("{a: {$not: {$in: [1, /foo/]}}}", "{}", "{}", "nt[ina_re]@t"); + testComputeKey("{a: {$not: {$in: [1, 'foo']}}}", "{}", "{}", "nt[ina]@f"); + testComputeKey("{a: {$not: {$in: [1, /foo/]}}}", "{}", "{}", "nt[ina_re]@f"); testComputeKey( - "{a: {$not: {$in: [1, /foo/i, /bar/i, /baz/msi]}}}", "{}", "{}", "nt[ina_re/ims/]@t"); + "{a: {$not: {$in: [1, /foo/i, /bar/i, /baz/msi]}}}", "{}", "{}", "nt[ina_re/ims/]@f"); // Test that a $not-$in containing a single regex is unwrapped to $not-$regex. - testComputeKey("{a: {$not: {$in: [/foo/]}}}", "{}", "{}", "nt[rea]@t"); - testComputeKey("{a: {$not: {$in: [/foo/i]}}}", "{}", "{}", "nt[rea/i/]@t"); + testComputeKey("{a: {$not: {$in: [/foo/]}}}", "{}", "{}", "nt[rea]@f"); + testComputeKey("{a: {$not: {$in: [/foo/i]}}}", "{}", "{}", "nt[rea/i/]@f"); } TEST(CanonicalQueryEncoderTest, CheckCollationIsEncoded) { + // The computed key depends on which execution engine is enabled. As such, we disable SBE for + // this test so that the test doesn't break should the default value of + // 'internalQueryEnableSlotBasedExecutionEngine' change in the future. + RAIIServerParameterControllerForTest controllerSBE( + "internalQueryEnableSlotBasedExecutionEngine", false); unique_ptr<CanonicalQuery> cq(canonicalize( fromjson("{a: 1, b: 1}"), {}, {}, fromjson("{locale: 'mock_reverse_string'}"))); - testComputeKey(*cq, "an[eqa,eqb]#mock_reverse_string02300000@t"); + testComputeKey(*cq, "an[eqa,eqb]#mock_reverse_string02300000@f"); } TEST(CanonicalQueryEncoderTest, ComputeKeySBE) { // Generated cache keys should be treated as opaque to the user. + // SBE must be enabled in order to generate SBE plan cache keys. + RAIIServerParameterControllerForTest controllerSBE( + "internalQueryEnableSlotBasedExecutionEngine", true); + // TODO SERVER-61314: Remove when featureFlagSbePlanCache is removed. RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbePlanCache", true); diff --git a/src/mongo/db/query/explain.cpp b/src/mongo/db/query/explain.cpp index 414badb8332..4ec9e8d9e7d 100644 --- a/src/mongo/db/query/explain.cpp +++ b/src/mongo/db/query/explain.cpp @@ -96,7 +96,7 @@ void generatePlannerInfo(PlanExecutor* exec, QuerySettingsDecoration::get(collection->getSharedDecorations()); if (exec->getCanonicalQuery()->isSbeCompatible() && feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV() && - !exec->getCanonicalQuery()->getForceClassicEngine() && + exec->getCanonicalQuery()->getEnableSlotBasedExecutionEngine() && // TODO(SERVER-61507): Remove pipeline check once lowered pipelines are integrated with // SBE plan cache. exec->getCanonicalQuery()->pipeline().empty()) { diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp index 9eba8febf1f..df84d16f0e0 100644 --- a/src/mongo/db/query/get_executor.cpp +++ b/src/mongo/db/query/get_executor.cpp @@ -1386,7 +1386,7 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutor( const auto& mainColl = collections.getMainCollection(); canonicalQuery->setSbeCompatible( sbe::isQuerySbeCompatible(&mainColl, canonicalQuery.get(), plannerOptions)); - return !canonicalQuery->getForceClassicEngine() && canonicalQuery->isSbeCompatible() + return canonicalQuery->getEnableSlotBasedExecutionEngine() && canonicalQuery->isSbeCompatible() ? getSlotBasedExecutor(opCtx, collections, std::move(canonicalQuery), diff --git a/src/mongo/db/query/plan_cache_key_info_test.cpp b/src/mongo/db/query/plan_cache_key_info_test.cpp index 13d37bd7b12..472b1f0ab9c 100644 --- a/src/mongo/db/query/plan_cache_key_info_test.cpp +++ b/src/mongo/db/query/plan_cache_key_info_test.cpp @@ -420,10 +420,10 @@ TEST(PlanCacheKeyInfoTest, DifferentQueryEngines) { false, // sparse IndexEntry::Identifier{""})}; // name - // Helper to construct a plan cache key given the 'forceClassicEngine' flag. - auto constructPlanCacheKey = [&](bool forceClassicEngine) { - RAIIServerParameterControllerForTest controller{"internalQueryForceClassicEngine", - forceClassicEngine}; + // Helper to construct a plan cache key given the 'enableSlotBasedExecutionEngine' flag. + auto constructPlanCacheKey = [&](bool enableSlotBasedExecutionEngine) { + RAIIServerParameterControllerForTest controller{ + "internalQueryEnableSlotBasedExecutionEngine", enableSlotBasedExecutionEngine}; const auto queryStr = "{a: 0}"; unique_ptr<CanonicalQuery> cq(canonicalize(queryStr)); return makeKey(*cq, indexCores); diff --git a/src/mongo/db/query/query_knobs.idl b/src/mongo/db/query/query_knobs.idl index 4756981a4b9..c75f5beb09e 100644 --- a/src/mongo/db/query/query_knobs.idl +++ b/src/mongo/db/query/query_knobs.idl @@ -653,11 +653,11 @@ server_parameters: default: false on_update: plan_cache_util::clearSbeCacheOnParameterChange - internalQueryForceClassicEngine: - description: "If true, the system will use the classic execution engine for all queries, - otherwise eligible queries will execute using the SBE execution engine." + internalQueryEnableSlotBasedExecutionEngine: + description: "If true, the system will use the SBE execution engine for eligible queries, + otherwise all queries will execute using the classic execution engine." set_at: [ startup, runtime ] - cpp_varname: "internalQueryForceClassicEngine" + cpp_varname: "internalQueryEnableSlotBasedExecutionEngine" cpp_vartype: AtomicWord<bool> default: false diff --git a/src/mongo/db/query/query_planner.cpp b/src/mongo/db/query/query_planner.cpp index fa810499cb4..69c679888f8 100644 --- a/src/mongo/db/query/query_planner.cpp +++ b/src/mongo/db/query/query_planner.cpp @@ -212,7 +212,7 @@ void tryToAddColumnScan(const QueryPlannerParams& params, // We only want to use the columnar index if we can avoid fetching the whole document. return; } - if (!query.isSbeCompatible() || query.getForceClassicEngine()) { + if (!query.isSbeCompatible() || !query.getEnableSlotBasedExecutionEngine()) { // We only support column scans in SBE. return; } diff --git a/src/mongo/db/query/query_planner_columnar_test.cpp b/src/mongo/db/query/query_planner_columnar_test.cpp index 7698a24a08e..10c92f6cebd 100644 --- a/src/mongo/db/query/query_planner_columnar_test.cpp +++ b/src/mongo/db/query/query_planner_columnar_test.cpp @@ -38,6 +38,7 @@ #include "mongo/db/query/query_planner.h" #include "mongo/db/query/query_planner_test_fixture.h" #include "mongo/db/query/query_planner_test_lib.h" +#include "mongo/idl/server_parameter_test_util.h" #include "mongo/unittest/death_test.h" namespace mongo { @@ -81,6 +82,11 @@ protected: } return stages; } + +private: + // SBE must be enabled in order to test columnar indexes. + RAIIServerParameterControllerForTest _controllerSBE{ + "internalQueryEnableSlotBasedExecutionEngine", true}; }; TEST_F(QueryPlannerColumnarTest, InclusionProjectionUsesColumnarIndex) { diff --git a/src/mongo/dbtests/query_stage_multiplan.cpp b/src/mongo/dbtests/query_stage_multiplan.cpp index 3552cf095fd..ce40f343858 100644 --- a/src/mongo/dbtests/query_stage_multiplan.cpp +++ b/src/mongo/dbtests/query_stage_multiplan.cpp @@ -551,7 +551,8 @@ TEST_F(QueryStageMultiPlanTest, MPSExplainAllPlans) { // // This is a regression test for SERVER-20111. TEST_F(QueryStageMultiPlanTest, MPSSummaryStats) { - RAIIServerParameterControllerForTest controller("internalQueryForceClassicEngine", true); + RAIIServerParameterControllerForTest controller("internalQueryEnableSlotBasedExecutionEngine", + false); const int N = 5000; for (int i = 0; i < N; ++i) { diff --git a/src/mongo/shell/servers.js b/src/mongo/shell/servers.js index 165ee334be4..bf688fb06bd 100644 --- a/src/mongo/shell/servers.js +++ b/src/mongo/shell/servers.js @@ -643,6 +643,20 @@ var _isMongodVersionEqualOrAfter = function(version1, version2) { return false; }; +// Returns if version2 came before version 1. +var _isMongodVersionBefore = function(version1, version2) { + var versionParts1 = _convertVersionToIntegerArray(version1); + var versionParts2 = _convertVersionToIntegerArray(version2); + if (versionParts2[0] < versionParts1[0] || + (versionParts2[0] === versionParts1[0] && versionParts2[1] < versionParts1[1]) || + (versionParts2[0] === versionParts1[0] && versionParts2[1] === versionParts1[1] && + versionParts2[2] < versionParts1[2])) { + return true; + } + + return false; +}; + // Removes a setParameter parameter from mongods or mongoses running a version that won't recognize // them. var _removeSetParameterIfBeforeVersion = function( @@ -658,6 +672,24 @@ var _removeSetParameterIfBeforeVersion = function( } }; +// Similar to the function above, but accepts two versions such that if the configured binVersion is +// between the specified versions, it removes the setParameter parameter. +var _removeSetParameterIfBetweenSpecifiedVersions = function( + opts, parameterName, afterVersion, beforeVersion, isMongos = false) { + var processString = isMongos ? "mongos" : "mongod"; + var versionCompatible = (opts.binVersion === "" || opts.binVersion === undefined || + // For 'opts.binVersion' to be compatible with 'parameterName', it must + // be GTE 'afterVersion' or LT 'beforeVersion'. + _isMongodVersionEqualOrAfter(afterVersion, opts.binVersion) || + _isMongodVersionBefore(beforeVersion, opts.binVersion)); + if (!versionCompatible && opts.setParameter && opts.setParameter[parameterName] != undefined) { + print("Removing '" + parameterName + "' setParameter with value " + + opts.setParameter[parameterName] + " because it isn't compatible with " + + processString + " running version " + opts.binVersion); + delete opts.setParameter[parameterName]; + } +}; + /** * @option {object} opts * @@ -703,7 +735,8 @@ MongoRunner.mongodOptions = function(opts = {}) { opts, "enableDefaultWriteConcernUpdatesForInitiate", "5.0.0"); _removeSetParameterIfBeforeVersion(opts, "enableReconfigRollbackCommittedWritesCheck", "5.0.0"); _removeSetParameterIfBeforeVersion(opts, "featureFlagRetryableFindAndModify", "5.0.0"); - _removeSetParameterIfBeforeVersion(opts, "internalQueryForceClassicEngine", "5.1.0"); + _removeSetParameterIfBetweenSpecifiedVersions( + opts, "internalQueryEnableSlotBasedExecutionEngine", "6.0.0", "5.1.0"); _removeSetParameterIfBeforeVersion(opts, "allowMultipleArbiters", "5.3.0"); if (!opts.logFile && opts.useLogFiles) { |