Compare commits
13 Commits
sample-bra
...
svilen-opt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1df7ae759 | ||
|
|
4352257977 | ||
|
|
6dee6f0a7b | ||
|
|
b7b7cd9f44 | ||
|
|
07ee2c7f5a | ||
|
|
55a0e18e1d | ||
|
|
6679e02a89 | ||
|
|
4a7131637a | ||
|
|
9edbc1726d | ||
|
|
18af06fa5a | ||
|
|
fdee50f0bd | ||
|
|
1f977bf829 | ||
|
|
893dab73b0 |
@@ -8,6 +8,7 @@ env.SConscript(
|
||||
dirs=[
|
||||
"collation",
|
||||
"datetime",
|
||||
'optimizer',
|
||||
],
|
||||
exports=[
|
||||
'env'
|
||||
|
||||
27
src/mongo/db/query/optimizer/SConscript
Normal file
27
src/mongo/db/query/optimizer/SConscript
Normal file
@@ -0,0 +1,27 @@
|
||||
# -*- mode: python -*-
|
||||
|
||||
Import("env")
|
||||
|
||||
env = env.Clone()
|
||||
|
||||
env.Library(
|
||||
target="optimizer",
|
||||
source=[
|
||||
"defs.cpp",
|
||||
"memo.cpp",
|
||||
"node.cpp",
|
||||
],
|
||||
LIBDEPS=[
|
||||
# "$BUILD_DIR/mongo/base",
|
||||
],
|
||||
)
|
||||
|
||||
env.CppUnitTest(
|
||||
target='optimizer_test',
|
||||
source=[
|
||||
'optimizer_test.cpp',
|
||||
],
|
||||
LIBDEPS=[
|
||||
'optimizer',
|
||||
]
|
||||
)
|
||||
305
src/mongo/db/query/optimizer/algebra/operator.h
Normal file
305
src/mongo/db/query/optimizer/algebra/operator.h
Normal file
@@ -0,0 +1,305 @@
|
||||
/**
|
||||
* 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 <vector>
|
||||
|
||||
#include "mongo/db/query/optimizer/algebra/polyvalue.h"
|
||||
|
||||
namespace mongo::optimizer {
|
||||
namespace algebra {
|
||||
|
||||
template <typename T, int S>
|
||||
struct OpNodeStorage {
|
||||
T _nodes[S];
|
||||
|
||||
template <typename... Ts>
|
||||
OpNodeStorage(Ts&&... vals) : _nodes{std::forward<Ts>(vals)...} {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct OpNodeStorage<T, 0> {};
|
||||
|
||||
/*=====-----
|
||||
*
|
||||
* Arity of operator can be:
|
||||
* 1. statically known - A, A, A, ...
|
||||
* 2. dynamic prefix with optional statically know - vector<A>, A, A, A, ...
|
||||
*
|
||||
* Denotations map A to some B.
|
||||
* So static arity <A,A,A> is mapped to <B,B,B>.
|
||||
* Similarly, arity <vector<A>,A> is mapped to <vector<B>,B>
|
||||
*
|
||||
* There is a wrinkle when B is a reference (if allowed at all)
|
||||
* Arity <vector<A>, A, A> is mapped to <vector<B>&, B&, B&> - note that the reference is lifted
|
||||
* outside of the vector.
|
||||
*
|
||||
*/
|
||||
template <typename Slot, typename Derived, int Arity>
|
||||
class OpSpecificArity : public OpNodeStorage<Slot, Arity> {
|
||||
using Base = OpNodeStorage<Slot, Arity>;
|
||||
|
||||
public:
|
||||
template <typename... Ts>
|
||||
OpSpecificArity(Ts&&... vals) : Base({std::forward<Ts>(vals)...}) {
|
||||
static_assert(sizeof...(Ts) == Arity, "constructor paramaters do not match");
|
||||
}
|
||||
|
||||
template <int I, std::enable_if_t<(I >= 0 && I < Arity), int> = 0>
|
||||
auto& get() noexcept {
|
||||
return this->_nodes[I];
|
||||
}
|
||||
|
||||
template <int I, std::enable_if_t<(I >= 0 && I < Arity), int> = 0>
|
||||
const auto& get() const noexcept {
|
||||
return this->_nodes[I];
|
||||
}
|
||||
};
|
||||
/*=====-----
|
||||
*
|
||||
* Operator with dynamic arity
|
||||
*
|
||||
*/
|
||||
template <typename Slot, typename Derived, int Arity>
|
||||
class OpSpecificDynamicArity : public OpSpecificArity<Slot, Derived, Arity> {
|
||||
using Base = OpSpecificArity<Slot, Derived, Arity>;
|
||||
|
||||
std::vector<Slot> _dyNodes;
|
||||
|
||||
public:
|
||||
template <typename... Ts>
|
||||
OpSpecificDynamicArity(std::vector<Slot> nodes, Ts&&... vals)
|
||||
: Base({std::forward<Ts>(vals)...}), _dyNodes(std::move(nodes)) {}
|
||||
|
||||
auto& nodes() {
|
||||
return _dyNodes;
|
||||
}
|
||||
const auto& nodes() const {
|
||||
return _dyNodes;
|
||||
}
|
||||
};
|
||||
|
||||
/*=====-----
|
||||
*
|
||||
* Semantic transport interface
|
||||
*
|
||||
*/
|
||||
namespace detail {
|
||||
template <typename D, typename T, typename = std::void_t<>>
|
||||
struct has_prepare : std::false_type {};
|
||||
template <typename D, typename T>
|
||||
struct has_prepare<D, T, std::void_t<decltype(std::declval<D>().prepare(std::declval<T&>()))>>
|
||||
: std::true_type {};
|
||||
|
||||
template <typename D, typename T>
|
||||
inline constexpr auto has_prepare_v = has_prepare<D, T>::value;
|
||||
|
||||
template <typename Slot, typename Derived, int Arity>
|
||||
inline constexpr int get_arity(const OpSpecificArity<Slot, Derived, Arity>*) {
|
||||
return Arity;
|
||||
}
|
||||
|
||||
template <typename Slot, typename Derived, int Arity>
|
||||
inline constexpr bool is_dynamic(const OpSpecificArity<Slot, Derived, Arity>*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Slot, typename Derived, int Arity>
|
||||
inline constexpr bool is_dynamic(const OpSpecificDynamicArity<Slot, Derived, Arity>*) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using OpConcreteType = typename std::remove_reference_t<T>::template get_t<0>;
|
||||
} // namespace detail
|
||||
|
||||
template <typename D, bool withSlot>
|
||||
class OpTransporter {
|
||||
D& _domain;
|
||||
|
||||
template <typename T, bool B>
|
||||
struct Deducer {};
|
||||
template <typename T>
|
||||
struct Deducer<T, true> {
|
||||
using type = decltype(std::declval<D>().transport(
|
||||
std::declval<T>(), std::declval<detail::OpConcreteType<T>&>()));
|
||||
};
|
||||
template <typename T>
|
||||
struct Deducer<T, false> {
|
||||
using type =
|
||||
decltype(std::declval<D>().transport(std::declval<detail::OpConcreteType<T>&>()));
|
||||
};
|
||||
template <typename T>
|
||||
using deduced_t = typename Deducer<T, withSlot>::type;
|
||||
|
||||
template <typename N, typename T, typename... Ts>
|
||||
auto transformStep(N&& slot, T&& op, Ts&&... args) {
|
||||
if constexpr (withSlot) {
|
||||
return _domain.transport(
|
||||
std::forward<N>(slot), std::forward<T>(op), std::forward<Ts>(args)...);
|
||||
} else {
|
||||
return _domain.transport(std::forward<T>(op), std::forward<Ts>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename N, typename T, size_t... I>
|
||||
auto transportUnpack(N&& slot, T&& op, std::index_sequence<I...>) {
|
||||
return transformStep(
|
||||
std::forward<N>(slot), std::forward<T>(op), op.template get<I>().visit(*this)...);
|
||||
}
|
||||
template <typename N, typename T, size_t... I>
|
||||
auto transportDynamicUnpack(N&& slot, T&& op, std::index_sequence<I...>) {
|
||||
std::vector<decltype(slot.visit(*this))> v;
|
||||
for (auto& node : op.nodes()) {
|
||||
v.emplace_back(node.visit(*this));
|
||||
}
|
||||
return transformStep(std::forward<N>(slot),
|
||||
std::forward<T>(op),
|
||||
std::move(v),
|
||||
op.template get<I>().visit(*this)...);
|
||||
}
|
||||
template <typename N, typename T, size_t... I>
|
||||
void transportUnpackVoid(N&& slot, T&& op, std::index_sequence<I...>) {
|
||||
(op.template get<I>().visit(*this), ...);
|
||||
return transformStep(std::forward<N>(slot), std::forward<T>(op), op.template get<I>()...);
|
||||
}
|
||||
template <typename N, typename T, size_t... I>
|
||||
void transportDynamicUnpackVoid(N&& slot, T&& op, std::index_sequence<I...>) {
|
||||
for (auto& node : op.nodes()) {
|
||||
node.visit(*this);
|
||||
}
|
||||
(op.template get<I>().visit(*this), ...);
|
||||
return transformStep(
|
||||
std::forward<N>(slot), std::forward<T>(op), op.nodes(), op.template get<I>()...);
|
||||
}
|
||||
|
||||
public:
|
||||
OpTransporter(D& domain) : _domain(domain) {}
|
||||
|
||||
template <typename N, typename T, typename R = deduced_t<N>>
|
||||
R operator()(N&& slot, T&& op) {
|
||||
// N is either `PolyValue<Ts...>&` or `const PolyValue<Ts...>&` i.e. reference
|
||||
// T is either `A&` or `const A&` where A is one of Ts
|
||||
using type = std::remove_reference_t<T>;
|
||||
|
||||
constexpr int arity = detail::get_arity(static_cast<type*>(nullptr));
|
||||
constexpr bool is_dynamic = detail::is_dynamic(static_cast<type*>(nullptr));
|
||||
|
||||
if constexpr (detail::has_prepare_v<D, type>) {
|
||||
_domain.prepare(std::forward<T>(op));
|
||||
}
|
||||
if constexpr (is_dynamic) {
|
||||
if constexpr (std::is_same_v<R, void>) {
|
||||
return transportDynamicUnpackVoid(
|
||||
std::forward<N>(slot), std::forward<T>(op), std::make_index_sequence<arity>{});
|
||||
} else {
|
||||
return transportDynamicUnpack(
|
||||
std::forward<N>(slot), std::forward<T>(op), std::make_index_sequence<arity>{});
|
||||
}
|
||||
} else {
|
||||
if constexpr (std::is_same_v<R, void>) {
|
||||
return transportUnpackVoid(
|
||||
std::forward<N>(slot), std::forward<T>(op), std::make_index_sequence<arity>{});
|
||||
} else {
|
||||
return transportUnpack(
|
||||
std::forward<N>(slot), std::forward<T>(op), std::make_index_sequence<arity>{});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename D, bool withSlot>
|
||||
class OpWalker {
|
||||
D& _domain;
|
||||
|
||||
template <typename N, typename T, typename... Ts>
|
||||
auto walkStep(N&& slot, T&& op, Ts&&... args) {
|
||||
if constexpr (withSlot) {
|
||||
return _domain.walk(
|
||||
std::forward<N>(slot), std::forward<T>(op), std::forward<Ts>(args)...);
|
||||
} else {
|
||||
return _domain.walk(std::forward<T>(op), std::forward<Ts>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename N, typename T, typename... Args, size_t... I>
|
||||
auto walkUnpack(N&& slot, T&& op, std::index_sequence<I...>, Args&&... args) {
|
||||
return walkStep(std::forward<N>(slot),
|
||||
std::forward<T>(op),
|
||||
std::forward<Args>(args)...,
|
||||
op.template get<I>()...);
|
||||
}
|
||||
template <typename N, typename T, typename... Args, size_t... I>
|
||||
auto walkDynamicUnpack(N&& slot, T&& op, std::index_sequence<I...>, Args&&... args) {
|
||||
return walkStep(std::forward<N>(slot),
|
||||
std::forward<T>(op),
|
||||
std::forward<Args>(args)...,
|
||||
op.nodes(),
|
||||
op.template get<I>()...);
|
||||
}
|
||||
|
||||
public:
|
||||
OpWalker(D& domain) : _domain(domain) {}
|
||||
|
||||
template <typename N, typename T, typename... Args>
|
||||
auto operator()(N&& slot, T&& op, Args&&... args) {
|
||||
// N is either `PolyValue<Ts...>&` or `const PolyValue<Ts...>&` i.e. reference
|
||||
// T is either `A&` or `const A&` where A is one of Ts
|
||||
using type = std::remove_reference_t<T>;
|
||||
|
||||
constexpr int arity = detail::get_arity(static_cast<type*>(nullptr));
|
||||
constexpr bool is_dynamic = detail::is_dynamic(static_cast<type*>(nullptr));
|
||||
|
||||
if constexpr (is_dynamic) {
|
||||
return walkDynamicUnpack(std::forward<N>(slot),
|
||||
std::forward<T>(op),
|
||||
std::make_index_sequence<arity>{},
|
||||
std::forward<Args>(args)...);
|
||||
} else {
|
||||
return walkUnpack(std::forward<N>(slot),
|
||||
std::forward<T>(op),
|
||||
std::make_index_sequence<arity>{},
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <bool withSlot = false, typename D, typename N>
|
||||
auto transport(N&& node, D& domain) {
|
||||
return node.visit(OpTransporter<D, withSlot>{domain});
|
||||
}
|
||||
|
||||
template <bool withSlot = false, typename D, typename N, typename... Args>
|
||||
auto walk(N&& node, D& domain, Args&&... args) {
|
||||
return node.visit(OpWalker<D, withSlot>{domain}, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
} // namespace algebra
|
||||
} // namespace mongo::optimizer
|
||||
381
src/mongo/db/query/optimizer/algebra/polyvalue.h
Normal file
381
src/mongo/db/query/optimizer/algebra/polyvalue.h
Normal file
@@ -0,0 +1,381 @@
|
||||
/**
|
||||
* 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 <array>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
namespace mongo::optimizer {
|
||||
namespace algebra {
|
||||
namespace detail {
|
||||
|
||||
template <typename T, typename... Args>
|
||||
inline constexpr bool is_one_of_v = std::disjunction_v<std::is_same<T, Args>...>;
|
||||
|
||||
template <typename T, typename... Args>
|
||||
inline constexpr bool is_one_of_f() {
|
||||
return is_one_of_v<T, Args...>;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
struct is_unique_t : std::true_type {};
|
||||
|
||||
template <typename H, typename... T>
|
||||
struct is_unique_t<H, T...>
|
||||
: std::bool_constant<!is_one_of_f<H, T...>() && is_unique_t<T...>::value> {};
|
||||
|
||||
template <typename... Args>
|
||||
inline constexpr bool is_unique_v = is_unique_t<Args...>::value;
|
||||
|
||||
// Given the type T find its index in Ts
|
||||
template <typename T, typename... Ts>
|
||||
static inline constexpr int find_index() {
|
||||
static_assert(detail::is_unique_v<Ts...>, "Types must be unique");
|
||||
constexpr bool matchVector[] = {std::is_same<T, Ts>::value...};
|
||||
|
||||
for (int index = 0; index < static_cast<int>(sizeof...(Ts)); ++index) {
|
||||
if (matchVector[index]) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <int N, typename T, typename... Ts>
|
||||
struct get_type_by_index_impl {
|
||||
using type = typename get_type_by_index_impl<N - 1, Ts...>::type;
|
||||
};
|
||||
template <typename T, typename... Ts>
|
||||
struct get_type_by_index_impl<0, T, Ts...> {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
// Given the index I return the type from Ts
|
||||
template <int I, typename... Ts>
|
||||
using get_type_by_index = typename get_type_by_index_impl<I, Ts...>::type;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/*=====-----
|
||||
*
|
||||
* The overload trick to construct visitors from lambdas.
|
||||
*
|
||||
*/
|
||||
template <class... Ts>
|
||||
struct overload : Ts... {
|
||||
using Ts::operator()...;
|
||||
};
|
||||
template <class... Ts>
|
||||
overload(Ts...)->overload<Ts...>;
|
||||
|
||||
/*=====-----
|
||||
*
|
||||
* Forward declarations
|
||||
*
|
||||
*/
|
||||
template <typename... Ts>
|
||||
class PolyValue;
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
class ControlBlockVTable;
|
||||
|
||||
/*=====-----
|
||||
*
|
||||
* The base control block that PolyValue holds.
|
||||
*
|
||||
* It does not contain anything else by the runtime tag.
|
||||
*
|
||||
*/
|
||||
template <typename... Ts>
|
||||
class ControlBlock {
|
||||
const int _tag;
|
||||
|
||||
protected:
|
||||
ControlBlock(int tag) noexcept : _tag(tag) {}
|
||||
|
||||
public:
|
||||
auto getRuntimeTag() const noexcept {
|
||||
return _tag;
|
||||
}
|
||||
};
|
||||
|
||||
/*=====-----
|
||||
*
|
||||
* The concrete control block VTable generator.
|
||||
*
|
||||
* It must be empty ad PolyValue derives from the generators
|
||||
* and we want EBO to kick in.
|
||||
*
|
||||
*/
|
||||
template <typename T, typename... Ts>
|
||||
class ControlBlockVTable {
|
||||
static constexpr int _staticTag = detail::find_index<T, Ts...>();
|
||||
static_assert(_staticTag != -1, "Type must be on the list");
|
||||
|
||||
using AbstractType = ControlBlock<Ts...>;
|
||||
using PolyValueType = PolyValue<Ts...>;
|
||||
|
||||
/*=====-----
|
||||
*
|
||||
* The concrete control block for every type T of Ts.
|
||||
*
|
||||
* It derives from the ControlBlock. All methods are private and only
|
||||
* the friend class ControlBlockVTable can call them.
|
||||
*
|
||||
*/
|
||||
class ConcreteType : public AbstractType {
|
||||
T _t;
|
||||
|
||||
public:
|
||||
template <typename... Args>
|
||||
ConcreteType(Args&&... args) : AbstractType(_staticTag), _t(std::forward<Args>(args)...) {}
|
||||
|
||||
const T* getPtr() const {
|
||||
return &_t;
|
||||
}
|
||||
|
||||
T* getPtr() {
|
||||
return &_t;
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr auto concrete(AbstractType* block) noexcept {
|
||||
return static_cast<ConcreteType*>(block);
|
||||
}
|
||||
|
||||
static constexpr auto concrete(const AbstractType* block) noexcept {
|
||||
return static_cast<const ConcreteType*>(block);
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename... Args>
|
||||
static AbstractType* make(Args&&... args) {
|
||||
return new ConcreteType(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
static AbstractType* clone(const AbstractType* block) {
|
||||
return new ConcreteType(*concrete(block));
|
||||
}
|
||||
|
||||
static void destroy(AbstractType* block) noexcept {
|
||||
delete concrete(block);
|
||||
}
|
||||
|
||||
static bool compareEq(AbstractType* blockLhs, AbstractType* blockRhs) noexcept {
|
||||
if (blockLhs->getRuntimeTag() == blockRhs->getRuntimeTag()) {
|
||||
return *castConst<T>(blockLhs) == *castConst<T>(blockRhs);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static constexpr bool is_v = std::is_base_of_v<U, T>;
|
||||
|
||||
template <typename U>
|
||||
static U* cast(AbstractType* block) {
|
||||
if constexpr (is_v<U>) {
|
||||
return static_cast<U*>(concrete(block)->getPtr());
|
||||
} else {
|
||||
// gcc bug 81676
|
||||
(void)block;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static const U* castConst(const AbstractType* block) {
|
||||
if constexpr (is_v<U>) {
|
||||
return static_cast<const U*>(concrete(block)->getPtr());
|
||||
} else {
|
||||
// gcc bug 81676
|
||||
(void)block;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename V, typename... Args>
|
||||
static auto visit(V&& v, PolyValueType& holder, AbstractType* block, Args&&... args) {
|
||||
return v(holder, *cast<T>(block), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename V, typename... Args>
|
||||
static auto visitConst(V&& v,
|
||||
const PolyValueType& holder,
|
||||
const AbstractType* block,
|
||||
Args&&... args) {
|
||||
return v(holder, *castConst<T>(block), std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
/*=====-----
|
||||
*
|
||||
* This is a variation on variant and polymorphic value theme.
|
||||
*
|
||||
* A tag based dispatch
|
||||
*
|
||||
* Supported operations:
|
||||
* - construction
|
||||
* - destruction
|
||||
* - clone a = b;
|
||||
* - cast a.cast<T>()
|
||||
* - multi-method cast to common base a.cast<B>()
|
||||
* - multi-method visit
|
||||
*/
|
||||
template <typename... Ts>
|
||||
class PolyValue : private ControlBlockVTable<Ts, Ts...>... {
|
||||
static_assert(detail::is_unique_v<Ts...>, "Types must be unique");
|
||||
static_assert(std::conjunction_v<std::is_empty<ControlBlockVTable<Ts, Ts...>>...>,
|
||||
"VTable base classes must be empty");
|
||||
|
||||
ControlBlock<Ts...>* _object{nullptr};
|
||||
|
||||
PolyValue(ControlBlock<Ts...>* object) noexcept : _object(object) {}
|
||||
|
||||
auto tag() const noexcept {
|
||||
return _object->getRuntimeTag();
|
||||
}
|
||||
|
||||
void check() const {
|
||||
if (!_object) {
|
||||
throw std::logic_error("PolyValue is empty");
|
||||
}
|
||||
}
|
||||
|
||||
static void destroy(ControlBlock<Ts...>* object) {
|
||||
static constexpr std::array destroyTbl = {&ControlBlockVTable<Ts, Ts...>::destroy...};
|
||||
|
||||
destroyTbl[object->getRuntimeTag()](object);
|
||||
}
|
||||
|
||||
public:
|
||||
PolyValue() = delete;
|
||||
|
||||
PolyValue(const PolyValue& other) {
|
||||
static constexpr std::array cloneTbl = {&ControlBlockVTable<Ts, Ts...>::clone...};
|
||||
if (other._object) {
|
||||
_object = cloneTbl[other.tag()](other._object);
|
||||
}
|
||||
}
|
||||
|
||||
PolyValue(PolyValue&& other) noexcept {
|
||||
swap(other);
|
||||
}
|
||||
|
||||
~PolyValue() noexcept {
|
||||
if (_object) {
|
||||
destroy(_object);
|
||||
}
|
||||
}
|
||||
|
||||
PolyValue& operator=(PolyValue other) noexcept {
|
||||
swap(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static PolyValue make(Args&&... args) {
|
||||
return PolyValue{ControlBlockVTable<T, Ts...>::make(std::forward<Args>(args)...)};
|
||||
}
|
||||
|
||||
template <int I>
|
||||
using get_t = detail::get_type_by_index<I, Ts...>;
|
||||
|
||||
template <typename V, typename... Args>
|
||||
auto visit(V&& v, Args&&... args) {
|
||||
// unfortunately gcc rejects much nicer code, clang and msvc accept
|
||||
// static constexpr std::array visitTbl = { &ControlBlockVTable<Ts, Ts...>::template
|
||||
// visit<V>... };
|
||||
|
||||
using FunPtrType =
|
||||
decltype(&ControlBlockVTable<get_t<0>, Ts...>::template visit<V, Args...>);
|
||||
static constexpr FunPtrType visitTbl[] = {
|
||||
&ControlBlockVTable<Ts, Ts...>::template visit<V, Args...>...};
|
||||
|
||||
check();
|
||||
return visitTbl[tag()](std::forward<V>(v), *this, _object, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename V, typename... Args>
|
||||
auto visit(V&& v, Args&&... args) const {
|
||||
// unfortunately gcc rejects much nicer code, clang and msvc accept
|
||||
// static constexpr std::array visitTbl = { &ControlBlockVTable<Ts, Ts...>::template
|
||||
// visitConst<V>... };
|
||||
|
||||
using FunPtrType =
|
||||
decltype(&ControlBlockVTable<get_t<0>, Ts...>::template visitConst<V, Args...>);
|
||||
static constexpr FunPtrType visitTbl[] = {
|
||||
&ControlBlockVTable<Ts, Ts...>::template visitConst<V, Args...>...};
|
||||
|
||||
check();
|
||||
return visitTbl[tag()](std::forward<V>(v), *this, _object, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* cast() {
|
||||
check();
|
||||
static constexpr std::array castTbl = {&ControlBlockVTable<Ts, Ts...>::template cast<T>...};
|
||||
return castTbl[tag()](_object);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T* cast() const {
|
||||
static constexpr std::array castTbl = {
|
||||
&ControlBlockVTable<Ts, Ts...>::template castConst<T>...};
|
||||
|
||||
check();
|
||||
return castTbl[tag()](_object);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
static constexpr std::array isTbl = {ControlBlockVTable<Ts, Ts...>::template is_v<T>...};
|
||||
|
||||
check();
|
||||
return isTbl[tag()];
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return !_object;
|
||||
}
|
||||
|
||||
void swap(PolyValue& other) noexcept {
|
||||
std::swap(other._object, _object);
|
||||
}
|
||||
|
||||
bool operator==(const PolyValue& rhs) const noexcept {
|
||||
static constexpr std::array cmp = {ControlBlockVTable<Ts, Ts...>::compareEq...};
|
||||
return cmp[tag()](_object, rhs._object);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace algebra
|
||||
} // namespace mongo::optimizer
|
||||
40
src/mongo/db/query/optimizer/defs.cpp
Normal file
40
src/mongo/db/query/optimizer/defs.cpp
Normal 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
|
||||
52
src/mongo/db/query/optimizer/defs.h
Normal file
52
src/mongo/db/query/optimizer/defs.h
Normal 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
|
||||
38
src/mongo/db/query/optimizer/filter.h
Normal file
38
src/mongo/db/query/optimizer/filter.h
Normal 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
|
||||
43
src/mongo/db/query/optimizer/memo.cpp
Normal file
43
src/mongo/db/query/optimizer/memo.cpp
Normal file
@@ -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
|
||||
* <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/algebra/operator.h"
|
||||
#include "mongo/db/query/optimizer/memo.h"
|
||||
#include "mongo/db/query/optimizer/node.h"
|
||||
|
||||
namespace mongo::optimizer {
|
||||
|
||||
std::string MemoGenerator::generateMemo(const PolymorphicNode& e) {
|
||||
_os.str("");
|
||||
_os.clear();
|
||||
algebra::transport<false>(e, *this);
|
||||
return _os.str();
|
||||
}
|
||||
|
||||
} // namespace mongo::optimizer
|
||||
54
src/mongo/db/query/optimizer/memo.h
Normal file
54
src/mongo/db/query/optimizer/memo.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 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>
|
||||
|
||||
#include "mongo/db/query/optimizer/node.h"
|
||||
|
||||
namespace mongo::optimizer {
|
||||
|
||||
class MemoGenerator {
|
||||
public:
|
||||
template <typename T, typename... Ts>
|
||||
void transport(const T&, Ts&&...) {}
|
||||
|
||||
template <typename T>
|
||||
void prepare(const T& n) {
|
||||
n.generateMemo(_os);
|
||||
}
|
||||
|
||||
std::string generateMemo(const PolymorphicNode& e);
|
||||
|
||||
private:
|
||||
std::ostringstream _os;
|
||||
};
|
||||
|
||||
} // namespace mongo::optimizer
|
||||
116
src/mongo/db/query/optimizer/node.cpp
Normal file
116
src/mongo/db/query/optimizer/node.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* 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 <functional>
|
||||
#include <stack>
|
||||
|
||||
#include "mongo/db/query/optimizer/memo.h"
|
||||
#include "mongo/db/query/optimizer/node.h"
|
||||
|
||||
namespace mongo::optimizer {
|
||||
|
||||
Node::Node(Context& ctx) : _nodeId(ctx.getNextNodeId()) {}
|
||||
|
||||
void Node::generateMemoBase(std::ostringstream& os) const {
|
||||
os << "NodeId: " << _nodeId << "\n";
|
||||
}
|
||||
|
||||
ScanNode::ScanNode(Context& ctx, CollectionNameType collectionName)
|
||||
: Base(), Node(ctx), _collectionName(std::move(collectionName)) {}
|
||||
|
||||
void ScanNode::generateMemo(std::ostringstream& os) const {
|
||||
Node::generateMemoBase(os);
|
||||
os << "Scan"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
MultiJoinNode::MultiJoinNode(Context& ctx,
|
||||
FilterSet filterSet,
|
||||
ProjectionMap projectionMap,
|
||||
PolymorphicNodeVector children)
|
||||
: Base(std::move(children)),
|
||||
Node(ctx),
|
||||
_filterSet(std::move(filterSet)),
|
||||
_projectionMap(std::move(projectionMap)) {}
|
||||
|
||||
void MultiJoinNode::generateMemo(std::ostringstream& os) const {
|
||||
Node::generateMemoBase(os);
|
||||
os << "MultiJoin"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
UnionNode::UnionNode(Context& ctx, PolymorphicNodeVector children)
|
||||
: Base(std::move(children)), Node(ctx) {}
|
||||
|
||||
void UnionNode::generateMemo(std::ostringstream& os) const {
|
||||
Node::generateMemoBase(os);
|
||||
os << "Union"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
GroupByNode::GroupByNode(Context& ctx,
|
||||
GroupByNode::GroupByVector groupByVector,
|
||||
GroupByNode::ProjectionMap projectionMap,
|
||||
PolymorphicNode child)
|
||||
: Base(std::move(child)),
|
||||
Node(ctx),
|
||||
_groupByVector(std::move(groupByVector)),
|
||||
_projectionMap(std::move(projectionMap)) {}
|
||||
|
||||
void GroupByNode::generateMemo(std::ostringstream& os) const {
|
||||
Node::generateMemoBase(os);
|
||||
os << "GroupBy"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
UnwindNode::UnwindNode(Context& ctx,
|
||||
ProjectionName projectionName,
|
||||
const bool retainNonArrays,
|
||||
PolymorphicNode child)
|
||||
: Base(std::move(child)),
|
||||
Node(ctx),
|
||||
_projectionName(std::move(projectionName)),
|
||||
_retainNonArrays(retainNonArrays) {}
|
||||
|
||||
void UnwindNode::generateMemo(std::ostringstream& os) const {
|
||||
Node::generateMemoBase(os);
|
||||
os << "Unwind"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
WindNode::WindNode(Context& ctx, ProjectionName projectionName, PolymorphicNode child)
|
||||
: Base(std::move(child)), Node(ctx), _projectionName(std::move(projectionName)) {}
|
||||
|
||||
void WindNode::generateMemo(std::ostringstream& os) const {
|
||||
Node::generateMemoBase(os);
|
||||
os << "Wind"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
} // namespace mongo::optimizer
|
||||
183
src/mongo/db/query/optimizer/node.h
Normal file
183
src/mongo/db/query/optimizer/node.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* 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/algebra/operator.h"
|
||||
#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 ScanNode;
|
||||
class MultiJoinNode;
|
||||
class UnionNode;
|
||||
class GroupByNode;
|
||||
class UnwindNode;
|
||||
class WindNode;
|
||||
|
||||
using PolymorphicNode =
|
||||
algebra::PolyValue<ScanNode, MultiJoinNode, UnionNode, GroupByNode, UnwindNode, WindNode>;
|
||||
|
||||
template <typename Derived, size_t Arity>
|
||||
using Operator = algebra::OpSpecificArity<PolymorphicNode, Derived, Arity>;
|
||||
|
||||
template <typename Derived, size_t Arity>
|
||||
using OperatorDynamic = algebra::OpSpecificDynamicArity<PolymorphicNode, Derived, Arity>;
|
||||
|
||||
template <typename Derived>
|
||||
using OperatorDynamicHomogenous = OperatorDynamic<Derived, 0>;
|
||||
|
||||
using PolymorphicNodeVector = std::vector<PolymorphicNode>;
|
||||
|
||||
template <typename T, typename... Args>
|
||||
inline auto make(Args&&... args) {
|
||||
return PolymorphicNode::make<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline auto makeSeq(Args&&... args) {
|
||||
PolymorphicNodeVector seq;
|
||||
(seq.emplace_back(std::forward<Args>(args)), ...);
|
||||
return seq;
|
||||
}
|
||||
|
||||
class Node {
|
||||
protected:
|
||||
explicit Node(Context& ctx);
|
||||
|
||||
void generateMemoBase(std::ostringstream& os) const;
|
||||
|
||||
public:
|
||||
Node() = delete;
|
||||
|
||||
private:
|
||||
const NodeIdType _nodeId;
|
||||
};
|
||||
|
||||
class ScanNode final : public Operator<ScanNode, 0>, public Node {
|
||||
using Base = Operator<ScanNode, 0>;
|
||||
|
||||
public:
|
||||
explicit ScanNode(Context& ctx, CollectionNameType collectionName);
|
||||
|
||||
void generateMemo(std::ostringstream& os) const;
|
||||
|
||||
private:
|
||||
const CollectionNameType _collectionName;
|
||||
};
|
||||
|
||||
class MultiJoinNode final : public OperatorDynamicHomogenous<MultiJoinNode>, public Node {
|
||||
using Base = OperatorDynamicHomogenous<MultiJoinNode>;
|
||||
|
||||
public:
|
||||
using FilterSet = std::unordered_set<FilterType>;
|
||||
using ProjectionMap = std::unordered_map<ProjectionName, ProjectionType>;
|
||||
|
||||
explicit MultiJoinNode(Context& ctx,
|
||||
FilterSet filterSet,
|
||||
ProjectionMap projectionMap,
|
||||
PolymorphicNodeVector children);
|
||||
|
||||
void generateMemo(std::ostringstream& os) const;
|
||||
|
||||
private:
|
||||
FilterSet _filterSet;
|
||||
ProjectionMap _projectionMap;
|
||||
};
|
||||
|
||||
class UnionNode final : public OperatorDynamicHomogenous<UnionNode>, public Node {
|
||||
using Base = OperatorDynamicHomogenous<UnionNode>;
|
||||
|
||||
public:
|
||||
explicit UnionNode(Context& ctx, PolymorphicNodeVector children);
|
||||
|
||||
void generateMemo(std::ostringstream& os) const;
|
||||
};
|
||||
|
||||
class GroupByNode : public Operator<GroupByNode, 1>, public Node {
|
||||
using Base = Operator<GroupByNode, 1>;
|
||||
|
||||
public:
|
||||
using GroupByVector = std::vector<ProjectionName>;
|
||||
using ProjectionMap = std::unordered_map<ProjectionName, ProjectionType>;
|
||||
|
||||
explicit GroupByNode(Context& ctx,
|
||||
GroupByVector groupByVector,
|
||||
ProjectionMap projectionMap,
|
||||
PolymorphicNode child);
|
||||
|
||||
void generateMemo(std::ostringstream& os) const;
|
||||
|
||||
private:
|
||||
GroupByVector _groupByVector;
|
||||
ProjectionMap _projectionMap;
|
||||
};
|
||||
|
||||
class UnwindNode final : public Operator<UnwindNode, 1>, public Node {
|
||||
using Base = Operator<UnwindNode, 1>;
|
||||
|
||||
public:
|
||||
explicit UnwindNode(Context& ctx,
|
||||
ProjectionName projectionName,
|
||||
bool retainNonArrays,
|
||||
PolymorphicNode child);
|
||||
|
||||
void generateMemo(std::ostringstream& os) const;
|
||||
|
||||
private:
|
||||
const ProjectionName _projectionName;
|
||||
const bool _retainNonArrays;
|
||||
};
|
||||
|
||||
class WindNode final : public Operator<WindNode, 1>, public Node {
|
||||
using Base = Operator<WindNode, 1>;
|
||||
|
||||
public:
|
||||
explicit WindNode(Context& ctx, ProjectionName projectionName, PolymorphicNode child);
|
||||
|
||||
void generateMemo(std::ostringstream& os) const;
|
||||
|
||||
private:
|
||||
const ProjectionName _projectionName;
|
||||
};
|
||||
|
||||
} // namespace mongo::optimizer
|
||||
56
src/mongo/db/query/optimizer/optimizer_test.cpp
Normal file
56
src/mongo/db/query/optimizer/optimizer_test.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 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/memo.h"
|
||||
#include "mongo/db/query/optimizer/node.h"
|
||||
#include "mongo/unittest/unittest.h"
|
||||
|
||||
namespace mongo::optimizer {
|
||||
namespace {
|
||||
|
||||
TEST(Optimizer, Basic) {
|
||||
Context ctx;
|
||||
MemoGenerator gen;
|
||||
|
||||
PolymorphicNode scanNode = make<ScanNode>(ctx, "test");
|
||||
ASSERT_EQ("NodeId: 0\nScan\n", gen.generateMemo(scanNode));
|
||||
|
||||
PolymorphicNode joinNode = make<MultiJoinNode>(ctx,
|
||||
MultiJoinNode::FilterSet{},
|
||||
MultiJoinNode::ProjectionMap{},
|
||||
makeSeq(std::move(scanNode)));
|
||||
ASSERT_EQ("NodeId: 1\nMultiJoin\nNodeId: 0\nScan\n", gen.generateMemo(joinNode));
|
||||
|
||||
|
||||
PolymorphicNode cloned = joinNode;
|
||||
ASSERT_EQ("NodeId: 1\nMultiJoin\nNodeId: 0\nScan\n", gen.generateMemo(cloned));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mongo::optimizer
|
||||
38
src/mongo/db/query/optimizer/projection.h
Normal file
38
src/mongo/db/query/optimizer/projection.h
Normal 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
|
||||
38
src/mongo/db/query/optimizer/props.h
Normal file
38
src/mongo/db/query/optimizer/props.h
Normal 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
|
||||
Reference in New Issue
Block a user