diff options
-rw-r--r-- | buildscripts/resmokeconfig/suites/cqf_passthrough.yml | 110 | ||||
-rw-r--r-- | etc/evergreen.yml | 4 | ||||
-rw-r--r-- | etc/evergreen_yml_components/definitions.yml | 7 | ||||
-rw-r--r-- | src/mongo/db/commands/cqf/cqf_command_utils.cpp | 90 | ||||
-rw-r--r-- | src/mongo/db/commands/cqf/cqf_command_utils.h | 3 | ||||
-rw-r--r-- | src/mongo/db/commands/find_cmd.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/query/projection_ast_visitor.h | 9 |
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: |