1
0
Fork 0

Merge branch 'aql2' of https://github.com/triAGENS/ArangoDB into aql2

This commit is contained in:
Jan Steemann 2014-08-21 15:54:48 +02:00
commit 89e74559ae
3 changed files with 101 additions and 85 deletions

View File

@ -427,6 +427,14 @@ namespace triagens {
_varUsageValid = false; _varUsageValid = false;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief can the node throw?
////////////////////////////////////////////////////////////////////////////////
virtual bool canThrow () {
return false;
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- protected functions // --SECTION-- protected functions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -646,7 +654,7 @@ namespace triagens {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief get indexes with fields <attrs> or nullptr if none exist /// @brief get vector of indexes with fields <attrs>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
vector<TRI_index_t*> getIndexes (vector<std::string> attrs) const { vector<TRI_index_t*> getIndexes (vector<std::string> attrs) const {
@ -914,24 +922,25 @@ namespace triagens {
}; };
// 3-way comparison: a return of -1 indicates that left is // 3-way comparison: a return of -1 indicates that left is
// tighter than right, 0 that they are equal, 1 that right is tighter than // tighter than right, 0 that they are equal, 1 that right is tighter than
// left. For example, (x<1) is tighter than (x<=1) and (x>1) is tighter // left. For example, (x<1) is tighter than (x<=1) and (x>1) is tighter
// than (x>=1) . . . // than (x>=1) . . .
static int CompareRangeInfoBound (RangeInfoBound const* left, RangeInfoBound const* right) { static int CompareRangeInfoBound (RangeInfoBound const* left,
if (left == nullptr) { RangeInfoBound const* right) {
return (right == nullptr ? 0 : 1); if (left == nullptr) {
} return (right == nullptr ? 0 : 1);
if (right == nullptr) { }
return -1; if (right == nullptr) {
} return -1;
}
int cmp = TRI_CompareValuesJson(left->_bound.json(), right->_bound.json()); int cmp = TRI_CompareValuesJson(left->_bound.json(), right->_bound.json());
if (cmp == 0 && (left->_include != right->_include)) { if (cmp == 0 && (left->_include != right->_include)) {
cmp = (left->_include?-1:1); cmp = (left->_include?-1:1);
} }
return cmp; return cmp;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief class to keep a vector of RangeInfos . . . /// @brief class to keep a vector of RangeInfos . . .
@ -1074,7 +1083,6 @@ static int CompareRangeInfoBound (RangeInfoBound const* left, RangeInfoBound con
} }
~IndexRangeNode () { ~IndexRangeNode () {
delete _ranges;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -1362,6 +1370,14 @@ static int CompareRangeInfoBound (RangeInfoBound const* left, RangeInfoBound con
return v; return v;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief can the node throw?
////////////////////////////////////////////////////////////////////////////////
bool canThrow () {
return _expression->canThrow();
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- private variables // --SECTION-- private variables
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -1485,6 +1501,15 @@ static int CompareRangeInfoBound (RangeInfoBound const* left, RangeInfoBound con
return v; return v;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief can the node throw?
////////////////////////////////////////////////////////////////////////////////
bool canThrow () {
std::cout << "SubqueryNode method for canThrow is not implemented!\n";
return true;
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- private variables // --SECTION-- private variables
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -947,55 +947,15 @@ void ExecutionPlan::findVarUsage () {
_varSetBy = finder._varSetBy; _varSetBy = finder._varSetBy;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief helper struct for unlinkNodes
////////////////////////////////////////////////////////////////////////////////
struct NodeUnlinker : public WalkerWorker<ExecutionNode> {
ExecutionPlan* _plan;
std::unordered_set<ExecutionNode*>& _toRemove;
NodeUnlinker (ExecutionPlan* plan,
std::unordered_set<ExecutionNode*>& toRemove)
: _plan(plan),
_toRemove(toRemove) {
}
~NodeUnlinker () {
}
void before (ExecutionNode* en) {
if (_toRemove.find(en) != _toRemove.end()) {
// Remove this node:
auto&& parents = en->getParents();
if (parents.empty()) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"Cannot remove root node of plan.");
}
else if (parents.size() > 1) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"Cannot remove node with more than one parent.");
}
else {
auto&& dep = en->getDependencies();
parents[0]->removeDependency(en);
for (auto x : dep) {
parents[0]->addDependency(x);
}
}
}
}
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief unlinkNodes, note that this does not delete the removed /// @brief unlinkNodes, note that this does not delete the removed
/// nodes and that one cannot remove the root node of the plan. /// nodes and that one cannot remove the root node of the plan.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void ExecutionPlan::unlinkNodes (std::unordered_set<ExecutionNode*>& toRemove) { void ExecutionPlan::unlinkNodes (std::unordered_set<ExecutionNode*>& toRemove) {
NodeUnlinker remover(this, toRemove); for (auto x : toRemove) {
root()->walk(&remover); unlinkNode(x);
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -1004,9 +964,22 @@ void ExecutionPlan::unlinkNodes (std::unordered_set<ExecutionNode*>& toRemove) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void ExecutionPlan::unlinkNode (ExecutionNode* node) { void ExecutionPlan::unlinkNode (ExecutionNode* node) {
std::unordered_set<ExecutionNode*> toUnlink; auto&& parents = node->getParents();
toUnlink.insert(node); if (parents.empty()) {
return unlinkNodes(toUnlink); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"Cannot unlink root node of plan.");
}
else if (parents.size() > 1) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"Cannot remove node with more than one parent.");
}
else {
auto&& dep = node->getDependencies();
parents[0]->removeDependency(node);
for (auto x : dep) {
parents[0]->addDependency(x);
}
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -1079,6 +1052,7 @@ ExecutionPlan* ExecutionPlan::clone (){
auto plan = new ExecutionPlan(); auto plan = new ExecutionPlan();
try { try {
plan->_root = _root->clone(); plan->_root = _root->clone();
plan->_nextId = _nextId;
CloneNodeAdder adder(plan); CloneNodeAdder adder(plan);
plan->_root->walk(&adder); plan->_root->walk(&adder);
plan->findVarUsage(); plan->findVarUsage();

View File

@ -271,8 +271,6 @@ class CalculationNodeFinder : public WalkerWorker<ExecutionNode> {
if (map != nullptr) { if (map != nullptr) {
// check the first components of <map> against indexes of <node> . . . // check the first components of <map> against indexes of <node> . . .
// FIXME does this need to be done like this? Couldn't we keep track
// earlier?
std::vector<std::string> attrs; std::vector<std::string> attrs;
std::vector<RangeInfo*> rangeInfo; std::vector<RangeInfo*> rangeInfo;
for (auto x : *map){ for (auto x : *map){
@ -281,27 +279,46 @@ class CalculationNodeFinder : public WalkerWorker<ExecutionNode> {
} }
std::vector<TRI_index_t*> idxs = node->getIndexes(attrs); std::vector<TRI_index_t*> idxs = node->getIndexes(attrs);
//use make one new plan for every index in <idxs> that replaces the // make one new plan for every index in <idxs> that replaces the
//enumerate collection node with a RangeIndexNode . . . // enumerate collection node with a RangeIndexNode . . .
for (auto idx: idxs) { for (auto idx: idxs) {
std::cout << "FOUND INDEX!\n"; bool stop = false;
auto newPlan = _plan->clone(); if (idx->_type == TRI_IDX_TYPE_HASH_INDEX){
ExecutionNode* newNode = nullptr; // only use a hash index if the corresponding rangeInfos are all
try{ // equalities . . .
newNode = new IndexRangeNode( newPlan->nextId(), node->vocbase(), for(auto x : rangeInfo){
node->collection(), node->outVariable(), idx, &rangeInfo); if (x->_low == nullptr || x->_high == nullptr ||
newPlan->registerNode(newNode); !TRI_CheckSameValueJson(x->_low->_bound.json(),
} x->_high->_bound.json()) || !(x->_low->_include) ||
catch (...) { !(x->_high->_include) ) {
if (newNode != nullptr) { stop = true;
delete newNode; std::cout << "not using hash index . . .\n";
break;
}
} }
delete newPlan;
throw;
} }
newPlan->replaceNode(newPlan->getNodeById(node->id()), newNode);
std::cout << newPlan->root()->toJson(TRI_UNKNOWN_MEM_ZONE, true).toString() << "\n"; if (!stop) {
_out.push_back(newPlan); std::cout << "FOUND INDEX!\n";
auto newPlan = _plan->clone();
ExecutionNode* newNode = nullptr;
try{
newNode = new IndexRangeNode( newPlan->nextId(), node->vocbase(),
node->collection(), node->outVariable(), idx, &rangeInfo);
newPlan->registerNode(newNode);
}
catch (...) {
if (newNode != nullptr) {
delete newNode;
}
delete newPlan;
throw;
}
newPlan->replaceNode(newPlan->getNodeById(node->id()), newNode);
std::cout << newPlan->root()->toJson(TRI_UNKNOWN_MEM_ZONE, false).toString()
<< "\n";
_out.push_back(newPlan);
}
} }
} }
} }