mirror of https://gitee.com/bigwinds/arangodb
remove-redundant-sorts, initial
This commit is contained in:
parent
9d4b1b1c88
commit
2eb38c9657
|
@ -814,6 +814,31 @@ void AstNode::append (triagens::basics::StringBuffer* buffer) const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief stringify a node
|
||||
/// note that currently stringification is only supported for certain node types
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string AstNode::stringify () const {
|
||||
switch (type) {
|
||||
case NODE_TYPE_ATTRIBUTE_ACCESS: {
|
||||
auto member = getMember(0);
|
||||
return member->stringify() + std::string(".") + getStringValue();
|
||||
}
|
||||
|
||||
case NODE_TYPE_REFERENCE: {
|
||||
auto variable = static_cast<Variable*>(getData());
|
||||
TRI_ASSERT(variable != nullptr);
|
||||
return variable->name;
|
||||
}
|
||||
|
||||
default: {
|
||||
}
|
||||
}
|
||||
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "stringification not supported for node type");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -493,6 +493,13 @@ namespace triagens {
|
|||
|
||||
void append (triagens::basics::StringBuffer*) const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief stringify a node
|
||||
/// note that currently stringification is only supported for certain node types
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string stringify () const;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "Aql/ExecutionNode.h"
|
||||
#include "Aql/Collection.h"
|
||||
#include "Aql/ExecutionPlan.h"
|
||||
#include "Aql/WalkerWorker.h"
|
||||
#include "Aql/Ast.h"
|
||||
|
||||
|
@ -70,7 +71,7 @@ std::unordered_map<int, std::string const> const ExecutionNode::TypeNames{
|
|||
/// @brief returns the type name of the node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const std::string& ExecutionNode::getTypeString () const {
|
||||
std::string const& ExecutionNode::getTypeString () const {
|
||||
auto it = TypeNames.find(static_cast<int>(getType()));
|
||||
if (it != TypeNames.end()) {
|
||||
return (*it).second;
|
||||
|
@ -918,6 +919,44 @@ std::vector<std::pair<ExecutionNode*, bool>> SortNode::getCalcNodePairs ()
|
|||
return findExp._myVars;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns all sort information
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SortInformation SortNode::getSortInformation (ExecutionPlan* plan) const {
|
||||
SortInformation result;
|
||||
|
||||
auto elements = getElements();
|
||||
for (auto it = elements.begin(); it != elements.end(); ++it) {
|
||||
auto variable = (*it).first;
|
||||
TRI_ASSERT(variable != nullptr);
|
||||
auto setter = plan->getVarSetBy(variable->id);
|
||||
|
||||
if (setter == nullptr) {
|
||||
result.isValid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (setter->getType() == ExecutionNode::CALCULATION) {
|
||||
// variable introduced by a calculation
|
||||
auto expression = static_cast<CalculationNode*>(setter)->expression();
|
||||
|
||||
if (! expression->isAttributeAccess() &&
|
||||
! expression->isReference()) {
|
||||
result.isComplex = true;
|
||||
break;
|
||||
}
|
||||
|
||||
result.criteria.emplace_back(std::make_tuple(setter, expression->stringify(), (*it).second));
|
||||
}
|
||||
else {
|
||||
result.criteria.emplace_back(std::make_tuple(setter, variable->name, (*it).second));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- methods of AggregateNode
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -154,7 +154,7 @@ namespace triagens {
|
|||
/// @brief return the type name of the node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const std::string &getTypeString () const;
|
||||
std::string const& getTypeString () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks whether we know a type of this kind; throws exception if not.
|
||||
|
@ -1413,6 +1413,20 @@ namespace triagens {
|
|||
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- struct SortInformation
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief this is an auxilliary struct for processed sort criteria information
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct SortInformation {
|
||||
std::vector<std::tuple<ExecutionNode const*, std::string, bool>> criteria;
|
||||
bool isValid = true;
|
||||
bool isComplex = false;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class SortNode
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -1493,10 +1507,16 @@ namespace triagens {
|
|||
/// @brief get Variables Used Here including ASC/DESC
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<std::pair<Variable const*, bool>> getElements () {
|
||||
std::vector<std::pair<Variable const*, bool>> getElements () const {
|
||||
return _elements;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns all sort information
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SortInformation getSortInformation (ExecutionPlan*) const;
|
||||
|
||||
std::vector<std::pair<ExecutionNode*, bool>> getCalcNodePairs ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -347,14 +347,11 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check whether this is a simple access to a variable with n attributes.
|
||||
/// @brief check whether this is an attribute access of any degree (e.g. a.b,
|
||||
/// a.b.c, ...)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Expression::isMultipleAttributeAccess () const {
|
||||
if (!isSimple()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Expression::isAttributeAccess () const {
|
||||
auto expNode = _node;
|
||||
|
||||
if (expNode->type != triagens::aql::NODE_TYPE_ATTRIBUTE_ACCESS) {
|
||||
|
@ -362,15 +359,23 @@ bool Expression::isMultipleAttributeAccess () const {
|
|||
}
|
||||
|
||||
while (expNode->type == triagens::aql::NODE_TYPE_ATTRIBUTE_ACCESS) {
|
||||
expNode = expNode->getMember (0);
|
||||
expNode = expNode->getMember(0);
|
||||
}
|
||||
|
||||
return (expNode->type == triagens::aql::NODE_TYPE_REFERENCE);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check whether this is a reference access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Expression::isReference () const {
|
||||
return (_node->type == triagens::aql::NODE_TYPE_REFERENCE);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief this gives you ("variable.access", "Reference")
|
||||
/// call isSimpleAccessReference in advance to enshure no exceptions.
|
||||
/// call isSimpleAccessReference in advance to ensure no exceptions.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::pair<std::string, std::string> Expression::getMultipleAttributes() const {
|
||||
if (!isSimple()) {
|
||||
|
@ -411,6 +416,14 @@ std::pair<std::string, std::string> Expression::getMultipleAttributes() const {
|
|||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief stringify an expression
|
||||
/// note that currently stringification is only supported for certain node types
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string Expression::stringify () const {
|
||||
return _node->stringify();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
|
|
|
@ -151,18 +151,32 @@ namespace triagens {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check whether this is a simple access to a variable with n attributes.
|
||||
/// @brief check whether this is an attribute access of any degree (e.g. a.b,
|
||||
/// a.b.c, ...)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool isMultipleAttributeAccess () const;
|
||||
bool isAttributeAccess () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check whether this is only a reference access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool isReference () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief this gives you ("variable.access", "Reference")
|
||||
/// call isSimpleAccessReference in advance to enshure no exceptions.
|
||||
/// call isSimpleAccessReference in advance to ensure no exceptions.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::pair<std::string, std::string> getMultipleAttributes() const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief stringify an expression
|
||||
/// note that currently stringification is only supported for certain node types
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string stringify () const;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -170,10 +170,14 @@ void Optimizer::setupRules () {
|
|||
TRI_ASSERT(_rules.empty());
|
||||
|
||||
// List all the rules in the system here:
|
||||
// lower level values mean earlier rule execution
|
||||
// if two rules have the same level value, they will be executed in declaration order
|
||||
|
||||
// try to find sort blocks which are superseeded by indexes
|
||||
registerRule("use-index-for-sort", useIndexForSort, 2000);
|
||||
|
||||
|
||||
// remove redundant sort blocks
|
||||
registerRule("remove-redundant-sorts", removeRedundantSorts, 1000);
|
||||
|
||||
// try to find a filter after an enumerate collection and find an index . . .
|
||||
registerRule("use-index-range", useIndexRange, 999);
|
||||
|
|
|
@ -49,6 +49,38 @@ int triagens::aql::dummyRule (Optimizer*,
|
|||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remove redundant sorts
|
||||
/// this rule modifies the plan in place:
|
||||
/// - sorts that are covered by earlier sorts will be removed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int triagens::aql::removeRedundantSorts (Optimizer* opt,
|
||||
ExecutionPlan* plan,
|
||||
int level,
|
||||
Optimizer::PlanList& out) {
|
||||
// should we enter subqueries??
|
||||
std::vector<ExecutionNode*> nodes = plan->findNodesOfType(triagens::aql::ExecutionNode::SORT, true);
|
||||
|
||||
for (auto n : nodes) {
|
||||
auto sortInfo = static_cast<SortNode*>(n)->getSortInformation(plan);
|
||||
|
||||
if (sortInfo.isValid) {
|
||||
/*
|
||||
TODO: finalize
|
||||
std::cout << "FOUND SORT:\n";
|
||||
for (auto it = sortInfo.criteria.begin(); it != sortInfo.criteria.end(); ++it) {
|
||||
std::cout << "- " << std::get<1>(*it) << ", " << std::get<2>(*it) << "\n";
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
out.push_back(plan, level);
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remove all unnecessary filters
|
||||
/// this rule modifies the plan in place:
|
||||
|
@ -61,6 +93,7 @@ int triagens::aql::removeUnnecessaryFiltersRule (Optimizer* opt,
|
|||
int level,
|
||||
Optimizer::PlanList& out) {
|
||||
std::unordered_set<ExecutionNode*> toUnlink;
|
||||
// should we enter subqueries??
|
||||
std::vector<ExecutionNode*> nodes = plan->findNodesOfType(triagens::aql::ExecutionNode::FILTER, true);
|
||||
|
||||
for (auto n : nodes) {
|
||||
|
@ -594,11 +627,11 @@ public:
|
|||
d->ASC = sortParams[n].second;
|
||||
d->calculationNodeID = sortParams[n].first->id();
|
||||
|
||||
if (sortParams[n].first->getType() == EN::CALCULATION) {
|
||||
if (sortParams[n].first->getType() == EN::CALCULATION) {
|
||||
auto cn = static_cast<triagens::aql::CalculationNode*>(sortParams[n].first);
|
||||
auto oneSortExpression = cn->expression();
|
||||
|
||||
if (oneSortExpression->isMultipleAttributeAccess()) {
|
||||
if (oneSortExpression->isAttributeAccess()) {
|
||||
auto simpleExpression = oneSortExpression->getMultipleAttributes();
|
||||
d->variableName = simpleExpression.first;
|
||||
d->attributevec = simpleExpression.second;
|
||||
|
@ -813,7 +846,6 @@ int triagens::aql::useIndexForSort (Optimizer* opt,
|
|||
ExecutionPlan* plan,
|
||||
int level,
|
||||
Optimizer::PlanList& out) {
|
||||
std::cout << plan->toJson(TRI_UNKNOWN_MEM_ZONE, false).toString() << "\n";
|
||||
std::vector<ExecutionNode*> nodes
|
||||
= plan->findNodesOfType(triagens::aql::ExecutionNode::SORT, true);
|
||||
for (auto n : nodes) {
|
||||
|
|
|
@ -46,6 +46,14 @@ namespace triagens {
|
|||
|
||||
int dummyRule (Optimizer*, ExecutionPlan*, int level, Optimizer::PlanList&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remove redundant sorts
|
||||
/// this rule modifies the plan in place:
|
||||
/// - sorts that are covered by earlier sorts will be removed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int removeRedundantSorts (Optimizer*, ExecutionPlan*, int level, Optimizer::PlanList&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remove all unnecessary filters
|
||||
/// this rule modifies the plan in place:
|
||||
|
|
Loading…
Reference in New Issue