diff options
author | David Storch <david.storch@mongodb.com> | 2022-07-14 18:09:12 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-07-14 19:16:56 +0000 |
commit | 5dfda9e29d70115f1af249d540b414ad8227834a (patch) | |
tree | c2340734a5ab04e57ddc1d950d8ac4994cfb4039 | |
parent | 91cef76e80b79fe4a2867413af5910027c3b69d5 (diff) | |
download | mongo-5dfda9e29d70115f1af249d540b414ad8227834a.tar.gz |
SERVER-61314 Consolidate featureFlagSbePlanCache with featureFlagSbeFull
41 files changed, 224 insertions, 278 deletions
diff --git a/jstests/core/collation_plan_cache.js b/jstests/core/collation_plan_cache.js index 8f108a89b9e..88a54798642 100644 --- a/jstests/core/collation_plan_cache.js +++ b/jstests/core/collation_plan_cache.js @@ -14,8 +14,7 @@ load("jstests/libs/analyze_plan.js"); // For getPlanCacheKeyFromExplain. load("jstests/libs/sbe_util.js"); // For checkSBEEnabled. -const isSbePlanCacheEnabled = - checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]); +const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]); var coll = db.collation_plan_cache; coll.drop(); @@ -49,7 +48,7 @@ assert.commandWorked( // The query shape should have been added. var shapes = coll.aggregate([{$planCacheStats: {}}]).toArray(); assert.eq(1, shapes.length, 'unexpected cache size after running query'); -if (!isSbePlanCacheEnabled) { +if (!isSbeEnabled) { assert.eq(shapes[0].createdFromQuery.query, {a: 'foo', b: 5}, shapes); assert.eq(shapes[0].createdFromQuery.sort, {}, shapes); assert.eq(shapes[0].createdFromQuery.projection, {}, shapes); diff --git a/jstests/core/explode_for_sort_plan_cache.js b/jstests/core/explode_for_sort_plan_cache.js index f4e5a87be7f..7a3935ce233 100644 --- a/jstests/core/explode_for_sort_plan_cache.js +++ b/jstests/core/explode_for_sort_plan_cache.js @@ -56,7 +56,7 @@ const sortSpec = { // TODO SERVER-67576: remove this branch once explode for sort plans are supported by the SBE plan // cache. -if (checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) { +if (checkSBEEnabled(db, ["featureFlagSbeFull"])) { // Run the query for the first time and make sure the plan hasn't been cached. assert.eq(0, coll.find(querySpec).sort(sortSpec).itcount()); assertCacheEntryDoesNotExist(querySpec, sortSpec); diff --git a/jstests/core/idhack.js b/jstests/core/idhack.js index ff541a59c0f..69c157221e0 100644 --- a/jstests/core/idhack.js +++ b/jstests/core/idhack.js @@ -62,9 +62,8 @@ winningPlan = getWinningPlan(explain.queryPlanner); engineSpecificAssertion(!isIdhack(db, winningPlan), isIxscan(db, winningPlan), db, winningPlan); // Covered query returning _id field only can be handled by ID hack. -const isSBEPlanCacheEnabled = - checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]); -const parentStage = isSBEPlanCacheEnabled ? "PROJECTION_COVERED" : "FETCH"; +const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]); +const parentStage = isSbeEnabled ? "PROJECTION_COVERED" : "FETCH"; explain = t.find(query, {_id: 1}).explain(); winningPlan = getWinningPlan(explain.queryPlanner); engineSpecificAssertion( diff --git a/jstests/core/index_filter_commands_invalidate_plan_cache_entries.js b/jstests/core/index_filter_commands_invalidate_plan_cache_entries.js index e4011c61198..37f23dc96d4 100644 --- a/jstests/core/index_filter_commands_invalidate_plan_cache_entries.js +++ b/jstests/core/index_filter_commands_invalidate_plan_cache_entries.js @@ -17,10 +17,9 @@ load("jstests/libs/analyze_plan.js"); // For getPlanCacheKeyFromShape. load("jstests/libs/sbe_util.js"); // For checkSBEEnabled. -// For testing convenience this variable is made an integer "1" if featureFlagSbePlanCache is on, -// because the expected amount of plan cache entries differs between the two different plan caches. -const isSbePlanCacheEnabled = - checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]) ? 1 : 0; +// For testing convenience this variable is made an integer "1" if SBE is fully enabled, because the +// expected amount of plan cache entries differs between the SBE plan cache and the classic one. +const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]) ? 1 : 0; const collName = "index_filter_commands_invalidate_plan_cache_entries"; const coll = db[collName]; @@ -61,11 +60,11 @@ assert.eq(0, coll.find({a: 1}).skip(1).itcount()); // SBE plan cache key encodes "skip", so there's one more plan cache entry in SBE plan cache. While // in classic plan cache, queries with only difference in "skip" share the same plan cache entry. -assert.eq(coll.aggregate([{$planCacheStats: {}}]).itcount(), 3 + isSbePlanCacheEnabled); +assert.eq(coll.aggregate([{$planCacheStats: {}}]).itcount(), 3 + isSbeEnabled); assert.commandWorked( db.runCommand({planCacheSetFilter: collName, query: {a: 1, b: 1}, indexes: [{a: 1}]})); -assert.eq(coll.aggregate([{$planCacheStats: {}}]).toArray().length, 2 + isSbePlanCacheEnabled); +assert.eq(coll.aggregate([{$planCacheStats: {}}]).toArray().length, 2 + isSbeEnabled); // This planCacheSetFilter command will invalidate plan cache entries with filter {a: 1}. There are // two entries in the SBE plan cache that got invalidated, or one entry in the classic plan cache diff --git a/jstests/core/plan_cache_list_plans.js b/jstests/core/plan_cache_list_plans.js index e478be751da..02a1d71593c 100644 --- a/jstests/core/plan_cache_list_plans.js +++ b/jstests/core/plan_cache_list_plans.js @@ -24,7 +24,7 @@ load("jstests/libs/sbe_util.js"); // For checkSBEEnabled. let coll = db.jstests_plan_cache_list_plans; coll.drop(); -const isSBEAndPlanCacheOn = checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]); +const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]); function dumpPlanCacheState() { return coll.aggregate([{$planCacheStats: {}}]).toArray(); @@ -94,7 +94,7 @@ let entry = getPlansForCacheEntry({a: 1, b: 1}, {a: -1}, {_id: 0, a: 1}); assert(entry.hasOwnProperty('works'), entry); assert.eq(entry.isActive, false); -if (!isSBEAndPlanCacheOn) { +if (!isSbeEnabled) { // Note that SBE plan cache entry does not include "creationExecStats". We expect that there // were two candidate plans evaluated when the cache entry was created. assert(entry.hasOwnProperty("creationExecStats"), entry); @@ -131,7 +131,7 @@ entry = getPlansForCacheEntry({a: 3, b: 3}, {a: -1}, {_id: 0, a: 1}); assert(entry.hasOwnProperty('works'), entry); assert.eq(entry.isActive, true); -if (!isSBEAndPlanCacheOn) { +if (!isSbeEnabled) { // Note that SBE plan cache entry does not include "creationExecStats". There should be the same // number of candidate plan scores as candidate plans. assert.eq(entry.creationExecStats.length, entry.candidatePlanScores.length, entry); diff --git a/jstests/core/plan_cache_list_shapes.js b/jstests/core/plan_cache_list_shapes.js index 83dd402cbbb..6db043884bf 100644 --- a/jstests/core/plan_cache_list_shapes.js +++ b/jstests/core/plan_cache_list_shapes.js @@ -16,8 +16,8 @@ 'use strict'; load("jstests/libs/sbe_util.js"); // For checkSBEEnabled. -if (checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) { - jsTest.log("Skipping test because SBE and SBE plan cache are both enabled."); +if (checkSBEEnabled(db, ["featureFlagSbeFull"])) { + jsTest.log("Skipping test because SBE is fully enabled."); return; } diff --git a/jstests/core/plan_cache_sbe.js b/jstests/core/plan_cache_sbe.js index 6ca74ad42f3..723b96abc54 100644 --- a/jstests/core/plan_cache_sbe.js +++ b/jstests/core/plan_cache_sbe.js @@ -19,18 +19,16 @@ (function() { "use strict"; -load("jstests/libs/sbe_util.js"); // For checkSBEEnabled. -load("jstests/libs/sbe_explain_helpers.js"); // For engineSpecificAssertion. +load("jstests/libs/sbe_util.js"); // For checkSBEEnabled. const coll = db.plan_cache_sbe; coll.drop(); -const isSbePlanCacheEnabled = - checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]); +const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]); assert.commandWorked(coll.insert({a: 1, b: 1})); // Check that a new entry is added to the plan cache even for single plans. -if (isSbePlanCacheEnabled) { +if (isSbeEnabled) { assert.eq(1, coll.find({a: 1}).itcount()); // Validate sbe plan cache stats entry. const allStats = coll.aggregate([{$planCacheStats: {}}]).toArray(); @@ -56,23 +54,11 @@ assert.eq(allStats.length, 1, allStats); const stats = allStats[0]; assert(stats.hasOwnProperty("cachedPlan"), stats); -if (!isSbePlanCacheEnabled) { - // TODO SERVER-61314: Please modify this branch when "featureFlagSbePlanCache" is removed. - // Currently this branch will be taken if either 1) SBE is disabled, or 2) SBE is enabled but - // the "featureFlagSbePlanCache" flag is disabled. - engineSpecificAssertion(!stats.cachedPlan.hasOwnProperty("queryPlan"), - stats.cachedPlan.hasOwnProperty("queryPlan"), - db, - stats); - engineSpecificAssertion(!stats.cachedPlan.hasOwnProperty("slotBasedPlan"), - stats.cachedPlan.hasOwnProperty("slotBasedPlan"), - db, - stats); +if (isSbeEnabled) { + assert(stats.cachedPlan.hasOwnProperty("slots"), stats); + assert(stats.cachedPlan.hasOwnProperty("stages"), stats); } else { - engineSpecificAssertion( - !stats.cachedPlan.hasOwnProperty("slots") && !stats.cachedPlan.hasOwnProperty("stages"), - stats.cachedPlan.hasOwnProperty("slots") && stats.cachedPlan.hasOwnProperty("stages"), - db, - stats); + assert(!stats.cachedPlan.hasOwnProperty("queryPlan"), stats); + assert(!stats.cachedPlan.hasOwnProperty("slotBasedPlan"), stats); } })(); diff --git a/jstests/core/plan_cache_shell_helpers.js b/jstests/core/plan_cache_shell_helpers.js index 299f071e8d9..1628883aaa2 100644 --- a/jstests/core/plan_cache_shell_helpers.js +++ b/jstests/core/plan_cache_shell_helpers.js @@ -17,8 +17,7 @@ load('jstests/aggregation/extras/utils.js'); // For assertArrayEq. load("jstests/libs/analyze_plan.js"); // For getPlanCacheKeyFromShape. load("jstests/libs/sbe_util.js"); // For checkSBEEnabled. -const isSBEPlanCacheEnabled = - checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]); +const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]); var coll = db.jstests_plan_cache_shell_helpers; coll.drop(); @@ -81,7 +80,7 @@ assert.eq([{count: 4}], planCache.list([{$count: "count"}]), planCache.list()); // Test that we can collect descriptions of all the queries that created cache entries using the // list() helper. -if (isSBEPlanCacheEnabled) { +if (isSbeEnabled) { assertArrayEq({ expected: [ {planCacheKey: getPlanCacheKeyFromShape({query: queryB, collection: coll, db: db})}, diff --git a/jstests/core/query_hash_stability.js b/jstests/core/query_hash_stability.js index 129c8a4c701..aa0a3399e70 100644 --- a/jstests/core/query_hash_stability.js +++ b/jstests/core/query_hash_stability.js @@ -112,7 +112,7 @@ assertPlanCacheField({ // SBE's planCacheKey encoding encodes "collection version" which will be increased after dropping // an index. -if (!checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) { +if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) { // The 'planCacheKey' should be the same as what it was before we dropped the index. assertPlanCacheField({ firstExplain: initialExplain, diff --git a/jstests/core/sbe/plan_cache_sbe_with_or_queries.js b/jstests/core/sbe/plan_cache_sbe_with_or_queries.js index f5e61d19110..a529af6e23c 100644 --- a/jstests/core/sbe/plan_cache_sbe_with_or_queries.js +++ b/jstests/core/sbe/plan_cache_sbe_with_or_queries.js @@ -16,9 +16,8 @@ load("jstests/libs/analyze_plan.js"); load("jstests/libs/sbe_util.js"); // For checkSBEEnabled. -const isSBEEnabled = checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]); -if (!isSBEEnabled) { - jsTest.log("Skip running the test because featureFlagSbePlanCache is not enabled"); +if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) { + jsTest.log("Skip running the test because SBE is not enabled"); return; } diff --git a/jstests/core/sbe_plan_cache_autoparameterize_collscan.js b/jstests/core/sbe_plan_cache_autoparameterize_collscan.js index 63054ff7d7d..05c188a04a5 100644 --- a/jstests/core/sbe_plan_cache_autoparameterize_collscan.js +++ b/jstests/core/sbe_plan_cache_autoparameterize_collscan.js @@ -17,10 +17,10 @@ load("jstests/libs/analyze_plan.js"); load("jstests/libs/sbe_util.js"); -// This test is specifically verifying the behavior of the SBE plan cache. So if either the SBE plan -// cache or SBE itself are disabled, bail out. -if (!checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) { - jsTestLog("Skipping test because either SBE engine or SBE plan cache is disabled"); +// This test is specifically verifying the behavior of the SBE plan cache, which is only enabled +// when 'featureFlagSbeFull' is on. +if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) { + jsTestLog("Skipping test because SBE is not fully enabled"); return; } diff --git a/jstests/core/wildcard_index_cached_plans.js b/jstests/core/wildcard_index_cached_plans.js index 9b0b0c33b6d..586882381e9 100644 --- a/jstests/core/wildcard_index_cached_plans.js +++ b/jstests/core/wildcard_index_cached_plans.js @@ -19,9 +19,8 @@ load('jstests/libs/analyze_plan.js'); // For getPlanStage(). load("jstests/libs/collection_drop_recreate.js"); // For assert[Drop|Create]Collection. -load('jstests/libs/fixture_helpers.js'); // For getPrimaryForNodeHostingDatabase and isMongos. -load("jstests/libs/sbe_util.js"); // For checkSBEEnabled. -load("jstests/libs/sbe_explain_helpers.js"); // For engineSpecificAssertion. +load('jstests/libs/fixture_helpers.js'); // For getPrimaryForNodeHostingDatabase and isMongos. +load("jstests/libs/sbe_util.js"); // For checkSBEEnabled. const coll = db.wildcard_cached_plans; coll.drop(); @@ -29,7 +28,7 @@ coll.drop(); assert.commandWorked(coll.createIndex({"b.$**": 1})); assert.commandWorked(coll.createIndex({"a": 1})); -const sbePlanCacheEnabled = checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]); +const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]); // In order for the plan cache to be used, there must be more than one plan available. Insert // data into the collection such that the b.$** index will be far more selective than the index @@ -72,22 +71,11 @@ for (let i = 0; i < 2; i++) { let cacheEntry = getCacheEntryForQuery(query); assert.neq(cacheEntry, null); assert.eq(cacheEntry.isActive, true); -if (!sbePlanCacheEnabled) { +if (!isSbeEnabled) { // Should be at least two plans: one using the {a: 1} index and the other using the b.$** index. assert.gte(cacheEntry.creationExecStats.length, 2, tojson(cacheEntry.plans)); - // In SBE index scan stage does not serialize key pattern in execution stats, so we use IXSCAN - // from the query plan instead. - const sbeIxScan = function() { - const cachedPlan = cacheEntry.cachedPlan; - if (!cachedPlan) - return null; - if (!cachedPlan.queryPlan) - return null; - return getPlanStage(cachedPlan.queryPlan, "IXSCAN"); - }(); - - const classicIxScan = function() { + const ixscan = function() { const execStats = cacheEntry.creationExecStats; if (!execStats) return null; @@ -99,11 +87,14 @@ if (!sbePlanCacheEnabled) { return getPlanStage(elem.executionStages, "IXSCAN"); }(); const expectedKeyPattern = {"$_path": 1, "b": 1}; - const classicKeyPatternMatch = - classicIxScan !== null && bsonWoCompare(classicIxScan.keyPattern, expectedKeyPattern) === 0; - const sbeKeyPatternmatch = - sbeIxScan !== null && bsonWoCompare(sbeIxScan.keyPattern, expectedKeyPattern) === 0; - engineSpecificAssertion(classicKeyPatternMatch, sbeKeyPatternmatch, db, tojson(cacheEntry)); + assert.neq(null, ixscan, cacheEntry); + assert(bsonWoCompare(ixscan.keyPattern, expectedKeyPattern) === 0, ixscan); +} else { + assert(cacheEntry.hasOwnProperty("cachedPlan"), cacheEntry); + assert(cacheEntry.cachedPlan.hasOwnProperty("stages"), cacheEntry); + const sbePlan = cacheEntry.cachedPlan.stages; + // The SBE plan string should contain the name of the b.$** index. + assert(sbePlan.includes("b.$**_1"), cacheEntry); } // Run the query again. This time it should use the cached plan. We should get the same result @@ -125,7 +116,7 @@ assert.neq(getPlanCacheKeyFromShape({query: queryWithBNull, collection: coll, db // There should only have been one solution for the above query, so it would get cached only by the // SBE plan cache. cacheEntry = getCacheEntryForQuery({a: 1, b: null}); -if (sbePlanCacheEnabled) { +if (isSbeEnabled) { assert.neq(cacheEntry, null); assert.eq(cacheEntry.isActive, true, cacheEntry); assert.eq(cacheEntry.isPinned, true, cacheEntry); diff --git a/jstests/core/wildcard_index_filter.js b/jstests/core/wildcard_index_filter.js index e4f06a30fc7..414b46ef1dc 100644 --- a/jstests/core/wildcard_index_filter.js +++ b/jstests/core/wildcard_index_filter.js @@ -12,12 +12,6 @@ load("jstests/libs/analyze_plan.js"); load("jstests/libs/fixture_helpers.js"); // For 'isMongos()'. -load("jstests/libs/sbe_util.js"); // For checkSBEEnabled. - -if (checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) { - jsTest.log("Skipping test because SBE and SBE plan cache are both enabled."); - return; -} const coll = db.wildcard_index_filter; diff --git a/jstests/noPassthrough/plan_cache_group_lookup.js b/jstests/noPassthrough/plan_cache_group_lookup.js index 22d5b90fc28..88b84dd1def 100644 --- a/jstests/noPassthrough/plan_cache_group_lookup.js +++ b/jstests/noPassthrough/plan_cache_group_lookup.js @@ -19,7 +19,6 @@ if (!checkSBEEnabled(db)) { } const sbeFullEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]); -const sbePlanCacheEnabled = checkSBEEnabled(db, ["featureFlagSbePlanCache"]); assert.commandWorked(coll.insert({a: 1})); assert.commandWorked(coll.createIndex({a: 1, a1: 1})); @@ -102,7 +101,7 @@ const groupStage = { (function testLoweredPipelineCombination() { setupForeignColl(); - const expectedVersion = sbePlanCacheEnabled ? 2 : 1; + const expectedVersion = sbeFullEnabled ? 2 : 1; coll.getPlanCache().clear(); testLoweredPipeline( @@ -126,14 +125,13 @@ const groupStage = { setupForeignColl(); testLoweredPipeline({ pipeline: [multiPlanningQueryStage, lookupStage, {$_internalInhibitOptimization: {}}], - version: sbePlanCacheEnabled ? 2 : 1 + version: sbeFullEnabled ? 2 : 1 }); })(); (function testNonExistentForeignCollectionCache() { - if (!sbePlanCacheEnabled) { - jsTestLog( - "Skipping testNonExistentForeignCollectionCache when SBE plan cache is not enabled"); + if (!sbeFullEnabled) { + jsTestLog("Skipping testNonExistentForeignCollectionCache when SBE is not fully enabled"); return; } @@ -156,9 +154,9 @@ const groupStage = { })(); (function testForeignCollectionDropCacheInvalidation() { - if (!sbePlanCacheEnabled) { + if (!sbeFullEnabled) { jsTestLog( - "Skipping testForeignCollectionDropCacheInvalidation when SBE plan cache is not enabled"); + "Skipping testForeignCollectionDropCacheInvalidation when SBE is not fully enabled"); return; } @@ -171,9 +169,8 @@ const groupStage = { })(); (function testForeignIndexDropCacheInvalidation() { - if (!sbePlanCacheEnabled) { - jsTestLog( - "Skipping testForeignIndexDropCacheInvalidation when SBE plan cache is not enabled"); + if (!sbeFullEnabled) { + jsTestLog("Skipping testForeignIndexDropCacheInvalidation when SBE is not fully enabled"); return; } @@ -186,9 +183,8 @@ const groupStage = { })(); (function testForeignIndexBuildCacheInvalidation() { - if (!sbePlanCacheEnabled) { - jsTestLog( - "Skipping testForeignIndexBuildCacheInvalidation when SBE plan cache is not enabled"); + if (!sbeFullEnabled) { + jsTestLog("Skipping testForeignIndexBuildCacheInvalidation when SBE is not fully enabled"); return; } @@ -201,9 +197,8 @@ const groupStage = { })(); (function testLookupSbeAndClassicPlanCacheKey() { - if (!sbeFullEnabled || !sbePlanCacheEnabled) { - jsTestLog( - "Skipping testLookupWithClassicPlanCache when SBE full or SBE plan cache is not enabled"); + if (!sbeFullEnabled) { + jsTestLog("Skipping testLookupWithClassicPlanCache when SBE is not fully enabled"); return; } diff --git a/jstests/noPassthrough/plan_cache_index_create.js b/jstests/noPassthrough/plan_cache_index_create.js index 862a46b7c64..26d6c1d8bb7 100644 --- a/jstests/noPassthrough/plan_cache_index_create.js +++ b/jstests/noPassthrough/plan_cache_index_create.js @@ -178,8 +178,8 @@ rst.initiate(); const primaryDB = rst.getPrimary().getDB(dbName); const secondaryDB = rst.getSecondary().getDB(dbName); -if (checkSBEEnabled(primaryDB, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) { - jsTest.log("Skipping test because SBE and SBE plan cache are both enabled."); +if (checkSBEEnabled(primaryDB, ["featureFlagSbeFull"])) { + jsTest.log("Skipping test because SBE is fully enabled"); rst.stopSet(); return; } diff --git a/jstests/noPassthrough/plan_cache_list_failed_plans.js b/jstests/noPassthrough/plan_cache_list_failed_plans.js index 853680f1872..9fd79e8308e 100644 --- a/jstests/noPassthrough/plan_cache_list_failed_plans.js +++ b/jstests/noPassthrough/plan_cache_list_failed_plans.js @@ -8,10 +8,9 @@ const conn = MongoRunner.runMongod(); assert.neq(null, conn, "mongod was unable to start up"); const testDB = conn.getDB("jstests_plan_cache_list_failed_plans"); const coll = testDB.test; -const isSBEEnabled = checkSBEEnabled(testDB, ["featureFlagSbeFull"]); -if (checkSBEEnabled(testDB, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) { - jsTest.log("Skipping test because SBE and SBE plan cache are both enabled."); +if (checkSBEEnabled(testDB, ["featureFlagSbeFull"])) { + jsTest.log("Skipping test because SBE is fully enabled"); MongoRunner.stopMongod(conn); return; } @@ -44,12 +43,7 @@ const creationExecStats = planCacheEntry.creationExecStats; assert.eq(creationExecStats.length, 2, planCacheEntry); // We expect that the first plan succeed, and the second failed. assert(!creationExecStats[0].hasOwnProperty("failed"), planCacheEntry); -// SBE will not report the 'failed' field. -if (isSBEEnabled) { - assert(!creationExecStats[1].hasOwnProperty("failed"), planCacheEntry); -} else { - assert.eq(creationExecStats[1].failed, true, planCacheEntry); -} +assert.eq(creationExecStats[1].failed, true, planCacheEntry); // The failing plan should have a score of 0. const candidatePlanScores = planCacheEntry.candidatePlanScores; diff --git a/jstests/noPassthrough/plan_cache_memory_debug_info.js b/jstests/noPassthrough/plan_cache_memory_debug_info.js index e7c36ac4fff..dc126dcc2b0 100644 --- a/jstests/noPassthrough/plan_cache_memory_debug_info.js +++ b/jstests/noPassthrough/plan_cache_memory_debug_info.js @@ -79,8 +79,8 @@ assert.neq(conn, null, "mongod failed to start"); const db = conn.getDB("test"); const coll = db.plan_cache_memory_debug_info; -if (checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) { - jsTest.log("Skipping test because SBE and SBE plan cache are both enabled."); +if (checkSBEEnabled(db, ["featureFlagSbeFull"])) { + jsTest.log("Skipping test because SBE is fully enabled"); MongoRunner.stopMongod(conn); return; } diff --git a/jstests/noPassthrough/plan_cache_replan_group_lookup.js b/jstests/noPassthrough/plan_cache_replan_group_lookup.js index 73d89c93b31..5da23cf502f 100644 --- a/jstests/noPassthrough/plan_cache_replan_group_lookup.js +++ b/jstests/noPassthrough/plan_cache_replan_group_lookup.js @@ -19,7 +19,6 @@ const coll = db.plan_cache_replan_group_lookup; const foreignCollName = "foreign"; coll.drop(); -const sbePlanCacheEnabled = checkSBEEnabled(db, ["featureFlagSbePlanCache"]); const sbeFullEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]); function getPlansForCacheEntry(match) { @@ -166,7 +165,7 @@ const aIndexPredicate = [{$match: {a: 1042, b: 1}}]; // {a: 1} index is used. const bIndexPredicate = [{$match: {a: 1, b: 1042}}]; -const expectedVersion = sbePlanCacheEnabled ? 2 : 1; +const expectedVersion = sbeFullEnabled ? 2 : 1; // $group tests. const groupSuffix = [{$group: {_id: "$c"}}, {$count: "n"}]; testFn(aIndexPredicate.concat(groupSuffix), @@ -260,9 +259,9 @@ assert.eq(2, coll.aggregate(aLookup).toArray()[0].n); // If SBE plan cache is enabled, a new cache entry will be created in the SBE plan cache after // invalidation. The corresponding cache entry in SBE plan cache should be inactive because the SBE // plan cache is invalidated on index drop. -assertCacheUsage(sbePlanCacheEnabled /*multiPlanning*/, +assertCacheUsage(sbeFullEnabled /*multiPlanning*/, expectedVersion /* cacheEntryVersion */, - !sbePlanCacheEnabled /*cacheEntryIsActive*/, + !sbeFullEnabled /*cacheEntryIsActive*/, "a_1" /*cachedIndexName*/, aLookup); @@ -271,7 +270,7 @@ verifyCorrectLookupAlgorithmUsed("NestedLoopJoin", aLookup, {allowDiskUse: false assert.eq(2, coll.aggregate(aLookup).toArray()[0].n); // Note that multi-planning is expected here when the SBE plan cache is enabled because the // 'allowDiskUse' value is part of the SBE plan cache key encoding. -assertCacheUsage(sbePlanCacheEnabled /*multiPlanning*/, +assertCacheUsage(sbeFullEnabled /*multiPlanning*/, expectedVersion /* cacheEntryVersion */, true /*cacheEntryIsActive*/, "a_1" /*cachedIndexName*/, @@ -281,9 +280,9 @@ assertCacheUsage(sbePlanCacheEnabled /*multiPlanning*/, dropLookupForeignColl(); verifyCorrectLookupAlgorithmUsed("NonExistentForeignCollection", aLookup, {allowDiskUse: true}); assert.eq(2, coll.aggregate(aLookup).toArray()[0].n); -assertCacheUsage(sbePlanCacheEnabled /*multiPlanning*/, +assertCacheUsage(sbeFullEnabled /*multiPlanning*/, expectedVersion /* cacheEntryVersion */, - !sbePlanCacheEnabled /*cacheEntryIsActive*/, + !sbeFullEnabled /*cacheEntryIsActive*/, "a_1" /*cachedIndexName*/, aLookup); @@ -346,10 +345,10 @@ verifyCorrectLookupAlgorithmUsed( // If SBE plan cache is enabled, after dropping index, the $lookup plan cache will be invalidated. // We will need to rerun the multi-planner. -if (sbePlanCacheEnabled) { +if (sbeFullEnabled) { runLookupQuery({allowDiskUse: false}); assertCacheUsage(true /*multiPlanning*/, - sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */, + 2 /* cacheEntryVersion */, false /*activeCacheEntry*/, "b_1" /*cachedIndexName*/, avoidReplanLookupPipeline, @@ -357,7 +356,7 @@ if (sbePlanCacheEnabled) { runLookupQuery({allowDiskUse: false}); assertCacheUsage(true /*multiPlanning*/, - sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */, + 2 /* cacheEntryVersion */, true /*activeCacheEntry*/, "b_1" /*cachedIndexName*/, avoidReplanLookupPipeline, @@ -366,7 +365,7 @@ if (sbePlanCacheEnabled) { runLookupQuery({allowDiskUse: false}); assertCacheUsage(false /*multiPlanning*/, - sbePlanCacheEnabled && sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */, + sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */, true /*activeCacheEntry*/, "b_1" /*cachedIndexName*/, avoidReplanLookupPipeline, @@ -374,7 +373,7 @@ assertCacheUsage(false /*multiPlanning*/, runLookupQuery({allowDiskUse: false}); assertCacheUsage(false /*multiPlanning*/, - sbePlanCacheEnabled && sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */, + sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */, true /*activeCacheEntry*/, "b_1" /*cachedIndexName*/, avoidReplanLookupPipeline, @@ -386,7 +385,7 @@ verifyCorrectLookupAlgorithmUsed("HashJoin", avoidReplanLookupPipeline, {allowDi // If SBE plan cache is enabled, using different 'allowDiskUse' option will result in // different plan cache key. -if (sbePlanCacheEnabled) { +if (sbeFullEnabled) { runLookupQuery({allowDiskUse: true}); assertCacheUsage(true /*multiPlanning*/, 2 /* cacheEntryVersion */, @@ -406,14 +405,14 @@ if (sbePlanCacheEnabled) { runLookupQuery({allowDiskUse: true}); assertCacheUsage(false /*multiPlanning*/, - sbePlanCacheEnabled ? 2 : 1 /* cacheEntryVersion */, + sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */, true /*activeCacheEntry*/, "b_1" /*cachedIndexName*/, avoidReplanLookupPipeline, {allowDiskUse: true}); runLookupQuery({allowDiskUse: true}); assertCacheUsage(false /*multiPlanning*/, - sbePlanCacheEnabled ? 2 : 1 /* cacheEntryVersion */, + sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */, true /*activeCacheEntry*/, "b_1" /*cachedIndexName*/, avoidReplanLookupPipeline, @@ -439,25 +438,25 @@ verifyCorrectLookupAlgorithmUsed("IndexedLoopJoin", avoidReplanLookupPipeline); // Set up an active cache entry. runLookupQuery(); assertCacheUsage(true /*multiPlanning*/, - sbePlanCacheEnabled ? 2 : 1 /* cacheEntryVersion */, + sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */, false /*activeCacheEntry*/, "b_1" /*cachedIndexName*/, avoidReplanLookupPipeline); runLookupQuery(); assertCacheUsage(true /*multiPlanning*/, - sbePlanCacheEnabled ? 2 : 1 /* cacheEntryVersion */, + sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */, true /*activeCacheEntry*/, "b_1" /*cachedIndexName*/, avoidReplanLookupPipeline); runLookupQuery(); assertCacheUsage(false /*multiPlanning*/, - sbePlanCacheEnabled ? 2 : 1 /* cacheEntryVersion */, + sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */, true /*activeCacheEntry*/, "b_1" /*cachedIndexName*/, avoidReplanLookupPipeline); runLookupQuery(); assertCacheUsage(false /*multiPlanning*/, - sbePlanCacheEnabled ? 2 : 1 /* cacheEntryVersion */, + sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */, true /*activeCacheEntry*/, "b_1" /*cachedIndexName*/, avoidReplanLookupPipeline); @@ -472,7 +471,7 @@ let explain = coll.explain().aggregate(avoidReplanLookupPipeline); const eqLookupNodes = getAggPlanStages(explain, "EQ_LOOKUP"); assert.eq(eqLookupNodes.length, 0, "expected no EQ_LOOKUP nodes; got " + tojson(explain)); -if (sbePlanCacheEnabled) { +if (sbeFullEnabled) { runLookupQuery(); const profileObj = getLatestProfilerEntry(db, {op: "command", ns: coll.getFullName()}); const matchingCacheEntries = @@ -541,7 +540,7 @@ explain = coll.explain().aggregate(avoidReplanLookupPipeline); groupNodes = getAggPlanStages(explain, "GROUP"); assert.eq(groupNodes.length, 0); -if (sbePlanCacheEnabled) { +if (sbeFullEnabled) { runGroupQuery(); const profileObj = getLatestProfilerEntry(db, {op: "command", ns: coll.getFullName()}); const matchingCacheEntries = diff --git a/jstests/noPassthrough/plan_cache_replan_sort.js b/jstests/noPassthrough/plan_cache_replan_sort.js index e905c1a4425..711a2676a15 100644 --- a/jstests/noPassthrough/plan_cache_replan_sort.js +++ b/jstests/noPassthrough/plan_cache_replan_sort.js @@ -44,7 +44,7 @@ assert.eq(1, cachedPlans.length, cachedPlans); assert.eq(true, cachedPlans[0].isActive, cachedPlans); const cachedPlan = getCachedPlan(cachedPlans[0].cachedPlan); const cachedPlanVersion = cachedPlans[0].version; -if (checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) { +if (checkSBEEnabled(db, ["featureFlagSbeFull"])) { // If the SBE plan cache is on, then the cached plan has a different format. assert.eq(cachedPlanVersion, "2", cachedPlans); assert(cachedPlan.stages.includes("sort"), cachedPlans); diff --git a/jstests/noPassthrough/sbe_plan_cache_clear_on_param_change.js b/jstests/noPassthrough/sbe_plan_cache_clear_on_param_change.js index eecea2a2349..f5fe74022d1 100644 --- a/jstests/noPassthrough/sbe_plan_cache_clear_on_param_change.js +++ b/jstests/noPassthrough/sbe_plan_cache_clear_on_param_change.js @@ -48,10 +48,10 @@ assert.neq(conn, null, "mongod failed to start up"); const dbName = jsTestName(); const db = conn.getDB(dbName); -// This test is specifically verifying the behavior of the SBE plan cache. So if either the SBE plan -// cache or SBE itself are disabled, bail out. -if (!checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) { - jsTestLog("Skipping test because either SBE engine or SBE plan cache are disabled"); +// This test is specifically verifying the behavior of the SBE plan cache which is enabled by +// 'featureFlagSbeFull'. +if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) { + jsTestLog("Skipping test because SBE is not fully enabled"); MongoRunner.stopMongod(conn); return; } diff --git a/jstests/noPassthrough/sbe_plan_cache_key_reporting.js b/jstests/noPassthrough/sbe_plan_cache_key_reporting.js index f6073656e67..7fbaee10118 100644 --- a/jstests/noPassthrough/sbe_plan_cache_key_reporting.js +++ b/jstests/noPassthrough/sbe_plan_cache_key_reporting.js @@ -20,8 +20,8 @@ assert.neq(conn, null, "mongod failed to start"); const db = conn.getDB("plan_cache_key_reporting"); const coll = db.coll; -if (!checkSBEEnabled(db, ["featureFlagSbePlanCache"])) { - jsTest.log("Skipping test because SBE plan cache is not enabled."); +if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) { + jsTest.log("Skipping test because SBE is not fully enabled"); MongoRunner.stopMongod(conn); return; } diff --git a/jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js b/jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js index 6a50b4db853..591c9c525d5 100644 --- a/jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js +++ b/jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js @@ -16,8 +16,8 @@ const conn = MongoRunner.runMongod({}); assert.neq(conn, null, "mongod failed to start"); const db = conn.getDB("sbe_plan_cache_memory_debug_info"); -if (!checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) { - jsTest.log("Skipping test because SBE plan cache is not enabled."); +if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) { + jsTest.log("Skipping test because SBE is not fully enabled"); MongoRunner.stopMongod(conn); return; } diff --git a/jstests/noPassthrough/sbe_plan_cache_size_metric.js b/jstests/noPassthrough/sbe_plan_cache_size_metric.js index ebfe8d5f0bb..e41423704ed 100644 --- a/jstests/noPassthrough/sbe_plan_cache_size_metric.js +++ b/jstests/noPassthrough/sbe_plan_cache_size_metric.js @@ -21,6 +21,12 @@ const conn = MongoRunner.runMongod(); assert.neq(conn, null, "mongod failed to start"); const db = conn.getDB("sbe_plan_cache_size_metric"); +if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) { + jsTest.log("Skipping test because SBE is not fully enabled"); + MongoRunner.stopMongod(conn); + return; +} + function getCacheEntriesByQueryHashKey(coll, queryHash) { return coll.aggregate([{$planCacheStats: {}}, {$match: {queryHash}}]).toArray(); } @@ -44,64 +50,64 @@ function assertQueryInPlanCache(coll, query) { assert.eq(1, planCacheEntries.length, planCacheEntries); } -const isSbePlanCacheEnabled = - checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]); -if (isSbePlanCacheEnabled) { - const collectionName = "plan_cache_sbe"; - const coll = db[collectionName]; - coll.drop(); - - assert.commandWorked(coll.insert({a: 1, b: 1, c: 1})); - - // We need some indexes so that the multi-planner is executed. - assert.commandWorked(coll.createIndex({a: 1})); - assert.commandWorked(coll.createIndex({c: 1})); - assert.commandWorked(coll.createIndex({a: 1, b: 1})); - - const initialPlanCacheSize = getPlanCacheSize(); - // Plan cache must be empty. - assert.eq(0, coll.getPlanCache().list().length); - - const sbeQuery = {a: 1}; - const classicQuery = {a: 1, c: 1}; - - // Step 1. Insert an entry to SBE Plan Cache. - assert.eq(1, coll.find(sbeQuery).itcount()); - assertQueryInPlanCache(coll, sbeQuery); - // Plan Cache must contain exactly 1 entry. - assert.eq(1, coll.getPlanCache().list().length); - - // Assert metric is incremented for new cache entry. - const afterSbePlanCacheSize = getPlanCacheSize(); - assert.gt(afterSbePlanCacheSize, initialPlanCacheSize); - - // Step 2. Insert an entry to Classic Plan Cache. - // Force classic plan cache. - assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true})); - assert.eq(1, coll.find(classicQuery).itcount()); - assertQueryInPlanCache(coll, classicQuery); - // Plan Cache must contain exactly 2 entries. - assert.eq(2, coll.getPlanCache().list().length); - - // Assert metric is incremented for new cache entry. - const afterClassicPlanCacheSize = getPlanCacheSize(); - assert.gt(afterClassicPlanCacheSize, afterSbePlanCacheSize); - - // Step 3. Remove the entry from Classic Plan Cache. - // Clean up Classic Plan Cache. - assert.commandWorked(db.runCommand({planCacheClear: collectionName, query: classicQuery})); - // Assert metric is decremented back to values before insering classic plan cache entry. - assert.eq(afterSbePlanCacheSize, getPlanCacheSize()); - - // Step 4. Remove the entry from SBE Plan Cache. - // Move back to SBE plan cache. - assert.commandWorked( - db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false})); - // Clean up SBE Plan Cache - assert.commandWorked(db.runCommand({planCacheClear: collectionName, query: sbeQuery})); - // Assert metric is decremented back to initial value. - assert.eq(initialPlanCacheSize, getPlanCacheSize()); -} +const collectionName = "plan_cache_sbe"; +const coll = db[collectionName]; +coll.drop(); + +assert.commandWorked(coll.insert({a: 1, b: 1, c: 1})); + +// We need some indexes so that the multi-planner is executed. +assert.commandWorked(coll.createIndex({a: 1})); +assert.commandWorked(coll.createIndex({c: 1})); +assert.commandWorked(coll.createIndex({a: 1, b: 1})); + +const initialPlanCacheSize = getPlanCacheSize(); +// Plan cache must be empty. +assert.eq(0, coll.getPlanCache().list().length); + +const sbeQuery = { + a: 1 +}; +const classicQuery = { + a: 1, + c: 1 +}; + +// Step 1. Insert an entry to SBE Plan Cache. +assert.eq(1, coll.find(sbeQuery).itcount()); +assertQueryInPlanCache(coll, sbeQuery); +// Plan Cache must contain exactly 1 entry. +assert.eq(1, coll.getPlanCache().list().length); + +// Assert metric is incremented for new cache entry. +const afterSbePlanCacheSize = getPlanCacheSize(); +assert.gt(afterSbePlanCacheSize, initialPlanCacheSize); + +// Step 2. Insert an entry to Classic Plan Cache. +// Force classic plan cache. +assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true})); +assert.eq(1, coll.find(classicQuery).itcount()); +assertQueryInPlanCache(coll, classicQuery); +// Plan Cache must contain exactly 2 entries. +assert.eq(2, coll.getPlanCache().list().length); + +// Assert metric is incremented for new cache entry. +const afterClassicPlanCacheSize = getPlanCacheSize(); +assert.gt(afterClassicPlanCacheSize, afterSbePlanCacheSize); + +// Step 3. Remove the entry from Classic Plan Cache. +// Clean up Classic Plan Cache. +assert.commandWorked(db.runCommand({planCacheClear: collectionName, query: classicQuery})); +// Assert metric is decremented back to values before insering classic plan cache entry. +assert.eq(afterSbePlanCacheSize, getPlanCacheSize()); + +// Step 4. Remove the entry from SBE Plan Cache. +// Move back to SBE plan cache. +assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false})); +// Clean up SBE Plan Cache +assert.commandWorked(db.runCommand({planCacheClear: collectionName, query: sbeQuery})); +// Assert metric is decremented back to initial value. +assert.eq(initialPlanCacheSize, getPlanCacheSize()); MongoRunner.stopMongod(conn); })(); diff --git a/jstests/noPassthroughWithMongod/index_bounds_static_limit.js b/jstests/noPassthroughWithMongod/index_bounds_static_limit.js index ea0af1d1537..dc183a27346 100644 --- a/jstests/noPassthroughWithMongod/index_bounds_static_limit.js +++ b/jstests/noPassthroughWithMongod/index_bounds_static_limit.js @@ -9,10 +9,8 @@ load("jstests/libs/analyze_plan.js"); // For explain helpers. load("jstests/libs/sbe_util.js"); // For checkSBEEnabled. -const isSBEEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]); - -if (!isSBEEnabled) { - // This test is only relevant when SBE is enabled. +if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) { + jsTest.log("Skipping test because SBE is not fully enabled"); return; } @@ -54,21 +52,12 @@ function assertIndexScanPlan(explain, isGeneric) { } try { - const isSBEPlanCacheEnabled = checkSBEEnabled(db, ["featureFlagSbePlanCache"]); - // Verify that when the number of statically generated single interval bounds is less than the // static limit, the optimized plan is used. const optimized = coll.find({a: {$in: [1, 2, 3]}, b: {$in: [10, 11, 12]}, c: {$in: [42]}, d: {$lt: 3}}) .explain("executionStats"); - - if (isSBEPlanCacheEnabled) { - assertIndexScanPlan(optimized, /*isGeneric*/ false); - } else { - const optimiziedStages = optimized.executionStats.executionStages; - assert(planHasStage(db, optimiziedStages, "ixseek"), optimiziedStages); - assert(!planHasStage(db, optimiziedStages, "chkbounds"), optimiziedStages); - } + assertIndexScanPlan(optimized, /*isGeneric*/ false); // Verify that when the number of statically generated single interval bounds is greater than // the static limit, the generic plan is used. @@ -76,14 +65,7 @@ try { const generic = coll.find({a: {$in: [1, 2, 3]}, b: {$in: [10, 11, 12]}, c: {$in: [42]}, d: {$lt: 3}}) .explain("executionStats"); - - if (isSBEPlanCacheEnabled) { - assertIndexScanPlan(generic, /*isGeneric*/ true); - } else { - const genericStages = generic.executionStats.executionStages; - assert(planHasStage(db, genericStages, "chkbounds"), genericStages); - assert(planHasStage(db, genericStages, "ixseek"), genericStages); - } + assertIndexScanPlan(generic, /*isGeneric*/ true); } finally { setStaticLimit(staticLimit); } diff --git a/jstests/noPassthroughWithMongod/ne_array_indexability.js b/jstests/noPassthroughWithMongod/ne_array_indexability.js index 8c96060dbf6..f2ecb27151f 100644 --- a/jstests/noPassthroughWithMongod/ne_array_indexability.js +++ b/jstests/noPassthroughWithMongod/ne_array_indexability.js @@ -31,7 +31,7 @@ function runTest(queryToCache, queryToRunAfterCaching) { // a different planCacheKey. The SBE plan cache, on the other hand, does not auto-parameterize // $in or $eq involving a constant of type array, and therefore will consider the two queries to // have different shapes. - if (checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) { + if (checkSBEEnabled(db, ["featureFlagSbeFull"])) { assert.neq(explain.queryPlanner.queryHash, cacheEntries[0].queryHash); } else { assert.eq(explain.queryPlanner.queryHash, cacheEntries[0].queryHash); diff --git a/jstests/noPassthroughWithMongod/plan_cache_replanning.js b/jstests/noPassthroughWithMongod/plan_cache_replanning.js index 5a45226ad1f..e17a81cb660 100644 --- a/jstests/noPassthroughWithMongod/plan_cache_replanning.js +++ b/jstests/noPassthroughWithMongod/plan_cache_replanning.js @@ -10,8 +10,7 @@ load('jstests/libs/analyze_plan.js'); // For getPlanStage(). load("jstests/libs/collection_drop_recreate.js"); // For assert[Drop|Create]Collection. load("jstests/libs/sbe_util.js"); // For checkSBEEnabled. -const isSbePlanCacheEnabled = - checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]); +const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]); let coll = assertDropAndRecreateCollection(db, "plan_cache_replanning"); @@ -32,7 +31,7 @@ function assertPlanHasIxScanStage(entry, indexName, expectedQueryHash) { assert.eq(entry.queryHash, expectedQueryHash, entry); const cachedPlan = getCachedPlan(entry.cachedPlan); - if (isSbePlanCacheEnabled) { + if (isSbeEnabled) { // The $planCacheStats output for the SBE plan cache only contains an debug string // representation of the execution plan. Rather than parse this string, we just check that // the index name appears somewhere in the plan. @@ -202,7 +201,7 @@ coll = assertDropAndRecreateCollection(db, "plan_cache_replanning"); // Execution stats from when the plan cache entry was created are not exposed from the SBE plan // cache. let specialValueCacheEntryKeysExamined; - if (!isSbePlanCacheEnabled) { + if (!isSbeEnabled) { specialValueCacheEntryKeysExamined = entry.creationExecStats[0].totalKeysExamined; } @@ -224,7 +223,7 @@ coll = assertDropAndRecreateCollection(db, "plan_cache_replanning"); // The new cache entry's plan should have used fewer works (and examined fewer keys) compared // to the old cache entry's, since the query on the special value is slightly less efficient. assert.lt(entry.works, specialValueCacheEntryWorks, entry); - if (!isSbePlanCacheEnabled) { + if (!isSbeEnabled) { assert.lt(entry.creationExecStats[0].totalKeysExamined, specialValueCacheEntryKeysExamined, entry); @@ -240,7 +239,7 @@ coll = assertDropAndRecreateCollection(db, "plan_cache_replanning"); assertPlanHasIxScanStage(entry, "selectiveKey_1_tiebreak_1", queryHash); assert.eq(entry.works, entryAfterRunningSpecialQuery.works, entryAfterRunningSpecialQuery); - if (!isSbePlanCacheEnabled) { + if (!isSbeEnabled) { assert.eq(entryAfterRunningSpecialQuery.creationExecStats[0].totalKeysExamined, entry.creationExecStats[0].totalKeysExamined, entryAfterRunningSpecialQuery); diff --git a/src/mongo/db/commands/index_filter_commands.cpp b/src/mongo/db/commands/index_filter_commands.cpp index 5deb5ecd339..699b8d99c69 100644 --- a/src/mongo/db/commands/index_filter_commands.cpp +++ b/src/mongo/db/commands/index_filter_commands.cpp @@ -232,7 +232,7 @@ Status ClearFilters::runIndexFilterCommand(OperationContext* opCtx, sbe::PlanCache* planCacheSBE = nullptr; invariant(planCacheClassic); - if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { planCacheSBE = &sbe::getPlanCache(opCtx); } @@ -352,7 +352,7 @@ Status SetFilter::runIndexFilterCommand(OperationContext* opCtx, sbe::PlanCache* planCacheSBE = nullptr; invariant(planCacheClassic); - if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { planCacheSBE = &sbe::getPlanCache(opCtx); } diff --git a/src/mongo/db/commands/plan_cache_clear_command.cpp b/src/mongo/db/commands/plan_cache_clear_command.cpp index daf4bb18937..0b63f957d75 100644 --- a/src/mongo/db/commands/plan_cache_clear_command.cpp +++ b/src/mongo/db/commands/plan_cache_clear_command.cpp @@ -91,7 +91,7 @@ Status clear(OperationContext* opCtx, // Default value of planner options (0) is SBE compatible, so it does not affect result of // sbe::isQuerySbeCompatible here. const size_t plannerOptions = 0; - if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV() && + if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV() && !cq->getForceClassicEngine() && sbe::isQuerySbeCompatible(&collection, cq.get(), plannerOptions)) { cq->setSbeCompatible(true); @@ -112,7 +112,7 @@ Status clear(OperationContext* opCtx, planCache->clear(); - if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { auto version = CollectionQueryInfo::get(collection).getPlanCacheInvalidatorVersion(); sbe::clearPlanCacheEntriesWith(opCtx->getServiceContext(), collection->uuid(), version); } diff --git a/src/mongo/db/exec/plan_cache_util.cpp b/src/mongo/db/exec/plan_cache_util.cpp index 4f648536b64..1bd6f9fe75d 100644 --- a/src/mongo/db/exec/plan_cache_util.cpp +++ b/src/mongo/db/exec/plan_cache_util.cpp @@ -82,7 +82,7 @@ void updatePlanCache(OperationContext* opCtx, // TODO SERVER-67576: re-enable caching of "explode for sort" plans in the SBE cache. if (shouldCacheQuery(query) && collections.getMainCollection() && !solution.hasExplodedForSort && - feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { auto key = plan_cache_key_factory::make(query, collections); auto plan = std::make_unique<sbe::CachedSbePlan>(root.clone(), data); plan->indexFilterApplied = solution.indexFilterApplied; diff --git a/src/mongo/db/exec/plan_cache_util.h b/src/mongo/db/exec/plan_cache_util.h index 940fea8f575..b233338882f 100644 --- a/src/mongo/db/exec/plan_cache_util.h +++ b/src/mongo/db/exec/plan_cache_util.h @@ -200,7 +200,7 @@ void updatePlanCache( if (winningPlan.solution->cacheData != nullptr) { if constexpr (std::is_same_v<PlanStageType, std::unique_ptr<sbe::PlanStage>>) { - if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { tassert(6142201, "The winning CandidatePlan should contain the original plan", winningPlan.clonedPlan); @@ -224,8 +224,9 @@ void updatePlanCache( &callbacks, boost::none /* worksGrowthCoefficient */)); } else { - // TODO SERVER-64882: Fall back to use the classic plan cache. - // Remove this branch after "gFeatureFlagSbePlanCache" is removed. + // Fall back to use the classic plan cache. + // + // TODO SERVER-64882: Remove this branch after "gFeatureFlagSbeFull" is removed. cacheClassicPlan(); } } else { diff --git a/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp b/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp index 792cb69a079..4e13c886c71 100644 --- a/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp +++ b/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp @@ -554,7 +554,7 @@ std::vector<BSONObj> CommonMongodProcessInterface::getMatchingPlanCacheEntryStat auto planCacheEntries = planCache->getMatchingStats({} /* cacheKeyFilterFunc */, serializer, predicate); - if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { // Retrieve plan cache entries from the SBE plan cache. const auto cacheKeyFilter = [uuid = collection->uuid(), collVersion = collQueryInfo.getPlanCacheInvalidatorVersion()]( diff --git a/src/mongo/db/query/canonical_query.cpp b/src/mongo/db/query/canonical_query.cpp index 0df32aab8fa..674e44bfac9 100644 --- a/src/mongo/db/query/canonical_query.cpp +++ b/src/mongo/db/query/canonical_query.cpp @@ -202,7 +202,7 @@ Status CanonicalQuery::init(OperationContext* opCtx, // If caching is disabled, do not perform any autoparameterization. if (!internalQueryDisablePlanCache.load() && - feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { const bool hasNoTextNodes = !QueryPlannerCommon::hasNode(_root.get(), MatchExpression::TEXT); if (hasNoTextNodes) { @@ -541,8 +541,8 @@ std::string CanonicalQuery::toStringShort() const { } CanonicalQuery::QueryShapeString CanonicalQuery::encodeKey() const { - return (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV() && - !_forceClassicEngine && _sbeCompatible) + return (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV() && !_forceClassicEngine && + _sbeCompatible) ? canonical_query_encoder::encodeSBE(*this) : canonical_query_encoder::encode(*this); } diff --git a/src/mongo/db/query/canonical_query_encoder.cpp b/src/mongo/db/query/canonical_query_encoder.cpp index c24be53a1b8..1ab4e5c89cf 100644 --- a/src/mongo/db/query/canonical_query_encoder.cpp +++ b/src/mongo/db/query/canonical_query_encoder.cpp @@ -1095,8 +1095,8 @@ void encodeKeyForAutoParameterizedMatchSBE(MatchExpression* matchExpr, BufBuilde std::string encodeSBE(const CanonicalQuery& cq) { tassert(6512900, - "using the SBE plan cache key encoding requires the SBE plan cache to be enabled", - feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()); + "using the SBE plan cache key encoding requires SBE to be fully enabled", + feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()); tassert(6142104, "attempting to encode SBE plan cache key for SBE-incompatible query", cq.isSbeCompatible()); diff --git a/src/mongo/db/query/canonical_query_encoder_test.cpp b/src/mongo/db/query/canonical_query_encoder_test.cpp index eb0719db9a5..359a50ab625 100644 --- a/src/mongo/db/query/canonical_query_encoder_test.cpp +++ b/src/mongo/db/query/canonical_query_encoder_test.cpp @@ -418,7 +418,7 @@ TEST(CanonicalQueryEncoderTest, ComputeKeySBE) { // SBE must be enabled in order to generate SBE plan cache keys. RAIIServerParameterControllerForTest controllerSBE("internalQueryForceClassicEngine", false); - RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbePlanCache", true); + RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbeFull", true); testComputeSBEKey("{}", "{}", "{}", "YW4ABQAAAAAAAAAAAAAAAG5ubm4FAAAAAGZe"); testComputeSBEKey("{$or: [{a: 1}, {b: 2}]}", @@ -536,7 +536,7 @@ TEST(CanonicalQueryEncoderTest, ComputeKeySBEWithPipeline) { // SBE must be enabled in order to generate SBE plan cache keys. RAIIServerParameterControllerForTest controllerSBE("internalQueryForceClassicEngine", false); - RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbePlanCache", true); + RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbeFull", true); auto getLookupBson = [](StringData localField, StringData foreignField, StringData asField) { return BSON("$lookup" << BSON("from" << foreignNss.coll() << "localField" << localField @@ -596,7 +596,7 @@ TEST(CanonicalQueryEncoderTest, ComputeKeySBEWithPipeline) { TEST(CanonicalQueryEncoderTest, ComputeKeySBEWithReadConcern) { // SBE must be enabled in order to generate SBE plan cache keys. RAIIServerParameterControllerForTest controllerSBE("internalQueryForceClassicEngine", false); - RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbePlanCache", true); + RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbeFull", true); const auto sbeEncodingWithoutReadConcernAvailable = "ZXEAYT8AAAAABQAAAAB+YWEAAAAAAAAAAG5ubm4FAAAAAGZe"; diff --git a/src/mongo/db/query/canonical_query_test.cpp b/src/mongo/db/query/canonical_query_test.cpp index dbb2fd929da..a15a3b918b0 100644 --- a/src/mongo/db/query/canonical_query_test.cpp +++ b/src/mongo/db/query/canonical_query_test.cpp @@ -456,7 +456,7 @@ TEST(CanonicalQueryTest, InvalidSortOrdersFailToCanonicalize) { } TEST(CanonicalQueryTest, DoNotParameterizeTextExpressions) { - RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbePlanCache", true); + RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbeFull", true); auto cq = canonicalize("{$text: {$search: \"Hello World!\"}}", MatchExpressionParser::kDefaultSpecialFeatures | MatchExpressionParser::kText); @@ -464,7 +464,7 @@ TEST(CanonicalQueryTest, DoNotParameterizeTextExpressions) { } TEST(CanonicalQueryTest, DoParameterizeRegularExpressions) { - RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbePlanCache", true); + RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbeFull", true); auto cq = canonicalize("{a: 1, b: {$lt: 5}}"); ASSERT_TRUE(cq->isParameterized()); } diff --git a/src/mongo/db/query/explain.cpp b/src/mongo/db/query/explain.cpp index 8c7796209cb..cb6bc97957a 100644 --- a/src/mongo/db/query/explain.cpp +++ b/src/mongo/db/query/explain.cpp @@ -97,7 +97,7 @@ void generatePlannerInfo(PlanExecutor* exec, const QuerySettings* querySettings = QuerySettingsDecoration::get(mainCollection->getSharedDecorations()); if (exec->getCanonicalQuery()->isSbeCompatible() && - feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV() && + feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV() && !exec->getCanonicalQuery()->getForceClassicEngine()) { const auto planCacheKeyInfo = plan_cache_key_factory::make(*exec->getCanonicalQuery(), collections); diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp index d7dfc3ae66d..ae3c0d20c5f 100644 --- a/src/mongo/db/query/get_executor.cpp +++ b/src/mongo/db/query/get_executor.cpp @@ -1021,7 +1021,7 @@ protected: // go through the normal planning and plan compilation process, resulting in an // auto-parameterized SBE plan cache entry. Subsequent idhack queries can simply re-use this // cache entry, and the hot path for recovering cached plans is already carefully optimized. - if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { return nullptr; } @@ -1099,7 +1099,7 @@ protected: std::unique_ptr<SlotBasedPrepareExecutionResult> buildCachedPlan( const sbe::PlanCacheKey& planCacheKey) final { if (shouldCacheQuery(*_cq)) { - if (!feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + if (!feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { // If the feature flag is off, we first try to build an "id hack" plan because the // id hack plans are not cached in the classic cache. We then fall back to use the // classic plan cache. @@ -1138,8 +1138,11 @@ protected: return buildIdHackPlan(); } - // A temporary function to allow recovering SBE plans from the classic plan cache. - // TODO SERVER-61314: Remove this function when "featureFlagSbePlanCache" is removed. + // A temporary function to allow recovering SBE plans from the classic plan cache. When the + // feature flag for "SBE full" is disabled, we are still able to use the classic plan cache for + // queries that execute in SBE. + // + // TODO SERVER-64882: Remove this function when "featureFlagSbeFull" is removed. std::unique_ptr<SlotBasedPrepareExecutionResult> buildCachedPlanFromClassicCache() { const auto& mainColl = getMainCollection(); auto planCacheKey = plan_cache_key_factory::make<PlanCacheKey>(*_cq, mainColl); diff --git a/src/mongo/db/query/query_feature_flags.idl b/src/mongo/db/query/query_feature_flags.idl index df2bb74890b..e714b0f7e54 100644 --- a/src/mongo/db/query/query_feature_flags.idl +++ b/src/mongo/db/query/query_feature_flags.idl @@ -54,11 +54,6 @@ feature_flags: default: true version: 6.0 - featureFlagSbePlanCache: - description: "Feature flag for enabling use of the SBE plan cache" - cpp_varname: gFeatureFlagSbePlanCache - default: false - featureFlagChangeStreamsFurtherEnrichedEvents: description: "Feature flag for enabling the reshardCollection and refineCollectionShardKey events, as well as enhancements to the updateDescription field for update events" cpp_varname: gFeatureFlagChangeStreamsFurtherEnrichedEvents @@ -99,7 +94,8 @@ feature_flags: default: false featureFlagSbeFull: - description: "Feature flag to enable using SBE for a larger number of queries" + description: "Feature flag for enabling full SBE support. Enables SBE for a much larger class + of queries, including NLJ $lookup plans. Also enables the SBE plan cache." cpp_varname: gFeatureFlagSbeFull default: false diff --git a/src/mongo/db/query/sbe_cached_solution_planner.cpp b/src/mongo/db/query/sbe_cached_solution_planner.cpp index d6b57f629ce..416610f401f 100644 --- a/src/mongo/db/query/sbe_cached_solution_planner.cpp +++ b/src/mongo/db/query/sbe_cached_solution_planner.cpp @@ -58,8 +58,11 @@ CandidatePlans CachedSolutionPlanner::plan( // only track the number of reads from the local side. Thus, we can use the number of reads the // plan was cached with during multiplanning even though multiplanning ran trials of // pre-extended plans. - if (!_cq.pipeline().empty() && - !feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + // + // When "featureFlagSbeFull" is enabled we use the SBE plan cache. The SBE plan cache stores the + // entire plan, including the part for any agg pipeline pushed down to SBE. Therefore, this + // logic is only necessary when "featureFlagSbeFull" is disabled. + if (!_cq.pipeline().empty() && !feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { _yieldPolicy->clearRegisteredPlans(); auto secondaryCollectionsInfo = fillOutSecondaryCollectionsInformation(_opCtx, _collections, &_cq); @@ -185,7 +188,7 @@ CandidatePlans CachedSolutionPlanner::replan(bool shouldCache, std::string reaso // be simplified to only deactivate the entry in the SBE plan cache. auto cache = CollectionQueryInfo::get(mainColl).getPlanCache(); cache->deactivate(plan_cache_key_factory::make<mongo::PlanCacheKey>(_cq, mainColl)); - if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { auto&& sbePlanCache = sbe::getPlanCache(_opCtx); sbePlanCache.deactivate(plan_cache_key_factory::make(_cq, _collections)); } diff --git a/src/mongo/db/query/sbe_plan_cache.cpp b/src/mongo/db/query/sbe_plan_cache.cpp index bbd6db6418a..14d92b0d608 100644 --- a/src/mongo/db/query/sbe_plan_cache.cpp +++ b/src/mongo/db/query/sbe_plan_cache.cpp @@ -105,7 +105,7 @@ class PlanCacheOnParamChangeUpdaterImpl final : public plan_cache_util::OnParamC public: void updateCacheSize(ServiceContext* serviceCtx, plan_cache_util::PlanCacheSizeParameter parameter) final { - if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { auto size = getPlanCacheSizeInBytes(parameter); auto& globalPlanCache = sbePlanCacheDecoration(serviceCtx); globalPlanCache->reset(size); @@ -113,7 +113,7 @@ public: } void clearCache(ServiceContext* serviceCtx) final { - if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { auto& globalPlanCache = sbePlanCacheDecoration(serviceCtx); globalPlanCache->clear(); } @@ -125,7 +125,7 @@ ServiceContext::ConstructorActionRegisterer planCacheRegisterer{ plan_cache_util::sbePlanCacheOnParamChangeUpdater(serviceCtx) = std::make_unique<PlanCacheOnParamChangeUpdaterImpl>(); - if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { auto status = plan_cache_util::PlanCacheSizeParameter::parse(planCacheSize.get()); uassertStatusOK(status); @@ -139,15 +139,15 @@ ServiceContext::ConstructorActionRegisterer planCacheRegisterer{ sbe::PlanCache& getPlanCache(ServiceContext* serviceCtx) { uassert(5933402, - "Cannot getPlanCache() if gFeatureFlagSbePlanCache is disabled", - feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()); + "Cannot getPlanCache() if 'featureFlagSbeFull' is disabled", + feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()); return *sbePlanCacheDecoration(serviceCtx); } sbe::PlanCache& getPlanCache(OperationContext* opCtx) { uassert(5933401, - "Cannot getPlanCache() if gFeatureFlagSbePlanCache is disabled", - feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()); + "Cannot getPlanCache() if 'featureFlagSbeFull' is disabled", + feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()); tassert(5933400, "Cannot get the global SBE plan cache by a nullptr", opCtx); return getPlanCache(opCtx->getServiceContext()); } @@ -155,7 +155,7 @@ sbe::PlanCache& getPlanCache(OperationContext* opCtx) { void clearPlanCacheEntriesWith(ServiceContext* serviceCtx, UUID collectionUuid, size_t collectionVersion) { - if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { auto removed = sbe::getPlanCache(serviceCtx) .removeIf([&collectionUuid, collectionVersion](const PlanCacheKey& key, diff --git a/src/mongo/db/query/sbe_stage_builder_filter.cpp b/src/mongo/db/query/sbe_stage_builder_filter.cpp index 50a58292484..adc537049e5 100644 --- a/src/mongo/db/query/sbe_stage_builder_filter.cpp +++ b/src/mongo/db/query/sbe_stage_builder_filter.cpp @@ -2065,11 +2065,12 @@ std::pair<boost::optional<sbe::value::SlotId>, EvalStage> generateFilter( return {boost::none, std::move(stage)}; } - // We only use the classic matcher path (aka "franken matcher") when the plan cache is off, - // because embedding the classic matcher into the query execution tree is not compatible with - // auto parameterization. All of the constants used in the filter are in the MatchExpression - // itself, rather than in slots. - if (!feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + // We only use the classic matcher path (aka "franken matcher") when the SBE is not fully + // enabled. Fully enabling SBE turns on the SBE plan cache, and embedding the classic matcher + // into the query execution tree is not compatible with the plan cache's use of + // auto-parameterization. This is because when embedding the classic matcher all of the + // constants used in the filter are in the MatchExpression itself rather than in slots. + if (!feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { tassert(6681403, "trackIndex=true not supported for classic matcher in SBE", !trackIndex); auto expr = makeFunction("applyClassicMatcher", @@ -2106,11 +2107,12 @@ EvalStage generateIndexFilter(StageBuilderState& state, return stage; } - // We only use the classic matcher path (aka "franken matcher") when the plan cache is off, - // because embedding the classic matcher into the query execution tree is not compatible with - // auto parameterization. All of the constants used in the filter are in the MatchExpression - // itself, rather than in slots. - if (!feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) { + // We only use the classic matcher path (aka "franken matcher") when SBE is not fully enabled. + // Fully enabling SBE turns on the SBE plan cache, and embedding the classic matcher into the + // query execution tree is not compatible with the plan cache's use of auto-parameterization. + // This is because when embedding the classic mathcer all of the constants used in the filter + // are in the MatchExpression itself rather than in slots. + if (!feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { BSONObjBuilder keyPatternBuilder; for (auto& field : keyFields) { keyPatternBuilder.append(field, 1); |