mirror of https://gitee.com/bigwinds/arangodb
now inspect sort and filter nodes
This commit is contained in:
parent
5dbf5e14e3
commit
e619ef3e4e
|
@ -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";
|
||||||
|
|
Loading…
Reference in New Issue