1
0
Fork 0

now inspect sort and filter nodes

This commit is contained in:
Jan Christoph Uhde 2016-12-01 12:21:51 +01:00
parent 5dbf5e14e3
commit e619ef3e4e
1 changed files with 71 additions and 45 deletions

View File

@ -3959,6 +3959,9 @@ std::unique_ptr<Condition> buildGeoCondition(ExecutionPlan* plan, GeoIndexInfo&
return condition; return condition;
} }
// GEO RULES //////////////////////////////////////////////////////////////////
// TODO - remove debug code // TODO - remove debug code
#ifdef OBIDEBUG #ifdef OBIDEBUG
#define OBILEVEL ERR #define OBILEVEL ERR
@ -4089,70 +4092,82 @@ bool applyGeoOptimization(bool near, ExecutionPlan* plan, ExecutionNode* node, A
}; };
AstNode const* identifyGeoOptimizationCandidate(bool sort, ExecutionPlan* plan, ExecutionNode* n){ AstNode const* identifyGeoOptimizationCandidate(ExecutionNode::NodeType type, ExecutionPlan* plan, ExecutionNode* n){
if(sort){ ExecutionNode* setter = nullptr;
auto node = static_cast<SortNode*>(n);
auto const& elements = node->getElements();
// we're looking for "SORT DISTANCE(x,y,a,b) ASC", which has just one sort criterion switch(type){
if ( !(elements.size() == 1 && elements[0].second)) { case EN::SORT: {
return nullptr; auto node = static_cast<SortNode*>(n);
auto const& elements = node->getElements();
// we're looking for "SORT DISTANCE(x,y,a,b) ASC", which has just one sort criterion
if ( !(elements.size() == 1 && elements[0].second)) {
return nullptr;
}
//variable of sort expression
auto const variable = elements[0].first;
TRI_ASSERT(variable != nullptr);
//// find the expression that is bound to the variable
// get the expression node that holds the cacluation
setter = plan->getVarSetBy(variable->id);
} }
break;
//variable of sort expression case EN::FILTER: {
auto const variable = elements[0].first; auto node = static_cast<FilterNode*>(n);
TRI_ASSERT(variable != nullptr);
//// find the expression that is bound to the variable // filter nodes always have one input variable
// get the expression node that holds the cacluation auto varsUsedHere = node->getVariablesUsedHere();
auto setter = plan->getVarSetBy(variable->id); TRI_ASSERT(varsUsedHere.size() == 1);
if (setter == nullptr || setter->getType() != EN::CALCULATION) {
return nullptr; // now check who introduced our variable
auto variable = varsUsedHere[0];
setter = plan->getVarSetBy(variable->id);
} }
break;
// downcast to calculation node and get expression default:
auto cn = static_cast<CalculationNode*>(setter);
auto const expression = cn->expression();
// the expression must exist and it must be a function call
if (expression == nullptr || expression->node() == nullptr ||
expression->node()->type != NODE_TYPE_FCALL) {
// not the right type of node
return nullptr; return nullptr;
} }
//get the ast node of the expression if (setter == nullptr || setter->getType() != EN::CALCULATION) {
AstNode const* funcNode = expression->node(); return nullptr;
auto func = static_cast<Function const*>(funcNode->getData()); }
// downcast to calculation node and get expression
auto cn = static_cast<CalculationNode*>(setter);
auto const expression = cn->expression();
// we're looking for "DISTANCE()", which is a function call // the expression must exist and it must be a function call
// with an empty parameters array if (expression == nullptr || expression->node() == nullptr ||
if ( func->externalName != "DISTANCE" || funcNode->numMembers() != 1 ) { expression->node()->type != NODE_TYPE_FCALL) {
return nullptr; // not the right type of node
}
return funcNode;
} else {
return nullptr; return nullptr;
} }
//get the ast node of the expression
AstNode const* funcNode = expression->node();
auto func = static_cast<Function const*>(funcNode->getData());
// we're looking for "DISTANCE()", which is a function call
// with an empty parameters array
if ( func->externalName != "DISTANCE" || funcNode->numMembers() != 1 ) {
return nullptr;
}
return funcNode;
return nullptr;
}; };
void checkNodesForGeoOptimization(ExecutionNode::NodeType type, ExecutionPlan* plan, bool& modified){
void arangodb::aql::optimizeGeoIndexRule(Optimizer* opt,
ExecutionPlan* plan,
Optimizer::Rule const* rule) {
LOG(OBILEVEL) << "ENTER GEO RULE";
SmallVector<ExecutionNode*>::allocator_type::arena_type a; SmallVector<ExecutionNode*>::allocator_type::arena_type a;
SmallVector<ExecutionNode*> nodes{a}; SmallVector<ExecutionNode*> nodes{a};
bool modified = false;
plan->findNodesOfType(nodes, EN::SORT, true); plan->findNodesOfType(nodes, EN::SORT, true);
for (auto const& n : nodes) { for (auto const& n : nodes) {
auto funcNode = identifyGeoOptimizationCandidate(true, plan, n); auto funcNode = identifyGeoOptimizationCandidate(EN::SORT, plan, n);
if(!funcNode){ if(!funcNode){
continue; continue;
} }
@ -4161,6 +4176,17 @@ void arangodb::aql::optimizeGeoIndexRule(Optimizer* opt,
modified = true; modified = true;
} }
} }
}
void arangodb::aql::optimizeGeoIndexRule(Optimizer* opt,
ExecutionPlan* plan,
Optimizer::Rule const* rule) {
LOG(OBILEVEL) << "ENTER GEO RULE";
bool modified = false;
checkNodesForGeoOptimization(EN::SORT, plan, modified);
checkNodesForGeoOptimization(EN::FILTER, plan, modified);
opt->addPlan(plan, rule, modified); opt->addPlan(plan, rule, modified);
LOG(OBILEVEL) << "EXIT GEO RULE"; LOG(OBILEVEL) << "EXIT GEO RULE";