mirror of https://gitee.com/bigwinds/arangodb
more robust logic
This commit is contained in:
parent
02b8bd6b91
commit
b9dc309bc2
|
@ -816,7 +816,7 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
auto node = static_cast<CalculationNode*>(en);
|
||||
std::string attr;
|
||||
Variable const* enumCollVar = nullptr;
|
||||
buildRangeInfo(node->expression()->node(), enumCollVar, attr, false);
|
||||
buildRangeInfo(node->expression()->node(), enumCollVar, attr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1110,11 +1110,10 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void buildRangeInfo (AstNode const* node,
|
||||
void findVarAndAttr (AstNode const* node,
|
||||
Variable const*& enumCollVar,
|
||||
std::string& attr,
|
||||
bool isOrCondition) {
|
||||
|
||||
std::string& attr) {
|
||||
|
||||
if (node->type == NODE_TYPE_REFERENCE) {
|
||||
auto x = static_cast<Variable*>(node->getData());
|
||||
auto setter = _plan->getVarSetBy(x->id);
|
||||
|
@ -1126,7 +1125,7 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
}
|
||||
|
||||
if (node->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
|
||||
buildRangeInfo(node->getMember(0), enumCollVar, attr, isOrCondition);
|
||||
buildRangeInfo(node->getMember(0), enumCollVar, attr);
|
||||
|
||||
if (enumCollVar != nullptr) {
|
||||
char const* attributeName = node->getStringValue();
|
||||
|
@ -1135,12 +1134,20 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RangeInfoMapVec buildRangeInfo (AstNode const* node,
|
||||
Variable const*& enumCollVar,
|
||||
std::string& attr) {
|
||||
|
||||
|
||||
if (node->type == NODE_TYPE_OPERATOR_BINARY_EQ) {
|
||||
auto lhs = node->getMember(0);
|
||||
auto rhs = node->getMember(1);
|
||||
RangeInfoMap rim;
|
||||
if (rhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
|
||||
buildRangeInfo(rhs, enumCollVar, attr, isOrCondition);
|
||||
findVarAndAttr(rhs, enumCollVar, attr);
|
||||
if (enumCollVar != nullptr) {
|
||||
std::unordered_set<Variable*> varsUsed
|
||||
= Ast::getReferencedVariables(lhs);
|
||||
|
@ -1148,19 +1155,20 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
== varsUsed.end()) {
|
||||
// Found a multiple attribute access of a variable and an
|
||||
// expression which does not involve that variable:
|
||||
insert(enumCollVar->name,
|
||||
attr.substr(0, attr.size() - 1),
|
||||
RangeInfoBound(lhs, true),
|
||||
RangeInfoBound(lhs, true),
|
||||
true,
|
||||
isOrCondition);
|
||||
|
||||
rim.insert(enumCollVar->name,
|
||||
attr.substr(0, attr.size() - 1),
|
||||
RangeInfoBound(lhs, true),
|
||||
RangeInfoBound(lhs, true),
|
||||
true);
|
||||
|
||||
enumCollVar = nullptr;
|
||||
attr.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
|
||||
buildRangeInfo(lhs, enumCollVar, attr, isOrCondition);
|
||||
findVarAndAttr(rhs, enumCollVar, attr);
|
||||
if (enumCollVar != nullptr) {
|
||||
std::unordered_set<Variable*> varsUsed
|
||||
= Ast::getReferencedVariables(rhs);
|
||||
|
@ -1168,18 +1176,18 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
== varsUsed.end()) {
|
||||
// Found a multiple attribute access of a variable and an
|
||||
// expression which does not involve that variable:
|
||||
insert(enumCollVar->name,
|
||||
attr.substr(0, attr.size() - 1),
|
||||
RangeInfoBound(rhs, true),
|
||||
RangeInfoBound(rhs, true),
|
||||
true,
|
||||
isOrCondition);
|
||||
rim.insert(enumCollVar->name,
|
||||
attr.substr(0, attr.size() - 1),
|
||||
RangeInfoBound(rhs, true),
|
||||
RangeInfoBound(rhs, true),
|
||||
true,
|
||||
isOrCondition);
|
||||
enumCollVar = nullptr;
|
||||
attr.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
return RangeInfoMapVec(rim);
|
||||
}
|
||||
|
||||
if (node->type == NODE_TYPE_OPERATOR_BINARY_LT ||
|
||||
|
@ -1187,6 +1195,7 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
node->type == NODE_TYPE_OPERATOR_BINARY_LE ||
|
||||
node->type == NODE_TYPE_OPERATOR_BINARY_GE) {
|
||||
|
||||
RangeInfoMap rim;
|
||||
bool include = (node->type == NODE_TYPE_OPERATOR_BINARY_LE ||
|
||||
node->type == NODE_TYPE_OPERATOR_BINARY_GE);
|
||||
|
||||
|
@ -1197,7 +1206,7 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
// Attribute access on the right:
|
||||
// First find out whether there is a multiple attribute access
|
||||
// of a variable on the right:
|
||||
buildRangeInfo(rhs, enumCollVar, attr, isOrCondition);
|
||||
findVarAndAttr(rhs, enumCollVar, attr);
|
||||
if (enumCollVar != nullptr) {
|
||||
RangeInfoBound low;
|
||||
RangeInfoBound high;
|
||||
|
@ -1211,12 +1220,11 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
low.assign(lhs, include);
|
||||
}
|
||||
|
||||
insert(enumCollVar->name,
|
||||
attr.substr(0, attr.size() - 1),
|
||||
low,
|
||||
high,
|
||||
false,
|
||||
isOrCondition);
|
||||
rim.insert(enumCollVar->name,
|
||||
attr.substr(0, attr.size() - 1),
|
||||
low,
|
||||
high,
|
||||
false);
|
||||
|
||||
enumCollVar = nullptr;
|
||||
attr.clear();
|
||||
|
@ -1227,7 +1235,7 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
// Attribute access on the left:
|
||||
// First find out whether there is a multiple attribute access
|
||||
// of a variable on the left:
|
||||
buildRangeInfo(lhs, enumCollVar, attr, isOrCondition);
|
||||
findVarAndAttr(lhs, enumCollVar, attr);
|
||||
if (enumCollVar != nullptr) {
|
||||
RangeInfoBound low;
|
||||
RangeInfoBound high;
|
||||
|
@ -1241,31 +1249,31 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
high.assign(rhs, include);
|
||||
}
|
||||
|
||||
insert(enumCollVar->name,
|
||||
attr.substr(0, attr.size() - 1),
|
||||
low,
|
||||
high,
|
||||
false,
|
||||
isOrCondition);
|
||||
rim.insert(enumCollVar->name,
|
||||
attr.substr(0, attr.size() - 1),
|
||||
low,
|
||||
high,
|
||||
false);
|
||||
|
||||
enumCollVar = nullptr;
|
||||
attr.clear();
|
||||
}
|
||||
}
|
||||
return;
|
||||
return RangeInfoMapVec(rim);
|
||||
}
|
||||
|
||||
if (node->type == NODE_TYPE_OPERATOR_BINARY_AND) {
|
||||
buildRangeInfo(node->getMember(0), enumCollVar, attr, false);
|
||||
buildRangeInfo(node->getMember(1), enumCollVar, attr, false);
|
||||
return;
|
||||
// distribute AND into OR
|
||||
return andCombineRangeInfoMapVecs(buildRangeInfo(node->getMember(0), enumCollVar, attr),
|
||||
buildRangeInfo(node->getMember(1), enumCollVar, attr));
|
||||
}
|
||||
|
||||
if (node->type == NODE_TYPE_OPERATOR_BINARY_IN) {
|
||||
auto lhs = node->getMember(0); // enumCollVar
|
||||
auto rhs = node->getMember(1); // value
|
||||
RangeInfoMapVec rimv;
|
||||
if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
|
||||
buildRangeInfo(lhs, enumCollVar, attr, true);
|
||||
findVarAndAttr(lhs, enumCollVar, attr);
|
||||
if (enumCollVar != nullptr) {
|
||||
std::unordered_set<Variable*> varsUsed
|
||||
= Ast::getReferencedVariables(rhs);
|
||||
|
@ -1275,33 +1283,30 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
// expression which does not involve that variable:
|
||||
std::vector<RangeInfo> ranges;
|
||||
for (size_t i = 0; i < rhs->numMembers(); i++) {
|
||||
ranges.emplace_back(RangeInfo(enumCollVar->name, attr.substr(0, attr.size() - 1),
|
||||
RangeInfoBound(rhs->getMember(i), true),
|
||||
RangeInfoBound(rhs->getMember(i), true), true));
|
||||
}
|
||||
if (! isOrCondition) {
|
||||
_rangeInfoMapVec->insertDistributeAndIntoOr(ranges);
|
||||
} else {
|
||||
_rangeInfoMapVec->insertOr(ranges);
|
||||
ranges.emplace_back(RangeInfo(enumCollVar->name,
|
||||
attr.substr(0, attr.size() - 1),
|
||||
RangeInfoBound(rhs->getMember(i), true),
|
||||
RangeInfoBound(rhs->getMember(i), true),
|
||||
true));
|
||||
}
|
||||
rimv->insertOr(ranges);
|
||||
enumCollVar = nullptr;
|
||||
attr.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
return rimv;
|
||||
}
|
||||
|
||||
if (node->type == NODE_TYPE_OPERATOR_BINARY_OR) {
|
||||
buildRangeInfo(node->getMember(0), enumCollVar, attr, true);
|
||||
buildRangeInfo(node->getMember(1), enumCollVar, attr, true);
|
||||
return;
|
||||
return orCombineRangeInfoMapVecs(buildRangeInfo(node->getMember(0), enumCollVar, attr),
|
||||
buildRangeInfo(node->getMember(1), enumCollVar, attr, true));
|
||||
}
|
||||
|
||||
// default case
|
||||
attr.clear();
|
||||
enumCollVar = nullptr;
|
||||
return;
|
||||
return RangeInfoMapVec();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -188,6 +188,18 @@ triagens::basics::Json RangeInfo::toJson () const {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief class RangeInfoMap
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RangeInfoMap::RangeInfoMap (std::string const& var,
|
||||
std::string const& name,
|
||||
RangeInfoBound low,
|
||||
RangeInfoBound high,
|
||||
bool equality)
|
||||
: _ranges() {
|
||||
RangeInfo ri(var, name, low, high, equality);
|
||||
std::unordered_map<std::string, RangeInfo> map;
|
||||
map.emplace(make_pair(name, ri));
|
||||
_ranges.emplace(std::make_pair(var, map));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief insert if there is no range corresponding to variable name <var>,
|
||||
|
@ -347,6 +359,18 @@ void RangeInfoMap::insert (std::string const& var,
|
|||
insert(RangeInfo(var, name, low, high, equality));
|
||||
}
|
||||
|
||||
RangeInfoMap andCombineRangeInfoMaps (RangeInfoMap lhs, RangeInfoMap rhs) {
|
||||
|
||||
RangeInfoMap rim = lhs.clone();
|
||||
|
||||
for (auto x: rhs._ranges) {
|
||||
for (auto y: x.second) {
|
||||
rim.insert(y.second.clone());
|
||||
}
|
||||
}
|
||||
return rim;
|
||||
}
|
||||
|
||||
void RangeInfoMap::eraseEmptyOrUndefined(std::string const& var) {
|
||||
|
||||
std::unordered_map<std::string, RangeInfo>* map = find(var);
|
||||
|
@ -367,6 +391,65 @@ void RangeInfoMap::eraseEmptyOrUndefined(std::string const& var) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
RangeInfoMapVec::RangeInfoMapVec (std::string const& var,
|
||||
std::string const& name,
|
||||
RangeInfoBound low,
|
||||
RangeInfoBound high,
|
||||
bool equality) :
|
||||
_rangeInfoMapVec() {
|
||||
|
||||
_rangeInfoMapVec.emplace_back(RangeInfoMap rim(var, name, low, high, equality));
|
||||
}
|
||||
|
||||
RangeInfoMapVec::RangeInfoMapVec (RangeInfoMap rim) :
|
||||
_rangeInfoMapVec() {
|
||||
|
||||
if (! rim.empty()){
|
||||
_rangeInfoMapVec.emplace_back(rim);
|
||||
}
|
||||
}
|
||||
|
||||
RangeInfoMapVec::emplace_back (RangeInfoMap rim) {
|
||||
_rangeInfoMapVec(emplace_back(rim));
|
||||
}
|
||||
|
||||
RangeInfoMapVec orCombineRangeInfoMapVecs (RangeInfoMapVec lhs, RangeInfoMapVec rhs) {
|
||||
|
||||
if (lhs.empty()) {
|
||||
return rhs; //TODO copy?
|
||||
}
|
||||
|
||||
if (rhs.empty()) {
|
||||
return lhs; //TODO copy?
|
||||
}
|
||||
|
||||
RangeInfoMapVec rimv;
|
||||
|
||||
for (size_t i = 0; i <= lhs.size(); i++) {
|
||||
rimv.emplace_back(lhs[i]->clone());
|
||||
}
|
||||
for (size_t i = 0; i <= rhs.size(); i++) {
|
||||
rimv.emplace_back(rhs[i]->clone());
|
||||
}
|
||||
|
||||
return rimv;
|
||||
}
|
||||
|
||||
// distributes AND into OR
|
||||
|
||||
RangeInfoMapVec andCombineRangeInfoMapVecs (RangeInfoMapVec lhs, RangeInfoMapVec rhs) {
|
||||
|
||||
RangeInfoMapVec rimv;
|
||||
|
||||
for (auto rimLhs: lhs) {
|
||||
for (auto rimRhs: rhs) {
|
||||
rimv.emplace_back(andCombineRangeInfoMaps(rimLhs->clone(), rimRhs->clone));
|
||||
}
|
||||
}
|
||||
return rimv;
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> RangeInfoMapVec::attributes (std::string const& var) {
|
||||
return _rangeInfoMapVec[0]->attributes(var);
|
||||
}
|
||||
|
@ -487,7 +570,6 @@ void RangeInfoMapVec::insertOr (std::vector<RangeInfo> ranges) {
|
|||
} else {
|
||||
sample = new RangeInfoMap();
|
||||
}
|
||||
// TODO make sure we don't insert identical bounds
|
||||
for (auto x: ranges) {
|
||||
if (!isIdenticalToExisting(x)) {
|
||||
RangeInfoMap* rim = sample->cloneExcluding(x._var);
|
||||
|
|
|
@ -587,6 +587,12 @@ namespace triagens {
|
|||
|
||||
RangeInfoMap () : _ranges() {
|
||||
}
|
||||
|
||||
RangeInfoMap (std::string const& var,
|
||||
std::string const& name,
|
||||
RangeInfoBound low,
|
||||
RangeInfoBound high,
|
||||
bool equality);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor
|
||||
|
@ -710,6 +716,18 @@ namespace triagens {
|
|||
|
||||
RangeInfoMapVec () : _rangeInfoMapVec() {
|
||||
}
|
||||
|
||||
|
||||
// construct RangeInfoMapVec containing a single RangeInfoMap containing a
|
||||
// single RangeInfo
|
||||
|
||||
RangeInfoMapVec (std::string const& var,
|
||||
std::string const& name,
|
||||
RangeInfoBound low,
|
||||
RangeInfoBound high,
|
||||
bool equality);
|
||||
|
||||
RangeInfoMapVec (RangeInfoMap rim);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor
|
||||
|
@ -738,7 +756,16 @@ namespace triagens {
|
|||
return list;
|
||||
}
|
||||
|
||||
RangeInfoMap* operator[] (size_t pos) {
|
||||
return _rangeInfoMapVec[pos];
|
||||
}
|
||||
|
||||
size_t size () {
|
||||
return _rangeInfoMapVec.size();
|
||||
}
|
||||
|
||||
void eraseEmptyOrUndefined (std::string const&);
|
||||
|
||||
void insertAnd (std::string const& var,
|
||||
std::string const& name,
|
||||
RangeInfoBound low,
|
||||
|
@ -774,6 +801,10 @@ namespace triagens {
|
|||
std::vector<RangeInfoMap*> _rangeInfoMapVec;
|
||||
};
|
||||
|
||||
RangeInfoMap andCombineRangeInfoMaps (RangeInfoMap, RangeInfoMap);
|
||||
RangeInfoMapVec orCombineRangeInfoMapVecs (RangeInfoMapVec, RangeInfoMapVec);
|
||||
RangeInfoMapVec andCombineRangeInfoMapVecs (RangeInfoMapVec, RangeInfoMapVec);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief IndexOrCondition, type for vector of vector of RangeInfo. The meaning
|
||||
/// is: the outer vector means an implicit "OR" between the entries. Each
|
||||
|
|
Loading…
Reference in New Issue