mirror of https://gitee.com/bigwinds/arangodb
blind commit of work, as I managed to break my local git repository (#5456)
This commit is contained in:
parent
c31c07ccaa
commit
f55df6786a
|
@ -231,7 +231,6 @@ void AqlItemBlock::shrink(size_t nrItems) {
|
||||||
|
|
||||||
void AqlItemBlock::rescale(size_t nrItems, RegisterId nrRegs) {
|
void AqlItemBlock::rescale(size_t nrItems, RegisterId nrRegs) {
|
||||||
TRI_ASSERT(_valueCount.empty());
|
TRI_ASSERT(_valueCount.empty());
|
||||||
TRI_ASSERT(nrRegs > 0);
|
|
||||||
TRI_ASSERT(nrRegs <= ExecutionNode::MaxRegisterId);
|
TRI_ASSERT(nrRegs <= ExecutionNode::MaxRegisterId);
|
||||||
|
|
||||||
size_t const targetSize = nrItems * nrRegs;
|
size_t const targetSize = nrItems * nrRegs;
|
||||||
|
|
|
@ -28,42 +28,30 @@
|
||||||
#include "VocBase/vocbase.h"
|
#include "VocBase/vocbase.h"
|
||||||
|
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
|
|
||||||
void SingletonBlock::deleteInputVariables() {
|
|
||||||
delete _inputRegisterValues;
|
|
||||||
_inputRegisterValues = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SingletonBlock::buildWhitelist() {
|
SingletonBlock::SingletonBlock(ExecutionEngine* engine, SingletonNode const* ep)
|
||||||
if (!_whitelistBuilt) {
|
: ExecutionBlock(engine, ep) {
|
||||||
auto en = ExecutionNode::castTo<SingletonNode const*>(getPlanNode());
|
auto en = ExecutionNode::castTo<SingletonNode const*>(getPlanNode());
|
||||||
auto const& registerPlan = en->getRegisterPlan()->varInfo;
|
auto const& registerPlan = en->getRegisterPlan()->varInfo;
|
||||||
std::unordered_set<Variable const*> const& varsUsedLater = en->getVarsUsedLater();
|
std::unordered_set<Variable const*> const& varsUsedLater = en->getVarsUsedLater();
|
||||||
|
|
||||||
for (auto const& it : varsUsedLater) {
|
for (auto const& it : varsUsedLater) {
|
||||||
auto it2 = registerPlan.find(it->id);
|
auto it2 = registerPlan.find(it->id);
|
||||||
|
|
||||||
if (it2 != registerPlan.end()) {
|
if (it2 != registerPlan.end()) {
|
||||||
_whitelist.emplace((*it2).second.registerId);
|
_whitelist.emplace((*it2).second.registerId);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_whitelistBuilt = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief initializeCursor, store a copy of the register values coming from
|
/// @brief initializeCursor, store a copy of the register values coming from
|
||||||
/// above
|
/// above
|
||||||
int SingletonBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
int SingletonBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
||||||
DEBUG_BEGIN_BLOCK();
|
DEBUG_BEGIN_BLOCK();
|
||||||
// Create a deep copy of the register values given to us:
|
// Create a deep copy of the register values given to us:
|
||||||
deleteInputVariables();
|
|
||||||
|
|
||||||
if (items != nullptr) {
|
if (items != nullptr) {
|
||||||
// build a whitelist with all the registers that we will copy from above
|
// build a whitelist with all the registers that we will copy from above
|
||||||
buildWhitelist();
|
_inputRegisterValues.reset(items->slice(pos, _whitelist));
|
||||||
deleteInputVariables();
|
|
||||||
TRI_ASSERT(_whitelistBuilt);
|
|
||||||
_inputRegisterValues = items->slice(pos, _whitelist);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_done = false;
|
_done = false;
|
||||||
|
@ -75,11 +63,8 @@ int SingletonBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
||||||
|
|
||||||
/// @brief shutdown the singleton block
|
/// @brief shutdown the singleton block
|
||||||
int SingletonBlock::shutdown(int errorCode) {
|
int SingletonBlock::shutdown(int errorCode) {
|
||||||
int res = ExecutionBlock::shutdown(errorCode);
|
_inputRegisterValues.reset();
|
||||||
|
return ExecutionBlock::shutdown(errorCode);
|
||||||
deleteInputVariables();
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SingletonBlock::getOrSkipSome(size_t atMost, bool skipping,
|
int SingletonBlock::getOrSkipSome(size_t atMost, bool skipping,
|
||||||
|
@ -96,9 +81,6 @@ int SingletonBlock::getOrSkipSome(size_t atMost, bool skipping,
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (_inputRegisterValues != nullptr) {
|
if (_inputRegisterValues != nullptr) {
|
||||||
buildWhitelist();
|
|
||||||
TRI_ASSERT(_whitelistBuilt);
|
|
||||||
|
|
||||||
skipped++;
|
skipped++;
|
||||||
for (RegisterId reg = 0; reg < _inputRegisterValues->getNrRegs();
|
for (RegisterId reg = 0; reg < _inputRegisterValues->getNrRegs();
|
||||||
++reg) {
|
++reg) {
|
||||||
|
|
|
@ -37,15 +37,7 @@ class ExecutionEngine;
|
||||||
|
|
||||||
class SingletonBlock final : public ExecutionBlock {
|
class SingletonBlock final : public ExecutionBlock {
|
||||||
public:
|
public:
|
||||||
SingletonBlock(ExecutionEngine* engine, SingletonNode const* ep)
|
SingletonBlock(ExecutionEngine* engine, SingletonNode const* ep);
|
||||||
: ExecutionBlock(engine, ep), _inputRegisterValues(nullptr), _whitelistBuilt(false) {}
|
|
||||||
|
|
||||||
~SingletonBlock() { deleteInputVariables(); }
|
|
||||||
|
|
||||||
int initialize() override final {
|
|
||||||
deleteInputVariables();
|
|
||||||
return ExecutionBlock::initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief initializeCursor, store a copy of the register values coming from
|
/// @brief initializeCursor, store a copy of the register values coming from
|
||||||
/// above
|
/// above
|
||||||
|
@ -56,19 +48,13 @@ class SingletonBlock final : public ExecutionBlock {
|
||||||
bool hasMore() override final { return !_done; }
|
bool hasMore() override final { return !_done; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void deleteInputVariables();
|
|
||||||
|
|
||||||
void buildWhitelist();
|
|
||||||
|
|
||||||
int getOrSkipSome(size_t atMost, bool skipping,
|
int getOrSkipSome(size_t atMost, bool skipping,
|
||||||
AqlItemBlock*& result, size_t& skipped) override;
|
AqlItemBlock*& result, size_t& skipped) override;
|
||||||
|
|
||||||
/// @brief _inputRegisterValues
|
/// @brief _inputRegisterValues
|
||||||
AqlItemBlock* _inputRegisterValues;
|
std::unique_ptr<AqlItemBlock> _inputRegisterValues;
|
||||||
|
|
||||||
std::unordered_set<RegisterId> _whitelist;
|
std::unordered_set<RegisterId> _whitelist;
|
||||||
|
|
||||||
bool _whitelistBuilt;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FilterBlock final : public ExecutionBlock {
|
class FilterBlock final : public ExecutionBlock {
|
||||||
|
@ -110,13 +96,12 @@ class LimitBlock final : public ExecutionBlock {
|
||||||
_state(0), // start in the beginning
|
_state(0), // start in the beginning
|
||||||
_fullCount(ep->_fullCount) {}
|
_fullCount(ep->_fullCount) {}
|
||||||
|
|
||||||
~LimitBlock() {}
|
|
||||||
|
|
||||||
int initializeCursor(AqlItemBlock* items, size_t pos) override final;
|
int initializeCursor(AqlItemBlock* items, size_t pos) override final;
|
||||||
|
|
||||||
virtual int getOrSkipSome(size_t atMost, bool skipping,
|
int getOrSkipSome(size_t atMost, bool skipping,
|
||||||
AqlItemBlock*& result, size_t& skipped) override;
|
AqlItemBlock*& result, size_t& skipped) override;
|
||||||
|
|
||||||
|
private:
|
||||||
/// @brief _offset
|
/// @brief _offset
|
||||||
size_t _offset;
|
size_t _offset;
|
||||||
|
|
||||||
|
@ -138,8 +123,6 @@ class ReturnBlock final : public ExecutionBlock {
|
||||||
ReturnBlock(ExecutionEngine* engine, ReturnNode const* ep)
|
ReturnBlock(ExecutionEngine* engine, ReturnNode const* ep)
|
||||||
: ExecutionBlock(engine, ep), _returnInheritedResults(false) {}
|
: ExecutionBlock(engine, ep), _returnInheritedResults(false) {}
|
||||||
|
|
||||||
~ReturnBlock() {}
|
|
||||||
|
|
||||||
/// @brief getSome
|
/// @brief getSome
|
||||||
AqlItemBlock* getSome(size_t atMost) override final;
|
AqlItemBlock* getSome(size_t atMost) override final;
|
||||||
|
|
||||||
|
@ -161,8 +144,6 @@ class NoResultsBlock final : public ExecutionBlock {
|
||||||
NoResultsBlock(ExecutionEngine* engine, ExecutionNode const* ep)
|
NoResultsBlock(ExecutionEngine* engine, ExecutionNode const* ep)
|
||||||
: ExecutionBlock(engine, ep) {}
|
: ExecutionBlock(engine, ep) {}
|
||||||
|
|
||||||
~NoResultsBlock() {}
|
|
||||||
|
|
||||||
/// @brief initializeCursor, store a copy of the register values coming from
|
/// @brief initializeCursor, store a copy of the register values coming from
|
||||||
/// above
|
/// above
|
||||||
int initializeCursor(AqlItemBlock* items, size_t pos) override final;
|
int initializeCursor(AqlItemBlock* items, size_t pos) override final;
|
||||||
|
|
|
@ -58,6 +58,7 @@ using StringBuffer = arangodb::basics::StringBuffer;
|
||||||
|
|
||||||
GatherBlock::GatherBlock(ExecutionEngine* engine, GatherNode const* en)
|
GatherBlock::GatherBlock(ExecutionEngine* engine, GatherNode const* en)
|
||||||
: ExecutionBlock(engine, en),
|
: ExecutionBlock(engine, en),
|
||||||
|
_atDep(0),
|
||||||
_sortRegisters(),
|
_sortRegisters(),
|
||||||
_isSimple(en->elements().empty()),
|
_isSimple(en->elements().empty()),
|
||||||
_heap(en->_sortmode == 'h' ? new Heap : nullptr) {
|
_heap(en->_sortmode == 'h' ? new Heap : nullptr) {
|
||||||
|
@ -87,16 +88,6 @@ GatherBlock::~GatherBlock() {
|
||||||
_gatherBlockBuffer.clear();
|
_gatherBlockBuffer.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief initialize
|
|
||||||
int GatherBlock::initialize() {
|
|
||||||
DEBUG_BEGIN_BLOCK();
|
|
||||||
_atDep = 0;
|
|
||||||
return ExecutionBlock::initialize();
|
|
||||||
|
|
||||||
// cppcheck-suppress style
|
|
||||||
DEBUG_END_BLOCK();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief shutdown: need our own method since our _buffer is different
|
/// @brief shutdown: need our own method since our _buffer is different
|
||||||
int GatherBlock::shutdown(int errorCode) {
|
int GatherBlock::shutdown(int errorCode) {
|
||||||
DEBUG_BEGIN_BLOCK();
|
DEBUG_BEGIN_BLOCK();
|
||||||
|
@ -1209,71 +1200,37 @@ RemoteBlock::RemoteBlock(ExecutionEngine* engine, RemoteNode const* en,
|
||||||
!ownName.empty()));
|
!ownName.empty()));
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteBlock::~RemoteBlock() {}
|
|
||||||
|
|
||||||
/// @brief local helper to send a request
|
/// @brief local helper to send a request
|
||||||
std::unique_ptr<ClusterCommResult> RemoteBlock::sendRequest(
|
std::unique_ptr<ClusterCommResult> RemoteBlock::sendRequest(
|
||||||
arangodb::rest::RequestType type, std::string const& urlPart,
|
arangodb::rest::RequestType type, std::string const& urlPart,
|
||||||
std::string const& body) const {
|
std::string const& body) const {
|
||||||
DEBUG_BEGIN_BLOCK();
|
DEBUG_BEGIN_BLOCK();
|
||||||
auto cc = ClusterComm::instance();
|
auto cc = ClusterComm::instance();
|
||||||
if (cc != nullptr) {
|
if (cc == nullptr) {
|
||||||
// nullptr only happens on controlled shutdown
|
// nullptr only happens on controlled shutdown
|
||||||
|
return std::make_unique<ClusterCommResult>();
|
||||||
// Later, we probably want to set these sensibly:
|
|
||||||
ClientTransactionID const clientTransactionId = std::string("AQL");
|
|
||||||
CoordTransactionID const coordTransactionId = TRI_NewTickServer();
|
|
||||||
std::unordered_map<std::string, std::string> headers;
|
|
||||||
if (!_ownName.empty()) {
|
|
||||||
headers.emplace("Shard-Id", _ownName);
|
|
||||||
}
|
|
||||||
|
|
||||||
++_engine->_stats.httpRequests;
|
|
||||||
{
|
|
||||||
JobGuard guard(SchedulerFeature::SCHEDULER);
|
|
||||||
guard.block();
|
|
||||||
|
|
||||||
std::string const url = std::string("/_db/") +
|
|
||||||
arangodb::basics::StringUtils::urlEncode(_engine->getQuery()->trx()->vocbase().name()) +
|
|
||||||
urlPart + _queryId;
|
|
||||||
auto result =
|
|
||||||
cc->syncRequest(clientTransactionId, coordTransactionId, _server, type,
|
|
||||||
std::move(url), body, headers, defaultTimeOut);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::make_unique<ClusterCommResult>();
|
|
||||||
|
|
||||||
// cppcheck-suppress style
|
|
||||||
DEBUG_END_BLOCK();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief initialize
|
|
||||||
int RemoteBlock::initialize() {
|
|
||||||
DEBUG_BEGIN_BLOCK();
|
|
||||||
|
|
||||||
if (!_isResponsibleForInitializeCursor) {
|
|
||||||
// do nothing...
|
|
||||||
return TRI_ERROR_NO_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ClusterCommResult> res =
|
// Later, we probably want to set these sensibly:
|
||||||
sendRequest(rest::RequestType::PUT, "/_api/aql/initialize/", "{}");
|
ClientTransactionID const clientTransactionId = std::string("AQL");
|
||||||
throwExceptionAfterBadSyncRequest(res.get(), false);
|
CoordTransactionID const coordTransactionId = TRI_NewTickServer();
|
||||||
|
std::unordered_map<std::string, std::string> headers;
|
||||||
// If we get here, then res->result is the response which will be
|
if (!_ownName.empty()) {
|
||||||
// a serialized AqlItemBlock:
|
headers.emplace("Shard-Id", _ownName);
|
||||||
StringBuffer const& responseBodyBuf(res->result->getBody());
|
}
|
||||||
|
|
||||||
std::shared_ptr<VPackBuilder> builder =
|
std::string url = std::string("/_db/") +
|
||||||
VPackParser::fromJson(responseBodyBuf.c_str(), responseBodyBuf.length());
|
arangodb::basics::StringUtils::urlEncode(_engine->getQuery()->trx()->vocbase().name()) +
|
||||||
VPackSlice slice = builder->slice();
|
urlPart + _queryId;
|
||||||
|
|
||||||
if (slice.hasKey("code")) {
|
++_engine->_stats.requests;
|
||||||
return slice.get("code").getNumericValue<int>();
|
{
|
||||||
|
JobGuard guard(SchedulerFeature::SCHEDULER);
|
||||||
|
guard.block();
|
||||||
|
|
||||||
|
return cc->syncRequest(clientTransactionId, coordTransactionId, _server, type,
|
||||||
|
std::move(url), body, headers, defaultTimeOut);
|
||||||
}
|
}
|
||||||
return TRI_ERROR_INTERNAL;
|
|
||||||
|
|
||||||
// cppcheck-suppress style
|
// cppcheck-suppress style
|
||||||
DEBUG_END_BLOCK();
|
DEBUG_END_BLOCK();
|
||||||
|
@ -1288,6 +1245,12 @@ int RemoteBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
||||||
// do nothing...
|
// do nothing...
|
||||||
return TRI_ERROR_NO_ERROR;
|
return TRI_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (items == nullptr) {
|
||||||
|
// we simply ignore the initialCursor request, as the remote side
|
||||||
|
// will initialize the cursor lazily
|
||||||
|
return TRI_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
VPackOptions options(VPackOptions::Defaults);
|
VPackOptions options(VPackOptions::Defaults);
|
||||||
options.buildUnindexedArrays = true;
|
options.buildUnindexedArrays = true;
|
||||||
|
@ -1295,21 +1258,15 @@ int RemoteBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
||||||
|
|
||||||
VPackBuilder builder(&options);
|
VPackBuilder builder(&options);
|
||||||
builder.openObject();
|
builder.openObject();
|
||||||
|
|
||||||
if (items == nullptr) {
|
builder.add("exhausted", VPackValue(false));
|
||||||
// first call, items is still a nullptr
|
builder.add("error", VPackValue(false));
|
||||||
builder.add("exhausted", VPackValue(true));
|
builder.add("pos", VPackValue(pos));
|
||||||
builder.add("error", VPackValue(false));
|
builder.add(VPackValue("items"));
|
||||||
} else {
|
builder.openObject();
|
||||||
builder.add("exhausted", VPackValue(false));
|
items->toVelocyPack(_engine->getQuery()->trx(), builder);
|
||||||
builder.add("error", VPackValue(false));
|
builder.close();
|
||||||
builder.add("pos", VPackValue(pos));
|
|
||||||
builder.add(VPackValue("items"));
|
|
||||||
builder.openObject();
|
|
||||||
items->toVelocyPack(_engine->getQuery()->trx(), builder);
|
|
||||||
builder.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.close();
|
builder.close();
|
||||||
|
|
||||||
std::string bodyString(builder.slice().toJson());
|
std::string bodyString(builder.slice().toJson());
|
||||||
|
|
|
@ -63,9 +63,6 @@ class GatherBlock : public ExecutionBlock {
|
||||||
|
|
||||||
~GatherBlock();
|
~GatherBlock();
|
||||||
|
|
||||||
/// @brief initialize
|
|
||||||
int initialize() override;
|
|
||||||
|
|
||||||
/// @brief shutdown: need our own method since our _buffer is different
|
/// @brief shutdown: need our own method since our _buffer is different
|
||||||
int shutdown(int) override final;
|
int shutdown(int) override final;
|
||||||
|
|
||||||
|
@ -203,8 +200,6 @@ class ScatterBlock : public BlockWithClients {
|
||||||
std::vector<std::string> const& shardIds)
|
std::vector<std::string> const& shardIds)
|
||||||
: BlockWithClients(engine, ep, shardIds) {}
|
: BlockWithClients(engine, ep, shardIds) {}
|
||||||
|
|
||||||
~ScatterBlock() {}
|
|
||||||
|
|
||||||
/// @brief initializeCursor
|
/// @brief initializeCursor
|
||||||
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||||
|
|
||||||
|
@ -230,8 +225,6 @@ class DistributeBlock : public BlockWithClients {
|
||||||
std::vector<std::string> const& shardIds,
|
std::vector<std::string> const& shardIds,
|
||||||
Collection const* collection);
|
Collection const* collection);
|
||||||
|
|
||||||
~DistributeBlock() {}
|
|
||||||
|
|
||||||
/// @brief initializeCursor
|
/// @brief initializeCursor
|
||||||
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||||
|
|
||||||
|
@ -297,14 +290,9 @@ class RemoteBlock final : public ExecutionBlock {
|
||||||
std::string const& server, std::string const& ownName,
|
std::string const& server, std::string const& ownName,
|
||||||
std::string const& queryId);
|
std::string const& queryId);
|
||||||
|
|
||||||
~RemoteBlock();
|
|
||||||
|
|
||||||
/// @brief timeout
|
/// @brief timeout
|
||||||
static double const defaultTimeOut;
|
static double const defaultTimeOut;
|
||||||
|
|
||||||
/// @brief initialize
|
|
||||||
int initialize() override final;
|
|
||||||
|
|
||||||
/// @brief initializeCursor, could be called multiple times
|
/// @brief initializeCursor, could be called multiple times
|
||||||
int initializeCursor(AqlItemBlock* items, size_t pos) override final;
|
int initializeCursor(AqlItemBlock* items, size_t pos) override final;
|
||||||
|
|
||||||
|
@ -319,7 +307,7 @@ class RemoteBlock final : public ExecutionBlock {
|
||||||
|
|
||||||
/// @brief hasMore
|
/// @brief hasMore
|
||||||
bool hasMore() override final;
|
bool hasMore() override final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// @brief internal method to send a request
|
/// @brief internal method to send a request
|
||||||
std::unique_ptr<arangodb::ClusterCommResult> sendRequest(
|
std::unique_ptr<arangodb::ClusterCommResult> sendRequest(
|
||||||
|
@ -327,14 +315,14 @@ class RemoteBlock final : public ExecutionBlock {
|
||||||
std::string const& body) const;
|
std::string const& body) const;
|
||||||
|
|
||||||
/// @brief our server, can be like "shard:S1000" or like "server:Claus"
|
/// @brief our server, can be like "shard:S1000" or like "server:Claus"
|
||||||
std::string _server;
|
std::string const _server;
|
||||||
|
|
||||||
/// @brief our own identity, in case of the coordinator this is empty,
|
/// @brief our own identity, in case of the coordinator this is empty,
|
||||||
/// in case of the DBservers, this is the shard ID as a string
|
/// in case of the DBservers, this is the shard ID as a string
|
||||||
std::string _ownName;
|
std::string const _ownName;
|
||||||
|
|
||||||
/// @brief the ID of the query on the server as a string
|
/// @brief the ID of the query on the server as a string
|
||||||
std::string _queryId;
|
std::string const _queryId;
|
||||||
|
|
||||||
/// @brief whether or not this block will forward initialize,
|
/// @brief whether or not this block will forward initialize,
|
||||||
/// initializeCursor or shutDown requests
|
/// initializeCursor or shutDown requests
|
||||||
|
|
|
@ -241,23 +241,10 @@ SortedCollectBlock::SortedCollectBlock(ExecutionEngine* engine,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SortedCollectBlock::~SortedCollectBlock() {}
|
|
||||||
|
|
||||||
/// @brief initialize
|
|
||||||
int SortedCollectBlock::initialize() {
|
|
||||||
int res = ExecutionBlock::initialize();
|
|
||||||
|
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
// reserve space for the current row
|
// reserve space for the current row
|
||||||
_currentGroup.initialize(_groupRegisters.size());
|
_currentGroup.initialize(_groupRegisters.size());
|
||||||
_pos = 0;
|
_pos = 0;
|
||||||
|
|
||||||
return TRI_ERROR_NO_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SortedCollectBlock::initializeCursor(AqlItemBlock* items,
|
int SortedCollectBlock::initializeCursor(AqlItemBlock* items,
|
||||||
|
@ -604,8 +591,6 @@ HashedCollectBlock::HashedCollectBlock(ExecutionEngine* engine,
|
||||||
TRI_ASSERT(!_groupRegisters.empty());
|
TRI_ASSERT(!_groupRegisters.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
HashedCollectBlock::~HashedCollectBlock() {}
|
|
||||||
|
|
||||||
int HashedCollectBlock::getOrSkipSome(size_t atMost,
|
int HashedCollectBlock::getOrSkipSome(size_t atMost,
|
||||||
bool skipping, AqlItemBlock*& result,
|
bool skipping, AqlItemBlock*& result,
|
||||||
size_t& skipped) {
|
size_t& skipped) {
|
||||||
|
@ -874,17 +859,6 @@ DistinctCollectBlock::~DistinctCollectBlock() {
|
||||||
clearValues();
|
clearValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief initialize
|
|
||||||
int DistinctCollectBlock::initialize() {
|
|
||||||
int res = ExecutionBlock::initialize();
|
|
||||||
|
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRI_ERROR_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DistinctCollectBlock::initializeCursor(AqlItemBlock* items,
|
int DistinctCollectBlock::initializeCursor(AqlItemBlock* items,
|
||||||
size_t pos) {
|
size_t pos) {
|
||||||
DEBUG_BEGIN_BLOCK();
|
DEBUG_BEGIN_BLOCK();
|
||||||
|
|
|
@ -85,10 +85,6 @@ class SortedCollectBlock final : public ExecutionBlock {
|
||||||
public:
|
public:
|
||||||
SortedCollectBlock(ExecutionEngine*, CollectNode const*);
|
SortedCollectBlock(ExecutionEngine*, CollectNode const*);
|
||||||
|
|
||||||
~SortedCollectBlock();
|
|
||||||
|
|
||||||
int initialize() override final;
|
|
||||||
|
|
||||||
/// @brief initializeCursor
|
/// @brief initializeCursor
|
||||||
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||||
|
|
||||||
|
@ -132,7 +128,6 @@ class SortedCollectBlock final : public ExecutionBlock {
|
||||||
class HashedCollectBlock : public ExecutionBlock {
|
class HashedCollectBlock : public ExecutionBlock {
|
||||||
public:
|
public:
|
||||||
HashedCollectBlock(ExecutionEngine*, CollectNode const*);
|
HashedCollectBlock(ExecutionEngine*, CollectNode const*);
|
||||||
~HashedCollectBlock();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int getOrSkipSome(size_t atMost, bool skipping,
|
int getOrSkipSome(size_t atMost, bool skipping,
|
||||||
|
@ -157,8 +152,6 @@ class DistinctCollectBlock : public ExecutionBlock {
|
||||||
DistinctCollectBlock(ExecutionEngine*, CollectNode const*);
|
DistinctCollectBlock(ExecutionEngine*, CollectNode const*);
|
||||||
~DistinctCollectBlock();
|
~DistinctCollectBlock();
|
||||||
|
|
||||||
int initialize() override final;
|
|
||||||
|
|
||||||
/// @brief initializeCursor
|
/// @brief initializeCursor
|
||||||
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||||
|
|
||||||
|
|
|
@ -50,10 +50,6 @@ EnumerateCollectionBlock::EnumerateCollectionBlock(
|
||||||
TRI_ASSERT(_cursor->ok());
|
TRI_ASSERT(_cursor->ok());
|
||||||
|
|
||||||
buildCallback();
|
buildCallback();
|
||||||
}
|
|
||||||
|
|
||||||
int EnumerateCollectionBlock::initialize() {
|
|
||||||
DEBUG_BEGIN_BLOCK();
|
|
||||||
|
|
||||||
if (ServerState::instance()->isRunningInCluster() && _collection->isSatellite()) {
|
if (ServerState::instance()->isRunningInCluster() && _collection->isSatellite()) {
|
||||||
auto logicalCollection = _collection->getCollection();
|
auto logicalCollection = _collection->getCollection();
|
||||||
|
@ -90,11 +86,6 @@ int EnumerateCollectionBlock::initialize() {
|
||||||
"collection " + _collection->name + " did not come into sync in time (" + std::to_string(maxWait) +")");
|
"collection " + _collection->name + " did not come into sync in time (" + std::to_string(maxWait) +")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExecutionBlock::initialize();
|
|
||||||
|
|
||||||
// cppcheck-suppress style
|
|
||||||
DEBUG_END_BLOCK();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int EnumerateCollectionBlock::initializeCursor(AqlItemBlock* items,
|
int EnumerateCollectionBlock::initializeCursor(AqlItemBlock* items,
|
||||||
|
|
|
@ -46,11 +46,6 @@ class EnumerateCollectionBlock final : public ExecutionBlock, public DocumentPro
|
||||||
EnumerateCollectionBlock(ExecutionEngine* engine,
|
EnumerateCollectionBlock(ExecutionEngine* engine,
|
||||||
EnumerateCollectionNode const* ep);
|
EnumerateCollectionNode const* ep);
|
||||||
|
|
||||||
~EnumerateCollectionBlock() = default;
|
|
||||||
|
|
||||||
/// @brief initialize, here we fetch all docs from the database
|
|
||||||
int initialize() override final;
|
|
||||||
|
|
||||||
/// @brief initializeCursor
|
/// @brief initializeCursor
|
||||||
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||||
|
|
||||||
|
|
|
@ -87,8 +87,17 @@ bool ExecutionBlock::removeDependency(ExecutionBlock* ep) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief whether or not the query was killed
|
||||||
|
bool ExecutionBlock::isKilled() const { return _engine->getQuery()->killed(); }
|
||||||
|
|
||||||
|
/// @brief whether or not the query was killed
|
||||||
|
void ExecutionBlock::throwIfKilled() {
|
||||||
|
if (isKilled()) {
|
||||||
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_KILLED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ExecutionBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
int ExecutionBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
||||||
DEBUG_BEGIN_BLOCK();
|
|
||||||
for (auto& d : _dependencies) {
|
for (auto& d : _dependencies) {
|
||||||
int res = d->initializeCursor(items, pos);
|
int res = d->initializeCursor(items, pos);
|
||||||
|
|
||||||
|
@ -104,29 +113,6 @@ int ExecutionBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
||||||
|
|
||||||
_done = false;
|
_done = false;
|
||||||
return TRI_ERROR_NO_ERROR;
|
return TRI_ERROR_NO_ERROR;
|
||||||
DEBUG_END_BLOCK();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief whether or not the query was killed
|
|
||||||
bool ExecutionBlock::isKilled() const { return _engine->getQuery()->killed(); }
|
|
||||||
|
|
||||||
/// @brief whether or not the query was killed
|
|
||||||
void ExecutionBlock::throwIfKilled() {
|
|
||||||
if (isKilled()) {
|
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_KILLED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief initialize
|
|
||||||
int ExecutionBlock::initialize() {
|
|
||||||
for (auto it = _dependencies.begin(); it != _dependencies.end(); ++it) {
|
|
||||||
int res = (*it)->initialize();
|
|
||||||
|
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRI_ERROR_NO_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief shutdown, will be called exactly once for the whole query
|
/// @brief shutdown, will be called exactly once for the whole query
|
||||||
|
|
|
@ -102,16 +102,7 @@ class ExecutionBlock {
|
||||||
/// @brief remove a dependency, returns true if the pointer was found and
|
/// @brief remove a dependency, returns true if the pointer was found and
|
||||||
/// removed, please note that this does not delete ep!
|
/// removed, please note that this does not delete ep!
|
||||||
bool removeDependency(ExecutionBlock* ep);
|
bool removeDependency(ExecutionBlock* ep);
|
||||||
|
|
||||||
/// @brief access the pos-th dependency
|
|
||||||
ExecutionBlock* operator[](size_t pos) {
|
|
||||||
if (pos >= _dependencies.size()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _dependencies.at(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Methods for execution
|
/// @brief Methods for execution
|
||||||
/// Lifecycle is:
|
/// Lifecycle is:
|
||||||
/// CONSTRUCTOR
|
/// CONSTRUCTOR
|
||||||
|
@ -123,8 +114,6 @@ class ExecutionBlock {
|
||||||
/// then the ExecutionEngine automatically calls
|
/// then the ExecutionEngine automatically calls
|
||||||
/// shutdown()
|
/// shutdown()
|
||||||
/// DESTRUCTOR
|
/// DESTRUCTOR
|
||||||
/// @brief initialize
|
|
||||||
virtual int initialize();
|
|
||||||
|
|
||||||
/// @brief initializeCursor, could be called multiple times
|
/// @brief initializeCursor, could be called multiple times
|
||||||
virtual int initializeCursor(AqlItemBlock* items, size_t pos);
|
virtual int initializeCursor(AqlItemBlock* items, size_t pos);
|
||||||
|
@ -223,7 +212,7 @@ class ExecutionBlock {
|
||||||
|
|
||||||
/// @brief current working position in the first entry of _buffer
|
/// @brief current working position in the first entry of _buffer
|
||||||
size_t _pos;
|
size_t _pos;
|
||||||
|
|
||||||
/// @brief if this is set, we are done, this is reset to false by execute()
|
/// @brief if this is set, we are done, this is reset to false by execute()
|
||||||
bool _done;
|
bool _done;
|
||||||
|
|
||||||
|
|
|
@ -181,6 +181,7 @@ ExecutionEngine::ExecutionEngine(Query* query)
|
||||||
_root(nullptr),
|
_root(nullptr),
|
||||||
_query(query),
|
_query(query),
|
||||||
_resultRegister(0),
|
_resultRegister(0),
|
||||||
|
_initializeCursorCalled(false),
|
||||||
_wasShutdown(false),
|
_wasShutdown(false),
|
||||||
_previouslyLockedShards(nullptr),
|
_previouslyLockedShards(nullptr),
|
||||||
_lockedShards(nullptr) {
|
_lockedShards(nullptr) {
|
||||||
|
@ -582,7 +583,6 @@ ExecutionEngine* ExecutionEngine::instantiateFromPlan(
|
||||||
engine->_root = root;
|
engine->_root = root;
|
||||||
|
|
||||||
if (plan->isResponsibleForInitialize()) {
|
if (plan->isResponsibleForInitialize()) {
|
||||||
root->initialize();
|
|
||||||
root->initializeCursor(nullptr, 0);
|
root->initializeCursor(nullptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,24 +70,26 @@ class ExecutionEngine {
|
||||||
|
|
||||||
/// @brief initializeCursor, could be called multiple times
|
/// @brief initializeCursor, could be called multiple times
|
||||||
int initializeCursor(AqlItemBlock* items, size_t pos) {
|
int initializeCursor(AqlItemBlock* items, size_t pos) {
|
||||||
|
_initializeCursorCalled = true;
|
||||||
return _root->initializeCursor(items, pos);
|
return _root->initializeCursor(items, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief initialize
|
|
||||||
int initialize() {
|
|
||||||
return _root->initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief shutdown, will be called exactly once for the whole query
|
/// @brief shutdown, will be called exactly once for the whole query
|
||||||
int shutdown(int errorCode);
|
int shutdown(int errorCode);
|
||||||
|
|
||||||
/// @brief getSome
|
/// @brief getSome
|
||||||
AqlItemBlock* getSome(size_t atMost) {
|
AqlItemBlock* getSome(size_t atMost) {
|
||||||
|
if (!_initializeCursorCalled) {
|
||||||
|
initializeCursor(nullptr, 0);
|
||||||
|
}
|
||||||
return _root->getSome(atMost);
|
return _root->getSome(atMost);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief skipSome
|
/// @brief skipSome
|
||||||
size_t skipSome(size_t atMost) {
|
size_t skipSome(size_t atMost) {
|
||||||
|
if (!_initializeCursorCalled) {
|
||||||
|
initializeCursor(nullptr, 0);
|
||||||
|
}
|
||||||
return _root->skipSome(atMost);
|
return _root->skipSome(atMost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,12 +98,18 @@ class ExecutionEngine {
|
||||||
|
|
||||||
/// @brief skip
|
/// @brief skip
|
||||||
bool skip(size_t number, size_t& actuallySkipped) {
|
bool skip(size_t number, size_t& actuallySkipped) {
|
||||||
|
if (!_initializeCursorCalled) {
|
||||||
|
initializeCursor(nullptr, 0);
|
||||||
|
}
|
||||||
return _root->skip(number, actuallySkipped);
|
return _root->skip(number, actuallySkipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief hasMore
|
/// @brief hasMore
|
||||||
inline bool hasMore() const { return _root->hasMore(); }
|
inline bool hasMore() const { return _root->hasMore(); }
|
||||||
|
|
||||||
|
/// @brief whether or not initializeCursor was called
|
||||||
|
bool initializeCursorCalled() const { return _initializeCursorCalled; }
|
||||||
|
|
||||||
/// @brief add a block to the engine
|
/// @brief add a block to the engine
|
||||||
TEST_VIRTUAL void addBlock(ExecutionBlock*);
|
TEST_VIRTUAL void addBlock(ExecutionBlock*);
|
||||||
|
|
||||||
|
@ -148,9 +156,12 @@ class ExecutionEngine {
|
||||||
/// @brief the register the final result of the query is stored in
|
/// @brief the register the final result of the query is stored in
|
||||||
RegisterId _resultRegister;
|
RegisterId _resultRegister;
|
||||||
|
|
||||||
|
/// @brief whether or not initializeCursor was called
|
||||||
|
bool _initializeCursorCalled;
|
||||||
|
|
||||||
/// @brief whether or not shutdown() was executed
|
/// @brief whether or not shutdown() was executed
|
||||||
bool _wasShutdown;
|
bool _wasShutdown;
|
||||||
|
|
||||||
/// @brief _previouslyLockedShards, this is read off at instanciating
|
/// @brief _previouslyLockedShards, this is read off at instanciating
|
||||||
/// time from a thread local variable
|
/// time from a thread local variable
|
||||||
std::unordered_set<std::string>* _previouslyLockedShards;
|
std::unordered_set<std::string>* _previouslyLockedShards;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "ExecutionNode.h"
|
#include "ExecutionNode.h"
|
||||||
|
#include "Aql/AqlItemBlock.h"
|
||||||
#include "Aql/Ast.h"
|
#include "Aql/Ast.h"
|
||||||
#include "Aql/BasicBlocks.h"
|
#include "Aql/BasicBlocks.h"
|
||||||
#include "Aql/CalculationBlock.h"
|
#include "Aql/CalculationBlock.h"
|
||||||
|
|
|
@ -343,7 +343,7 @@ class ExecutionNode {
|
||||||
static constexpr unsigned SERIALIZE_PARENTS = 1;
|
static constexpr unsigned SERIALIZE_PARENTS = 1;
|
||||||
/// include estimate cost (used in the explainer)
|
/// include estimate cost (used in the explainer)
|
||||||
static constexpr unsigned SERIALIZE_ESTIMATES = 1 << 1;
|
static constexpr unsigned SERIALIZE_ESTIMATES = 1 << 1;
|
||||||
/// print all ExecutionNode information required in cluster snippets
|
/// Print all ExecutionNode information required in cluster snippets
|
||||||
static constexpr unsigned SERIALIZE_DETAILS = 1 << 2;
|
static constexpr unsigned SERIALIZE_DETAILS = 1 << 2;
|
||||||
/// include additional function info for explain
|
/// include additional function info for explain
|
||||||
static constexpr unsigned SERIALIZE_FUNCTIONS = 1 << 3;
|
static constexpr unsigned SERIALIZE_FUNCTIONS = 1 << 3;
|
||||||
|
|
|
@ -40,7 +40,7 @@ void ExecutionStats::toVelocyPack(VPackBuilder& builder, bool reportFullCount) c
|
||||||
builder.add("scannedFull", VPackValue(scannedFull));
|
builder.add("scannedFull", VPackValue(scannedFull));
|
||||||
builder.add("scannedIndex", VPackValue(scannedIndex));
|
builder.add("scannedIndex", VPackValue(scannedIndex));
|
||||||
builder.add("filtered", VPackValue(filtered));
|
builder.add("filtered", VPackValue(filtered));
|
||||||
builder.add("httpRequests", VPackValue(httpRequests));
|
builder.add("httpRequests", VPackValue(requests));
|
||||||
if (reportFullCount) {
|
if (reportFullCount) {
|
||||||
// fullCount is optional
|
// fullCount is optional
|
||||||
builder.add("fullCount", VPackValue(fullCount > count ? fullCount : count));
|
builder.add("fullCount", VPackValue(fullCount > count ? fullCount : count));
|
||||||
|
@ -75,7 +75,7 @@ void ExecutionStats::add(ExecutionStats const& summand) {
|
||||||
scannedFull += summand.scannedFull;
|
scannedFull += summand.scannedFull;
|
||||||
scannedIndex += summand.scannedIndex;
|
scannedIndex += summand.scannedIndex;
|
||||||
filtered += summand.filtered;
|
filtered += summand.filtered;
|
||||||
httpRequests += summand.httpRequests;
|
requests += summand.requests;
|
||||||
if (summand.fullCount > 0) {
|
if (summand.fullCount > 0) {
|
||||||
fullCount += summand.fullCount;
|
fullCount += summand.fullCount;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ ExecutionStats::ExecutionStats()
|
||||||
scannedFull(0),
|
scannedFull(0),
|
||||||
scannedIndex(0),
|
scannedIndex(0),
|
||||||
filtered(0),
|
filtered(0),
|
||||||
httpRequests(0),
|
requests(0),
|
||||||
fullCount(0),
|
fullCount(0),
|
||||||
count(0),
|
count(0),
|
||||||
executionTime(0.0) {}
|
executionTime(0.0) {}
|
||||||
|
@ -117,13 +117,9 @@ ExecutionStats::ExecutionStats(VPackSlice const& slice)
|
||||||
filtered = slice.get("filtered").getNumber<int64_t>();
|
filtered = slice.get("filtered").getNumber<int64_t>();
|
||||||
|
|
||||||
if (slice.hasKey("httpRequests")) {
|
if (slice.hasKey("httpRequests")) {
|
||||||
httpRequests = slice.get("httpRequests").getNumber<int64_t>();
|
requests = slice.get("httpRequests").getNumber<int64_t>();
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
if (slice.hasKey("count")) {
|
|
||||||
count = slice.get("count").getNumber<int64_t>();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// note: fullCount is an optional attribute!
|
// note: fullCount is an optional attribute!
|
||||||
if (slice.hasKey("fullCount")) {
|
if (slice.hasKey("fullCount")) {
|
||||||
fullCount = slice.get("fullCount").getNumber<int64_t>();
|
fullCount = slice.get("fullCount").getNumber<int64_t>();
|
||||||
|
|
|
@ -73,7 +73,7 @@ struct ExecutionStats {
|
||||||
scannedFull = 0;
|
scannedFull = 0;
|
||||||
scannedIndex = 0;
|
scannedIndex = 0;
|
||||||
filtered = 0;
|
filtered = 0;
|
||||||
httpRequests = 0;
|
requests = 0;
|
||||||
fullCount = 0;
|
fullCount = 0;
|
||||||
count = 0;
|
count = 0;
|
||||||
executionTime = 0.0;
|
executionTime = 0.0;
|
||||||
|
@ -93,9 +93,9 @@ struct ExecutionStats {
|
||||||
|
|
||||||
/// @brief number of documents filtered away
|
/// @brief number of documents filtered away
|
||||||
int64_t filtered;
|
int64_t filtered;
|
||||||
/// @brief total number of HTTP requests made
|
|
||||||
|
/// @brief total number of requests made
|
||||||
int64_t httpRequests;
|
int64_t requests;
|
||||||
|
|
||||||
/// @brief total number of results, before applying last limit
|
/// @brief total number of results, before applying last limit
|
||||||
int64_t fullCount;
|
int64_t fullCount;
|
||||||
|
|
|
@ -136,6 +136,8 @@ IndexBlock::IndexBlock(ExecutionEngine* engine, IndexNode const* en)
|
||||||
// build the _documentProducer callback for extracting
|
// build the _documentProducer callback for extracting
|
||||||
// documents from the index
|
// documents from the index
|
||||||
buildCallback();
|
buildCallback();
|
||||||
|
|
||||||
|
initializeOnce();
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexBlock::~IndexBlock() { cleanupNonConstExpressions(); }
|
IndexBlock::~IndexBlock() { cleanupNonConstExpressions(); }
|
||||||
|
@ -211,40 +213,11 @@ void IndexBlock::executeExpressions() {
|
||||||
tmp->changeMember(idx, evaluatedNode);
|
tmp->changeMember(idx, evaluatedNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*AstNode* oldOrMember = _condition->getMember(toReplace->orMember);
|
|
||||||
AstNode* orMember = ast->shallowCopyForModify(oldOrMember);
|
|
||||||
TRI_DEFER(FINALIZE_SUBTREE(orMember));
|
|
||||||
newCondition->changeMember(toReplace->orMember, orMember);
|
|
||||||
|
|
||||||
AstNode* oldAndMember = orMember->getMember(toReplace->andMember);
|
|
||||||
AstNode* andMember = ast->shallowCopyForModify(oldAndMember);
|
|
||||||
TRI_DEFER(FINALIZE_SUBTREE(andMember));
|
|
||||||
orMember->changeMember(toReplace->andMember, andMember);
|
|
||||||
|
|
||||||
if (toReplace->funcMember < 0) {
|
|
||||||
andMember->changeMember(toReplace->operatorMember, evaluatedNode);
|
|
||||||
} else {
|
|
||||||
AstNode* oldFuncMember = andMember->getMember(toReplace->funcMember);
|
|
||||||
AstNode* funcMember = ast->shallowCopyForModify(oldFuncMember);
|
|
||||||
TRI_DEFER(FINALIZE_SUBTREE(funcMember));
|
|
||||||
andMember->changeMember(toReplace->operatorMember, funcMember);
|
|
||||||
|
|
||||||
AstNode* oldArrayMember = funcMember->getMember(0);
|
|
||||||
AstNode* arrayMember = ast->shallowCopyForModify(oldArrayMember);
|
|
||||||
TRI_DEFER(FINALIZE_SUBTREE(arrayMember));
|
|
||||||
funcMember->changeMember(0, arrayMember);
|
|
||||||
|
|
||||||
arrayMember->changeMember(toReplace->funcMember, evaluatedNode);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
DEBUG_END_BLOCK();
|
DEBUG_END_BLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
int IndexBlock::initialize() {
|
void IndexBlock::initializeOnce() {
|
||||||
DEBUG_BEGIN_BLOCK();
|
|
||||||
int res = ExecutionBlock::initialize();
|
|
||||||
|
|
||||||
auto en = ExecutionNode::castTo<IndexNode const*>(getPlanNode());
|
auto en = ExecutionNode::castTo<IndexNode const*>(getPlanNode());
|
||||||
auto ast = en->_plan->getAst();
|
auto ast = en->_plan->getAst();
|
||||||
|
|
||||||
|
@ -284,8 +257,8 @@ int IndexBlock::initialize() {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_condition == nullptr) {
|
if (_condition == nullptr) {
|
||||||
// This Node has no condition. Iterate over the complete index.
|
// this node has no condition. Iterate over the complete index.
|
||||||
return res;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto outVariable = en->outVariable();
|
auto outVariable = en->outVariable();
|
||||||
|
@ -371,11 +344,6 @@ int IndexBlock::initialize() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
|
||||||
|
|
||||||
// cppcheck-suppress style
|
|
||||||
DEBUG_END_BLOCK();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// init the ranges for reading, this should be called once per new incoming
|
// init the ranges for reading, this should be called once per new incoming
|
||||||
|
|
|
@ -63,9 +63,6 @@ class IndexBlock final : public ExecutionBlock, public DocumentProducingBlock {
|
||||||
|
|
||||||
~IndexBlock();
|
~IndexBlock();
|
||||||
|
|
||||||
/// @brief initialize, here we fetch all docs from the database
|
|
||||||
int initialize() override;
|
|
||||||
|
|
||||||
/// @brief initializeCursor, here we release our docs from this collection
|
/// @brief initializeCursor, here we release our docs from this collection
|
||||||
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||||
|
|
||||||
|
@ -75,6 +72,8 @@ class IndexBlock final : public ExecutionBlock, public DocumentProducingBlock {
|
||||||
size_t skipSome(size_t atMost) override final;
|
size_t skipSome(size_t atMost) override final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void initializeOnce();
|
||||||
|
|
||||||
/// @brief adds a SORT to a dynamic IN condition
|
/// @brief adds a SORT to a dynamic IN condition
|
||||||
arangodb::aql::AstNode* makeUnique(arangodb::aql::AstNode*) const;
|
arangodb::aql::AstNode* makeUnique(arangodb::aql::AstNode*) const;
|
||||||
|
|
||||||
|
|
|
@ -907,7 +907,7 @@ QueryResult Query::explain() {
|
||||||
try {
|
try {
|
||||||
init();
|
init();
|
||||||
enterState(QueryExecutionState::ValueType::PARSING);
|
enterState(QueryExecutionState::ValueType::PARSING);
|
||||||
|
|
||||||
Parser parser(this);
|
Parser parser(this);
|
||||||
|
|
||||||
parser.parse(true);
|
parser.parse(true);
|
||||||
|
@ -983,8 +983,7 @@ QueryResult Query::explain() {
|
||||||
!_isModificationQuery && _warnings.empty() &&
|
!_isModificationQuery && _warnings.empty() &&
|
||||||
_ast->root()->isCacheable());
|
_ast->root()->isCacheable());
|
||||||
}
|
}
|
||||||
|
|
||||||
// technically no need to commit, as we are only explaining here
|
|
||||||
auto commitResult = _trx->commit();
|
auto commitResult = _trx->commit();
|
||||||
if (commitResult.fail()) {
|
if (commitResult.fail()) {
|
||||||
THROW_ARANGO_EXCEPTION(commitResult);
|
THROW_ARANGO_EXCEPTION(commitResult);
|
||||||
|
|
|
@ -584,12 +584,7 @@ void RestAqlHandler::useQuery(std::string const& operation,
|
||||||
void RestAqlHandler::getInfoQuery(std::string const& operation,
|
void RestAqlHandler::getInfoQuery(std::string const& operation,
|
||||||
std::string const& idString) {
|
std::string const& idString) {
|
||||||
bool found;
|
bool found;
|
||||||
std::string shardId;
|
std::string const& shardId = _request->header("shard-id", found);
|
||||||
std::string const& shardIdCharP = _request->header("shard-id", found);
|
|
||||||
|
|
||||||
if (found && !shardIdCharP.empty()) {
|
|
||||||
shardId = shardIdCharP;
|
|
||||||
}
|
|
||||||
|
|
||||||
Query* query = nullptr;
|
Query* query = nullptr;
|
||||||
if (findQuery(idString, query)) {
|
if (findQuery(idString, query)) {
|
||||||
|
@ -761,11 +756,20 @@ bool RestAqlHandler::findQuery(std::string const& idString, Query*& query) {
|
||||||
void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
|
void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
|
||||||
VPackSlice const querySlice) {
|
VPackSlice const querySlice) {
|
||||||
bool found;
|
bool found;
|
||||||
std::string shardId;
|
std::string const& shardId = _request->header("shard-id", found);
|
||||||
std::string const& shardIdCharP = _request->header("shard-id", found);
|
|
||||||
|
|
||||||
if (found && !shardIdCharP.empty()) {
|
// upon first usage, the "initializeCursor" method must be called
|
||||||
shardId = shardIdCharP;
|
// note: if the operation is "initializeCursor" itself, we do not initialize
|
||||||
|
// the cursor here but let the case for "initializeCursor" process it.
|
||||||
|
// this is because the request may contain additional data
|
||||||
|
if ((operation == "getSome" || operation == "skipSome") &&
|
||||||
|
!query->engine()->initializeCursorCalled()) {
|
||||||
|
int res = query->engine()->initializeCursor(nullptr, 0);
|
||||||
|
if (res != TRI_ERROR_NO_ERROR) {
|
||||||
|
generateError(GeneralResponse::responseCode(res),
|
||||||
|
res, "cannot initialize cursor for AQL query");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VPackBuilder answerBuilder;
|
VPackBuilder answerBuilder;
|
||||||
|
@ -781,19 +785,8 @@ void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
|
||||||
JobGuard guard(SchedulerFeature::SCHEDULER);
|
JobGuard guard(SchedulerFeature::SCHEDULER);
|
||||||
guard.block();
|
guard.block();
|
||||||
|
|
||||||
try {
|
// let exceptions propagate from here
|
||||||
res = query->trx()->lockCollections();
|
res = query->trx()->lockCollections();
|
||||||
} catch (std::exception const& ex) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
|
||||||
TRI_ERROR_HTTP_SERVER_ERROR,
|
|
||||||
std::string("lock lead to an exception: ") + ex.what());
|
|
||||||
return;
|
|
||||||
} catch (...) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
|
||||||
TRI_ERROR_HTTP_SERVER_ERROR,
|
|
||||||
"lock lead to an exception");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
answerBuilder.add(StaticStrings::Error, VPackValue(res != TRI_ERROR_NO_ERROR));
|
answerBuilder.add(StaticStrings::Error, VPackValue(res != TRI_ERROR_NO_ERROR));
|
||||||
|
@ -817,155 +810,62 @@ void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
|
||||||
answerBuilder.add("exhausted", VPackValue(true));
|
answerBuilder.add("exhausted", VPackValue(true));
|
||||||
answerBuilder.add("error", VPackValue(false));
|
answerBuilder.add("error", VPackValue(false));
|
||||||
} else {
|
} else {
|
||||||
try {
|
items->toVelocyPack(query->trx(), answerBuilder);
|
||||||
items->toVelocyPack(query->trx(), answerBuilder);
|
|
||||||
} catch (...) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
|
||||||
TRI_ERROR_HTTP_SERVER_ERROR,
|
|
||||||
"cannot transform AqlItemBlock to VelocyPack");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (operation == "skipSome") {
|
} else if (operation == "skipSome") {
|
||||||
auto atMost = VelocyPackHelper::getNumericValue<size_t>(
|
auto atMost = VelocyPackHelper::getNumericValue<size_t>(
|
||||||
querySlice, "atMost", ExecutionBlock::DefaultBatchSize());
|
querySlice, "atMost", ExecutionBlock::DefaultBatchSize());
|
||||||
size_t skipped;
|
size_t skipped;
|
||||||
try {
|
if (shardId.empty()) {
|
||||||
if (shardId.empty()) {
|
skipped = query->engine()->skipSome(atMost);
|
||||||
skipped = query->engine()->skipSome(atMost);
|
} else {
|
||||||
} else {
|
auto block =
|
||||||
auto block =
|
static_cast<BlockWithClients*>(query->engine()->root());
|
||||||
static_cast<BlockWithClients*>(query->engine()->root());
|
if (block->getPlanNode()->getType() != ExecutionNode::SCATTER &&
|
||||||
if (block->getPlanNode()->getType() != ExecutionNode::SCATTER &&
|
block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) {
|
||||||
block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) {
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
"unexpected node type");
|
||||||
"unexpected node type");
|
|
||||||
}
|
|
||||||
skipped = block->skipSomeForShard(atMost, shardId);
|
|
||||||
}
|
}
|
||||||
} catch (std::exception const& ex) {
|
skipped = block->skipSomeForShard(atMost, shardId);
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
|
||||||
TRI_ERROR_HTTP_SERVER_ERROR,
|
|
||||||
std::string("skipSome lead to an exception: ") + ex.what());
|
|
||||||
return;
|
|
||||||
} catch (...) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
|
||||||
TRI_ERROR_HTTP_SERVER_ERROR,
|
|
||||||
"skipSome lead to an exception");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
answerBuilder.add("skipped", VPackValue(static_cast<double>(skipped)));
|
answerBuilder.add("skipped", VPackValue(skipped));
|
||||||
answerBuilder.add("error", VPackValue(false));
|
answerBuilder.add("error", VPackValue(false));
|
||||||
} else if (operation == "skip") {
|
|
||||||
auto number =
|
|
||||||
VelocyPackHelper::getNumericValue<size_t>(querySlice, "number", 1);
|
|
||||||
try {
|
|
||||||
bool exhausted;
|
|
||||||
if (shardId.empty()) {
|
|
||||||
size_t numActuallySkipped = 0;
|
|
||||||
exhausted = query->engine()->skip(number, numActuallySkipped);
|
|
||||||
} else {
|
|
||||||
auto block =
|
|
||||||
static_cast<BlockWithClients*>(query->engine()->root());
|
|
||||||
if (block->getPlanNode()->getType() != ExecutionNode::SCATTER &&
|
|
||||||
block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) {
|
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
|
||||||
"unexpected node type");
|
|
||||||
}
|
|
||||||
exhausted = block->skipForShard(number, shardId);
|
|
||||||
}
|
|
||||||
answerBuilder.add("exhausted", VPackValue(exhausted));
|
|
||||||
answerBuilder.add("error", VPackValue(false));
|
|
||||||
} catch (std::exception const& ex) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
|
||||||
TRI_ERROR_HTTP_SERVER_ERROR,
|
|
||||||
std::string("skip lead to an exception: ") + ex.what());
|
|
||||||
return;
|
|
||||||
} catch (...) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
|
||||||
TRI_ERROR_HTTP_SERVER_ERROR,
|
|
||||||
"skip lead to an exception");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (operation == "initialize") {
|
} else if (operation == "initialize") {
|
||||||
int res;
|
// this is a no-op now
|
||||||
try {
|
answerBuilder.add(StaticStrings::Error, VPackValue(false));
|
||||||
res = query->engine()->initialize();
|
answerBuilder.add(StaticStrings::Code, VPackValue(TRI_ERROR_NO_ERROR));
|
||||||
} catch (arangodb::basics::Exception const& ex) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR, ex.code(), std::string("initialize lead to an exception: ") + ex.what());
|
|
||||||
return;
|
|
||||||
} catch (std::exception const& ex) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_HTTP_SERVER_ERROR, std::string("initialize lead to an exception: ") + ex.what());
|
|
||||||
return;
|
|
||||||
} catch (...) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
|
||||||
TRI_ERROR_HTTP_SERVER_ERROR,
|
|
||||||
"initialize lead to an exception");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
answerBuilder.add(StaticStrings::Error, VPackValue(res != TRI_ERROR_NO_ERROR));
|
|
||||||
answerBuilder.add(StaticStrings::Code, VPackValue(static_cast<double>(res)));
|
|
||||||
} else if (operation == "initializeCursor") {
|
} else if (operation == "initializeCursor") {
|
||||||
auto pos =
|
auto pos =
|
||||||
VelocyPackHelper::getNumericValue<size_t>(querySlice, "pos", 0);
|
VelocyPackHelper::getNumericValue<size_t>(querySlice, "pos", 0);
|
||||||
std::unique_ptr<AqlItemBlock> items;
|
std::unique_ptr<AqlItemBlock> items;
|
||||||
int res;
|
int res;
|
||||||
try {
|
if (VelocyPackHelper::getBooleanValue(querySlice, "exhausted", true)) {
|
||||||
if (VelocyPackHelper::getBooleanValue(querySlice, "exhausted",
|
res = query->engine()->initializeCursor(nullptr, 0);
|
||||||
true)) {
|
} else {
|
||||||
res = query->engine()->initializeCursor(nullptr, 0);
|
items.reset(new AqlItemBlock(query->resourceMonitor(),
|
||||||
} else {
|
querySlice.get("items")));
|
||||||
items.reset(new AqlItemBlock(query->resourceMonitor(),
|
res = query->engine()->initializeCursor(items.get(), pos);
|
||||||
querySlice.get("items")));
|
|
||||||
res = query->engine()->initializeCursor(items.get(), pos);
|
|
||||||
}
|
|
||||||
} catch (arangodb::basics::Exception const& ex) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR, ex.code(), std::string("initializeCursor lead to an exception: ") + ex.what());
|
|
||||||
return;
|
|
||||||
} catch (std::exception const& ex) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_HTTP_SERVER_ERROR, std::string("initializeCursor lead to an exception: ") + ex.what());
|
|
||||||
return;
|
|
||||||
} catch (...) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
|
||||||
TRI_ERROR_HTTP_SERVER_ERROR,
|
|
||||||
"initializeCursor lead to an exception");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
answerBuilder.add(StaticStrings::Error, VPackValue(res != TRI_ERROR_NO_ERROR));
|
answerBuilder.add(StaticStrings::Error, VPackValue(res != TRI_ERROR_NO_ERROR));
|
||||||
answerBuilder.add(StaticStrings::Code, VPackValue(static_cast<double>(res)));
|
answerBuilder.add(StaticStrings::Code, VPackValue(res));
|
||||||
} else if (operation == "shutdown") {
|
} else if (operation == "shutdown") {
|
||||||
int res = TRI_ERROR_INTERNAL;
|
|
||||||
int errorCode = VelocyPackHelper::getNumericValue<int>(
|
int errorCode = VelocyPackHelper::getNumericValue<int>(
|
||||||
querySlice, "code", TRI_ERROR_INTERNAL);
|
querySlice, "code", TRI_ERROR_INTERNAL);
|
||||||
try {
|
int res = query->engine()->shutdown(errorCode); // pass errorCode to shutdown
|
||||||
res = query->engine()->shutdown(
|
|
||||||
errorCode); // pass errorCode to shutdown
|
|
||||||
|
|
||||||
// return statistics
|
// return statistics
|
||||||
answerBuilder.add(VPackValue("stats"));
|
answerBuilder.add(VPackValue("stats"));
|
||||||
query->getStats(answerBuilder);
|
query->getStats(answerBuilder);
|
||||||
|
|
||||||
// return warnings if present
|
// return warnings if present
|
||||||
query->addWarningsToVelocyPack(answerBuilder);
|
query->addWarningsToVelocyPack(answerBuilder);
|
||||||
|
|
||||||
// return the query to the registry
|
// return the query to the registry
|
||||||
_queryRegistry->close(&_vocbase, _qId);
|
_queryRegistry->close(&_vocbase, _qId);
|
||||||
|
|
||||||
// delete the query from the registry
|
// delete the query from the registry
|
||||||
_queryRegistry->destroy(&_vocbase, _qId, errorCode);
|
_queryRegistry->destroy(&_vocbase, _qId, errorCode);
|
||||||
_qId = 0;
|
_qId = 0;
|
||||||
} catch (arangodb::basics::Exception const& ex) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR, ex.code(), std::string("shutdown lead to an exception: ") + ex.what());
|
|
||||||
return;
|
|
||||||
} catch (std::exception const& ex) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_HTTP_SERVER_ERROR, std::string("shutdown lead to an exception: ") + ex.what());
|
|
||||||
return;
|
|
||||||
} catch (...) {
|
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
|
||||||
TRI_ERROR_HTTP_SERVER_ERROR,
|
|
||||||
"shutdown lead to an exception");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
answerBuilder.add(StaticStrings::Error, VPackValue(res != TRI_ERROR_NO_ERROR));
|
answerBuilder.add(StaticStrings::Error, VPackValue(res != TRI_ERROR_NO_ERROR));
|
||||||
answerBuilder.add(StaticStrings::Code, VPackValue(res));
|
answerBuilder.add(StaticStrings::Code, VPackValue(res));
|
||||||
} else {
|
} else {
|
||||||
|
@ -974,17 +874,13 @@ void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sendResponse(rest::ResponseCode::OK, answerBuilder.slice(),
|
sendResponse(rest::ResponseCode::OK, answerBuilder.slice(), transactionContext.get());
|
||||||
transactionContext.get());
|
|
||||||
} catch (arangodb::basics::Exception const& ex) {
|
} catch (arangodb::basics::Exception const& ex) {
|
||||||
generateError(rest::ResponseCode::BAD, ex.code(), ex.message());
|
generateError(GeneralResponse::responseCode(ex.code()), ex.code(), ex.message());
|
||||||
return;
|
|
||||||
} catch (std::exception const& ex) {
|
} catch (std::exception const& ex) {
|
||||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_FAILED, ex.what());
|
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL, ex.what());
|
||||||
return;
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL, "unknown exception caught in handleUsequery");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -993,7 +889,6 @@ std::shared_ptr<VPackBuilder> RestAqlHandler::parseVelocyPackBody() {
|
||||||
try {
|
try {
|
||||||
std::shared_ptr<VPackBuilder> body = _request->toVelocyPackBuilderPtr();
|
std::shared_ptr<VPackBuilder> body = _request->toVelocyPackBuilderPtr();
|
||||||
if (body == nullptr) {
|
if (body == nullptr) {
|
||||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "cannot parse json object";
|
|
||||||
generateError(rest::ResponseCode::BAD,
|
generateError(rest::ResponseCode::BAD,
|
||||||
TRI_ERROR_HTTP_CORRUPTED_JSON, "cannot parse json object");
|
TRI_ERROR_HTTP_CORRUPTED_JSON, "cannot parse json object");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1009,7 +904,6 @@ std::shared_ptr<VPackBuilder> RestAqlHandler::parseVelocyPackBody() {
|
||||||
}
|
}
|
||||||
return body;
|
return body;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "cannot parse json object";
|
|
||||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_CORRUPTED_JSON,
|
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_CORRUPTED_JSON,
|
||||||
"cannot parse json object");
|
"cannot parse json object");
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,14 +100,7 @@ ShortestPathBlock::ShortestPathBlock(ExecutionEngine* engine,
|
||||||
if (arangodb::ServerState::instance()->isCoordinator()) {
|
if (arangodb::ServerState::instance()->isCoordinator()) {
|
||||||
_engines = ep->engines();
|
_engines = ep->engines();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ShortestPathBlock::~ShortestPathBlock() {
|
|
||||||
}
|
|
||||||
|
|
||||||
int ShortestPathBlock::initialize() {
|
|
||||||
DEBUG_BEGIN_BLOCK();
|
|
||||||
int res = ExecutionBlock::initialize();
|
|
||||||
auto varInfo = getPlanNode()->getRegisterPlan()->varInfo;
|
auto varInfo = getPlanNode()->getRegisterPlan()->varInfo;
|
||||||
|
|
||||||
if (usesVertexOutput()) {
|
if (usesVertexOutput()) {
|
||||||
|
@ -124,11 +117,6 @@ int ShortestPathBlock::initialize() {
|
||||||
TRI_ASSERT(it->second.registerId < ExecutionNode::MaxRegisterId);
|
TRI_ASSERT(it->second.registerId < ExecutionNode::MaxRegisterId);
|
||||||
_edgeReg = it->second.registerId;
|
_edgeReg = it->second.registerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
|
||||||
|
|
||||||
// cppcheck-suppress style
|
|
||||||
DEBUG_END_BLOCK();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ShortestPathBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
int ShortestPathBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
||||||
|
|
|
@ -45,11 +45,6 @@ class ShortestPathBlock : public ExecutionBlock {
|
||||||
public:
|
public:
|
||||||
ShortestPathBlock(ExecutionEngine* engine, ShortestPathNode const* ep);
|
ShortestPathBlock(ExecutionEngine* engine, ShortestPathNode const* ep);
|
||||||
|
|
||||||
~ShortestPathBlock();
|
|
||||||
|
|
||||||
/// @brief initialize, here we fetch all docs from the database
|
|
||||||
int initialize() override;
|
|
||||||
|
|
||||||
/// @brief initializeCursor
|
/// @brief initializeCursor
|
||||||
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||||
|
|
||||||
|
@ -62,11 +57,8 @@ class ShortestPathBlock : public ExecutionBlock {
|
||||||
// will only return less than atMost if there aren't atMost many
|
// will only return less than atMost if there aren't atMost many
|
||||||
// things to skip overall.
|
// things to skip overall.
|
||||||
size_t skipSome(size_t atMost) override final;
|
size_t skipSome(size_t atMost) override final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// SECTION private Functions
|
|
||||||
|
|
||||||
/// @brief Compute the next shortest path
|
/// @brief Compute the next shortest path
|
||||||
bool nextPath(AqlItemBlock const*);
|
bool nextPath(AqlItemBlock const*);
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,9 @@
|
||||||
#include "Aql/ExecutionPlan.h"
|
#include "Aql/ExecutionPlan.h"
|
||||||
#include "Aql/ShortestPathBlock.h"
|
#include "Aql/ShortestPathBlock.h"
|
||||||
#include "Aql/Query.h"
|
#include "Aql/Query.h"
|
||||||
|
#include "Graph/ShortestPathFinder.h"
|
||||||
#include "Graph/ShortestPathOptions.h"
|
#include "Graph/ShortestPathOptions.h"
|
||||||
|
#include "Graph/ShortestPathResult.h"
|
||||||
#include "Indexes/Index.h"
|
#include "Indexes/Index.h"
|
||||||
#include "Utils/CollectionNameResolver.h"
|
#include "Utils/CollectionNameResolver.h"
|
||||||
#include "VocBase/LogicalCollection.h"
|
#include "VocBase/LogicalCollection.h"
|
||||||
|
|
|
@ -41,17 +41,6 @@ SubqueryBlock::SubqueryBlock(ExecutionEngine* engine, SubqueryNode const* en,
|
||||||
TRI_ASSERT(_outReg < ExecutionNode::MaxRegisterId);
|
TRI_ASSERT(_outReg < ExecutionNode::MaxRegisterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief initialize, tell dependency and the subquery
|
|
||||||
int SubqueryBlock::initialize() {
|
|
||||||
int res = ExecutionBlock::initialize();
|
|
||||||
|
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
return getSubquery()->initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief getSome
|
/// @brief getSome
|
||||||
AqlItemBlock* SubqueryBlock::getSome(size_t atMost) {
|
AqlItemBlock* SubqueryBlock::getSome(size_t atMost) {
|
||||||
DEBUG_BEGIN_BLOCK();
|
DEBUG_BEGIN_BLOCK();
|
||||||
|
|
|
@ -39,9 +39,6 @@ class SubqueryBlock : public ExecutionBlock {
|
||||||
SubqueryBlock(ExecutionEngine*, SubqueryNode const*, ExecutionBlock*);
|
SubqueryBlock(ExecutionEngine*, SubqueryNode const*, ExecutionBlock*);
|
||||||
~SubqueryBlock() = default;
|
~SubqueryBlock() = default;
|
||||||
|
|
||||||
/// @brief initialize, tell dependency and the subquery
|
|
||||||
int initialize() override final;
|
|
||||||
|
|
||||||
/// @brief getSome
|
/// @brief getSome
|
||||||
AqlItemBlock* getSome(size_t atMost) override final;
|
AqlItemBlock* getSome(size_t atMost) override final;
|
||||||
|
|
||||||
|
@ -50,7 +47,7 @@ class SubqueryBlock : public ExecutionBlock {
|
||||||
|
|
||||||
/// @brief getter for the pointer to the subquery
|
/// @brief getter for the pointer to the subquery
|
||||||
ExecutionBlock* getSubquery() { return _subquery; }
|
ExecutionBlock* getSubquery() { return _subquery; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// @brief execute the subquery and return its results
|
/// @brief execute the subquery and return its results
|
||||||
std::vector<AqlItemBlock*>* executeSubquery();
|
std::vector<AqlItemBlock*>* executeSubquery();
|
||||||
|
|
|
@ -123,30 +123,7 @@ TraversalBlock::TraversalBlock(ExecutionEngine* engine, TraversalNode const* ep)
|
||||||
if (arangodb::ServerState::instance()->isCoordinator()) {
|
if (arangodb::ServerState::instance()->isCoordinator()) {
|
||||||
_engines = ep->engines();
|
_engines = ep->engines();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
TraversalBlock::~TraversalBlock() {
|
|
||||||
freeCaches();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TraversalBlock::freeCaches() {
|
|
||||||
for (auto& v : _vertices) {
|
|
||||||
v.destroy();
|
|
||||||
}
|
|
||||||
_vertices.clear();
|
|
||||||
for (auto& e : _edges) {
|
|
||||||
e.destroy();
|
|
||||||
}
|
|
||||||
_edges.clear();
|
|
||||||
for (auto& p : _paths) {
|
|
||||||
p.destroy();
|
|
||||||
}
|
|
||||||
_paths.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
int TraversalBlock::initialize() {
|
|
||||||
DEBUG_BEGIN_BLOCK();
|
|
||||||
int res = ExecutionBlock::initialize();
|
|
||||||
auto varInfo = getPlanNode()->getRegisterPlan()->varInfo;
|
auto varInfo = getPlanNode()->getRegisterPlan()->varInfo;
|
||||||
|
|
||||||
if (usesVertexOutput()) {
|
if (usesVertexOutput()) {
|
||||||
|
@ -170,11 +147,25 @@ int TraversalBlock::initialize() {
|
||||||
TRI_ASSERT(it->second.registerId < ExecutionNode::MaxRegisterId);
|
TRI_ASSERT(it->second.registerId < ExecutionNode::MaxRegisterId);
|
||||||
_pathReg = it->second.registerId;
|
_pathReg = it->second.registerId;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
TraversalBlock::~TraversalBlock() {
|
||||||
|
freeCaches();
|
||||||
|
}
|
||||||
|
|
||||||
// cppcheck-suppress style
|
void TraversalBlock::freeCaches() {
|
||||||
DEBUG_END_BLOCK();
|
for (auto& v : _vertices) {
|
||||||
|
v.destroy();
|
||||||
|
}
|
||||||
|
_vertices.clear();
|
||||||
|
for (auto& e : _edges) {
|
||||||
|
e.destroy();
|
||||||
|
}
|
||||||
|
_edges.clear();
|
||||||
|
for (auto& p : _paths) {
|
||||||
|
p.destroy();
|
||||||
|
}
|
||||||
|
_paths.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int TraversalBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
int TraversalBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
||||||
|
|
|
@ -43,9 +43,6 @@ class TraversalBlock final : public ExecutionBlock {
|
||||||
|
|
||||||
~TraversalBlock();
|
~TraversalBlock();
|
||||||
|
|
||||||
/// @brief initialize, here we fetch all docs from the database
|
|
||||||
int initialize() override;
|
|
||||||
|
|
||||||
/// @brief initializeCursor
|
/// @brief initializeCursor
|
||||||
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||||
|
|
||||||
|
@ -59,7 +56,6 @@ class TraversalBlock final : public ExecutionBlock {
|
||||||
size_t skipSome(size_t atMost) override final;
|
size_t skipSome(size_t atMost) override final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// @brief cleanup, here we clean up all internally generated values
|
/// @brief cleanup, here we clean up all internally generated values
|
||||||
void freeCaches();
|
void freeCaches();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue