mirror of https://gitee.com/bigwinds/arangodb
further snapshot
This commit is contained in:
parent
0dcffe898c
commit
553c638cfe
|
@ -795,7 +795,7 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
_plan(plan),
|
||||
_canThrow(false),
|
||||
_level(level) {
|
||||
_rangeInfoMapVec = new RangeInfoMap();
|
||||
_rangeInfoMapVec = new RangeInfoMapVec();
|
||||
_varIds.insert(var->id);
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
buildRangeInfoAND(node->expression()->node(), enumCollVar, attr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -858,7 +858,7 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
auto node = static_cast<EnumerateCollectionNode*>(en);
|
||||
auto var = node->getVariablesSetHere()[0]; // should only be 1
|
||||
std::unordered_map<std::string, RangeInfo>* map
|
||||
= _rangeInfoMapVec->find(var->name);
|
||||
= _rangeInfoMapVec->find(var->name, 0);
|
||||
// check if we have any ranges with this var
|
||||
|
||||
if (map != nullptr) {
|
||||
|
@ -872,60 +872,44 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
for (auto v : varsSetHere) {
|
||||
varsDefined.erase(v);
|
||||
}
|
||||
for (auto& x : *map) {
|
||||
auto worker = [&] (std::list<RangeInfoBound>& bounds) -> void {
|
||||
for (auto it = bounds.begin(); it != bounds.end();
|
||||
/* no hoisting */) {
|
||||
AstNode const* a = it->getExpressionAst(_plan->getAst());
|
||||
std::unordered_set<Variable*> varsUsed
|
||||
= Ast::getReferencedVariables(a);
|
||||
bool bad = false;
|
||||
for (auto v : varsUsed) {
|
||||
if (varsDefined.find(const_cast<Variable const*>(v))
|
||||
== varsDefined.end()) {
|
||||
bad = true;
|
||||
pos = 0;
|
||||
do {
|
||||
for (auto& x : *map) {
|
||||
auto worker = [&] (std::list<RangeInfoBound>& bounds) -> void {
|
||||
for (auto it = bounds.begin(); it != bounds.end();
|
||||
/* no hoisting */) {
|
||||
AstNode const* a = it->getExpressionAst(_plan->getAst());
|
||||
std::unordered_set<Variable*> varsUsed
|
||||
= Ast::getReferencedVariables(a);
|
||||
bool bad = false;
|
||||
for (auto v : varsUsed) {
|
||||
if (varsDefined.find(const_cast<Variable const*>(v))
|
||||
== varsDefined.end()) {
|
||||
bad = true;
|
||||
}
|
||||
}
|
||||
if (bad) {
|
||||
it = bounds.erase(it);
|
||||
x.second.revokeEquality(); // just to be sure
|
||||
}
|
||||
else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
if (bad) {
|
||||
it = bounds.erase(it);
|
||||
x.second.revokeEquality(); // just to be sure
|
||||
}
|
||||
else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
};
|
||||
worker(x.second._lows);
|
||||
worker(x.second._highs);
|
||||
}
|
||||
// Now remove empty conditions:
|
||||
for (auto it = map->begin(); it != map->end(); /* no hoisting */ ) {
|
||||
if (it->second._lows.empty() &&
|
||||
it->second._highs.empty() &&
|
||||
! it->second._lowConst.isDefined() &&
|
||||
! it->second._highConst.isDefined()) {
|
||||
it = map->erase(it);
|
||||
};
|
||||
worker(x.second._lows);
|
||||
worker(x.second._highs);
|
||||
}
|
||||
else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
map = _rangeInfoMapVec->find(var->name, ++pos);
|
||||
} while (map !=nullptr);
|
||||
// Now remove empty conditions:
|
||||
_rangeInfoMapVec->eraseEmptyOrUndefined(var->name);
|
||||
|
||||
std::vector<size_t> validPos = _rangeInfoMapVec->validPositions(var->name);
|
||||
// are any of the RangeInfoMaps in the vector valid?
|
||||
|
||||
// check the first components of <map> against indexes of <node>...
|
||||
std::unordered_set<std::string> attrs;
|
||||
|
||||
bool valid = true; // are all the range infos valid?
|
||||
|
||||
for(auto x: *map) {
|
||||
valid &= x.second.isValid();
|
||||
if (! valid) {
|
||||
break;
|
||||
}
|
||||
attrs.insert(x.first);
|
||||
}
|
||||
|
||||
if (! _canThrow) {
|
||||
if (! valid) { // ranges are not valid . . .
|
||||
if (validPos.empty()) { // ranges are not valid . . .
|
||||
auto newPlan = _plan->clone();
|
||||
try {
|
||||
auto parents = newPlan->getNodeById(node->id())->getParents();
|
||||
|
@ -942,123 +926,155 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
}
|
||||
}
|
||||
else {
|
||||
std::vector<Index*> idxs;
|
||||
std::vector<size_t> prefixes;
|
||||
// {idxs.at(i)->_fields[0]..idxs.at(i)->_fields[prefixes.at(i)]}
|
||||
// is a subset of <attrs>
|
||||
|
||||
// note: prefixes are only used for skiplist indexes
|
||||
// for all other index types, the prefix value will always be 0
|
||||
node->getIndexesForIndexRangeNode(attrs, idxs, prefixes);
|
||||
std::vector<Index*> idxs;
|
||||
std::vector<size_t> prefixes;
|
||||
// {idxs.at(i)->_fields[0]..idxs.at(i)->_fields[prefixes.at(i)]}
|
||||
// is a subset of <attrs>
|
||||
|
||||
// make one new plan for every index in <idxs> that replaces the
|
||||
// enumerate collection node with a IndexRangeNode ...
|
||||
|
||||
for (size_t i = 0; i < idxs.size(); i++) {
|
||||
std::vector<std::vector<RangeInfo>> rangeInfo;
|
||||
rangeInfo.push_back(std::vector<RangeInfo>());
|
||||
// note: prefixes are only used for skiplist indexes
|
||||
// for all other index types, the prefix value will always be 0
|
||||
node->getIndexesForIndexRangeNode(
|
||||
_rangeInfoMapVec->attributes(var->name, 0), idxs, prefixes);
|
||||
//TODO remove the 2nd arg from attribute in the line above
|
||||
|
||||
// make one new plan for every index in <idxs> that replaces the
|
||||
// enumerate collection node with a IndexRangeNode ...
|
||||
|
||||
// ranges must be valid and all comparisons == if hash
|
||||
// index or == followed by a single <, >, >=, or <=
|
||||
// if a skip index in the order of the fields of the
|
||||
// index.
|
||||
auto idx = idxs.at(i);
|
||||
TRI_ASSERT(idx != nullptr);
|
||||
|
||||
if (idx->type == TRI_IDX_TYPE_PRIMARY_INDEX) {
|
||||
bool handled = false;
|
||||
auto range = map->find(std::string(TRI_VOC_ATTRIBUTE_ID));
|
||||
|
||||
if (range != map->end()) {
|
||||
if (! range->second.is1ValueRangeInfo()) {
|
||||
rangeInfo.at(0).clear(); // not usable
|
||||
}
|
||||
else {
|
||||
rangeInfo.at(0).push_back(range->second);
|
||||
handled = true;
|
||||
}
|
||||
for (size_t i = 0; i < idxs.size(); i++) {
|
||||
IndexOrCondition indexOrCondition;
|
||||
for (size_t k = 0; k < validPos.size(); k++) {
|
||||
indexOrCondition.push_back(std::vector<RangeInfo>());
|
||||
}
|
||||
|
||||
if (! handled) {
|
||||
range = map->find(std::string(TRI_VOC_ATTRIBUTE_KEY));
|
||||
|
||||
if (range != map->end()) {
|
||||
if (! range->second.is1ValueRangeInfo()) {
|
||||
rangeInfo.at(0).clear(); // not usable
|
||||
|
||||
// ranges must be valid and all comparisons == if hash
|
||||
// index or == followed by a single <, >, >=, or <=
|
||||
// if a skip index in the order of the fields of the
|
||||
// index.
|
||||
auto idx = idxs.at(i);
|
||||
TRI_ASSERT(idx != nullptr);
|
||||
|
||||
if (idx->type == TRI_IDX_TYPE_PRIMARY_INDEX) {
|
||||
for (size_t k = 0; k < validPos.size(); k++) {
|
||||
bool handled = false;
|
||||
|
||||
auto map = _rangeInfoMapVec->find(var->name, validPos[k]);
|
||||
auto range = map->find(std::string(TRI_VOC_ATTRIBUTE_ID));
|
||||
|
||||
if (range != map->end()) {
|
||||
if (! range->second.is1ValueRangeInfo()) {
|
||||
indexOrCondition.at(k).clear(); // not usable
|
||||
}
|
||||
else {
|
||||
indexOrCondition.at(k).push_back(range->second);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rangeInfo.at(0).push_back(range->second);
|
||||
|
||||
if (! handled) {
|
||||
range = map->find(std::string(TRI_VOC_ATTRIBUTE_KEY));
|
||||
|
||||
if (range != map->end()) {
|
||||
if (! range->second.is1ValueRangeInfo()) {
|
||||
indexOrCondition.at(k).clear(); // not usable
|
||||
}
|
||||
else {
|
||||
indexOrCondition.at(k).push_back(range->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (idx->type == TRI_IDX_TYPE_HASH_INDEX) {
|
||||
for (size_t j = 0; j < idx->fields.size(); j++) {
|
||||
auto range = map->find(idx->fields[j]);
|
||||
|
||||
if (! range->second.is1ValueRangeInfo()) {
|
||||
rangeInfo.at(0).clear(); // not usable
|
||||
else if (idx->type == TRI_IDX_TYPE_HASH_INDEX) {
|
||||
for (size_t k = 0; k < validPos.size(); k++) {
|
||||
auto map = _rangeInfoMapVec->find(var->name, validPos[k]);
|
||||
for (size_t j = 0; j < idx->fields.size(); j++) {
|
||||
auto range = map->find(idx->fields[j]);
|
||||
|
||||
if (! range->second.is1ValueRangeInfo()) {
|
||||
indexOrCondition.at(k).clear(); // not usable
|
||||
break;
|
||||
}
|
||||
indexOrCondition.at(k).push_back(range->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (idx->type == TRI_IDX_TYPE_EDGE_INDEX) {
|
||||
for (size_t k = 0; k < validPos.size(); k++) {
|
||||
bool handled = false;
|
||||
auto range = map->find(std::string(TRI_VOC_ATTRIBUTE_FROM));
|
||||
auto map = _rangeInfoMapVec->find(var->name, validPos[k]);
|
||||
if (range != map->end()) {
|
||||
if (! range->second.is1ValueRangeInfo()) {
|
||||
indexOrCondition.at(k).clear(); // not usable
|
||||
}
|
||||
else {
|
||||
indexOrCondition.at(k).push_back(range->second);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! handled) {
|
||||
range = map->find(std::string(TRI_VOC_ATTRIBUTE_TO));
|
||||
|
||||
if (range != map->end()) {
|
||||
if (! range->second.is1ValueRangeInfo()) {
|
||||
indexOrCondition.at(k).clear(); // not usable
|
||||
}
|
||||
else {
|
||||
indexOrCondition.at(k).push_back(range->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (idx->type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
|
||||
for (size_t k = 0; k < validPos.size(); k++) {
|
||||
auto map = _rangeInfoMapVec->find(var->name, validPos[k]);
|
||||
|
||||
size_t j = 0;
|
||||
auto range = map->find(idx->fields[0]);
|
||||
TRI_ASSERT(range != map->end());
|
||||
indexOrCondition.at(k).push_back(range->second);
|
||||
bool equality = range->second.is1ValueRangeInfo();
|
||||
while (++j < prefixes.at(i) && equality) {
|
||||
range = map->find(idx->fields[j]);
|
||||
indexOrCondition.at(k).push_back(range->second);
|
||||
equality = equality && range->second.is1ValueRangeInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO remove empty positions in indexOrCondition?
|
||||
// check if there are any non-empty positions in
|
||||
// indexOrCondition
|
||||
bool isEmpty = true;
|
||||
for (size_t k = 0; k < validPos.size(); k++) {
|
||||
if (! indexOrCondition.at(k).empty()) {
|
||||
isEmpty = false;
|
||||
break;
|
||||
}
|
||||
rangeInfo.at(0).push_back(range->second);
|
||||
}
|
||||
}
|
||||
else if (idx->type == TRI_IDX_TYPE_EDGE_INDEX) {
|
||||
bool handled = false;
|
||||
auto range = map->find(std::string(TRI_VOC_ATTRIBUTE_FROM));
|
||||
|
||||
if (range != map->end()) {
|
||||
if (! range->second.is1ValueRangeInfo()) {
|
||||
rangeInfo.at(0).clear(); // not usable
|
||||
}
|
||||
else {
|
||||
rangeInfo.at(0).push_back(range->second);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! handled) {
|
||||
range = map->find(std::string(TRI_VOC_ATTRIBUTE_TO));
|
||||
|
||||
if (range != map->end()) {
|
||||
if (! range->second.is1ValueRangeInfo()) {
|
||||
rangeInfo.at(0).clear(); // not usable
|
||||
}
|
||||
else {
|
||||
rangeInfo.at(0).push_back(range->second);
|
||||
}
|
||||
if (! isEmpty) {
|
||||
auto newPlan = _plan->clone();
|
||||
if (newPlan == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (idx->type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
|
||||
size_t j = 0;
|
||||
auto range = map->find(idx->fields[0]);
|
||||
TRI_ASSERT(range != map->end());
|
||||
rangeInfo.at(0).push_back(range->second);
|
||||
bool equality = range->second.is1ValueRangeInfo();
|
||||
while (++j < prefixes.at(i) && equality) {
|
||||
range = map->find(idx->fields[j]);
|
||||
rangeInfo.at(0).push_back(range->second);
|
||||
equality = equality && range->second.is1ValueRangeInfo();
|
||||
}
|
||||
}
|
||||
|
||||
if (! rangeInfo.at(0).empty()) {
|
||||
auto newPlan = _plan->clone();
|
||||
if (newPlan == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
try {
|
||||
ExecutionNode* newNode = new IndexRangeNode(newPlan, newPlan->nextId(), node->vocbase(),
|
||||
node->collection(), node->outVariable(), idx, rangeInfo, false);
|
||||
newPlan->registerNode(newNode);
|
||||
newPlan->replaceNode(newPlan->getNodeById(node->id()), newNode);
|
||||
_opt->addPlan(newPlan, _level, true);
|
||||
}
|
||||
catch (...) {
|
||||
delete newPlan;
|
||||
throw;
|
||||
try {
|
||||
ExecutionNode* newNode = new IndexRangeNode(newPlan,
|
||||
newPlan->nextId(), node->vocbase(),
|
||||
node->collection(), node->outVariable(), idx,
|
||||
indexOrCondition, false);
|
||||
newPlan->registerNode(newNode);
|
||||
newPlan->replaceNode(newPlan->getNodeById(node->id()), newNode);
|
||||
_opt->addPlan(newPlan, _level, true);
|
||||
}
|
||||
catch (...) {
|
||||
delete newPlan;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1073,9 +1089,9 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void buildRangeInfo (AstNode const* node,
|
||||
Variable const*& enumCollVar,
|
||||
std::string& attr) {
|
||||
void buildRangeInfoAND (AstNode const* node,
|
||||
Variable const*& enumCollVar,
|
||||
std::string& attr) {
|
||||
if (node->type == NODE_TYPE_REFERENCE) {
|
||||
auto x = static_cast<Variable*>(node->getData());
|
||||
auto setter = _plan->getVarSetBy(x->id);
|
||||
|
@ -1087,7 +1103,7 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
}
|
||||
|
||||
if (node->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
|
||||
buildRangeInfo(node->getMember(0), enumCollVar, attr);
|
||||
buildRangeInfoAND(node->getMember(0), enumCollVar, attr);
|
||||
|
||||
if (enumCollVar != nullptr) {
|
||||
char const* attributeName = node->getStringValue();
|
||||
|
@ -1101,7 +1117,7 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
auto lhs = node->getMember(0);
|
||||
auto rhs = node->getMember(1);
|
||||
if (rhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
|
||||
buildRangeInfo(rhs, enumCollVar, attr);
|
||||
buildRangeInfoAND(rhs, enumCollVar, attr);
|
||||
if (enumCollVar != nullptr) {
|
||||
std::unordered_set<Variable*> varsUsed
|
||||
= Ast::getReferencedVariables(lhs);
|
||||
|
@ -1109,10 +1125,12 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
== varsUsed.end()) {
|
||||
// Found a multiple attribute access of a variable and an
|
||||
// expression which does not involve that variable:
|
||||
_ranges->insert(enumCollVar->name,
|
||||
attr.substr(0, attr.size() - 1),
|
||||
RangeInfoBound(lhs, true),
|
||||
RangeInfoBound(lhs, true), true);
|
||||
_rangeInfoMapVec->insertAnd(enumCollVar->name,
|
||||
attr.substr(0, attr.size() - 1),
|
||||
RangeInfoBound(lhs, true),
|
||||
RangeInfoBound(lhs, true), true);
|
||||
// FIXME: this is not the right thing in general, how do we know
|
||||
// this is an AND at this point?
|
||||
}
|
||||
enumCollVar = nullptr;
|
||||
attr.clear();
|
||||
|
@ -1120,7 +1138,7 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
}
|
||||
|
||||
if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
|
||||
buildRangeInfo(lhs, enumCollVar, attr);
|
||||
buildRangeInfoAND(lhs, enumCollVar, attr);
|
||||
if (enumCollVar != nullptr) {
|
||||
std::unordered_set<Variable*> varsUsed
|
||||
= Ast::getReferencedVariables(rhs);
|
||||
|
@ -1128,10 +1146,10 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
== varsUsed.end()) {
|
||||
// Found a multiple attribute access of a variable and an
|
||||
// expression which does not involve that variable:
|
||||
_ranges->insert(enumCollVar->name,
|
||||
attr.substr(0, attr.size() - 1),
|
||||
RangeInfoBound(rhs, true),
|
||||
RangeInfoBound(rhs, true), true);
|
||||
_rangeInfoMapVec->insertAND(enumCollVar->name,
|
||||
attr.substr(0, attr.size() - 1),
|
||||
RangeInfoBound(rhs, true),
|
||||
RangeInfoBound(rhs, true), true);
|
||||
}
|
||||
enumCollVar = nullptr;
|
||||
attr.clear();
|
||||
|
@ -1155,7 +1173,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);
|
||||
buildRangeInfoAND(rhs, enumCollVar, attr);
|
||||
if (enumCollVar != nullptr) {
|
||||
RangeInfoBound low;
|
||||
RangeInfoBound high;
|
||||
|
@ -1168,8 +1186,9 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
else {
|
||||
low.assign(lhs, include);
|
||||
}
|
||||
_ranges->insert(enumCollVar->name, attr.substr(0, attr.size() - 1),
|
||||
low, high, false);
|
||||
_rangeInfoMapVec->insertAND(enumCollVar->name,
|
||||
attr.substr(0, attr.size() - 1),
|
||||
low, high, false);
|
||||
|
||||
enumCollVar = nullptr;
|
||||
attr.clear();
|
||||
|
@ -1180,7 +1199,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);
|
||||
buildRangeInfoAND(lhs, enumCollVar, attr);
|
||||
if (enumCollVar != nullptr) {
|
||||
RangeInfoBound low;
|
||||
RangeInfoBound high;
|
||||
|
@ -1193,7 +1212,7 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
else {
|
||||
high.assign(rhs, include);
|
||||
}
|
||||
_ranges->insert(enumCollVar->name, attr.substr(0, attr.size() - 1),
|
||||
_rangeInfoMapVec->insertAND(enumCollVar->name, attr.substr(0, attr.size() - 1),
|
||||
low, high, false);
|
||||
|
||||
enumCollVar = nullptr;
|
||||
|
@ -1205,10 +1224,10 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
}
|
||||
|
||||
if (node->type == NODE_TYPE_OPERATOR_BINARY_AND) {
|
||||
buildRangeInfo(node->getMember(0), enumCollVar, attr);
|
||||
buildRangeInfo(node->getMember(1), enumCollVar, attr);
|
||||
buildRangeInfoAND(node->getMember(0), enumCollVar, attr);
|
||||
buildRangeInfoAND(node->getMember(1), enumCollVar, attr);
|
||||
}
|
||||
if (node->type == NODE_TYPE_OPERATOR_BINARY_IN) {
|
||||
/*if (node->type == NODE_TYPE_OPERATOR_BINARY_IN) {
|
||||
auto lhs = node->getMember(0); // enumCollVar
|
||||
auto rhs = node->getMember(1); // value
|
||||
|
||||
|
@ -1220,13 +1239,13 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
RangeInfoBound low(rhs->getMember(i), true);
|
||||
RangeInfoBound high(rhs->getMember(i), true);
|
||||
//FIXME don't assume this is constant
|
||||
_ranges->insert(enumCollVar->name, attr.substr(0, attr.size() - 1),
|
||||
_rangeInfoMapVec->insert(enumCollVar->name, attr.substr(0, attr.size() - 1),
|
||||
low, high, true);
|
||||
}
|
||||
enumCollVar = nullptr;
|
||||
attr.clear();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
// default case
|
||||
attr.clear();
|
||||
enumCollVar = nullptr;
|
||||
|
|
|
@ -285,6 +285,32 @@ void RangeInfo::fuse (RangeInfo const& that) {
|
|||
}
|
||||
}
|
||||
|
||||
bool RangeInfoMap::isValid (std::string const& var) {
|
||||
// are all the range infos valid?
|
||||
|
||||
std::unordered_map<std::string, RangeInfo>* map = find(var);
|
||||
if (map != nullptr) {
|
||||
for(auto x: *map) {
|
||||
if (! x.second.isValid()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> RangeInfoMap::attributes (std::string const& var) {
|
||||
std::unordered_set<std::string> attrs;
|
||||
std::unordered_map<std::string, RangeInfo>* map = find(var);
|
||||
if (map != nullptr) {
|
||||
for(auto x: *map) {
|
||||
attrs.insert(x.first);
|
||||
}
|
||||
}
|
||||
return attrs;
|
||||
}
|
||||
|
||||
RangeInfoMap* RangeInfoMap::clone () {
|
||||
auto rim = new RangeInfoMap();
|
||||
for (auto x: _ranges) {
|
||||
|
@ -307,6 +333,7 @@ RangeInfoMap* RangeInfoMap::cloneExcluding (std::string const& var) {
|
|||
return rim;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief insert if there is no range corresponding to variable name <var>,
|
||||
/// and attribute <name>, and otherwise intersection with existing range
|
||||
|
@ -320,8 +347,59 @@ void RangeInfoMap::insert (std::string const& var,
|
|||
insert(RangeInfo(var, name, low, high, equality));
|
||||
}
|
||||
|
||||
void RangeInfoMap::eraseEmptyOrUndefined(std::string const& var) {
|
||||
|
||||
std::unordered_map<std::string, RangeInfo>* map = find(var);
|
||||
if (map != nullptr) {
|
||||
for (auto it = map->begin(); it != map->end(); /* no hoisting */ ) {
|
||||
if (it->second._lows.empty() &&
|
||||
it->second._highs.empty() &&
|
||||
! it->second._lowConst.isDefined() &&
|
||||
! it->second._highConst.isDefined()) {
|
||||
it = map->erase(it);
|
||||
}
|
||||
else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// FIXME maybe this is unnecessary, it should be that the return value here is
|
||||
// independent of pos, i.e that every entry in the vec has the same attributes??
|
||||
std::unordered_set<std::string> RangeInfoMapVec::attributes (std::string const& var, size_t pos) {
|
||||
TRI_ASSERT(pos < _rangeInfoMapVec.size());
|
||||
|
||||
return _rangeInfoMapVec[pos].attributes(var);
|
||||
}
|
||||
|
||||
void RangeInfoMapVec::validPositions(std::string const& var) {
|
||||
std::vector<size_t> valid;
|
||||
|
||||
for (i = 0; i < _rangeInfoMapVec.size(); i++) {
|
||||
if (_rangeInfoMapVec[i].isValid(var)) {
|
||||
valid.push_back(i);
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
void RangeInfoMapVec::eraseEmptyOrUndefined(std::string const& var) {
|
||||
for (RangeInfoMap x: _rangeInfoMapVec) {
|
||||
x.eraseEmptyOrUndefined(var);
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, RangeInfo>* find (std::string const& var, size_t pos) {
|
||||
if (pos >= _rangeInfoMapVec.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return _rangeInfoMapVec[pos].find(var);
|
||||
}
|
||||
|
||||
void RangeInfoMapVec::insertAnd (std::string const& var,
|
||||
std::string const& name,
|
||||
RangeInfoBound low,
|
||||
|
@ -333,7 +411,8 @@ void RangeInfoMapVec::insertAnd (std::string const& var,
|
|||
// var.attr > 1 and var.attr < 10
|
||||
|
||||
void RangeInfoMapVec::insertAnd (RangeInfo range) {
|
||||
|
||||
// maybe have to add a new RangeInfoMap if the _rangeInfoMapVec is empty...
|
||||
// FIXME
|
||||
for (size_t i = 0; i < _rangeInfoMapVec.size(); i++) {
|
||||
_rangeInfoMapVec[i]->insert(range);
|
||||
}
|
||||
|
|
|
@ -648,6 +648,8 @@ namespace triagens {
|
|||
|
||||
RangeInfoMap* clone ();
|
||||
RangeInfoMap* cloneExcluding (std::string const&);
|
||||
void eraseEmptyOrUndefined (std::string const&);
|
||||
bool isValid ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief private data
|
||||
|
@ -704,6 +706,7 @@ namespace triagens {
|
|||
return list;
|
||||
}
|
||||
|
||||
void eraseEmptyOrUndefined (std::string const&);
|
||||
void insertAnd (std::string const& var,
|
||||
std::string const& name,
|
||||
RangeInfoBound low,
|
||||
|
@ -717,13 +720,17 @@ namespace triagens {
|
|||
|
||||
void insertDistributeAndIntoOr (std::vector<RangeInfo> ranges);
|
||||
|
||||
std::unordered_map<std::string, RangeInfo>* find (std::string const& var, size_t pos);
|
||||
|
||||
std::vector<size_t> validPositions ();
|
||||
// in what positions are the RangeInfoMaps in the vector valid
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief private data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
std::vector<RangeInfoMap*> _rangeInfoMapVec;
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue