mirror of https://gitee.com/bigwinds/arangodb
Instanciate expressions for variable bounds.
And various cleanups.
This commit is contained in:
parent
821e9b4533
commit
31e02e42cb
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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 () {
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue