summaryrefslogtreecommitdiff
path: root/jstests
diff options
context:
space:
mode:
authorMihai Andrei <mihai.andrei@mongodb.com>2023-02-07 00:58:25 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-02-07 02:32:02 +0000
commitb185d04364c298e701943a1e800c4036ce8df6e7 (patch)
tree6a91575c0096863e38b1b0fd12d1bfd90d55ac7f /jstests
parent967a6745ba487edaff558e36fdc572c6ca066fea (diff)
downloadmongo-b185d04364c298e701943a1e800c4036ce8df6e7.tar.gz
SERVER-71798 Expand the set of queries eligible for SBE in the 6.3 release
Diffstat (limited to 'jstests')
-rw-r--r--jstests/aggregation/add_with_date.js2
-rw-r--r--jstests/aggregation/explain_limit.js2
-rw-r--r--jstests/aggregation/optimize_away_pipeline.js89
-rw-r--r--jstests/core/columnstore/column_scan_skip_row_store_projection.js4
-rw-r--r--jstests/core/columnstore/column_store_index_compression.js5
-rw-r--r--jstests/core/columnstore/columnstore_eligibility.js33
-rw-r--r--jstests/core/computed_projections.js9
-rw-r--r--jstests/core/index/hidden_index.js3
-rw-r--r--jstests/core/index/index_filter_commands.js5
-rw-r--r--jstests/core/index/index_filter_commands_invalidate_plan_cache_entries.js2
-rw-r--r--jstests/core/index/indexj.js38
-rw-r--r--jstests/core/index/wildcard/wildcard_index_cached_plans.js2
-rw-r--r--jstests/core/query/explode_for_sort_plan_cache.js4
-rw-r--r--jstests/core/query/expr/expr_index_use.js6
-rw-r--r--jstests/core/query/idhack.js3
-rw-r--r--jstests/core/query/null_query_semantics.js4
-rw-r--r--jstests/core/query/or/or_to_in.js6
-rw-r--r--jstests/core/query/plan_cache/cached_plan_trial_does_not_discard_work.js5
-rw-r--r--jstests/core/query/plan_cache/collation_plan_cache.js3
-rw-r--r--jstests/core/query/plan_cache/plan_cache_clear.js4
-rw-r--r--jstests/core/query/plan_cache/plan_cache_list_plans.js2
-rw-r--r--jstests/core/query/plan_cache/plan_cache_list_shapes.js4
-rw-r--r--jstests/core/query/plan_cache/plan_cache_sbe.js6
-rw-r--r--jstests/core/query/plan_cache/plan_cache_shell_helpers.js2
-rw-r--r--jstests/core/query/project/projection_expr_mod.js9
-rw-r--r--jstests/core/query/project/projection_semantics.js5
-rw-r--r--jstests/core/query/query_hash_stability.js2
-rw-r--r--jstests/core/sbe/from_plan_cache_flag.js11
-rw-r--r--jstests/core/sbe/plan_cache_sbe_with_or_queries.js5
-rw-r--r--jstests/core/sbe/sbe_explain_rejected_plans.js9
-rw-r--r--jstests/core/sbe/sbe_ixscan_explain.js7
-rw-r--r--jstests/core/sbe_plan_cache_autoparameterize_collscan.js65
-rw-r--r--jstests/cqf/analyze/scalar_histograms.js7
-rw-r--r--jstests/libs/parallelTester.js9
-rw-r--r--jstests/libs/sbe_explain_helpers.js18
-rw-r--r--jstests/libs/sbe_util.js86
-rw-r--r--jstests/noPassthrough/columnstore_index_rowstore_settings.js5
-rw-r--r--jstests/noPassthrough/currentop_query.js2
-rw-r--r--jstests/noPassthrough/external_sort_find.js2
-rw-r--r--jstests/noPassthrough/log_and_profile_query_hash.js2
-rw-r--r--jstests/noPassthrough/lookup_metrics.js3
-rw-r--r--jstests/noPassthrough/lookup_pushdown.js174
-rw-r--r--jstests/noPassthrough/plan_cache_group_lookup.js32
-rw-r--r--jstests/noPassthrough/plan_cache_index_create.js4
-rw-r--r--jstests/noPassthrough/plan_cache_list_failed_plans.js4
-rw-r--r--jstests/noPassthrough/plan_cache_memory_debug_info.js4
-rw-r--r--jstests/noPassthrough/plan_cache_replan_group_lookup.js40
-rw-r--r--jstests/noPassthrough/plan_cache_replan_sort.js2
-rw-r--r--jstests/noPassthrough/plan_cache_stats_agg_source.js6
-rw-r--r--jstests/noPassthrough/query_engine_stats.js4
-rw-r--r--jstests/noPassthrough/restart_index_build_if_resume_fails.js6
-rw-r--r--jstests/noPassthrough/restart_index_build_if_resume_interrupted_by_shutdown.js3
-rw-r--r--jstests/noPassthrough/resumable_index_build_bulk_load_phase.js5
-rw-r--r--jstests/noPassthrough/resumable_index_build_bulk_load_phase_large.js5
-rw-r--r--jstests/noPassthrough/resumable_index_build_clearing_tmp_directory_on_restart.js3
-rw-r--r--jstests/noPassthrough/resumable_index_build_collection_scan_phase.js5
-rw-r--r--jstests/noPassthrough/resumable_index_build_collection_scan_phase_large.js3
-rw-r--r--jstests/noPassthrough/resumable_index_build_drain_writes_phase_primary.js4
-rw-r--r--jstests/noPassthrough/resumable_index_build_drain_writes_phase_secondary.js4
-rw-r--r--jstests/noPassthrough/resumable_index_build_initialized.js5
-rw-r--r--jstests/noPassthrough/resumable_index_build_mixed_phases.js5
-rw-r--r--jstests/noPassthrough/sbe_multiplanner_trial_termination.js4
-rw-r--r--jstests/noPassthrough/sbe_plan_cache_clear_on_param_change.js7
-rw-r--r--jstests/noPassthrough/sbe_plan_cache_key_reporting.js4
-rw-r--r--jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js4
-rw-r--r--jstests/noPassthrough/sbe_plan_cache_size_metric.js4
-rw-r--r--jstests/noPassthrough/server_status_multiplanner.js4
-rw-r--r--jstests/noPassthroughWithMongod/columnstore_planning_heuristics.js5
-rw-r--r--jstests/noPassthroughWithMongod/group_pushdown.js56
-rw-r--r--jstests/noPassthroughWithMongod/index_bounds_static_limit.js4
-rw-r--r--jstests/noPassthroughWithMongod/ne_array_indexability.js2
-rw-r--r--jstests/noPassthroughWithMongod/plan_cache_replanning.js2
-rw-r--r--jstests/noPassthroughWithMongod/sbe_query_eligibility.js192
-rw-r--r--jstests/sharding/invalidate_plan_cache_entries_when_collection_generation_changes.js7
-rw-r--r--jstests/sharding/sbe_plan_cache_does_not_block_range_deletion.js12
75 files changed, 567 insertions, 548 deletions
diff --git a/jstests/aggregation/add_with_date.js b/jstests/aggregation/add_with_date.js
index b80c304e42c..4d76a6908d7 100644
--- a/jstests/aggregation/add_with_date.js
+++ b/jstests/aggregation/add_with_date.js
@@ -28,8 +28,6 @@ assert.commandWorked(coll.insert({
nanDecimal: NumberDecimal("NaN"),
}));
-const isSBEEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
-
// Adding a Decimal128 value to a date literal.
assert.eq(ISODate("2019-01-30T07:30:10.957Z"),
getResultOfExpression({$add: ["$decimalVal", ISODate("2019-01-30T07:30:10.137Z")]}));
diff --git a/jstests/aggregation/explain_limit.js b/jstests/aggregation/explain_limit.js
index 7ce18401062..5e017f9b74e 100644
--- a/jstests/aggregation/explain_limit.js
+++ b/jstests/aggregation/explain_limit.js
@@ -18,7 +18,7 @@ let coll = db.explain_limit;
const kCollSize = 105;
const kLimit = 10;
-const isSBEEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
+const isSBEEnabled = checkSBEEnabled(db);
// Return whether or explain() was successful and contained the appropriate fields given the
// requested verbosity. Checks that the number of documents examined and returned are correct given
diff --git a/jstests/aggregation/optimize_away_pipeline.js b/jstests/aggregation/optimize_away_pipeline.js
index 065691a0663..453ee78db40 100644
--- a/jstests/aggregation/optimize_away_pipeline.js
+++ b/jstests/aggregation/optimize_away_pipeline.js
@@ -639,33 +639,66 @@ function assertProjectionIsNotRemoved(pipeline, projectionType = "PROJECTION_SIM
assertProjectionCanBeRemovedBeforeGroup(
[{$project: {a: 1, b: 1}}, {$group: {_id: "$a", s: {$sum: "$b"}}}]);
-assertProjectionCanBeRemovedBeforeGroup(
- [{$project: {'a.b': 1, 'b.c': 1}}, {$group: {_id: "$a.b", s: {$sum: "$b.c"}}}],
- "PROJECTION_DEFAULT");
-
-// Test that an inclusion projection is NOT optimized away if it is NOT redundant. This one fails to
-// include a dependency of the $group and so will have an impact on the query results.
+// Test that an inclusion projection is NOT optimized away if it is NOT redundant. This one
+// fails to include a dependency of the $group and so will have an impact on the query results.
assertProjectionIsNotRemoved([{$project: {a: 1}}, {$group: {_id: "$a", s: {$sum: "$b"}}}]);
-// Test similar cases with dotted paths.
-assertProjectionIsNotRemoved([{$project: {'a.b': 1}}, {$group: {_id: "$a.b", s: {$sum: "$b"}}}],
- "PROJECTION_DEFAULT");
-assertProjectionIsNotRemoved([{$project: {'a.b': 1}}, {$group: {_id: "$a.b", s: {$sum: "$a.c"}}}],
- "PROJECTION_DEFAULT");
// TODO SERVER-67323 This one could be removed, but is left for future work.
assertProjectionIsNotRemoved(
[{$project: {a: 1, b: 1}}, {$group: {_id: "$a.b", s: {$sum: "$b.c"}}}]);
-// Spinoff on the one above: Without supporting this kind of prefixing analysis, we can confuse
-// ourselves with our dependency analysis. If the $group depends on both "path" and "path.subpath"
-// then it will generate a $project on only "path" to express its dependency set. We then fail to
-// optimize that out.
+// If the $group depends on both "path" and "path.subpath" then it will generate a $project on only
+// "path" to express its dependency set. We then fail to optimize that out. As a future improvement,
+// we could improve the optimizer to ensure that a projection stage is not present in the resulting
+// plan.
pipeline = [{$group: {_id: "$a.b", s: {$first: "$a"}}}];
// TODO SERVER-XYZ Assert this can be optimized out.
// assertProjectionCanBeRemovedBeforeGroup(pipeline, "PROJECTION_DEFAULT");
// assertProjectionCanBeRemovedBeforeGroup(pipeline, "PROJECTION_SIMPLE");
assertProjectionIsNotRemoved(pipeline);
+// Though $group is generally eligible for pushdown into SBE, such a pushdown may be inhibited by
+// dotted as well as computed projections. As such we only run the test cases below if SBE is fully
+// enabled.
+const sbeFull = checkSBEEnabled(db, ["featureFlagSbeFull"], true /* checkAllNodes */);
+if (sbeFull) {
+ assertProjectionCanBeRemovedBeforeGroup(
+ [{$project: {'a.b': 1, 'b.c': 1}}, {$group: {_id: "$a.b", s: {$sum: "$b.c"}}}],
+ "PROJECTION_DEFAULT");
+
+ // Test that a computed projection at the front of the pipeline is pushed down, even if there's
+ // no finite dependency set.
+ pipeline = [{$project: {x: {$add: ["$a", 1]}}}];
+ assertPipelineDoesNotUseAggregation(
+ {pipeline: pipeline, expectedStages: ["COLLSCAN", "PROJECTION_DEFAULT"]});
+
+ // The projections below are not removed because they fail to include the $group's dependencies.
+ assertProjectionIsNotRemoved([{$project: {'a.b': 1}}, {$group: {_id: "$a.b", s: {$sum: "$b"}}}],
+ "PROJECTION_DEFAULT");
+ assertProjectionIsNotRemoved(
+ [{$project: {'a.b': 1}}, {$group: {_id: "$a.b", s: {$sum: "$a.c"}}}], "PROJECTION_DEFAULT");
+
+ pipeline = [{$project: {a: {$add: ["$a", 1]}}}, {$group: {_id: "$a", s: {$sum: "$b"}}}];
+ assertPipelineIfGroupPushdown(
+ // Test that a computed projection at the front of the pipeline is pushed down when there's
+ // a finite dependency set. Additionally, the group pushdown shouldn't erase the computed
+ // projection.
+ function() {
+ explain = coll.explain().aggregate(pipeline);
+ assertPipelineDoesNotUseAggregation(
+ {pipeline: pipeline, expectedStages: ["COLLSCAN", "PROJECTION_DEFAULT", "GROUP"]});
+ },
+ // Test that a computed projection at the front of the pipeline is pushed down when there's
+ // a finite dependency set.
+ function() {
+ explain = coll.explain().aggregate(pipeline);
+ assertPipelineUsesAggregation({
+ pipeline: pipeline,
+ expectedStages: ["COLLSCAN", "PROJECTION_DEFAULT", "$group"],
+ });
+ });
+}
+
// We generate a projection stage from dependency analysis, even if the pipeline begins with an
// exclusion projection.
pipeline = [{$project: {c: 0}}, {$group: {_id: "$a", b: {$sum: "$b"}}}];
@@ -696,32 +729,6 @@ pipeline = [{$project: {x: 0}}];
assertPipelineDoesNotUseAggregation(
{pipeline: pipeline, expectedStages: ["PROJECTION_SIMPLE", "COLLSCAN"]});
-// Test that a computed projection at the front of the pipeline is pushed down, even if there's no
-// finite dependency set.
-pipeline = [{$project: {x: {$add: ["$a", 1]}}}];
-assertPipelineDoesNotUseAggregation(
- {pipeline: pipeline, expectedStages: ["COLLSCAN", "PROJECTION_DEFAULT"]});
-
-pipeline = [{$project: {a: {$add: ["$a", 1]}}}, {$group: {_id: "$a", s: {$sum: "$b"}}}];
-assertPipelineIfGroupPushdown(
- // Test that a computed projection at the front of the pipeline is pushed down when there's a
- // finite dependency set. Additionally, the group pushdown shouldn't erase the computed
- // projection.
- function() {
- explain = coll.explain().aggregate(pipeline);
- assertPipelineDoesNotUseAggregation(
- {pipeline: pipeline, expectedStages: ["COLLSCAN", "PROJECTION_DEFAULT", "GROUP"]});
- },
- // Test that a computed projection at the front of the pipeline is pushed down when there's a
- // finite dependency set.
- function() {
- explain = coll.explain().aggregate(pipeline);
- assertPipelineUsesAggregation({
- pipeline: pipeline,
- expectedStages: ["COLLSCAN", "PROJECTION_DEFAULT", "$group"],
- });
- });
-
// getMore cases.
// Test getMore on a collection with an optimized away pipeline.
diff --git a/jstests/core/columnstore/column_scan_skip_row_store_projection.js b/jstests/core/columnstore/column_scan_skip_row_store_projection.js
index b69e515d7ef..8124af3e446 100644
--- a/jstests/core/columnstore/column_scan_skip_row_store_projection.js
+++ b/jstests/core/columnstore/column_scan_skip_row_store_projection.js
@@ -30,8 +30,8 @@ load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
load("jstests/libs/clustered_collections/clustered_collection_util.js");
load("jstests/libs/columnstore_util.js"); // For setUpServerForColumnStoreIndexTest.
-const columnstoreEnabled = checkSBEEnabled(
- db, ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"], true /* checkAllNodes */);
+const columnstoreEnabled =
+ checkSBEEnabled(db, ["featureFlagColumnstoreIndexes"], true /* checkAllNodes */);
if (!columnstoreEnabled) {
jsTestLog("Skipping columnstore index test since the feature flag is not enabled.");
return;
diff --git a/jstests/core/columnstore/column_store_index_compression.js b/jstests/core/columnstore/column_store_index_compression.js
index c66c12abef0..52b74a23a10 100644
--- a/jstests/core/columnstore/column_store_index_compression.js
+++ b/jstests/core/columnstore/column_store_index_compression.js
@@ -8,7 +8,6 @@
* # Column store indexes are still under a feature flag and require full SBE.
* uses_column_store_index,
* featureFlagColumnstoreIndexes,
- * featureFlagSbeFull,
*
* # In passthrough suites, this test makes direct connections to mongod instances that compose
* # the passthrough fixture in order to perform additional validation. Tenant migration,
@@ -28,8 +27,8 @@ load("jstests/libs/fixture_helpers.js"); // For isMongos
load("jstests/libs/index_catalog_helpers.js"); // For IndexCatalogHelpers
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-const columnstoreEnabled = checkSBEEnabled(
- db, ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"], true /* checkAllNodes */);
+const columnstoreEnabled =
+ checkSBEEnabled(db, ["featureFlagColumnstoreIndexes"], true /* checkAllNodes */);
if (!columnstoreEnabled) {
jsTestLog("Skipping columnstore index test since the feature flag is not enabled.");
return;
diff --git a/jstests/core/columnstore/columnstore_eligibility.js b/jstests/core/columnstore/columnstore_eligibility.js
index c65f4c50eff..791d9929608 100644
--- a/jstests/core/columnstore/columnstore_eligibility.js
+++ b/jstests/core/columnstore/columnstore_eligibility.js
@@ -25,8 +25,6 @@ if (!setUpServerForColumnStoreIndexTest(db)) {
return;
}
-const sbeFull = checkSBEEnabled(db, ["featureFlagSbeFull"]);
-
const coll = db.columnstore_eligibility;
coll.drop();
@@ -66,12 +64,35 @@ assert(planHasStage(db, explain, "COLUMN_SCAN"), explain);
// will be applied after assembling an intermediate result containing both "a" and "b".
explain = coll.find({$or: [{a: 2}, {b: 2}]}, {_id: 0, a: 1}).explain();
-// For top-level $or queries, COLUMN_SCAN is only used when sbeFull is also enabled due to a
-// quirk in the engine selection logic. TODO: SERVER-XYZ.
+// COLUMN_SCAN is used for top-level $or queries.
+assert(planHasStage(db, explain, "COLUMN_SCAN"), explain);
+
+// COLUMN_SCAN is only used for for certain top-level $or queries when sbeFull is also enabled due
+// to a quirk in the engine selection logic.
+const sbeFull = checkSBEEnabled(db, ["featureFlagSbeFull"]);
+explain = coll.explain().aggregate([
+ {$match: {$or: [{a: {$gt: 0}}, {b: {$gt: 0}}]}},
+ {$project: {_id: 0, computedField: {$add: ["$a", "$b"]}}},
+]);
+let planHasColumnScan = planHasStage(db, explain, "COLUMN_SCAN");
+
if (sbeFull) {
- assert(planHasStage(db, explain, "COLUMN_SCAN"), explain);
+ assert(planHasColumnScan, explain);
+} else {
+ assert(!planHasColumnScan, explain);
+}
+
+explain = coll.explain().aggregate([
+ {$match: {$or: [{a: {$gt: 0}}, {b: {$gt: 0}}]}},
+ {$project: {_id: 0, computedField: {$add: ["$a", "$b"]}}},
+ {$group: {_id: "$computedField"}}
+]);
+planHasColumnScan = planHasStage(db, explain, "COLUMN_SCAN");
+
+if (sbeFull) {
+ assert(planHasColumnScan, explain);
} else {
- assert(planHasStage(db, explain, "COLLSCAN"), explain);
+ assert(!planHasColumnScan, explain);
}
// Simplest case: just scan "a" column.
diff --git a/jstests/core/computed_projections.js b/jstests/core/computed_projections.js
index 06ea2476bd9..fd432771f44 100644
--- a/jstests/core/computed_projections.js
+++ b/jstests/core/computed_projections.js
@@ -2,14 +2,7 @@
"use strict";
load("jstests/aggregation/extras/utils.js"); // For arrayEq and orderedArrayEq.
-load("jstests/libs/sbe_util.js"); // For checkSBEEnabledOnSomeNode.
-
-const isSBEEnabled = checkSBEEnabledOnSomeNode(db);
-if (isSBEEnabled) {
- // Override error-code-checking APIs. We only load this when SBE is explicitly enabled, because
- // it causes failures in the parallel suites.
- load("jstests/libs/sbe_assert_error_override.js");
-}
+load("jstests/libs/sbe_assert_error_override.js");
// It is safe for other tests to run while this failpoint is active, so long as those tests do not
// use documents containing a field with "POISON" as their name. Note that this command can fail.
diff --git a/jstests/core/index/hidden_index.js b/jstests/core/index/hidden_index.js
index e1edef07fe7..572d9016ae0 100644
--- a/jstests/core/index/hidden_index.js
+++ b/jstests/core/index/hidden_index.js
@@ -25,8 +25,7 @@ load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
load("jstests/libs/columnstore_util.js"); // For setUpServerForColumnStoreIndexTest.
const columnstoreEnabled =
- checkSBEEnabled(
- db, ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"], true /* checkAllNodes */) &&
+ checkSBEEnabled(db, ["featureFlagColumnstoreIndexes"], true /* checkAllNodes */) &&
setUpServerForColumnStoreIndexTest(db);
const collName = "hidden_index";
diff --git a/jstests/core/index/index_filter_commands.js b/jstests/core/index/index_filter_commands.js
index 1272cb2fd19..429a79adea8 100644
--- a/jstests/core/index/index_filter_commands.js
+++ b/jstests/core/index/index_filter_commands.js
@@ -33,7 +33,8 @@
* assumes_read_preference_unchanged,
* assumes_unsharded_collection,
* does_not_support_stepdowns,
- * requires_fcv_60
+ * # The SBE plan cache was first enabled in 6.3.
+ * requires_fcv_63,
* ]
*/
@@ -344,7 +345,7 @@ assert.commandFailed(
filters = getFilters();
assert.eq(0, filters.length, tojson(filters));
-if (checkSBEEnabled(db, ["featureFlagSbeFull"], true /* checkAllNodes */)) {
+if (checkSBEEnabled(db)) {
//
// Test that planCacheSetFilter doesn't apply to the inner side of a $lookup.
//
diff --git a/jstests/core/index/index_filter_commands_invalidate_plan_cache_entries.js b/jstests/core/index/index_filter_commands_invalidate_plan_cache_entries.js
index 059241284ac..bc2dc74c0e1 100644
--- a/jstests/core/index/index_filter_commands_invalidate_plan_cache_entries.js
+++ b/jstests/core/index/index_filter_commands_invalidate_plan_cache_entries.js
@@ -27,7 +27,7 @@ load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
// 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 isSbeEnabled = checkSBEEnabled(db) ? 1 : 0;
const collName = "index_filter_commands_invalidate_plan_cache_entries";
const coll = db[collName];
diff --git a/jstests/core/index/indexj.js b/jstests/core/index/indexj.js
index 3023b661e59..93034fec923 100644
--- a/jstests/core/index/indexj.js
+++ b/jstests/core/index/indexj.js
@@ -7,12 +7,15 @@
// # Different assertions are made depending on whether SBE or classic is used. Implicitly
// # creating an index can change which engine is used.
// assumes_no_implicit_index_creation,
+// # This test assumes that either SBE or classic is fully enabled and that we're not running in
+// # a mixed version cluster.
+// requires_fcv_63,
// ]
(function() {
"use strict";
-load("jstests/libs/sbe_explain_helpers.js"); // For engineSpecificAssertion.
+load("jstests/libs/sbe_util.js"); // For 'checkSBEEnabled'.
const t = db[jsTestName()];
t.drop();
@@ -56,42 +59,39 @@ assert.commandWorked(t.insert({a: 2, b: 2}));
// SBE or the classic engine. This is because the classic engine will use a multi-interval index
// scan whereas SBE will decompose the intervals into a set of single-interval bounds and will end
// up examining 0 keys.
-let assertFn = function(expectedKeys, numKeysExamined) {
- return numKeysExamined === expectedKeys;
-};
+const isSBEEnabled = checkSBEEnabled(db);
+let expectedKeys = isSBEEnabled ? 0 : 3;
let errMsg = function(actualNumKeys) {
return "Chosen plan examined " + actualNumKeys + " keys";
};
-let sbeAssert = actualKeys => assertFn(0, actualKeys);
-let classicAssert = actualKeys => assertFn(3, actualKeys);
let numKeys = keysExamined({a: {$in: [1, 2]}, b: {$gt: 1, $lt: 2}}, {a: 1, b: 1});
-engineSpecificAssertion(classicAssert(numKeys), sbeAssert(numKeys), db, errMsg(numKeys));
+assert.eq(numKeys, expectedKeys, errMsg(numKeys));
numKeys = keysExamined({a: {$in: [1, 2]}, b: {$gt: 1, $lt: 2}}, {a: 1, b: 1}, {a: -1, b: -1});
-engineSpecificAssertion(classicAssert(numKeys), sbeAssert(numKeys), db, errMsg(numKeys));
+assert.eq(numKeys, expectedKeys, errMsg(numKeys));
assert.commandWorked(t.insert({a: 1, b: 1}));
assert.commandWorked(t.insert({a: 1, b: 1}));
numKeys = keysExamined({a: {$in: [1, 2]}, b: {$gt: 1, $lt: 2}}, {a: 1, b: 1});
-engineSpecificAssertion(classicAssert(numKeys), sbeAssert(numKeys), db, errMsg(numKeys));
+assert.eq(numKeys, expectedKeys, errMsg(numKeys));
numKeys = keysExamined({a: {$in: [1, 2]}, b: {$gt: 1, $lt: 2}}, {a: 1, b: 1});
-engineSpecificAssertion(classicAssert(numKeys), sbeAssert(numKeys), db, errMsg(numKeys));
+assert.eq(numKeys, expectedKeys, errMsg(numKeys));
numKeys = keysExamined({a: {$in: [1, 2]}, b: {$gt: 1, $lt: 2}}, {a: 1, b: 1}, {a: -1, b: -1});
-engineSpecificAssertion(classicAssert(numKeys), sbeAssert(numKeys), db, errMsg(numKeys));
+assert.eq(numKeys, expectedKeys, errMsg(numKeys));
// We examine one less key in the classic engine because the bounds are slightly tighter.
-classicAssert = actualKeys => assertFn(2, actualKeys);
-numKeys = keysExamined({a: {$in: [1, 1.9]}, b: {$gt: 1, $lt: 2}}, {a: 1, b: 1});
-engineSpecificAssertion(classicAssert(numKeys), sbeAssert(numKeys), db, errMsg(numKeys));
+if (!isSBEEnabled) {
+ expectedKeys = 2;
+}
+numKeys = keysExamined({a: {$in: [1, 1.9]}, b: {$gt: 1, $lt: 2}}, {a: 1, b: 1});
+assert.eq(numKeys, expectedKeys, errMsg(numKeys));
numKeys = keysExamined({a: {$in: [1.1, 2]}, b: {$gt: 1, $lt: 2}}, {a: 1, b: 1}, {a: -1, b: -1});
-engineSpecificAssertion(classicAssert(numKeys), sbeAssert(numKeys), db, errMsg(numKeys));
-
+assert.eq(numKeys, expectedKeys, errMsg(numKeys));
assert.commandWorked(t.insert({a: 1, b: 1.5}));
// We examine one extra key in both engines because we've inserted a document that falls within
// both sets of bounds being scanned.
-sbeAssert = actualKeys => assertFn(1, actualKeys);
-classicAssert = actualKeys => assertFn(4, actualKeys);
+expectedKeys = isSBEEnabled ? 1 : 4;
numKeys = keysExamined({a: {$in: [1, 2]}, b: {$gt: 1, $lt: 2}}, {a: 1, b: 1});
-engineSpecificAssertion(classicAssert(numKeys), sbeAssert(numKeys), db, errMsg(numKeys));
+assert.eq(numKeys, expectedKeys, errMsg(numKeys));
})();
diff --git a/jstests/core/index/wildcard/wildcard_index_cached_plans.js b/jstests/core/index/wildcard/wildcard_index_cached_plans.js
index f3a41f5361e..5e78a11d451 100644
--- a/jstests/core/index/wildcard/wildcard_index_cached_plans.js
+++ b/jstests/core/index/wildcard/wildcard_index_cached_plans.js
@@ -34,7 +34,7 @@ coll.drop();
assert.commandWorked(coll.createIndex({"b.$**": 1}));
assert.commandWorked(coll.createIndex({"a": 1}));
-const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
+const isSbeEnabled = checkSBEEnabled(db);
// 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
diff --git a/jstests/core/query/explode_for_sort_plan_cache.js b/jstests/core/query/explode_for_sort_plan_cache.js
index 3d489ad9d54..2da78284a6a 100644
--- a/jstests/core/query/explode_for_sort_plan_cache.js
+++ b/jstests/core/query/explode_for_sort_plan_cache.js
@@ -11,7 +11,7 @@
* # If all chunks are moved off of a shard, it can cause the plan cache to miss commands.
* assumes_balancer_off,
* assumes_unsharded_collection,
- * requires_fcv_62,
+ * requires_fcv_63,
* # Plan cache state is node-local and will not get migrated alongside tenant data.
* tenant_migration_incompatible,
* # Part of this test does different checks depending on the engine used. If an implicit index
@@ -65,7 +65,7 @@ const sortSpec = {
// TODO SERVER-67576: remove this branch once explode for sort plans are supported by the SBE plan
// cache.
-if (checkSBEEnabled(db, ["featureFlagSbeFull"])) {
+if (checkSBEEnabled(db)) {
// 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/query/expr/expr_index_use.js b/jstests/core/query/expr/expr_index_use.js
index a0f85bc69c9..2eadaf645be 100644
--- a/jstests/core/query/expr/expr_index_use.js
+++ b/jstests/core/query/expr/expr_index_use.js
@@ -1,6 +1,7 @@
// Confirms expected index use when performing a match with a $expr statement.
// @tags: [
// assumes_read_concern_local,
+// requires_fcv_63,
// ]
(function() {
@@ -92,10 +93,7 @@ function confirmExpectedExprExecution(expr, metricsToCheck, collation) {
];
assert.eq(metricsToCheck.nReturned, coll.aggregate(pipelineWithProject, aggOptions).itcount());
let explain = coll.explain("executionStats").aggregate(pipelineWithProject, aggOptions);
- assert(getAggPlanStage(explain, "COLLSCAN", isSBEEnabled /* useQueryPlannerSection */) ||
- checkBothEnginesAreRunOnCluster(db) &&
- (getAggPlanStage(explain, "COLLSCAN", false /* useQueryPlannerSection */) ||
- getAggPlanStage(explain, "COLLSCAN", true /* useQueryPlannerSection */)),
+ assert(getAggPlanStage(explain, "COLLSCAN", isSBEEnabled /* useQueryPlannerSection */),
explain);
// Verifies that there are no rejected plans, and that the winning plan uses the expected
diff --git a/jstests/core/query/idhack.js b/jstests/core/query/idhack.js
index e60bd9c8a50..1ddab70d4cd 100644
--- a/jstests/core/query/idhack.js
+++ b/jstests/core/query/idhack.js
@@ -61,8 +61,7 @@ winningPlan = getWinningPlan(explain.queryPlanner);
assert(!isIdhack(db, winningPlan), winningPlan);
// Covered query returning _id field only can be handled by ID hack.
-const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
-const parentStage = isSbeEnabled ? "PROJECTION_COVERED" : "FETCH";
+const parentStage = checkSBEEnabled(db) ? "PROJECTION_COVERED" : "FETCH";
explain = t.find(query, {_id: 1}).explain();
winningPlan = getWinningPlan(explain.queryPlanner);
assert(isIdhack(db, winningPlan), winningPlan);
diff --git a/jstests/core/query/null_query_semantics.js b/jstests/core/query/null_query_semantics.js
index a99741853d2..71cd4b7c84f 100644
--- a/jstests/core/query/null_query_semantics.js
+++ b/jstests/core/query/null_query_semantics.js
@@ -790,8 +790,8 @@ const keyPatterns = [
];
// Include Columnstore Index only if FF is enabled and collection is not clustered.
-const columnstoreEnabled = checkSBEEnabled(
- db, ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"], true /* checkAllNodes */);
+const columnstoreEnabled =
+ checkSBEEnabled(db, ["featureFlagColumnstoreIndexes"], true /* checkAllNodes */);
if (columnstoreEnabled && setUpServerForColumnStoreIndexTest(db)) {
keyPatterns.push({keyPattern: {"$**": "columnstore"}});
}
diff --git a/jstests/core/query/or/or_to_in.js b/jstests/core/query/or/or_to_in.js
index 5d3c745dc95..681e2af9e2a 100644
--- a/jstests/core/query/or/or_to_in.js
+++ b/jstests/core/query/or/or_to_in.js
@@ -4,6 +4,7 @@
// This test is not prepared to handle explain output for sharded collections.
// @tags: [
// assumes_unsharded_collection,
+// requires_fcv_63,
// ]
(function() {
@@ -11,7 +12,6 @@
load("jstests/aggregation/extras/utils.js"); // For assertArrayEq.
load("jstests/libs/analyze_plan.js");
-load("jstests/libs/sbe_util.js"); // For checkBothEnginesAreRunOnCluster.
var coll = db.orToIn;
coll.drop();
@@ -48,9 +48,7 @@ function assertEquivPlanAndResult(expectedQuery, actualQuery, supportWithCollati
// Make sure both queries have the same access plan.
const expectedPlan = getWinningPlan(expectedExplain.queryPlanner);
const actualPlan = getWinningPlan(actualExplain.queryPlanner);
- if (!checkBothEnginesAreRunOnCluster(db)) {
- assert.docEq(expectedPlan, actualPlan);
- }
+ assert.docEq(expectedPlan, actualPlan);
// The queries must produce the same result.
const expectedRes = coll.find(expectedQuery).toArray();
diff --git a/jstests/core/query/plan_cache/cached_plan_trial_does_not_discard_work.js b/jstests/core/query/plan_cache/cached_plan_trial_does_not_discard_work.js
index f83b9e6a817..941ec0106b5 100644
--- a/jstests/core/query/plan_cache/cached_plan_trial_does_not_discard_work.js
+++ b/jstests/core/query/plan_cache/cached_plan_trial_does_not_discard_work.js
@@ -12,7 +12,8 @@
// assumes_read_preference_unchanged,
// assumes_unsharded_collection,
// does_not_support_stepdowns,
-// requires_fcv_52,
+// # The SBE plan cache was first enabled in 6.3.
+// requires_fcv_63,
// requires_profiling,
// # Plan cache state is node-local and will not get migrated alongside tenant data.
// tenant_migration_incompatible,
@@ -25,7 +26,7 @@
load("jstests/libs/profiler.js"); // getLatestProfileEntry.
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
+if (!checkSBEEnabled(db)) {
jsTestLog("Skipping test because SBE is disabled");
return;
}
diff --git a/jstests/core/query/plan_cache/collation_plan_cache.js b/jstests/core/query/plan_cache/collation_plan_cache.js
index da6c2f08081..99e983dd2fa 100644
--- a/jstests/core/query/plan_cache/collation_plan_cache.js
+++ b/jstests/core/query/plan_cache/collation_plan_cache.js
@@ -20,7 +20,6 @@
load("jstests/libs/analyze_plan.js"); // For getPlanCacheKeyFromExplain.
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
var coll = db.collation_plan_cache;
coll.drop();
@@ -54,6 +53,8 @@ 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');
+
+const isSbeEnabled = checkSBEEnabled(db);
if (!isSbeEnabled) {
assert.eq(shapes[0].createdFromQuery.query, {a: 'foo', b: 5}, shapes);
assert.eq(shapes[0].createdFromQuery.sort, {}, shapes);
diff --git a/jstests/core/query/plan_cache/plan_cache_clear.js b/jstests/core/query/plan_cache/plan_cache_clear.js
index 7aee144bc89..d03330ab08e 100644
--- a/jstests/core/query/plan_cache/plan_cache_clear.js
+++ b/jstests/core/query/plan_cache/plan_cache_clear.js
@@ -15,6 +15,8 @@
// assumes_unsharded_collection,
// # Plan cache state is node-local and will not get migrated alongside tenant data.
// tenant_migration_incompatible,
+// # The SBE plan cache was first enabled in 6.3.
+// requires_fcv_63,
// # TODO SERVER-67607: Test plan cache with CQF enabled.
// cqf_incompatible,
// ]
@@ -104,7 +106,7 @@ const nonExistentColl = db.plan_cache_clear_nonexistent;
nonExistentColl.drop();
assert.commandWorked(nonExistentColl.runCommand('planCacheClear'));
-if (checkSBEEnabled(db, ["featureFlagSbeFull"], true /* checkAllNodes */)) {
+if (checkSBEEnabled(db)) {
// Plan cache commands should work against the main collection only, not foreignColl
// collections, when $lookup is pushed down into SBE.
const foreignColl = db.plan_cache_clear_foreign;
diff --git a/jstests/core/query/plan_cache/plan_cache_list_plans.js b/jstests/core/query/plan_cache/plan_cache_list_plans.js
index 6521aac3448..b0f7a24c615 100644
--- a/jstests/core/query/plan_cache/plan_cache_list_plans.js
+++ b/jstests/core/query/plan_cache/plan_cache_list_plans.js
@@ -29,7 +29,7 @@ load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
let coll = db.jstests_plan_cache_list_plans;
coll.drop();
-const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
+const isSbeEnabled = checkSBEEnabled(db);
function dumpPlanCacheState() {
return coll.aggregate([{$planCacheStats: {}}]).toArray();
diff --git a/jstests/core/query/plan_cache/plan_cache_list_shapes.js b/jstests/core/query/plan_cache/plan_cache_list_shapes.js
index 7d348cc21a2..48535eae0c3 100644
--- a/jstests/core/query/plan_cache/plan_cache_list_shapes.js
+++ b/jstests/core/query/plan_cache/plan_cache_list_shapes.js
@@ -20,8 +20,8 @@
'use strict';
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-if (checkSBEEnabled(db, ["featureFlagSbeFull"])) {
- jsTest.log("Skipping test because SBE is fully enabled.");
+if (checkSBEEnabled(db)) {
+ jsTest.log("Skipping test because SBE is enabled.");
return;
}
diff --git a/jstests/core/query/plan_cache/plan_cache_sbe.js b/jstests/core/query/plan_cache/plan_cache_sbe.js
index aeb0609246c..2a35b786d70 100644
--- a/jstests/core/query/plan_cache/plan_cache_sbe.js
+++ b/jstests/core/query/plan_cache/plan_cache_sbe.js
@@ -12,8 +12,8 @@
* assumes_read_concern_unchanged,
* assumes_read_preference_unchanged,
* assumes_unsharded_collection,
- * # The SBE plan cache was introduced in 6.0.
- * requires_fcv_60,
+ * # The SBE plan cache was first enabled in 6.3.
+ * requires_fcv_63,
* # Plan cache state is node-local and will not get migrated alongside tenant data.
* tenant_migration_incompatible,
* # TODO SERVER-67607: Test plan cache with CQF enabled.
@@ -30,7 +30,7 @@ load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
const coll = db.plan_cache_sbe;
coll.drop();
-const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"], true /* checkAllNodes */);
+const isSbeEnabled = checkSBEEnabled(db);
assert.commandWorked(coll.insert({a: 1, b: 1}));
diff --git a/jstests/core/query/plan_cache/plan_cache_shell_helpers.js b/jstests/core/query/plan_cache/plan_cache_shell_helpers.js
index b663e09e90b..a102d8a001d 100644
--- a/jstests/core/query/plan_cache/plan_cache_shell_helpers.js
+++ b/jstests/core/query/plan_cache/plan_cache_shell_helpers.js
@@ -21,7 +21,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 isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
+const isSbeEnabled = checkSBEEnabled(db);
var coll = db.jstests_plan_cache_shell_helpers;
coll.drop();
diff --git a/jstests/core/query/project/projection_expr_mod.js b/jstests/core/query/project/projection_expr_mod.js
index aa882d190b5..a8f2905bce5 100644
--- a/jstests/core/query/project/projection_expr_mod.js
+++ b/jstests/core/query/project/projection_expr_mod.js
@@ -4,14 +4,7 @@
"use strict";
load("jstests/aggregation/extras/utils.js"); // For assertArrayEq.
-load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-
-const isSBEEnabled = checkSBEEnabledOnSomeNode(db);
-if (isSBEEnabled) {
- // Override error-code-checking APIs. We only load this when SBE is explicitly enabled, because
- // it causes failures in the parallel suites.
- load("jstests/libs/sbe_assert_error_override.js");
-}
+load("jstests/libs/sbe_assert_error_override.js");
const coll = db.projection_expr_mod;
coll.drop();
diff --git a/jstests/core/query/project/projection_semantics.js b/jstests/core/query/project/projection_semantics.js
index cf71f951755..1f811c84b36 100644
--- a/jstests/core/query/project/projection_semantics.js
+++ b/jstests/core/query/project/projection_semantics.js
@@ -6,7 +6,8 @@
* # We could potentially need to resume an index build in the event of a stepdown, which is not
* # yet implemented.
* does_not_support_stepdowns,
- * requires_fcv_62,
+ * # Columnstore indexes were first enabled by default on 6.3.
+ * requires_fcv_63,
* # Columnstore tests set server parameters to disable columnstore query planning heuristics -
* # server parameters are stored in-memory only so are not transferred onto the recipient.
* tenant_migration_incompatible,
@@ -19,7 +20,7 @@
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
load("jstests/libs/columnstore_util.js"); // For setUpServerForColumnStoreIndexTest.
-if (!checkSBEEnabled(db, ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"])) {
+if (!checkSBEEnabled(db, ["featureFlagColumnstoreIndexes"])) {
jsTestLog("Skipping test since columnstore Indexes are not enabled");
return;
}
diff --git a/jstests/core/query/query_hash_stability.js b/jstests/core/query/query_hash_stability.js
index aa0a3399e70..c358f1c7d34 100644
--- a/jstests/core/query/query_hash_stability.js
+++ b/jstests/core/query/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, ["featureFlagSbeFull"])) {
+if (!checkSBEEnabled(db)) {
// The 'planCacheKey' should be the same as what it was before we dropped the index.
assertPlanCacheField({
firstExplain: initialExplain,
diff --git a/jstests/core/sbe/from_plan_cache_flag.js b/jstests/core/sbe/from_plan_cache_flag.js
index ef910b42513..15fee88f73c 100644
--- a/jstests/core/sbe/from_plan_cache_flag.js
+++ b/jstests/core/sbe/from_plan_cache_flag.js
@@ -1,8 +1,10 @@
-// The test runs commands that are not allowed with security token: setProfilingLevel.
// @tags: [
+// # The test runs commands that are not allowed with security token: setProfilingLevel.
// not_allowed_with_security_token,
// requires_profiling,
// does_not_support_stepdowns,
+// # The SBE plan cache was first enabled in 6.3.
+// requires_fcv_63,
// # TODO SERVER-67607: Test plan cache with CQF enabled.
// cqf_incompatible,
// ]
@@ -14,7 +16,7 @@ load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
load("jstests/libs/profiler.js"); // For getLatestProfilerEntry.
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-if (!checkSBEEnabled(db, ["featureFlagSbeFull"], true /* checkAllNodes */)) {
+if (!checkSBEEnabled(db)) {
jsTest.log("Skip running the test because SBE is not enabled");
return;
}
@@ -33,11 +35,6 @@ assert.commandWorked(coll.insert({a: 2}));
let pipeline = {$match: {a: 1}};
coll.aggregate([pipeline]).toArray();
let profileObj = getLatestProfilerEntry(testDB);
-/* fromPlanCache can be undefined in the profiler entry. The first ! determines the
- * profileObj.fromPlanCache value's associated true/false value (important in the case where
- * undefined) and then returns the opposite of the associated true/false value. The second !
- * returns the opposite of the opposite value. In other words, the !! returns the boolean true/false
- * association of a value. */
assert.eq(!!profileObj.fromPlanCache, false);
coll.aggregate({$match: {a: 2}}).toArray();
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 a4c474c82bd..f4a90d42dc1 100644
--- a/jstests/core/sbe/plan_cache_sbe_with_or_queries.js
+++ b/jstests/core/sbe/plan_cache_sbe_with_or_queries.js
@@ -7,7 +7,8 @@
// assumes_read_concern_unchanged,
// assumes_unsharded_collection,
// does_not_support_stepdowns,
-// requires_fcv_60,
+// # The SBE plan cache was first enabled in 6.3.
+// requires_fcv_63,
// # Plan cache state is node-local and will not get migrated alongside tenant data.
// tenant_migration_incompatible,
// # TODO SERVER-67607: Test plan cache with CQF enabled.
@@ -20,7 +21,7 @@
load("jstests/libs/analyze_plan.js");
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-if (!checkSBEEnabled(db, ["featureFlagSbeFull"], true /* checkAllNodes */)) {
+if (!checkSBEEnabled(db)) {
jsTest.log("Skip running the test because SBE is not enabled");
return;
}
diff --git a/jstests/core/sbe/sbe_explain_rejected_plans.js b/jstests/core/sbe/sbe_explain_rejected_plans.js
index 0e858cfd48c..a6ae2575186 100644
--- a/jstests/core/sbe/sbe_explain_rejected_plans.js
+++ b/jstests/core/sbe/sbe_explain_rejected_plans.js
@@ -1,6 +1,9 @@
/**
* Tests that SBE reports correct rejected plans when calling explain().
- * @tags: [assumes_unsharded_collection, requires_fcv_62]
+ * @tags: [
+ * assumes_unsharded_collection,
+ * requires_fcv_63,
+ * ]
*/
(function() {
"use strict";
@@ -9,9 +12,9 @@ load("jstests/libs/analyze_plan.js");
load("jstests/libs/collection_drop_recreate.js");
load("jstests/libs/sbe_util.js"); // For 'checkSBEEnabled'.
-const isSBEEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
+const isSBEEnabled = checkSBEEnabled(db);
if (!isSBEEnabled) {
- jsTestLog("Skipping test because the SBE feature flag is disabled");
+ jsTestLog("Skipping test because SBE is disabled");
return;
}
diff --git a/jstests/core/sbe/sbe_ixscan_explain.js b/jstests/core/sbe/sbe_ixscan_explain.js
index fee902af2b8..d79b8a209fc 100644
--- a/jstests/core/sbe/sbe_ixscan_explain.js
+++ b/jstests/core/sbe/sbe_ixscan_explain.js
@@ -3,7 +3,8 @@
//
// @tags: [
// assumes_against_mongod_not_mongos,
-// requires_fcv_51,
+// # The SBE plan cache was first enabled in 6.3.
+// requires_fcv_63,
// ]
(function() {
@@ -12,9 +13,9 @@
load('jstests/libs/analyze_plan.js'); // For getPlanStages
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-const isSBEEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"], true /* checkAllNodes */);
+const isSBEEnabled = checkSBEEnabled(db);
if (!isSBEEnabled) {
- jsTestLog("Skipping test because the SBE feature flag is disabled");
+ jsTestLog("Skipping test because SBE is disabled");
return;
}
diff --git a/jstests/core/sbe_plan_cache_autoparameterize_collscan.js b/jstests/core/sbe_plan_cache_autoparameterize_collscan.js
index f5be457ce99..3294846e3bd 100644
--- a/jstests/core/sbe_plan_cache_autoparameterize_collscan.js
+++ b/jstests/core/sbe_plan_cache_autoparameterize_collscan.js
@@ -7,8 +7,8 @@
* assumes_read_preference_unchanged,
* assumes_unsharded_collection,
* does_not_support_stepdowns,
- * # The SBE plan cache was introduced in 6.0.
- * requires_fcv_60,
+ * # The SBE plan cache was enabled by default in 6.3.
+ * requires_fcv_63,
* # Plan cache state is node-local and will not get migrated alongside tenant data.
* tenant_migration_incompatible,
* # TODO SERVER-67607: Test plan cache with CQF enabled.
@@ -24,9 +24,9 @@ load("jstests/libs/analyze_plan.js");
load("jstests/libs/sbe_util.js");
// This test is specifically verifying the behavior of the SBE plan cache, which is only enabled
-// when 'featureFlagSbeFull' is on.
-if (!checkSBEEnabled(db, ["featureFlagSbeFull"], true /* checkAllNodes */)) {
- jsTestLog("Skipping test because SBE is not fully enabled");
+// when SBE is enabled.
+if (!checkSBEEnabled(db)) {
+ jsTestLog("Skipping test because SBE is not enabled");
return;
}
@@ -305,32 +305,35 @@ runTest({query: {a: {$exists: true}}, projection: {_id: 1}},
false);
// Test that comparisons expressed as $expr are not auto-parameterized.
-runTest({query: {$expr: {$eq: ["$a", 3]}}, projection: {_id: 1}},
- [{_id: 2}],
- {query: {$expr: {$eq: ["$a", 4]}}, projection: {_id: 1}},
- [{_id: 3}, {_id: 4}],
- false);
-runTest({query: {$expr: {$lt: ["$a", 3]}, a: {$type: "number"}}, projection: {_id: 1}},
- [{_id: 0}, {_id: 1}],
- {query: {$expr: {$lt: ["$a", 4]}, a: {$type: "number"}}, projection: {_id: 1}},
- [{_id: 0}, {_id: 1}, {_id: 2}],
- false);
-runTest({query: {$expr: {$lte: ["$a", 3]}, a: {$type: "number"}}, projection: {_id: 1}},
- [{_id: 0}, {_id: 1}, {_id: 2}],
- {query: {$expr: {$lte: ["$a", 4]}, a: {$type: "number"}}, projection: {_id: 1}},
- [{_id: 0}, {_id: 1}, {_id: 2}, {_id: 3}, {_id: 4}],
- false);
-runTest({query: {$expr: {$gt: ["$a", 2]}, a: {$type: "number"}}, projection: {_id: 1}},
- [{_id: 2}, {_id: 3}, {_id: 4}, {_id: 5}, {_id: 6}],
- {query: {$expr: {$gt: ["$a", 3]}, a: {$type: "number"}}, projection: {_id: 1}},
- [{_id: 3}, {_id: 4}, {_id: 5}, {_id: 6}],
- false);
-runTest({query: {$expr: {$gte: ["$a", 2]}, a: {$type: "number"}}, projection: {_id: 1}},
- [{_id: 1}, {_id: 2}, {_id: 3}, {_id: 4}, {_id: 5}, {_id: 6}],
- {query: {$expr: {$gte: ["$a", 3]}, a: {$type: "number"}}, projection: {_id: 1}},
- [{_id: 2}, {_id: 3}, {_id: 4}, {_id: 5}, {_id: 6}],
- false);
-
+if (checkSBEEnabled(db, ["featureFlagSbeFull"])) {
+ runTest({query: {$expr: {$eq: ["$a", 3]}}, projection: {_id: 1}},
+ [{_id: 2}],
+ {query: {$expr: {$eq: ["$a", 4]}}, projection: {_id: 1}},
+ [{_id: 3}, {_id: 4}],
+ false);
+ runTest({query: {$expr: {$lt: ["$a", 3]}, a: {$type: "number"}}, projection: {_id: 1}},
+ [{_id: 0}, {_id: 1}],
+ {query: {$expr: {$lt: ["$a", 4]}, a: {$type: "number"}}, projection: {_id: 1}},
+ [{_id: 0}, {_id: 1}, {_id: 2}],
+ false);
+ runTest({query: {$expr: {$lte: ["$a", 3]}, a: {$type: "number"}}, projection: {_id: 1}},
+ [{_id: 0}, {_id: 1}, {_id: 2}],
+ {query: {$expr: {$lte: ["$a", 4]}, a: {$type: "number"}}, projection: {_id: 1}},
+ [{_id: 0}, {_id: 1}, {_id: 2}, {_id: 3}, {_id: 4}],
+ false);
+ runTest({query: {$expr: {$gt: ["$a", 2]}, a: {$type: "number"}}, projection: {_id: 1}},
+ [{_id: 2}, {_id: 3}, {_id: 4}, {_id: 5}, {_id: 6}],
+ {query: {$expr: {$gt: ["$a", 3]}, a: {$type: "number"}}, projection: {_id: 1}},
+ [{_id: 3}, {_id: 4}, {_id: 5}, {_id: 6}],
+ false);
+ runTest({query: {$expr: {$gte: ["$a", 2]}, a: {$type: "number"}}, projection: {_id: 1}},
+ [{_id: 1}, {_id: 2}, {_id: 3}, {_id: 4}, {_id: 5}, {_id: 6}],
+ {query: {$expr: {$gte: ["$a", 3]}, a: {$type: "number"}}, projection: {_id: 1}},
+ [{_id: 2}, {_id: 3}, {_id: 4}, {_id: 5}, {_id: 6}],
+ false);
+} else {
+ jsTestLog("Skipping $expr test cases because SBE is not fully enabled");
+}
// Test that the entire list of $in values is treated as a parameter.
runTest({query: {a: {$in: [1, 2]}}, projection: {_id: 1}},
[{_id: 0}, {_id: 1}],
diff --git a/jstests/cqf/analyze/scalar_histograms.js b/jstests/cqf/analyze/scalar_histograms.js
index 7777880a1f8..83dfa7c0a42 100644
--- a/jstests/cqf/analyze/scalar_histograms.js
+++ b/jstests/cqf/analyze/scalar_histograms.js
@@ -2,22 +2,17 @@
"use strict";
load("jstests/libs/optimizer_utils.js"); // For checkCascadesOptimizerEnabled.
-load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
if (!checkCascadesOptimizerEnabled(db)) {
jsTestLog("Skipping test because the optimizer is not enabled");
return;
}
-if (checkSBEEnabled(db, ["featureFlagSbeFull"], true)) {
- jsTestLog("Skipping the test because it doesn't work in Full SBE");
- return;
-}
-
assert.commandWorked(
db.adminCommand({setParameter: 1, internalQueryFrameworkControl: "tryBonsai"}));
const coll = db.cqf_analyze_scalar_hist;
+coll.drop();
const stats_coll = db.system.statistics.cqf_analyze_scalar_hist;
const testAnalyzeStats = (key, docs, count) => {
diff --git a/jstests/libs/parallelTester.js b/jstests/libs/parallelTester.js
index bc76e43d96b..ddd8190175b 100644
--- a/jstests/libs/parallelTester.js
+++ b/jstests/libs/parallelTester.js
@@ -253,6 +253,15 @@ if (typeof _threadInject != "undefined") {
// inMemory storage engine.
"timeseries/timeseries_compact.js",
+ // TODO (SERVER-63228): Remove this exclusion once the feature flag is enabled by
+ // default.
+ "timeseries/timeseries_index_ttl_partial.js",
+
+ // These tests load 'sbe_assert_error_override.js' unconditionally, which causes
+ // failures in the parallel suite.
+ "computed_projections.js",
+ "query/project/projection_expr_mod.js",
+
// TODO (SERVER-66393): Remove this exclusion once the feature flag is enabled by
// default.
"timeseries/timeseries_update_multi.js",
diff --git a/jstests/libs/sbe_explain_helpers.js b/jstests/libs/sbe_explain_helpers.js
index 994394c9abb..a405efc1ae5 100644
--- a/jstests/libs/sbe_explain_helpers.js
+++ b/jstests/libs/sbe_explain_helpers.js
@@ -41,24 +41,6 @@ function getSbePlanStages(queryLayerOutput, stage) {
}
/**
- * Helper to make an assertion depending on the engine being used. If we're in a mixed version
- * cluster, then we assert that either 'classicAssert' or 'sbeAssert' is true because the outcome
- * will depend on which node we're making assertions against. If we're not in a mixed version
- * scenario, then we make an assertion depending on the return value of 'checkSBEEnabled'.
- */
-function engineSpecificAssertion(classicAssert, sbeAssert, theDB, msg) {
- if (checkBothEnginesAreRunOnCluster(theDB)) {
- assert(classicAssert || sbeAssert, msg);
- } else if (checkSBEEnabled(theDB, ["featureFlagSbeFull"])) {
- // This function assumes that SBE is fully enabled, and will fall back to the classic
- // assert if it is not.
- assert(sbeAssert, msg);
- } else {
- assert(classicAssert, msg);
- }
-}
-
-/**
* Gets the query info object at either the top level or the first stage from a v2
* explainOutput. If a query is a find query or some prefix stage(s) of a pipeline is pushed down to
* SBE, then plan information will be in the 'queryPlanner' object. Currently, this supports find
diff --git a/jstests/libs/sbe_util.js b/jstests/libs/sbe_util.js
index 1508052cae0..90451a646f7 100644
--- a/jstests/libs/sbe_util.js
+++ b/jstests/libs/sbe_util.js
@@ -98,89 +98,3 @@ function checkSBEEnabled(theDB, featureFlags = [], checkAllNodes = false) {
return checkResult;
}
-
-/**
- * If 'theDB' corresponds to a node in a cluster, then returns true if the cluster that it
- * belongs to has at least one node that has SBE enabled and at least one node that has it
- * disabled; false otherwise.
- */
-function checkBothEnginesAreRunOnCluster(theDB) {
- let result = false;
- assert.soon(() => {
- if (!FixtureHelpers.isMongos(theDB) && !FixtureHelpers.isReplSet(theDB)) {
- return true;
- }
-
- // Retry the check if we fail to discover the topology (this can happen if the test
- // suite has killed the primary).
- let nodes;
- try {
- nodes = DiscoverTopology.findNonConfigNodes(theDB.getMongo());
- } catch (e) {
- return false;
- }
-
- let engineMap = {sbe: 0, classic: 0};
-
- for (const node of nodes) {
- // If we cannot contact a node because it was killed or is otherwise unreachable, we
- // skip it and check the other nodes in the cluster. For our purposes, this is ok
- // because test suites which step down/kill certain nodes are configured to use
- // exactly one engine, whereas the test suites which are configured use both engines
- // (namely, the multiversion suites), do not step down/kill nodes.
- try {
- const conn = new Mongo(node);
- if (FixtureHelpers.isMongos(conn.getDB("admin"))) {
- continue;
- }
-
- const getParam = conn.adminCommand({
- getParameter: 1,
- internalQueryFrameworkControl: 1,
- internalQueryForceClassicEngine: 1,
- featureFlagSbeFull: 1,
- });
-
- if (getParam.hasOwnProperty("internalQueryFrameworkControl")) {
- // We say SBE is fully enabled if the engine is on and either
- // 'featureFlagSbeFull' doesn't exist on the targeted server, or it exists and
- // is set to true.
- if (getParam.internalQueryFrameworkControl !== "forceClassicEngine" &&
- getParam.featureFlagSbeFull.value) {
- engineMap.sbe++;
- } else {
- engineMap.classic++;
- }
- } else {
- // 'internalQueryForceClassicEngine' should be set on the previous versions
- // before 'internalQueryFrameworkControl' is introduced.
- assert(getParam.hasOwnProperty("internalQueryForceClassicEngine"), getParam);
- if (!getParam.internalQueryForceClassicEngine.value &&
- getParam.featureFlagSbeFull.value) {
- engineMap.sbe++;
- } else {
- engineMap.classic++;
- }
- }
-
- result = (engineMap.sbe > 0 && engineMap.classic > 0);
- if (result) {
- return true;
- }
- } catch (e) {
- continue;
- }
- }
-
- return true;
- });
-
- return result;
-}
-
-/**
- * Returns 'true' if SBE is enabled on at least on one node for the given connection 'db'.
- */
-function checkSBEEnabledOnSomeNode(db) {
- return checkSBEEnabled(db) || checkBothEnginesAreRunOnCluster(db);
-}
diff --git a/jstests/noPassthrough/columnstore_index_rowstore_settings.js b/jstests/noPassthrough/columnstore_index_rowstore_settings.js
index 54f405cf7b7..22a2475cdc0 100644
--- a/jstests/noPassthrough/columnstore_index_rowstore_settings.js
+++ b/jstests/noPassthrough/columnstore_index_rowstore_settings.js
@@ -3,9 +3,8 @@
* reconstruct the result of a query.
*
* @tags: [
- * # column store indexes are still under a feature flag and require full sbe
- * featureFlagColumnstoreIndexes,
- * featureFlagSbeFull,
+ * # column store indexes are still under a feature flag
+ * featureFlagColumnstoreIndexes
* ]
*/
diff --git a/jstests/noPassthrough/currentop_query.js b/jstests/noPassthrough/currentop_query.js
index 7b6be89d2d8..a3244f66343 100644
--- a/jstests/noPassthrough/currentop_query.js
+++ b/jstests/noPassthrough/currentop_query.js
@@ -79,7 +79,7 @@ function runTests({conn, currentOp, truncatedOps, localOps}) {
const isLocalMongosCurOp = (FixtureHelpers.isMongos(testDB) && localOps);
const isRemoteShardCurOp = (FixtureHelpers.isMongos(testDB) && !localOps);
- const sbeEnabled = checkSBEEnabled(testDB, ["featureFlagSbeFull"]);
+ const sbeEnabled = checkSBEEnabled(testDB);
// If 'truncatedOps' is true, run only the subset of tests designed to validate the
// truncation behaviour. Otherwise, run the standard set of tests which assume that
diff --git a/jstests/noPassthrough/external_sort_find.js b/jstests/noPassthrough/external_sort_find.js
index befac93c5dc..a1505f129a3 100644
--- a/jstests/noPassthrough/external_sort_find.js
+++ b/jstests/noPassthrough/external_sort_find.js
@@ -21,7 +21,7 @@ assert.neq(null, conn, "mongod was unable to start up with options: " + tojson(o
const testDb = conn.getDB("test");
const collection = testDb.external_sort_find;
-const isSBEEnabled = checkSBEEnabled(testDb, ["featureFlagSbeFull"]);
+const isSBEEnabled = checkSBEEnabled(testDb);
// Construct a document that is just over 1 kB.
const charToRepeat = "-";
diff --git a/jstests/noPassthrough/log_and_profile_query_hash.js b/jstests/noPassthrough/log_and_profile_query_hash.js
index b31cfcfe0ad..65093194711 100644
--- a/jstests/noPassthrough/log_and_profile_query_hash.js
+++ b/jstests/noPassthrough/log_and_profile_query_hash.js
@@ -110,7 +110,7 @@ const testList = [
test: function(db, comment) {
assert.eq(200, db.test.find().comment(comment).itcount());
},
- hasPlanCacheKey: checkSBEEnabled(testDB, ["featureFlagSbeFull"])
+ hasPlanCacheKey: checkSBEEnabled(testDB)
},
{
comment: "Test1 find query",
diff --git a/jstests/noPassthrough/lookup_metrics.js b/jstests/noPassthrough/lookup_metrics.js
index 44082f99ac2..9f2aec0bfdb 100644
--- a/jstests/noPassthrough/lookup_metrics.js
+++ b/jstests/noPassthrough/lookup_metrics.js
@@ -8,8 +8,7 @@
load("jstests/libs/sbe_util.js"); // For 'checkSBEEnabled()'.
load("jstests/libs/analyze_plan.js"); // For 'getAggPlanStages' and other explain helpers.
-const conn =
- MongoRunner.runMongod({setParameter: {featureFlagSbeFull: true, allowDiskUseByDefault: true}});
+const conn = MongoRunner.runMongod({setParameter: {allowDiskUseByDefault: true}});
assert.neq(null, conn, "mongod was unable to start up");
const db = conn.getDB(jsTestName());
diff --git a/jstests/noPassthrough/lookup_pushdown.js b/jstests/noPassthrough/lookup_pushdown.js
index 8c6496d10f1..641c73d5ff2 100644
--- a/jstests/noPassthrough/lookup_pushdown.js
+++ b/jstests/noPassthrough/lookup_pushdown.js
@@ -18,7 +18,7 @@ const JoinAlgorithm = {
};
// Standalone cases.
-const conn = MongoRunner.runMongod({setParameter: {allowDiskUseByDefault: true}});
+const conn = MongoRunner.runMongod();
assert.neq(null, conn, "mongod was unable to start up");
const name = "lookup_pushdown";
const foreignCollName = "foreign_lookup_pushdown";
@@ -112,15 +112,13 @@ function runTest(coll,
}
let db = conn.getDB(name);
-if (!checkSBEEnabled(db)) {
- jsTestLog("Skipping test because either the sbe lookup pushdown feature flag is disabled or" +
- " sbe itself is disabled");
+const sbeEnabled = checkSBEEnabled(db);
+if (!sbeEnabled) {
+ jsTestLog("Skipping test because SBE is disabled");
MongoRunner.stopMongod(conn);
return;
}
-const sbeFullEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
-
let coll = db[name];
const localDocs = [{_id: 1, a: 2}];
assert.commandWorked(coll.insert(localDocs));
@@ -300,48 +298,6 @@ function setLookupPushdownDisabled(value) {
{allowDiskUse: false});
}());
-// Verify that SBE is only used when a $lookup or a $group is present.
-(function testLookupGroupIsRequiredForPushdown() {
- // Don't execute this test case if SBE is fully enabled.
- if (sbeFullEnabled) {
- jsTestLog("Skipping test case because we are supporting SBE beyond $group and $lookup" +
- " pushdown");
- return;
- }
-
- const assertEngineUsed = function(pipeline, isSBE) {
- const explain = coll.explain().aggregate(pipeline);
- assert(explain.hasOwnProperty("explainVersion"), explain);
- if (isSBE) {
- assert.eq(explain.explainVersion, "2", explain);
- } else {
- assert.eq(explain.explainVersion, "1", explain);
- }
- };
-
- const lookup = {$lookup: {from: "coll", localField: "a", foreignField: "b", as: "out"}};
- const group = {
- $group: {
- _id: "$a",
- out: {$min: "$b"},
- }
- };
- const match = {$match: {a: 1}};
-
- // $lookup and $group should each run in SBE.
- assertEngineUsed([lookup], true /* isSBE */);
- assertEngineUsed([group], true /* isSBE */);
- assertEngineUsed([lookup, group], true /* isSBE */);
-
- // $match on its own won't use SBE, nor will an empty pipeline.
- assertEngineUsed([match], false /* isSBE */);
- assertEngineUsed([], false /* isSBE */);
-
- // $match will use SBE if followed by either a $group or a $lookup.
- assertEngineUsed([match, lookup], true /* isSBE */);
- assertEngineUsed([match, group], true /* isSBE */);
-})();
-
// Build an index on the foreign collection that matches the foreignField. This should cause us
// to choose an indexed nested loop join.
(function testIndexNestedLoopJoinRegularIndex() {
@@ -707,61 +663,56 @@ function setLookupPushdownDisabled(value) {
// Test which verifies that the right side of a classic $lookup is never lowered into SBE, even if
// the queries for the right side are eligible on their own to run in SBE.
(function verifyThatClassicLookupRightSideIsNeverLoweredIntoSBE() {
- // If running with SBE fully enabled, verify that our $match is SBE compatible. Otherwise,
- // verify that the same $match, when used as a $lookup sub-pipeline, will not be lowered
- // into SBE.
+ // Confirm that our candidate subpipeline is SBE compatible on its own.
const subPipeline = [{$match: {b: 2}}];
- if (sbeFullEnabled) {
- const subPipelineExplain = foreignColl.explain().aggregate(subPipeline);
- assert(subPipelineExplain.hasOwnProperty("explainVersion"), subPipelineExplain);
- assert.eq(subPipelineExplain["explainVersion"], "2", subPipelineExplain);
- } else {
- const pipeline = [{$lookup: {from: foreignCollName, pipeline: subPipeline, as: "result"}}];
- runTest(coll, pipeline, JoinAlgorithm.Classic /* expectedJoinAlgorithm */);
-
- // Create multiple indexes that can be used to answer the subPipeline query. This will allow
- // the winning plan to be cached.
- assert.commandWorked(foreignColl.dropIndexes());
- assert.commandWorked(foreignColl.createIndexes([{b: 1, a: 1}, {b: 1, c: 1}]));
-
- // Run the pipeline enough times to generate a cache entry for the right side in the foreign
- // collection.
- coll.aggregate(pipeline).itcount();
- coll.aggregate(pipeline).itcount();
-
- const cacheEntries = foreignColl.getPlanCache().list();
- assert.eq(cacheEntries.length, 1);
- const cacheEntry = cacheEntries[0];
-
- // The cached plan should be a classic plan.
- assert(cacheEntry.hasOwnProperty("version"), cacheEntry);
- assert.eq(cacheEntry.version, "1", cacheEntry);
- assert(cacheEntry.hasOwnProperty("cachedPlan"), cacheEntry);
- const cachedPlan = cacheEntry.cachedPlan;
-
- // The cached plan should not have slot based plan. Instead, it should be a FETCH + IXSCAN
- // executed in the classic engine.
- assert(!cachedPlan.hasOwnProperty("slots"), cacheEntry);
- assert(cachedPlan.hasOwnProperty("stage"), cacheEntry);
-
- assert(planHasStage(db, cachedPlan, "FETCH"), cacheEntry);
- assert(planHasStage(db, cachedPlan, "IXSCAN"), cacheEntry);
- assert.commandWorked(coll.dropIndexes());
- }
+ const subPipelineExplain = foreignColl.explain().aggregate(subPipeline);
+ assert(subPipelineExplain.hasOwnProperty("explainVersion"), subPipelineExplain);
+ assert.eq(subPipelineExplain["explainVersion"], "2", subPipelineExplain);
+
+ // Now, run a lookup and force it to run in the classic engine by prefixing it with
+ // '$_internalInhibitOptimization'.
+ const pipeline = [
+ {$_internalInhibitOptimization: {}},
+ {$lookup: {from: foreignCollName, pipeline: subPipeline, as: "result"}}
+ ];
+ runTest(coll, pipeline, JoinAlgorithm.Classic /* expectedJoinAlgorithm */);
+
+ // Create multiple indexes that can be used to answer the subPipeline query. This will allow
+ // the winning plan to be cached.
+ assert.commandWorked(foreignColl.dropIndexes());
+ assert.commandWorked(foreignColl.createIndexes([{b: 1, a: 1}, {b: 1, c: 1}]));
+
+ // Run the pipeline enough times to generate a cache entry for the right side in the foreign
+ // collection.
+ coll.aggregate(pipeline).itcount();
+ coll.aggregate(pipeline).itcount();
+
+ const cacheEntries = foreignColl.getPlanCache().list();
+ assert.eq(cacheEntries.length, 1);
+ const cacheEntry = cacheEntries[0];
+
+ // The cached plan should be a classic plan.
+ assert(cacheEntry.hasOwnProperty("version"), cacheEntry);
+ assert.eq(cacheEntry.version, "1", cacheEntry);
+ assert(cacheEntry.hasOwnProperty("cachedPlan"), cacheEntry);
+ const cachedPlan = cacheEntry.cachedPlan;
+
+ // The cached plan should not have slot based plan. Instead, it should be a FETCH + IXSCAN
+ // executed in the classic engine.
+ assert(!cachedPlan.hasOwnProperty("slots"), cacheEntry);
+ assert(cachedPlan.hasOwnProperty("stage"), cacheEntry);
+
+ assert(planHasStage(db, cachedPlan, "FETCH"), cacheEntry);
+ assert(planHasStage(db, cachedPlan, "IXSCAN"), cacheEntry);
+ assert.commandWorked(coll.dropIndexes());
}());
MongoRunner.stopMongod(conn);
-// Verify that pipeline stages get pushed down according to the subset of SBE that is enabled.
-(function verifyPushdownLogicSbePartiallyEnabled() {
- const conn = MongoRunner.runMongod({setParameter: {allowDiskUseByDefault: true}});
+// Verify that $lookup and $group stages get pushed down as expected.
+(function verifyLookupGroupStagesArePushedDown() {
+ const conn = MongoRunner.runMongod();
const db = conn.getDB(name);
- if (sbeFullEnabled) {
- jsTestLog("Skipping test case because SBE is fully enabled, but this test case assumes" +
- " that it is not fully enabled");
- MongoRunner.stopMongod(conn);
- return;
- }
const coll = db[name];
const foreignColl = db[foreignCollName];
@@ -838,7 +789,7 @@ MongoRunner.stopMongod(conn);
(function testHashJoinQueryKnobs() {
// Create a new scope and start a new mongod so that the mongod-wide global state changes do not
// affect subsequent tests if any.
- const conn = MongoRunner.runMongod({setParameter: {featureFlagSbeFull: true}});
+ const conn = MongoRunner.runMongod();
const db = conn.getDB(name);
const lcoll = db.query_knobs_local;
const fcoll = db.query_knobs_foreign;
@@ -851,8 +802,7 @@ MongoRunner.stopMongod(conn);
runTest(lcoll,
[{$lookup: {from: fcoll.getName(), localField: "a", foreignField: "a", as: "out"}}],
JoinAlgorithm.HJ,
- null /* indexKeyPattern */,
- {allowDiskUse: true});
+ null /* indexKeyPattern */);
// The fcollStats.count means the number of documents in a collection, the fcollStats.size means
// the collection's data size, and the fcollStats.storageSize means the allocated storage size.
@@ -868,8 +818,7 @@ MongoRunner.stopMongod(conn);
runTest(lcoll,
[{$lookup: {from: fcoll.getName(), localField: "a", foreignField: "a", as: "out"}}],
JoinAlgorithm.HJ,
- null /* indexKeyPattern */,
- {allowDiskUse: true});
+ null /* indexKeyPattern */);
// Setting the 'internalQueryDisableLookupExecutionUsingHashJoin' knob to true will disable
// HJ plans from being chosen and since the pipeline is SBE compatible it will fallback to
@@ -882,8 +831,7 @@ MongoRunner.stopMongod(conn);
runTest(lcoll,
[{$lookup: {from: fcoll.getName(), localField: "a", foreignField: "a", as: "out"}}],
JoinAlgorithm.NLJ,
- null /* indexKeyPattern */,
- {allowDiskUse: true});
+ null /* indexKeyPattern */);
// Test that we can go back to generating HJ plans.
assert.commandWorked(db.adminCommand({
@@ -894,8 +842,7 @@ MongoRunner.stopMongod(conn);
runTest(lcoll,
[{$lookup: {from: fcoll.getName(), localField: "a", foreignField: "a", as: "out"}}],
JoinAlgorithm.HJ,
- null /* indexKeyPattern */,
- {allowDiskUse: true});
+ null /* indexKeyPattern */);
// Setting the 'internalQueryCollectionMaxNoOfDocumentsToChooseHashJoin' to count - 1 results in
// choosing the NLJ algorithm.
@@ -907,8 +854,7 @@ MongoRunner.stopMongod(conn);
runTest(lcoll,
[{$lookup: {from: fcoll.getName(), localField: "a", foreignField: "a", as: "out"}}],
JoinAlgorithm.NLJ,
- null /* indexKeyPattern */,
- {allowDiskUse: true});
+ null /* indexKeyPattern */);
// Reverting back 'internalQueryCollectionMaxNoOfDocumentsToChooseHashJoin' to the previous
// value. Setting the 'internalQueryCollectionMaxDataSizeBytesToChooseHashJoin' to size - 1
@@ -922,8 +868,7 @@ MongoRunner.stopMongod(conn);
runTest(lcoll,
[{$lookup: {from: fcoll.getName(), localField: "a", foreignField: "a", as: "out"}}],
JoinAlgorithm.NLJ,
- null /* indexKeyPattern */,
- {allowDiskUse: true});
+ null /* indexKeyPattern */);
// Reverting back 'internalQueryCollectionMaxDataSizeBytesToChooseHashJoin' to the previous
// value. Setting the 'internalQueryCollectionMaxStorageSizeBytesToChooseHashJoin' to
@@ -937,8 +882,7 @@ MongoRunner.stopMongod(conn);
runTest(lcoll,
[{$lookup: {from: fcoll.getName(), localField: "a", foreignField: "a", as: "out"}}],
JoinAlgorithm.NLJ,
- null /* indexKeyPattern */,
- {allowDiskUse: true});
+ null /* indexKeyPattern */);
MongoRunner.stopMongod(conn);
}());
@@ -1010,11 +954,7 @@ MongoRunner.stopMongod(conn);
}());
// Sharded cases.
-const st = new ShardingTest({
- shards: 2,
- mongos: 1,
- other: {shardOptions: {setParameter: {featureFlagSbeFull: true, allowDiskUseByDefault: true}}}
-});
+const st = new ShardingTest({shards: 2, mongos: 1});
db = st.s.getDB(name);
// Setup. Here, 'coll' is sharded, 'foreignColl' is unsharded, 'viewName' is an unsharded view,
diff --git a/jstests/noPassthrough/plan_cache_group_lookup.js b/jstests/noPassthrough/plan_cache_group_lookup.js
index f18277689b5..dcef122bf80 100644
--- a/jstests/noPassthrough/plan_cache_group_lookup.js
+++ b/jstests/noPassthrough/plan_cache_group_lookup.js
@@ -22,8 +22,6 @@ if (!checkSBEEnabled(db)) {
return;
}
-const sbeFullEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
-
assert.commandWorked(coll.insert({a: 1}));
assert.commandWorked(coll.createIndex({a: 1, a1: 1}));
assert.commandWorked(coll.createIndex({a: 1, a2: 1}));
@@ -123,7 +121,7 @@ const groupStage = {
(function testLoweredPipelineCombination() {
setupForeignColl();
- const expectedVersion = sbeFullEnabled ? 2 : 1;
+ const expectedVersion = 2;
coll.getPlanCache().clear();
testLoweredPipeline(
@@ -147,16 +145,11 @@ const groupStage = {
setupForeignColl();
testLoweredPipeline({
pipeline: [multiPlanningQueryStage, lookupStage, {$_internalInhibitOptimization: {}}],
- version: sbeFullEnabled ? 2 : 1
+ version: 2
});
})();
(function testNonExistentForeignCollectionCache() {
- if (!sbeFullEnabled) {
- jsTestLog("Skipping testNonExistentForeignCollectionCache when SBE is not fully enabled");
- return;
- }
-
coll.getPlanCache().clear();
foreignColl.drop();
const entryWithoutForeignColl =
@@ -176,12 +169,6 @@ const groupStage = {
})();
(function testForeignCollectionDropCacheInvalidation() {
- if (!sbeFullEnabled) {
- jsTestLog(
- "Skipping testForeignCollectionDropCacheInvalidation when SBE is not fully enabled");
- return;
- }
-
coll.getPlanCache().clear();
setupForeignColl();
testLoweredPipeline({pipeline: [multiPlanningQueryStage, lookupStage], version: 2});
@@ -191,11 +178,6 @@ const groupStage = {
})();
(function testForeignIndexDropCacheInvalidation() {
- if (!sbeFullEnabled) {
- jsTestLog("Skipping testForeignIndexDropCacheInvalidation when SBE is not fully enabled");
- return;
- }
-
coll.getPlanCache().clear();
setupForeignColl({b: 1} /* index */);
testLoweredPipeline({pipeline: [multiPlanningQueryStage, lookupStage], version: 2});
@@ -205,11 +187,6 @@ const groupStage = {
})();
(function testForeignIndexBuildCacheInvalidation() {
- if (!sbeFullEnabled) {
- jsTestLog("Skipping testForeignIndexBuildCacheInvalidation when SBE is not fully enabled");
- return;
- }
-
coll.getPlanCache().clear();
setupForeignColl({b: 1} /* index */);
testLoweredPipeline({pipeline: [multiPlanningQueryStage, lookupStage], version: 2});
@@ -219,11 +196,6 @@ const groupStage = {
})();
(function testLookupSbeAndClassicPlanCacheKey() {
- if (!sbeFullEnabled) {
- jsTestLog("Skipping testLookupWithClassicPlanCache when SBE is not fully enabled");
- return;
- }
-
setupForeignColl({b: 1} /* index */);
// When using SBE engine, the plan cache key of $match vs. $match + $lookup should be different.
diff --git a/jstests/noPassthrough/plan_cache_index_create.js b/jstests/noPassthrough/plan_cache_index_create.js
index fed5fa3c18e..7a37e49bfc4 100644
--- a/jstests/noPassthrough/plan_cache_index_create.js
+++ b/jstests/noPassthrough/plan_cache_index_create.js
@@ -180,8 +180,8 @@ rst.initiate();
const primaryDB = rst.getPrimary().getDB(dbName);
const secondaryDB = rst.getSecondary().getDB(dbName);
-if (checkSBEEnabled(primaryDB, ["featureFlagSbeFull"])) {
- jsTest.log("Skipping test because SBE is fully enabled");
+if (checkSBEEnabled(primaryDB)) {
+ jsTest.log("Skipping test because SBE is 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 9fd79e8308e..3e778a53e3a 100644
--- a/jstests/noPassthrough/plan_cache_list_failed_plans.js
+++ b/jstests/noPassthrough/plan_cache_list_failed_plans.js
@@ -9,8 +9,8 @@ assert.neq(null, conn, "mongod was unable to start up");
const testDB = conn.getDB("jstests_plan_cache_list_failed_plans");
const coll = testDB.test;
-if (checkSBEEnabled(testDB, ["featureFlagSbeFull"])) {
- jsTest.log("Skipping test because SBE is fully enabled");
+if (checkSBEEnabled(testDB)) {
+ jsTest.log("Skipping test because SBE is enabled");
MongoRunner.stopMongod(conn);
return;
}
diff --git a/jstests/noPassthrough/plan_cache_memory_debug_info.js b/jstests/noPassthrough/plan_cache_memory_debug_info.js
index 331077bebfa..a52d1f5aebe 100644
--- a/jstests/noPassthrough/plan_cache_memory_debug_info.js
+++ b/jstests/noPassthrough/plan_cache_memory_debug_info.js
@@ -83,8 +83,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, ["featureFlagSbeFull"])) {
- jsTest.log("Skipping test because SBE is fully enabled");
+if (checkSBEEnabled(db)) {
+ jsTest.log("Skipping test because SBE is 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 1fa8be2ab10..941b9ba7d8d 100644
--- a/jstests/noPassthrough/plan_cache_replan_group_lookup.js
+++ b/jstests/noPassthrough/plan_cache_replan_group_lookup.js
@@ -19,7 +19,7 @@ const coll = db.plan_cache_replan_group_lookup;
const foreignCollName = "foreign";
coll.drop();
-const sbeFullEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
+const sbeEnabled = checkSBEEnabled(db);
function getPlansForCacheEntry(match) {
const matchingCacheEntries = coll.getPlanCache().list([{$match: match}]);
@@ -165,7 +165,7 @@ const aIndexPredicate = [{$match: {a: 1042, b: 1}}];
// {a: 1} index is used.
const bIndexPredicate = [{$match: {a: 1, b: 1042}}];
-const expectedVersion = sbeFullEnabled ? 2 : 1;
+const expectedVersion = sbeEnabled ? 2 : 1;
// $group tests.
const groupSuffix = [{$group: {_id: "$c"}}, {$count: "n"}];
testFn(aIndexPredicate.concat(groupSuffix),
@@ -249,9 +249,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(sbeFullEnabled /*multiPlanning*/,
+assertCacheUsage(sbeEnabled /*multiPlanning*/,
expectedVersion /* cacheEntryVersion */,
- !sbeFullEnabled /*cacheEntryIsActive*/,
+ !sbeEnabled /*cacheEntryIsActive*/,
"a_1" /*cachedIndexName*/,
aLookup);
@@ -260,7 +260,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(sbeFullEnabled /*multiPlanning*/,
+assertCacheUsage(sbeEnabled /*multiPlanning*/,
expectedVersion /* cacheEntryVersion */,
true /*cacheEntryIsActive*/,
"a_1" /*cachedIndexName*/,
@@ -270,9 +270,9 @@ assertCacheUsage(sbeFullEnabled /*multiPlanning*/,
dropLookupForeignColl();
verifyCorrectLookupAlgorithmUsed("NonExistentForeignCollection", aLookup, {allowDiskUse: true});
assert.eq(2, coll.aggregate(aLookup).toArray()[0].n);
-assertCacheUsage(sbeFullEnabled /*multiPlanning*/,
+assertCacheUsage(sbeEnabled /*multiPlanning*/,
expectedVersion /* cacheEntryVersion */,
- !sbeFullEnabled /*cacheEntryIsActive*/,
+ !sbeEnabled /*cacheEntryIsActive*/,
"a_1" /*cachedIndexName*/,
aLookup);
@@ -335,7 +335,7 @@ 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 (sbeFullEnabled) {
+if (sbeEnabled) {
runLookupQuery({allowDiskUse: false});
assertCacheUsage(true /*multiPlanning*/,
2 /* cacheEntryVersion */,
@@ -355,7 +355,7 @@ if (sbeFullEnabled) {
runLookupQuery({allowDiskUse: false});
assertCacheUsage(false /*multiPlanning*/,
- sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeEnabled ? 2 : 1 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline,
@@ -363,7 +363,7 @@ assertCacheUsage(false /*multiPlanning*/,
runLookupQuery({allowDiskUse: false});
assertCacheUsage(false /*multiPlanning*/,
- sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeEnabled ? 2 : 1 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline,
@@ -375,7 +375,7 @@ verifyCorrectLookupAlgorithmUsed("HashJoin", avoidReplanLookupPipeline, {allowDi
// If SBE plan cache is enabled, using different 'allowDiskUse' option will result in
// different plan cache key.
-if (sbeFullEnabled) {
+if (sbeEnabled) {
runLookupQuery({allowDiskUse: true});
assertCacheUsage(true /*multiPlanning*/,
2 /* cacheEntryVersion */,
@@ -395,14 +395,14 @@ if (sbeFullEnabled) {
runLookupQuery({allowDiskUse: true});
assertCacheUsage(false /*multiPlanning*/,
- sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeEnabled ? 2 : 1 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline,
{allowDiskUse: true});
runLookupQuery({allowDiskUse: true});
assertCacheUsage(false /*multiPlanning*/,
- sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeEnabled ? 2 : 1 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline,
@@ -428,25 +428,25 @@ verifyCorrectLookupAlgorithmUsed("IndexedLoopJoin", avoidReplanLookupPipeline);
// Set up an active cache entry.
runLookupQuery();
assertCacheUsage(true /*multiPlanning*/,
- sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeEnabled ? 2 : 1 /* cacheEntryVersion */,
false /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline);
runLookupQuery();
assertCacheUsage(true /*multiPlanning*/,
- sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeEnabled ? 2 : 1 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline);
runLookupQuery();
assertCacheUsage(false /*multiPlanning*/,
- sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeEnabled ? 2 : 1 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline);
runLookupQuery();
assertCacheUsage(false /*multiPlanning*/,
- sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeEnabled ? 2 : 1 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline);
@@ -459,7 +459,7 @@ assertCacheUsage(false /*multiPlanning*/,
* solution.
*/
function testReplanningAndCacheInvalidationOnForeignCollSizeIncrease(singleSolution) {
- if (!sbeFullEnabled) {
+ if (!sbeEnabled) {
return;
}
@@ -552,7 +552,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 (sbeFullEnabled) {
+if (sbeEnabled) {
runLookupQuery();
const profileObj = getLatestProfilerEntry(db, {op: "command", ns: coll.getFullName()});
const matchingCacheEntries =
@@ -621,7 +621,7 @@ explain = coll.explain().aggregate(avoidReplanLookupPipeline);
groupNodes = getAggPlanStages(explain, "GROUP");
assert.eq(groupNodes.length, 0);
-if (sbeFullEnabled) {
+if (sbeEnabled) {
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 711a2676a15..16c80ea346b 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, ["featureFlagSbeFull"])) {
+if (checkSBEEnabled(db)) {
// 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/plan_cache_stats_agg_source.js b/jstests/noPassthrough/plan_cache_stats_agg_source.js
index 01bbf6a75a0..9c2777e1f04 100644
--- a/jstests/noPassthrough/plan_cache_stats_agg_source.js
+++ b/jstests/noPassthrough/plan_cache_stats_agg_source.js
@@ -16,11 +16,7 @@ assert.neq(null, conn, "mongod failed to start up");
const testDb = conn.getDB("test");
const coll = testDb.plan_cache_stats_agg_source;
-
-// Note that the "getParameter" command is expected to fail in versions of mongod that do not yet
-// include the slot-based execution engine. When that happens, however, 'isSBEEnabled' still
-// correctly evaluates to false.
-const isSBEEnabled = checkSBEEnabled(testDb, ["featureFlagSbeFull"]);
+const isSBEEnabled = checkSBEEnabled(testDb);
function makeMatchForFilteringByShape(query) {
const keyHash = getPlanCacheKeyFromShape({query: query, collection: coll, db: testDb});
diff --git a/jstests/noPassthrough/query_engine_stats.js b/jstests/noPassthrough/query_engine_stats.js
index bf0cef1f043..a505b7512a0 100644
--- a/jstests/noPassthrough/query_engine_stats.js
+++ b/jstests/noPassthrough/query_engine_stats.js
@@ -15,8 +15,8 @@ assert.neq(null, conn, "mongod was unable to start up");
let db = conn.getDB(jsTestName());
// This test assumes that SBE is being used for most queries.
-if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
- jsTestLog("Skipping test because SBE is not fully enabled");
+if (!checkSBEEnabled(db)) {
+ jsTestLog("Skipping test because SBE is not enabled");
MongoRunner.stopMongod(conn);
return;
}
diff --git a/jstests/noPassthrough/restart_index_build_if_resume_fails.js b/jstests/noPassthrough/restart_index_build_if_resume_fails.js
index 0336894febf..bcd1e3a50ce 100644
--- a/jstests/noPassthrough/restart_index_build_if_resume_fails.js
+++ b/jstests/noPassthrough/restart_index_build_if_resume_fails.js
@@ -24,9 +24,9 @@ rst.initiate();
let primary = rst.getPrimary();
let coll = primary.getDB(dbName).getCollection(collName);
-const columnstoreEnabled = checkSBEEnabled(primary.getDB(dbName),
- ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"],
- true /* checkAllNodes */) &&
+const columnstoreEnabled =
+ checkSBEEnabled(
+ primary.getDB(dbName), ["featureFlagColumnstoreIndexes"], true /* checkAllNodes */) &&
setUpServerForColumnStoreIndexTest(primary.getDB(dbName));
assert.commandWorked(coll.insert({a: 1}));
diff --git a/jstests/noPassthrough/restart_index_build_if_resume_interrupted_by_shutdown.js b/jstests/noPassthrough/restart_index_build_if_resume_interrupted_by_shutdown.js
index 0d9d4b1ff9b..46f5fd8d80a 100644
--- a/jstests/noPassthrough/restart_index_build_if_resume_interrupted_by_shutdown.js
+++ b/jstests/noPassthrough/restart_index_build_if_resume_interrupted_by_shutdown.js
@@ -25,8 +25,7 @@ rst.initiate();
let primary = rst.getPrimary();
const columnstoreEnabled =
- checkSBEEnabled(
- primary.getDB(dbName), ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"], true) &&
+ checkSBEEnabled(primary.getDB(dbName), ["featureFlagColumnstoreIndexes"], true) &&
setUpServerForColumnStoreIndexTest(primary.getDB(dbName));
ResumableIndexBuildTest.runResumeInterruptedByShutdown(
diff --git a/jstests/noPassthrough/resumable_index_build_bulk_load_phase.js b/jstests/noPassthrough/resumable_index_build_bulk_load_phase.js
index 6e24516c726..147c4e4281e 100644
--- a/jstests/noPassthrough/resumable_index_build_bulk_load_phase.js
+++ b/jstests/noPassthrough/resumable_index_build_bulk_load_phase.js
@@ -21,9 +21,8 @@ const rst = new ReplSetTest({nodes: 1});
rst.startSet();
rst.initiate();
-const columnstoreEnabled = checkSBEEnabled(rst.getPrimary().getDB(dbName),
- ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"],
- true) &&
+const columnstoreEnabled =
+ checkSBEEnabled(rst.getPrimary().getDB(dbName), ["featureFlagColumnstoreIndexes"], true) &&
setUpServerForColumnStoreIndexTest(rst.getPrimary().getDB(dbName));
const runTests = function(docs, indexSpecsFlat, collNameSuffix) {
diff --git a/jstests/noPassthrough/resumable_index_build_bulk_load_phase_large.js b/jstests/noPassthrough/resumable_index_build_bulk_load_phase_large.js
index 3c217cc272f..8cbdcb18268 100644
--- a/jstests/noPassthrough/resumable_index_build_bulk_load_phase_large.js
+++ b/jstests/noPassthrough/resumable_index_build_bulk_load_phase_large.js
@@ -23,9 +23,8 @@ const rst = new ReplSetTest(
rst.startSet();
rst.initiate();
-const columnstoreEnabled = checkSBEEnabled(rst.getPrimary().getDB(dbName),
- ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"],
- true) &&
+const columnstoreEnabled =
+ checkSBEEnabled(rst.getPrimary().getDB(dbName), ["featureFlagColumnstoreIndexes"], true) &&
setUpServerForColumnStoreIndexTest(rst.getPrimary().getDB(dbName));
// Insert enough data so that the collection scan spills to disk.
diff --git a/jstests/noPassthrough/resumable_index_build_clearing_tmp_directory_on_restart.js b/jstests/noPassthrough/resumable_index_build_clearing_tmp_directory_on_restart.js
index fb563c40cca..c94db0b2ee7 100644
--- a/jstests/noPassthrough/resumable_index_build_clearing_tmp_directory_on_restart.js
+++ b/jstests/noPassthrough/resumable_index_build_clearing_tmp_directory_on_restart.js
@@ -30,8 +30,7 @@ rst.initiate();
// Insert enough data so that the collection scan spills to disk.
const primary = rst.getPrimary();
const columnstoreEnabled =
- checkSBEEnabled(
- primary.getDB(dbName), ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"], true) &&
+ checkSBEEnabled(primary.getDB(dbName), ["featureFlagColumnstoreIndexes"], true) &&
setUpServerForColumnStoreIndexTest(primary.getDB(dbName));
const coll = primary.getDB(dbName).getCollection(jsTestName());
const bulk = coll.initializeUnorderedBulkOp();
diff --git a/jstests/noPassthrough/resumable_index_build_collection_scan_phase.js b/jstests/noPassthrough/resumable_index_build_collection_scan_phase.js
index 5186ecfe278..49ec48f5ced 100644
--- a/jstests/noPassthrough/resumable_index_build_collection_scan_phase.js
+++ b/jstests/noPassthrough/resumable_index_build_collection_scan_phase.js
@@ -22,9 +22,8 @@ const rst = new ReplSetTest({nodes: 1});
rst.startSet();
rst.initiate();
-const columnstoreEnabled = checkSBEEnabled(rst.getPrimary().getDB(dbName),
- ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"],
- true) &&
+const columnstoreEnabled =
+ checkSBEEnabled(rst.getPrimary().getDB(dbName), ["featureFlagColumnstoreIndexes"], true) &&
setUpServerForColumnStoreIndexTest(rst.getPrimary().getDB(dbName));
const runTests = function(docs, indexSpecsFlat, collNameSuffix) {
diff --git a/jstests/noPassthrough/resumable_index_build_collection_scan_phase_large.js b/jstests/noPassthrough/resumable_index_build_collection_scan_phase_large.js
index d1c498eb3eb..d1dd867cb3e 100644
--- a/jstests/noPassthrough/resumable_index_build_collection_scan_phase_large.js
+++ b/jstests/noPassthrough/resumable_index_build_collection_scan_phase_large.js
@@ -33,8 +33,7 @@ const primary = rst.getPrimary();
const coll = primary.getDB(dbName).getCollection(jsTestName());
const columnstoreEnabled =
- checkSBEEnabled(
- primary.getDB(dbName), ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"], true) &&
+ checkSBEEnabled(primary.getDB(dbName), ["featureFlagColumnstoreIndexes"], true) &&
setUpServerForColumnStoreIndexTest(primary.getDB(dbName));
const bulk = coll.initializeUnorderedBulkOp();
diff --git a/jstests/noPassthrough/resumable_index_build_drain_writes_phase_primary.js b/jstests/noPassthrough/resumable_index_build_drain_writes_phase_primary.js
index 8e6f529c8c4..52def8c8bde 100644
--- a/jstests/noPassthrough/resumable_index_build_drain_writes_phase_primary.js
+++ b/jstests/noPassthrough/resumable_index_build_drain_writes_phase_primary.js
@@ -25,8 +25,8 @@ rst.initiate();
const primary = rst.getPrimary();
const coll = primary.getDB(dbName).getCollection(collName);
-const columnstoreEnabled = checkSBEEnabled(
- primary.getDB(dbName), ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"], true);
+const columnstoreEnabled =
+ checkSBEEnabled(primary.getDB(dbName), ["featureFlagColumnstoreIndexes"], true);
assert.commandWorked(coll.insert({a: 1}));
diff --git a/jstests/noPassthrough/resumable_index_build_drain_writes_phase_secondary.js b/jstests/noPassthrough/resumable_index_build_drain_writes_phase_secondary.js
index f70971967c1..cb859855d34 100644
--- a/jstests/noPassthrough/resumable_index_build_drain_writes_phase_secondary.js
+++ b/jstests/noPassthrough/resumable_index_build_drain_writes_phase_secondary.js
@@ -33,8 +33,8 @@ rst.initiateWithHighElectionTimeout();
let primary = rst.getPrimary();
let coll = primary.getDB(dbName).getCollection(collName);
-const columnstoreEnabled = checkSBEEnabled(
- primary.getDB(dbName), ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"], true);
+const columnstoreEnabled =
+ checkSBEEnabled(primary.getDB(dbName), ["featureFlagColumnstoreIndexes"], true);
assert.commandWorked(coll.insert({a: 1}));
diff --git a/jstests/noPassthrough/resumable_index_build_initialized.js b/jstests/noPassthrough/resumable_index_build_initialized.js
index f89c0fed9a3..aa672b3260d 100644
--- a/jstests/noPassthrough/resumable_index_build_initialized.js
+++ b/jstests/noPassthrough/resumable_index_build_initialized.js
@@ -22,9 +22,8 @@ const rst = new ReplSetTest({nodes: 1});
rst.startSet();
rst.initiate();
-const columnstoreEnabled = checkSBEEnabled(rst.getPrimary().getDB(dbName),
- ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"],
- true) &&
+const columnstoreEnabled =
+ checkSBEEnabled(rst.getPrimary().getDB(dbName), ["featureFlagColumnstoreIndexes"], true) &&
setUpServerForColumnStoreIndexTest(rst.getPrimary().getDB(dbName));
const runTests = function(docs, indexSpecsFlat, collNameSuffix) {
diff --git a/jstests/noPassthrough/resumable_index_build_mixed_phases.js b/jstests/noPassthrough/resumable_index_build_mixed_phases.js
index d372e51360b..463d481d5e2 100644
--- a/jstests/noPassthrough/resumable_index_build_mixed_phases.js
+++ b/jstests/noPassthrough/resumable_index_build_mixed_phases.js
@@ -21,9 +21,8 @@ const rst = new ReplSetTest({nodes: 1});
rst.startSet();
rst.initiate();
-const columnstoreEnabled = checkSBEEnabled(rst.getPrimary().getDB(dbName),
- ["featureFlagColumnstoreIndexes", "featureFlagSbeFull"],
- true) &&
+const columnstoreEnabled =
+ checkSBEEnabled(rst.getPrimary().getDB(dbName), ["featureFlagColumnstoreIndexes"], true) &&
setUpServerForColumnStoreIndexTest(rst.getPrimary().getDB(dbName));
const runTest = function(docs, indexSpecs, failPoints, resumePhases, resumeChecks, collNameSuffix) {
diff --git a/jstests/noPassthrough/sbe_multiplanner_trial_termination.js b/jstests/noPassthrough/sbe_multiplanner_trial_termination.js
index 0fdd65ef851..a3178cd2858 100644
--- a/jstests/noPassthrough/sbe_multiplanner_trial_termination.js
+++ b/jstests/noPassthrough/sbe_multiplanner_trial_termination.js
@@ -25,8 +25,8 @@ assert.neq(conn, null, "mongod failed to start");
const db = conn.getDB(dbName);
// This test assumes that SBE is being used for most queries.
-if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
- jsTestLog("Skipping test because SBE is not fully enabled");
+if (!checkSBEEnabled(db)) {
+ jsTestLog("Skipping test because SBE is not enabled");
MongoRunner.stopMongod(conn);
return;
}
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 546d94f7e2f..09b94049c97 100644
--- a/jstests/noPassthrough/sbe_plan_cache_clear_on_param_change.js
+++ b/jstests/noPassthrough/sbe_plan_cache_clear_on_param_change.js
@@ -56,10 +56,9 @@ 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 which is enabled by
-// 'featureFlagSbeFull'.
-if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
- jsTestLog("Skipping test because SBE is not fully enabled");
+// This test is specifically verifying the behavior of the SBE plan cache.
+if (!checkSBEEnabled(db)) {
+ jsTestLog("Skipping test because SBE is not 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 e603c495d0e..0cf0546a6bd 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, ["featureFlagSbeFull"])) {
- jsTest.log("Skipping test because SBE is not fully enabled");
+if (!checkSBEEnabled(db)) {
+ jsTest.log("Skipping test because SBE is not 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 7bcdba91a34..d07a4456002 100644
--- a/jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js
+++ b/jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js
@@ -19,8 +19,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, ["featureFlagSbeFull"])) {
- jsTest.log("Skipping test because SBE is not fully enabled");
+if (!checkSBEEnabled(db)) {
+ jsTest.log("Skipping test because SBE is not 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 a0b820d10f2..1eb667754e0 100644
--- a/jstests/noPassthrough/sbe_plan_cache_size_metric.js
+++ b/jstests/noPassthrough/sbe_plan_cache_size_metric.js
@@ -23,8 +23,8 @@ 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");
+if (!checkSBEEnabled(db)) {
+ jsTest.log("Skipping test because SBE is not enabled");
MongoRunner.stopMongod(conn);
return;
}
diff --git a/jstests/noPassthrough/server_status_multiplanner.js b/jstests/noPassthrough/server_status_multiplanner.js
index 580bc736daa..db4c528f031 100644
--- a/jstests/noPassthrough/server_status_multiplanner.js
+++ b/jstests/noPassthrough/server_status_multiplanner.js
@@ -24,8 +24,8 @@ assert.neq(conn, null, "mongod failed to start");
const db = conn.getDB(dbName);
// This test assumes that SBE is being used for most queries.
-if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
- jsTestLog("Skipping test because SBE is not fully enabled");
+if (!checkSBEEnabled(db)) {
+ jsTestLog("Skipping test because SBE is not enabled");
MongoRunner.stopMongod(conn);
return;
}
diff --git a/jstests/noPassthroughWithMongod/columnstore_planning_heuristics.js b/jstests/noPassthroughWithMongod/columnstore_planning_heuristics.js
index 8bf80294e61..386ae3d57ad 100644
--- a/jstests/noPassthroughWithMongod/columnstore_planning_heuristics.js
+++ b/jstests/noPassthroughWithMongod/columnstore_planning_heuristics.js
@@ -2,9 +2,8 @@
* Testing of the query planner heuristics for determining whether a collection is eligible for
* column scan.
* @tags: [
- * # column store indexes are still under a feature flag and require full sbe
- * featureFlagColumnstoreIndexes,
- * featureFlagSbeFull
+ * # column store indexes are still under a feature flag
+ * featureFlagColumnstoreIndexes
* ]
*/
(function() {
diff --git a/jstests/noPassthroughWithMongod/group_pushdown.js b/jstests/noPassthroughWithMongod/group_pushdown.js
index fe11f9f8def..63bbc29de15 100644
--- a/jstests/noPassthroughWithMongod/group_pushdown.js
+++ b/jstests/noPassthroughWithMongod/group_pushdown.js
@@ -8,7 +8,7 @@ load("jstests/libs/analyze_plan.js");
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
if (!checkSBEEnabled(db)) {
- jsTestLog("Skipping test because the sbe group pushdown feature flag is disabled");
+ jsTestLog("Skipping test because SBE is not enabled");
return;
}
@@ -185,28 +185,38 @@ assertResultsMatchWithAndWithoutPushdown(
],
1);
-// The $group stage refers to two existing sub-fields.
-assertResultsMatchWithAndWithoutPushdown(
- coll,
- [
- {$project: {item: 1, price: 1, quantity: 1, dateParts: {$dateToParts: {date: "$date"}}}},
- {
- $group: {
- _id: "$item",
- hs: {$sum: {$add: ["$dateParts.hour", "$dateParts.hour", "$dateParts.minute"]}}
- }
- },
- ],
- [{"_id": "a", "hs": 39}, {"_id": "b", "hs": 34}, {"_id": "c", "hs": 23}],
- 1);
-
-// The $group stage refers to a non-existing sub-field twice.
-assertResultsMatchWithAndWithoutPushdown(
- coll,
- [{$group: {_id: "$item", hs: {$sum: {$add: ["$date.hour", "$date.hour"]}}}}],
- [{"_id": "a", "hs": 0}, {"_id": "b", "hs": 0}, {"_id": "c", "hs": 0}],
- 1);
-
+// Computed projections are only eligible for pushdown into SBE when SBE is fully enabled.
+// Additionally, $group stages with dotted fields may only be eligible for pushdown when SBE is
+// fully enabled as dependancy analysis may produce a dotted projection, which are not currently
+// supported in mainline SBE.
+const sbeFull = checkSBEEnabled(db, ["featureFlagSbeFull"]);
+if (sbeFull) {
+ // The $group stage refers to two existing sub-fields.
+ assertResultsMatchWithAndWithoutPushdown(
+ coll,
+ [
+ {
+ $project:
+ {item: 1, price: 1, quantity: 1, dateParts: {$dateToParts: {date: "$date"}}}
+ },
+ {
+ $group: {
+ _id: "$item",
+ hs: {$sum:
+ {$add: ["$dateParts.hour", "$dateParts.hour", "$dateParts.minute"]}}
+ }
+ },
+ ],
+ [{"_id": "a", "hs": 39}, {"_id": "b", "hs": 34}, {"_id": "c", "hs": 23}],
+ 1);
+
+ // The $group stage refers to a non-existing sub-field twice.
+ assertResultsMatchWithAndWithoutPushdown(
+ coll,
+ [{$group: {_id: "$item", hs: {$sum: {$add: ["$date.hour", "$date.hour"]}}}}],
+ [{"_id": "a", "hs": 0}, {"_id": "b", "hs": 0}, {"_id": "c", "hs": 0}],
+ 1);
+}
// Two group stages both get pushed down and the second $group stage refers to only existing
// top-level fields of the first $group. The field name may be one of "result" / "recordId" /
// "returnKey" / "snapshotId" / "indexId" / "indexKey" / "indexKeyPattern" which are reserved names
diff --git a/jstests/noPassthroughWithMongod/index_bounds_static_limit.js b/jstests/noPassthroughWithMongod/index_bounds_static_limit.js
index dc183a27346..616ddcf2a93 100644
--- a/jstests/noPassthroughWithMongod/index_bounds_static_limit.js
+++ b/jstests/noPassthroughWithMongod/index_bounds_static_limit.js
@@ -9,8 +9,8 @@
load("jstests/libs/analyze_plan.js"); // For explain helpers.
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
- jsTest.log("Skipping test because SBE is not fully enabled");
+if (!checkSBEEnabled(db)) {
+ jsTest.log("Skipping test because SBE is not enabled");
return;
}
diff --git a/jstests/noPassthroughWithMongod/ne_array_indexability.js b/jstests/noPassthroughWithMongod/ne_array_indexability.js
index f2ecb27151f..e632e5fc1b6 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, ["featureFlagSbeFull"])) {
+ if (checkSBEEnabled(db)) {
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 e17a81cb660..d293413f0fc 100644
--- a/jstests/noPassthroughWithMongod/plan_cache_replanning.js
+++ b/jstests/noPassthroughWithMongod/plan_cache_replanning.js
@@ -10,7 +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 isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
+const isSbeEnabled = checkSBEEnabled(db);
let coll = assertDropAndRecreateCollection(db, "plan_cache_replanning");
diff --git a/jstests/noPassthroughWithMongod/sbe_query_eligibility.js b/jstests/noPassthroughWithMongod/sbe_query_eligibility.js
new file mode 100644
index 00000000000..f9bc9fcb181
--- /dev/null
+++ b/jstests/noPassthroughWithMongod/sbe_query_eligibility.js
@@ -0,0 +1,192 @@
+/**
+ * Test that verifies which query shapes which are eligible for SBE.
+ */
+(function() {
+"use strict";
+
+load("jstests/libs/analyze_plan.js");
+load("jstests/libs/sbe_util.js"); // For 'checkSBEEnabled'.
+
+/**
+ * Utility which asserts whether, when aggregating over 'collection' with 'pipeline', whether
+ * explain reports that SBE or classic was used, based on the value of 'isSBE'.
+ */
+function assertEngineUsed(collection, pipeline, isSBE) {
+ const explain = collection.explain().aggregate(pipeline);
+ const expectedExplainVersion = isSBE ? "2" : "1";
+ assert(explain.hasOwnProperty("explainVersion"), explain);
+ assert.eq(explain.explainVersion, expectedExplainVersion, explain);
+}
+
+if (!checkSBEEnabled(db)) {
+ jsTestLog("Skipping test because SBE is disabled");
+ return;
+}
+
+const collName = "sbe_eligiblity";
+const coll = db[collName];
+coll.drop();
+assert.commandWorked(coll.insert({}));
+assert.eq(coll.find().itcount(), 1);
+
+// Simple eligible cases.
+const expectedSbeCases = [
+ // Non-$expr match filters.
+ [{$match: {a: 1}}],
+ [{$match: {"a.b.c": 1}}],
+
+ // Top level projections.
+ [{$project: {a: 1, b: 1}}],
+ [{$project: {a: 0, b: 0}}],
+
+ // Sorts with no common prefixes.
+ [{$sort: {a: 1}}],
+ [{$sort: {"a.b.c": 1}}],
+
+ // Test a combination of the above categories.
+ [{$match: {a: 1}}, {$sort: {b: 1}}],
+ [{$match: {a: 1}}, {$sort: {b: 1, c: 1}}],
+ [{$match: {a: 1}}, {$project: {b: 1, c: 1}}, {$sort: {b: 1, c: 1}}],
+ [
+ {$match: {a: 1, b: 1, "c.d.e": {$mod: [2, 0]}}},
+ {$project: {b: 1, c: 1}},
+ {$sort: {b: 1, c: 1}}
+ ],
+
+ // $lookup and $group should work as expected.
+ [
+ {$match: {a: 1}},
+ {$project: {a: 1}},
+ {$lookup: {from: collName, localField: "a", foreignField: "a", as: "out"}}
+ ],
+ [{$match: {a: 1}}, {$project: {a: 1}}, {$group: {_id: "$a", out: {$sum: 1}}}],
+
+ // If we have a non-SBE compatible expression after the pushdown boundary, this should not
+ // inhibit the pushdown of the pipeline prefix into SBE.
+ [
+ {$match: {a: 1}},
+ {$project: {a: 1}},
+ {$lookup: {from: collName, localField: "a", foreignField: "a", as: "out"}},
+ {$addFields: {foo: {$sum: "$a"}}},
+ {$match: {$expr: {$eq: ["$a", "$b"]}}}
+ ],
+ [
+ {$match: {a: 1}},
+ {$project: {a: 1}},
+ {$group: {_id: "$a", out: {$sum: 1}}},
+ {$match: {$expr: {$eq: ["$a", "$b"]}}}
+ ],
+];
+
+for (const pipeline of expectedSbeCases) {
+ assertEngineUsed(coll, pipeline, true /* isSBE */);
+}
+
+// The cases below are expected to use SBE only if 'featureFlagSbeFull' is on.
+const isSbeFullyEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
+const sbeFullCases = [
+ // Match filters with $expr.
+ [{$match: {$expr: {$eq: ["$a", "$b"]}}}],
+ [{$match: {$and: [{$expr: {$eq: ["$a", "$b"]}}, {c: 1}]}}],
+
+ // Dotted projections.
+ [{$project: {"a.b": 1}}],
+ [{$project: {"a.b": 0}}],
+ [{$project: {"a.b": 1, "a.c": 1}}],
+ [{$project: {"a.b.c.d.e.f.g": 0, "h.i.j.k": 0}}],
+
+ // Computed projections.
+ [{$project: {a: {$add: ["$foo", "$bar"]}}}],
+ [{$project: {a: {$divide: ["$foo", "$bar"]}}}],
+
+ // Sorts with common prefixes.
+ [{$sort: {"a.b": 1, "a.c": 1}}],
+ [{$sort: {"a.b.f.g": 1, "a.d.e.f": 1}}],
+ [{$sort: {"a": 1, "b": 1, "c.d": 1, "c.f": 1}}],
+
+ // Mix SBE-eligible and non-SBE eligible filters, projections and sorts.
+
+ // Match filters with $expr should inhibit pushdown.
+ [{$project: {a: 1, b: 1}}, {$match: {$expr: {$eq: ["$a", "$b"]}}}],
+ [{$match: {$and: [{$expr: {$eq: ["$a", "$b"]}}, {c: 1}]}}, {$sort: {a: 1, d: 1}}],
+ [
+ {$match: {$and: [{$expr: {$eq: ["$a", "$b"]}}, {c: 1}]}},
+ {
+ $lookup:
+ {from: collName, localField: "c_custkey", foreignField: "o_custkey", as: "custsale"}
+ }
+ ],
+
+ // Dotted projections should inhibit pushdown.
+ [{$match: {d: 1}}, {$project: {"a.b": 1}}],
+ [{$sort: {d: 1, e: 1}}, {$project: {"a.b": 0}}],
+ [{$match: {$or: [{a: {$gt: 0}}, {b: {$gt: 0}}]}}, {$project: {"d.a": 1}}],
+
+ [
+ {$project: {"a.b": 1, "a.d": 1}},
+ {$lookup: {from: collName, localField: "a", foreignField: "a", as: "out"}},
+ ],
+
+ // Computed projections should inhibit pushdown.
+ [{$match: {foo: {$gt: 0}}}, {$project: {a: {$add: ["$foo", "$bar"]}}}],
+ [{$project: {a: {$add: ["$foo", "$bar"]}}}, {$sort: {a: 1}}],
+ [
+ {$project: {a: {$add: ["$foo", "$bar"]}}},
+ {$group: {_id: "$a", "ct": {$sum: 1}}},
+ ],
+ [
+ {$project: {a: {$add: ["$out", 1]}}},
+ {$lookup: {from: collName, localField: "a", foreignField: "a", as: "out"}},
+ ],
+
+ // Sorts with common prefixes should inhibit pushdown.
+ [{$match: {foo: {$gt: 0}}}, {$sort: {"a.b": 1, "a.c": 1}}],
+ [{$sort: {"a.b.f.g": 1, "a.d.e.f": 1}}, {$project: {a: 1}}],
+ [{$match: {$or: [{a: {$gt: 0}}, {b: {$gt: 0}}]}}, {$sort: {"d.a": 1, "d.b": 1}}],
+ [
+ {$sort: {"a.b": 1, "a.c": 1}},
+ {$group: {_id: {a: "$foo", b: "$bar"}, "a": {$sum: 1}}},
+ ],
+ [
+ {$sort: {"b.c": 1, "b.d": 1}},
+ {$lookup: {from: collName, localField: "a", foreignField: "a", as: "out"}},
+ ],
+
+ // TPC-H query whose $lookup is SBE compatible, but which features a $match which uses $expr.
+ // Note that $match will be pushed to the front of the pipeline.
+ [
+ {
+ $lookup:
+ {from: collName, localField: "c_custkey", foreignField: "o_custkey", as: "custsale"}
+ },
+ {$addFields: {cntrycode: {$substr: ["$c_phone", 0, 2]}, custsale: {$size: "$custsale"}}},
+ {
+ $match: {
+ $and: [
+ {
+ $expr: {
+ $in: [
+ "$cntrycode",
+ [
+ {$toString: "13"},
+ {$toString: "31"},
+ {$toString: "23"},
+ {$toString: "29"},
+ {$toString: "30"},
+ {$toString: "18"},
+ {$toString: "17"}
+ ]
+ ]
+ }
+ },
+ {$expr: {$gt: ["$c_acctbal", 0.00]}}
+ ]
+ }
+ }
+ ],
+];
+
+for (const pipeline of sbeFullCases) {
+ assertEngineUsed(coll, pipeline, isSbeFullyEnabled /* isSBE */);
+}
+})();
diff --git a/jstests/sharding/invalidate_plan_cache_entries_when_collection_generation_changes.js b/jstests/sharding/invalidate_plan_cache_entries_when_collection_generation_changes.js
index 6aafb4c44ae..ffc349fa76b 100644
--- a/jstests/sharding/invalidate_plan_cache_entries_when_collection_generation_changes.js
+++ b/jstests/sharding/invalidate_plan_cache_entries_when_collection_generation_changes.js
@@ -1,6 +1,11 @@
/**
* Tests that plan cache entries are deleted after shard key refining, resharding and renaming
* operations.
+ *
+ * @tags: [
+ * # The SBE plan cache was enabled by default in 6.3.
+ * requires_fcv_63,
+ * ]
*/
// Cannot run the filtering metadata check on tests that run refineCollectionShardKey.
@@ -28,7 +33,7 @@ const db = st.getDB(dbName);
const collA = db["collA"];
const collB = db["collB"];
-if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
+if (!checkSBEEnabled(db)) {
jsTestLog("********** Skip the test because SBE is disabled **********");
st.stop();
return;
diff --git a/jstests/sharding/sbe_plan_cache_does_not_block_range_deletion.js b/jstests/sharding/sbe_plan_cache_does_not_block_range_deletion.js
index e48b23ccf44..b117f7b3e69 100644
--- a/jstests/sharding/sbe_plan_cache_does_not_block_range_deletion.js
+++ b/jstests/sharding/sbe_plan_cache_does_not_block_range_deletion.js
@@ -24,7 +24,7 @@ const st = new ShardingTest({mongos: 1, config: 1, shards: 2});
assert.commandWorked(st.s.adminCommand({enableSharding: dbName}));
st.ensurePrimaryShard(dbName, st.shard0.shardName);
-const isSbeFullyEnabled = checkSBEEnabled(st.s.getDB(dbName), ["featureFlagSbeFull"]);
+const isSBEEnabled = checkSBEEnabled(st.s.getDB(dbName));
const coll = st.s.getDB(dbName)[collName];
@@ -67,9 +67,9 @@ function runTest({indexes, document, filter}) {
});
}
-// Scenario with just one available indexed plan. If SBE is fully enabled, then the SBE plan cache
-// is in use and we expect a pinned plan cache entry.
-if (isSbeFullyEnabled) {
+// Scenario with just one available indexed plan. If SBE is enabled, then the SBE plan cache is in
+// use and we expect a pinned plan cache entry.
+if (isSBEEnabled) {
runTest({indexes: [{a: 1}], document: {_id: 0, a: "abc"}, filter: {a: "abc"}});
}
@@ -83,8 +83,8 @@ runTest({
// Test a rooted $or query. This should use the subplanner. The way that the subplanner interacts
// with the plan cache differs between the classic engine and SBE. In the classic engine, the plan
// for each branch is cached independently, whereas in SBE we cache the entire "composite" plan.
-// This test is written to expect the SBE behavior, so it only runs when SBE is fully enabled.
-if (isSbeFullyEnabled) {
+// This test is written to expect the SBE behavior, so it only runs when SBE is enabled.
+if (isSBEEnabled) {
runTest({
indexes: [{a: 1}, {b: 1}, {c: 1}, {d: 1}],
document: {_id: 0, a: "abc", b: "123", c: 4, d: 5},