optimizer

This commit is contained in:
Svilen Mihaylov
2020-09-09 13:23:30 -04:00
parent 067c84541c
commit 1f977bf829
11 changed files with 726 additions and 0 deletions

View File

@@ -8,6 +8,7 @@ env.SConscript(
dirs=[
"collation",
"datetime",
'optimizer',
],
exports=[
'env'

View File

@@ -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',
]
)

View File

@@ -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
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* 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

View File

@@ -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
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* 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 <string>
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

View File

@@ -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
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* 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 <string>
namespace mongo::optimizer {
using FilterType = std::string;
} // namespace mongo::optimizer

View File

@@ -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
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* 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<NodePtr> 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<NodePtr> 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<NodePtr> 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<NodePtr> children) {
return NodePtr(new UnionNode(ctx, std::move(children)));
}
UnionNode::UnionNode(Context& ctx, std::vector<NodePtr> 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

View File

@@ -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
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* 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 <memory>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#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<Node>;
class AbstractVisitor;
class Node {
friend class AbstractVisitor;
protected:
explicit Node(Context& ctx);
explicit Node(Context& ctx, NodePtr child);
explicit Node(Context& ctx, std::vector<NodePtr> 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<NodePtr> _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<FilterType>;
using ProjectionMap = std::unordered_map<ProjectionName, ProjectionType>;
static NodePtr create(Context& ctx,
FilterSet filterSet,
ProjectionMap projectionMap,
std::vector<NodePtr> children);
void generateMemoInternal(std::ostringstream& os);
protected:
void visit(AbstractVisitor& visitor) override;
private:
explicit MultiJoinNode(Context& ctx,
FilterSet filterSet,
ProjectionMap projectionMap,
std::vector<NodePtr> children);
FilterSet _filterSet;
ProjectionMap _projectionMap;
};
class UnionNode : public Node {
public:
static NodePtr create(Context& ctx, std::vector<NodePtr> children);
void generateMemoInternal(std::ostringstream& os);
protected:
void visit(AbstractVisitor& visitor) override;
private:
explicit UnionNode(Context& ctx, std::vector<NodePtr> children);
};
class GroupByNode : public Node {
public:
using GroupByVector = std::vector<ProjectionName>;
using ProjectionMap = std::unordered_map<ProjectionName, ProjectionType>;
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

View File

@@ -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
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* 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

View File

@@ -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
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* 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 <string>
namespace mongo::optimizer {
using ProjectionType = std::string;
} // namespace mongo::optimizer

View File

@@ -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
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* 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 <string>
namespace mongo::optimizer {
using LogicalProperties = std::string;
} // namespace mongo::optimizer

View File

@@ -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
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* 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 <string>
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