From 893dab73b05c3bfe99176ac18b6625c88611e5e8 Mon Sep 17 00:00:00 2001 From: Svilen Mihaylov Date: Wed, 9 Sep 2020 13:23:30 -0400 Subject: optimizer --- src/mongo/db/query/SConscript | 1 + src/mongo/db/query/optimizer/SConscript | 26 ++++ src/mongo/db/query/optimizer/defs.cpp | 40 ++++++ src/mongo/db/query/optimizer/defs.h | 53 ++++++++ src/mongo/db/query/optimizer/filter.h | 38 ++++++ src/mongo/db/query/optimizer/node.cpp | 129 +++++++++++++++++++ src/mongo/db/query/optimizer/node.h | 163 ++++++++++++++++++++++++ src/mongo/db/query/optimizer/optimizer_test.cpp | 43 +++++++ src/mongo/db/query/optimizer/projection.h | 38 ++++++ src/mongo/db/query/optimizer/props.h | 38 ++++++ 10 files changed, 569 insertions(+) create mode 100644 src/mongo/db/query/optimizer/SConscript create mode 100644 src/mongo/db/query/optimizer/defs.cpp create mode 100644 src/mongo/db/query/optimizer/defs.h create mode 100644 src/mongo/db/query/optimizer/filter.h create mode 100644 src/mongo/db/query/optimizer/node.cpp create mode 100644 src/mongo/db/query/optimizer/node.h create mode 100644 src/mongo/db/query/optimizer/optimizer_test.cpp create mode 100644 src/mongo/db/query/optimizer/projection.h create mode 100644 src/mongo/db/query/optimizer/props.h diff --git a/src/mongo/db/query/SConscript b/src/mongo/db/query/SConscript index eada898eafb..a82d443d5bf 100644 --- a/src/mongo/db/query/SConscript +++ b/src/mongo/db/query/SConscript @@ -8,6 +8,7 @@ env.SConscript( dirs=[ "collation", "datetime", + 'optimizer', ], exports=[ 'env' diff --git a/src/mongo/db/query/optimizer/SConscript b/src/mongo/db/query/optimizer/SConscript new file mode 100644 index 00000000000..175b109625d --- /dev/null +++ b/src/mongo/db/query/optimizer/SConscript @@ -0,0 +1,26 @@ +# -*- mode: python -*- + +Import("env") + +env = env.Clone() + +env.Library( + target="optimizer", + source=[ + "defs.cpp", + "node.cpp", + ], + LIBDEPS=[ +# "$BUILD_DIR/mongo/base", + ], +) + +env.CppUnitTest( + target='optimizer_test', + source=[ + 'optimizer_test.cpp', + ], + LIBDEPS=[ + 'optimizer', + ] +) diff --git a/src/mongo/db/query/optimizer/defs.cpp b/src/mongo/db/query/optimizer/defs.cpp new file mode 100644 index 00000000000..07eb9c8b85c --- /dev/null +++ b/src/mongo/db/query/optimizer/defs.cpp @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/db/query/optimizer/defs.h" + +namespace mongo::optimizer { + +Context::Context() : _currentNodeId(0) {} + +NodeIdType Context::nextNodeId() { + return _currentNodeId++; +} + +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/defs.h b/src/mongo/db/query/optimizer/defs.h new file mode 100644 index 00000000000..84f8e1ff783 --- /dev/null +++ b/src/mongo/db/query/optimizer/defs.h @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include + +namespace mongo::optimizer { + +using FieldNameType = std::string; +using CollectionNameType = std::string; +using ProjectionName = std::string; + +using NodeIdType = uint64_t; + +class Context +{ +public: + Context();; + + NodeIdType nextNodeId(); + +private: + NodeIdType _currentNodeId; +}; + +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/filter.h b/src/mongo/db/query/optimizer/filter.h new file mode 100644 index 00000000000..1e62d7c020b --- /dev/null +++ b/src/mongo/db/query/optimizer/filter.h @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include + +namespace mongo::optimizer { + +using FilterType = std::string; + +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/node.cpp b/src/mongo/db/query/optimizer/node.cpp new file mode 100644 index 00000000000..46a5fcc3859 --- /dev/null +++ b/src/mongo/db/query/optimizer/node.cpp @@ -0,0 +1,129 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/db/query/optimizer/node.h" + +namespace mongo::optimizer { + +Node::Node(NodePtr child) { + _children.push_back(std::move(child)); +} + +Node::Node(std::vector children) : _children(std::move(children)) {} + +std::string Node::generateMemo() { + std::ostringstream os; + generateMemoInternal(os); + return os.str(); +} + +NodePtr ScanNode::create(CollectionNameType collectionName) { + return NodePtr(new ScanNode(std::move(collectionName))); +} + +ScanNode::ScanNode(CollectionNameType collectionName) + : Node(), _collectionName(std::move(collectionName)) {} + +void ScanNode::generateMemoInternal(std::ostringstream& os) { + os << "Scan"; +} + +NodePtr MultiJoinNode::create(FilterSet filterSet, + ProjectionMap projectionMap, + std::vector children) { + return NodePtr( + new MultiJoinNode(std::move(filterSet), std::move(projectionMap), std::move(children))); +} + +MultiJoinNode::MultiJoinNode(FilterSet filterSet, + ProjectionMap projectionMap, + std::vector children) + : Node(std::move(children)), + _filterSet(std::move(filterSet)), + _projectionMap(std::move(projectionMap)) {} + +void MultiJoinNode::generateMemoInternal(std::ostringstream& os) { + os << "MultiJoin"; +} + +NodePtr UnionNode::create(std::vector children) { + return NodePtr(new UnionNode(std::move(children))); +} + +UnionNode::UnionNode(std::vector children) : Node(std::move(children)) {} + +void UnionNode::generateMemoInternal(std::ostringstream& os) { + os << "Union"; +} + +NodePtr GroupByNode::create(GroupByNode::GroupByVector groupByVector, + GroupByNode::ProjectionMap projectionMap, + NodePtr child) { + return NodePtr( + new GroupByNode(std::move(groupByVector), std::move(projectionMap), std::move(child))); +} + +GroupByNode::GroupByNode(GroupByNode::GroupByVector groupByVector, + GroupByNode::ProjectionMap projectionMap, + NodePtr child) + : Node(std::move(child)), + _groupByVector(std::move(groupByVector)), + _projectionMap(std::move(projectionMap)) {} + +void GroupByNode::generateMemoInternal(std::ostringstream& os) { + os << "GroupBy"; +} + +NodePtr UnwindNode::create(ProjectionName projectionName, + const bool retainNonArrays, + NodePtr child) { + return NodePtr(new UnwindNode(std::move(projectionName), retainNonArrays, std::move(child))); +} + +UnwindNode::UnwindNode(ProjectionName projectionName, const bool retainNonArrays, NodePtr child) + : Node(std::move(child)), + _projectionName(std::move(projectionName)), + _retainNonArrays(retainNonArrays) {} + +void UnwindNode::generateMemoInternal(std::ostringstream& os) { + os << "Unwind"; +} + +NodePtr WindNode::create(ProjectionName projectionName, NodePtr child) { + return NodePtr(new WindNode(std::move(projectionName), std::move(child))); +} + +WindNode::WindNode(ProjectionName projectionName, NodePtr child) + : Node(std::move(child)), _projectionName(std::move(projectionName)) {} + +void WindNode::generateMemoInternal(std::ostringstream& os) { + os << "Wind"; +} + +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/node.h b/src/mongo/db/query/optimizer/node.h new file mode 100644 index 00000000000..b2aba1adc3e --- /dev/null +++ b/src/mongo/db/query/optimizer/node.h @@ -0,0 +1,163 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "mongo/db/query/optimizer/defs.h" +#include "mongo/db/query/optimizer/filter.h" +#include "mongo/db/query/optimizer/projection.h" +#include "mongo/db/query/optimizer/props.h" + + +namespace mongo::optimizer { + +class Node; +using NodePtr = std::unique_ptr; + + +class Node { +protected: + Node() : _children() {} + + // pass context + explicit Node(NodePtr child); + + explicit Node(std::vector children); + + virtual void generateMemoInternal(std::ostringstream& os) = 0; + + // clone +public: + virtual std::string generateMemo() final; + +private: + // id + // properties + std::vector _children; +}; + +class ScanNode : public Node { +public: + static NodePtr create(CollectionNameType collectionName); + +protected: + void generateMemoInternal(std::ostringstream& os) override; + +private: + explicit ScanNode(CollectionNameType collectionName); + + const CollectionNameType _collectionName; +}; + +class MultiJoinNode : public Node { +public: + using FilterSet = std::unordered_set; + using ProjectionMap = std::unordered_map; + + static NodePtr create(FilterSet filterSet, + ProjectionMap projectionMap, + std::vector children); + +protected: + void generateMemoInternal(std::ostringstream& os) override; + +private: + explicit MultiJoinNode(FilterSet filterSet, + ProjectionMap projectionMap, + std::vector children); + + FilterSet _filterSet; + ProjectionMap _projectionMap; +}; + +class UnionNode : public Node { +public: + static NodePtr create(std::vector children); + +protected: + void generateMemoInternal(std::ostringstream& os) override; + +private: + explicit UnionNode(std::vector children); +}; + +class GroupByNode : public Node { +public: + using GroupByVector = std::vector; + using ProjectionMap = std::unordered_map; + + static NodePtr create(GroupByVector groupByVector, ProjectionMap projectionMap, NodePtr child); + +protected: + void generateMemoInternal(std::ostringstream& os) override; + +private: + explicit GroupByNode(GroupByVector groupByVector, ProjectionMap projectionMap, NodePtr child); + + GroupByVector _groupByVector; + ProjectionMap _projectionMap; +}; + +class UnwindNode : public Node { +public: + static NodePtr create(ProjectionName projectionName, bool retainNonArrays, NodePtr child); + +protected: + void generateMemoInternal(std::ostringstream& os) override; + +private: + UnwindNode(ProjectionName projectionName, bool retainNonArrays, NodePtr child); + + const ProjectionName _projectionName; + const bool _retainNonArrays; +}; + +class WindNode : public Node { +public: + static NodePtr create(ProjectionName projectionName, NodePtr child); + +protected: + void generateMemoInternal(std::ostringstream& os) override; + +private: + WindNode(ProjectionName projectionName, NodePtr child); + + const ProjectionName _projectionName; +}; + + +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/optimizer_test.cpp b/src/mongo/db/query/optimizer/optimizer_test.cpp new file mode 100644 index 00000000000..1f244624f7b --- /dev/null +++ b/src/mongo/db/query/optimizer/optimizer_test.cpp @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/db/query/optimizer/node.h" +#include "mongo/unittest/unittest.h" + +namespace mongo::optimizer { +namespace { + +TEST(Optimizer, Basic) { + NodePtr ptr = ScanNode::create("test"); + const std::string s = ptr->generateMemo(); + NodePtr ptr1 = ScanNode::create("test"); +} + +} // namespace +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/projection.h b/src/mongo/db/query/optimizer/projection.h new file mode 100644 index 00000000000..78be4907a9e --- /dev/null +++ b/src/mongo/db/query/optimizer/projection.h @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include + +namespace mongo::optimizer { + +using ProjectionType = std::string; + +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/props.h b/src/mongo/db/query/optimizer/props.h new file mode 100644 index 00000000000..cd366152493 --- /dev/null +++ b/src/mongo/db/query/optimizer/props.h @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include + +namespace mongo::optimizer { + +using LogicalProperties = std::string; + +} // namespace mongo::optimizer -- cgit v1.2.1 From 1f977bf82929e2e6b36457d6b769ec00a2db6424 Mon Sep 17 00:00:00 2001 From: Svilen Mihaylov Date: Wed, 9 Sep 2020 13:23:30 -0400 Subject: optimizer --- src/mongo/db/query/SConscript | 1 + src/mongo/db/query/optimizer/SConscript | 26 +++ src/mongo/db/query/optimizer/defs.cpp | 40 +++++ src/mongo/db/query/optimizer/defs.h | 52 ++++++ src/mongo/db/query/optimizer/filter.h | 38 +++++ src/mongo/db/query/optimizer/node.cpp | 211 ++++++++++++++++++++++++ src/mongo/db/query/optimizer/node.h | 191 +++++++++++++++++++++ src/mongo/db/query/optimizer/optimizer_test.cpp | 45 +++++ src/mongo/db/query/optimizer/projection.h | 38 +++++ src/mongo/db/query/optimizer/props.h | 38 +++++ src/mongo/db/query/optimizer/visitor.h | 46 ++++++ 11 files changed, 726 insertions(+) create mode 100644 src/mongo/db/query/optimizer/SConscript create mode 100644 src/mongo/db/query/optimizer/defs.cpp create mode 100644 src/mongo/db/query/optimizer/defs.h create mode 100644 src/mongo/db/query/optimizer/filter.h create mode 100644 src/mongo/db/query/optimizer/node.cpp create mode 100644 src/mongo/db/query/optimizer/node.h create mode 100644 src/mongo/db/query/optimizer/optimizer_test.cpp create mode 100644 src/mongo/db/query/optimizer/projection.h create mode 100644 src/mongo/db/query/optimizer/props.h create mode 100644 src/mongo/db/query/optimizer/visitor.h diff --git a/src/mongo/db/query/SConscript b/src/mongo/db/query/SConscript index eada898eafb..a82d443d5bf 100644 --- a/src/mongo/db/query/SConscript +++ b/src/mongo/db/query/SConscript @@ -8,6 +8,7 @@ env.SConscript( dirs=[ "collation", "datetime", + 'optimizer', ], exports=[ 'env' diff --git a/src/mongo/db/query/optimizer/SConscript b/src/mongo/db/query/optimizer/SConscript new file mode 100644 index 00000000000..175b109625d --- /dev/null +++ b/src/mongo/db/query/optimizer/SConscript @@ -0,0 +1,26 @@ +# -*- mode: python -*- + +Import("env") + +env = env.Clone() + +env.Library( + target="optimizer", + source=[ + "defs.cpp", + "node.cpp", + ], + LIBDEPS=[ +# "$BUILD_DIR/mongo/base", + ], +) + +env.CppUnitTest( + target='optimizer_test', + source=[ + 'optimizer_test.cpp', + ], + LIBDEPS=[ + 'optimizer', + ] +) diff --git a/src/mongo/db/query/optimizer/defs.cpp b/src/mongo/db/query/optimizer/defs.cpp new file mode 100644 index 00000000000..cb6611fdd97 --- /dev/null +++ b/src/mongo/db/query/optimizer/defs.cpp @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/db/query/optimizer/defs.h" + +namespace mongo::optimizer { + +Context::Context() : _nextNodeId(0) {} + +NodeIdType Context::getNextNodeId() { + return _nextNodeId++; +} + +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/defs.h b/src/mongo/db/query/optimizer/defs.h new file mode 100644 index 00000000000..589c5dea24f --- /dev/null +++ b/src/mongo/db/query/optimizer/defs.h @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include + +namespace mongo::optimizer { + +using FieldNameType = std::string; +using CollectionNameType = std::string; +using ProjectionName = std::string; + +using NodeIdType = uint64_t; + +class Context { +public: + Context(); + + NodeIdType getNextNodeId(); + +private: + NodeIdType _nextNodeId; +}; + +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/filter.h b/src/mongo/db/query/optimizer/filter.h new file mode 100644 index 00000000000..1e62d7c020b --- /dev/null +++ b/src/mongo/db/query/optimizer/filter.h @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include + +namespace mongo::optimizer { + +using FilterType = std::string; + +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/node.cpp b/src/mongo/db/query/optimizer/node.cpp new file mode 100644 index 00000000000..f2b0973ba58 --- /dev/null +++ b/src/mongo/db/query/optimizer/node.cpp @@ -0,0 +1,211 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/db/query/optimizer/node.h" +#include "mongo/db/query/optimizer/visitor.h" + +namespace mongo::optimizer { + +Node::Node(Context& ctx) : _nodeId(ctx.getNextNodeId()), _children() {} + +Node::Node(Context& ctx, NodePtr child) : _nodeId(ctx.getNextNodeId()) { + _children.push_back(std::move(child)); +} + +Node::Node(Context& ctx, std::vector children) + : _nodeId(ctx.getNextNodeId()), _children(std::move(children)) {} + +void Node::generateMemoBase(std::ostringstream& os) { + os << "NodeId: " << _nodeId << "\n"; +} + +std::string Node::generateMemo() { + std::ostringstream os; + + class MemoVisitor: public AbstractVisitor + { + protected: + void visit(ScanNode& node) override { + node.generateMemoInternal(os); + } + void visit(MultiJoinNode& node) override { + node.generateMemoInternal(os); + } + void visit(UnionNode& node) override { + node.generateMemoInternal(os); + } + void visit(GroupByNode& node) override { + node.generateMemoInternal(os); + } + void visit(UnwindNode& node) override { + node.generateMemoInternal(os); + } + void visit(WindNode& node) override { + node.generateMemoInternal(os); + } + public: + std::ostringstream os; + }; + + MemoVisitor visitor; + visitPreOrder(visitor); + return visitor.os.str(); +} + +void Node::visitPreOrder(AbstractVisitor& visitor) { + visit(visitor); + for (const NodePtr& ptr: _children) { + ptr->visitPreOrder(visitor); + } +} + +NodePtr ScanNode::create(Context& ctx, CollectionNameType collectionName) { + return NodePtr(new ScanNode(ctx, std::move(collectionName))); +} + +ScanNode::ScanNode(Context& ctx, CollectionNameType collectionName) + : Node(ctx), _collectionName(std::move(collectionName)) {} + +void ScanNode::generateMemoInternal(std::ostringstream& os) { + Node::generateMemoBase(os); + os << "Scan" << "\n"; +} + +void ScanNode::visit(AbstractVisitor& visitor) { + visitor.visit(*this); +} + +NodePtr MultiJoinNode::create(Context& ctx, + FilterSet filterSet, + ProjectionMap projectionMap, + std::vector children) { + return NodePtr(new MultiJoinNode( + ctx, std::move(filterSet), std::move(projectionMap), std::move(children))); +} + +MultiJoinNode::MultiJoinNode(Context& ctx, + FilterSet filterSet, + ProjectionMap projectionMap, + std::vector children) + : Node(ctx, std::move(children)), + _filterSet(std::move(filterSet)), + _projectionMap(std::move(projectionMap)) {} + +void MultiJoinNode::generateMemoInternal(std::ostringstream& os) { + Node::generateMemoBase(os); + os << "MultiJoin" << "\n"; +} + +void MultiJoinNode::visit(AbstractVisitor& visitor) { + visitor.visit(*this); +} + +NodePtr UnionNode::create(Context& ctx, std::vector children) { + return NodePtr(new UnionNode(ctx, std::move(children))); +} + +UnionNode::UnionNode(Context& ctx, std::vector children) + : Node(ctx, std::move(children)) {} + +void UnionNode::generateMemoInternal(std::ostringstream& os) { + Node::generateMemoBase(os); + os << "Union" << "\n"; +} + +void UnionNode::visit(AbstractVisitor& visitor) { + visitor.visit(*this); +} + +NodePtr GroupByNode::create(Context& ctx, + GroupByNode::GroupByVector groupByVector, + GroupByNode::ProjectionMap projectionMap, + NodePtr child) { + return NodePtr( + new GroupByNode(ctx, std::move(groupByVector), std::move(projectionMap), std::move(child))); +} + +GroupByNode::GroupByNode(Context& ctx, + GroupByNode::GroupByVector groupByVector, + GroupByNode::ProjectionMap projectionMap, + NodePtr child) + : Node(ctx, std::move(child)), + _groupByVector(std::move(groupByVector)), + _projectionMap(std::move(projectionMap)) {} + +void GroupByNode::generateMemoInternal(std::ostringstream& os) { + Node::generateMemoBase(os); + os << "GroupBy" << "\n"; +} + +void GroupByNode::visit(AbstractVisitor& visitor) { + visitor.visit(*this); +} + +NodePtr UnwindNode::create(Context& ctx, + ProjectionName projectionName, + const bool retainNonArrays, + NodePtr child) { + return NodePtr( + new UnwindNode(ctx, std::move(projectionName), retainNonArrays, std::move(child))); +} + +UnwindNode::UnwindNode(Context& ctx, + ProjectionName projectionName, + const bool retainNonArrays, + NodePtr child) + : Node(ctx, std::move(child)), + _projectionName(std::move(projectionName)), + _retainNonArrays(retainNonArrays) {} + +void UnwindNode::generateMemoInternal(std::ostringstream& os) { + Node::generateMemoBase(os); + os << "Unwind" << "\n"; +} + +void UnwindNode::visit(AbstractVisitor& visitor) { + visitor.visit(*this); +} + +NodePtr WindNode::create(Context& ctx, ProjectionName projectionName, NodePtr child) { + return NodePtr(new WindNode(ctx, std::move(projectionName), std::move(child))); +} + +WindNode::WindNode(Context& ctx, ProjectionName projectionName, NodePtr child) + : Node(ctx, std::move(child)), _projectionName(std::move(projectionName)) {} + +void WindNode::generateMemoInternal(std::ostringstream& os) { + Node::generateMemoBase(os); + os << "Wind" << "\n"; +} + +void WindNode::visit(AbstractVisitor& visitor) { + visitor.visit(*this); +} + +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/node.h b/src/mongo/db/query/optimizer/node.h new file mode 100644 index 00000000000..44f7b8258ce --- /dev/null +++ b/src/mongo/db/query/optimizer/node.h @@ -0,0 +1,191 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "mongo/db/query/optimizer/defs.h" +#include "mongo/db/query/optimizer/filter.h" +#include "mongo/db/query/optimizer/projection.h" +#include "mongo/db/query/optimizer/props.h" + + +namespace mongo::optimizer { + +class Node; +using NodePtr = std::unique_ptr; + +class AbstractVisitor; + +class Node { + friend class AbstractVisitor; + +protected: + explicit Node(Context& ctx); + explicit Node(Context& ctx, NodePtr child); + explicit Node(Context& ctx, std::vector children); + + virtual void generateMemoBase(std::ostringstream& os); + + virtual void visit(AbstractVisitor& visitor) = 0; + + virtual void visitPreOrder(AbstractVisitor& visitor) final; + + // clone +public: + Node() = delete; + + virtual std::string generateMemo() final; + +private: + const NodeIdType _nodeId; + std::vector _children; +}; + +class ScanNode : public Node { +public: + static NodePtr create(Context& ctx, CollectionNameType collectionName); + + void generateMemoInternal(std::ostringstream& os); + +protected: + void visit(AbstractVisitor& visitor) override; + +private: + explicit ScanNode(Context& ctx, CollectionNameType collectionName); + + const CollectionNameType _collectionName; +}; + +class MultiJoinNode : public Node { +public: + using FilterSet = std::unordered_set; + using ProjectionMap = std::unordered_map; + + static NodePtr create(Context& ctx, + FilterSet filterSet, + ProjectionMap projectionMap, + std::vector children); + + void generateMemoInternal(std::ostringstream& os); + +protected: + void visit(AbstractVisitor& visitor) override; + +private: + explicit MultiJoinNode(Context& ctx, + FilterSet filterSet, + ProjectionMap projectionMap, + std::vector children); + + FilterSet _filterSet; + ProjectionMap _projectionMap; +}; + +class UnionNode : public Node { +public: + static NodePtr create(Context& ctx, std::vector children); + + void generateMemoInternal(std::ostringstream& os); + +protected: + void visit(AbstractVisitor& visitor) override; + +private: + explicit UnionNode(Context& ctx, std::vector children); +}; + +class GroupByNode : public Node { +public: + using GroupByVector = std::vector; + using ProjectionMap = std::unordered_map; + + static NodePtr create(Context& ctx, + GroupByVector groupByVector, + ProjectionMap projectionMap, + NodePtr child); + + void generateMemoInternal(std::ostringstream& os); + +protected: + void visit(AbstractVisitor& visitor) override; + +private: + explicit GroupByNode(Context& ctx, + GroupByVector groupByVector, + ProjectionMap projectionMap, + NodePtr child); + + GroupByVector _groupByVector; + ProjectionMap _projectionMap; +}; + +class UnwindNode : public Node { +public: + static NodePtr create(Context& ctx, + ProjectionName projectionName, + bool retainNonArrays, + NodePtr child); + + void generateMemoInternal(std::ostringstream& os); + +protected: + + void visit(AbstractVisitor& visitor) override; + +private: + UnwindNode(Context& ctx, ProjectionName projectionName, bool retainNonArrays, NodePtr child); + + const ProjectionName _projectionName; + const bool _retainNonArrays; +}; + +class WindNode : public Node { +public: + static NodePtr create(Context& ctx, ProjectionName projectionName, NodePtr child); + + void generateMemoInternal(std::ostringstream& os); + +protected: + void visit(AbstractVisitor& visitor) override; + +private: + WindNode(Context& ctx, ProjectionName projectionName, NodePtr child); + + const ProjectionName _projectionName; +}; + +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/optimizer_test.cpp b/src/mongo/db/query/optimizer/optimizer_test.cpp new file mode 100644 index 00000000000..4b36d49760f --- /dev/null +++ b/src/mongo/db/query/optimizer/optimizer_test.cpp @@ -0,0 +1,45 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/db/query/optimizer/node.h" +#include "mongo/unittest/unittest.h" + +namespace mongo::optimizer { +namespace { + +TEST(Optimizer, Basic) { + Context ctx; + + NodePtr ptr = ScanNode::create(ctx, "test"); + const std::string& s = ptr->generateMemo(); + NodePtr ptr1 = ScanNode::create(ctx, "test"); +} + +} // namespace +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/projection.h b/src/mongo/db/query/optimizer/projection.h new file mode 100644 index 00000000000..78be4907a9e --- /dev/null +++ b/src/mongo/db/query/optimizer/projection.h @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include + +namespace mongo::optimizer { + +using ProjectionType = std::string; + +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/props.h b/src/mongo/db/query/optimizer/props.h new file mode 100644 index 00000000000..cd366152493 --- /dev/null +++ b/src/mongo/db/query/optimizer/props.h @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include + +namespace mongo::optimizer { + +using LogicalProperties = std::string; + +} // namespace mongo::optimizer diff --git a/src/mongo/db/query/optimizer/visitor.h b/src/mongo/db/query/optimizer/visitor.h new file mode 100644 index 00000000000..bb5acfb7412 --- /dev/null +++ b/src/mongo/db/query/optimizer/visitor.h @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include + +namespace mongo::optimizer { + +class AbstractVisitor { +public: + virtual void visit(ScanNode& node) = 0; + virtual void visit(MultiJoinNode& node) = 0; + virtual void visit(UnionNode& node) = 0; + virtual void visit(GroupByNode& node) = 0; + virtual void visit(UnwindNode& node) = 0; + virtual void visit(WindNode& node) = 0; +}; + +} // namespace mongo::optimizer -- cgit v1.2.1 From 18af06fa5a43e829035b625eba4dab504a905880 Mon Sep 17 00:00:00 2001 From: Svilen Mihaylov Date: Wed, 9 Sep 2020 15:26:53 -0400 Subject: fix visitor --- src/mongo/db/query/optimizer/node.cpp | 40 ++++++++++++------------- src/mongo/db/query/optimizer/node.h | 14 ++++----- src/mongo/db/query/optimizer/optimizer_test.cpp | 3 +- src/mongo/db/query/optimizer/visitor.h | 12 ++++---- 4 files changed, 33 insertions(+), 36 deletions(-) diff --git a/src/mongo/db/query/optimizer/node.cpp b/src/mongo/db/query/optimizer/node.cpp index f2b0973ba58..c52d55c1be9 100644 --- a/src/mongo/db/query/optimizer/node.cpp +++ b/src/mongo/db/query/optimizer/node.cpp @@ -41,33 +41,31 @@ Node::Node(Context& ctx, NodePtr child) : _nodeId(ctx.getNextNodeId()) { Node::Node(Context& ctx, std::vector children) : _nodeId(ctx.getNextNodeId()), _children(std::move(children)) {} -void Node::generateMemoBase(std::ostringstream& os) { +void Node::generateMemoBase(std::ostringstream& os) const { os << "NodeId: " << _nodeId << "\n"; } std::string Node::generateMemo() { - std::ostringstream os; - class MemoVisitor: public AbstractVisitor { protected: - void visit(ScanNode& node) override { - node.generateMemoInternal(os); + void visit(const ScanNode& node) override { + node.generateScanMemo(os); } - void visit(MultiJoinNode& node) override { - node.generateMemoInternal(os); + void visit(const MultiJoinNode& node) override { + node.generateMultiJoinMemo(os); } - void visit(UnionNode& node) override { - node.generateMemoInternal(os); + void visit(const UnionNode& node) override { + node.generateUnionMemo(os); } - void visit(GroupByNode& node) override { - node.generateMemoInternal(os); + void visit(const GroupByNode& node) override { + node.generateGroupByMemo(os); } - void visit(UnwindNode& node) override { - node.generateMemoInternal(os); + void visit(const UnwindNode& node) override { + node.generateUnwindMemo(os); } - void visit(WindNode& node) override { - node.generateMemoInternal(os); + void visit(const WindNode& node) override { + node.generateWindMemo(os); } public: std::ostringstream os; @@ -92,7 +90,7 @@ NodePtr ScanNode::create(Context& ctx, CollectionNameType collectionName) { ScanNode::ScanNode(Context& ctx, CollectionNameType collectionName) : Node(ctx), _collectionName(std::move(collectionName)) {} -void ScanNode::generateMemoInternal(std::ostringstream& os) { +void ScanNode::generateScanMemo(std::ostringstream& os) const { Node::generateMemoBase(os); os << "Scan" << "\n"; } @@ -117,7 +115,7 @@ MultiJoinNode::MultiJoinNode(Context& ctx, _filterSet(std::move(filterSet)), _projectionMap(std::move(projectionMap)) {} -void MultiJoinNode::generateMemoInternal(std::ostringstream& os) { +void MultiJoinNode::generateMultiJoinMemo(std::ostringstream& os) const { Node::generateMemoBase(os); os << "MultiJoin" << "\n"; } @@ -133,7 +131,7 @@ NodePtr UnionNode::create(Context& ctx, std::vector children) { UnionNode::UnionNode(Context& ctx, std::vector children) : Node(ctx, std::move(children)) {} -void UnionNode::generateMemoInternal(std::ostringstream& os) { +void UnionNode::generateUnionMemo(std::ostringstream& os) const { Node::generateMemoBase(os); os << "Union" << "\n"; } @@ -158,7 +156,7 @@ GroupByNode::GroupByNode(Context& ctx, _groupByVector(std::move(groupByVector)), _projectionMap(std::move(projectionMap)) {} -void GroupByNode::generateMemoInternal(std::ostringstream& os) { +void GroupByNode::generateGroupByMemo(std::ostringstream& os) const { Node::generateMemoBase(os); os << "GroupBy" << "\n"; } @@ -183,7 +181,7 @@ UnwindNode::UnwindNode(Context& ctx, _projectionName(std::move(projectionName)), _retainNonArrays(retainNonArrays) {} -void UnwindNode::generateMemoInternal(std::ostringstream& os) { +void UnwindNode::generateUnwindMemo(std::ostringstream& os) const { Node::generateMemoBase(os); os << "Unwind" << "\n"; } @@ -199,7 +197,7 @@ NodePtr WindNode::create(Context& ctx, ProjectionName projectionName, NodePtr ch WindNode::WindNode(Context& ctx, ProjectionName projectionName, NodePtr child) : Node(ctx, std::move(child)), _projectionName(std::move(projectionName)) {} -void WindNode::generateMemoInternal(std::ostringstream& os) { +void WindNode::generateWindMemo(std::ostringstream& os) const { Node::generateMemoBase(os); os << "Wind" << "\n"; } diff --git a/src/mongo/db/query/optimizer/node.h b/src/mongo/db/query/optimizer/node.h index 44f7b8258ce..917144c81df 100644 --- a/src/mongo/db/query/optimizer/node.h +++ b/src/mongo/db/query/optimizer/node.h @@ -58,7 +58,7 @@ protected: explicit Node(Context& ctx, NodePtr child); explicit Node(Context& ctx, std::vector children); - virtual void generateMemoBase(std::ostringstream& os); + void generateMemoBase(std::ostringstream& os) const; virtual void visit(AbstractVisitor& visitor) = 0; @@ -79,7 +79,7 @@ class ScanNode : public Node { public: static NodePtr create(Context& ctx, CollectionNameType collectionName); - void generateMemoInternal(std::ostringstream& os); + void generateScanMemo(std::ostringstream& os) const; protected: void visit(AbstractVisitor& visitor) override; @@ -100,7 +100,7 @@ public: ProjectionMap projectionMap, std::vector children); - void generateMemoInternal(std::ostringstream& os); + void generateMultiJoinMemo(std::ostringstream& os) const; protected: void visit(AbstractVisitor& visitor) override; @@ -119,7 +119,7 @@ class UnionNode : public Node { public: static NodePtr create(Context& ctx, std::vector children); - void generateMemoInternal(std::ostringstream& os); + void generateUnionMemo(std::ostringstream& os) const; protected: void visit(AbstractVisitor& visitor) override; @@ -138,7 +138,7 @@ public: ProjectionMap projectionMap, NodePtr child); - void generateMemoInternal(std::ostringstream& os); + void generateGroupByMemo(std::ostringstream& os) const; protected: void visit(AbstractVisitor& visitor) override; @@ -160,7 +160,7 @@ public: bool retainNonArrays, NodePtr child); - void generateMemoInternal(std::ostringstream& os); + void generateUnwindMemo(std::ostringstream& os) const; protected: @@ -177,7 +177,7 @@ class WindNode : public Node { public: static NodePtr create(Context& ctx, ProjectionName projectionName, NodePtr child); - void generateMemoInternal(std::ostringstream& os); + void generateWindMemo(std::ostringstream& os) const; protected: void visit(AbstractVisitor& visitor) override; diff --git a/src/mongo/db/query/optimizer/optimizer_test.cpp b/src/mongo/db/query/optimizer/optimizer_test.cpp index 4b36d49760f..7eeaf801b16 100644 --- a/src/mongo/db/query/optimizer/optimizer_test.cpp +++ b/src/mongo/db/query/optimizer/optimizer_test.cpp @@ -37,8 +37,7 @@ TEST(Optimizer, Basic) { Context ctx; NodePtr ptr = ScanNode::create(ctx, "test"); - const std::string& s = ptr->generateMemo(); - NodePtr ptr1 = ScanNode::create(ctx, "test"); + ASSERT_EQ("NodeId: 0\nScan\n", ptr->generateMemo()); } } // namespace diff --git a/src/mongo/db/query/optimizer/visitor.h b/src/mongo/db/query/optimizer/visitor.h index bb5acfb7412..1aa0a886fab 100644 --- a/src/mongo/db/query/optimizer/visitor.h +++ b/src/mongo/db/query/optimizer/visitor.h @@ -35,12 +35,12 @@ namespace mongo::optimizer { class AbstractVisitor { public: - virtual void visit(ScanNode& node) = 0; - virtual void visit(MultiJoinNode& node) = 0; - virtual void visit(UnionNode& node) = 0; - virtual void visit(GroupByNode& node) = 0; - virtual void visit(UnwindNode& node) = 0; - virtual void visit(WindNode& node) = 0; + virtual void visit(const ScanNode& node) = 0; + virtual void visit(const MultiJoinNode& node) = 0; + virtual void visit(const UnionNode& node) = 0; + virtual void visit(const GroupByNode& node) = 0; + virtual void visit(const UnwindNode& node) = 0; + virtual void visit(const WindNode& node) = 0; }; } // namespace mongo::optimizer -- cgit v1.2.1 From 9edbc1726d8b6084b7440c0fd47a2f6a46b0bce6 Mon Sep 17 00:00:00 2001 From: Svilen Mihaylov Date: Wed, 9 Sep 2020 15:48:21 -0400 Subject: fix visitor --- src/mongo/db/query/optimizer/node.cpp | 74 +++++++++++++------------ src/mongo/db/query/optimizer/node.h | 38 +++++++------ src/mongo/db/query/optimizer/optimizer_test.cpp | 7 ++- 3 files changed, 65 insertions(+), 54 deletions(-) diff --git a/src/mongo/db/query/optimizer/node.cpp b/src/mongo/db/query/optimizer/node.cpp index c52d55c1be9..d101f60b018 100644 --- a/src/mongo/db/query/optimizer/node.cpp +++ b/src/mongo/db/query/optimizer/node.cpp @@ -45,28 +45,35 @@ void Node::generateMemoBase(std::ostringstream& os) const { os << "NodeId: " << _nodeId << "\n"; } -std::string Node::generateMemo() { - class MemoVisitor: public AbstractVisitor - { +void Node::visitPreOrder(AbstractVisitor& visitor) const { + visit(visitor); + for (const NodePtr& ptr : _children) { + ptr->visitPreOrder(visitor); + } +} + +std::string Node::generateMemo() const { + class MemoVisitor : public AbstractVisitor { protected: void visit(const ScanNode& node) override { - node.generateScanMemo(os); + node.generateMemo(os); } void visit(const MultiJoinNode& node) override { - node.generateMultiJoinMemo(os); + node.generateMemo(os); } void visit(const UnionNode& node) override { - node.generateUnionMemo(os); + node.generateMemo(os); } void visit(const GroupByNode& node) override { - node.generateGroupByMemo(os); + node.generateMemo(os); } void visit(const UnwindNode& node) override { - node.generateUnwindMemo(os); + node.generateMemo(os); } void visit(const WindNode& node) override { - node.generateWindMemo(os); + node.generateMemo(os); } + public: std::ostringstream os; }; @@ -76,13 +83,6 @@ std::string Node::generateMemo() { return visitor.os.str(); } -void Node::visitPreOrder(AbstractVisitor& visitor) { - visit(visitor); - for (const NodePtr& ptr: _children) { - ptr->visitPreOrder(visitor); - } -} - NodePtr ScanNode::create(Context& ctx, CollectionNameType collectionName) { return NodePtr(new ScanNode(ctx, std::move(collectionName))); } @@ -90,12 +90,13 @@ NodePtr ScanNode::create(Context& ctx, CollectionNameType collectionName) { ScanNode::ScanNode(Context& ctx, CollectionNameType collectionName) : Node(ctx), _collectionName(std::move(collectionName)) {} -void ScanNode::generateScanMemo(std::ostringstream& os) const { +void ScanNode::generateMemo(std::ostringstream& os) const { Node::generateMemoBase(os); - os << "Scan" << "\n"; + os << "Scan" + << "\n"; } -void ScanNode::visit(AbstractVisitor& visitor) { +void ScanNode::visit(AbstractVisitor& visitor) const { visitor.visit(*this); } @@ -115,12 +116,13 @@ MultiJoinNode::MultiJoinNode(Context& ctx, _filterSet(std::move(filterSet)), _projectionMap(std::move(projectionMap)) {} -void MultiJoinNode::generateMultiJoinMemo(std::ostringstream& os) const { +void MultiJoinNode::generateMemo(std::ostringstream& os) const { Node::generateMemoBase(os); - os << "MultiJoin" << "\n"; + os << "MultiJoin" + << "\n"; } -void MultiJoinNode::visit(AbstractVisitor& visitor) { +void MultiJoinNode::visit(AbstractVisitor& visitor) const { visitor.visit(*this); } @@ -131,12 +133,13 @@ NodePtr UnionNode::create(Context& ctx, std::vector children) { UnionNode::UnionNode(Context& ctx, std::vector children) : Node(ctx, std::move(children)) {} -void UnionNode::generateUnionMemo(std::ostringstream& os) const { +void UnionNode::generateMemo(std::ostringstream& os) const { Node::generateMemoBase(os); - os << "Union" << "\n"; + os << "Union" + << "\n"; } -void UnionNode::visit(AbstractVisitor& visitor) { +void UnionNode::visit(AbstractVisitor& visitor) const { visitor.visit(*this); } @@ -156,12 +159,13 @@ GroupByNode::GroupByNode(Context& ctx, _groupByVector(std::move(groupByVector)), _projectionMap(std::move(projectionMap)) {} -void GroupByNode::generateGroupByMemo(std::ostringstream& os) const { +void GroupByNode::generateMemo(std::ostringstream& os) const { Node::generateMemoBase(os); - os << "GroupBy" << "\n"; + os << "GroupBy" + << "\n"; } -void GroupByNode::visit(AbstractVisitor& visitor) { +void GroupByNode::visit(AbstractVisitor& visitor) const { visitor.visit(*this); } @@ -181,12 +185,13 @@ UnwindNode::UnwindNode(Context& ctx, _projectionName(std::move(projectionName)), _retainNonArrays(retainNonArrays) {} -void UnwindNode::generateUnwindMemo(std::ostringstream& os) const { +void UnwindNode::generateMemo(std::ostringstream& os) const { Node::generateMemoBase(os); - os << "Unwind" << "\n"; + os << "Unwind" + << "\n"; } -void UnwindNode::visit(AbstractVisitor& visitor) { +void UnwindNode::visit(AbstractVisitor& visitor) const { visitor.visit(*this); } @@ -197,12 +202,13 @@ NodePtr WindNode::create(Context& ctx, ProjectionName projectionName, NodePtr ch WindNode::WindNode(Context& ctx, ProjectionName projectionName, NodePtr child) : Node(ctx, std::move(child)), _projectionName(std::move(projectionName)) {} -void WindNode::generateWindMemo(std::ostringstream& os) const { +void WindNode::generateMemo(std::ostringstream& os) const { Node::generateMemoBase(os); - os << "Wind" << "\n"; + os << "Wind" + << "\n"; } -void WindNode::visit(AbstractVisitor& visitor) { +void WindNode::visit(AbstractVisitor& visitor) const { visitor.visit(*this); } diff --git a/src/mongo/db/query/optimizer/node.h b/src/mongo/db/query/optimizer/node.h index 917144c81df..fba45edab17 100644 --- a/src/mongo/db/query/optimizer/node.h +++ b/src/mongo/db/query/optimizer/node.h @@ -51,7 +51,8 @@ using NodePtr = std::unique_ptr; class AbstractVisitor; class Node { - friend class AbstractVisitor; +public: + using ChildVector = std::vector; protected: explicit Node(Context& ctx); @@ -60,29 +61,31 @@ protected: void generateMemoBase(std::ostringstream& os) const; - virtual void visit(AbstractVisitor& visitor) = 0; + virtual void visit(AbstractVisitor& visitor) const = 0; - virtual void visitPreOrder(AbstractVisitor& visitor) final; + void visitPreOrder(AbstractVisitor& visitor) const; // clone public: Node() = delete; - virtual std::string generateMemo() final; + std::string generateMemo() const; + + //NodePtr clone(Context& ctx) const; private: const NodeIdType _nodeId; - std::vector _children; + ChildVector _children; }; class ScanNode : public Node { public: static NodePtr create(Context& ctx, CollectionNameType collectionName); - void generateScanMemo(std::ostringstream& os) const; + void generateMemo(std::ostringstream& os) const; protected: - void visit(AbstractVisitor& visitor) override; + void visit(AbstractVisitor& visitor) const override; private: explicit ScanNode(Context& ctx, CollectionNameType collectionName); @@ -100,10 +103,10 @@ public: ProjectionMap projectionMap, std::vector children); - void generateMultiJoinMemo(std::ostringstream& os) const; + void generateMemo(std::ostringstream& os) const; protected: - void visit(AbstractVisitor& visitor) override; + void visit(AbstractVisitor& visitor) const override; private: explicit MultiJoinNode(Context& ctx, @@ -119,10 +122,10 @@ class UnionNode : public Node { public: static NodePtr create(Context& ctx, std::vector children); - void generateUnionMemo(std::ostringstream& os) const; + void generateMemo(std::ostringstream& os) const; protected: - void visit(AbstractVisitor& visitor) override; + void visit(AbstractVisitor& visitor) const override; private: explicit UnionNode(Context& ctx, std::vector children); @@ -138,10 +141,10 @@ public: ProjectionMap projectionMap, NodePtr child); - void generateGroupByMemo(std::ostringstream& os) const; + void generateMemo(std::ostringstream& os) const; protected: - void visit(AbstractVisitor& visitor) override; + void visit(AbstractVisitor& visitor) const override; private: explicit GroupByNode(Context& ctx, @@ -160,11 +163,10 @@ public: bool retainNonArrays, NodePtr child); - void generateUnwindMemo(std::ostringstream& os) const; + void generateMemo(std::ostringstream& os) const; protected: - - void visit(AbstractVisitor& visitor) override; + void visit(AbstractVisitor& visitor) const override; private: UnwindNode(Context& ctx, ProjectionName projectionName, bool retainNonArrays, NodePtr child); @@ -177,10 +179,10 @@ class WindNode : public Node { public: static NodePtr create(Context& ctx, ProjectionName projectionName, NodePtr child); - void generateWindMemo(std::ostringstream& os) const; + void generateMemo(std::ostringstream& os) const; protected: - void visit(AbstractVisitor& visitor) override; + void visit(AbstractVisitor& visitor) const override; private: WindNode(Context& ctx, ProjectionName projectionName, NodePtr child); diff --git a/src/mongo/db/query/optimizer/optimizer_test.cpp b/src/mongo/db/query/optimizer/optimizer_test.cpp index 7eeaf801b16..f7eb881c531 100644 --- a/src/mongo/db/query/optimizer/optimizer_test.cpp +++ b/src/mongo/db/query/optimizer/optimizer_test.cpp @@ -36,8 +36,11 @@ namespace { TEST(Optimizer, Basic) { Context ctx; - NodePtr ptr = ScanNode::create(ctx, "test"); - ASSERT_EQ("NodeId: 0\nScan\n", ptr->generateMemo()); + NodePtr ptrScan = ScanNode::create(ctx, "test"); + Node::ChildVector v; + v.push_back(std::move(ptrScan)); + NodePtr ptrJoin = MultiJoinNode::create(ctx, {}, {}, std::move(v)); + ASSERT_EQ("NodeId: 1\nMultiJoin\nNodeId: 0\nScan\n", ptrJoin->generateMemo()); } } // namespace -- cgit v1.2.1 From 4a7131637aa7f0d7132e35938b51a58b5d3529d1 Mon Sep 17 00:00:00 2001 From: Svilen Mihaylov Date: Wed, 9 Sep 2020 17:01:28 -0400 Subject: clone --- src/mongo/db/query/optimizer/node.cpp | 111 +++++++++++++++++++++--- src/mongo/db/query/optimizer/node.h | 22 +++-- src/mongo/db/query/optimizer/optimizer_test.cpp | 3 + 3 files changed, 116 insertions(+), 20 deletions(-) diff --git a/src/mongo/db/query/optimizer/node.cpp b/src/mongo/db/query/optimizer/node.cpp index d101f60b018..4836dcce39e 100644 --- a/src/mongo/db/query/optimizer/node.cpp +++ b/src/mongo/db/query/optimizer/node.cpp @@ -27,8 +27,12 @@ * it in the license file. */ +#include +#include + #include "mongo/db/query/optimizer/node.h" #include "mongo/db/query/optimizer/visitor.h" +#include "mongo/util/assert_util.h" namespace mongo::optimizer { @@ -38,7 +42,7 @@ Node::Node(Context& ctx, NodePtr child) : _nodeId(ctx.getNextNodeId()) { _children.push_back(std::move(child)); } -Node::Node(Context& ctx, std::vector children) +Node::Node(Context& ctx, ChildVector children) : _nodeId(ctx.getNextNodeId()), _children(std::move(children)) {} void Node::generateMemoBase(std::ostringstream& os) const { @@ -52,41 +56,102 @@ void Node::visitPreOrder(AbstractVisitor& visitor) const { } } +void Node::visitPostOrder(AbstractVisitor& visitor) const { + for (const NodePtr& ptr : _children) { + ptr->visitPostOrder(visitor); + } + visit(visitor); +} + std::string Node::generateMemo() const { class MemoVisitor : public AbstractVisitor { protected: void visit(const ScanNode& node) override { - node.generateMemo(os); + node.generateMemo(_os); } void visit(const MultiJoinNode& node) override { - node.generateMemo(os); + node.generateMemo(_os); } void visit(const UnionNode& node) override { - node.generateMemo(os); + node.generateMemo(_os); } void visit(const GroupByNode& node) override { - node.generateMemo(os); + node.generateMemo(_os); } void visit(const UnwindNode& node) override { - node.generateMemo(os); + node.generateMemo(_os); } void visit(const WindNode& node) override { - node.generateMemo(os); + node.generateMemo(_os); } public: - std::ostringstream os; + std::ostringstream _os; }; MemoVisitor visitor; visitPreOrder(visitor); - return visitor.os.str(); + return visitor._os.str(); +} + +NodePtr Node::clone(Context& ctx) const { + class CloneVisitor : public AbstractVisitor { + public: + explicit CloneVisitor(Context& ctx) : _ctx(ctx), _childStack() {} + + protected: + void visit(const ScanNode& node) override { + doClone(node, [&](ChildVector v){ return ScanNode::clone(_ctx, node); }); + } + void visit(const MultiJoinNode& node) override { + doClone(node, [&](ChildVector v){ return MultiJoinNode::clone(_ctx, node, std::move(v)); }); + } + void visit(const UnionNode& node) override { + doClone(node, [&](ChildVector v){ return UnionNode::clone(_ctx, node, std::move(v)); }); + } + void visit(const GroupByNode& node) override { + doClone(node, [&](ChildVector v){ return GroupByNode::clone(_ctx, node, std::move(v.at(0))); }); + } + void visit(const UnwindNode& node) override { + doClone(node, [&](ChildVector v){ return UnwindNode::clone(_ctx, node, std::move(v.at(0))); }); + } + void visit(const WindNode& node) override { + doClone(node, [&](ChildVector v){ return WindNode::clone(_ctx, node, std::move(v.at(0))); }); + } + + private: + void doClone(const Node& node, const std::function& cloneFn) { + ChildVector newChildren; + for (int i = 0; i < node.getChildCount(); i++) { + newChildren.push_back(std::move(_childStack.top())); + _childStack.pop(); + } + _childStack.push(cloneFn(std::move(newChildren))); + } + + public: + Context& _ctx; + std::stack _childStack; + }; + + CloneVisitor visitor(ctx); + visitPostOrder(visitor); + invariant(visitor._childStack.size() == 1); + return std::move(visitor._childStack.top()); +} + +int Node::getChildCount() const { + return _children.size(); } NodePtr ScanNode::create(Context& ctx, CollectionNameType collectionName) { return NodePtr(new ScanNode(ctx, std::move(collectionName))); } +NodePtr ScanNode::clone(Context& ctx, const ScanNode& other) { + return create(ctx, other._collectionName); +} + ScanNode::ScanNode(Context& ctx, CollectionNameType collectionName) : Node(ctx), _collectionName(std::move(collectionName)) {} @@ -103,15 +168,19 @@ void ScanNode::visit(AbstractVisitor& visitor) const { NodePtr MultiJoinNode::create(Context& ctx, FilterSet filterSet, ProjectionMap projectionMap, - std::vector children) { + ChildVector children) { return NodePtr(new MultiJoinNode( ctx, std::move(filterSet), std::move(projectionMap), std::move(children))); } +NodePtr MultiJoinNode::clone(Context& ctx, const MultiJoinNode& other, ChildVector newChildren) { + return create(ctx, other._filterSet, other._projectionMap, std::move(newChildren)); +} + MultiJoinNode::MultiJoinNode(Context& ctx, FilterSet filterSet, ProjectionMap projectionMap, - std::vector children) + ChildVector children) : Node(ctx, std::move(children)), _filterSet(std::move(filterSet)), _projectionMap(std::move(projectionMap)) {} @@ -126,11 +195,15 @@ void MultiJoinNode::visit(AbstractVisitor& visitor) const { visitor.visit(*this); } -NodePtr UnionNode::create(Context& ctx, std::vector children) { +NodePtr UnionNode::create(Context& ctx, ChildVector children) { return NodePtr(new UnionNode(ctx, std::move(children))); } -UnionNode::UnionNode(Context& ctx, std::vector children) +NodePtr UnionNode::clone(Context& ctx, const UnionNode& other, ChildVector newChildren) { + return create(ctx, std::move(newChildren)); +} + +UnionNode::UnionNode(Context& ctx, ChildVector children) : Node(ctx, std::move(children)) {} void UnionNode::generateMemo(std::ostringstream& os) const { @@ -151,6 +224,10 @@ NodePtr GroupByNode::create(Context& ctx, new GroupByNode(ctx, std::move(groupByVector), std::move(projectionMap), std::move(child))); } +NodePtr GroupByNode::clone(Context& ctx, const GroupByNode& other, NodePtr newChild) { + return create(ctx, other._groupByVector, other._projectionMap, std::move(newChild)); +} + GroupByNode::GroupByNode(Context& ctx, GroupByNode::GroupByVector groupByVector, GroupByNode::ProjectionMap projectionMap, @@ -177,6 +254,10 @@ NodePtr UnwindNode::create(Context& ctx, new UnwindNode(ctx, std::move(projectionName), retainNonArrays, std::move(child))); } +NodePtr UnwindNode::clone(Context& ctx, const UnwindNode& other, NodePtr newChild) { + return create(ctx, other._projectionName, other._retainNonArrays, std::move(newChild)); +} + UnwindNode::UnwindNode(Context& ctx, ProjectionName projectionName, const bool retainNonArrays, @@ -199,6 +280,10 @@ NodePtr WindNode::create(Context& ctx, ProjectionName projectionName, NodePtr ch return NodePtr(new WindNode(ctx, std::move(projectionName), std::move(child))); } +NodePtr WindNode::clone(Context& ctx, const WindNode& other, NodePtr newChild) { + return create(ctx, other._projectionName, std::move(newChild)); +} + WindNode::WindNode(Context& ctx, ProjectionName projectionName, NodePtr child) : Node(ctx, std::move(child)), _projectionName(std::move(projectionName)) {} diff --git a/src/mongo/db/query/optimizer/node.h b/src/mongo/db/query/optimizer/node.h index fba45edab17..78010d7d333 100644 --- a/src/mongo/db/query/optimizer/node.h +++ b/src/mongo/db/query/optimizer/node.h @@ -57,13 +57,13 @@ public: protected: explicit Node(Context& ctx); explicit Node(Context& ctx, NodePtr child); - explicit Node(Context& ctx, std::vector children); + explicit Node(Context& ctx, ChildVector children); void generateMemoBase(std::ostringstream& os) const; virtual void visit(AbstractVisitor& visitor) const = 0; - void visitPreOrder(AbstractVisitor& visitor) const; + void visitPostOrder(AbstractVisitor& visitor) const; // clone public: @@ -71,7 +71,9 @@ public: std::string generateMemo() const; - //NodePtr clone(Context& ctx) const; + NodePtr clone(Context& ctx) const; + + int getChildCount() const; private: const NodeIdType _nodeId; @@ -81,6 +83,7 @@ private: class ScanNode : public Node { public: static NodePtr create(Context& ctx, CollectionNameType collectionName); + static NodePtr clone(Context& ctx, const ScanNode& other); void generateMemo(std::ostringstream& os) const; @@ -101,7 +104,8 @@ public: static NodePtr create(Context& ctx, FilterSet filterSet, ProjectionMap projectionMap, - std::vector children); + ChildVector children); + static NodePtr clone(Context& ctx, const MultiJoinNode& other, ChildVector newChildren); void generateMemo(std::ostringstream& os) const; @@ -112,7 +116,7 @@ private: explicit MultiJoinNode(Context& ctx, FilterSet filterSet, ProjectionMap projectionMap, - std::vector children); + ChildVector children); FilterSet _filterSet; ProjectionMap _projectionMap; @@ -120,7 +124,8 @@ private: class UnionNode : public Node { public: - static NodePtr create(Context& ctx, std::vector children); + static NodePtr create(Context& ctx, ChildVector children); + static NodePtr clone(Context& ctx, const UnionNode& other, ChildVector newChildren); void generateMemo(std::ostringstream& os) const; @@ -128,7 +133,7 @@ protected: void visit(AbstractVisitor& visitor) const override; private: - explicit UnionNode(Context& ctx, std::vector children); + explicit UnionNode(Context& ctx, ChildVector children); }; class GroupByNode : public Node { @@ -140,6 +145,7 @@ public: GroupByVector groupByVector, ProjectionMap projectionMap, NodePtr child); + static NodePtr clone(Context& ctx, const GroupByNode& other, NodePtr newChild); void generateMemo(std::ostringstream& os) const; @@ -162,6 +168,7 @@ public: ProjectionName projectionName, bool retainNonArrays, NodePtr child); + static NodePtr clone(Context& ctx, const UnwindNode& other, NodePtr newChild); void generateMemo(std::ostringstream& os) const; @@ -178,6 +185,7 @@ private: class WindNode : public Node { public: static NodePtr create(Context& ctx, ProjectionName projectionName, NodePtr child); + static NodePtr clone(Context& ctx, const WindNode& other, NodePtr newChild); void generateMemo(std::ostringstream& os) const; diff --git a/src/mongo/db/query/optimizer/optimizer_test.cpp b/src/mongo/db/query/optimizer/optimizer_test.cpp index f7eb881c531..86966e05a7e 100644 --- a/src/mongo/db/query/optimizer/optimizer_test.cpp +++ b/src/mongo/db/query/optimizer/optimizer_test.cpp @@ -41,6 +41,9 @@ TEST(Optimizer, Basic) { v.push_back(std::move(ptrScan)); NodePtr ptrJoin = MultiJoinNode::create(ctx, {}, {}, std::move(v)); ASSERT_EQ("NodeId: 1\nMultiJoin\nNodeId: 0\nScan\n", ptrJoin->generateMemo()); + + NodePtr cloned = ptrJoin->clone(ctx); + ASSERT_EQ("NodeId: 3\nMultiJoin\nNodeId: 2\nScan\n", cloned->generateMemo()); } } // namespace -- cgit v1.2.1