GCC Code Coverage Report


Directory: ./
File: src/mongo/db/pipeline/abt/projection_ast_visitor.cpp
Date: 2022-10-04 12:39:21
Exec Total Coverage
Lines: 53 62 85.5%
Branches: 0 0 -%

Line Branch Exec Source
1 /**
2 * Copyright (C) 2022-present MongoDB, Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the Server Side Public License, version 1,
6 * as published by MongoDB, Inc.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * Server Side Public License for more details.
12 *
13 * You should have received a copy of the Server Side Public License
14 * along with this program. If not, see
15 * <http://www.mongodb.com/licensing/server-side-public-license>.
16 *
17 * As a special exception, the copyright holders give permission to link the
18 * code of portions of this program with the OpenSSL library under certain
19 * conditions as described in each individual source file and distribute
20 * linked combinations including the program with the OpenSSL library. You
21 * must comply with the Server Side Public License in all respects for
22 * all of the code used other than as permitted herein. If you modify file(s)
23 * with this exception, you may extend this exception to your version of the
24 * file(s), but you are not obligated to do so. If you do not wish to do so,
25 * delete this exception statement from your version. If you delete this
26 * exception statement from all source files in the program, then also delete
27 * it in the license file.
28 */
29
30 #include "mongo/db/pipeline/abt/projection_ast_visitor.h"
31
32 #include "mongo/db/pipeline/abt/agg_expression_visitor.h"
33 #include "mongo/db/pipeline/abt/utils.h"
34 #include "mongo/db/query/projection_ast_path_tracking_visitor.h"
35
36 namespace mongo::optimizer {
37
38 class ProjectionPreVisitor final : public projection_ast::ProjectionASTConstVisitor {
39 public:
40 4620 ProjectionPreVisitor(projection_ast::PathTrackingVisitorContext<>* context,
41 bool isInclusion,
42 const ProjectionName& rootProjName,
43 const ProjectionName& scanProjName)
44 4620 : _context{context},
45 4620 _builder(rootProjName, rootProjName == scanProjName),
46 4620 _isInclusion(isInclusion) {
47 4620 invariant(_context);
48 4620 }
49
50 void visit(const projection_ast::ProjectionPositionalASTNode* node) final {
51 unsupportedProjectionType("ProjectionPositionalASTNode");
52 }
53
54 void visit(const projection_ast::ProjectionSliceASTNode* node) final {
55 unsupportedProjectionType("ProjectionSliceASTNode");
56 }
57
58 void visit(const projection_ast::ProjectionElemMatchASTNode* node) final {
59 unsupportedProjectionType("ProjectionElemMatchASTNode");
60 }
61
62 108 void visit(const projection_ast::ExpressionASTNode* node) final {
63 216 unsupportedProjectionType("ExpressionASTNode");
64 }
65
66 68544 void visit(const projection_ast::BooleanConstantASTNode* node) final {
67 68544 const auto& path = _context->fullPath();
68 68544 if (_isInclusion) {
69 67824 const auto isIdField = path == "_id";
70 // If current field is _id and _id : 0, then don't include it.
71 67824 if (isIdField && !node->value()) {
72 3162 return;
73 }
74 // In inclusion projection only _id field can be excluded, make sure this is the case.
75 64662 tassert(
76 6684601, "In inclusion projection only _id field can be excluded", node->value());
77 64662 builderIntegrateInclusion(path.fullPath());
78 } else {
79 720 builderIntegrateExclusion(path.fullPath());
80 }
81 }
82
83 6276 void visit(const projection_ast::ProjectionPathASTNode* node) final {}
84 void visit(const projection_ast::MatchExpressionASTNode* node) final {
85 unsupportedProjectionType("MatchExpressionASTNode");
86 }
87
88 4512 auto generateABT() {
89 4512 return _builder.generateABT();
90 }
91
92 private:
93 projection_ast::PathTrackingVisitorContext<>* _context;
94 FieldMapBuilder _builder;
95 bool _isInclusion;
96
97 65382 void assertSupportedPath(const std::string& path) {
98 65382 uassert(ErrorCodes::InternalErrorNotSupported,
99 "Projection contains unsupported numeric path component",
100 !FieldRef(path).hasNumericPathComponents());
101 65382 }
102
103 64662 void builderIntegrateInclusion(const std::string& fullPath) {
104 64662 assertSupportedPath(fullPath);
105 64662 _builder.integrateFieldPath(FieldPath(fullPath),
106 33165 [](const bool isLastElement, FieldMapEntry& entry) {
107 33165 entry._hasLeadingObj = true;
108 33165 entry._hasKeep = true;
109 33165 });
110 64662 }
111
112 720 void builderIntegrateExclusion(const std::string& fullPath) {
113 720 assertSupportedPath(fullPath);
114 720 _builder.integrateFieldPath(FieldPath(fullPath),
115 426 [](const bool isLastElement, FieldMapEntry& entry) {
116 426 if (isLastElement) {
117 360 entry._hasDrop = true;
118 }
119 426 });
120 720 }
121
122 108 void unsupportedProjectionType(const std::string& unsupportedNode) const {
123 216 uasserted(ErrorCodes::InternalErrorNotSupported,
124 str::stream() << "Projection node is not supported (type: " << unsupportedNode
125 << ")");
126 }
127 };
128
129 2310 void translateProjection(AlgebrizerContext& ctx, const projection_ast::Projection* proj) {
130 2364 projection_ast::PathTrackingVisitorContext context{};
131 2310 const bool isInclusion = proj->type() == projection_ast::ProjectType::kInclusion;
132 2310 const ProjectionName& rootProjName = ctx.getNode()._rootProjection;
133
134 2364 ProjectionPreVisitor astVisitor{&context, isInclusion, rootProjName, ctx.getScanProjName()};
135 4674 projection_ast::PathTrackingWalker walker{&context, {&astVisitor}, {}};
136 2310 tree_walker::walk<true, projection_ast::ASTNode>(proj->root(), &walker);
137
138 2256 auto result = astVisitor.generateABT();
139 2256 if (!result) {
140 return;
141 }
142 4512 auto entry = ctx.getNode();
143 4512 const ProjectionName projName = ctx.getNextId("combinedProjection");
144 2256 ctx.setNode<EvaluationNode>(projName, projName, std::move(*result), std::move(entry._node));
145 }
146
147 } // namespace mongo::optimizer
148