1
0
Fork 0

Instanciate expressions for variable bounds.

And various cleanups.
This commit is contained in:
Max Neunhoeffer 2014-09-11 14:28:38 +02:00
parent 821e9b4533
commit 31e02e42cb
12 changed files with 156 additions and 58 deletions

View File

@ -30,7 +30,6 @@
#include "Aql/Ast.h"
#include "Aql/Collection.h"
#include "Aql/Executor.h"
#include "Aql/Parser.h"
#include "BasicsC/tri-strings.h"
#include "Utils/Exception.h"
#include "VocBase/collection.h"
@ -55,10 +54,8 @@ AstNode const Ast::NopNode = { NODE_TYPE_NOP };
/// @brief create the AST
////////////////////////////////////////////////////////////////////////////////
Ast::Ast (Query* query,
Parser* parser)
Ast::Ast (Query* query)
: _query(query),
_parser(parser),
_nodes(),
_scopes(),
_variables(),
@ -68,7 +65,6 @@ Ast::Ast (Query* query,
_writeCollection(nullptr) {
TRI_ASSERT(_query != nullptr);
TRI_ASSERT(_parser != nullptr);
_nodes.reserve(32);

View File

@ -43,7 +43,6 @@
namespace triagens {
namespace aql {
class Parser;
class Query;
// -----------------------------------------------------------------------------
@ -66,8 +65,7 @@ namespace triagens {
/// @brief create the AST
////////////////////////////////////////////////////////////////////////////////
Ast (Query*,
Parser*);
Ast (Query*);
////////////////////////////////////////////////////////////////////////////////
/// @brief destroy the AST
@ -603,12 +601,6 @@ namespace triagens {
Query* _query;
////////////////////////////////////////////////////////////////////////////////
/// @brief the query parser
////////////////////////////////////////////////////////////////////////////////
Parser* _parser;
////////////////////////////////////////////////////////////////////////////////
/// @brief all nodes created in the AST - will be used for freeing them later
////////////////////////////////////////////////////////////////////////////////

View File

@ -782,20 +782,66 @@ size_t EnumerateCollectionBlock::skipSome (size_t atLeast, size_t atMost) {
// -----------------------------------------------------------------------------
IndexRangeBlock::IndexRangeBlock (ExecutionEngine* engine,
IndexRangeNode const* ep)
: ExecutionBlock(engine, ep),
_collection(ep->_collection),
_posInDocs(0) {
/*
std::cout << "USING INDEX: " << ep->_index->_iid << ", " <<
TRI_TypeNameIndex(ep->_index->_type) << "\n";
IndexRangeNode const* en)
: ExecutionBlock(engine, en),
_collection(en->_collection),
_posInDocs(0),
_allBoundsConstant(true) {
/*
std::cout << "USING INDEX: " << en->_index->_iid << ", " <<
TRI_TypeNameIndex(en->_index->_type) << "\n";
*/
// TODO: detect whether all ranges are constant
// TODO: if not, instanciate expressions
std::vector<std::vector<RangeInfo>> const& orRanges = en->_ranges;
TRI_ASSERT(orRanges.size() == 1); // OR expressions not yet implemented
// Detect, whether all ranges are constant:
std::vector<RangeInfo> const& attrRanges = orRanges[0];
for (auto r : attrRanges) {
_allBoundsConstant &= r.isConstant();
}
// instanciate expressions:
auto instanciateExpression = [&] (Json const& json) -> void {
auto a = new AstNode(engine->getQuery()->ast(), json);
// all new AstNodes are registered with the Ast in the Query
auto e = new Expression(engine->getQuery()->executor(), a);
try {
_allVariableBoundExpressions.push_back(e);
}
catch (...) {
delete e;
throw;
}
};
if (! _allBoundsConstant) {
try {
for (auto r : attrRanges) {
for (auto l : r._lows) {
instanciateExpression(l.bound());
}
for (auto h : r._highs) {
instanciateExpression(h.bound());
}
}
}
catch (...) {
for (auto e : _allVariableBoundExpressions) {
delete e;
}
throw;
}
}
}
IndexRangeBlock::~IndexRangeBlock () {
// TODO: free expressions
for (auto e : _allVariableBoundExpressions) {
delete e;
}
_allVariableBoundExpressions.clear();
}
bool IndexRangeBlock::readIndex () {

View File

@ -684,6 +684,20 @@ public:
size_t _posInDocs;
////////////////////////////////////////////////////////////////////////////////
/// @brief _allBoundsConstant, this indicates whether all given bounds
/// are constant
////////////////////////////////////////////////////////////////////////////////
bool _allBoundsConstant;
////////////////////////////////////////////////////////////////////////////////
/// @brief _allBoundsConstant, this indicates whether all given bounds
/// are constant
////////////////////////////////////////////////////////////////////////////////
std::vector<Expression*> _allVariableBoundExpressions;
};
// -----------------------------------------------------------------------------

View File

@ -44,11 +44,12 @@ using namespace triagens::aql;
/// @brief create the engine
////////////////////////////////////////////////////////////////////////////////
ExecutionEngine::ExecutionEngine (AQL_TRANSACTION_V8* trx)
ExecutionEngine::ExecutionEngine (AQL_TRANSACTION_V8* trx, Query* query)
: _stats(),
_blocks(),
_root(nullptr),
_trx(trx) {
_trx(trx),
_query(query) {
_blocks.reserve(8);
}
@ -220,8 +221,9 @@ struct Instanciator : public WalkerWorker<ExecutionNode> {
////////////////////////////////////////////////////////////////////////////////
ExecutionEngine* ExecutionEngine::instanciateFromPlan (AQL_TRANSACTION_V8* trx,
Query* query,
ExecutionPlan* plan) {
auto engine = new ExecutionEngine(trx);
auto engine = new ExecutionEngine(trx, query);
try {
if (! plan->varUsageComputed()) {

View File

@ -57,7 +57,7 @@ namespace triagens {
/// @brief create the engine
////////////////////////////////////////////////////////////////////////////////
ExecutionEngine (AQL_TRANSACTION_V8* trx);
ExecutionEngine (AQL_TRANSACTION_V8* trx, Query* query);
public:
@ -78,6 +78,7 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
static ExecutionEngine* instanciateFromPlan (AQL_TRANSACTION_V8*,
Query*,
ExecutionPlan*);
////////////////////////////////////////////////////////////////////////////////
@ -97,6 +98,14 @@ namespace triagens {
return _trx;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the query
////////////////////////////////////////////////////////////////////////////////
Query* getQuery () const {
return _query;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getSome
////////////////////////////////////////////////////////////////////////////////
@ -188,6 +197,11 @@ namespace triagens {
AQL_TRANSACTION_V8* _trx;
////////////////////////////////////////////////////////////////////////////////
/// @brief a pointer to the query
////////////////////////////////////////////////////////////////////////////////
Query* _query;
};
}

View File

@ -505,7 +505,8 @@ void EnumerateCollectionNode::getIndexesForIndexRangeNode
}
}
std::vector<EnumerateCollectionNode::IndexMatch> EnumerateCollectionNode::getIndicesOrdered (IndexMatchVec &attrs) const {
std::vector<EnumerateCollectionNode::IndexMatch>
EnumerateCollectionNode::getIndicesOrdered (IndexMatchVec &attrs) const {
std::vector<IndexMatch> out;
TRI_document_collection_t* document = _collection->documentCollection();

View File

@ -880,12 +880,15 @@ namespace triagens {
TRI_ASSERT(_collection != nullptr);
TRI_ASSERT(_outVariable != nullptr);
TRI_ASSERT(_index != nullptr);
/*
std::cout << "Hallole" << std::endl;
for (auto x : ranges) {
std::cout << "Or Entry:" << std::endl;
for (auto y : x) {
std::cout << y.toString() << std::endl;
}
}
*/
}
IndexRangeNode (Ast*, basics::Json const& base);

View File

@ -786,7 +786,7 @@ int triagens::aql::useIndexRange (Optimizer* opt,
/// @brief analyse the sortnode and its calculation nodes
////////////////////////////////////////////////////////////////////////////////
class sortAnalysis {
class SortAnalysis {
using ECN = triagens::aql::EnumerateCollectionNode;
typedef std::pair<ECN::IndexMatchVec, RangeInfoVec> Range_IndexPair;
@ -807,31 +807,38 @@ public:
/// @brief constructor; fetches the referenced calculation nodes and builds
/// _sortNodeData for later use.
////////////////////////////////////////////////////////////////////////////////
sortAnalysis (SortNode * node)
: sortNodeID(node->id())
SortAnalysis (SortNode* node)
: sortNodeID(node->id())
{
auto sortParams = node->getCalcNodePairs();
for (size_t n = 0; n < sortParams.size(); n++) {
auto d = new sortNodeData;
d->ASC = sortParams[n].second;
d->calculationNodeID = sortParams[n].first->id();
try {
d->ASC = sortParams[n].second;
d->calculationNodeID = sortParams[n].first->id();
if (sortParams[n].first->getType() == EN::CALCULATION) {
auto cn = static_cast<triagens::aql::CalculationNode*>(sortParams[n].first);
auto oneSortExpression = cn->expression();
if (oneSortExpression->isAttributeAccess()) {
auto simpleExpression = oneSortExpression->getMultipleAttributes();
d->variableName = simpleExpression.first;
d->attributevec = simpleExpression.second;
if (sortParams[n].first->getType() == EN::CALCULATION) {
auto cn = static_cast<triagens::aql::CalculationNode*>(sortParams[n].first);
auto oneSortExpression = cn->expression();
if (oneSortExpression->isAttributeAccess()) {
auto simpleExpression = oneSortExpression->getMultipleAttributes();
d->variableName = simpleExpression.first;
d->attributevec = simpleExpression.second;
}
}
_sortNodeData.push_back(d);
}
catch (...) {
delete d;
throw;
}
_sortNodeData.push_back(d);
}
}
~sortAnalysis () {
~SortAnalysis () {
for (auto x : _sortNodeData){
delete x;
}
@ -840,6 +847,7 @@ public:
////////////////////////////////////////////////////////////////////////////////
/// @brief checks the whether we only have simple calculation nodes
////////////////////////////////////////////////////////////////////////////////
bool isAnalyzeable () {
if (_sortNodeData.size() == 0) {
return false;
@ -874,6 +882,7 @@ public:
/// @brief checks whether our calculation nodes reference variableName;
/// @returns pair used for further processing with the indices.
////////////////////////////////////////////////////////////////////////////////
Range_IndexPair getAttrsForVariableName (std::string &variableName) {
ECN::IndexMatchVec v;
RangeInfoVec rangeInfo;
@ -883,17 +892,22 @@ public:
return std::make_pair(v, rangeInfo); // for now, no mixed support.
}
}
// Collect the right data for the sorting:
for (size_t j = 0; j < _sortNodeData.size(); j ++) {
v.push_back(std::make_pair(_sortNodeData[j]->attributevec,
_sortNodeData[j]->ASC));
rangeInfo.push_back(std::vector<RangeInfo>());
}
// We only need one or-condition (because this is mandatory) which
// refers to 0 of the attributes:
rangeInfo.push_back(std::vector<RangeInfo>());
return std::make_pair(v, rangeInfo);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief removes the sortNode and its referenced Calculationnodes from the plan.
/// @brief removes the sortNode and its referenced Calculationnodes from
/// the plan.
////////////////////////////////////////////////////////////////////////////////
void removeSortNodeFromPlan (ExecutionPlan *newPlan) {
newPlan->unlinkNode(newPlan->getNodeById(sortNodeID));
}
@ -904,7 +918,7 @@ class sortToIndexNode : public WalkerWorker<ExecutionNode> {
Optimizer* _opt;
ExecutionPlan* _plan;
sortAnalysis* _sortNode;
SortAnalysis* _sortNode;
Optimizer::RuleLevel _level;
public:
@ -913,7 +927,7 @@ class sortToIndexNode : public WalkerWorker<ExecutionNode> {
sortToIndexNode (Optimizer* opt,
ExecutionPlan* plan,
sortAnalysis* Node,
SortAnalysis* Node,
Optimizer::RuleLevel level)
: _opt(opt),
_plan(plan),
@ -1036,7 +1050,7 @@ int triagens::aql::useIndexForSort (Optimizer* opt,
= plan->findNodesOfType(triagens::aql::ExecutionNode::SORT, true);
for (auto n : nodes) {
auto thisSortNode = static_cast<SortNode*>(n);
sortAnalysis node(thisSortNode);
SortAnalysis node(thisSortNode);
if (node.isAnalyzeable()) {
sortToIndexNode finder(opt, plan, &node, rule->level);
thisSortNode->walk(&finder);/// todo auf der dependency anfangen

View File

@ -43,7 +43,7 @@ using namespace triagens::aql;
Parser::Parser (Query* query)
: _query(query),
_ast(nullptr),
_ast(query->ast()),
_scanner(nullptr),
_buffer(query->queryString()),
_remainingLength(query->queryLength()),
@ -51,8 +51,6 @@ Parser::Parser (Query* query)
_marker(nullptr),
_stack() {
_ast = new Ast(query, this);
_stack.reserve(16);
}
@ -61,9 +59,6 @@ Parser::Parser (Query* query)
////////////////////////////////////////////////////////////////////////////////
Parser::~Parser () {
if (_ast != nullptr) {
delete _ast;
}
}
// -----------------------------------------------------------------------------

View File

@ -67,10 +67,13 @@ Query::Query (TRI_vocbase_t* vocbase,
_bindParameters(bindParameters),
_options(options),
_collections(vocbase),
_strings() {
_strings(),
_ast(nullptr) {
TRI_ASSERT(_vocbase != nullptr);
_ast = new Ast(this);
_strings.reserve(32);
}
@ -86,10 +89,12 @@ Query::Query (TRI_vocbase_t* vocbase,
_bindParameters(nullptr),
_options(nullptr),
_collections(vocbase),
_strings() {
_strings(),
_ast(nullptr) {
TRI_ASSERT(_vocbase != nullptr);
_ast = new Ast(this);
_strings.reserve(32);
}
@ -278,7 +283,7 @@ QueryResult Query::execute () {
triagens::basics::Json stats;
try {
auto engine = ExecutionEngine::instanciateFromPlan(&trx, plan);
auto engine = ExecutionEngine::instanciateFromPlan(&trx, this, plan);
try {
AqlItemBlock* value;

View File

@ -48,6 +48,7 @@ namespace triagens {
class Expression;
struct Variable;
struct AstNode;
class Ast;
// -----------------------------------------------------------------------------
// --SECTION-- public types
@ -155,6 +156,14 @@ namespace triagens {
return _queryLength;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getter for _ast
////////////////////////////////////////////////////////////////////////////////
Ast* ast () const {
return _ast;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief extract a region from the query
////////////////////////////////////////////////////////////////////////////////
@ -291,6 +300,13 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
std::vector<char const*> _strings;
////////////////////////////////////////////////////////////////////////////////
/// @brief _ast, we need an ast to manage the memory for AstNodes, even
/// if we do not have a parser, because AstNodes occur in plans and engines
////////////////////////////////////////////////////////////////////////////////
Ast* _ast;
};
}