mirror of https://gitee.com/bigwinds/arangodb
Splicing gather cleanup (#10479)
Some cleanup and deprecation information
This commit is contained in:
parent
2902ab9c23
commit
168103af88
|
@ -896,7 +896,7 @@ if (CMAKE_COMPILER_IS_GNUCC)
|
||||||
message(STATUS "Compiler type GNU: ${CMAKE_CXX_COMPILER}")
|
message(STATUS "Compiler type GNU: ${CMAKE_CXX_COMPILER}")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set(BASE_FLAGS "-Wall -Wextra -Wno-unused-parameter ${BASE_FLAGS}")
|
set(BASE_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-deprecated-declarations ${BASE_FLAGS}")
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS "-g" CACHE INTERNAL "default C compiler flags")
|
set(CMAKE_C_FLAGS "-g" CACHE INTERNAL "default C compiler flags")
|
||||||
set(CMAKE_C_FLAGS_DEBUG "-O0 -g -D_DEBUG=1" CACHE INTERNAL "C debug flags")
|
set(CMAKE_C_FLAGS_DEBUG "-O0 -g -D_DEBUG=1" CACHE INTERNAL "C debug flags")
|
||||||
|
@ -915,7 +915,7 @@ elseif (CMAKE_COMPILER_IS_CLANG)
|
||||||
message(STATUS "Compiler type CLANG: ${CMAKE_CXX_COMPILER}")
|
message(STATUS "Compiler type CLANG: ${CMAKE_CXX_COMPILER}")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set(BASE_FLAGS "-Wall -Wextra -Wno-unused-parameter ${BASE_FLAGS}")
|
set(BASE_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-deprecated-declarations ${BASE_FLAGS}")
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS "-g" CACHE INTERNAL "default C compiler flags")
|
set(CMAKE_C_FLAGS "-g" CACHE INTERNAL "default C compiler flags")
|
||||||
set(CMAKE_C_FLAGS_DEBUG "-O0 -g -D_DEBUG=1" CACHE INTERNAL "C debug flags")
|
set(CMAKE_C_FLAGS_DEBUG "-O0 -g -D_DEBUG=1" CACHE INTERNAL "C debug flags")
|
||||||
|
@ -934,6 +934,8 @@ elseif (MSVC)
|
||||||
message(STATUS "Compiler type MSVC: ${CMAKE_CXX_COMPILER}")
|
message(STATUS "Compiler type MSVC: ${CMAKE_CXX_COMPILER}")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
set(BASE_FLAGS "/wd4996 ${BASE_FLAGS}")
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS "/MTd" CACHE INTERNAL "default C++ compiler flags")
|
set(CMAKE_C_FLAGS "/MTd" CACHE INTERNAL "default C++ compiler flags")
|
||||||
set(CMAKE_C_FLAGS_DEBUG "/D _DEBUG /MTd /Zi /Ob0 /Od /RTC1 /bigobj" CACHE INTERNAL "C++ debug flags")
|
set(CMAKE_C_FLAGS_DEBUG "/D _DEBUG /MTd /Zi /Ob0 /Od /RTC1 /bigobj" CACHE INTERNAL "C++ debug flags")
|
||||||
set(CMAKE_C_FLAGS_MINSIZEREL "/MT /O1 /Ob1" CACHE INTERNAL "C++ minimal size flags")
|
set(CMAKE_C_FLAGS_MINSIZEREL "/MT /O1 /Ob1" CACHE INTERNAL "C++ minimal size flags")
|
||||||
|
|
|
@ -57,8 +57,6 @@ class ShadowAqlItemRow;
|
||||||
* => If all rows have been Fetched, it will return DONE and an AqlItemMatrix, the Matrix will return results
|
* => If all rows have been Fetched, it will return DONE and an AqlItemMatrix, the Matrix will return results
|
||||||
* => Any later call will return DONE and a nullptr. So make sure you keep the Matrix.
|
* => Any later call will return DONE and a nullptr. So make sure you keep the Matrix.
|
||||||
* => This state can be left only if the shadowRow is fetched.
|
* => This state can be left only if the shadowRow is fetched.
|
||||||
* - fetchBlockForPassthrough()
|
|
||||||
* => Cannot be used! Only required to make the code compile
|
|
||||||
* - preFetchNumberOfRows()
|
* - preFetchNumberOfRows()
|
||||||
* => Will do the same as fetchAllRows, but NOT give out the data, it will only hold it internally.
|
* => Will do the same as fetchAllRows, but NOT give out the data, it will only hold it internally.
|
||||||
* => On response it will inform the caller on exactly how many Rows will be returned until the next ShadowRow appears.
|
* => On response it will inform the caller on exactly how many Rows will be returned until the next ShadowRow appears.
|
||||||
|
|
|
@ -331,11 +331,13 @@ struct AqlValue final {
|
||||||
|
|
||||||
/// @brief materializes a value into the builder
|
/// @brief materializes a value into the builder
|
||||||
void toVelocyPack(velocypack::Options const*, arangodb::velocypack::Builder&, bool resolveExternals) const;
|
void toVelocyPack(velocypack::Options const*, arangodb::velocypack::Builder&, bool resolveExternals) const;
|
||||||
|
[[deprecated("Pass VPackOptions instead of the transaction")]]
|
||||||
void toVelocyPack(transaction::Methods*, arangodb::velocypack::Builder&, bool resolveExternals) const;
|
void toVelocyPack(transaction::Methods*, arangodb::velocypack::Builder&, bool resolveExternals) const;
|
||||||
|
|
||||||
/// @brief materialize a value into a new one. this expands docvecs and
|
/// @brief materialize a value into a new one. this expands docvecs and
|
||||||
/// ranges
|
/// ranges
|
||||||
AqlValue materialize(velocypack::Options const*, bool& hasCopied, bool resolveExternals) const;
|
AqlValue materialize(velocypack::Options const*, bool& hasCopied, bool resolveExternals) const;
|
||||||
|
[[deprecated("Pass VPackOptions instead of the transaction")]]
|
||||||
AqlValue materialize(transaction::Methods*, bool& hasCopied, bool resolveExternals) const;
|
AqlValue materialize(transaction::Methods*, bool& hasCopied, bool resolveExternals) const;
|
||||||
|
|
||||||
/// @brief return the slice for the value
|
/// @brief return the slice for the value
|
||||||
|
@ -368,6 +370,7 @@ struct AqlValue final {
|
||||||
/// @brief compare function for two values
|
/// @brief compare function for two values
|
||||||
static int Compare(velocypack::Options const*, AqlValue const& left,
|
static int Compare(velocypack::Options const*, AqlValue const& left,
|
||||||
AqlValue const& right, bool useUtf8);
|
AqlValue const& right, bool useUtf8);
|
||||||
|
[[deprecated("Pass VPackOptions instead of the transaction")]]
|
||||||
static int Compare(transaction::Methods*, AqlValue const& left,
|
static int Compare(transaction::Methods*, AqlValue const& left,
|
||||||
AqlValue const& right, bool useUtf8);
|
AqlValue const& right, bool useUtf8);
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ namespace aql {
|
||||||
/// @brief Helper class to materialize AqlValues (see AqlValue::materialize).
|
/// @brief Helper class to materialize AqlValues (see AqlValue::materialize).
|
||||||
struct AqlValueMaterializer {
|
struct AqlValueMaterializer {
|
||||||
explicit AqlValueMaterializer(velocypack::Options const* options);
|
explicit AqlValueMaterializer(velocypack::Options const* options);
|
||||||
|
[[deprecated("Pass VPackOptions instead of the transaction")]]
|
||||||
explicit AqlValueMaterializer(arangodb::transaction::Methods* trx);
|
explicit AqlValueMaterializer(arangodb::transaction::Methods* trx);
|
||||||
|
|
||||||
AqlValueMaterializer(AqlValueMaterializer const& other);
|
AqlValueMaterializer(AqlValueMaterializer const& other);
|
||||||
|
|
|
@ -36,13 +36,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
template <CalculationType calculationType>
|
|
||||||
constexpr bool CalculationExecutor<calculationType>::Properties::preservesOrder;
|
|
||||||
template <CalculationType calculationType>
|
|
||||||
constexpr BlockPassthrough CalculationExecutor<calculationType>::Properties::allowsBlockPassthrough;
|
|
||||||
template <CalculationType calculationType>
|
|
||||||
constexpr bool CalculationExecutor<calculationType>::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
CalculationExecutorInfos::CalculationExecutorInfos(
|
CalculationExecutorInfos::CalculationExecutorInfos(
|
||||||
RegisterId outputRegister, RegisterId nrInputRegisters,
|
RegisterId outputRegister, RegisterId nrInputRegisters,
|
||||||
RegisterId nrOutputRegisters, std::unordered_set<RegisterId> registersToClear,
|
RegisterId nrOutputRegisters, std::unordered_set<RegisterId> registersToClear,
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "Aql/IndexNode.h"
|
#include "Aql/IndexNode.h"
|
||||||
#include "Aql/ModificationNodes.h"
|
#include "Aql/ModificationNodes.h"
|
||||||
#include "Aql/MultiDependencySingleRowFetcher.h"
|
#include "Aql/MultiDependencySingleRowFetcher.h"
|
||||||
|
#include "Aql/ParallelUnsortedGatherExecutor.h"
|
||||||
#include "Aql/Query.h"
|
#include "Aql/Query.h"
|
||||||
#include "Aql/RemoteExecutor.h"
|
#include "Aql/RemoteExecutor.h"
|
||||||
#include "Aql/ScatterExecutor.h"
|
#include "Aql/ScatterExecutor.h"
|
||||||
|
@ -49,7 +50,6 @@
|
||||||
#include "Aql/SortRegister.h"
|
#include "Aql/SortRegister.h"
|
||||||
#include "Aql/SortingGatherExecutor.h"
|
#include "Aql/SortingGatherExecutor.h"
|
||||||
#include "Aql/UnsortedGatherExecutor.h"
|
#include "Aql/UnsortedGatherExecutor.h"
|
||||||
#include "Aql/UnsortingGatherExecutor.h"
|
|
||||||
#include "Aql/types.h"
|
#include "Aql/types.h"
|
||||||
#include "Basics/VelocyPackHelper.h"
|
#include "Basics/VelocyPackHelper.h"
|
||||||
#include "Cluster/ServerState.h"
|
#include "Cluster/ServerState.h"
|
||||||
|
@ -494,14 +494,15 @@ std::unique_ptr<ExecutionBlock> GatherNode::createBlock(
|
||||||
TRI_ASSERT(getRegisterPlan()->nrRegs[previousNode->getDepth()] ==
|
TRI_ASSERT(getRegisterPlan()->nrRegs[previousNode->getDepth()] ==
|
||||||
getRegisterPlan()->nrRegs[getDepth()]);
|
getRegisterPlan()->nrRegs[getDepth()]);
|
||||||
if (ServerState::instance()->isCoordinator() && _parallelism == Parallelism::Parallel) {
|
if (ServerState::instance()->isCoordinator() && _parallelism == Parallelism::Parallel) {
|
||||||
UnsortedGatherExecutorInfos infos(getRegisterPlan()->nrRegs[getDepth()],
|
ParallelUnsortedGatherExecutorInfos infos(getRegisterPlan()->nrRegs[getDepth()],
|
||||||
calcRegsToKeep(), getRegsToClear());
|
calcRegsToKeep(), getRegsToClear());
|
||||||
return std::make_unique<ExecutionBlockImpl<UnsortedGatherExecutor>>(&engine, this, std::move(infos));
|
return std::make_unique<ExecutionBlockImpl<ParallelUnsortedGatherExecutor>>(
|
||||||
|
&engine, this, std::move(infos));
|
||||||
} else {
|
} else {
|
||||||
IdExecutorInfos infos(getRegisterPlan()->nrRegs[getDepth()],
|
IdExecutorInfos infos(getRegisterPlan()->nrRegs[getDepth()],
|
||||||
calcRegsToKeep(), getRegsToClear());
|
calcRegsToKeep(), getRegsToClear());
|
||||||
|
|
||||||
return std::make_unique<ExecutionBlockImpl<UnsortingGatherExecutor>>(&engine, this,
|
return std::make_unique<ExecutionBlockImpl<UnsortedGatherExecutor>>(&engine, this,
|
||||||
std::move(infos));
|
std::move(infos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,10 +36,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool ConstrainedSortExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough ConstrainedSortExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool ConstrainedSortExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void eraseRow(SharedAqlItemBlockPtr& block, size_t row) {
|
void eraseRow(SharedAqlItemBlockPtr& block, size_t row) {
|
||||||
|
@ -55,7 +51,7 @@ void eraseRow(SharedAqlItemBlockPtr& block, size_t row) {
|
||||||
class arangodb::aql::ConstrainedLessThan {
|
class arangodb::aql::ConstrainedLessThan {
|
||||||
public:
|
public:
|
||||||
ConstrainedLessThan(velocypack::Options const* options,
|
ConstrainedLessThan(velocypack::Options const* options,
|
||||||
std::vector<arangodb::aql::SortRegister>& sortRegisters) noexcept
|
std::vector<arangodb::aql::SortRegister> const& sortRegisters) noexcept
|
||||||
: _vpackOptions(options), _heapBuffer(nullptr), _sortRegisters(sortRegisters) {}
|
: _vpackOptions(options), _heapBuffer(nullptr), _sortRegisters(sortRegisters) {}
|
||||||
|
|
||||||
void setBuffer(arangodb::aql::AqlItemBlock* heap) { _heapBuffer = heap; }
|
void setBuffer(arangodb::aql::AqlItemBlock* heap) { _heapBuffer = heap; }
|
||||||
|
@ -82,7 +78,7 @@ class arangodb::aql::ConstrainedLessThan {
|
||||||
private:
|
private:
|
||||||
velocypack::Options const* const _vpackOptions;
|
velocypack::Options const* const _vpackOptions;
|
||||||
arangodb::aql::AqlItemBlock* _heapBuffer;
|
arangodb::aql::AqlItemBlock* _heapBuffer;
|
||||||
std::vector<arangodb::aql::SortRegister>& _sortRegisters;
|
std::vector<arangodb::aql::SortRegister> const& _sortRegisters;
|
||||||
}; // ConstrainedLessThan
|
}; // ConstrainedLessThan
|
||||||
|
|
||||||
arangodb::Result ConstrainedSortExecutor::pushRow(InputAqlItemRow& input) {
|
arangodb::Result ConstrainedSortExecutor::pushRow(InputAqlItemRow& input) {
|
||||||
|
@ -92,16 +88,16 @@ arangodb::Result ConstrainedSortExecutor::pushRow(InputAqlItemRow& input) {
|
||||||
|
|
||||||
size_t dRow = _rowsPushed;
|
size_t dRow = _rowsPushed;
|
||||||
|
|
||||||
if (dRow >= _infos._limit) {
|
if (dRow >= _infos.limit()) {
|
||||||
// pop an entry first
|
// pop an entry first
|
||||||
std::pop_heap(_rows.begin(), _rows.end(), *_cmpHeap.get());
|
std::pop_heap(_rows.begin(), _rows.end(), *_cmpHeap);
|
||||||
dRow = _rows.back();
|
dRow = _rows.back();
|
||||||
eraseRow(_heapBuffer, dRow);
|
eraseRow(_heapBuffer, dRow);
|
||||||
} else {
|
} else {
|
||||||
_rows.emplace_back(dRow); // add to heap vector
|
_rows.emplace_back(dRow); // add to heap vector
|
||||||
}
|
}
|
||||||
|
|
||||||
TRI_ASSERT(dRow < _infos._limit);
|
TRI_ASSERT(dRow < _infos.limit());
|
||||||
TRI_IF_FAILURE("SortBlock::doSortingInner") {
|
TRI_IF_FAILURE("SortBlock::doSortingInner") {
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
|
||||||
}
|
}
|
||||||
|
@ -113,7 +109,7 @@ arangodb::Result ConstrainedSortExecutor::pushRow(InputAqlItemRow& input) {
|
||||||
++_rowsPushed;
|
++_rowsPushed;
|
||||||
|
|
||||||
// now restore heap condition
|
// now restore heap condition
|
||||||
std::push_heap(_rows.begin(), _rows.end(), *_cmpHeap.get());
|
std::push_heap(_rows.begin(), _rows.end(), *_cmpHeap);
|
||||||
|
|
||||||
return TRI_ERROR_NO_ERROR;
|
return TRI_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -142,15 +138,15 @@ ConstrainedSortExecutor::ConstrainedSortExecutor(Fetcher& fetcher, SortExecutorI
|
||||||
_rowsPushed(0),
|
_rowsPushed(0),
|
||||||
_rowsRead(0),
|
_rowsRead(0),
|
||||||
_skippedAfter(0),
|
_skippedAfter(0),
|
||||||
_heapBuffer(_infos._manager.requestBlock(_infos._limit,
|
_heapBuffer(_infos.itemBlockManager().requestBlock(_infos.limit(),
|
||||||
_infos.numberOfOutputRegisters())),
|
_infos.numberOfOutputRegisters())),
|
||||||
_cmpHeap(std::make_unique<ConstrainedLessThan>(_infos.vpackOptions(),
|
_cmpHeap(std::make_unique<ConstrainedLessThan>(_infos.vpackOptions(),
|
||||||
_infos.sortRegisters())),
|
_infos.sortRegisters())),
|
||||||
_heapOutputRow{_heapBuffer, make_shared_unordered_set(),
|
_heapOutputRow{_heapBuffer, make_shared_unordered_set(),
|
||||||
make_shared_unordered_set(_infos.numberOfOutputRegisters()),
|
make_shared_unordered_set(_infos.numberOfOutputRegisters()),
|
||||||
_infos.registersToClear()} {
|
_infos.registersToClear()} {
|
||||||
TRI_ASSERT(_infos._limit > 0);
|
TRI_ASSERT(_infos.limit() > 0);
|
||||||
_rows.reserve(infos._limit);
|
_rows.reserve(infos.limit());
|
||||||
_cmpHeap->setBuffer(_heapBuffer.get());
|
_cmpHeap->setBuffer(_heapBuffer.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +180,7 @@ ExecutionState ConstrainedSortExecutor::consumeInput() {
|
||||||
TRI_ASSERT(_state == ExecutionState::DONE);
|
TRI_ASSERT(_state == ExecutionState::DONE);
|
||||||
} else {
|
} else {
|
||||||
++_rowsRead;
|
++_rowsRead;
|
||||||
if (_rowsPushed < _infos._limit || !compareInput(_rows.front(), input)) {
|
if (_rowsPushed < _infos.limit() || !compareInput(_rows.front(), input)) {
|
||||||
// Push this row into the heap
|
// Push this row into the heap
|
||||||
pushRow(input);
|
pushRow(input);
|
||||||
}
|
}
|
||||||
|
@ -255,7 +251,7 @@ std::pair<ExecutionState, size_t> ConstrainedSortExecutor::expectedNumberOfRows(
|
||||||
return {state, 0};
|
return {state, 0};
|
||||||
}
|
}
|
||||||
// Return the minimum of upstream + limit
|
// Return the minimum of upstream + limit
|
||||||
rowsLeft = (std::min)(expectedRows, _infos._limit);
|
rowsLeft = (std::min)(expectedRows, _infos.limit());
|
||||||
} else {
|
} else {
|
||||||
// We have exactly the following rows available:
|
// We have exactly the following rows available:
|
||||||
rowsLeft = _rows.size() - _returnNext;
|
rowsLeft = _rows.size() - _returnNext;
|
||||||
|
|
|
@ -37,10 +37,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool CountCollectExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough CountCollectExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool CountCollectExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
CountCollectExecutorInfos::CountCollectExecutorInfos(
|
CountCollectExecutorInfos::CountCollectExecutorInfos(
|
||||||
RegisterId collectRegister, RegisterId nrInputRegisters, RegisterId nrOutputRegisters,
|
RegisterId collectRegister, RegisterId nrInputRegisters, RegisterId nrOutputRegisters,
|
||||||
// cppcheck-suppress passedByValue
|
// cppcheck-suppress passedByValue
|
||||||
|
|
|
@ -38,10 +38,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool DistinctCollectExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough DistinctCollectExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool DistinctCollectExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
DistinctCollectExecutorInfos::DistinctCollectExecutorInfos(
|
DistinctCollectExecutorInfos::DistinctCollectExecutorInfos(
|
||||||
RegisterId nrInputRegisters, RegisterId nrOutputRegisters,
|
RegisterId nrInputRegisters, RegisterId nrOutputRegisters,
|
||||||
std::unordered_set<RegisterId> registersToClear,
|
std::unordered_set<RegisterId> registersToClear,
|
||||||
|
|
|
@ -65,7 +65,7 @@ std::unique_ptr<ExecutionBlock> DistributeConsumerNode::createBlock(
|
||||||
getRegisterPlan()->nrRegs[getDepth()]);
|
getRegisterPlan()->nrRegs[getDepth()]);
|
||||||
IdExecutorInfos infos(getRegisterPlan()->nrRegs[getDepth()], calcRegsToKeep(),
|
IdExecutorInfos infos(getRegisterPlan()->nrRegs[getDepth()], calcRegsToKeep(),
|
||||||
getRegsToClear(), _distributeId, _isResponsibleForInitializeCursor);
|
getRegsToClear(), _distributeId, _isResponsibleForInitializeCursor);
|
||||||
return std::make_unique<ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, SingleRowFetcher<BlockPassthrough::Enable>>>>(
|
return std::make_unique<ExecutionBlockImpl<IdExecutor<SingleRowFetcher<BlockPassthrough::Enable>>>>(
|
||||||
&engine, this, std::move(infos));
|
&engine, this, std::move(infos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,11 +75,11 @@ void DistributeConsumerNode::cloneRegisterPlan(ScatterNode* dependency) {
|
||||||
_registerPlan = dependency->getRegisterPlan();
|
_registerPlan = dependency->getRegisterPlan();
|
||||||
_depth = dependency->getDepth();
|
_depth = dependency->getDepth();
|
||||||
{
|
{
|
||||||
auto later = dependency->getVarsUsedLater();
|
auto const& later = dependency->getVarsUsedLater();
|
||||||
setVarsUsedLater(later);
|
setVarsUsedLater(later);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto valid = dependency->getVarsValid();
|
auto const& valid = dependency->getVarsValid();
|
||||||
setVarsValid(valid);
|
setVarsValid(valid);
|
||||||
}
|
}
|
||||||
setVarUsageValid();
|
setVarUsageValid();
|
||||||
|
|
|
@ -27,17 +27,19 @@
|
||||||
#include "Basics/Exceptions.h"
|
#include "Basics/Exceptions.h"
|
||||||
#include "Basics/voc-errors.h"
|
#include "Basics/voc-errors.h"
|
||||||
|
|
||||||
namespace arangodb {
|
#include <utility>
|
||||||
namespace aql {
|
|
||||||
|
namespace arangodb::aql {
|
||||||
|
|
||||||
class ExecutionBlock;
|
class ExecutionBlock;
|
||||||
class ExecutionPlan;
|
class ExecutionPlan;
|
||||||
class ScatterNode;
|
class ScatterNode;
|
||||||
|
|
||||||
class DistributeConsumerNode : public ExecutionNode {
|
class DistributeConsumerNode : public ExecutionNode {
|
||||||
public:
|
public:
|
||||||
DistributeConsumerNode(ExecutionPlan* plan, size_t id, std::string const& distributeId)
|
DistributeConsumerNode(ExecutionPlan* plan, size_t id, std::string distributeId)
|
||||||
: ExecutionNode(plan, id),
|
: ExecutionNode(plan, id),
|
||||||
_distributeId(distributeId),
|
_distributeId(std::move(distributeId)),
|
||||||
_isResponsibleForInitializeCursor(true) {}
|
_isResponsibleForInitializeCursor(true) {}
|
||||||
|
|
||||||
DistributeConsumerNode(ExecutionPlan* plan, arangodb::velocypack::Slice const& base);
|
DistributeConsumerNode(ExecutionPlan* plan, arangodb::velocypack::Slice const& base);
|
||||||
|
@ -106,7 +108,6 @@ class DistributeConsumerNode : public ExecutionNode {
|
||||||
bool _isResponsibleForInitializeCursor;
|
bool _isResponsibleForInitializeCursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aql
|
} // namespace arangodb::aql
|
||||||
} // namespace arangodb
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,10 +43,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool EnumerateCollectionExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough EnumerateCollectionExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool EnumerateCollectionExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
EnumerateCollectionExecutorInfos::EnumerateCollectionExecutorInfos(
|
EnumerateCollectionExecutorInfos::EnumerateCollectionExecutorInfos(
|
||||||
RegisterId outputRegister, RegisterId nrInputRegisters, RegisterId nrOutputRegisters,
|
RegisterId outputRegister, RegisterId nrInputRegisters, RegisterId nrOutputRegisters,
|
||||||
// cppcheck-suppress passedByValue
|
// cppcheck-suppress passedByValue
|
||||||
|
|
|
@ -47,10 +47,6 @@ void throwArrayExpectedException(AqlValue const& value) {
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
constexpr bool EnumerateListExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough EnumerateListExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool EnumerateListExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
EnumerateListExecutorInfos::EnumerateListExecutorInfos(
|
EnumerateListExecutorInfos::EnumerateListExecutorInfos(
|
||||||
RegisterId inputRegister, RegisterId outputRegister,
|
RegisterId inputRegister, RegisterId outputRegister,
|
||||||
RegisterId nrInputRegisters, RegisterId nrOutputRegisters,
|
RegisterId nrInputRegisters, RegisterId nrOutputRegisters,
|
||||||
|
|
|
@ -55,7 +55,7 @@ class ExecutionBlock {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// @brief batch size value
|
/// @brief batch size value
|
||||||
static constexpr inline size_t DefaultBatchSize() { return 1000; }
|
[[nodiscard]] static constexpr inline size_t DefaultBatchSize() { return 1000; }
|
||||||
|
|
||||||
/// @brief Number to use when we skip all. Should really be inf, but don't
|
/// @brief Number to use when we skip all. Should really be inf, but don't
|
||||||
/// use something near std::numeric_limits<size_t>::max() to avoid overflows
|
/// use something near std::numeric_limits<size_t>::max() to avoid overflows
|
||||||
|
@ -63,7 +63,7 @@ class ExecutionBlock {
|
||||||
/// This is used as an argument for skipSome(), e.g. when counting everything.
|
/// This is used as an argument for skipSome(), e.g. when counting everything.
|
||||||
/// Setting this to any other value >0 does not (and must not) affect the
|
/// Setting this to any other value >0 does not (and must not) affect the
|
||||||
/// results. It's only to reduce the number of necessary skipSome calls.
|
/// results. It's only to reduce the number of necessary skipSome calls.
|
||||||
static constexpr inline size_t SkipAllSize() { return 1000000000; }
|
[[nodiscard]] static constexpr inline size_t SkipAllSize() { return 1000000000; }
|
||||||
|
|
||||||
/// @brief Methods for execution
|
/// @brief Methods for execution
|
||||||
/// Lifecycle is:
|
/// Lifecycle is:
|
||||||
|
@ -78,10 +78,10 @@ class ExecutionBlock {
|
||||||
/// DESTRUCTOR
|
/// DESTRUCTOR
|
||||||
|
|
||||||
/// @brief initializeCursor, could be called multiple times
|
/// @brief initializeCursor, could be called multiple times
|
||||||
virtual std::pair<ExecutionState, Result> initializeCursor(InputAqlItemRow const& input);
|
[[nodiscard]] virtual std::pair<ExecutionState, Result> initializeCursor(InputAqlItemRow const& input);
|
||||||
|
|
||||||
/// @brief shutdown, will be called exactly once for the whole query
|
/// @brief shutdown, will be called exactly once for the whole query
|
||||||
virtual std::pair<ExecutionState, Result> shutdown(int errorCode);
|
[[nodiscard]] virtual std::pair<ExecutionState, Result> shutdown(int errorCode);
|
||||||
|
|
||||||
/// @brief getSome, gets some more items, semantic is as follows: not
|
/// @brief getSome, gets some more items, semantic is as follows: not
|
||||||
/// more than atMost items may be delivered. The method tries to
|
/// more than atMost items may be delivered. The method tries to
|
||||||
|
@ -90,39 +90,39 @@ class ExecutionBlock {
|
||||||
/// if it returns an actual block, it must contain at least one item.
|
/// if it returns an actual block, it must contain at least one item.
|
||||||
/// getSome() also takes care of tracing and clearing registers; don't do it
|
/// getSome() also takes care of tracing and clearing registers; don't do it
|
||||||
/// in getOrSkipSome() implementations.
|
/// in getOrSkipSome() implementations.
|
||||||
virtual std::pair<ExecutionState, SharedAqlItemBlockPtr> getSome(size_t atMost) = 0;
|
[[nodiscard]] virtual std::pair<ExecutionState, SharedAqlItemBlockPtr> getSome(size_t atMost) = 0;
|
||||||
|
|
||||||
// Trace the start of a getSome call
|
// Trace the start of a getSome call
|
||||||
void traceGetSomeBegin(size_t atMost);
|
void traceGetSomeBegin(size_t atMost);
|
||||||
|
|
||||||
// Trace the end of a getSome call, potentially with result
|
// Trace the end of a getSome call, potentially with result
|
||||||
std::pair<ExecutionState, SharedAqlItemBlockPtr> traceGetSomeEnd(
|
[[nodiscard]] std::pair<ExecutionState, SharedAqlItemBlockPtr> traceGetSomeEnd(
|
||||||
ExecutionState state, SharedAqlItemBlockPtr result);
|
ExecutionState state, SharedAqlItemBlockPtr result);
|
||||||
|
|
||||||
void traceSkipSomeBegin(size_t atMost);
|
void traceSkipSomeBegin(size_t atMost);
|
||||||
|
|
||||||
std::pair<ExecutionState, size_t> traceSkipSomeEnd(std::pair<ExecutionState, size_t> res);
|
[[nodiscard]] std::pair<ExecutionState, size_t> traceSkipSomeEnd(std::pair<ExecutionState, size_t> res);
|
||||||
|
|
||||||
std::pair<ExecutionState, size_t> traceSkipSomeEnd(ExecutionState state, size_t skipped);
|
[[nodiscard]] std::pair<ExecutionState, size_t> traceSkipSomeEnd(ExecutionState state, size_t skipped);
|
||||||
|
|
||||||
/// @brief skipSome, skips some more items, semantic is as follows: not
|
/// @brief skipSome, skips some more items, semantic is as follows: not
|
||||||
/// more than atMost items may be skipped. The method tries to
|
/// more than atMost items may be skipped. The method tries to
|
||||||
/// skip a block of at most atMost items, however, it may skip
|
/// skip a block of at most atMost items, however, it may skip
|
||||||
/// less (for example if there are not enough items to come). The number of
|
/// less (for example if there are not enough items to come). The number of
|
||||||
/// elements skipped is returned.
|
/// elements skipped is returned.
|
||||||
virtual std::pair<ExecutionState, size_t> skipSome(size_t atMost) = 0;
|
[[nodiscard]] virtual std::pair<ExecutionState, size_t> skipSome(size_t atMost) = 0;
|
||||||
|
|
||||||
ExecutionState getHasMoreState();
|
[[nodiscard]] ExecutionState getHasMoreState();
|
||||||
|
|
||||||
// TODO: Can we get rid of this? Problem: Subquery Executor is using it.
|
// TODO: Can we get rid of this? Problem: Subquery Executor is using it.
|
||||||
ExecutionNode const* getPlanNode() const;
|
[[nodiscard]] ExecutionNode const* getPlanNode() const;
|
||||||
|
|
||||||
[[nodiscard]] velocypack::Options const* trxVpackOptions() const noexcept;
|
[[nodiscard]] velocypack::Options const* trxVpackOptions() const noexcept;
|
||||||
|
|
||||||
/// @brief add a dependency
|
/// @brief add a dependency
|
||||||
void addDependency(ExecutionBlock* ep);
|
void addDependency(ExecutionBlock* ep);
|
||||||
|
|
||||||
bool isInSplicedSubquery() const noexcept;
|
[[nodiscard]] bool isInSplicedSubquery() const noexcept;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// @brief the execution engine
|
/// @brief the execution engine
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "Aql/ModificationExecutor.h"
|
#include "Aql/ModificationExecutor.h"
|
||||||
#include "Aql/MultiDependencySingleRowFetcher.h"
|
#include "Aql/MultiDependencySingleRowFetcher.h"
|
||||||
#include "Aql/NoResultsExecutor.h"
|
#include "Aql/NoResultsExecutor.h"
|
||||||
|
#include "Aql/ParallelUnsortedGatherExecutor.h"
|
||||||
#include "Aql/Query.h"
|
#include "Aql/Query.h"
|
||||||
#include "Aql/QueryOptions.h"
|
#include "Aql/QueryOptions.h"
|
||||||
#include "Aql/ReturnExecutor.h"
|
#include "Aql/ReturnExecutor.h"
|
||||||
|
@ -64,7 +65,6 @@
|
||||||
#include "Aql/SubqueryStartExecutor.h"
|
#include "Aql/SubqueryStartExecutor.h"
|
||||||
#include "Aql/TraversalExecutor.h"
|
#include "Aql/TraversalExecutor.h"
|
||||||
#include "Aql/UnsortedGatherExecutor.h"
|
#include "Aql/UnsortedGatherExecutor.h"
|
||||||
#include "Aql/UnsortingGatherExecutor.h"
|
|
||||||
|
|
||||||
#include "Aql/SimpleModifier.h"
|
#include "Aql/SimpleModifier.h"
|
||||||
#include "Aql/UpsertModifier.h"
|
#include "Aql/UpsertModifier.h"
|
||||||
|
@ -375,8 +375,8 @@ static SkipVariants constexpr skipType() {
|
||||||
std::is_same<Executor, LimitExecutor>::value ||
|
std::is_same<Executor, LimitExecutor>::value ||
|
||||||
std::is_same<Executor, ConstrainedSortExecutor>::value ||
|
std::is_same<Executor, ConstrainedSortExecutor>::value ||
|
||||||
std::is_same<Executor, SortingGatherExecutor>::value ||
|
std::is_same<Executor, SortingGatherExecutor>::value ||
|
||||||
std::is_same<Executor, UnsortingGatherExecutor>::value ||
|
|
||||||
std::is_same<Executor, UnsortedGatherExecutor>::value ||
|
std::is_same<Executor, UnsortedGatherExecutor>::value ||
|
||||||
|
std::is_same<Executor, ParallelUnsortedGatherExecutor>::value ||
|
||||||
std::is_same<Executor, MaterializeExecutor<RegisterId>>::value ||
|
std::is_same<Executor, MaterializeExecutor<RegisterId>>::value ||
|
||||||
std::is_same<Executor, MaterializeExecutor<std::string const&>>::value),
|
std::is_same<Executor, MaterializeExecutor<std::string const&>>::value),
|
||||||
"Unexpected executor for SkipVariants::EXECUTOR");
|
"Unexpected executor for SkipVariants::EXECUTOR");
|
||||||
|
@ -521,7 +521,7 @@ std::pair<ExecutionState, Result> ExecutionBlockImpl<Executor>::shutdown(int err
|
||||||
namespace arangodb::aql {
|
namespace arangodb::aql {
|
||||||
// TODO -- remove this specialization when cpp 17 becomes available
|
// TODO -- remove this specialization when cpp 17 becomes available
|
||||||
template <>
|
template <>
|
||||||
std::pair<ExecutionState, Result> ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, ConstFetcher>>::initializeCursor(
|
std::pair<ExecutionState, Result> ExecutionBlockImpl<IdExecutor<ConstFetcher>>::initializeCursor(
|
||||||
InputAqlItemRow const& input) {
|
InputAqlItemRow const& input) {
|
||||||
// reinitialize the DependencyProxy
|
// reinitialize the DependencyProxy
|
||||||
_dependencyProxy.reset();
|
_dependencyProxy.reset();
|
||||||
|
@ -632,12 +632,13 @@ std::pair<ExecutionState, Result> ExecutionBlockImpl<SubqueryExecutor<false>>::s
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::pair<ExecutionState, Result> ExecutionBlockImpl<
|
std::pair<ExecutionState, Result> ExecutionBlockImpl<
|
||||||
IdExecutor<BlockPassthrough::Enable, SingleRowFetcher<BlockPassthrough::Enable>>>::shutdown(int errorCode) {
|
IdExecutor<SingleRowFetcher<BlockPassthrough::Enable>>>::shutdown(int errorCode) {
|
||||||
if (this->infos().isResponsibleForInitializeCursor()) {
|
if (this->infos().isResponsibleForInitializeCursor()) {
|
||||||
return ExecutionBlock::shutdown(errorCode);
|
return ExecutionBlock::shutdown(errorCode);
|
||||||
}
|
}
|
||||||
return {ExecutionState::DONE, {errorCode}};
|
return {ExecutionState::DONE, {errorCode}};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace arangodb::aql
|
} // namespace arangodb::aql
|
||||||
|
|
||||||
namespace arangodb::aql {
|
namespace arangodb::aql {
|
||||||
|
@ -863,7 +864,6 @@ template class ::arangodb::aql::ExecutionBlockImpl<EnumerateCollectionExecutor>;
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<EnumerateListExecutor>;
|
template class ::arangodb::aql::ExecutionBlockImpl<EnumerateListExecutor>;
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<FilterExecutor>;
|
template class ::arangodb::aql::ExecutionBlockImpl<FilterExecutor>;
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<HashedCollectExecutor>;
|
template class ::arangodb::aql::ExecutionBlockImpl<HashedCollectExecutor>;
|
||||||
|
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<IResearchViewExecutor<false, arangodb::iresearch::MaterializeType::Materialized>>;
|
template class ::arangodb::aql::ExecutionBlockImpl<IResearchViewExecutor<false, arangodb::iresearch::MaterializeType::Materialized>>;
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<IResearchViewExecutor<false, arangodb::iresearch::MaterializeType::LateMaterialized>>;
|
template class ::arangodb::aql::ExecutionBlockImpl<IResearchViewExecutor<false, arangodb::iresearch::MaterializeType::LateMaterialized>>;
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<IResearchViewExecutor<false, arangodb::iresearch::MaterializeType::LateMaterializedWithVars>>;
|
template class ::arangodb::aql::ExecutionBlockImpl<IResearchViewExecutor<false, arangodb::iresearch::MaterializeType::LateMaterializedWithVars>>;
|
||||||
|
@ -875,9 +875,8 @@ template class ::arangodb::aql::ExecutionBlockImpl<IResearchViewMergeExecutor<fa
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<IResearchViewMergeExecutor<true, arangodb::iresearch::MaterializeType::Materialized>>;
|
template class ::arangodb::aql::ExecutionBlockImpl<IResearchViewMergeExecutor<true, arangodb::iresearch::MaterializeType::Materialized>>;
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<IResearchViewMergeExecutor<true, arangodb::iresearch::MaterializeType::LateMaterialized>>;
|
template class ::arangodb::aql::ExecutionBlockImpl<IResearchViewMergeExecutor<true, arangodb::iresearch::MaterializeType::LateMaterialized>>;
|
||||||
|
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, ConstFetcher>>;
|
template class ::arangodb::aql::ExecutionBlockImpl<IdExecutor<ConstFetcher>>;
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<
|
template class ::arangodb::aql::ExecutionBlockImpl<IdExecutor<SingleRowFetcher<BlockPassthrough::Enable>>>;
|
||||||
IdExecutor<BlockPassthrough::Enable, SingleRowFetcher<BlockPassthrough::Enable>>>;
|
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<IndexExecutor>;
|
template class ::arangodb::aql::ExecutionBlockImpl<IndexExecutor>;
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<LimitExecutor>;
|
template class ::arangodb::aql::ExecutionBlockImpl<LimitExecutor>;
|
||||||
|
|
||||||
|
@ -901,8 +900,8 @@ template class ::arangodb::aql::ExecutionBlockImpl<SubqueryExecutor<false>>;
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<SubqueryStartExecutor>;
|
template class ::arangodb::aql::ExecutionBlockImpl<SubqueryStartExecutor>;
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<TraversalExecutor>;
|
template class ::arangodb::aql::ExecutionBlockImpl<TraversalExecutor>;
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<SortingGatherExecutor>;
|
template class ::arangodb::aql::ExecutionBlockImpl<SortingGatherExecutor>;
|
||||||
|
template class ::arangodb::aql::ExecutionBlockImpl<ParallelUnsortedGatherExecutor>;
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<UnsortedGatherExecutor>;
|
template class ::arangodb::aql::ExecutionBlockImpl<UnsortedGatherExecutor>;
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<UnsortingGatherExecutor>;
|
|
||||||
|
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<MaterializeExecutor<RegisterId>>;
|
template class ::arangodb::aql::ExecutionBlockImpl<MaterializeExecutor<RegisterId>>;
|
||||||
template class ::arangodb::aql::ExecutionBlockImpl<MaterializeExecutor<std::string const&>>;
|
template class ::arangodb::aql::ExecutionBlockImpl<MaterializeExecutor<std::string const&>>;
|
||||||
|
|
|
@ -170,7 +170,7 @@ class ExecutionBlockImpl final : public ExecutionBlock {
|
||||||
|
|
||||||
[[nodiscard]] std::pair<ExecutionState, Result> initializeCursor(InputAqlItemRow const& input) override;
|
[[nodiscard]] std::pair<ExecutionState, Result> initializeCursor(InputAqlItemRow const& input) override;
|
||||||
|
|
||||||
Infos const& infos() const;
|
[[nodiscard]] Infos const& infos() const;
|
||||||
|
|
||||||
/// @brief shutdown, will be called exactly once for the whole query
|
/// @brief shutdown, will be called exactly once for the whole query
|
||||||
/// Special implementation for all Executors that need to implement Shutdown
|
/// Special implementation for all Executors that need to implement Shutdown
|
||||||
|
|
|
@ -712,8 +712,7 @@ ExecutionEngine* ExecutionEngine::instantiateFromPlan(QueryRegistry& queryRegist
|
||||||
|
|
||||||
bool const returnInheritedResults = !arangodb::ServerState::isDBServer(role);
|
bool const returnInheritedResults = !arangodb::ServerState::isDBServer(role);
|
||||||
if (returnInheritedResults) {
|
if (returnInheritedResults) {
|
||||||
auto returnNode =
|
auto returnNode = dynamic_cast<ExecutionBlockImpl<IdExecutor<void>>*>(root);
|
||||||
dynamic_cast<ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, void>>*>(root);
|
|
||||||
TRI_ASSERT(returnNode != nullptr);
|
TRI_ASSERT(returnNode != nullptr);
|
||||||
engine->resultRegister(returnNode->getOutputRegisterId());
|
engine->resultRegister(returnNode->getOutputRegisterId());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1204,7 +1204,7 @@ const ::arangodb::containers::HashSet<const Variable*>& ExecutionNode::getVarsUs
|
||||||
return _varsUsedLater;
|
return _varsUsedLater;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecutionNode::setVarsValid(::arangodb::containers::HashSet<const Variable*>& v) {
|
void ExecutionNode::setVarsValid(::arangodb::containers::HashSet<const Variable*> const& v) {
|
||||||
_varsValid = v;
|
_varsValid = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1283,8 +1283,8 @@ std::unique_ptr<ExecutionBlock> SingletonNode::createBlock(
|
||||||
|
|
||||||
IdExecutorInfos infos(nrRegs, std::move(toKeep), getRegsToClear());
|
IdExecutorInfos infos(nrRegs, std::move(toKeep), getRegsToClear());
|
||||||
|
|
||||||
return std::make_unique<ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, ConstFetcher>>>(
|
return std::make_unique<ExecutionBlockImpl<IdExecutor<ConstFetcher>>>(&engine, this,
|
||||||
&engine, this, std::move(infos));
|
std::move(infos));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief toVelocyPack, for SingletonNode
|
/// @brief toVelocyPack, for SingletonNode
|
||||||
|
@ -2170,8 +2170,8 @@ std::unique_ptr<ExecutionBlock> ReturnNode::createBlock(
|
||||||
returnInheritedResults ? getRegisterPlan()->nrRegs[getDepth()] : 1;
|
returnInheritedResults ? getRegisterPlan()->nrRegs[getDepth()] : 1;
|
||||||
|
|
||||||
if (returnInheritedResults) {
|
if (returnInheritedResults) {
|
||||||
return std::make_unique<ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, void>>>(
|
return std::make_unique<ExecutionBlockImpl<IdExecutor<void>>>(&engine, this,
|
||||||
&engine, this, inputRegister, _count);
|
inputRegister, _count);
|
||||||
} else {
|
} else {
|
||||||
TRI_ASSERT(!returnInheritedResults);
|
TRI_ASSERT(!returnInheritedResults);
|
||||||
ReturnExecutorInfos infos(inputRegister, numberInputRegisters,
|
ReturnExecutorInfos infos(inputRegister, numberInputRegisters,
|
||||||
|
|
|
@ -363,7 +363,7 @@ class ExecutionNode {
|
||||||
::arangodb::containers::HashSet<Variable const*> const& getVarsUsedLater() const;
|
::arangodb::containers::HashSet<Variable const*> const& getVarsUsedLater() const;
|
||||||
|
|
||||||
/// @brief setVarsValid
|
/// @brief setVarsValid
|
||||||
void setVarsValid(::arangodb::containers::HashSet<Variable const*>& v);
|
void setVarsValid(::arangodb::containers::HashSet<Variable const*> const& v);
|
||||||
|
|
||||||
/// @brief getVarsValid, this returns the set of variables that is valid
|
/// @brief getVarsValid, this returns the set of variables that is valid
|
||||||
/// for items leaving this node, this includes those that will be set here
|
/// for items leaving this node, this includes those that will be set here
|
||||||
|
|
|
@ -37,10 +37,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool FilterExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough FilterExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool FilterExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
FilterExecutorInfos::FilterExecutorInfos(RegisterId inputRegister, RegisterId nrInputRegisters,
|
FilterExecutorInfos::FilterExecutorInfos(RegisterId inputRegister, RegisterId nrInputRegisters,
|
||||||
RegisterId nrOutputRegisters,
|
RegisterId nrOutputRegisters,
|
||||||
// cppcheck-suppress passedByValue
|
// cppcheck-suppress passedByValue
|
||||||
|
|
|
@ -39,10 +39,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool HashedCollectExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough HashedCollectExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool HashedCollectExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
static const AqlValue EmptyValue;
|
static const AqlValue EmptyValue;
|
||||||
|
|
||||||
HashedCollectExecutorInfos::HashedCollectExecutorInfos(
|
HashedCollectExecutorInfos::HashedCollectExecutorInfos(
|
||||||
|
|
|
@ -54,14 +54,6 @@
|
||||||
|
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
template <typename Impl, typename Traits>
|
|
||||||
constexpr bool IResearchViewExecutorBase<Impl, Traits>::Properties::preservesOrder;
|
|
||||||
template <typename Impl, typename Traits>
|
|
||||||
constexpr BlockPassthrough IResearchViewExecutorBase<Impl, Traits>::Properties::allowsBlockPassthrough;
|
|
||||||
template <typename Impl, typename Traits>
|
|
||||||
constexpr bool IResearchViewExecutorBase<Impl, Traits>::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
using namespace arangodb::iresearch;
|
using namespace arangodb::iresearch;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -37,14 +37,7 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
template <BlockPassthrough usePassThrough, class T>
|
ExecutionBlockImpl<IdExecutor<void>>::ExecutionBlockImpl(ExecutionEngine* engine,
|
||||||
constexpr bool IdExecutor<usePassThrough, T>::Properties::preservesOrder;
|
|
||||||
template <BlockPassthrough usePassThrough, class T>
|
|
||||||
constexpr BlockPassthrough IdExecutor<usePassThrough, T>::Properties::allowsBlockPassthrough;
|
|
||||||
template <BlockPassthrough usePassThrough, class T>
|
|
||||||
constexpr bool IdExecutor<usePassThrough, T>::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, void>>::ExecutionBlockImpl(ExecutionEngine* engine,
|
|
||||||
ExecutionNode const* node,
|
ExecutionNode const* node,
|
||||||
RegisterId outputRegister, bool doCount)
|
RegisterId outputRegister, bool doCount)
|
||||||
: ExecutionBlock(engine, node),
|
: ExecutionBlock(engine, node),
|
||||||
|
@ -57,7 +50,7 @@ ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, void>>::ExecutionBlockIm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<ExecutionState, size_t> ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, void>>::skipSome(size_t atMost) {
|
std::pair<ExecutionState, size_t> ExecutionBlockImpl<IdExecutor<void>>::skipSome(size_t atMost) {
|
||||||
traceSkipSomeBegin(atMost);
|
traceSkipSomeBegin(atMost);
|
||||||
if (isDone()) {
|
if (isDone()) {
|
||||||
return traceSkipSomeEnd(ExecutionState::DONE, 0);
|
return traceSkipSomeEnd(ExecutionState::DONE, 0);
|
||||||
|
@ -74,7 +67,7 @@ std::pair<ExecutionState, size_t> ExecutionBlockImpl<IdExecutor<BlockPassthrough
|
||||||
return traceSkipSomeEnd(state, skipped);
|
return traceSkipSomeEnd(state, skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<ExecutionState, SharedAqlItemBlockPtr> ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, void>>::getSome(size_t atMost) {
|
std::pair<ExecutionState, SharedAqlItemBlockPtr> ExecutionBlockImpl<IdExecutor<void>>::getSome(size_t atMost) {
|
||||||
traceGetSomeBegin(atMost);
|
traceGetSomeBegin(atMost);
|
||||||
if (isDone()) {
|
if (isDone()) {
|
||||||
return traceGetSomeEnd(ExecutionState::DONE, nullptr);
|
return traceGetSomeEnd(ExecutionState::DONE, nullptr);
|
||||||
|
@ -93,32 +86,32 @@ std::pair<ExecutionState, SharedAqlItemBlockPtr> ExecutionBlockImpl<IdExecutor<B
|
||||||
return traceGetSomeEnd(state, block);
|
return traceGetSomeEnd(state, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool aql::ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, void>>::isDone() const noexcept {
|
bool aql::ExecutionBlockImpl<IdExecutor<void>>::isDone() const noexcept {
|
||||||
// I'd like to assert this in the constructor, but the dependencies are
|
// I'd like to assert this in the constructor, but the dependencies are
|
||||||
// added after construction.
|
// added after construction.
|
||||||
TRI_ASSERT(!_dependencies.empty());
|
TRI_ASSERT(!_dependencies.empty());
|
||||||
return _currentDependency >= _dependencies.size();
|
return _currentDependency >= _dependencies.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterId ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, void>>::getOutputRegisterId() const noexcept {
|
RegisterId ExecutionBlockImpl<IdExecutor<void>>::getOutputRegisterId() const noexcept {
|
||||||
return _outputRegister;
|
return _outputRegister;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecutionBlock& ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, void>>::currentDependency() const {
|
ExecutionBlock& ExecutionBlockImpl<IdExecutor<void>>::currentDependency() const {
|
||||||
TRI_ASSERT(_currentDependency < _dependencies.size());
|
TRI_ASSERT(_currentDependency < _dependencies.size());
|
||||||
TRI_ASSERT(_dependencies[_currentDependency] != nullptr);
|
TRI_ASSERT(_dependencies[_currentDependency] != nullptr);
|
||||||
return *_dependencies[_currentDependency];
|
return *_dependencies[_currentDependency];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, void>>::nextDependency() noexcept {
|
void ExecutionBlockImpl<IdExecutor<void>>::nextDependency() noexcept {
|
||||||
++_currentDependency;
|
++_currentDependency;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, void>>::doCount() const noexcept {
|
bool ExecutionBlockImpl<IdExecutor<void>>::doCount() const noexcept {
|
||||||
return _doCount;
|
return _doCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, void>>::countStats(SharedAqlItemBlockPtr& block) {
|
void ExecutionBlockImpl<IdExecutor<void>>::countStats(SharedAqlItemBlockPtr& block) {
|
||||||
if (doCount() && block != nullptr) {
|
if (doCount() && block != nullptr) {
|
||||||
CountStats stats;
|
CountStats stats;
|
||||||
stats.setCounted(block->size());
|
stats.setCounted(block->size());
|
||||||
|
@ -144,19 +137,19 @@ bool IdExecutorInfos::isResponsibleForInitializeCursor() const {
|
||||||
return _isResponsibleForInitializeCursor;
|
return _isResponsibleForInitializeCursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <BlockPassthrough usePassThrough, class UsedFetcher>
|
template <class UsedFetcher>
|
||||||
IdExecutor<usePassThrough, UsedFetcher>::IdExecutor(Fetcher& fetcher, IdExecutorInfos& infos)
|
IdExecutor<UsedFetcher>::IdExecutor(Fetcher& fetcher, IdExecutorInfos& infos)
|
||||||
: _fetcher(fetcher) {
|
: _fetcher(fetcher) {
|
||||||
if (!infos.distributeId().empty()) {
|
if (!infos.distributeId().empty()) {
|
||||||
_fetcher.setDistributeId(infos.distributeId());
|
_fetcher.setDistributeId(infos.distributeId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <BlockPassthrough usePassThrough, class UsedFetcher>
|
template <class UsedFetcher>
|
||||||
IdExecutor<usePassThrough, UsedFetcher>::~IdExecutor() = default;
|
IdExecutor<UsedFetcher>::~IdExecutor() = default;
|
||||||
|
|
||||||
template <BlockPassthrough usePassThrough, class UsedFetcher>
|
template <class UsedFetcher>
|
||||||
std::pair<ExecutionState, NoStats> IdExecutor<usePassThrough, UsedFetcher>::produceRows(OutputAqlItemRow& output) {
|
std::pair<ExecutionState, NoStats> IdExecutor<UsedFetcher>::produceRows(OutputAqlItemRow& output) {
|
||||||
ExecutionState state = ExecutionState::HASMORE;
|
ExecutionState state = ExecutionState::HASMORE;
|
||||||
NoStats stats;
|
NoStats stats;
|
||||||
InputAqlItemRow inputRow = InputAqlItemRow{CreateInvalidInputRowHint{}};
|
InputAqlItemRow inputRow = InputAqlItemRow{CreateInvalidInputRowHint{}};
|
||||||
|
@ -191,34 +184,13 @@ std::pair<ExecutionState, NoStats> IdExecutor<usePassThrough, UsedFetcher>::prod
|
||||||
return {state, stats};
|
return {state, stats};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <BlockPassthrough usePassThrough, class UsedFetcher>
|
template <class UsedFetcher>
|
||||||
template <BlockPassthrough allowPass, typename>
|
std::tuple<ExecutionState, typename IdExecutor<UsedFetcher>::Stats, SharedAqlItemBlockPtr>
|
||||||
std::tuple<ExecutionState, NoStats, size_t> IdExecutor<usePassThrough, UsedFetcher>::skipRows(size_t atMost) {
|
IdExecutor<UsedFetcher>::fetchBlockForPassthrough(size_t atMost) {
|
||||||
ExecutionState state;
|
|
||||||
size_t skipped;
|
|
||||||
std::tie(state, skipped) = _fetcher.skipRows(atMost);
|
|
||||||
return {state, NoStats{}, skipped};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <BlockPassthrough usePassThrough, class UsedFetcher>
|
|
||||||
template <BlockPassthrough allowPass, typename>
|
|
||||||
std::tuple<ExecutionState, typename IdExecutor<usePassThrough, UsedFetcher>::Stats, SharedAqlItemBlockPtr>
|
|
||||||
IdExecutor<usePassThrough, UsedFetcher>::fetchBlockForPassthrough(size_t atMost) {
|
|
||||||
auto rv = _fetcher.fetchBlockForPassthrough(atMost);
|
auto rv = _fetcher.fetchBlockForPassthrough(atMost);
|
||||||
return {rv.first, {}, std::move(rv.second)};
|
return {rv.first, {}, std::move(rv.second)};
|
||||||
}
|
}
|
||||||
|
|
||||||
template class ::arangodb::aql::IdExecutor<BlockPassthrough::Enable, ConstFetcher>;
|
template class ::arangodb::aql::IdExecutor<ConstFetcher>;
|
||||||
// ID can always pass through
|
// ID can always pass through
|
||||||
template class ::arangodb::aql::IdExecutor<BlockPassthrough::Enable, SingleRowFetcher<BlockPassthrough::Enable>>;
|
template class ::arangodb::aql::IdExecutor<SingleRowFetcher<BlockPassthrough::Enable>>;
|
||||||
// Local gather does NOT want to passThrough
|
|
||||||
template class ::arangodb::aql::IdExecutor<BlockPassthrough::Disable, SingleRowFetcher<BlockPassthrough::Disable>>;
|
|
||||||
|
|
||||||
template std::tuple<ExecutionState, typename IdExecutor<BlockPassthrough::Enable, ConstFetcher>::Stats, SharedAqlItemBlockPtr>
|
|
||||||
IdExecutor<BlockPassthrough::Enable, ConstFetcher>::fetchBlockForPassthrough<BlockPassthrough::Enable, void>(size_t atMost);
|
|
||||||
|
|
||||||
template std::tuple<ExecutionState, typename IdExecutor<BlockPassthrough::Enable, SingleRowFetcher<BlockPassthrough::Enable>>::Stats, SharedAqlItemBlockPtr>
|
|
||||||
IdExecutor<BlockPassthrough::Enable, SingleRowFetcher<BlockPassthrough::Enable>>::fetchBlockForPassthrough<BlockPassthrough::Enable, void>(size_t atMost);
|
|
||||||
|
|
||||||
template std::tuple<ExecutionState, NoStats, size_t>
|
|
||||||
IdExecutor<BlockPassthrough::Disable, SingleRowFetcher<BlockPassthrough::Disable>>::skipRows<BlockPassthrough::Disable, void>(size_t atMost);
|
|
||||||
|
|
|
@ -31,7 +31,20 @@
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
// TODO Clean up unused variants of the IdExecutor - some of them aren't in use anymore.
|
// There are currently three variants of IdExecutor in use:
|
||||||
|
//
|
||||||
|
// - IdExecutor<void>
|
||||||
|
// This is a variant of the ReturnBlock. It can optionally count and holds
|
||||||
|
// an output register id.
|
||||||
|
// - IdExecutor<ConstFetcher>
|
||||||
|
// This is the SingletonBlock.
|
||||||
|
// - IdExecutor<SingleRowFetcher<BlockPassthrough::Enable>>
|
||||||
|
// This is the DistributeConsumerBlock. It holds a distributeId and honors
|
||||||
|
// isResponsibleForInitializeCursor.
|
||||||
|
//
|
||||||
|
// The last variant using the SingleRowFetcher could be replaced by the (faster)
|
||||||
|
// void variant. It only has to learn distributeId and
|
||||||
|
// isResponsibleForInitializeCursor for that.
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
namespace transaction {
|
namespace transaction {
|
||||||
|
@ -57,9 +70,8 @@ class IdExecutorInfos : public ExecutorInfos {
|
||||||
IdExecutorInfos(IdExecutorInfos const&) = delete;
|
IdExecutorInfos(IdExecutorInfos const&) = delete;
|
||||||
~IdExecutorInfos() = default;
|
~IdExecutorInfos() = default;
|
||||||
|
|
||||||
std::string const& distributeId();
|
[[nodiscard]] std::string const& distributeId();
|
||||||
|
|
||||||
// TODO This is probably needed only for UnsortingGather now, so can be removed here.
|
|
||||||
[[nodiscard]] bool isResponsibleForInitializeCursor() const;
|
[[nodiscard]] bool isResponsibleForInitializeCursor() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -69,16 +81,16 @@ class IdExecutorInfos : public ExecutorInfos {
|
||||||
};
|
};
|
||||||
|
|
||||||
// forward declaration
|
// forward declaration
|
||||||
template <BlockPassthrough usePassThrough, class T>
|
template <class Fetcher>
|
||||||
class IdExecutor;
|
class IdExecutor;
|
||||||
|
|
||||||
// (empty) implementation of IdExecutor<void>
|
// (empty) implementation of IdExecutor<void>
|
||||||
template <>
|
template <>
|
||||||
class IdExecutor<BlockPassthrough::Enable, void> {};
|
class IdExecutor<void> {};
|
||||||
|
|
||||||
// implementation of ExecutionBlockImpl<IdExecutor<void>>
|
// implementation of ExecutionBlockImpl<IdExecutor<void>>
|
||||||
template <>
|
template <>
|
||||||
class ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, void>> : public ExecutionBlock {
|
class ExecutionBlockImpl<IdExecutor<void>> : public ExecutionBlock {
|
||||||
public:
|
public:
|
||||||
ExecutionBlockImpl(ExecutionEngine* engine, ExecutionNode const* node,
|
ExecutionBlockImpl(ExecutionEngine* engine, ExecutionNode const* node,
|
||||||
RegisterId outputRegister, bool doCount);
|
RegisterId outputRegister, bool doCount);
|
||||||
|
@ -108,13 +120,13 @@ class ExecutionBlockImpl<IdExecutor<BlockPassthrough::Enable, void>> : public Ex
|
||||||
bool const _doCount;
|
bool const _doCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <BlockPassthrough usePassThrough, class UsedFetcher>
|
template <class UsedFetcher>
|
||||||
// cppcheck-suppress noConstructor
|
// cppcheck-suppress noConstructor
|
||||||
class IdExecutor {
|
class IdExecutor {
|
||||||
public:
|
public:
|
||||||
struct Properties {
|
struct Properties {
|
||||||
static constexpr bool preservesOrder = true;
|
static constexpr bool preservesOrder = true;
|
||||||
static constexpr BlockPassthrough allowsBlockPassthrough = usePassThrough;
|
static constexpr BlockPassthrough allowsBlockPassthrough = BlockPassthrough::Enable;
|
||||||
static constexpr bool inputSizeRestrictsOutputSize = false;
|
static constexpr bool inputSizeRestrictsOutputSize = false;
|
||||||
};
|
};
|
||||||
// Only Supports SingleRowFetcher and ConstFetcher
|
// Only Supports SingleRowFetcher and ConstFetcher
|
||||||
|
@ -133,12 +145,8 @@ class IdExecutor {
|
||||||
*/
|
*/
|
||||||
std::pair<ExecutionState, Stats> produceRows(OutputAqlItemRow& output);
|
std::pair<ExecutionState, Stats> produceRows(OutputAqlItemRow& output);
|
||||||
|
|
||||||
template <BlockPassthrough allowPass = usePassThrough, typename = std::enable_if_t<allowPass == BlockPassthrough::Enable>>
|
|
||||||
std::tuple<ExecutionState, Stats, SharedAqlItemBlockPtr> fetchBlockForPassthrough(size_t atMost);
|
std::tuple<ExecutionState, Stats, SharedAqlItemBlockPtr> fetchBlockForPassthrough(size_t atMost);
|
||||||
|
|
||||||
template <BlockPassthrough allowPass = usePassThrough, typename = std::enable_if_t<allowPass == BlockPassthrough::Disable>>
|
|
||||||
std::tuple<ExecutionState, NoStats, size_t> skipRows(size_t atMost);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Fetcher& _fetcher;
|
Fetcher& _fetcher;
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,10 +55,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool IndexExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough IndexExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool IndexExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
/// resolve constant attribute accesses
|
/// resolve constant attribute accesses
|
||||||
static void resolveFCallConstAttributes(AstNode* fcall) {
|
static void resolveFCallConstAttributes(AstNode* fcall) {
|
||||||
|
|
|
@ -42,10 +42,6 @@
|
||||||
|
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool KShortestPathsExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough KShortestPathsExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool KShortestPathsExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
using namespace arangodb::graph;
|
using namespace arangodb::graph;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -37,10 +37,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool LimitExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough LimitExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool LimitExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
LimitExecutorInfos::LimitExecutorInfos(RegisterId nrInputRegisters, RegisterId nrOutputRegisters,
|
LimitExecutorInfos::LimitExecutorInfos(RegisterId nrInputRegisters, RegisterId nrOutputRegisters,
|
||||||
// cppcheck-suppress passedByValue
|
// cppcheck-suppress passedByValue
|
||||||
std::unordered_set<RegisterId> registersToClear,
|
std::unordered_set<RegisterId> registersToClear,
|
||||||
|
|
|
@ -30,10 +30,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool NoResultsExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough NoResultsExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool NoResultsExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
NoResultsExecutor::NoResultsExecutor(Fetcher& fetcher, ExecutorInfos& infos) {}
|
NoResultsExecutor::NoResultsExecutor(Fetcher& fetcher, ExecutorInfos& infos) {}
|
||||||
NoResultsExecutor::~NoResultsExecutor() = default;
|
NoResultsExecutor::~NoResultsExecutor() = default;
|
||||||
|
|
||||||
|
|
|
@ -7283,7 +7283,7 @@ namespace {
|
||||||
|
|
||||||
bool nodeMakesThisQueryLevelUnsuitableForSubquerySplicing(ExecutionNode const* const node) {
|
bool nodeMakesThisQueryLevelUnsuitableForSubquerySplicing(ExecutionNode const* const node) {
|
||||||
// TODO Enable modification nodes again, as soon as the corresponding branch
|
// TODO Enable modification nodes again, as soon as the corresponding branch
|
||||||
// is merged.
|
// is merged. Fix them in the switch statement below, too!
|
||||||
if (node->isModificationNode()) {
|
if (node->isModificationNode()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// DISCLAIMER
|
||||||
|
///
|
||||||
|
/// Copyright 2019 ArangoDB GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// @author Simon Grätzer
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "ParallelUnsortedGatherExecutor.h"
|
||||||
|
|
||||||
|
#include "Aql/MultiDependencySingleRowFetcher.h"
|
||||||
|
#include "Aql/OutputAqlItemRow.h"
|
||||||
|
#include "Aql/Stats.h"
|
||||||
|
#include "Transaction/Methods.h"
|
||||||
|
|
||||||
|
#include "Logger/LogMacros.h"
|
||||||
|
|
||||||
|
using namespace arangodb;
|
||||||
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
|
ParallelUnsortedGatherExecutorInfos::ParallelUnsortedGatherExecutorInfos(
|
||||||
|
RegisterId nrInOutRegisters, std::unordered_set<RegisterId> registersToKeep,
|
||||||
|
std::unordered_set<RegisterId> registersToClear)
|
||||||
|
: ExecutorInfos(make_shared_unordered_set(), make_shared_unordered_set(),
|
||||||
|
nrInOutRegisters, nrInOutRegisters,
|
||||||
|
std::move(registersToClear), std::move(registersToKeep)) {}
|
||||||
|
|
||||||
|
ParallelUnsortedGatherExecutor::ParallelUnsortedGatherExecutor(Fetcher& fetcher, Infos& infos)
|
||||||
|
: _fetcher(fetcher), _numberDependencies(0), _currentDependency(0), _skipped(0) {}
|
||||||
|
|
||||||
|
ParallelUnsortedGatherExecutor::~ParallelUnsortedGatherExecutor() = default;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Guarantees requiredby this this block:
|
||||||
|
/// 1) For every dependency the input is sorted, according to the same strategy.
|
||||||
|
///
|
||||||
|
/// What this block does:
|
||||||
|
/// InitPhase:
|
||||||
|
/// Fetch 1 Block for every dependency.
|
||||||
|
/// ExecPhase:
|
||||||
|
/// Fetch row of scheduled block.
|
||||||
|
/// Pick the next (sorted) element (by strategy)
|
||||||
|
/// Schedule this block to fetch Row
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::pair<ExecutionState, NoStats> ParallelUnsortedGatherExecutor::produceRows(OutputAqlItemRow& output) {
|
||||||
|
initDependencies();
|
||||||
|
|
||||||
|
ExecutionState state;
|
||||||
|
InputAqlItemRow inputRow = InputAqlItemRow{CreateInvalidInputRowHint{}};
|
||||||
|
|
||||||
|
size_t x;
|
||||||
|
for (x = 0; x < _numberDependencies; ++x) {
|
||||||
|
size_t i = (_currentDependency + x) % _numberDependencies;
|
||||||
|
|
||||||
|
if (_upstream[i] == ExecutionState::DONE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t tmp = 0;
|
||||||
|
|
||||||
|
state = ExecutionState::HASMORE;
|
||||||
|
while (!output.isFull() && state == ExecutionState::HASMORE) {
|
||||||
|
std::tie(state, inputRow) = _fetcher.fetchRowForDependency(i, output.numRowsLeft() /*atMost*/);
|
||||||
|
if (inputRow) {
|
||||||
|
output.copyRow(inputRow);
|
||||||
|
TRI_ASSERT(output.produced());
|
||||||
|
output.advanceRow();
|
||||||
|
tmp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_upstream[i] = state;
|
||||||
|
if (output.isFull()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_currentDependency = x;
|
||||||
|
|
||||||
|
NoStats stats;
|
||||||
|
|
||||||
|
// fix assert in ExecutionBlockImpl<E>::getSomeWithoutTrace
|
||||||
|
if (output.isFull()) {
|
||||||
|
return {ExecutionState::HASMORE, stats};
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t numWaiting = 0;
|
||||||
|
for (x = 0; x < _numberDependencies; ++x) {
|
||||||
|
if (_upstream[x] == ExecutionState::HASMORE) {
|
||||||
|
return {ExecutionState::HASMORE, stats};
|
||||||
|
} else if (_upstream[x] == ExecutionState::WAITING) {
|
||||||
|
numWaiting++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (numWaiting > 0) {
|
||||||
|
return {ExecutionState::WAITING, stats};
|
||||||
|
}
|
||||||
|
|
||||||
|
TRI_ASSERT(std::all_of(_upstream.begin(), _upstream.end(), [](auto const& s) { return s == ExecutionState::DONE; } ));
|
||||||
|
return {ExecutionState::DONE, stats};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<ExecutionState, ParallelUnsortedGatherExecutor::Stats, size_t>
|
||||||
|
ParallelUnsortedGatherExecutor::skipRows(size_t const toSkip) {
|
||||||
|
initDependencies();
|
||||||
|
TRI_ASSERT(_skipped <= toSkip);
|
||||||
|
|
||||||
|
ExecutionState state = ExecutionState::HASMORE;
|
||||||
|
while (_skipped < toSkip) {
|
||||||
|
|
||||||
|
const size_t i = _currentDependency;
|
||||||
|
if (_upstream[i] == ExecutionState::DONE) {
|
||||||
|
if (std::all_of(_upstream.begin(), _upstream.end(),
|
||||||
|
[](auto s) { return s == ExecutionState::DONE; })) {
|
||||||
|
state = ExecutionState::DONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_currentDependency = (i + 1) % _numberDependencies;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRI_ASSERT(_skipped <= toSkip);
|
||||||
|
|
||||||
|
size_t skippedNow;
|
||||||
|
std::tie(state, skippedNow) = _fetcher.skipRowsForDependency(i, toSkip - _skipped);
|
||||||
|
_upstream[i] = state;
|
||||||
|
if (state == ExecutionState::WAITING) {
|
||||||
|
TRI_ASSERT(skippedNow == 0);
|
||||||
|
return {ExecutionState::WAITING, NoStats{}, 0};
|
||||||
|
}
|
||||||
|
_skipped += skippedNow;
|
||||||
|
|
||||||
|
if (_upstream[i] == ExecutionState::DONE) {
|
||||||
|
if (std::all_of(_upstream.begin(), _upstream.end(),
|
||||||
|
[](auto s) { return s == ExecutionState::DONE; })) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_currentDependency = (i + 1) % _numberDependencies;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t skipped = _skipped;
|
||||||
|
_skipped = 0;
|
||||||
|
|
||||||
|
TRI_ASSERT(skipped <= toSkip);
|
||||||
|
return {state, NoStats{}, skipped};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParallelUnsortedGatherExecutor::initDependencies() {
|
||||||
|
if (_numberDependencies == 0) {
|
||||||
|
// We need to initialize the dependencies once, they are injected
|
||||||
|
// after the fetcher is created.
|
||||||
|
_numberDependencies = _fetcher.numberDependencies();
|
||||||
|
TRI_ASSERT(_numberDependencies > 0);
|
||||||
|
_upstream.resize(_numberDependencies, ExecutionState::HASMORE);
|
||||||
|
TRI_ASSERT(std::all_of(_upstream.begin(), _upstream.end(), [](auto const& s) { return s == ExecutionState::HASMORE; } ));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// DISCLAIMER
|
||||||
|
///
|
||||||
|
/// Copyright 2019 ArangoDB GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// @author Simon Grätzer
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef ARANGOD_AQL_PARALLEL_UNSORTED_GATHER_EXECUTOR_H
|
||||||
|
#define ARANGOD_AQL_PARALLEL_UNSORTED_GATHER_EXECUTOR_H
|
||||||
|
|
||||||
|
#include "Aql/ClusterNodes.h"
|
||||||
|
#include "Aql/ExecutionState.h"
|
||||||
|
#include "Aql/ExecutorInfos.h"
|
||||||
|
#include "Aql/InputAqlItemRow.h"
|
||||||
|
#include "Containers/SmallVector.h"
|
||||||
|
|
||||||
|
namespace arangodb {
|
||||||
|
|
||||||
|
namespace transaction {
|
||||||
|
class Methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace aql {
|
||||||
|
|
||||||
|
class MultiDependencySingleRowFetcher;
|
||||||
|
class NoStats;
|
||||||
|
class OutputAqlItemRow;
|
||||||
|
struct SortRegister;
|
||||||
|
|
||||||
|
class ParallelUnsortedGatherExecutorInfos : public ExecutorInfos {
|
||||||
|
public:
|
||||||
|
ParallelUnsortedGatherExecutorInfos(RegisterId nrInOutRegisters,
|
||||||
|
std::unordered_set<RegisterId> registersToKeep,
|
||||||
|
std::unordered_set<RegisterId> registersToClear);
|
||||||
|
ParallelUnsortedGatherExecutorInfos() = delete;
|
||||||
|
ParallelUnsortedGatherExecutorInfos(ParallelUnsortedGatherExecutorInfos&&) = default;
|
||||||
|
ParallelUnsortedGatherExecutorInfos(ParallelUnsortedGatherExecutorInfos const&) = delete;
|
||||||
|
~ParallelUnsortedGatherExecutorInfos() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParallelUnsortedGatherExecutor {
|
||||||
|
public:
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Properties {
|
||||||
|
static constexpr bool preservesOrder = true;
|
||||||
|
static constexpr BlockPassthrough allowsBlockPassthrough = BlockPassthrough::Disable;
|
||||||
|
static constexpr bool inputSizeRestrictsOutputSize = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
using Fetcher = MultiDependencySingleRowFetcher;
|
||||||
|
using Infos = ParallelUnsortedGatherExecutorInfos;
|
||||||
|
using Stats = NoStats;
|
||||||
|
|
||||||
|
ParallelUnsortedGatherExecutor(Fetcher& fetcher, Infos& info);
|
||||||
|
~ParallelUnsortedGatherExecutor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief produce the next Row of Aql Values.
|
||||||
|
*
|
||||||
|
* @return ExecutionState,
|
||||||
|
* if something was written output.hasValue() == true
|
||||||
|
*/
|
||||||
|
std::pair<ExecutionState, Stats> produceRows(OutputAqlItemRow& output);
|
||||||
|
|
||||||
|
std::tuple<ExecutionState, Stats, size_t> skipRows(size_t atMost);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void initDependencies();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Fetcher& _fetcher;
|
||||||
|
// 64: default size of buffer; 8: Alignment size; computed to 4 but breaks in windows debug build.
|
||||||
|
::arangodb::containers::SmallVector<ExecutionState, 64, 8>::allocator_type::arena_type _arena;
|
||||||
|
::arangodb::containers::SmallVector<ExecutionState, 64, 8> _upstream{_arena};
|
||||||
|
|
||||||
|
// Total Number of dependencies
|
||||||
|
size_t _numberDependencies;
|
||||||
|
|
||||||
|
size_t _currentDependency;
|
||||||
|
|
||||||
|
size_t _skipped;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace aql
|
||||||
|
} // namespace arangodb
|
||||||
|
|
||||||
|
#endif // ARANGOD_AQL_PARALLEL_UNSORTED_GATHER_EXECUTOR_H
|
|
@ -499,7 +499,7 @@ std::unique_ptr<ExecutionPlan> Query::preparePlan() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto trx = AqlTransaction::create(std::move(ctx), _collections.collections(),
|
auto trx = AqlTransaction::create(ctx, _collections.collections(),
|
||||||
_queryOptions.transactionOptions, _part == PART_MAIN,
|
_queryOptions.transactionOptions, _part == PART_MAIN,
|
||||||
std::move(inaccessibleCollections));
|
std::move(inaccessibleCollections));
|
||||||
// create the transaction object, but do not start it yet
|
// create the transaction object, but do not start it yet
|
||||||
|
|
|
@ -31,10 +31,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool ReturnExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough ReturnExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool ReturnExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
ReturnExecutorInfos::ReturnExecutorInfos(RegisterId inputRegister, RegisterId nrInputRegisters,
|
ReturnExecutorInfos::ReturnExecutorInfos(RegisterId inputRegister, RegisterId nrInputRegisters,
|
||||||
RegisterId nrOutputRegisters, bool doCount)
|
RegisterId nrOutputRegisters, bool doCount)
|
||||||
: ExecutorInfos(make_shared_unordered_set({inputRegister}),
|
: ExecutorInfos(make_shared_unordered_set({inputRegister}),
|
||||||
|
|
|
@ -66,24 +66,24 @@ class ShadowAqlItemRow {
|
||||||
/// @brief get the number of data registers in the underlying block.
|
/// @brief get the number of data registers in the underlying block.
|
||||||
/// Not all of these registers are necessarily filled by this
|
/// Not all of these registers are necessarily filled by this
|
||||||
/// ShadowRow. There might be empty registers on deeper levels.
|
/// ShadowRow. There might be empty registers on deeper levels.
|
||||||
RegisterCount getNrRegisters() const noexcept;
|
[[nodiscard]] RegisterCount getNrRegisters() const noexcept;
|
||||||
|
|
||||||
/// @brief a ShadowRow is relevant iff it indicates an end of subquery block on the subquery context
|
/// @brief a ShadowRow is relevant iff it indicates an end of subquery block on the subquery context
|
||||||
/// we are in right now. This will only be of importance on nested subqueries.
|
/// we are in right now. This will only be of importance on nested subqueries.
|
||||||
/// Within the inner subquery all shadowrows of this inner are relavant. All shadowRows
|
/// Within the inner subquery all shadowrows of this inner are relevant. All shadowRows
|
||||||
/// of the outer subquery are NOT relevant
|
/// of the outer subquery are NOT relevant
|
||||||
/// Also note: There is a guarantee that a non-relevant shadowrow, can only be encountered
|
/// Also note: There is a guarantee that a non-relevant shadowrow, can only be encountered
|
||||||
/// right after a shadowrow. And only in descending nesting level. (eg 1. inner most, 2. inner, 3. outer most)
|
/// right after a shadowrow. And only in descending nesting level. (eg 1. inner most, 2. inner, 3. outer most)
|
||||||
bool isRelevant() const noexcept;
|
[[nodiscard]] bool isRelevant() const noexcept;
|
||||||
|
|
||||||
/// @brief Test if this shadow row is initialized, eg has a block and has a valid depth.
|
/// @brief Test if this shadow row is initialized, eg has a block and has a valid depth.
|
||||||
bool isInitialized() const;
|
[[nodiscard]] bool isInitialized() const;
|
||||||
|
|
||||||
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
|
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
|
||||||
/**
|
/**
|
||||||
* @brief Compare the underlying block. Only for assertions.
|
* @brief Compare the underlying block. Only for assertions.
|
||||||
*/
|
*/
|
||||||
bool internalBlockIs(SharedAqlItemBlockPtr const& other) const;
|
[[nodiscard]] bool internalBlockIs(SharedAqlItemBlockPtr const& other) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,21 +93,21 @@ class ShadowAqlItemRow {
|
||||||
*
|
*
|
||||||
* @return Reference to the AqlValue stored in that variable.
|
* @return Reference to the AqlValue stored in that variable.
|
||||||
*/
|
*/
|
||||||
AqlValue const& getValue(RegisterId registerId) const;
|
[[nodiscard]] AqlValue const& getValue(RegisterId registerId) const;
|
||||||
|
|
||||||
/// @brief get the depthValue of the shadow row as AqlValue
|
/// @brief get the depthValue of the shadow row as AqlValue
|
||||||
AqlValue const& getShadowDepthValue() const;
|
[[nodiscard]] AqlValue const& getShadowDepthValue() const;
|
||||||
|
|
||||||
/// @brief get the depthValue of the shadow row as int64_t >= 0
|
/// @brief get the depthValue of the shadow row as int64_t >= 0
|
||||||
/// NOTE: Innermost query will have depth 0. Outermost query wil have highest depth.
|
/// NOTE: Innermost query will have depth 0. Outermost query wil have highest depth.
|
||||||
uint64_t getDepth() const;
|
[[nodiscard]] uint64_t getDepth() const;
|
||||||
|
|
||||||
// Note that == and != here check whether the rows are *identical*, that is,
|
// Note that == and != here check whether the rows are *identical*, that is,
|
||||||
// the same row in the same block.
|
// the same row in the same block.
|
||||||
// TODO Make this a named method
|
// TODO Make this a named method
|
||||||
bool operator==(ShadowAqlItemRow const& other) const noexcept;
|
[[nodiscard]] bool operator==(ShadowAqlItemRow const& other) const noexcept;
|
||||||
|
|
||||||
bool operator!=(ShadowAqlItemRow const& other) const noexcept;
|
[[nodiscard]] bool operator!=(ShadowAqlItemRow const& other) const noexcept;
|
||||||
|
|
||||||
// This checks whether the rows are equivalent, in the sense that they hold
|
// This checks whether the rows are equivalent, in the sense that they hold
|
||||||
// the same number of registers and their entry-AqlValues compare equal,
|
// the same number of registers and their entry-AqlValues compare equal,
|
||||||
|
@ -120,9 +120,9 @@ class ShadowAqlItemRow {
|
||||||
velocypack::Options const* option) const noexcept;
|
velocypack::Options const* option) const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AqlItemBlock& block() noexcept;
|
[[nodiscard]] AqlItemBlock& block() noexcept;
|
||||||
|
|
||||||
AqlItemBlock const& block() const noexcept;
|
[[nodiscard]] AqlItemBlock const& block() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -41,10 +41,6 @@
|
||||||
|
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool ShortestPathExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough ShortestPathExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool ShortestPathExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
using namespace arangodb::graph;
|
using namespace arangodb::graph;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -38,13 +38,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
template <typename Modifier>
|
|
||||||
constexpr bool SingleRemoteModificationExecutor<Modifier>::Properties::preservesOrder;
|
|
||||||
template <typename Modifier>
|
|
||||||
constexpr BlockPassthrough SingleRemoteModificationExecutor<Modifier>::Properties::allowsBlockPassthrough;
|
|
||||||
template <typename Modifier>
|
|
||||||
constexpr bool SingleRemoteModificationExecutor<Modifier>::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::unique_ptr<VPackBuilder> merge(VPackSlice document, std::string const& key,
|
std::unique_ptr<VPackBuilder> merge(VPackSlice document, std::string const& key,
|
||||||
TRI_voc_rid_t revision) {
|
TRI_voc_rid_t revision) {
|
||||||
|
|
|
@ -61,8 +61,6 @@ class SingleRowFetcher {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Fetch one new AqlItemRow from upstream.
|
* @brief Fetch one new AqlItemRow from upstream.
|
||||||
* **Guarantee**: the row returned is valid only
|
|
||||||
* until the next call to fetchRow.
|
|
||||||
*
|
*
|
||||||
* @param atMost may be passed if a block knows the maximum it might want to
|
* @param atMost may be passed if a block knows the maximum it might want to
|
||||||
* fetch from upstream (should apply only to the LimitExecutor). Will
|
* fetch from upstream (should apply only to the LimitExecutor). Will
|
||||||
|
@ -71,7 +69,7 @@ class SingleRowFetcher {
|
||||||
*
|
*
|
||||||
* @return A pair with the following properties:
|
* @return A pair with the following properties:
|
||||||
* ExecutionState:
|
* ExecutionState:
|
||||||
* WAITING => IO going on, immediatly return to caller.
|
* WAITING => IO going on, immediately return to caller.
|
||||||
* DONE => No more to expect from Upstream, if you are done with
|
* DONE => No more to expect from Upstream, if you are done with
|
||||||
* this row return DONE to caller.
|
* this row return DONE to caller.
|
||||||
* HASMORE => There is potentially more from above, call again if
|
* HASMORE => There is potentially more from above, call again if
|
||||||
|
|
|
@ -34,10 +34,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool SortExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough SortExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool SortExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// @brief OurLessThan
|
/// @brief OurLessThan
|
||||||
|
@ -83,15 +79,12 @@ static std::shared_ptr<std::unordered_set<RegisterId>> mapSortRegistersToRegiste
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
SortExecutorInfos::SortExecutorInfos(
|
SortExecutorInfos::SortExecutorInfos(std::vector<SortRegister> sortRegisters,
|
||||||
// cppcheck-suppress passedByValue
|
std::size_t limit, AqlItemBlockManager& manager,
|
||||||
std::vector<SortRegister> sortRegisters, std::size_t limit,
|
RegisterId nrInputRegisters, RegisterId nrOutputRegisters,
|
||||||
AqlItemBlockManager& manager, RegisterId nrInputRegisters, RegisterId nrOutputRegisters,
|
std::unordered_set<RegisterId> registersToClear,
|
||||||
// cppcheck-suppress passedByValue
|
std::unordered_set<RegisterId> registersToKeep,
|
||||||
std::unordered_set<RegisterId> registersToClear,
|
velocypack::Options const* options, bool stable)
|
||||||
// cppcheck-suppress passedByValue
|
|
||||||
std::unordered_set<RegisterId> registersToKeep,
|
|
||||||
velocypack::Options const* options, bool stable)
|
|
||||||
: ExecutorInfos(mapSortRegistersToRegisterIds(sortRegisters), nullptr,
|
: ExecutorInfos(mapSortRegistersToRegisterIds(sortRegisters), nullptr,
|
||||||
nrInputRegisters, nrOutputRegisters,
|
nrInputRegisters, nrOutputRegisters,
|
||||||
std::move(registersToClear), std::move(registersToKeep)),
|
std::move(registersToClear), std::move(registersToKeep)),
|
||||||
|
@ -103,7 +96,7 @@ SortExecutorInfos::SortExecutorInfos(
|
||||||
TRI_ASSERT(!_sortRegisters.empty());
|
TRI_ASSERT(!_sortRegisters.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<SortRegister>& SortExecutorInfos::sortRegisters() {
|
std::vector<SortRegister> const& SortExecutorInfos::sortRegisters() const noexcept {
|
||||||
return _sortRegisters;
|
return _sortRegisters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,6 +106,12 @@ velocypack::Options const* SortExecutorInfos::vpackOptions() const noexcept {
|
||||||
return _vpackOptions;
|
return _vpackOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t SortExecutorInfos::limit() const noexcept { return _limit; }
|
||||||
|
|
||||||
|
AqlItemBlockManager& SortExecutorInfos::itemBlockManager() noexcept {
|
||||||
|
return _manager;
|
||||||
|
}
|
||||||
|
|
||||||
SortExecutor::SortExecutor(Fetcher& fetcher, SortExecutorInfos& infos)
|
SortExecutor::SortExecutor(Fetcher& fetcher, SortExecutorInfos& infos)
|
||||||
: _infos(infos), _fetcher(fetcher), _input(nullptr), _returnNext(0) {}
|
: _infos(infos), _fetcher(fetcher), _input(nullptr), _returnNext(0) {}
|
||||||
SortExecutor::~SortExecutor() = default;
|
SortExecutor::~SortExecutor() = default;
|
||||||
|
|
|
@ -63,10 +63,15 @@ class SortExecutorInfos : public ExecutorInfos {
|
||||||
|
|
||||||
[[nodiscard]] velocypack::Options const* vpackOptions() const noexcept;
|
[[nodiscard]] velocypack::Options const* vpackOptions() const noexcept;
|
||||||
|
|
||||||
std::vector<SortRegister>& sortRegisters();
|
[[nodiscard]] std::vector<SortRegister> const& sortRegisters() const noexcept;
|
||||||
|
|
||||||
bool stable() const;
|
[[nodiscard]] bool stable() const;
|
||||||
|
|
||||||
|
[[nodiscard]] size_t limit() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] AqlItemBlockManager& itemBlockManager() noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
std::size_t _limit;
|
std::size_t _limit;
|
||||||
AqlItemBlockManager& _manager;
|
AqlItemBlockManager& _manager;
|
||||||
velocypack::Options const* _vpackOptions;
|
velocypack::Options const* _vpackOptions;
|
||||||
|
|
|
@ -235,7 +235,7 @@ std::unique_ptr<ExecutionBlock> SortNode::createBlock(
|
||||||
auto it = getRegisterPlan()->varInfo.find(element.var->id);
|
auto it = getRegisterPlan()->varInfo.find(element.var->id);
|
||||||
TRI_ASSERT(it != getRegisterPlan()->varInfo.end());
|
TRI_ASSERT(it != getRegisterPlan()->varInfo.end());
|
||||||
RegisterId id = it->second.registerId;
|
RegisterId id = it->second.registerId;
|
||||||
sortRegs.push_back(SortRegister{id, element});
|
sortRegs.emplace_back(id, element);
|
||||||
}
|
}
|
||||||
SortExecutorInfos infos(std::move(sortRegs), _limit, engine.itemBlockManager(),
|
SortExecutorInfos infos(std::move(sortRegs), _limit, engine.itemBlockManager(),
|
||||||
getRegisterPlan()->nrRegs[previousNode->getDepth()],
|
getRegisterPlan()->nrRegs[previousNode->getDepth()],
|
||||||
|
|
|
@ -40,10 +40,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool SortedCollectExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough SortedCollectExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool SortedCollectExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
static const AqlValue EmptyValue;
|
static const AqlValue EmptyValue;
|
||||||
|
|
||||||
SortedCollectExecutor::CollectGroup::CollectGroup(bool count, Infos& infos)
|
SortedCollectExecutor::CollectGroup::CollectGroup(bool count, Infos& infos)
|
||||||
|
|
|
@ -31,10 +31,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool SortingGatherExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough SortingGatherExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool SortingGatherExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// @brief OurLessThan: comparison method for elements of SortingGatherBlock
|
/// @brief OurLessThan: comparison method for elements of SortingGatherBlock
|
||||||
|
|
|
@ -35,10 +35,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool SubqueryEndExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough SubqueryEndExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool SubqueryEndExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
SubqueryEndExecutorInfos::SubqueryEndExecutorInfos(
|
SubqueryEndExecutorInfos::SubqueryEndExecutorInfos(
|
||||||
std::shared_ptr<std::unordered_set<RegisterId>> readableInputRegisters,
|
std::shared_ptr<std::unordered_set<RegisterId>> readableInputRegisters,
|
||||||
std::shared_ptr<std::unordered_set<RegisterId>> writeableOutputRegisters,
|
std::shared_ptr<std::unordered_set<RegisterId>> writeableOutputRegisters,
|
||||||
|
@ -53,11 +49,9 @@ SubqueryEndExecutorInfos::SubqueryEndExecutorInfos(
|
||||||
_outReg(outReg),
|
_outReg(outReg),
|
||||||
_inReg(inReg) {}
|
_inReg(inReg) {}
|
||||||
|
|
||||||
SubqueryEndExecutorInfos::SubqueryEndExecutorInfos(SubqueryEndExecutorInfos&& other) = default;
|
|
||||||
|
|
||||||
SubqueryEndExecutorInfos::~SubqueryEndExecutorInfos() = default;
|
SubqueryEndExecutorInfos::~SubqueryEndExecutorInfos() = default;
|
||||||
|
|
||||||
bool SubqueryEndExecutorInfos::usesInputRegister() const {
|
bool SubqueryEndExecutorInfos::usesInputRegister() const noexcept {
|
||||||
return _inReg != RegisterPlan::MaxRegisterId;
|
return _inReg != RegisterPlan::MaxRegisterId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +59,12 @@ velocypack::Options const* SubqueryEndExecutorInfos::vpackOptions() const noexce
|
||||||
return _vpackOptions;
|
return _vpackOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RegisterId SubqueryEndExecutorInfos::getOutputRegister() const noexcept {
|
||||||
|
return _outReg;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterId SubqueryEndExecutorInfos::getInputRegister() const noexcept { return _inReg; }
|
||||||
|
|
||||||
SubqueryEndExecutor::SubqueryEndExecutor(Fetcher& fetcher, SubqueryEndExecutorInfos& infos)
|
SubqueryEndExecutor::SubqueryEndExecutor(Fetcher& fetcher, SubqueryEndExecutorInfos& infos)
|
||||||
: _fetcher(fetcher), _infos(infos), _accumulator(nullptr), _state(ACCUMULATE) {
|
: _fetcher(fetcher), _infos(infos), _accumulator(nullptr), _state(ACCUMULATE) {
|
||||||
resetAccumulator();
|
resetAccumulator();
|
||||||
|
|
|
@ -52,14 +52,14 @@ class SubqueryEndExecutorInfos : public ExecutorInfos {
|
||||||
RegisterId outReg);
|
RegisterId outReg);
|
||||||
|
|
||||||
SubqueryEndExecutorInfos() = delete;
|
SubqueryEndExecutorInfos() = delete;
|
||||||
SubqueryEndExecutorInfos(SubqueryEndExecutorInfos&&);
|
SubqueryEndExecutorInfos(SubqueryEndExecutorInfos&&) noexcept = default;
|
||||||
SubqueryEndExecutorInfos(SubqueryEndExecutorInfos const&) = delete;
|
SubqueryEndExecutorInfos(SubqueryEndExecutorInfos const&) = delete;
|
||||||
~SubqueryEndExecutorInfos();
|
~SubqueryEndExecutorInfos();
|
||||||
|
|
||||||
[[nodiscard]] velocypack::Options const* vpackOptions() const noexcept;
|
[[nodiscard]] velocypack::Options const* vpackOptions() const noexcept;
|
||||||
inline RegisterId getOutputRegister() const { return _outReg; }
|
[[nodiscard]] RegisterId getOutputRegister() const noexcept;
|
||||||
bool usesInputRegister() const;
|
[[nodiscard]] bool usesInputRegister() const noexcept;
|
||||||
inline RegisterId getInputRegister() const { return _inReg; }
|
[[nodiscard]] RegisterId getInputRegister() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
velocypack::Options const* _vpackOptions;
|
velocypack::Options const* _vpackOptions;
|
||||||
|
|
|
@ -30,13 +30,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
template <bool isModificationSubquery>
|
|
||||||
constexpr bool SubqueryExecutor<isModificationSubquery>::Properties::preservesOrder;
|
|
||||||
template <bool isModificationSubquery>
|
|
||||||
constexpr BlockPassthrough SubqueryExecutor<isModificationSubquery>::Properties::allowsBlockPassthrough;
|
|
||||||
template <bool isModificationSubquery>
|
|
||||||
constexpr bool SubqueryExecutor<isModificationSubquery>::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
SubqueryExecutorInfos::SubqueryExecutorInfos(
|
SubqueryExecutorInfos::SubqueryExecutorInfos(
|
||||||
std::shared_ptr<std::unordered_set<RegisterId>> readableInputRegisters,
|
std::shared_ptr<std::unordered_set<RegisterId>> readableInputRegisters,
|
||||||
std::shared_ptr<std::unordered_set<RegisterId>> writeableOutputRegisters,
|
std::shared_ptr<std::unordered_set<RegisterId>> writeableOutputRegisters,
|
||||||
|
|
|
@ -30,10 +30,6 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool SubqueryStartExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough SubqueryStartExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool SubqueryStartExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
SubqueryStartExecutor::SubqueryStartExecutor(Fetcher& fetcher, Infos& infos)
|
SubqueryStartExecutor::SubqueryStartExecutor(Fetcher& fetcher, Infos& infos)
|
||||||
: _fetcher(fetcher),
|
: _fetcher(fetcher),
|
||||||
_state(ExecutionState::HASMORE),
|
_state(ExecutionState::HASMORE),
|
||||||
|
|
|
@ -37,10 +37,6 @@ using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
using namespace arangodb::traverser;
|
using namespace arangodb::traverser;
|
||||||
|
|
||||||
constexpr bool TraversalExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough TraversalExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool TraversalExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
TraversalExecutorInfos::TraversalExecutorInfos(
|
TraversalExecutorInfos::TraversalExecutorInfos(
|
||||||
std::shared_ptr<std::unordered_set<RegisterId>> inputRegisters,
|
std::shared_ptr<std::unordered_set<RegisterId>> inputRegisters,
|
||||||
std::shared_ptr<std::unordered_set<RegisterId>> outputRegisters, RegisterId nrInputRegisters,
|
std::shared_ptr<std::unordered_set<RegisterId>> outputRegisters, RegisterId nrInputRegisters,
|
||||||
|
|
|
@ -17,167 +17,109 @@
|
||||||
///
|
///
|
||||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
///
|
///
|
||||||
/// @author Simon Grätzer
|
/// @author Tobias Gödderz
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "UnsortedGatherExecutor.h"
|
#include "UnsortedGatherExecutor.h"
|
||||||
|
|
||||||
|
#include "Aql/IdExecutor.h" // for IdExecutorInfos
|
||||||
#include "Aql/MultiDependencySingleRowFetcher.h"
|
#include "Aql/MultiDependencySingleRowFetcher.h"
|
||||||
#include "Aql/OutputAqlItemRow.h"
|
#include "Aql/OutputAqlItemRow.h"
|
||||||
#include "Aql/SortRegister.h"
|
|
||||||
#include "Aql/Stats.h"
|
#include "Aql/Stats.h"
|
||||||
#include "Transaction/Methods.h"
|
#include "Basics/debugging.h"
|
||||||
|
|
||||||
#include "Logger/LogMacros.h"
|
|
||||||
|
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
constexpr bool UnsortedGatherExecutor::Properties::preservesOrder;
|
|
||||||
constexpr BlockPassthrough UnsortedGatherExecutor::Properties::allowsBlockPassthrough;
|
|
||||||
constexpr bool UnsortedGatherExecutor::Properties::inputSizeRestrictsOutputSize;
|
|
||||||
|
|
||||||
UnsortedGatherExecutorInfos::UnsortedGatherExecutorInfos(
|
|
||||||
RegisterId nrInOutRegisters, std::unordered_set<RegisterId> registersToKeep,
|
|
||||||
std::unordered_set<RegisterId> registersToClear)
|
|
||||||
: ExecutorInfos(make_shared_unordered_set(), make_shared_unordered_set(),
|
|
||||||
nrInOutRegisters, nrInOutRegisters,
|
|
||||||
std::move(registersToClear), std::move(registersToKeep)) {}
|
|
||||||
|
|
||||||
UnsortedGatherExecutor::UnsortedGatherExecutor(Fetcher& fetcher, Infos& infos)
|
UnsortedGatherExecutor::UnsortedGatherExecutor(Fetcher& fetcher, Infos& infos)
|
||||||
: _fetcher(fetcher),
|
: _fetcher(fetcher) {}
|
||||||
_numberDependencies(0),
|
|
||||||
_currentDependency(0),
|
|
||||||
_skipped(0) {}
|
|
||||||
|
|
||||||
UnsortedGatherExecutor::~UnsortedGatherExecutor() = default;
|
UnsortedGatherExecutor::~UnsortedGatherExecutor() = default;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
auto UnsortedGatherExecutor::produceRows(OutputAqlItemRow& output)
|
||||||
/// @brief Guarantees requiredby this this block:
|
-> std::pair<ExecutionState, Stats> {
|
||||||
/// 1) For every dependency the input is sorted, according to the same strategy.
|
while (!output.isFull() && !done()) {
|
||||||
///
|
// Note that fetchNextRow may return DONE (because the current dependency is
|
||||||
/// What this block does:
|
// DONE), and also return an unitialized row in that case, but we are not
|
||||||
/// InitPhase:
|
// DONE completely - that's what `done()` is for.
|
||||||
/// Fetch 1 Block for every dependency.
|
auto [state, inputRow] = fetchNextRow(output.numRowsLeft());
|
||||||
/// ExecPhase:
|
|
||||||
/// Fetch row of scheduled block.
|
|
||||||
/// Pick the next (sorted) element (by strategy)
|
|
||||||
/// Schedule this block to fetch Row
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
std::pair<ExecutionState, NoStats> UnsortedGatherExecutor::produceRows(OutputAqlItemRow& output) {
|
|
||||||
|
|
||||||
initDependencies();
|
|
||||||
|
|
||||||
ExecutionState state;
|
|
||||||
InputAqlItemRow inputRow = InputAqlItemRow{CreateInvalidInputRowHint{}};
|
|
||||||
|
|
||||||
size_t x;
|
|
||||||
for (x = 0; x < _numberDependencies; ++x) {
|
|
||||||
size_t i = (_currentDependency + x) % _numberDependencies;
|
|
||||||
|
|
||||||
if (_upstream[i] == ExecutionState::DONE) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t tmp = 0;
|
|
||||||
|
|
||||||
state = ExecutionState::HASMORE;
|
|
||||||
while (!output.isFull() && state == ExecutionState::HASMORE) {
|
|
||||||
std::tie(state, inputRow) = _fetcher.fetchRowForDependency(i, output.numRowsLeft() /*atMost*/);
|
|
||||||
if (inputRow) {
|
|
||||||
output.copyRow(inputRow);
|
|
||||||
TRI_ASSERT(output.produced());
|
|
||||||
output.advanceRow();
|
|
||||||
tmp++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_upstream[i] = state;
|
|
||||||
if (output.isFull()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_currentDependency = x;
|
|
||||||
|
|
||||||
NoStats stats;
|
|
||||||
|
|
||||||
// fix assert in ExecutionBlockImpl<E>::getSomeWithoutTrace
|
|
||||||
if (output.isFull()) {
|
|
||||||
return {ExecutionState::HASMORE, stats};
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t numWaiting = 0;
|
|
||||||
for (x = 0; x < _numberDependencies; ++x) {
|
|
||||||
if (_upstream[x] == ExecutionState::HASMORE) {
|
|
||||||
return {ExecutionState::HASMORE, stats};
|
|
||||||
} else if (_upstream[x] == ExecutionState::WAITING) {
|
|
||||||
numWaiting++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (numWaiting > 0) {
|
|
||||||
return {ExecutionState::WAITING, stats};
|
|
||||||
}
|
|
||||||
|
|
||||||
TRI_ASSERT(std::all_of(_upstream.begin(), _upstream.end(), [](auto const& s) { return s == ExecutionState::DONE; } ));
|
|
||||||
return {ExecutionState::DONE, stats};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::tuple<ExecutionState, UnsortedGatherExecutor::Stats, size_t> UnsortedGatherExecutor::skipRows(size_t const toSkip) {
|
|
||||||
|
|
||||||
initDependencies();
|
|
||||||
TRI_ASSERT(_skipped <= toSkip);
|
|
||||||
|
|
||||||
ExecutionState state = ExecutionState::HASMORE;
|
|
||||||
while (_skipped < toSkip) {
|
|
||||||
|
|
||||||
const size_t i = _currentDependency;
|
|
||||||
if (_upstream[i] == ExecutionState::DONE) {
|
|
||||||
if (std::all_of(_upstream.begin(), _upstream.end(),
|
|
||||||
[](auto s) { return s == ExecutionState::DONE; })) {
|
|
||||||
state = ExecutionState::DONE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_currentDependency = (i + 1) % _numberDependencies;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRI_ASSERT(_skipped <= toSkip);
|
|
||||||
|
|
||||||
size_t skippedNow;
|
|
||||||
std::tie(state, skippedNow) = _fetcher.skipRowsForDependency(i, toSkip - _skipped);
|
|
||||||
_upstream[i] = state;
|
|
||||||
if (state == ExecutionState::WAITING) {
|
if (state == ExecutionState::WAITING) {
|
||||||
TRI_ASSERT(skippedNow == 0);
|
return {state, {}};
|
||||||
return {ExecutionState::WAITING, NoStats{}, 0};
|
}
|
||||||
|
// HASMORE => inputRow.isInitialized()
|
||||||
|
TRI_ASSERT(state == ExecutionState::DONE || inputRow.isInitialized());
|
||||||
|
if (inputRow.isInitialized()) {
|
||||||
|
output.copyRow(inputRow);
|
||||||
|
TRI_ASSERT(output.produced());
|
||||||
|
output.advanceRow();
|
||||||
}
|
}
|
||||||
_skipped += skippedNow;
|
|
||||||
|
|
||||||
if (_upstream[i] == ExecutionState::DONE) {
|
|
||||||
if (std::all_of(_upstream.begin(), _upstream.end(),
|
|
||||||
[](auto s) { return s == ExecutionState::DONE; })) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_currentDependency = (i + 1) % _numberDependencies;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t skipped = _skipped;
|
|
||||||
_skipped = 0;
|
|
||||||
|
|
||||||
TRI_ASSERT(skipped <= toSkip);
|
auto state = done() ? ExecutionState::DONE : ExecutionState::HASMORE;
|
||||||
return {state, NoStats{}, skipped};
|
return {state, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnsortedGatherExecutor::initDependencies() {
|
auto UnsortedGatherExecutor::fetcher() const noexcept -> const Fetcher& {
|
||||||
if (_numberDependencies == 0) {
|
return _fetcher;
|
||||||
// We need to initialize the dependencies once, they are injected
|
}
|
||||||
// after the fetcher is created.
|
|
||||||
_numberDependencies = _fetcher.numberDependencies();
|
auto UnsortedGatherExecutor::fetcher() noexcept -> Fetcher& { return _fetcher; }
|
||||||
TRI_ASSERT(_numberDependencies > 0);
|
|
||||||
_upstream.resize(_numberDependencies, ExecutionState::HASMORE);
|
auto UnsortedGatherExecutor::numDependencies() const
|
||||||
TRI_ASSERT(std::all_of(_upstream.begin(), _upstream.end(), [](auto const& s) { return s == ExecutionState::HASMORE; } ));
|
noexcept(noexcept(_fetcher.numberDependencies())) -> size_t {
|
||||||
}
|
return _fetcher.numberDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto UnsortedGatherExecutor::fetchNextRow(size_t atMost)
|
||||||
|
-> std::pair<ExecutionState, InputAqlItemRow> {
|
||||||
|
auto res = fetcher().fetchRowForDependency(currentDependency(), atMost);
|
||||||
|
if (res.first == ExecutionState::DONE) {
|
||||||
|
advanceDependency();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto UnsortedGatherExecutor::skipNextRows(size_t atMost)
|
||||||
|
-> std::pair<ExecutionState, size_t> {
|
||||||
|
auto res = fetcher().skipRowsForDependency(currentDependency(), atMost);
|
||||||
|
if (res.first == ExecutionState::DONE) {
|
||||||
|
advanceDependency();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto UnsortedGatherExecutor::done() const noexcept -> bool {
|
||||||
|
return _currentDependency >= numDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto UnsortedGatherExecutor::currentDependency() const noexcept -> size_t {
|
||||||
|
return _currentDependency;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto UnsortedGatherExecutor::advanceDependency() noexcept -> void {
|
||||||
|
TRI_ASSERT(_currentDependency < numDependencies());
|
||||||
|
++_currentDependency;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto UnsortedGatherExecutor::skipRows(size_t const atMost)
|
||||||
|
-> std::tuple<ExecutionState, UnsortedGatherExecutor::Stats, size_t> {
|
||||||
|
auto const rowsLeftToSkip = [&atMost, &skipped = this->_skipped]() {
|
||||||
|
TRI_ASSERT(atMost >= skipped);
|
||||||
|
return atMost - skipped;
|
||||||
|
};
|
||||||
|
while (rowsLeftToSkip() > 0 && !done()) {
|
||||||
|
// Note that skipNextRow may return DONE (because the current dependency is
|
||||||
|
// DONE), and also return an unitialized row in that case, but we are not
|
||||||
|
// DONE completely - that's what `done()` is for.
|
||||||
|
auto [state, skipped] = skipNextRows(rowsLeftToSkip());
|
||||||
|
_skipped += skipped;
|
||||||
|
if (state == ExecutionState::WAITING) {
|
||||||
|
return {state, {}, 0};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto state = done() ? ExecutionState::DONE : ExecutionState::HASMORE;
|
||||||
|
auto skipped = size_t{0};
|
||||||
|
std::swap(skipped, _skipped);
|
||||||
|
return {state, {}, skipped};
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,56 +17,58 @@
|
||||||
///
|
///
|
||||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
///
|
///
|
||||||
/// @author Simon Grätzer
|
/// @author Tobias Gödderz
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef ARANGOD_AQL_UNSORTED_GATHER_EXECUTOR_H
|
#ifndef ARANGOD_AQL_UNSORTEDGATHEREXECUTOR_H
|
||||||
#define ARANGOD_AQL_UNSORTED_GATHER_EXECUTOR_H
|
#define ARANGOD_AQL_UNSORTEDGATHEREXECUTOR_H
|
||||||
|
|
||||||
#include "Aql/ClusterNodes.h"
|
|
||||||
#include "Aql/ExecutionState.h"
|
#include "Aql/ExecutionState.h"
|
||||||
#include "Aql/ExecutorInfos.h"
|
#include "Aql/ExecutorInfos.h"
|
||||||
#include "Aql/InputAqlItemRow.h"
|
#include "Aql/MultiDependencySingleRowFetcher.h"
|
||||||
#include "Containers/SmallVector.h"
|
#include "Aql/types.h"
|
||||||
|
|
||||||
namespace arangodb {
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace transaction {
|
namespace arangodb::aql {
|
||||||
class Methods;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace aql {
|
|
||||||
|
|
||||||
class MultiDependencySingleRowFetcher;
|
|
||||||
class NoStats;
|
class NoStats;
|
||||||
|
class InputAqlItemRow;
|
||||||
class OutputAqlItemRow;
|
class OutputAqlItemRow;
|
||||||
struct SortRegister;
|
class IdExecutorInfos;
|
||||||
|
class SharedAqlItemBlockPtr;
|
||||||
class UnsortedGatherExecutorInfos : public ExecutorInfos {
|
|
||||||
public:
|
|
||||||
UnsortedGatherExecutorInfos(RegisterId nrInOutRegisters, std::unordered_set<RegisterId> registersToKeep,
|
|
||||||
std::unordered_set<RegisterId> registersToClear);
|
|
||||||
UnsortedGatherExecutorInfos() = delete;
|
|
||||||
UnsortedGatherExecutorInfos(UnsortedGatherExecutorInfos&&) = default;
|
|
||||||
UnsortedGatherExecutorInfos(UnsortedGatherExecutorInfos const&) = delete;
|
|
||||||
~UnsortedGatherExecutorInfos() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Produces all rows from its dependencies, which may be more than one,
|
||||||
|
* in some unspecified order. It is, purposefully, strictly synchronous, and
|
||||||
|
* always waits for an answer before requesting the next row(s). This is as
|
||||||
|
* opposed to the ParallelUnsortedGather, which already starts fetching the next
|
||||||
|
* dependenci(es) while waiting for an answer.
|
||||||
|
*
|
||||||
|
* The actual implementation fetches all available rows from the first
|
||||||
|
* dependency, then from the second, and so forth. But that is not guaranteed.
|
||||||
|
*/
|
||||||
class UnsortedGatherExecutor {
|
class UnsortedGatherExecutor {
|
||||||
public:
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Properties {
|
struct Properties {
|
||||||
static constexpr bool preservesOrder = true;
|
static constexpr bool preservesOrder = false;
|
||||||
static constexpr BlockPassthrough allowsBlockPassthrough = BlockPassthrough::Disable;
|
static constexpr BlockPassthrough allowsBlockPassthrough = BlockPassthrough::Disable;
|
||||||
|
// This (inputSizeRestrictsOutputSize) could be set to true, but its
|
||||||
|
// usefulness would be limited.
|
||||||
|
// We either can only use it for the last dependency, in which case it's
|
||||||
|
// already too late to avoid a large allocation for a small result set; or
|
||||||
|
// we'd have to prefetch all dependencies (at least until we got >=1000
|
||||||
|
// rows) before answering hasExpectedNumberOfRows(). This might be okay,
|
||||||
|
// but would increase the latency.
|
||||||
static constexpr bool inputSizeRestrictsOutputSize = false;
|
static constexpr bool inputSizeRestrictsOutputSize = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Fetcher = MultiDependencySingleRowFetcher;
|
using Fetcher = MultiDependencySingleRowFetcher;
|
||||||
using Infos = UnsortedGatherExecutorInfos;
|
// TODO I should probably implement custom Infos, we don't need distributeId().
|
||||||
|
using Infos = IdExecutorInfos;
|
||||||
using Stats = NoStats;
|
using Stats = NoStats;
|
||||||
|
|
||||||
UnsortedGatherExecutor(Fetcher& fetcher, Infos& info);
|
UnsortedGatherExecutor(Fetcher& fetcher, Infos&);
|
||||||
~UnsortedGatherExecutor();
|
~UnsortedGatherExecutor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,29 +77,29 @@ class UnsortedGatherExecutor {
|
||||||
* @return ExecutionState,
|
* @return ExecutionState,
|
||||||
* if something was written output.hasValue() == true
|
* if something was written output.hasValue() == true
|
||||||
*/
|
*/
|
||||||
std::pair<ExecutionState, Stats> produceRows(OutputAqlItemRow& output);
|
[[nodiscard]] auto produceRows(OutputAqlItemRow& output)
|
||||||
|
-> std::pair<ExecutionState, Stats>;
|
||||||
|
|
||||||
|
[[nodiscard]] auto skipRows(size_t atMost) -> std::tuple<ExecutionState, NoStats, size_t>;
|
||||||
|
|
||||||
std::tuple<ExecutionState, Stats, size_t> skipRows(size_t atMost);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
[[nodiscard]] auto numDependencies() const
|
||||||
void initDependencies();
|
noexcept(noexcept(static_cast<Fetcher*>(nullptr)->numberDependencies())) -> size_t;
|
||||||
|
[[nodiscard]] auto fetcher() const noexcept -> Fetcher const&;
|
||||||
|
[[nodiscard]] auto fetcher() noexcept -> Fetcher&;
|
||||||
|
[[nodiscard]] auto done() const noexcept -> bool;
|
||||||
|
[[nodiscard]] auto currentDependency() const noexcept -> size_t;
|
||||||
|
[[nodiscard]] auto fetchNextRow(size_t atMost)
|
||||||
|
-> std::pair<ExecutionState, InputAqlItemRow>;
|
||||||
|
[[nodiscard]] auto skipNextRows(size_t atMost) -> std::pair<ExecutionState, size_t>;
|
||||||
|
auto advanceDependency() noexcept -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Fetcher& _fetcher;
|
Fetcher& _fetcher;
|
||||||
// 64: default size of buffer; 8: Alignment size; computed to 4 but breaks in windows debug build.
|
size_t _currentDependency{0};
|
||||||
::arangodb::containers::SmallVector<ExecutionState, 64, 8>::allocator_type::arena_type _arena;
|
size_t _skipped{0};
|
||||||
::arangodb::containers::SmallVector<ExecutionState, 64, 8> _upstream{_arena};
|
|
||||||
|
|
||||||
// Total Number of dependencies
|
|
||||||
size_t _numberDependencies;
|
|
||||||
|
|
||||||
size_t _currentDependency;
|
|
||||||
|
|
||||||
size_t _skipped;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aql
|
} // namespace arangodb::aql
|
||||||
} // namespace arangodb
|
|
||||||
|
|
||||||
#endif
|
#endif // ARANGOD_AQL_UNSORTEDGATHEREXECUTOR_H
|
||||||
|
|
|
@ -1,130 +0,0 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// DISCLAIMER
|
|
||||||
///
|
|
||||||
/// Copyright 2019 ArangoDB GmbH, Cologne, Germany
|
|
||||||
///
|
|
||||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
/// you may not use this file except in compliance with the License.
|
|
||||||
/// You may obtain a copy of the License at
|
|
||||||
///
|
|
||||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
///
|
|
||||||
/// Unless required by applicable law or agreed to in writing, software
|
|
||||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
/// See the License for the specific language governing permissions and
|
|
||||||
/// limitations under the License.
|
|
||||||
///
|
|
||||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
||||||
///
|
|
||||||
/// @author Tobias Gödderz
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "UnsortingGatherExecutor.h"
|
|
||||||
#include <Logger/LogMacros.h>
|
|
||||||
|
|
||||||
#include "Aql/IdExecutor.h" // for IdExecutorInfos
|
|
||||||
#include "Aql/MultiDependencySingleRowFetcher.h"
|
|
||||||
#include "Aql/OutputAqlItemRow.h"
|
|
||||||
#include "Aql/Stats.h"
|
|
||||||
#include "Basics/Exceptions.h"
|
|
||||||
#include "Basics/debugging.h"
|
|
||||||
#include "Basics/voc-errors.h"
|
|
||||||
|
|
||||||
using namespace arangodb;
|
|
||||||
using namespace arangodb::aql;
|
|
||||||
|
|
||||||
UnsortingGatherExecutor::UnsortingGatherExecutor(Fetcher& fetcher, Infos& infos)
|
|
||||||
: _fetcher(fetcher) {}
|
|
||||||
|
|
||||||
UnsortingGatherExecutor::~UnsortingGatherExecutor() = default;
|
|
||||||
|
|
||||||
auto UnsortingGatherExecutor::produceRows(OutputAqlItemRow& output)
|
|
||||||
-> std::pair<ExecutionState, Stats> {
|
|
||||||
while (!output.isFull() && !done()) {
|
|
||||||
// Note that fetchNextRow may return DONE (because the current dependency is
|
|
||||||
// DONE), and also return an unitialized row in that case, but we are not
|
|
||||||
// DONE completely - that's what `done()` is for.
|
|
||||||
auto [state, inputRow] = fetchNextRow(output.numRowsLeft());
|
|
||||||
if (state == ExecutionState::WAITING) {
|
|
||||||
return {state, {}};
|
|
||||||
}
|
|
||||||
// HASMORE => inputRow.isInitialized()
|
|
||||||
TRI_ASSERT(state == ExecutionState::DONE || inputRow.isInitialized());
|
|
||||||
if (inputRow.isInitialized()) {
|
|
||||||
output.copyRow(inputRow);
|
|
||||||
TRI_ASSERT(output.produced());
|
|
||||||
output.advanceRow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto state = done() ? ExecutionState::DONE : ExecutionState::HASMORE;
|
|
||||||
return {state, {}};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto UnsortingGatherExecutor::fetcher() const noexcept -> const Fetcher& {
|
|
||||||
return _fetcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto UnsortingGatherExecutor::fetcher() noexcept -> Fetcher& {
|
|
||||||
return _fetcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto UnsortingGatherExecutor::numDependencies() const
|
|
||||||
noexcept(noexcept(_fetcher.numberDependencies())) -> size_t {
|
|
||||||
return _fetcher.numberDependencies();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto UnsortingGatherExecutor::fetchNextRow(size_t atMost)
|
|
||||||
-> std::pair<ExecutionState, InputAqlItemRow> {
|
|
||||||
auto res = fetcher().fetchRowForDependency(currentDependency(), atMost);
|
|
||||||
if (res.first == ExecutionState::DONE) {
|
|
||||||
advanceDependency();
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto UnsortingGatherExecutor::skipNextRows(size_t atMost)
|
|
||||||
-> std::pair<ExecutionState, size_t> {
|
|
||||||
auto res = fetcher().skipRowsForDependency(currentDependency(), atMost);
|
|
||||||
if (res.first == ExecutionState::DONE) {
|
|
||||||
advanceDependency();
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto UnsortingGatherExecutor::done() const noexcept -> bool {
|
|
||||||
return _currentDependency >= numDependencies();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto UnsortingGatherExecutor::currentDependency() const noexcept -> size_t {
|
|
||||||
return _currentDependency;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto UnsortingGatherExecutor::advanceDependency() noexcept -> void {
|
|
||||||
TRI_ASSERT(_currentDependency < numDependencies());
|
|
||||||
++_currentDependency;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto UnsortingGatherExecutor::skipRows(size_t const atMost)
|
|
||||||
-> std::tuple<ExecutionState, UnsortingGatherExecutor::Stats, size_t> {
|
|
||||||
auto const rowsLeftToSkip = [&atMost, &skipped = this->_skipped]() {
|
|
||||||
TRI_ASSERT(atMost >= skipped);
|
|
||||||
return atMost - skipped;
|
|
||||||
};
|
|
||||||
while (rowsLeftToSkip() > 0 && !done()) {
|
|
||||||
// Note that skipNextRow may return DONE (because the current dependency is
|
|
||||||
// DONE), and also return an unitialized row in that case, but we are not
|
|
||||||
// DONE completely - that's what `done()` is for.
|
|
||||||
auto [state, skipped] = skipNextRows(rowsLeftToSkip());
|
|
||||||
_skipped += skipped;
|
|
||||||
if (state == ExecutionState::WAITING) {
|
|
||||||
return {state, {}, 0};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto state = done() ? ExecutionState::DONE : ExecutionState::HASMORE;
|
|
||||||
auto skipped = size_t{0};
|
|
||||||
std::swap(skipped, _skipped);
|
|
||||||
return {state, {}, skipped};
|
|
||||||
}
|
|
|
@ -1,98 +0,0 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// DISCLAIMER
|
|
||||||
///
|
|
||||||
/// Copyright 2019 ArangoDB GmbH, Cologne, Germany
|
|
||||||
///
|
|
||||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
/// you may not use this file except in compliance with the License.
|
|
||||||
/// You may obtain a copy of the License at
|
|
||||||
///
|
|
||||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
///
|
|
||||||
/// Unless required by applicable law or agreed to in writing, software
|
|
||||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
/// See the License for the specific language governing permissions and
|
|
||||||
/// limitations under the License.
|
|
||||||
///
|
|
||||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
||||||
///
|
|
||||||
/// @author Tobias Gödderz
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef ARANGOD_AQL_UNSORTINGGATHEREXECUTOR_H
|
|
||||||
#define ARANGOD_AQL_UNSORTINGGATHEREXECUTOR_H
|
|
||||||
|
|
||||||
#include "Aql/ExecutionState.h"
|
|
||||||
#include "Aql/ExecutorInfos.h"
|
|
||||||
#include "Aql/MultiDependencySingleRowFetcher.h"
|
|
||||||
#include "Aql/types.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
namespace arangodb::aql {
|
|
||||||
|
|
||||||
class NoStats;
|
|
||||||
class InputAqlItemRow;
|
|
||||||
class OutputAqlItemRow;
|
|
||||||
class IdExecutorInfos;
|
|
||||||
class SharedAqlItemBlockPtr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Produces all rows from its dependencies, which may be more than one,
|
|
||||||
* in some unspecified order. It is, purposefully, strictly synchronous, and
|
|
||||||
* always waits for an answer before requesting the next row(s).
|
|
||||||
*
|
|
||||||
* The actual implementation fetches all available rows from the first
|
|
||||||
* dependency, then from the second, and so forth. But that is not guaranteed.
|
|
||||||
*/
|
|
||||||
class UnsortingGatherExecutor {
|
|
||||||
public:
|
|
||||||
struct Properties {
|
|
||||||
static constexpr bool preservesOrder = false;
|
|
||||||
static constexpr BlockPassthrough allowsBlockPassthrough = BlockPassthrough::Disable;
|
|
||||||
// TODO I think we can set this to true (but needs to implement
|
|
||||||
// hasExpectedNumberOfRows for that)
|
|
||||||
static constexpr bool inputSizeRestrictsOutputSize = false;
|
|
||||||
};
|
|
||||||
using Fetcher = MultiDependencySingleRowFetcher;
|
|
||||||
// TODO I should probably implement custom Infos, we don't need distributeId().
|
|
||||||
using Infos = IdExecutorInfos;
|
|
||||||
using Stats = NoStats;
|
|
||||||
|
|
||||||
UnsortingGatherExecutor(Fetcher& fetcher, Infos&);
|
|
||||||
~UnsortingGatherExecutor();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief produce the next Row of Aql Values.
|
|
||||||
*
|
|
||||||
* @return ExecutionState,
|
|
||||||
* if something was written output.hasValue() == true
|
|
||||||
*/
|
|
||||||
[[nodiscard]] auto produceRows(OutputAqlItemRow& output)
|
|
||||||
-> std::pair<ExecutionState, Stats>;
|
|
||||||
|
|
||||||
[[nodiscard]] auto skipRows(size_t atMost) -> std::tuple<ExecutionState, NoStats, size_t>;
|
|
||||||
|
|
||||||
private:
|
|
||||||
[[nodiscard]] auto numDependencies() const
|
|
||||||
noexcept(noexcept(static_cast<Fetcher*>(nullptr)->numberDependencies())) -> size_t;
|
|
||||||
[[nodiscard]] auto fetcher() const noexcept -> Fetcher const&;
|
|
||||||
[[nodiscard]] auto fetcher() noexcept -> Fetcher&;
|
|
||||||
[[nodiscard]] auto done() const noexcept -> bool;
|
|
||||||
[[nodiscard]] auto currentDependency() const noexcept -> size_t;
|
|
||||||
[[nodiscard]] auto fetchNextRow(size_t atMost)
|
|
||||||
-> std::pair<ExecutionState, InputAqlItemRow>;
|
|
||||||
[[nodiscard]] auto skipNextRows(size_t atMost) -> std::pair<ExecutionState, size_t>;
|
|
||||||
auto advanceDependency() noexcept -> void;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Fetcher& _fetcher;
|
|
||||||
size_t _currentDependency{0};
|
|
||||||
size_t _skipped{0};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace arangodb::aql
|
|
||||||
|
|
||||||
#endif // ARANGOD_AQL_UNSORTINGGATHEREXECUTOR_H
|
|
|
@ -350,8 +350,8 @@ set(LIB_ARANGO_AQL_SOURCES
|
||||||
Aql/TraversalConditionFinder.cpp
|
Aql/TraversalConditionFinder.cpp
|
||||||
Aql/TraversalExecutor.cpp
|
Aql/TraversalExecutor.cpp
|
||||||
Aql/TraversalNode.cpp
|
Aql/TraversalNode.cpp
|
||||||
|
Aql/ParallelUnsortedGatherExecutor.cpp
|
||||||
Aql/UnsortedGatherExecutor.cpp
|
Aql/UnsortedGatherExecutor.cpp
|
||||||
Aql/UnsortingGatherExecutor.cpp
|
|
||||||
Aql/UpdateReplaceModifier.cpp
|
Aql/UpdateReplaceModifier.cpp
|
||||||
Aql/UpsertModifier.cpp
|
Aql/UpsertModifier.cpp
|
||||||
Aql/V8Executor.cpp
|
Aql/V8Executor.cpp
|
||||||
|
@ -1008,7 +1008,7 @@ foreach(TARGET
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(${TARGET} PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
target_compile_options(${TARGET} PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||||
else ()
|
else ()
|
||||||
target_compile_options(${TARGET} PRIVATE -Werror)
|
target_compile_options(${TARGET} PRIVATE -Werror -Wno-error=deprecated-declarations)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
|
@ -80,9 +80,9 @@ endif ()
|
||||||
|
|
||||||
if (USE_FAIL_ON_WARNINGS)
|
if (USE_FAIL_ON_WARNINGS)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(arangobench PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
target_compile_options(arangobench PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||||
else ()
|
else ()
|
||||||
target_compile_options(arangobench PRIVATE -Werror)
|
target_compile_options(arangobench PRIVATE -Werror -Wno-error=deprecated-declarations)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
@ -139,9 +139,9 @@ endif ()
|
||||||
|
|
||||||
if (USE_FAIL_ON_WARNINGS)
|
if (USE_FAIL_ON_WARNINGS)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(arangobackup PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
target_compile_options(arangobackup PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||||
else ()
|
else ()
|
||||||
target_compile_options(arangobackup PRIVATE -Werror)
|
target_compile_options(arangobackup PRIVATE -Werror -Wno-error=deprecated-declarations)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
@ -198,9 +198,9 @@ endif ()
|
||||||
|
|
||||||
if (USE_FAIL_ON_WARNINGS)
|
if (USE_FAIL_ON_WARNINGS)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(arangodump PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
target_compile_options(arangodump PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||||
else ()
|
else ()
|
||||||
target_compile_options(arangodump PRIVATE -Werror)
|
target_compile_options(arangodump PRIVATE -Werror -Wno-error=deprecated-declarations)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
@ -254,9 +254,9 @@ endif ()
|
||||||
|
|
||||||
if (USE_FAIL_ON_WARNINGS)
|
if (USE_FAIL_ON_WARNINGS)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(arangoexport PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
target_compile_options(arangoexport PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||||
else ()
|
else ()
|
||||||
target_compile_options(arangoexport PRIVATE -Werror)
|
target_compile_options(arangoexport PRIVATE -Werror -Wno-error=deprecated-declarations)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
@ -322,9 +322,9 @@ install_command_alias(arangoimport
|
||||||
|
|
||||||
if (USE_FAIL_ON_WARNINGS)
|
if (USE_FAIL_ON_WARNINGS)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(arangoimport PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
target_compile_options(arangoimport PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||||
else ()
|
else ()
|
||||||
target_compile_options(arangoimport PRIVATE -Werror)
|
target_compile_options(arangoimport PRIVATE -Werror -Wno-error=deprecated-declarations)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
@ -379,9 +379,9 @@ endif ()
|
||||||
|
|
||||||
if (USE_FAIL_ON_WARNINGS)
|
if (USE_FAIL_ON_WARNINGS)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(arangorestore PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
target_compile_options(arangorestore PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||||
else ()
|
else ()
|
||||||
target_compile_options(arangorestore PRIVATE -Werror)
|
target_compile_options(arangorestore PRIVATE -Werror -Wno-error=deprecated-declarations)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
@ -444,9 +444,9 @@ endif ()
|
||||||
|
|
||||||
if (USE_FAIL_ON_WARNINGS)
|
if (USE_FAIL_ON_WARNINGS)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(arangosh PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
target_compile_options(arangosh PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||||
else ()
|
else ()
|
||||||
target_compile_options(arangosh PRIVATE -Werror)
|
target_compile_options(arangosh PRIVATE -Werror -Wno-error=deprecated-declarations)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
@ -500,9 +500,9 @@ endif ()
|
||||||
|
|
||||||
if (USE_FAIL_ON_WARNINGS)
|
if (USE_FAIL_ON_WARNINGS)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(arangovpack PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
target_compile_options(arangovpack PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||||
else ()
|
else ()
|
||||||
target_compile_options(arangovpack PRIVATE -Werror)
|
target_compile_options(arangovpack PRIVATE -Werror -Wno-error=deprecated-declarations)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
|
@ -309,11 +309,11 @@ endif()
|
||||||
if (USE_FAIL_ON_WARNINGS)
|
if (USE_FAIL_ON_WARNINGS)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(arango_v8 PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
target_compile_options(arango_v8 PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||||
target_compile_options(arango_geo PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
target_compile_options(arango_geo PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS96)
|
||||||
target_compile_options(arango PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
target_compile_options(arango PRIVATE /WX /D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||||
else ()
|
else ()
|
||||||
target_compile_options(arango_v8 PRIVATE -Werror)
|
target_compile_options(arango_v8 PRIVATE -Werror -Wno-error=deprecated-declarations)
|
||||||
target_compile_options(arango_geo PRIVATE -Werror)
|
target_compile_options(arango_geo PRIVATE -Werror -Wno-error=deprecated-declarations)
|
||||||
target_compile_options(arango PRIVATE -Werror)
|
target_compile_options(arango PRIVATE -Werror -Wno-error=deprecated-declarations)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
|
@ -26,9 +26,7 @@
|
||||||
|
|
||||||
#include <velocypack/Options.h>
|
#include <velocypack/Options.h>
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb::tests::aql {
|
||||||
namespace tests {
|
|
||||||
namespace aql {
|
|
||||||
|
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
|
@ -216,9 +214,7 @@ size_t MultiDependencyProxyMock<passBlocksThrough>::numFetchBlockCalls() const {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aql
|
} // namespace arangodb::tests::aql
|
||||||
} // namespace tests
|
|
||||||
} // namespace arangodb
|
|
||||||
|
|
||||||
template class ::arangodb::tests::aql::DependencyProxyMock<::arangodb::aql::BlockPassthrough::Enable>;
|
template class ::arangodb::tests::aql::DependencyProxyMock<::arangodb::aql::BlockPassthrough::Enable>;
|
||||||
template class ::arangodb::tests::aql::DependencyProxyMock<::arangodb::aql::BlockPassthrough::Disable>;
|
template class ::arangodb::tests::aql::DependencyProxyMock<::arangodb::aql::BlockPassthrough::Disable>;
|
||||||
|
|
|
@ -154,7 +154,7 @@ TEST_F(ExecutionBlockImplTest,
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ExecutionBlockImplTest,
|
TEST_F(ExecutionBlockImplTest,
|
||||||
there_is_a_block_in_the_upstream_with_now_rows_inside_the_executor_waits_using_skipsome) {
|
there_is_a_block_in_the_upstream_with_no_rows_inside_the_executor_waits_using_skipsome) {
|
||||||
std::deque<SharedAqlItemBlockPtr> blockDeque;
|
std::deque<SharedAqlItemBlockPtr> blockDeque;
|
||||||
SharedAqlItemBlockPtr block = buildBlock<1>(itemBlockManager, {{42}});
|
SharedAqlItemBlockPtr block = buildBlock<1>(itemBlockManager, {{42}});
|
||||||
blockDeque.push_back(std::move(block));
|
blockDeque.push_back(std::move(block));
|
||||||
|
|
|
@ -32,15 +32,12 @@
|
||||||
#include "Aql/ResourceUsage.h"
|
#include "Aql/ResourceUsage.h"
|
||||||
#include "Aql/Stats.h"
|
#include "Aql/Stats.h"
|
||||||
|
|
||||||
#include <velocypack/Builder.h>
|
|
||||||
#include <velocypack/velocypack-aliases.h>
|
#include <velocypack/velocypack-aliases.h>
|
||||||
|
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb::tests::aql {
|
||||||
namespace tests {
|
|
||||||
namespace aql {
|
|
||||||
|
|
||||||
class IdExecutorTest : public ::testing::Test {
|
class IdExecutorTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
|
@ -66,7 +63,7 @@ class IdExecutorTest : public ::testing::Test {
|
||||||
|
|
||||||
TEST_F(IdExecutorTest, there_are_no_rows_upstream) {
|
TEST_F(IdExecutorTest, there_are_no_rows_upstream) {
|
||||||
ConstFetcherHelper fetcher(itemBlockManager, nullptr);
|
ConstFetcherHelper fetcher(itemBlockManager, nullptr);
|
||||||
IdExecutor<::arangodb::aql::BlockPassthrough::Enable, ConstFetcher> testee(fetcher, infos);
|
IdExecutor<ConstFetcher> testee(fetcher, infos);
|
||||||
NoStats stats{};
|
NoStats stats{};
|
||||||
|
|
||||||
std::tie(state, stats) = testee.produceRows(row);
|
std::tie(state, stats) = testee.produceRows(row);
|
||||||
|
@ -77,7 +74,7 @@ TEST_F(IdExecutorTest, there_are_no_rows_upstream) {
|
||||||
TEST_F(IdExecutorTest, there_are_rows_in_the_upstream) {
|
TEST_F(IdExecutorTest, there_are_rows_in_the_upstream) {
|
||||||
auto input = VPackParser::fromJson("[ [true], [false], [true] ]");
|
auto input = VPackParser::fromJson("[ [true], [false], [true] ]");
|
||||||
ConstFetcherHelper fetcher(itemBlockManager, input->buffer());
|
ConstFetcherHelper fetcher(itemBlockManager, input->buffer());
|
||||||
IdExecutor<::arangodb::aql::BlockPassthrough::Enable, ConstFetcher> testee(fetcher, infos);
|
IdExecutor<ConstFetcher> testee(fetcher, infos);
|
||||||
NoStats stats{};
|
NoStats stats{};
|
||||||
|
|
||||||
// This block consumes all rows at once.
|
// This block consumes all rows at once.
|
||||||
|
@ -98,6 +95,4 @@ TEST_F(IdExecutorTest, there_are_rows_in_the_upstream) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aql
|
|
||||||
} // namespace tests
|
|
||||||
} // namespace arangodb
|
} // namespace arangodb
|
||||||
|
|
|
@ -50,9 +50,7 @@
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb::tests::aql {
|
||||||
namespace tests {
|
|
||||||
namespace aql {
|
|
||||||
|
|
||||||
class SortExecutorTest : public ::testing::Test {
|
class SortExecutorTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
|
@ -198,6 +196,4 @@ TEST_F(SortExecutorTest, rows_upstream_we_are_waiting_for_list_of_numbers) {
|
||||||
ASSERT_EQ(number, 5);
|
ASSERT_EQ(number, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aql
|
} // namespace arangodb::tests::aql
|
||||||
} // namespace tests
|
|
||||||
} // namespace arangodb
|
|
||||||
|
|
|
@ -25,8 +25,6 @@
|
||||||
#include "Aql/AqlItemBlock.h"
|
#include "Aql/AqlItemBlock.h"
|
||||||
#include "Aql/ExecutionEngine.h"
|
#include "Aql/ExecutionEngine.h"
|
||||||
#include "Aql/ExecutionState.h"
|
#include "Aql/ExecutionState.h"
|
||||||
#include "Aql/ExecutionStats.h"
|
|
||||||
#include "Aql/ExecutorInfos.h"
|
|
||||||
#include "Aql/QueryOptions.h"
|
#include "Aql/QueryOptions.h"
|
||||||
|
|
||||||
#include <velocypack/velocypack-aliases.h>
|
#include <velocypack/velocypack-aliases.h>
|
||||||
|
@ -92,24 +90,20 @@ std::pair<arangodb::aql::ExecutionState, size_t> WaitingExecutionBlockMock::skip
|
||||||
traceSkipSomeBegin(atMost);
|
traceSkipSomeBegin(atMost);
|
||||||
if (!_hasWaited) {
|
if (!_hasWaited) {
|
||||||
_hasWaited = true;
|
_hasWaited = true;
|
||||||
traceSkipSomeEnd(ExecutionState::WAITING, 0);
|
return traceSkipSomeEnd(ExecutionState::WAITING, 0);
|
||||||
return {ExecutionState::WAITING, 0};
|
|
||||||
}
|
}
|
||||||
_hasWaited = false;
|
_hasWaited = false;
|
||||||
|
|
||||||
if (_data.empty()) {
|
if (_data.empty()) {
|
||||||
traceSkipSomeEnd(ExecutionState::DONE, 0);
|
return traceSkipSomeEnd(ExecutionState::DONE, 0);
|
||||||
return {ExecutionState::DONE, 0};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t skipped = _data.front()->size();
|
size_t skipped = _data.front()->size();
|
||||||
_data.pop_front();
|
_data.pop_front();
|
||||||
|
|
||||||
if (_data.empty()) {
|
if (_data.empty()) {
|
||||||
traceSkipSomeEnd(ExecutionState::DONE, skipped);
|
return traceSkipSomeEnd(ExecutionState::DONE, skipped);
|
||||||
return {ExecutionState::DONE, skipped};
|
|
||||||
} else {
|
} else {
|
||||||
traceSkipSomeEnd(ExecutionState::HASMORE, skipped);
|
return traceSkipSomeEnd(ExecutionState::HASMORE, skipped);
|
||||||
return {ExecutionState::HASMORE, skipped};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -281,7 +281,7 @@ endif()
|
||||||
|
|
||||||
if (DARWIN AND FAIL_ON_WARNINGS)
|
if (DARWIN AND FAIL_ON_WARNINGS)
|
||||||
# Missing Braces is broken in older CLangs - disable them here.
|
# Missing Braces is broken in older CLangs - disable them here.
|
||||||
target_compile_options(arangodbtests PRIVATE -Werror -Wno-missing-braces)
|
target_compile_options(arangodbtests PRIVATE -Werror -Wno-error=deprecated-declarations -Wno-missing-braces)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# add these includes as system includes because otherwise
|
# add these includes as system includes because otherwise
|
||||||
|
|
Loading…
Reference in New Issue