8000 Feature/aql subquery execution block impl execute implementation count collect by mchacki · Pull Request #11172 · arangodb/arangodb · GitHub
[go: up one dir, main page]

Skip to content

Feature/aql subquery execution block impl execute implementation count collect #11172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
8b805d7
Move SubqueryStartExecutor to new interface
Jan 29, 2020
8ef2428
Diddle
Jan 31, 2020
2bda19d
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
Jan 31, 2020
147cd0c
Tests pass for SubqueryStartExecutor
Jan 31, 2020
cd694a1
Delete most of the SubqueryEndExecutor tests
Jan 31, 2020
7c5f90a
Skeleton tests
Feb 3, 2020
8f986f0
Junk
Feb 10, 2020
7332eff
Merge branch 'devel' into feature/AqlSubqueryExecutionBlockImplExecut…
Feb 10, 2020
fddf770
Cleanup and make work
Feb 11, 2020
6ddf0f1
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
Feb 11, 2020
1fe1772
Tweak ExecutorTestHelper to test pipelines
Feb 12, 2020
88ba3cd
SubqueryStart/SubqueryEnd
Feb 19, 2020
04de92e
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
Feb 19, 2020
1ae8cbc
Blafummel.
Feb 19, 2020
5881c54
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
Feb 20, 2020
041bd39
Modifications
Feb 20, 2020
de83c7b
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
Feb 20, 2020
187f38a
Fixup tests
Feb 20, 2020
7e33246
Address some comment 8000 s
Feb 20, 2020
1b47090
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
Feb 20, 2020
bf0b03d
Fix.
Feb 20, 2020
aeb3541
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
Feb 20, 2020
f2baeba
Fix tests
Feb 20, 2020
c5c20f8
Various fixes.
Feb 21, 2020
fc32f25
Made the branch compile on Mac
mchacki Feb 21, 2020
4bb25ce
Intermediate commit, does not compile, required for merge
mchacki Feb 21, 2020
dde4c58
Fixed one of the SplicedSubqueryTests
mchacki Feb 21, 2020
81443f6
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Feb 21, 2020
981b1ea
Seperated ShadowRow handling for SubqueryStart/End executors to get a…
mchacki Feb 21, 2020
a5099ef
Allow to use a fullCallStack in ExecutorTestHelper.
mchacki Feb 22, 2020
25e9c51
Added asserts on SubqueryEnd that is not allowed to be called with Sk…
mchacki Feb 22, 2020
24c8d27
Use AqlTestCase in SubqueryStartExecutorTest. Transformed first test …
mchacki Feb 22, 2020
fde3d31
Let ExecutorTestHelper also test for shadowRows
mchacki Feb 22, 2020
bc2ff3a
Adapted SingleInput=>Data+Shadow test to testing Helepr and make it pass
mchacki Feb 22, 2020
cf63e56
Transformed existing SubqueryStart tests to Helper, fixed a test wher…
mchacki Feb 22, 2020
238b905
Fixed Skip in SubqueryStartExecutor
mchacki Feb 23, 2020
6db38d2
Allow the Pipeline to add Consumer and dependency without fiddling wi…
mchacki Feb 23, 2020
8382a37
Added Skip adn ShadowRowForwarding tests to SubqueryStartExecutor
mchacki Feb 23, 2020
16c53a5
Fixed fullCount of SubqueryStart to be called properly.
mchacki Feb 23, 2020
2645708
Renamed isModificationSubquery -> isModificatioNode again
mchacki Feb 24, 2020
6c93d22
Consume more than one subquery en-block
mchacki Feb 24, 2020
5cb901b
Fixed debugReporting in SplicedSubqueryTest. Disabled the skip in sub…
mchacki Feb 24, 2020
c3b4551
Removed AQL debug log level from testing config
mchacki Feb 24, 2020
fca04a4
First version of Subquery Skip bypassing. Including 1 passing test.
mchacki Feb 24, 2020
da8ac78
Added disabled tests for skip, and proposed to do it later
mchacki Feb 24, 2020
43c7252
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Feb 24, 2020
c208d55
Fixed reporting of FILTERED in fullCount of EnumerateCollectionExecutor
mchacki Feb 24, 2020
eb5dc91
Enable calculationExecutor execute interface
mchacki Feb 24, 2020
595d7ee
Fixed compile issues
mchacki Feb 24, 2020
2a132d2
To Velocypack the modification Subquery value
mchacki Feb 24, 2020
c509270
Fixed illegal assert and reactivated failure tests
mchacki Feb 25, 2020
cfbf0d8
Fixed compile issue
mchacki Feb 25, 2020
6a3e41f
Deactivated Calculation again
mchacki Feb 25, 2020
1dacb92
Added a testSuite for countCollectExecutor
mchacki Feb 25, 2020
03b6193
Fixed Subquery Test for CountCollect
mchacki Feb 25, 2020
a7f1e56
Added CountCollectImplementation
mchacki Feb 25, 2020
4d7bc3b
Added Compatibility Mode to AqlCallStack
mchacki Feb 26, 2020
24e68a5
Removed IdExecutor<void> the only feature it has can be moved into ID…
mchacki Feb 26, 2020
1335302
When falling back in BlocksWithClients use compatibility stack
mchacki Feb 26, 2020
5db3328
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Feb 26, 2020
76a1797
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Feb 26, 2020
f3df055
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Feb 27, 2020
6c75a75
Fixed EnumerateCollectionExecutor
mchacki Feb 27, 2020
17f7169
Fixed fullCountBehaviour of EnumerateList. Also removed a unlimited,f…
mchacki Feb 27, 2020
f613876
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Feb 28, 2020
53ccaa8
Fixed endless loop while skipAl in OperationCursor
mchacki Feb 28, 2020
d8d19a5
Fixed View Executor, which sends a no-limit no-offset upstream.
mchacki Feb 28, 2020
572ac97
Fixed forwarding in NoResultsExecutor
mchacki Feb 28, 2020
1bb0a29
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Feb 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10000
Prev Previous commit
Next Next commit
SubqueryStart/SubqueryEnd
  • Loading branch information
Markus Pfeiffer committed Feb 19, 2020
commit 88ba3cd137781eafdd0b66bc59ed8ed8fdbb3f23
49 changes: 31 additions & 18 deletions arangod/Aql/ExecutionBlockImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1145,27 +1145,15 @@ ExecutionBlockImpl<Executor>::executeWithoutTrace(AqlCallStack stack) {
std::tie(_upstreamState, skippedLocal, bypassedRange) = _rowFetcher.execute(stack);
return {_upstreamState, skippedLocal, bypassedRange.getBlock()};
}
AqlCall clientCall = stack.popCall();

// Callstack handling for subqueries
// AqlCall subqueryCall{};
AqlCall clientCall = stack.popCall();
if constexpr (std::is_same_v<Executor, SubqueryStartExecutor>) {
// inspect the top two calls
// clientCall has the "topmost" which is coming from the subquery
// but we need the next one as real clientCall
// AqlCall subqueryCall = clientCall;
// TODO: what happens to the call from the subquery? Currently
// we're just discarding it
// subqueryCall = clientCall;
// (void)subqueryCall;
clientCall = stack.popCall();

// TODO: what do we do with subquery call? We know that the subquery
// needs one row to produce one row; If the subquery has an offset
// we might use that, too?
} else if constexpr (std::is_same_v<Executor, SubqueryEndExecutor>) {
// push original call
auto outsideCall = clientCall;
stack.pushCall(std::move(outsideCall));
clientCall = AqlCall{};

// special hack
// clientCall = AqlCall{clientCall.getOffset(), 0, 0, false};
}

// We can only have returned the following internal states
Expand Down Expand Up @@ -1281,7 +1269,23 @@ ExecutionBlockImpl<Executor>::executeWithoutTrace(AqlCallStack stack) {
TRI_ASSERT(!_lastRange.hasShadowRow());
size_t skippedLocal = 0;
auto callCopy = _upstreamRequest;

stack.pushCall(std::move(callCopy));

// Callstack handling for subqueries
// TODO: If the subquery is modifying we need to do some
// special handling here
if constexpr (std::is_same_v<Executor, SubqueryEndExecutor>) {
if (_executor.isModificationSubquery()) {
} else {
if (_upstreamRequest.getOffset() > 0) {
stack.pushCall(AqlCall{_upstreamRequest.getOffset(), 0, 0, false});
} else {
stack.pushCall(AqlCall{});
}
}
}

std::tie(_upstreamState, skippedLocal, _lastRange) = _rowFetcher.execute(stack);
if (_upstreamState == ExecutionState::WAITING) {
// We need to persist the old call before we return.
Expand All @@ -1305,6 +1309,15 @@ ExecutionBlockImpl<Executor>::executeWithoutTrace(AqlCallStack stack) {
// E.g. LastRow is releveant shadowRow. NextRow is non-relevant shadowRow.
// NOTE: I do not think this is an issue, as the Executor will always say that it cannot do anything with
// an empty input. Only exception might be COLLECT COUNT.

if constexpr (std::is_same_v<Executor, SubqueryStartExecutor>) {
// TODO: make sure ensureOutputBlock can be called here
ensureOutputBlock(std::move(clientCall));
_executor.produceShadowRow(*_outputItemRow);
// produceShadowRow modifies output
clientCall = _outputItemRow->getClientCall();
}

if (_lastRange.hasShadowRow()) {
auto const& [state, shadowRow] = _lastRange.nextShadowRow();
TRI_ASSERT(shadowRow.isInitialized());
Expand Down
3 changes: 3 additions & 0 deletions arangod/Aql/ExecutionState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ std::ostream& operator<<(std::ostream& ostream, ExecutorState state) {
case ExecutorState::HASMORE:
ostream << "HASMORE";
break;
default:
ostream << " WAT WAT WAT";
break;
}
return ostream;
}
Expand Down
137 changes: 73 additions & 64 deletions arangod/Aql/OptimizerRules.cpp

Large diffs are not rendered by default.

28 changes: 23 additions & 5 deletions arangod/Aql/SubqueryEndExecutionNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,18 @@ bool CompareVariables(Variable const* mine, Variable const* yours) {
SubqueryEndNode::SubqueryEndNode(ExecutionPlan* plan, arangodb::velocypack::Slice const& base)
: ExecutionNode(plan, base),
_inVariable(Variable::varFromVPack(plan->getAst(), base, "inVariable", true)),
_outVariable(Variable::varFromVPack(plan->getAst(), base, "outVariable")) {}
_outVariable(Variable::varFromVPack(plan->getAst(), base, "outVariable")),
_isModificationSubquery(base.get("isModificationSubquery").getBoolean()) {}

SubqueryEndNode::SubqueryEndNode(ExecutionPlan* plan, size_t id, Variable const* inVariable,
Variable const* outVariable, bool isModificationSubquery)
: ExecutionNode(plan, id),
_inVariable(inVariable),
_outVariable(outVariable),
_isModificationSubquery(isModificationSubquery) {
// _inVariable might be nullptr
TRI_ASSERT(_outVariable != nullptr);
}

void SubqueryEndNode::toVelocyPackHelper(VPackBuilder& nodes, unsigned flags,
std::unordered_set<ExecutionNode const*>& seen) const {
Expand Down Expand Up @@ -90,8 +101,9 @@ std::unique_ptr<ExecutionBlock> SubqueryEndNode::createBlock(
auto const vpackOptions = trx->transactionContextPtr()->getVPackOptions();
SubqueryEndExecutorInfos infos(inputRegisters, outputRegisters,
getRegisterPlan()->nrRegs[previousNode->getDepth()],
getRegisterPlan()->nrRegs[getDepth()], getRegsToClear(),
calcRegsToKeep(), vpackOptions, inReg, outReg);
getRegisterPlan()->nrRegs[getDepth()],
getRegsToClear(), calcRegsToKeep(), vpackOptions,
inReg, outReg, isModificationSubquery());

return std::make_unique<ExecutionBlockImpl<SubqueryEndExecutor>>(&engine, this,
std::move(infos));
Expand All @@ -108,7 +120,8 @@ ExecutionNode* SubqueryEndNode::clone(ExecutionPlan* plan, bool withDependencies
inVariable = plan->getAst()->variables()->createVariable(inVariable);
}
}
auto c = std::make_unique<SubqueryEndNode>(plan, _id, inVariable, outVariable);
auto c = std::make_unique<SubqueryEndNode>(plan, _id, inVariable, outVariable,
isModificationSubquery());

return cloneHelper(std::move(c), withDependencies, withProperties);
}
Expand All @@ -134,7 +147,8 @@ bool SubqueryEndNode::isEqualTo(ExecutionNode const& other) const {
SubqueryEndNode const& p = dynamic_cast<SubqueryEndNode const&>(other);
TRI_ASSERT(p._outVariable != nullptr);
if (!CompareVariables(_outVariable, p._outVariable) ||
!CompareVariables(_inVariable, p._inVariable)) {
!CompareVariables(_inVariable, p._inVariable) ||
_isModificationSubquery != p._isModificationSubquery) {
// One of the variables does not match
return false;
}
Expand All @@ -144,3 +158,7 @@ bool SubqueryEndNode::isEqualTo(ExecutionNode const& other) const {
return false;
}
}

bool SubqueryEndNode::isModificationSubquery() const {
return _isModificationSubquery;
}
9 changes: 3 additions & 6 deletions arangod/Aql/SubqueryEndExecutionNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,7 @@ class SubqueryEndNode : public ExecutionNode {
SubqueryEndNode(ExecutionPlan*, arangodb::velocypack::Slice const& base);

SubqueryEndNode(ExecutionPlan* plan, size_t id, Variable const* inVariable,
Variable const* outVariable)
: ExecutionNode(plan, id), _inVariable(inVariable), _outVariable(outVariable) {
// _inVariable might be nullptr
TRI_ASSERT(_outVariable != nullptr);
}
Variable const* outVariable, bool isModificationSubquery);

CostEstimate estimateCost() const override final;

Expand Down Expand Up @@ -74,11 +70,12 @@ class SubqueryEndNode : public ExecutionNode {
}

void replaceOutVariable(Variable const* var);
bool isModificationSubquery() const;

private:
Variable const* _inVariable;

Variable const* _outVariable;
bool _isModificationSubquery;
};

} // namespace aql
Expand Down
30 changes: 17 additions & 13 deletions arangod/Aql/SubqueryEndExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
#include <memory>
#include <utility>

#include "Logger/LogMacros.h"

using namespace arangodb;
using namespace arangodb::aql;

Expand All @@ -42,14 +44,15 @@ SubqueryEndExecutorInfos::SubqueryEndExecutorInfos(
std::shared_ptr<std::unordered_set<RegisterId>> writeableOutputRegisters,
RegisterId nrInputRegisters, RegisterId nrOutputRegisters,
std::unordered_set<RegisterId> const& registersToClear,
std::unordered_set<RegisterId> registersToKeep,
velocypack::Options const* const options, RegisterId inReg, RegisterId outReg)
std::unordered_set<RegisterId> registersToKeep, velocypack::Options const* const options,
RegisterId inReg, RegisterId outReg, bool isModificationSubquery)
: ExecutorInfos(std::move(readableInputRegisters),
std::move(writeableOutputRegisters), nrInputRegisters,
nrOutputRegisters, registersToClear, std::move(registersToKeep)),
_vpackOptions(options),
_outReg(outReg),
_inReg(inReg) {}
_inReg(inReg),
_isModificationSubquery(isModificationSubquery) {}

SubqueryEndExecutorInfos::~SubqueryEndExecutorInfos() = default;

Expand All @@ -69,6 +72,10 @@ RegisterId SubqueryEndExecutorInfos::getInputRegister() const noexcept {
return _inReg;
}

bool SubqueryEndExecutorInfos::isModificationSubquery() const noexcept {
return _isModificationSubquery;
}

SubqueryEndExecutor::SubqueryEndExecutor(Fetcher& fetcher, SubqueryEndExecutorInfos& infos)
: _fetcher(fetcher), _infos(infos), _accumulator(_infos.vpackOptions()) {}

Expand All @@ -80,7 +87,7 @@ std::pair<ExecutionState, NoStats> SubqueryEndExecutor::produceRows(OutputAqlIte

auto SubqueryEndExecutor::produceRows(AqlItemBlockInputRange& input, OutputAqlItemRow& output)
-> std::tuple<ExecutorState, Stats, AqlCall> {
ExecutorState state;
ExecutorState state{ExecutorState::HASMORE};
InputAqlItemRow inputRow = InputAqlItemRow{CreateInvalidInputRowHint()};

while (input.hasDataRow()) {
Expand All @@ -94,7 +101,7 @@ auto SubqueryEndExecutor::produceRows(AqlItemBlockInputRange& input, OutputAqlIt
_accumulator.addValue(inputRow.getValue(_infos.getInputRegister()));
}
}
return {state, NoStats{}, AqlCall{}};
return {input.upstreamState(), NoStats{}, AqlCall{}};
}

auto SubqueryEndExecutor::skipRowsRange(AqlItemBlockInputRange& input, AqlCall& call)
Expand All @@ -105,18 +112,11 @@ auto SubqueryEndExecutor::skipRowsRange(AqlItemBlockInputRange& input, AqlCall&
while (input.hasDataRow()) {
std::tie(state, inputRow) = input.nextDataRow();
TRI_ASSERT(inputRow.isInitialized());

// We got a data row, put it into the accumulator,
// if we're getting data through an input register.
// If not, we just "accumulate" an empty output.
// if (_infos.usesInputRegister()) {
// _accumulator.addValue(inputRow.getValue(_infos.getInputRegister()));
// }
}
// This is correct since the SubqueryEndExecutor produces one output out
// of the accumulation of all the (relevant) inputs
call.didSkip(1);
return {state, 1, AqlCall{}};
return {input.upstreamState(), 1, AqlCall{}};
}

auto SubqueryEndExecutor::stealValue(AqlValue& result) -> AqlValueGuard {
Expand All @@ -125,6 +125,10 @@ auto SubqueryEndExecutor::stealValue(AqlValue& result) -> AqlValueGuard {
return _accumulator.stealValue(result);
}

auto SubqueryEndExecutor::isModificationSubquery() const noexcept -> bool {
return _infos.isModificationSubquery();
}

void SubqueryEndExecutor::Accumulator::reset() {
_buffer = std::make_unique<arangodb::velocypack::Buffer<uint8_t>>();
_builder = std::make_unique<VPackBuilder>(*_buffer);
Expand Down
5 changes: 4 additions & 1 deletion arangod/Aql/SubqueryEndExecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class SubqueryEndExecutorInfos : public ExecutorInfos {
std::unordered_set<RegisterId> const& registersToClear,
std::unordered_set<RegisterId> registersToKeep,
velocypack::Options const* options, RegisterId inReg,
RegisterId outReg);
RegisterId outReg, bool isModificationSubquery);

SubqueryEndExecutorInfos() = delete;
SubqueryEndExecutorInfos(SubqueryEndExecutorInfos&&) noexcept = default;
Expand All @@ -61,11 +61,13 @@ class SubqueryEndExecutorInfos : public ExecutorInfos {
[[nodiscard]] RegisterId getOutputRegister() const noexcept;
[[nodiscard]] bool usesInputRegister() const noexcept;
[[nodiscard]] RegisterId getInputRegister() const noexcept;
[[nodiscard]] bool isModificationSubquery() const noexcept;

private:
velocypack::Options const* _vpackOptions;
RegisterId const _outReg;
RegisterId const _inReg;
bool const _isModificationSubquery;
};

class SubqueryEndExecutor {
Expand Down Expand Up @@ -98,6 +100,7 @@ class SubqueryEndExecutor {
[[nodiscard]] auto skipRowsRange(AqlItemBlockInputRange& input, AqlCall& call)
-> std::tuple<ExecutorState, size_t, AqlCall>;
[[nodiscard]] auto stealValue(AqlValue& result) -> AqlValueGuard;
[[nodiscard]] auto isModificationSubquery() const noexcept -> bool;

private:
enum class State {
Expand Down
3 changes: 3 additions & 0 deletions arangod/Aql/SubqueryStartExecutionNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,13 @@ class SubqueryStartNode : public ExecutionNode {

bool isEqualTo(ExecutionNode const& other) const override final;

bool isModificationNode();

private:
/// @brief This is only required for Explain output.
/// it has no practical usage other then to print this information during explain.
Variable const* _subqueryOutVariable;
bool _isModificationSubquery;
};

} // namespace aql
Expand Down
Loading
0