diff --git a/arangod/Aql/ExecutionBlock.h b/arangod/Aql/ExecutionBlock.h index 0f6b5c54a2..8e0f9b60eb 100644 --- a/arangod/Aql/ExecutionBlock.h +++ b/arangod/Aql/ExecutionBlock.h @@ -139,36 +139,36 @@ namespace triagens { struct VarInfo { unsigned int depth; - unsigned int index; - VarInfo(int depth, int index) : depth(depth), index(index) {} + RegisterId registerId; + VarInfo(int depth, int registerId) : depth(depth), registerId(registerId) {} }; struct VarOverview : public WalkerWorker { // The following are collected for global usage in the ExecutionBlock: - // map VariableIds to their depth and index: + // map VariableIds to their depth and registerId: std::unordered_map varInfo; // number of variables in the frame of the current depth: - std::vector nrVarsHere; + std::vector nrRegsHere; // number of variables in this and all outer frames together, // the entry with index i here is always the sum of all values - // in nrVarsHere from index 0 to i (inclusively) and the two + // in nrRegsHere from index 0 to i (inclusively) and the two // have the same length: - std::vector nrVars; + std::vector nrRegs; // Local for the walk: unsigned int depth; - unsigned int totalNrVars; + unsigned int totalNrRegs; // This is used to tell all Blocks and share a pointer to ourselves shared_ptr* me; VarOverview () - : depth(0), totalNrVars(0), me(nullptr) { - nrVarsHere.push_back(0); - nrVars.push_back(0); + : depth(0), totalNrRegs(0), me(nullptr) { + nrRegsHere.push_back(0); + nrRegs.push_back(0); }; void setSharedPtr (shared_ptr* shared) { @@ -177,10 +177,10 @@ namespace triagens { // Copy constructor used for a subquery: VarOverview (VarOverview const& v) - : varInfo(v.varInfo), nrVarsHere(v.nrVars), nrVars(v.nrVars), - depth(v.depth+1), totalNrVars(v.totalNrVars), me(nullptr) { - nrVarsHere.push_back(0); - nrVars.push_back(0); + : varInfo(v.varInfo), nrRegsHere(v.nrRegs), nrRegs(v.nrRegs), + depth(v.depth+1), totalNrRegs(v.totalNrRegs), me(nullptr) { + nrRegsHere.push_back(0); + nrRegs.push_back(0); } ~VarOverview () {}; @@ -198,49 +198,49 @@ namespace triagens { switch (eb->getPlanNode()->getType()) { case ExecutionNode::ENUMERATE_COLLECTION: { depth++; - nrVarsHere.push_back(1); - nrVars.push_back(1 + nrVars.back()); + nrRegsHere.push_back(1); + nrRegs.push_back(1 + nrRegs.back()); auto ep = static_cast(eb->getPlanNode()); varInfo.insert(make_pair(ep->_outVariable->id, - VarInfo(depth, totalNrVars))); - totalNrVars++; + VarInfo(depth, totalNrRegs))); + totalNrRegs++; break; } case ExecutionNode::ENUMERATE_LIST: { depth++; - nrVarsHere.push_back(1); - nrVars.push_back(1 + nrVars.back()); + nrRegsHere.push_back(1); + nrRegs.push_back(1 + nrRegs.back()); auto ep = static_cast(eb->getPlanNode()); varInfo.insert(make_pair(ep->_outVariable->id, - VarInfo(depth, totalNrVars))); - totalNrVars++; + VarInfo(depth, totalNrRegs))); + totalNrRegs++; break; } case ExecutionNode::CALCULATION: { - nrVarsHere[depth]++; - nrVars[depth]++; + nrRegsHere[depth]++; + nrRegs[depth]++; auto ep = static_cast(eb->getPlanNode()); varInfo.insert(make_pair(ep->_outVariable->id, - VarInfo(depth, totalNrVars))); - totalNrVars++; + VarInfo(depth, totalNrRegs))); + totalNrRegs++; break; } case ExecutionNode::PROJECTION: { - nrVarsHere[depth]++; - nrVars[depth]++; + nrRegsHere[depth]++; + nrRegs[depth]++; auto ep = static_cast(eb->getPlanNode()); varInfo.insert(make_pair(ep->_outVariable->id, - VarInfo(depth, totalNrVars))); - totalNrVars++; + VarInfo(depth, totalNrRegs))); + totalNrRegs++; break; } case ExecutionNode::SUBQUERY: { - nrVarsHere[depth]++; - nrVars[depth]++; + nrRegsHere[depth]++; + nrRegs[depth]++; auto ep = static_cast(eb->getPlanNode()); varInfo.insert(make_pair(ep->_outVariable->id, - VarInfo(depth, totalNrVars))); - totalNrVars++; + VarInfo(depth, totalNrRegs))); + totalNrRegs++; break; } // TODO: potentially more cases @@ -557,7 +557,7 @@ namespace triagens { return nullptr; } - AqlItemBlock* res(new AqlItemBlock(1, _varOverview->nrVars[_depth])); + AqlItemBlock* res(new AqlItemBlock(1, _varOverview->nrRegs[_depth])); _done = true; return res; } @@ -571,7 +571,7 @@ namespace triagens { return nullptr; } - AqlItemBlock* res(new AqlItemBlock(1, _varOverview->nrVars[_depth])); + AqlItemBlock* res(new AqlItemBlock(1, _varOverview->nrRegs[_depth])); _done = true; return res; } @@ -700,16 +700,16 @@ namespace triagens { AqlItemBlock* cur = _buffer.front(); // Copy stuff from frames above: - auto res = new AqlItemBlock(1, _varOverview->nrVars[_depth]); - TRI_ASSERT(cur->getNrVars() <= res->getNrVars()); - for (VariableId i = 0; i < cur->getNrVars(); i++) { + auto res = new AqlItemBlock(1, _varOverview->nrRegs[_depth]); + TRI_ASSERT(cur->getNrRegs() <= res->getNrRegs()); + for (RegisterId i = 0; i < cur->getNrRegs(); i++) { res->setValue(0, i, cur->getValue(_pos, i)->clone()); } // The result is in the first variable of this depth, // we do not need to do a lookup in _varOverview->varInfo, - // but can just take cur->getNrVars() as index: - res->setValue(0, cur->getNrVars(), + // but can just take cur->getNrRegs() as registerId: + res->setValue(0, cur->getNrRegs(), new AqlValue( new Json(_allDocs[_posInAllDocs++]->copy()) ) ); // Advance read position: @@ -748,16 +748,16 @@ namespace triagens { size_t available = _allDocs.size() - _posInAllDocs; size_t toSend = std::min(atMost, available); - auto res = new AqlItemBlock(toSend, _varOverview->nrVars[_depth]); - TRI_ASSERT(cur->getNrVars() <= res->getNrVars()); + auto res = new AqlItemBlock(toSend, _varOverview->nrRegs[_depth]); + TRI_ASSERT(cur->getNrRegs() <= res->getNrRegs()); for (size_t j = 0; j < toSend; j++) { - for (VariableId i = 0; i < cur->getNrVars(); i++) { + for (RegisterId i = 0; i < cur->getNrRegs(); i++) { res->setValue(j, i, cur->getValue(_pos, i)->clone()); } // The result is in the first variable of this depth, // we do not need to do a lookup in _varOverview->varInfo, - // but can just take cur->getNrVars() as index: - res->setValue(j, cur->getNrVars(), + // but can just take cur->getNrRegs() as registerId: + res->setValue(j, cur->getNrRegs(), new AqlValue( new Json(_allDocs[_posInAllDocs++]->copy()) ) ); } @@ -788,6 +788,80 @@ namespace triagens { size_t _posInAllDocs; }; +// ----------------------------------------------------------------------------- +// --SECTION-- CalculationBlock +// ----------------------------------------------------------------------------- + + class CalculationBlock : public ExecutionBlock { + + public: + + CalculationBlock (CalculationNode const* en) + : ExecutionBlock(en), _expression(en->expression()), _outReg(0) { + + std::unordered_set inVars = _expression->variables(); + for (auto it = inVars.begin(); it != inVars.end(); ++it) { + _inVars.push_back(*it); + auto it2 = _varOverview->varInfo.find((*it)->id); + TRI_ASSERT(it2 != _varOverview->varInfo.end()); + _inRegs.push_back(it2->second.registerId); + } + + auto it3 = _varOverview->varInfo.find(en->_outVariable->id); + TRI_ASSERT(it3 != _varOverview->varInfo.end()); + _outReg = it3->second.registerId; + } + + ~CalculationBlock () { + } + + void doEvaluation (AqlItemBlock* result) { + + for (size_t i = 0; i < result->size(); i++) { + // Now build V8-Object as argument: + for (size_t j = 0; j < _inVars.size(); j++) { + + } + } + } + + virtual AqlItemBlock* getOne () { + AqlItemBlock* res = ExecutionBlock::getOne(); + try { + doEvaluation(res); + return res; + } + catch (...) { + delete res; + throw; + } + } + + virtual AqlItemBlock* getSome (size_t atLeast, + size_t atMost) { + AqlItemBlock* res = ExecutionBlock::getSome(atLeast, atMost); + try { + doEvaluation(res); + return res; + } + catch (...) { + delete res; + throw; + } + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief we hold a pointer to the expression in the plan +//////////////////////////////////////////////////////////////////////////////// + + private: + Expression* _expression; + std::vector _inVars; + std::vector _inRegs; + RegisterId _outReg; + + }; + // ----------------------------------------------------------------------------- // --SECTION-- ReturnBlock // ----------------------------------------------------------------------------- @@ -817,9 +891,9 @@ namespace triagens { auto ep = static_cast(getPlanNode()); auto it = _varOverview->varInfo.find(ep->_inVariable->id); TRI_ASSERT(it != _varOverview->varInfo.end()); - unsigned int index = it->second.index; - stripped->setValue(0, 0, res->getValue(0, index)); - res->setValue(0, index, nullptr); + RegisterId registerId = it->second.registerId; + stripped->setValue(0, 0, res->getValue(0, registerId)); + res->setValue(0, registerId, nullptr); delete res; return stripped; } @@ -835,11 +909,11 @@ namespace triagens { auto ep = static_cast(getPlanNode()); auto it = _varOverview->varInfo.find(ep->_inVariable->id); TRI_ASSERT(it != _varOverview->varInfo.end()); - unsigned int index = it->second.index; + RegisterId registerId = it->second.registerId; AqlItemBlock* stripped = new AqlItemBlock(res->size(), 1); for (size_t i = 0; i < res->size(); i++) { - stripped->setValue(i, 0, res->getValue(i, index)); - res->setValue(i, index, nullptr); + stripped->setValue(i, 0, res->getValue(i, registerId)); + res->setValue(i, registerId, nullptr); } delete res; return stripped; diff --git a/arangod/Aql/Types.cpp b/arangod/Aql/Types.cpp index 4517e2f913..13eb08637b 100644 --- a/arangod/Aql/Types.cpp +++ b/arangod/Aql/Types.cpp @@ -93,21 +93,21 @@ AqlItemBlock* AqlItemBlock::splice(std::vector& blocks) auto it = blocks.begin(); TRI_ASSERT(it != blocks.end()); size_t totalSize = (*it)->size(); - VariableId nrVars = (*it)->getNrVars(); + RegisterId nrRegs = (*it)->getNrVars(); while (true) { if (++it == blocks.end()) { break; } totalSize += (*it)->size(); - TRI_ASSERT((*it)->getNrVars() == nrVars); + TRI_ASSERT((*it)->getNrVars() == nrRegs); } - auto res = new AqlItemBlock(totalSize, nrVars); + auto res = new AqlItemBlock(totalSize, nrRegs); size_t pos = 0; for (it = blocks.begin(); it != blocks.end(); ++it) { for (size_t row = 0; row < (*it)->size(); ++row) { - for (VariableId col = 0; col < nrVars; ++col) { + for (RegisterId col = 0; col < nrRegs; ++col) { res->setValue(pos+row, col, (*it)->getValue(row, col)); (*it)->setValue(row, col, nullptr); } diff --git a/arangod/Aql/Types.h b/arangod/Aql/Types.h index 7e8c1deead..454615115f 100644 --- a/arangod/Aql/Types.h +++ b/arangod/Aql/Types.h @@ -41,6 +41,7 @@ namespace triagens { // --SECTION-- AqlDoc // ----------------------------------------------------------------------------- + typedef unsigned int RegisterId; class AqlItemBlock; @@ -112,15 +113,15 @@ namespace triagens { AqlValue** _data; size_t _nrItems; - VariableId _nrVars; + RegisterId _nrRegs; public: - AqlItemBlock (size_t nrItems, VariableId nrVars) - : _nrItems(nrItems), _nrVars(nrVars) { - if (nrItems > 0 && nrVars > 0) { - _data = new AqlValue* [nrItems * nrVars]; - for (size_t i = 0; i < nrItems * nrVars; i++) { + AqlItemBlock (size_t nrItems, RegisterId nrRegs) + : _nrItems(nrItems), _nrRegs(nrRegs) { + if (nrItems > 0 && nrRegs > 0) { + _data = new AqlValue* [nrItems * nrRegs]; + for (size_t i = 0; i < nrItems * nrRegs; i++) { _data[i] = nullptr; } } @@ -136,7 +137,7 @@ namespace triagens { ~AqlItemBlock () { std::unordered_set cache; if (_data != nullptr) { - for (size_t i = 0; i < _nrItems * _nrVars; i++) { + for (size_t i = 0; i < _nrItems * _nrRegs; i++) { if (_data[i] != nullptr) { auto it = cache.find(_data[i]); if (it == cache.end()) { @@ -153,12 +154,12 @@ namespace triagens { /// @brief getValue, get the value of a variable //////////////////////////////////////////////////////////////////////////////// - AqlValue* getValue (size_t index, VariableId varNr) { + AqlValue* getValue (size_t index, RegisterId varNr) { if (_data == nullptr) { return nullptr; } else { - return _data[index * _nrVars + varNr]; + return _data[index * _nrRegs + varNr]; } } @@ -166,18 +167,18 @@ namespace triagens { /// @brief setValue, set the current value of a variable or attribute //////////////////////////////////////////////////////////////////////////////// - void setValue (size_t index, VariableId varNr, AqlValue* zeug) { + void setValue (size_t index, RegisterId varNr, AqlValue* zeug) { if (_data != nullptr) { - _data[index * _nrVars + varNr] = zeug; + _data[index * _nrRegs + varNr] = zeug; } } //////////////////////////////////////////////////////////////////////////////// -/// @brief getter for _nrVars +/// @brief getter for _nrRegs //////////////////////////////////////////////////////////////////////////////// - VariableId getNrVars () { - return _nrVars; + RegisterId getNrRegs () { + return _nrRegs; } //////////////////////////////////////////////////////////////////////////////// @@ -203,18 +204,18 @@ namespace triagens { AqlItemBlock* slice (size_t from, size_t to) { TRI_ASSERT(from < to && to <= _nrItems); std::unordered_map cache; - auto res = new AqlItemBlock(to-from, _nrVars); + auto res = new AqlItemBlock(to-from, _nrRegs); for (size_t row = from; row < to; row++) { - for (VariableId col = 0; col < _nrVars; col++) { - AqlValue* a = _data[row * _nrVars + col]; + for (RegisterId col = 0; col < _nrRegs; col++) { + AqlValue* a = _data[row * _nrRegs + col]; auto it = cache.find(a); if (it == cache.end()) { AqlValue* b = a->clone(); - res->_data[(row-from) * _nrVars + col] = b; + res->_data[(row-from) * _nrRegs + col] = b; cache.insert(make_pair(a,b)); } else { - res->_data[(row-from) * _nrVars + col] = it->second; + res->_data[(row-from) * _nrRegs + col] = it->second; } } }