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

Skip to content

Feature/aql subquery execution block impl execute implementation bypass skip #11203

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 serv 10000 ice 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 all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
81b6699
Fixed range-handling for Modification Executors
mchacki Feb 29, 2020
01025a7
DataRange handling in ModificationExecutor
mchacki Feb 29, 2020
fe53317
Honor batch-size defined by UpstreamExecutor
mchacki Feb 29, 2020
4bae2e4
Fixed compile issue
mchacki Feb 29, 2020
8a6d636
More fixes in modification
mchacki Feb 29, 2020
9cc084b
Remvoed log devel
mchacki Feb 29, 2020
5c4e05e
Fixed profiler Test. for NoResults node we cahnge the behaviour
mchacki Feb 29, 2020
e25a5ca
Activated getSome failure tests in ExecuteRestHandler
mchacki Feb 29, 2020
08709e9
Fixed skipping in Index
mchacki Feb 29, 2020
e7b2b00
Let the MultiDependencySingleROwFetcher return the correct states.
mchacki Feb 29, 2020
368127b
Fixed non-maintainer compilation
mchacki Feb 29, 2020
6eaad9f
Attempt to fix windows compile issue
mchacki Feb 29, 2020
06c3099
Fixed the non-maintainer compile ina different way
mchacki Feb 29, 2020
68d6ebe
Added API in MultiAqlItemBlockInputRange to get Number of dependencies
mchacki Feb 29, 2020
abd617e
Comments
mchacki Feb 29, 2020
d149e39
Savepoint commit, does not compile, but no harm is done. Will start b…
mchacki Feb 29, 2020
52dcde5
Another savepoint commit. does not compile, yet.
mchacki Feb 29, 2020
5ae6cac
First draft of new Style SortingGather not yet implemented: Paralleli…
mchacki Feb 29, 2020
8fb35bb
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Feb 29, 2020
d46e51c
Allow waiting within old-style subquery
mchacki Feb 29, 2020
94431f1
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Feb 29, 2020
1e5947a
Fixed invalid skipRwos in unsorted gather
mchacki Feb 29, 2020
b7aaa92
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Mar 1, 2020
56c41b1
First draft of ParallelUnsortedGatherExecutor
mchacki Mar 1, 2020
474bf92
Removed unused local variables
mchacki Mar 1, 2020
854082d
Added some Assertions in MultiAqlItemBlockInputRange
mchacki Mar 1, 2020
692c3b7
Initialize dependdencies of MultiDependencyFetcher
mchacki Mar 1, 2020
d525917
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Mar 1, 2020
03a03da
Fixed skipRows loop in UnsortingGatherNode
mchacki Mar 1, 2020
01bca14
Added an implementation for a SkipResult, in order to simplify exchan…
mchacki Mar 1, 2020
0a44131
Moved production API -> SkipResult
mchacki Mar 1, 2020
250fab7
Made tests compile with new SkipResult
mchacki Mar 1, 2020
bd53fa8
Added a test using skip and limit on subqueries
mchacki Mar 1, 2020
f72f45a
Prepared to use subqueries in SkipResult
mchacki Mar 1, 2020
9224b4c
Let subqueries modify the SkipResult subquery stack
mchacki Mar 2, 2020
fb6b9e1
Fixed return state of GatherNode
mchacki Mar 2, 2020
57ce96b
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Mar 2, 2020
6be3180
Activate all spliced subquery tests \o/
mchacki Mar 2, 2020
563821c
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Mar 2, 2020
6e8855b
Let SubqueryEnd honor the client request
mchacki Mar 2, 2020
c03498e
Added a Maintainer only test for the stack, if it is 36 compatible
mchacki Mar 2, 2020
d766db9
Added first part of side-effect executors. They now send upstream a f…
mchacki Mar 3, 2020
e6a8dcb
Add a fake FASTFORWARD call into a subquery-skipped ModificationExecu…
mchacki Mar 3, 2020
5659bc2
Added helper shadow row function for SideEffect executors
mchacki Mar 3, 2020
e28c231
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Mar 3, 2020
b1c6af5
Let the Modification Executor also produce data, even if no FullCount…
mchacki Mar 4, 2020
ac94ae3
Revert "Let the Modification Executor also produce data, even if no F…
mchacki Mar 4, 2020
7695b10
Revert "Revert "Let the Modification Executor also produce data, even…
mchacki Mar 4, 2020
6bf1343
Implemented proper fastForwarding and skipReporting in ExecutorsWithS…
mchacki Mar 4, 2020
6c743bc
Removed unreachable code, somehow the G++ in our tests tries to comil…
mchacki Mar 4, 2020
970d17f
noexcept -> throw is nono good. Thank you compiler for helping me her…
mchacki Mar 4, 2020
3dba1bc
Implment copy on SkipResult
mchacki Mar 4, 2020
50c452f
Adapted SubqueryStartTest to allow easy testing for Skipping on outer…
mchacki Mar 5, 2020
1874871
Fixed koenig lookup of SkipResult ostream operator
mchacki Mar 5, 2020
62898ce
Removed special case of SubqueryStartExecutor and include it on the h…
mchacki Mar 5, 2020
a4d4017
Sorry needed to make the _operations vector mutual because of 3.6 com…
mchacki Mar 5, 2020
1fe6c3b
Attempt to fix windows compile issue
mchacki Mar 5, 2020
c7e25df
Fixed behvaiour of SubqueryEndExecutor
mchacki Mar 5, 2020
c5581e4
Another windows attempt
mchacki Mar 5, 2020
15a7d6e
Fixed modify test, which would actually iterate over too many documen…
mchacki Mar 5, 2020
c30ac78
Fixed tests that assert on existence of SubqueryNode, now there will …
mchacki Mar 5, 2020
fe1757b
Consider a hardLimitFastForward inside the Callstack like a needToSki…
mchacki Mar 5, 2020
8000
3e4f6c7
Fixed all tests that are related to subqueries, which now need to ass…
mchacki Mar 6, 2020
435e841
Fixed jslint
mchacki Mar 6, 2020
f0bca7c
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Mar 10, 2020
1622f08
Fixed the callstack that has been seperated from the clientCall. In s…
mchacki Mar 10, 2020
aef48b6
Fixed skip result forwarding in Scatter/Gather
mchacki Mar 11, 2020
666fe7d
Fixed assertion if the ConstFetcher gets a block with subquery level …
mchacki Mar 11, 2020
680bce4
Moved merging of SubquerySkips in MultiDependencies into the Fetcher
mchacki Mar 11, 2020
3be7aac
Removed dead code and fixed overproduction of Rows in Subquery Executor
mchacki Mar 11, 2020
7b94bb7
Fixed bypassing of skip in SideEffect executors if they trigger waiti…
mchacki Mar 11, 2020
5165f55
Refactored old SubqueryExecutor, there has been some issue with WAITI…
mchacki Mar 11, 2020
9db1c38
Removed debug logging in test
mchacki Mar 12, 2020
4ff1dd8
Fixed empty subquery executor
mchacki Mar 12, 2020
7c79a70
Added an assertion in the AqlResult that no invalid block tries to be…
mchacki Mar 12, 2020
ae61cee
Added clientId into profile tracing. Fixed return of invalid blocks i…
mchacki Mar 12, 2020
ca243b2
Removed invalid AqlExecuteResult from Test
mchacki Mar 12, 2020
48eec3e
Update tests/Aql/SubqueryStartExecutorTest.cpp
mchacki Mar 12, 2020
fe82b4b
Fixed comment, thanks to reviewer
mchacki Mar 12, 2020
54db163
Merge branch 'feature/AqlSubqueryExecutionBlockImplExecuteImplementat…
mchacki Mar 12, 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
11 changes: 6 additions & 5 deletions arangod/Aql/AllRowsFetcher.cpp
9E81
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ std::pair<ExecutionState, AqlItemMatrix const*> AllRowsFetcher::fetchAllRows() {
return {ExecutionState::DONE, nullptr};
}

std::tuple<ExecutionState, size_t, AqlItemBlockInputMatrix> AllRowsFetcher::execute(AqlCallStack& stack) {
std::tuple<ExecutionState, SkipResult, AqlItemBlockInputMatrix> AllRowsFetcher::execute(AqlCallStack& stack) {
if (!stack.isRelevant()) {
auto [state, skipped, block] = _dependencyProxy->execute(stack);
return {state, skipped, AqlItemBlockInputMatrix{block}};
Expand All @@ -79,13 +79,14 @@ std::tuple<ExecutionState, size_t, AqlItemBlockInputMatrix> AllRowsFetcher::exec
TRI_ASSERT(!_aqlItemMatrix->stoppedOnShadowRow());
while (true) {
auto [state, skipped, block] = _dependencyProxy->execute(stack);
TRI_ASSERT(skipped == 0);
TRI_ASSERT(skipped.getSkipCount() == 0);

// we will either build a complete fetched AqlItemBlockInputMatrix or return an empty one
if (state == ExecutionState::WAITING) {
TRI_ASSERT(skipped.nothingSkipped());
TRI_ASSERT(block == nullptr);
// On waiting we have nothing to return
return {state, 0, AqlItemBlockInputMatrix{ExecutorState::HASMORE}};
return {state, SkipResult{}, AqlItemBlockInputMatrix{ExecutorState::HASMORE}};
}
TRI_ASSERT(block != nullptr || state == ExecutionState::DONE);

Expand All @@ -97,10 +98,10 @@ std::tuple<ExecutionState, size_t, AqlItemBlockInputMatrix> AllRowsFetcher::exec
// If we find a ShadowRow or ExecutionState == Done, we're done fetching.
if (_aqlItemMatrix->stoppedOnShadowRow() || state == ExecutionState::DONE) {
if (state == ExecutionState::HASMORE) {
return {state, 0,
return {state, skipped,
AqlItemBlockInputMatrix{ExecutorState::HASMORE, _aqlItemMatrix.get()}};
}
return {state, 0,
return {state, skipped,
AqlItemBlockInputMatrix{ExecutorState::DONE, _aqlItemMatrix.get()}};
}
}
Expand Down
3 changes: 2 additions & 1 deletion arangod/Aql/AllRowsFetcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ enum class ExecutionState;
template <BlockPassthrough>
class DependencyProxy;
class ShadowAqlItemRow;
class SkipResult;

/**
* @brief Interface for all AqlExecutors that do need all
Expand Down Expand Up @@ -110,7 +111,7 @@ class AllRowsFetcher {
* size_t => Amount of documents skipped
* DataRange => Resulting data
*/
std::tuple<ExecutionState, size_t, DataRange> execute(AqlCallStack& stack);
std::tuple<ExecutionState, SkipResult, DataRange> execute(AqlCallStack& stack);

/**
* @brief Fetch one new AqlItemRow from upstream.
Expand Down
108 changes: 65 additions & 43 deletions arangod/Aql/AqlCallStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ AqlCallStack::AqlCallStack(AqlCallStack const& other, AqlCall call)
// We can only use this constructor on relevant levels
// Alothers need to use passThrough constructor
TRI_ASSERT(other._depth == 0);
_operations.push(std::move(call));
_operations.emplace_back(std::move(call));
_compatibilityMode3_6 = other._compatibilityMode3_6;
}

Expand All @@ -51,7 +51,7 @@ AqlCallStack::AqlCallStack(AqlCallStack const& other)
_depth(other._depth),
_compatibilityMode3_6(other._compatibilityMode3_6) {}

AqlCallStack::AqlCallStack(std::stack<AqlCall>&& operations)
AqlCallStack::AqlCallStack(std::vector<AqlCall>&& operations)
: _operations(std::move(operations)) {}

bool AqlCallStack::isRelevant() const { return _depth == 0; }
Expand All @@ -68,40 +68,41 @@ AqlCall AqlCallStack::popCall() {
// to the upwards subquery.
// => Simply put another fetchAll Call on the stack.
// This code is to be removed in the next version after 3.7
_operations.push(AqlCall{});
_operations.emplace_back(AqlCall{});
}
auto call = _operations.top();
_operations.pop();
auto call = _operations.back();
_operations.pop_back();
return call;
}

AqlCall const& AqlCallStack::peek() const {
TRI_ASSERT(isRelevant());
TRI_ASSERT(_compatibilityMode3_6 || !_operations.empty());
if (is36Compatible() && _operations.empty()) {
// This is only for compatibility with 3.6
// there we do not have the stack beeing passed-through
// in AQL, we only have a single call.
// We can only get into this state in the abscence of
// LIMIT => we always do an unlimted softLimit call
// to the upwards subquery.
// => Simply put another fetchAll Call on the stack.
// This code is to be removed in the next version after 3.7
_operations.emplace_back(AqlCall{});
}
TRI_ASSERT(!_operations.empty());
return _operations.top();
return _operations.back();
}

void AqlCallStack::pushCall(AqlCall&& call) {
// TODO is this correct on subqueries?
TRI_ASSERT(isRelevant());
_operations.push(call);
_operations.emplace_back(std::move(call));
}

void AqlCallStack::pushCall(AqlCall const& call) {
// TODO is this correct on subqueries?
TRI_ASSERT(isRelevant());
_operations.push(call);
}

void AqlCallStack::stackUpMissingCalls() {
while (!isRelevant()) {
// For every depth, we add an additional default call.
// The default is to produce unlimited many results,
// using DefaultBatchSize each.
_operations.emplace(AqlCall{});
_depth--;
}
TRI_ASSERT(isRelevant());
_operations.emplace_back(call);
}

void AqlCallStack::pop() {
Expand Down Expand Up @@ -133,8 +134,9 @@ auto AqlCallStack::fromVelocyPack(velocypack::Slice const slice) -> ResultT<AqlC
"When deserializing AqlCallStack: stack is empty");
}

auto stack = std::stack<AqlCall>{};
auto stack = std::vector<AqlCall>{};
auto i = std::size_t{0};
stack.reserve(slice.length());
for (auto const entry : VPackArrayIterator(slice)) {
auto maybeAqlCall = AqlCall::fromVelocyPack(entry);

Expand All @@ -146,7 +148,7 @@ auto AqlCallStack::fromVelocyPack(velocypack::Slice const slice) -> ResultT<AqlC
return Result(TRI_ERROR_TYPE_ERROR, std::move(message));
}

stack.emplace(maybeAqlCall.get());
stack.emplace_back(maybeAqlCall.get());

++i;
}
Expand All @@ -157,19 +159,8 @@ auto AqlCallStack::fromVelocyPack(velocypack::Slice const slice) -> ResultT<AqlC
}

void AqlCallStack::toVelocyPack(velocypack::Builder& builder) const {
auto reverseStack = std::vector<AqlCall>{};
reverseStack.reserve(_operations.size());
{
auto ops = _operations;
while (!ops.empty()) {
reverseStack.emplace_back(ops.top());
ops.pop();
}
}

builder.openArray();
for (auto it = reverseStack.rbegin(); it != reverseStack.rend(); ++it) {
auto const& call = *it;
for (auto const& call : _operations) {
call.toVelocyPack(builder);
}
builder.close();
Expand All @@ -178,19 +169,50 @@ void AqlCallStack::toVelocyPack(velocypack::Builder& builder) const {
auto AqlCallStack::toString() const -> std::string {
auto result = std::string{};
result += "[";
auto ops = _operations;
if (!ops.empty()) {
auto op = ops.top();
ops.pop();
bool isFirst = true;
for (auto const& op : _operations) {
if (!isFirst) {
result += ",";
}
isFirst = false;
result += " ";
result += op.toString();
while (!ops.empty()) {
op = ops.top();
ops.pop();
result += ", ";
result += op.toString();
}
}
result += " ]";
return result;
}

auto AqlCallStack::createEquivalentFetchAllShadowRowsStack() const -> AqlCallStack {
AqlCallStack res{*this};
std::replace_if(
res._operations.begin(), res._operations.end(),
[](auto const&) -> bool { return true; }, AqlCall{});
return res;
}

auto AqlCallStack::needToSkipSubquery() const noexcept -> bool {
return std::any_of(_operations.begin(), _operations.end(), [](AqlCall const& call) -> bool {
return call.needSkipMore() || call.hardLimit == 0;
});
}

auto AqlCallStack::shadowRowDepthToSkip() const -> size_t {
TRI_ASSERT(needToSkipSubquery());
for (size_t i = 0; i < _operations.size(); ++i) {
auto& call = _operations.at(i);
if (call.needSkipMore() || call.hardLimit == 0) {
return _operations.size() - i - 1;
}
}
// unreachable
TRI_ASSERT(false);
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL_AQL);
}

auto AqlCallStack::modifyCallAtDepth(size_t depth) -> AqlCall& {
// depth 0 is back of vector
TRI_ASSERT(_operations.size() > depth);
// Take the depth-most from top of the vector.
auto& call = *(_operations.rbegin() + depth);
return call;
}
60 changes: 49 additions & 11 deletions arangod/Aql/AqlCallStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,6 @@ class AqlCallStack {
// Put another call on top of the stack.
void pushCall(AqlCall const& call);

// fill up all missing calls within this stack s.t. we reach depth == 0
// This needs to be called if an executor requires to be fully executed, even if skipped,
// even if the subquery it is located in is skipped.
// The default operations added here will correspond to produce all Rows, unlimitted.
// e.g. every Modification Executor needs to call this functionality, as modifictions need to be
// performed even if skipped.
void stackUpMissingCalls();

// Pops one subquery level.
// if this isRelevent it pops the top-most call from the stack.
// if this is not revelent it reduces the depth by 1.
Expand All @@ -95,12 +87,58 @@ class AqlCallStack {

void toVelocyPack(velocypack::Builder& builder) const;

auto is36Compatible() const noexcept -> bool { return _compatibilityMode3_6; }

/**
* @brief Create an equivalent call stack that does a full-produce
* of all Subquery levels. This is required for blocks
* that are not allowed to be bpassed.
* The top-most call remains unmodified, as the Executor might
* require some soft limit on it.
*
* @return AqlCallStack a stack of equivalent size, that does not skip
* on any lower subquery.
*/
auto createEquivalentFetchAllShadowRowsStack() const -> AqlCallStack;

/**
* @brief Check if we are in a subquery that is in-fact required to
* be skipped. This is relevant for executors that have created
* an equivalentFetchAllShadowRows stack, in order to decide if
* the need to produce output or if they are skipped.
*
* @return true
* @return false
*/
auto needToSkipSubquery() const noexcept -> bool;

/**
* @brief This is only valid if needToSkipSubquery is true.
* It will resolve to the heighest subquery level
* (outermost) that needs to be skipped.
*
*
* @return size_t Depth of the subquery that asks to be skipped.
*/
auto shadowRowDepthToSkip() const -> size_t;

/**
* @brief Get a reference to the call at the given shadowRowDepth
*
* @param depth ShadowRow depth we need to work on
* @return AqlCall& reference to the call, can be modified.
*/
auto modifyCallAtDepth(size_t depth) -> AqlCall&;

private:
explicit AqlCallStack(std::stack<AqlCall>&& operations);
explicit AqlCallStack(std::vector<AqlCall>&& operations);

private:
// The list of operations, stacked by depth (e.g. bottom element is from main query)
std::stack<AqlCall> _operations;
// The list of operations, stacked by depth (e.g. bottom element is from main
// query) NOTE: This is only mutable on 3.6 compatibility mode. We need to
// inject an additional call in any const operation here just to pretend we
// are not empty. Can be removed after 3.7.
mutable std::vector<AqlCall> _operations;

// The depth of subqueries that have not issued calls into operations,
// as they have been skipped.
Expand Down
Loading
0