summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buildscripts/resmokeconfig/suites/cqf_passthrough.yml110
-rw-r--r--etc/evergreen.yml4
-rw-r--r--etc/evergreen_yml_components/definitions.yml7
-rw-r--r--src/mongo/db/commands/cqf/cqf_command_utils.cpp90
-rw-r--r--src/mongo/db/commands/cqf/cqf_command_utils.h3
-rw-r--r--src/mongo/db/commands/find_cmd.cpp8
-rw-r--r--src/mongo/db/query/projection_ast_visitor.h9
7 files changed, 184 insertions, 47 deletions
diff --git a/buildscripts/resmokeconfig/suites/cqf_passthrough.yml b/buildscripts/resmokeconfig/suites/cqf_passthrough.yml
new file mode 100644
index 00000000000..48a26dfeee7
--- /dev/null
+++ b/buildscripts/resmokeconfig/suites/cqf_passthrough.yml
@@ -0,0 +1,110 @@
+test_kind: js_test
+
+selector:
+ roots:
+ - jstests/core/**/*.js
+ exclude_files:
+ # TODO SERVER-67427 Fix conjunctions over an array field.
+ - jstests/core/all2.js
+ - jstests/core/index_check2.js
+ - jstests/core/or5.js
+ # TODO SERVER-67369 enable once full type bracketing is supported.
+ - jstests/core/array_comparison_correctness.js
+ - jstests/core/arrayfind10.js
+ - jstests/core/arrayfind3.js
+ - jstests/core/date2.js
+ - jstests/core/expressions_matching_whole_array.js
+ - jstests/core/index_decimal.js
+ - jstests/core/min_max_key.js
+ - jstests/core/nan.js
+ # TODO SERVER-67506
+ - jstests/core/arrayfind5.js
+ - jstests/core/arrayfind8.js
+ # TODO SERVER-67371 These tests all use unsupported command options.
+ - jstests/core/batch_size.js
+ - jstests/core/find_getmore_cmd.js
+ - jstests/core/finda.js
+ - jstests/core/idhack.js
+ - jstests/core/index_diag.js
+ - jstests/core/kill_cursors.js
+ - jstests/core/minmax.js
+ - jstests/core/show_record_id.js
+ # TODO SERVER-67510
+ - jstests/core/collation_with_reverse_index.js
+ - jstests/core/find_covered_projection.js
+ # TODO SERVER-67548 Fix equality to null with indexes.
+ - jstests/core/cover_null_queries.js
+ - jstests/core/null_query_semantics.js
+ # TODO SERVER-62407 translate to ABT directly from find.
+ - jstests/core/currentop_cursors.js
+ - jstests/core/profile_getmore.js
+ # TODO SERVER-67503
+ - jstests/core/elemmatch_object.js
+ # TODO SERVER-67517
+ - jstests/core/field_name_empty.js
+ - jstests/core/field_name_validation.js
+ # TODO SERVER-67638
+ - jstests/core/grow_hash_table.js
+ - jstests/core/profile2.js
+ # TODO SERVER-67639
+ - jstests/core/index_stats.js
+ # TODO SERVER-67640
+ - jstests/core/operation_latency_histogram.js
+ - jstests/core/top.js
+ # TODO SERVER-64007 Enable yielding for plans generated from bonsai.
+ - jstests/core/ord.js
+ # TODO SERVER-67607
+ - jstests/core/cached_plan_trial_does_not_discard_work.js
+ - jstests/core/index_filter_commands_invalidate_plan_cache_entries.js
+ - jstests/core/plan_cache_clear.js
+ - jstests/core/plan_cache_list_shapes.js
+ - jstests/core/plan_cache_list_plans.js
+ - jstests/core/plan_cache_sbe.js
+ - jstests/core/plan_cache_shell_helpers.js
+ - jstests/core/plan_cache_stats_shard_and_host.js
+ - jstests/core/profile_query_hash.js
+ - jstests/core/sbe/plan_cache_sbe_with_or_queries.js
+ - jstests/core/sbe_plan_cache_autoparameterize_collscan.js
+ # TODO SERVER-67596 Allow reads to system.js collection.
+ - jstests/core/where_system_js.js
+ - jstests/core/find_and_modify_concurrent_update.js
+ - jstests/core/find_and_modify_where.js
+ # TODO SERVER-67637 Verify projection and sort for find command.
+ - jstests/core/plan_cache_positional_projection.js
+ - jstests/core/projection_meta_index_key.js
+ - jstests/core/positional_projection.js
+ - jstests/core/positional_projection_multiple_array_fields.js
+ - jstests/core/elemmatch_projection.js
+ - jstests/core/slice1.js
+ - jstests/core/explain_sort_type.js
+ - jstests/core/sortl.js
+ - jstests/core/index_filter_commands.js
+ - jstests/core/introspect_hidden_index_plan_cache_entries.js
+ # Transactions are not supported on MongoDB standalone nodes, so we do not run these tests in the
+ # 'core' suite. Instead we run them against a 1-node replica set in the 'core_txns' suite.
+ - jstests/core/txns/**/*.js
+
+executor:
+ archive:
+ hooks:
+ - ValidateCollections
+ config:
+ shell_options:
+ crashOnInvalidBSONError: ""
+ objcheck: ""
+ eval: load("jstests/libs/override_methods/detect_spawning_own_mongod.js");
+ hooks:
+ - class: ValidateCollections
+ shell_options:
+ global_vars:
+ TestData:
+ skipValidationOnNamespaceNotFound: false
+ - class: CleanEveryN
+ n: 20
+ fixture:
+ class: MongoDFixture
+ mongod_options:
+ set_parameters:
+ enableTestCommands: 1
+ featureFlagCommonQueryFramework: true
+ internalQueryEnableCascadesOptimizer: true
diff --git a/etc/evergreen.yml b/etc/evergreen.yml
index c04cbfea612..6de39718d11 100644
--- a/etc/evergreen.yml
+++ b/etc/evergreen.yml
@@ -875,6 +875,7 @@ buildvariants:
external_auth_jobs_max: 1
tasks:
- name: cqf
+ - name: cqf_passthrough
- name: cqf_parallel
- name: compile_and_archive_dist_test_then_package_TG
distros:
@@ -1419,6 +1420,7 @@ buildvariants:
--excludeWithAnyTags=incompatible_with_shard_merge
tasks: &enterprise-rhel-80-64-bit-dynamic-all-feature-flags-tasks
- name: cqf
+ - name: cqf_passthrough
- name: cqf_parallel
- name: compile_test_and_package_parallel_core_stream_TG
distros:
@@ -2214,6 +2216,7 @@ buildvariants:
separate_debug: off
tasks:
- name: cqf
+ - name: cqf_passthrough
- name: cqf_parallel
- name: compile_and_archive_dist_test_then_package_TG
- name: .aggregation
@@ -2371,6 +2374,7 @@ buildvariants:
large_distro_name: rhel80-build
tasks:
- name: cqf
+ - name: cqf_passthrough
- name: cqf_parallel
- name: compile_and_archive_dist_test_then_package_TG
- name: .aggregation
diff --git a/etc/evergreen_yml_components/definitions.yml b/etc/evergreen_yml_components/definitions.yml
index e0815b99ee5..469a01e22b0 100644
--- a/etc/evergreen_yml_components/definitions.yml
+++ b/etc/evergreen_yml_components/definitions.yml
@@ -7298,6 +7298,13 @@ tasks:
- func: "run tests"
- <<: *task_template
+ name: cqf_passthrough
+ tags: []
+ commands:
+ - func: "do setup"
+ - func: "run tests"
+
+- <<: *task_template
name: cqf_parallel
tags: []
commands:
diff --git a/src/mongo/db/commands/cqf/cqf_command_utils.cpp b/src/mongo/db/commands/cqf/cqf_command_utils.cpp
index a247427a4a8..57ebaf223a5 100644
--- a/src/mongo/db/commands/cqf/cqf_command_utils.cpp
+++ b/src/mongo/db/commands/cqf/cqf_command_utils.cpp
@@ -366,18 +366,32 @@ public:
ABTTransformerVisitor(bool& eligible) : _eligible(eligible) {}
void visit(const projection_executor::ExclusionProjectionExecutor* transformer) override {
- std::set<std::string> preservedPaths;
- transformer->getRoot()->reportProjectedPaths(&preservedPaths);
-
- for (const std::string& path : preservedPaths) {
- if (FieldRef(path).hasNumericPathComponents()) {
- unsupportedTransformer(transformer);
- return;
- }
- }
+ checkUnsupportedInclusionExclusion(transformer);
}
void visit(const projection_executor::InclusionProjectionExecutor* transformer) override {
+ checkUnsupportedInclusionExclusion(transformer);
+ }
+
+ void visit(const projection_executor::AddFieldsProjectionExecutor* transformer) override {
+ unsupportedTransformer(transformer);
+ }
+
+ void visit(const GroupFromFirstDocumentTransformation* transformer) override {
+ unsupportedTransformer(transformer);
+ }
+
+ void visit(const ReplaceRootTransformation* transformer) override {
+ unsupportedTransformer(transformer);
+ }
+
+private:
+ void unsupportedTransformer(const TransformerInterface* transformer) {
+ _eligible = false;
+ }
+
+ template <typename T>
+ void checkUnsupportedInclusionExclusion(const T* transformer) {
std::set<std::string> computedPaths;
StringMap<std::string> renamedPaths;
transformer->getRoot()->reportComputedPaths(&computedPaths, &renamedPaths);
@@ -399,23 +413,6 @@ public:
}
}
- void visit(const projection_executor::AddFieldsProjectionExecutor* transformer) override {
- unsupportedTransformer(transformer);
- }
-
- void visit(const GroupFromFirstDocumentTransformation* transformer) override {
- unsupportedTransformer(transformer);
- }
-
- void visit(const ReplaceRootTransformation* transformer) override {
- unsupportedTransformer(transformer);
- }
-
-private:
- void unsupportedTransformer(const TransformerInterface* transformer) const {
- _eligible = false;
- }
-
bool& _eligible;
};
@@ -627,7 +624,8 @@ bool isEligibleCommon(const RequestType& request,
return false;
}();
- return !unsupportedCmdOption && !unsupportedIndexType && !unsupportedCollectionType;
+ return !unsupportedCmdOption && !unsupportedIndexType && !unsupportedCollectionType &&
+ !storageGlobalParams.noTableScan.load();
}
boost::optional<bool> shouldForceBonsai() {
@@ -665,32 +663,52 @@ bool isEligibleForBonsai(const AggregateCommandRequest& request,
bool commandOptionsEligible = isEligibleCommon(request, opCtx, collection) &&
!request.getUnwrappedReadPref() && !request.getRequestReshardingResumeToken().has_value() &&
- !request.getExchange();
+ !request.getExchange() && !request.getExplain();
+
+ // Early return to avoid unnecessary work of walking the input pipeline.
+ if (!commandOptionsEligible) {
+ return false;
+ }
ABTUnsupportedDocumentSourceVisitor visitor;
DocumentSourceWalker walker(nullptr /*preVisitor*/, &visitor);
- walker.walk(pipeline);
- bool eligiblePipeline = visitor.eligible;
- return commandOptionsEligible && eligiblePipeline;
+ // The rudimentary walker may throw if it reaches a stage that it isn't aware about, so catch it
+ // here and return ineligible.
+ // TODO SERVER-62027 this should no longer be needed once all stages require a visit.
+ try {
+ walker.walk(pipeline);
+ } catch (DBException&) {
+ visitor.eligible = false;
+ }
+
+ return visitor.eligible;
}
-bool isEligibleForBonsai(const FindCommandRequest& request,
- const MatchExpression& expression,
+bool isEligibleForBonsai(const CanonicalQuery& cq,
OperationContext* opCtx,
const CollectionPtr& collection) {
if (auto forceBonsai = shouldForceBonsai(); forceBonsai.has_value()) {
return *forceBonsai;
}
- bool commandOptionsEligible = isEligibleCommon(request, opCtx, collection);
+ auto request = cq.getFindCommandRequest();
+ auto expression = cq.root();
+ bool commandOptionsEligible = isEligibleCommon(request, opCtx, collection) &&
+ !cq.getExplain() && !request.getReturnKey() && !request.getSingleBatch() &&
+ !request.getTailable();
+
+ // Early return to avoid unnecessary work of walking the input expression.
+ if (!commandOptionsEligible) {
+ return false;
+ }
bool eligibleMatch = true;
ABTMatchExpressionVisitor visitor(eligibleMatch);
MatchExpressionWalker walker(nullptr /*preVisitor*/, nullptr /*inVisitor*/, &visitor);
- tree_walker::walk<true, MatchExpression>(&expression, &walker);
+ tree_walker::walk<true, MatchExpression>(expression, &walker);
- return commandOptionsEligible && eligibleMatch;
+ return eligibleMatch;
}
} // namespace mongo
diff --git a/src/mongo/db/commands/cqf/cqf_command_utils.h b/src/mongo/db/commands/cqf/cqf_command_utils.h
index dcf685d73f1..4ceb333d364 100644
--- a/src/mongo/db/commands/cqf/cqf_command_utils.h
+++ b/src/mongo/db/commands/cqf/cqf_command_utils.h
@@ -72,8 +72,7 @@ bool isEligibleForBonsai(const AggregateCommandRequest& request,
/**
* Returns whether the given find command is eligible to use the bonsai optimizer.
*/
-bool isEligibleForBonsai(const FindCommandRequest& request,
- const MatchExpression& expression,
+bool isEligibleForBonsai(const CanonicalQuery& cq,
OperationContext* opCtx,
const CollectionPtr& collection);
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index f2be7b56ad6..a33679be303 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -306,9 +306,7 @@ public:
// If we are running a query against a view, or if we are trying to test the new
// optimizer, redirect this query through the aggregation system.
- if (ctx->getView() ||
- isEligibleForBonsai(
- cq->getFindCommandRequest(), *cq->root(), opCtx, ctx->getCollection())) {
+ if (ctx->getView() || isEligibleForBonsai(*cq, opCtx, ctx->getCollection())) {
// Relinquish locks. The aggregation command will re-acquire them.
ctx.reset();
@@ -511,9 +509,7 @@ public:
// If we are running a query against a view, or if we are trying to test the new
// optimizer, redirect this query through the aggregation system.
- if (ctx->getView() ||
- isEligibleForBonsai(
- cq->getFindCommandRequest(), *cq->root(), opCtx, ctx->getCollection())) {
+ if (ctx->getView() || isEligibleForBonsai(*cq, opCtx, ctx->getCollection())) {
// Relinquish locks. The aggregation command will re-acquire them.
ctx.reset();
diff --git a/src/mongo/db/query/projection_ast_visitor.h b/src/mongo/db/query/projection_ast_visitor.h
index b765973faf9..d3c14785e84 100644
--- a/src/mongo/db/query/projection_ast_visitor.h
+++ b/src/mongo/db/query/projection_ast_visitor.h
@@ -76,15 +76,18 @@ public:
: _preVisitor{preVisitor}, _inVisitor{inVisitor}, _postVisitor{postVisitor} {}
void preVisit(ASTNodePtr node) {
- node->acceptVisitor(_preVisitor);
+ if (_preVisitor)
+ node->acceptVisitor(_preVisitor);
}
void postVisit(ASTNodePtr node) {
- node->acceptVisitor(_postVisitor);
+ if (_postVisitor)
+ node->acceptVisitor(_postVisitor);
}
void inVisit(long count, ASTNodePtr node) {
- node->acceptVisitor(_inVisitor);
+ if (_inVisitor)
+ node->acceptVisitor(_inVisitor);
}
private: