1
0
Fork 0

remove-redundant-sorts, initial

This commit is contained in:
Jan Steemann 2014-08-28 12:39:28 +02:00
parent 9d4b1b1c88
commit 2eb38c9657
9 changed files with 180 additions and 18 deletions

View File

@ -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
// -----------------------------------------------------------------------------

View File

@ -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
// -----------------------------------------------------------------------------

View File

@ -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
// -----------------------------------------------------------------------------

View File

@ -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 ();
// -----------------------------------------------------------------------------

View File

@ -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

View 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
// -----------------------------------------------------------------------------

View File

@ -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);

View File

@ -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) {

View File

@ -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: