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;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief can the node throw?
////////////////////////////////////////////////////////////////////////////////
virtual bool canThrow () {
return false;
}
// -----------------------------------------------------------------------------
// --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 {
@ -914,24 +922,25 @@ namespace triagens {
};
// 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
// left. For example, (x<1) is tighter than (x<=1) and (x>1) is tighter
// than (x>=1) . . .
static int CompareRangeInfoBound (RangeInfoBound const* left, RangeInfoBound const* right) {
if (left == nullptr) {
return (right == nullptr ? 0 : 1);
}
if (right == nullptr) {
return -1;
}
// 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
// left. For example, (x<1) is tighter than (x<=1) and (x>1) is tighter
// than (x>=1) . . .
static int CompareRangeInfoBound (RangeInfoBound const* left,
RangeInfoBound const* right) {
if (left == nullptr) {
return (right == nullptr ? 0 : 1);
}
if (right == nullptr) {
return -1;
}
int cmp = TRI_CompareValuesJson(left->_bound.json(), right->_bound.json());
if (cmp == 0 && (left->_include != right->_include)) {
cmp = (left->_include?-1:1);
}
return cmp;
};
int cmp = TRI_CompareValuesJson(left->_bound.json(), right->_bound.json());
if (cmp == 0 && (left->_include != right->_include)) {
cmp = (left->_include?-1:1);
}
return cmp;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief class to keep a vector of RangeInfos . . .
@ -1074,7 +1083,6 @@ static int CompareRangeInfoBound (RangeInfoBound const* left, RangeInfoBound con
}
~IndexRangeNode () {
delete _ranges;
}
////////////////////////////////////////////////////////////////////////////////
@ -1362,6 +1370,14 @@ static int CompareRangeInfoBound (RangeInfoBound const* left, RangeInfoBound con
return v;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief can the node throw?
////////////////////////////////////////////////////////////////////////////////
bool canThrow () {
return _expression->canThrow();
}
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
@ -1485,6 +1501,15 @@ static int CompareRangeInfoBound (RangeInfoBound const* left, RangeInfoBound con
return v;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief can the node throw?
////////////////////////////////////////////////////////////////////////////////
bool canThrow () {
std::cout << "SubqueryNode method for canThrow is not implemented!\n";
return true;
}
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------

View File

@ -947,55 +947,15 @@ void ExecutionPlan::findVarUsage () {
_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
/// nodes and that one cannot remove the root node of the plan.
////////////////////////////////////////////////////////////////////////////////
void ExecutionPlan::unlinkNodes (std::unordered_set<ExecutionNode*>& toRemove) {
NodeUnlinker remover(this, toRemove);
root()->walk(&remover);
for (auto x : toRemove) {
unlinkNode(x);
}
}
////////////////////////////////////////////////////////////////////////////////
@ -1004,9 +964,22 @@ void ExecutionPlan::unlinkNodes (std::unordered_set<ExecutionNode*>& toRemove) {
////////////////////////////////////////////////////////////////////////////////
void ExecutionPlan::unlinkNode (ExecutionNode* node) {
std::unordered_set<ExecutionNode*> toUnlink;
toUnlink.insert(node);
return unlinkNodes(toUnlink);
auto&& parents = node->getParents();
if (parents.empty()) {
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();
try {
plan->_root = _root->clone();
plan->_nextId = _nextId;
CloneNodeAdder adder(plan);
plan->_root->walk(&adder);
plan->findVarUsage();

View File

@ -271,8 +271,6 @@ class CalculationNodeFinder : public WalkerWorker<ExecutionNode> {
if (map != nullptr) {
// 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<RangeInfo*> rangeInfo;
for (auto x : *map){
@ -281,27 +279,46 @@ class CalculationNodeFinder : public WalkerWorker<ExecutionNode> {
}
std::vector<TRI_index_t*> idxs = node->getIndexes(attrs);
//use make one new plan for every index in <idxs> that replaces the
//enumerate collection node with a RangeIndexNode . . .
// make one new plan for every index in <idxs> that replaces the
// enumerate collection node with a RangeIndexNode . . .
for (auto idx: idxs) {
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;
bool stop = false;
if (idx->_type == TRI_IDX_TYPE_HASH_INDEX){
// only use a hash index if the corresponding rangeInfos are all
// equalities . . .
for(auto x : rangeInfo){
if (x->_low == nullptr || x->_high == nullptr ||
!TRI_CheckSameValueJson(x->_low->_bound.json(),
x->_high->_bound.json()) || !(x->_low->_include) ||
!(x->_high->_include) ) {
stop = true;
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";
_out.push_back(newPlan);
if (!stop) {
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);
}
}
}
}