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) {
|
||||
TRI_ASSERT(_valueCount.empty());
|
||||
TRI_ASSERT(nrRegs > 0);
|
||||
TRI_ASSERT(nrRegs <= ExecutionNode::MaxRegisterId);
|
||||
|
||||
size_t const targetSize = nrItems * nrRegs;
|
||||
|
|
|
@ -28,42 +28,30 @@
|
|||
#include "VocBase/vocbase.h"
|
||||
|
||||
using namespace arangodb::aql;
|
||||
|
||||
void SingletonBlock::deleteInputVariables() {
|
||||
delete _inputRegisterValues;
|
||||
_inputRegisterValues = nullptr;
|
||||
}
|
||||
|
||||
void SingletonBlock::buildWhitelist() {
|
||||
if (!_whitelistBuilt) {
|
||||
auto en = ExecutionNode::castTo<SingletonNode const*>(getPlanNode());
|
||||
auto const& registerPlan = en->getRegisterPlan()->varInfo;
|
||||
std::unordered_set<Variable const*> const& varsUsedLater = en->getVarsUsedLater();
|
||||
SingletonBlock::SingletonBlock(ExecutionEngine* engine, SingletonNode const* ep)
|
||||
: ExecutionBlock(engine, ep) {
|
||||
auto en = ExecutionNode::castTo<SingletonNode const*>(getPlanNode());
|
||||
auto const& registerPlan = en->getRegisterPlan()->varInfo;
|
||||
std::unordered_set<Variable const*> const& varsUsedLater = en->getVarsUsedLater();
|
||||
|
||||
for (auto const& it : varsUsedLater) {
|
||||
auto it2 = registerPlan.find(it->id);
|
||||
for (auto const& it : varsUsedLater) {
|
||||
auto it2 = registerPlan.find(it->id);
|
||||
|
||||
if (it2 != registerPlan.end()) {
|
||||
_whitelist.emplace((*it2).second.registerId);
|
||||
}
|
||||
if (it2 != registerPlan.end()) {
|
||||
_whitelist.emplace((*it2).second.registerId);
|
||||
}
|
||||
}
|
||||
_whitelistBuilt = true;
|
||||
}
|
||||
|
||||
|
||||
/// @brief initializeCursor, store a copy of the register values coming from
|
||||
/// above
|
||||
int SingletonBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
||||
DEBUG_BEGIN_BLOCK();
|
||||
// Create a deep copy of the register values given to us:
|
||||
deleteInputVariables();
|
||||
|
||||
if (items != nullptr) {
|
||||
// build a whitelist with all the registers that we will copy from above
|
||||
buildWhitelist();
|
||||
deleteInputVariables();
|
||||
TRI_ASSERT(_whitelistBuilt);
|
||||
_inputRegisterValues = items->slice(pos, _whitelist);
|
||||
_inputRegisterValues.reset(items->slice(pos, _whitelist));
|
||||
}
|
||||
|
||||
_done = false;
|
||||
|
@ -75,11 +63,8 @@ int SingletonBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
|||
|
||||
/// @brief shutdown the singleton block
|
||||
int SingletonBlock::shutdown(int errorCode) {
|
||||
int res = ExecutionBlock::shutdown(errorCode);
|
||||
|
||||
deleteInputVariables();
|
||||
|
||||
return res;
|
||||
_inputRegisterValues.reset();
|
||||
return ExecutionBlock::shutdown(errorCode);
|
||||
}
|
||||
|
||||
int SingletonBlock::getOrSkipSome(size_t atMost, bool skipping,
|
||||
|
@ -96,9 +81,6 @@ int SingletonBlock::getOrSkipSome(size_t atMost, bool skipping,
|
|||
|
||||
try {
|
||||
if (_inputRegisterValues != nullptr) {
|
||||
buildWhitelist();
|
||||
TRI_ASSERT(_whitelistBuilt);
|
||||
|
||||
skipped++;
|
||||
for (RegisterId reg = 0; reg < _inputRegisterValues->getNrRegs();
|
||||
++reg) {
|
||||
|
|
|
@ -37,15 +37,7 @@ class ExecutionEngine;
|
|||
|
||||
class SingletonBlock final : public ExecutionBlock {
|
||||
public:
|
||||
SingletonBlock(ExecutionEngine* engine, SingletonNode const* ep)
|
||||
: ExecutionBlock(engine, ep), _inputRegisterValues(nullptr), _whitelistBuilt(false) {}
|
||||
|
||||
~SingletonBlock() { deleteInputVariables(); }
|
||||
|
||||
int initialize() override final {
|
||||
deleteInputVariables();
|
||||
return ExecutionBlock::initialize();
|
||||
}
|
||||
SingletonBlock(ExecutionEngine* engine, SingletonNode const* ep);
|
||||
|
||||
/// @brief initializeCursor, store a copy of the register values coming from
|
||||
/// above
|
||||
|
@ -56,19 +48,13 @@ class SingletonBlock final : public ExecutionBlock {
|
|||
bool hasMore() override final { return !_done; }
|
||||
|
||||
private:
|
||||
void deleteInputVariables();
|
||||
|
||||
void buildWhitelist();
|
||||
|
||||
int getOrSkipSome(size_t atMost, bool skipping,
|
||||
AqlItemBlock*& result, size_t& skipped) override;
|
||||
|
||||
/// @brief _inputRegisterValues
|
||||
AqlItemBlock* _inputRegisterValues;
|
||||
std::unique_ptr<AqlItemBlock> _inputRegisterValues;
|
||||
|
||||
std::unordered_set<RegisterId> _whitelist;
|
||||
|
||||
bool _whitelistBuilt;
|
||||
};
|
||||
|
||||
class FilterBlock final : public ExecutionBlock {
|
||||
|
@ -110,13 +96,12 @@ class LimitBlock final : public ExecutionBlock {
|
|||
_state(0), // start in the beginning
|
||||
_fullCount(ep->_fullCount) {}
|
||||
|
||||
~LimitBlock() {}
|
||||
|
||||
int initializeCursor(AqlItemBlock* items, size_t pos) override final;
|
||||
|
||||
virtual int getOrSkipSome(size_t atMost, bool skipping,
|
||||
AqlItemBlock*& result, size_t& skipped) override;
|
||||
|
||||
int getOrSkipSome(size_t atMost, bool skipping,
|
||||
AqlItemBlock*& result, size_t& skipped) override;
|
||||
|
||||
private:
|
||||
/// @brief _offset
|
||||
size_t _offset;
|
||||
|
||||
|
@ -138,8 +123,6 @@ class ReturnBlock final : public ExecutionBlock {
|
|||
ReturnBlock(ExecutionEngine* engine, ReturnNode const* ep)
|
||||
: ExecutionBlock(engine, ep), _returnInheritedResults(false) {}
|
||||
|
||||
~ReturnBlock() {}
|
||||
|
||||
/// @brief getSome
|
||||
AqlItemBlock* getSome(size_t atMost) override final;
|
||||
|
||||
|
@ -161,8 +144,6 @@ class NoResultsBlock final : public ExecutionBlock {
|
|||
NoResultsBlock(ExecutionEngine* engine, ExecutionNode const* ep)
|
||||
: ExecutionBlock(engine, ep) {}
|
||||
|
||||
~NoResultsBlock() {}
|
||||
|
||||
/// @brief initializeCursor, store a copy of the register values coming from
|
||||
/// above
|
||||
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)
|
||||
: ExecutionBlock(engine, en),
|
||||
_atDep(0),
|
||||
_sortRegisters(),
|
||||
_isSimple(en->elements().empty()),
|
||||
_heap(en->_sortmode == 'h' ? new Heap : nullptr) {
|
||||
|
@ -87,16 +88,6 @@ GatherBlock::~GatherBlock() {
|
|||
_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
|
||||
int GatherBlock::shutdown(int errorCode) {
|
||||
DEBUG_BEGIN_BLOCK();
|
||||
|
@ -1209,71 +1200,37 @@ RemoteBlock::RemoteBlock(ExecutionEngine* engine, RemoteNode const* en,
|
|||
!ownName.empty()));
|
||||
}
|
||||
|
||||
RemoteBlock::~RemoteBlock() {}
|
||||
|
||||
/// @brief local helper to send a request
|
||||
std::unique_ptr<ClusterCommResult> RemoteBlock::sendRequest(
|
||||
arangodb::rest::RequestType type, std::string const& urlPart,
|
||||
std::string const& body) const {
|
||||
DEBUG_BEGIN_BLOCK();
|
||||
auto cc = ClusterComm::instance();
|
||||
if (cc != nullptr) {
|
||||
if (cc == nullptr) {
|
||||
// nullptr only happens on controlled shutdown
|
||||
|
||||
// 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;
|
||||
return std::make_unique<ClusterCommResult>();
|
||||
}
|
||||
|
||||
std::unique_ptr<ClusterCommResult> res =
|
||||
sendRequest(rest::RequestType::PUT, "/_api/aql/initialize/", "{}");
|
||||
throwExceptionAfterBadSyncRequest(res.get(), false);
|
||||
|
||||
// If we get here, then res->result is the response which will be
|
||||
// a serialized AqlItemBlock:
|
||||
StringBuffer const& responseBodyBuf(res->result->getBody());
|
||||
|
||||
std::shared_ptr<VPackBuilder> builder =
|
||||
VPackParser::fromJson(responseBodyBuf.c_str(), responseBodyBuf.length());
|
||||
VPackSlice slice = builder->slice();
|
||||
|
||||
if (slice.hasKey("code")) {
|
||||
return slice.get("code").getNumericValue<int>();
|
||||
// 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);
|
||||
}
|
||||
|
||||
std::string url = std::string("/_db/") +
|
||||
arangodb::basics::StringUtils::urlEncode(_engine->getQuery()->trx()->vocbase().name()) +
|
||||
urlPart + _queryId;
|
||||
|
||||
++_engine->_stats.requests;
|
||||
{
|
||||
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
|
||||
DEBUG_END_BLOCK();
|
||||
|
@ -1288,6 +1245,12 @@ int RemoteBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
|||
// do nothing...
|
||||
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);
|
||||
options.buildUnindexedArrays = true;
|
||||
|
@ -1295,21 +1258,15 @@ int RemoteBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
|||
|
||||
VPackBuilder builder(&options);
|
||||
builder.openObject();
|
||||
|
||||
if (items == nullptr) {
|
||||
// first call, items is still a nullptr
|
||||
builder.add("exhausted", VPackValue(true));
|
||||
builder.add("error", VPackValue(false));
|
||||
} else {
|
||||
builder.add("exhausted", VPackValue(false));
|
||||
builder.add("error", VPackValue(false));
|
||||
builder.add("pos", VPackValue(pos));
|
||||
builder.add(VPackValue("items"));
|
||||
builder.openObject();
|
||||
items->toVelocyPack(_engine->getQuery()->trx(), builder);
|
||||
builder.close();
|
||||
}
|
||||
|
||||
|
||||
builder.add("exhausted", VPackValue(false));
|
||||
builder.add("error", VPackValue(false));
|
||||
builder.add("pos", VPackValue(pos));
|
||||
builder.add(VPackValue("items"));
|
||||
builder.openObject();
|
||||
items->toVelocyPack(_engine->getQuery()->trx(), builder);
|
||||
builder.close();
|
||||
|
||||
builder.close();
|
||||
|
||||
std::string bodyString(builder.slice().toJson());
|
||||
|
|
|
@ -63,9 +63,6 @@ class GatherBlock : public ExecutionBlock {
|
|||
|
||||
~GatherBlock();
|
||||
|
||||
/// @brief initialize
|
||||
int initialize() override;
|
||||
|
||||
/// @brief shutdown: need our own method since our _buffer is different
|
||||
int shutdown(int) override final;
|
||||
|
||||
|
@ -203,8 +200,6 @@ class ScatterBlock : public BlockWithClients {
|
|||
std::vector<std::string> const& shardIds)
|
||||
: BlockWithClients(engine, ep, shardIds) {}
|
||||
|
||||
~ScatterBlock() {}
|
||||
|
||||
/// @brief initializeCursor
|
||||
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
|
@ -230,8 +225,6 @@ class DistributeBlock : public BlockWithClients {
|
|||
std::vector<std::string> const& shardIds,
|
||||
Collection const* collection);
|
||||
|
||||
~DistributeBlock() {}
|
||||
|
||||
/// @brief initializeCursor
|
||||
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& queryId);
|
||||
|
||||
~RemoteBlock();
|
||||
|
||||
/// @brief timeout
|
||||
static double const defaultTimeOut;
|
||||
|
||||
/// @brief initialize
|
||||
int initialize() override final;
|
||||
|
||||
/// @brief initializeCursor, could be called multiple times
|
||||
int initializeCursor(AqlItemBlock* items, size_t pos) override final;
|
||||
|
||||
|
@ -319,7 +307,7 @@ class RemoteBlock final : public ExecutionBlock {
|
|||
|
||||
/// @brief hasMore
|
||||
bool hasMore() override final;
|
||||
|
||||
|
||||
private:
|
||||
/// @brief internal method to send a request
|
||||
std::unique_ptr<arangodb::ClusterCommResult> sendRequest(
|
||||
|
@ -327,14 +315,14 @@ class RemoteBlock final : public ExecutionBlock {
|
|||
std::string const& body) const;
|
||||
|
||||
/// @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,
|
||||
/// 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
|
||||
std::string _queryId;
|
||||
std::string const _queryId;
|
||||
|
||||
/// @brief whether or not this block will forward initialize,
|
||||
/// 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
|
||||
_currentGroup.initialize(_groupRegisters.size());
|
||||
_pos = 0;
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
int SortedCollectBlock::initializeCursor(AqlItemBlock* items,
|
||||
|
@ -604,8 +591,6 @@ HashedCollectBlock::HashedCollectBlock(ExecutionEngine* engine,
|
|||
TRI_ASSERT(!_groupRegisters.empty());
|
||||
}
|
||||
|
||||
HashedCollectBlock::~HashedCollectBlock() {}
|
||||
|
||||
int HashedCollectBlock::getOrSkipSome(size_t atMost,
|
||||
bool skipping, AqlItemBlock*& result,
|
||||
size_t& skipped) {
|
||||
|
@ -874,17 +859,6 @@ DistinctCollectBlock::~DistinctCollectBlock() {
|
|||
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,
|
||||
size_t pos) {
|
||||
DEBUG_BEGIN_BLOCK();
|
||||
|
|
|
@ -85,10 +85,6 @@ class SortedCollectBlock final : public ExecutionBlock {
|
|||
public:
|
||||
SortedCollectBlock(ExecutionEngine*, CollectNode const*);
|
||||
|
||||
~SortedCollectBlock();
|
||||
|
||||
int initialize() override final;
|
||||
|
||||
/// @brief initializeCursor
|
||||
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
|
@ -132,7 +128,6 @@ class SortedCollectBlock final : public ExecutionBlock {
|
|||
class HashedCollectBlock : public ExecutionBlock {
|
||||
public:
|
||||
HashedCollectBlock(ExecutionEngine*, CollectNode const*);
|
||||
~HashedCollectBlock();
|
||||
|
||||
private:
|
||||
int getOrSkipSome(size_t atMost, bool skipping,
|
||||
|
@ -157,8 +152,6 @@ class DistinctCollectBlock : public ExecutionBlock {
|
|||
DistinctCollectBlock(ExecutionEngine*, CollectNode const*);
|
||||
~DistinctCollectBlock();
|
||||
|
||||
int initialize() override final;
|
||||
|
||||
/// @brief initializeCursor
|
||||
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
|
|
|
@ -50,10 +50,6 @@ EnumerateCollectionBlock::EnumerateCollectionBlock(
|
|||
TRI_ASSERT(_cursor->ok());
|
||||
|
||||
buildCallback();
|
||||
}
|
||||
|
||||
int EnumerateCollectionBlock::initialize() {
|
||||
DEBUG_BEGIN_BLOCK();
|
||||
|
||||
if (ServerState::instance()->isRunningInCluster() && _collection->isSatellite()) {
|
||||
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) +")");
|
||||
}
|
||||
}
|
||||
|
||||
return ExecutionBlock::initialize();
|
||||
|
||||
// cppcheck-suppress style
|
||||
DEBUG_END_BLOCK();
|
||||
}
|
||||
|
||||
int EnumerateCollectionBlock::initializeCursor(AqlItemBlock* items,
|
||||
|
|
|
@ -46,11 +46,6 @@ class EnumerateCollectionBlock final : public ExecutionBlock, public DocumentPro
|
|||
EnumerateCollectionBlock(ExecutionEngine* engine,
|
||||
EnumerateCollectionNode const* ep);
|
||||
|
||||
~EnumerateCollectionBlock() = default;
|
||||
|
||||
/// @brief initialize, here we fetch all docs from the database
|
||||
int initialize() override final;
|
||||
|
||||
/// @brief initializeCursor
|
||||
int initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
|
|
|
@ -87,8 +87,17 @@ bool ExecutionBlock::removeDependency(ExecutionBlock* ep) {
|
|||
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) {
|
||||
DEBUG_BEGIN_BLOCK();
|
||||
for (auto& d : _dependencies) {
|
||||
int res = d->initializeCursor(items, pos);
|
||||
|
||||
|
@ -104,29 +113,6 @@ int ExecutionBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
|||
|
||||
_done = false;
|
||||
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
|
||||
|
|
|
@ -102,16 +102,7 @@ class ExecutionBlock {
|
|||
/// @brief remove a dependency, returns true if the pointer was found and
|
||||
/// removed, please note that this does not delete 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
|
||||
/// Lifecycle is:
|
||||
/// CONSTRUCTOR
|
||||
|
@ -123,8 +114,6 @@ class ExecutionBlock {
|
|||
/// then the ExecutionEngine automatically calls
|
||||
/// shutdown()
|
||||
/// DESTRUCTOR
|
||||
/// @brief initialize
|
||||
virtual int initialize();
|
||||
|
||||
/// @brief initializeCursor, could be called multiple times
|
||||
virtual int initializeCursor(AqlItemBlock* items, size_t pos);
|
||||
|
@ -223,7 +212,7 @@ class ExecutionBlock {
|
|||
|
||||
/// @brief current working position in the first entry of _buffer
|
||||
size_t _pos;
|
||||
|
||||
|
||||
/// @brief if this is set, we are done, this is reset to false by execute()
|
||||
bool _done;
|
||||
|
||||
|
|
|
@ -181,6 +181,7 @@ ExecutionEngine::ExecutionEngine(Query* query)
|
|||
_root(nullptr),
|
||||
_query(query),
|
||||
_resultRegister(0),
|
||||
_initializeCursorCalled(false),
|
||||
_wasShutdown(false),
|
||||
_previouslyLockedShards(nullptr),
|
||||
_lockedShards(nullptr) {
|
||||
|
@ -582,7 +583,6 @@ ExecutionEngine* ExecutionEngine::instantiateFromPlan(
|
|||
engine->_root = root;
|
||||
|
||||
if (plan->isResponsibleForInitialize()) {
|
||||
root->initialize();
|
||||
root->initializeCursor(nullptr, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -70,24 +70,26 @@ class ExecutionEngine {
|
|||
|
||||
/// @brief initializeCursor, could be called multiple times
|
||||
int initializeCursor(AqlItemBlock* items, size_t pos) {
|
||||
_initializeCursorCalled = true;
|
||||
return _root->initializeCursor(items, pos);
|
||||
}
|
||||
|
||||
/// @brief initialize
|
||||
int initialize() {
|
||||
return _root->initialize();
|
||||
}
|
||||
|
||||
/// @brief shutdown, will be called exactly once for the whole query
|
||||
int shutdown(int errorCode);
|
||||
|
||||
/// @brief getSome
|
||||
AqlItemBlock* getSome(size_t atMost) {
|
||||
if (!_initializeCursorCalled) {
|
||||
initializeCursor(nullptr, 0);
|
||||
}
|
||||
return _root->getSome(atMost);
|
||||
}
|
||||
|
||||
/// @brief skipSome
|
||||
size_t skipSome(size_t atMost) {
|
||||
if (!_initializeCursorCalled) {
|
||||
initializeCursor(nullptr, 0);
|
||||
}
|
||||
return _root->skipSome(atMost);
|
||||
}
|
||||
|
||||
|
@ -96,12 +98,18 @@ class ExecutionEngine {
|
|||
|
||||
/// @brief skip
|
||||
bool skip(size_t number, size_t& actuallySkipped) {
|
||||
if (!_initializeCursorCalled) {
|
||||
initializeCursor(nullptr, 0);
|
||||
}
|
||||
return _root->skip(number, actuallySkipped);
|
||||
}
|
||||
|
||||
/// @brief 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
|
||||
TEST_VIRTUAL void addBlock(ExecutionBlock*);
|
||||
|
||||
|
@ -148,9 +156,12 @@ class ExecutionEngine {
|
|||
/// @brief the register the final result of the query is stored in
|
||||
RegisterId _resultRegister;
|
||||
|
||||
/// @brief whether or not initializeCursor was called
|
||||
bool _initializeCursorCalled;
|
||||
|
||||
/// @brief whether or not shutdown() was executed
|
||||
bool _wasShutdown;
|
||||
|
||||
|
||||
/// @brief _previouslyLockedShards, this is read off at instanciating
|
||||
/// time from a thread local variable
|
||||
std::unordered_set<std::string>* _previouslyLockedShards;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ExecutionNode.h"
|
||||
#include "Aql/AqlItemBlock.h"
|
||||
#include "Aql/Ast.h"
|
||||
#include "Aql/BasicBlocks.h"
|
||||
#include "Aql/CalculationBlock.h"
|
||||
|
|
|
@ -343,7 +343,7 @@ class ExecutionNode {
|
|||
static constexpr unsigned SERIALIZE_PARENTS = 1;
|
||||
/// include estimate cost (used in the explainer)
|
||||
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;
|
||||
/// include additional function info for explain
|
||||
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("scannedIndex", VPackValue(scannedIndex));
|
||||
builder.add("filtered", VPackValue(filtered));
|
||||
builder.add("httpRequests", VPackValue(httpRequests));
|
||||
builder.add("httpRequests", VPackValue(requests));
|
||||
if (reportFullCount) {
|
||||
// fullCount is optional
|
||||
builder.add("fullCount", VPackValue(fullCount > count ? fullCount : count));
|
||||
|
@ -75,7 +75,7 @@ void ExecutionStats::add(ExecutionStats const& summand) {
|
|||
scannedFull += summand.scannedFull;
|
||||
scannedIndex += summand.scannedIndex;
|
||||
filtered += summand.filtered;
|
||||
httpRequests += summand.httpRequests;
|
||||
requests += summand.requests;
|
||||
if (summand.fullCount > 0) {
|
||||
fullCount += summand.fullCount;
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ ExecutionStats::ExecutionStats()
|
|||
scannedFull(0),
|
||||
scannedIndex(0),
|
||||
filtered(0),
|
||||
httpRequests(0),
|
||||
requests(0),
|
||||
fullCount(0),
|
||||
count(0),
|
||||
executionTime(0.0) {}
|
||||
|
@ -117,13 +117,9 @@ ExecutionStats::ExecutionStats(VPackSlice const& slice)
|
|||
filtered = slice.get("filtered").getNumber<int64_t>();
|
||||
|
||||
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!
|
||||
if (slice.hasKey("fullCount")) {
|
||||
fullCount = slice.get("fullCount").getNumber<int64_t>();
|
||||
|
|
|
@ -73,7 +73,7 @@ struct ExecutionStats {
|
|||
scannedFull = 0;
|
||||
scannedIndex = 0;
|
||||
filtered = 0;
|
||||
httpRequests = 0;
|
||||
requests = 0;
|
||||
fullCount = 0;
|
||||
count = 0;
|
||||
executionTime = 0.0;
|
||||
|
@ -93,9 +93,9 @@ struct ExecutionStats {
|
|||
|
||||
/// @brief number of documents filtered away
|
||||
int64_t filtered;
|
||||
/// @brief total number of HTTP requests made
|
||||
|
||||
int64_t httpRequests;
|
||||
|
||||
/// @brief total number of requests made
|
||||
int64_t requests;
|
||||
|
||||
/// @brief total number of results, before applying last limit
|
||||
int64_t fullCount;
|
||||
|
|
|
@ -136,6 +136,8 @@ IndexBlock::IndexBlock(ExecutionEngine* engine, IndexNode const* en)
|
|||
// build the _documentProducer callback for extracting
|
||||
// documents from the index
|
||||
buildCallback();
|
||||
|
||||
initializeOnce();
|
||||
}
|
||||
|
||||
IndexBlock::~IndexBlock() { cleanupNonConstExpressions(); }
|
||||
|
@ -211,40 +213,11 @@ void IndexBlock::executeExpressions() {
|
|||
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();
|
||||
}
|
||||
|
||||
int IndexBlock::initialize() {
|
||||
DEBUG_BEGIN_BLOCK();
|
||||
int res = ExecutionBlock::initialize();
|
||||
|
||||
void IndexBlock::initializeOnce() {
|
||||
auto en = ExecutionNode::castTo<IndexNode const*>(getPlanNode());
|
||||
auto ast = en->_plan->getAst();
|
||||
|
||||
|
@ -284,8 +257,8 @@ int IndexBlock::initialize() {
|
|||
};
|
||||
|
||||
if (_condition == nullptr) {
|
||||
// This Node has no condition. Iterate over the complete index.
|
||||
return res;
|
||||
// this node has no condition. Iterate over the complete index.
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -63,9 +63,6 @@ class IndexBlock final : public ExecutionBlock, public DocumentProducingBlock {
|
|||
|
||||
~IndexBlock();
|
||||
|
||||
/// @brief initialize, here we fetch all docs from the database
|
||||
int initialize() override;
|
||||
|
||||
/// @brief initializeCursor, here we release our docs from this collection
|
||||
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;
|
||||
|
||||
private:
|
||||
void initializeOnce();
|
||||
|
||||
/// @brief adds a SORT to a dynamic IN condition
|
||||
arangodb::aql::AstNode* makeUnique(arangodb::aql::AstNode*) const;
|
||||
|
||||
|
|
|
@ -907,7 +907,7 @@ QueryResult Query::explain() {
|
|||
try {
|
||||
init();
|
||||
enterState(QueryExecutionState::ValueType::PARSING);
|
||||
|
||||
|
||||
Parser parser(this);
|
||||
|
||||
parser.parse(true);
|
||||
|
@ -983,8 +983,7 @@ QueryResult Query::explain() {
|
|||
!_isModificationQuery && _warnings.empty() &&
|
||||
_ast->root()->isCacheable());
|
||||
}
|
||||
|
||||
// technically no need to commit, as we are only explaining here
|
||||
|
||||
auto commitResult = _trx->commit();
|
||||
if (commitResult.fail()) {
|
||||
THROW_ARANGO_EXCEPTION(commitResult);
|
||||
|
|
|
@ -584,12 +584,7 @@ void RestAqlHandler::useQuery(std::string const& operation,
|
|||
void RestAqlHandler::getInfoQuery(std::string const& operation,
|
||||
std::string const& idString) {
|
||||
bool found;
|
||||
std::string shardId;
|
||||
std::string const& shardIdCharP = _request->header("shard-id", found);
|
||||
|
||||
if (found && !shardIdCharP.empty()) {
|
||||
shardId = shardIdCharP;
|
||||
}
|
||||
std::string const& shardId = _request->header("shard-id", found);
|
||||
|
||||
Query* query = nullptr;
|
||||
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,
|
||||
VPackSlice const querySlice) {
|
||||
bool found;
|
||||
std::string shardId;
|
||||
std::string const& shardIdCharP = _request->header("shard-id", found);
|
||||
std::string const& shardId = _request->header("shard-id", found);
|
||||
|
||||
if (found && !shardIdCharP.empty()) {
|
||||
shardId = shardIdCharP;
|
||||
// upon first usage, the "initializeCursor" method must be called
|
||||
// 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;
|
||||
|
@ -781,19 +785,8 @@ void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
|
|||
JobGuard guard(SchedulerFeature::SCHEDULER);
|
||||
guard.block();
|
||||
|
||||
try {
|
||||
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;
|
||||
}
|
||||
// let exceptions propagate from here
|
||||
res = query->trx()->lockCollections();
|
||||
}
|
||||
|
||||
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("error", VPackValue(false));
|
||||
} else {
|
||||
try {
|
||||
items->toVelocyPack(query->trx(), answerBuilder);
|
||||
} catch (...) {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_HTTP_SERVER_ERROR,
|
||||
"cannot transform AqlItemBlock to VelocyPack");
|
||||
return;
|
||||
}
|
||||
items->toVelocyPack(query->trx(), answerBuilder);
|
||||
}
|
||||
} else if (operation == "skipSome") {
|
||||
auto atMost = VelocyPackHelper::getNumericValue<size_t>(
|
||||
querySlice, "atMost", ExecutionBlock::DefaultBatchSize());
|
||||
size_t skipped;
|
||||
try {
|
||||
if (shardId.empty()) {
|
||||
skipped = query->engine()->skipSome(atMost);
|
||||
} 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");
|
||||
}
|
||||
skipped = block->skipSomeForShard(atMost, shardId);
|
||||
if (shardId.empty()) {
|
||||
skipped = query->engine()->skipSome(atMost);
|
||||
} 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");
|
||||
}
|
||||
} catch (std::exception const& ex) {
|
||||
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;
|
||||
skipped = block->skipSomeForShard(atMost, shardId);
|
||||
}
|
||||
answerBuilder.add("skipped", VPackValue(static_cast<double>(skipped)));
|
||||
answerBuilder.add("skipped", VPackValue(skipped));
|
||||
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") {
|
||||
int res;
|
||||
try {
|
||||
res = query->engine()->initialize();
|
||||
} 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)));
|
||||
// this is a no-op now
|
||||
answerBuilder.add(StaticStrings::Error, VPackValue(false));
|
||||
answerBuilder.add(StaticStrings::Code, VPackValue(TRI_ERROR_NO_ERROR));
|
||||
} else if (operation == "initializeCursor") {
|
||||
auto pos =
|
||||
VelocyPackHelper::getNumericValue<size_t>(querySlice, "pos", 0);
|
||||
std::unique_ptr<AqlItemBlock> items;
|
||||
int res;
|
||||
try {
|
||||
if (VelocyPackHelper::getBooleanValue(querySlice, "exhausted",
|
||||
true)) {
|
||||
res = query->engine()->initializeCursor(nullptr, 0);
|
||||
} else {
|
||||
items.reset(new AqlItemBlock(query->resourceMonitor(),
|
||||
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;
|
||||
if (VelocyPackHelper::getBooleanValue(querySlice, "exhausted", true)) {
|
||||
res = query->engine()->initializeCursor(nullptr, 0);
|
||||
} else {
|
||||
items.reset(new AqlItemBlock(query->resourceMonitor(),
|
||||
querySlice.get("items")));
|
||||
res = query->engine()->initializeCursor(items.get(), pos);
|
||||
}
|
||||
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") {
|
||||
int res = TRI_ERROR_INTERNAL;
|
||||
int errorCode = VelocyPackHelper::getNumericValue<int>(
|
||||
querySlice, "code", TRI_ERROR_INTERNAL);
|
||||
try {
|
||||
res = query->engine()->shutdown(
|
||||
errorCode); // pass errorCode to shutdown
|
||||
int res = query->engine()->shutdown(errorCode); // pass errorCode to shutdown
|
||||
|
||||
// return statistics
|
||||
answerBuilder.add(VPackValue("stats"));
|
||||
query->getStats(answerBuilder);
|
||||
// return statistics
|
||||
answerBuilder.add(VPackValue("stats"));
|
||||
query->getStats(answerBuilder);
|
||||
|
||||
// return warnings if present
|
||||
query->addWarningsToVelocyPack(answerBuilder);
|
||||
// return warnings if present
|
||||
query->addWarningsToVelocyPack(answerBuilder);
|
||||
|
||||
// return the query to the registry
|
||||
_queryRegistry->close(&_vocbase, _qId);
|
||||
// return the query to the registry
|
||||
_queryRegistry->close(&_vocbase, _qId);
|
||||
|
||||
// delete the query from the registry
|
||||
_queryRegistry->destroy(&_vocbase, _qId, errorCode);
|
||||
_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;
|
||||
}
|
||||
// delete the query from the registry
|
||||
_queryRegistry->destroy(&_vocbase, _qId, errorCode);
|
||||
_qId = 0;
|
||||
answerBuilder.add(StaticStrings::Error, VPackValue(res != TRI_ERROR_NO_ERROR));
|
||||
answerBuilder.add(StaticStrings::Code, VPackValue(res));
|
||||
} else {
|
||||
|
@ -974,17 +874,13 @@ void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
|
|||
}
|
||||
}
|
||||
|
||||
sendResponse(rest::ResponseCode::OK, answerBuilder.slice(),
|
||||
transactionContext.get());
|
||||
sendResponse(rest::ResponseCode::OK, answerBuilder.slice(), transactionContext.get());
|
||||
} catch (arangodb::basics::Exception const& ex) {
|
||||
generateError(rest::ResponseCode::BAD, ex.code(), ex.message());
|
||||
return;
|
||||
generateError(GeneralResponse::responseCode(ex.code()), ex.code(), ex.message());
|
||||
} catch (std::exception const& ex) {
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_FAILED, ex.what());
|
||||
return;
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL, ex.what());
|
||||
} catch (...) {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL, "unknown exception caught in handleUsequery");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -993,7 +889,6 @@ std::shared_ptr<VPackBuilder> RestAqlHandler::parseVelocyPackBody() {
|
|||
try {
|
||||
std::shared_ptr<VPackBuilder> body = _request->toVelocyPackBuilderPtr();
|
||||
if (body == nullptr) {
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "cannot parse json object";
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_CORRUPTED_JSON, "cannot parse json object");
|
||||
return nullptr;
|
||||
|
@ -1009,7 +904,6 @@ std::shared_ptr<VPackBuilder> RestAqlHandler::parseVelocyPackBody() {
|
|||
}
|
||||
return body;
|
||||
} catch (...) {
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "cannot parse json object";
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_CORRUPTED_JSON,
|
||||
"cannot parse json object");
|
||||
}
|
||||
|
|
|
@ -100,14 +100,7 @@ ShortestPathBlock::ShortestPathBlock(ExecutionEngine* engine,
|
|||
if (arangodb::ServerState::instance()->isCoordinator()) {
|
||||
_engines = ep->engines();
|
||||
}
|
||||
}
|
||||
|
||||
ShortestPathBlock::~ShortestPathBlock() {
|
||||
}
|
||||
|
||||
int ShortestPathBlock::initialize() {
|
||||
DEBUG_BEGIN_BLOCK();
|
||||
int res = ExecutionBlock::initialize();
|
||||
|
||||
auto varInfo = getPlanNode()->getRegisterPlan()->varInfo;
|
||||
|
||||
if (usesVertexOutput()) {
|
||||
|
@ -124,11 +117,6 @@ int ShortestPathBlock::initialize() {
|
|||
TRI_ASSERT(it->second.registerId < ExecutionNode::MaxRegisterId);
|
||||
_edgeReg = it->second.registerId;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
// cppcheck-suppress style
|
||||
DEBUG_END_BLOCK();
|
||||
}
|
||||
|
||||
int ShortestPathBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
||||
|
|
|
@ -45,11 +45,6 @@ class ShortestPathBlock : public ExecutionBlock {
|
|||
public:
|
||||
ShortestPathBlock(ExecutionEngine* engine, ShortestPathNode const* ep);
|
||||
|
||||
~ShortestPathBlock();
|
||||
|
||||
/// @brief initialize, here we fetch all docs from the database
|
||||
int initialize() override;
|
||||
|
||||
/// @brief initializeCursor
|
||||
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
|
||||
// things to skip overall.
|
||||
size_t skipSome(size_t atMost) override final;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/// SECTION private Functions
|
||||
|
||||
/// @brief Compute the next shortest path
|
||||
bool nextPath(AqlItemBlock const*);
|
||||
|
||||
|
|
|
@ -30,7 +30,9 @@
|
|||
#include "Aql/ExecutionPlan.h"
|
||||
#include "Aql/ShortestPathBlock.h"
|
||||
#include "Aql/Query.h"
|
||||
#include "Graph/ShortestPathFinder.h"
|
||||
#include "Graph/ShortestPathOptions.h"
|
||||
#include "Graph/ShortestPathResult.h"
|
||||
#include "Indexes/Index.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
#include "VocBase/LogicalCollection.h"
|
||||
|
|
|
@ -41,17 +41,6 @@ SubqueryBlock::SubqueryBlock(ExecutionEngine* engine, SubqueryNode const* en,
|
|||
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
|
||||
AqlItemBlock* SubqueryBlock::getSome(size_t atMost) {
|
||||
DEBUG_BEGIN_BLOCK();
|
||||
|
|
|
@ -39,9 +39,6 @@ class SubqueryBlock : public ExecutionBlock {
|
|||
SubqueryBlock(ExecutionEngine*, SubqueryNode const*, ExecutionBlock*);
|
||||
~SubqueryBlock() = default;
|
||||
|
||||
/// @brief initialize, tell dependency and the subquery
|
||||
int initialize() override final;
|
||||
|
||||
/// @brief getSome
|
||||
AqlItemBlock* getSome(size_t atMost) override final;
|
||||
|
||||
|
@ -50,7 +47,7 @@ class SubqueryBlock : public ExecutionBlock {
|
|||
|
||||
/// @brief getter for the pointer to the subquery
|
||||
ExecutionBlock* getSubquery() { return _subquery; }
|
||||
|
||||
|
||||
private:
|
||||
/// @brief execute the subquery and return its results
|
||||
std::vector<AqlItemBlock*>* executeSubquery();
|
||||
|
|
|
@ -123,30 +123,7 @@ TraversalBlock::TraversalBlock(ExecutionEngine* engine, TraversalNode const* ep)
|
|||
if (arangodb::ServerState::instance()->isCoordinator()) {
|
||||
_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;
|
||||
|
||||
if (usesVertexOutput()) {
|
||||
|
@ -170,11 +147,25 @@ int TraversalBlock::initialize() {
|
|||
TRI_ASSERT(it->second.registerId < ExecutionNode::MaxRegisterId);
|
||||
_pathReg = it->second.registerId;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
TraversalBlock::~TraversalBlock() {
|
||||
freeCaches();
|
||||
}
|
||||
|
||||
// cppcheck-suppress style
|
||||
DEBUG_END_BLOCK();
|
||||
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::initializeCursor(AqlItemBlock* items, size_t pos) {
|
||||
|
|
|
@ -43,9 +43,6 @@ class TraversalBlock final : public ExecutionBlock {
|
|||
|
||||
~TraversalBlock();
|
||||
|
||||
/// @brief initialize, here we fetch all docs from the database
|
||||
int initialize() override;
|
||||
|
||||
/// @brief initializeCursor
|
||||
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;
|
||||
|
||||
private:
|
||||
|
||||
/// @brief cleanup, here we clean up all internally generated values
|
||||
void freeCaches();
|
||||
|
||||
|
|
Loading…
Reference in New Issue