mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'aql2' of https://github.com/triAGENS/ArangoDB into aql2
This commit is contained in:
commit
89e74559ae
|
@ -427,6 +427,14 @@ namespace triagens {
|
||||||
_varUsageValid = false;
|
_varUsageValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief can the node throw?
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
virtual bool canThrow () {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- protected functions
|
// --SECTION-- protected functions
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -646,7 +654,7 @@ namespace triagens {
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief get indexes with fields <attrs> or nullptr if none exist
|
/// @brief get vector of indexes with fields <attrs>
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
vector<TRI_index_t*> getIndexes (vector<std::string> attrs) const {
|
vector<TRI_index_t*> getIndexes (vector<std::string> attrs) const {
|
||||||
|
@ -914,24 +922,25 @@ namespace triagens {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 3-way comparison: a return of -1 indicates that left is
|
// 3-way comparison: a return of -1 indicates that left is
|
||||||
// tighter than right, 0 that they are equal, 1 that right is tighter than
|
// tighter than right, 0 that they are equal, 1 that right is tighter than
|
||||||
// left. For example, (x<1) is tighter than (x<=1) and (x>1) is tighter
|
// left. For example, (x<1) is tighter than (x<=1) and (x>1) is tighter
|
||||||
// than (x>=1) . . .
|
// than (x>=1) . . .
|
||||||
static int CompareRangeInfoBound (RangeInfoBound const* left, RangeInfoBound const* right) {
|
static int CompareRangeInfoBound (RangeInfoBound const* left,
|
||||||
if (left == nullptr) {
|
RangeInfoBound const* right) {
|
||||||
return (right == nullptr ? 0 : 1);
|
if (left == nullptr) {
|
||||||
}
|
return (right == nullptr ? 0 : 1);
|
||||||
if (right == nullptr) {
|
}
|
||||||
return -1;
|
if (right == nullptr) {
|
||||||
}
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int cmp = TRI_CompareValuesJson(left->_bound.json(), right->_bound.json());
|
int cmp = TRI_CompareValuesJson(left->_bound.json(), right->_bound.json());
|
||||||
if (cmp == 0 && (left->_include != right->_include)) {
|
if (cmp == 0 && (left->_include != right->_include)) {
|
||||||
cmp = (left->_include?-1:1);
|
cmp = (left->_include?-1:1);
|
||||||
}
|
}
|
||||||
return cmp;
|
return cmp;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief class to keep a vector of RangeInfos . . .
|
/// @brief class to keep a vector of RangeInfos . . .
|
||||||
|
@ -1074,7 +1083,6 @@ static int CompareRangeInfoBound (RangeInfoBound const* left, RangeInfoBound con
|
||||||
}
|
}
|
||||||
|
|
||||||
~IndexRangeNode () {
|
~IndexRangeNode () {
|
||||||
delete _ranges;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1362,6 +1370,14 @@ static int CompareRangeInfoBound (RangeInfoBound const* left, RangeInfoBound con
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief can the node throw?
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool canThrow () {
|
||||||
|
return _expression->canThrow();
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- private variables
|
// --SECTION-- private variables
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -1485,6 +1501,15 @@ static int CompareRangeInfoBound (RangeInfoBound const* left, RangeInfoBound con
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief can the node throw?
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool canThrow () {
|
||||||
|
std::cout << "SubqueryNode method for canThrow is not implemented!\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- private variables
|
// --SECTION-- private variables
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -947,55 +947,15 @@ void ExecutionPlan::findVarUsage () {
|
||||||
_varSetBy = finder._varSetBy;
|
_varSetBy = finder._varSetBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief helper struct for unlinkNodes
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct NodeUnlinker : public WalkerWorker<ExecutionNode> {
|
|
||||||
|
|
||||||
ExecutionPlan* _plan;
|
|
||||||
std::unordered_set<ExecutionNode*>& _toRemove;
|
|
||||||
|
|
||||||
NodeUnlinker (ExecutionPlan* plan,
|
|
||||||
std::unordered_set<ExecutionNode*>& toRemove)
|
|
||||||
: _plan(plan),
|
|
||||||
_toRemove(toRemove) {
|
|
||||||
}
|
|
||||||
|
|
||||||
~NodeUnlinker () {
|
|
||||||
}
|
|
||||||
|
|
||||||
void before (ExecutionNode* en) {
|
|
||||||
if (_toRemove.find(en) != _toRemove.end()) {
|
|
||||||
// Remove this node:
|
|
||||||
auto&& parents = en->getParents();
|
|
||||||
if (parents.empty()) {
|
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
|
||||||
"Cannot remove root node of plan.");
|
|
||||||
}
|
|
||||||
else if (parents.size() > 1) {
|
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
|
||||||
"Cannot remove node with more than one parent.");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
auto&& dep = en->getDependencies();
|
|
||||||
parents[0]->removeDependency(en);
|
|
||||||
for (auto x : dep) {
|
|
||||||
parents[0]->addDependency(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief unlinkNodes, note that this does not delete the removed
|
/// @brief unlinkNodes, note that this does not delete the removed
|
||||||
/// nodes and that one cannot remove the root node of the plan.
|
/// nodes and that one cannot remove the root node of the plan.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void ExecutionPlan::unlinkNodes (std::unordered_set<ExecutionNode*>& toRemove) {
|
void ExecutionPlan::unlinkNodes (std::unordered_set<ExecutionNode*>& toRemove) {
|
||||||
NodeUnlinker remover(this, toRemove);
|
for (auto x : toRemove) {
|
||||||
root()->walk(&remover);
|
unlinkNode(x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1004,9 +964,22 @@ void ExecutionPlan::unlinkNodes (std::unordered_set<ExecutionNode*>& toRemove) {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void ExecutionPlan::unlinkNode (ExecutionNode* node) {
|
void ExecutionPlan::unlinkNode (ExecutionNode* node) {
|
||||||
std::unordered_set<ExecutionNode*> toUnlink;
|
auto&& parents = node->getParents();
|
||||||
toUnlink.insert(node);
|
if (parents.empty()) {
|
||||||
return unlinkNodes(toUnlink);
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||||
|
"Cannot unlink root node of plan.");
|
||||||
|
}
|
||||||
|
else if (parents.size() > 1) {
|
||||||
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||||
|
"Cannot remove node with more than one parent.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto&& dep = node->getDependencies();
|
||||||
|
parents[0]->removeDependency(node);
|
||||||
|
for (auto x : dep) {
|
||||||
|
parents[0]->addDependency(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1079,6 +1052,7 @@ ExecutionPlan* ExecutionPlan::clone (){
|
||||||
auto plan = new ExecutionPlan();
|
auto plan = new ExecutionPlan();
|
||||||
try {
|
try {
|
||||||
plan->_root = _root->clone();
|
plan->_root = _root->clone();
|
||||||
|
plan->_nextId = _nextId;
|
||||||
CloneNodeAdder adder(plan);
|
CloneNodeAdder adder(plan);
|
||||||
plan->_root->walk(&adder);
|
plan->_root->walk(&adder);
|
||||||
plan->findVarUsage();
|
plan->findVarUsage();
|
||||||
|
|
|
@ -271,8 +271,6 @@ class CalculationNodeFinder : public WalkerWorker<ExecutionNode> {
|
||||||
|
|
||||||
if (map != nullptr) {
|
if (map != nullptr) {
|
||||||
// check the first components of <map> against indexes of <node> . . .
|
// check the first components of <map> against indexes of <node> . . .
|
||||||
// FIXME does this need to be done like this? Couldn't we keep track
|
|
||||||
// earlier?
|
|
||||||
std::vector<std::string> attrs;
|
std::vector<std::string> attrs;
|
||||||
std::vector<RangeInfo*> rangeInfo;
|
std::vector<RangeInfo*> rangeInfo;
|
||||||
for (auto x : *map){
|
for (auto x : *map){
|
||||||
|
@ -281,27 +279,46 @@ class CalculationNodeFinder : public WalkerWorker<ExecutionNode> {
|
||||||
}
|
}
|
||||||
std::vector<TRI_index_t*> idxs = node->getIndexes(attrs);
|
std::vector<TRI_index_t*> idxs = node->getIndexes(attrs);
|
||||||
|
|
||||||
//use make one new plan for every index in <idxs> that replaces the
|
// make one new plan for every index in <idxs> that replaces the
|
||||||
//enumerate collection node with a RangeIndexNode . . .
|
// enumerate collection node with a RangeIndexNode . . .
|
||||||
for (auto idx: idxs) {
|
for (auto idx: idxs) {
|
||||||
std::cout << "FOUND INDEX!\n";
|
bool stop = false;
|
||||||
auto newPlan = _plan->clone();
|
if (idx->_type == TRI_IDX_TYPE_HASH_INDEX){
|
||||||
ExecutionNode* newNode = nullptr;
|
// only use a hash index if the corresponding rangeInfos are all
|
||||||
try{
|
// equalities . . .
|
||||||
newNode = new IndexRangeNode( newPlan->nextId(), node->vocbase(),
|
for(auto x : rangeInfo){
|
||||||
node->collection(), node->outVariable(), idx, &rangeInfo);
|
if (x->_low == nullptr || x->_high == nullptr ||
|
||||||
newPlan->registerNode(newNode);
|
!TRI_CheckSameValueJson(x->_low->_bound.json(),
|
||||||
}
|
x->_high->_bound.json()) || !(x->_low->_include) ||
|
||||||
catch (...) {
|
!(x->_high->_include) ) {
|
||||||
if (newNode != nullptr) {
|
stop = true;
|
||||||
delete newNode;
|
std::cout << "not using hash index . . .\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
delete newPlan;
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
newPlan->replaceNode(newPlan->getNodeById(node->id()), newNode);
|
|
||||||
std::cout << newPlan->root()->toJson(TRI_UNKNOWN_MEM_ZONE, true).toString() << "\n";
|
if (!stop) {
|
||||||
_out.push_back(newPlan);
|
std::cout << "FOUND INDEX!\n";
|
||||||
|
auto newPlan = _plan->clone();
|
||||||
|
ExecutionNode* newNode = nullptr;
|
||||||
|
try{
|
||||||
|
newNode = new IndexRangeNode( newPlan->nextId(), node->vocbase(),
|
||||||
|
node->collection(), node->outVariable(), idx, &rangeInfo);
|
||||||
|
newPlan->registerNode(newNode);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
if (newNode != nullptr) {
|
||||||
|
delete newNode;
|
||||||
|
}
|
||||||
|
delete newPlan;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
newPlan->replaceNode(newPlan->getNodeById(node->id()), newNode);
|
||||||
|
std::cout << newPlan->root()->toJson(TRI_UNKNOWN_MEM_ZONE, false).toString()
|
||||||
|
<< "\n";
|
||||||
|
_out.push_back(newPlan);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue