1
0
Fork 0
arangodb/arangod/Aql/RangeInfo.h

1135 lines
45 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// @brief Infrastructure for RangeInfo
///
/// @file arangod/Aql/RangeInfo.h
///
/// DISCLAIMER
///
/// Copyright 2010-2014 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author not James
/// @author Copyright 2014, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGODB_AQL_RANGE_INFO_H
#define ARANGODB_AQL_RANGE_INFO_H 1
#include "Basics/Common.h"
#include "Aql/AstNode.h"
#include "Basics/JsonHelper.h"
#include "Basics/json-utilities.h"
class VocShaper;
namespace triagens {
namespace aql {
// -----------------------------------------------------------------------------
// --SECTION-- class RangeInfoBound
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief struct to keep an upper or lower bound named _bound and a bool
/// _include which indicates if the _bound is included or not. This can
/// hold a constant value (NODE_TYPE_VALUE) or a subexpression, which is
/// indicated by the boolean flag _isConstant. The whole thing can be
/// not _defined, which counts as _isConstant.
/// We have the following invariants:
/// (! _defined) ==> _isConstant
////////////////////////////////////////////////////////////////////////////////
struct RangeInfoBound {
// -----------------------------------------------------------------------------
// --SECTION-- constructors / destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief constructors
////////////////////////////////////////////////////////////////////////////////
RangeInfoBound (AstNode const* bound,
bool include)
: _bound(),
_include(include),
_defined(false),
_expressionAst(nullptr) {
if (bound->type == NODE_TYPE_VALUE) {
_bound = triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE,
bound->toJsonValue(TRI_UNKNOWN_MEM_ZONE));
_isConstant = true;
}
else {
_bound = triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE,
bound->toJson(TRI_UNKNOWN_MEM_ZONE, true));
_isConstant = false;
_expressionAst = bound;
}
_defined = true;
}
RangeInfoBound (triagens::basics::Json const& json)
: _bound(),
_include(basics::JsonHelper::checkAndGetBooleanValue(json.json(),
"include")),
_isConstant(basics::JsonHelper::checkAndGetBooleanValue(json.json(),
"isConstant")),
_defined(false),
_expressionAst(nullptr) {
triagens::basics::Json bound = json.get("bound");
if (! bound.isEmpty()) {
_bound = bound;
_defined = true;
}
}
RangeInfoBound (bool include,
bool isConstant,
triagens::basics::Json& json)
: _bound(),
_include(include),
_isConstant(isConstant),
_defined(false),
_expressionAst(nullptr) {
if (! json.isEmpty()) {
_bound = triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE, json.steal());
_defined = true;
}
}
RangeInfoBound ()
: _bound(),
_include(false),
_isConstant(false),
_defined(false),
_expressionAst(nullptr) {
}
RangeInfoBound (RangeInfoBound const& copy)
: _bound(copy._bound.copy()),
_include(copy._include),
_isConstant(copy._isConstant),
_defined(copy._defined),
_expressionAst(nullptr) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destructor
////////////////////////////////////////////////////////////////////////////////
~RangeInfoBound () {}
////////////////////////////////////////////////////////////////////////////////
/// @brief delete assignment
////////////////////////////////////////////////////////////////////////////////
RangeInfoBound& operator= (RangeInfoBound const& copy) = delete;
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief explicit assign
////////////////////////////////////////////////////////////////////////////////
void assign (basics::Json const& json) {
_defined = false; // keep it undefined in case of an exception
triagens::basics::Json bound = json.get("bound");
if (! bound.isEmpty()) {
_bound = bound;
_defined = true;
}
_include = basics::JsonHelper::checkAndGetBooleanValue(
json.json(), "include");
_isConstant = basics::JsonHelper::checkAndGetBooleanValue(
json.json(), "isConstant");
_expressionAst = nullptr;
}
void assign (AstNode const* bound,
bool include) {
_defined = false; // keep it undefined in case of an exception
_include = include;
if (bound->type == NODE_TYPE_VALUE) {
_bound = triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE,
bound->toJsonValue(TRI_UNKNOWN_MEM_ZONE));
_isConstant = true;
_expressionAst = nullptr;
}
else {
_bound = triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE,
bound->toJson(TRI_UNKNOWN_MEM_ZONE, true));
_isConstant = false;
_expressionAst = bound;
}
_defined = true;
}
void assign (RangeInfoBound const& copy) {
_bound = copy._bound.copy();
_include = copy._include;
_isConstant = copy._isConstant;
_defined = copy._defined;
_expressionAst = copy._expressionAst;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief toJson
////////////////////////////////////////////////////////////////////////////////
triagens::basics::Json toJson() const {
triagens::basics::Json item(basics::Json::Object, 3);
if (! _bound.isEmpty()) {
item("bound", _bound.copy());
}
item("include", triagens::basics::Json(_include))
("isConstant", triagens::basics::Json(!_defined || _isConstant));
return item;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief toIndexOperator, doesn't work with unbounded above and below
/// RangeInfos and only for constant values
////////////////////////////////////////////////////////////////////////////////
TRI_index_operator_t* toIndexOperator (bool high,
triagens::basics::Json parameters,
VocShaper* shaper) const {
TRI_ASSERT(_isConstant);
TRI_index_operator_type_e op;
if (high) {
if (_include) {
op = TRI_LE_INDEX_OPERATOR;
}
else {
op = TRI_LT_INDEX_OPERATOR;
}
}
else {
if (_include) {
op = TRI_GE_INDEX_OPERATOR;
}
else {
op = TRI_GT_INDEX_OPERATOR;
}
}
parameters.add(_bound.copy());
size_t nr = parameters.size();
return TRI_CreateIndexOperator(op, nullptr, nullptr, parameters.steal(), shaper, nr);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief andCombineLowerBounds, changes the bound in *this and replaces
/// it by the stronger bound of *this and that, interpreting both as lower
/// bounds.
////////////////////////////////////////////////////////////////////////////////
void andCombineLowerBounds (RangeInfoBound const& that);
////////////////////////////////////////////////////////////////////////////////
/// @brief andCombineUpperBounds, changes the bound in *this and replaces
/// it by the stronger bound of *this and that, interpreting both as upper
/// bounds.
////////////////////////////////////////////////////////////////////////////////
void andCombineUpperBounds (RangeInfoBound const& that);
////////////////////////////////////////////////////////////////////////////////
/// @brief getter for bound
////////////////////////////////////////////////////////////////////////////////
triagens::basics::Json const& bound () const {
return _bound;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getter for inclusion
////////////////////////////////////////////////////////////////////////////////
bool inclusive () const {
return _include;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief setter for inclusion
////////////////////////////////////////////////////////////////////////////////
void setInclude (bool value) {
_include = value;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getter for isConstant
////////////////////////////////////////////////////////////////////////////////
bool isConstant () const {
return ! _defined || _isConstant;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getter for isDefined
////////////////////////////////////////////////////////////////////////////////
bool isDefined () const {
return _defined;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getExpressionAst, looks up or computes (if necessary) an AST
/// for the variable bound, return nullptr for a constant bound, the new
/// (if needed) nodes are registered with the ast
////////////////////////////////////////////////////////////////////////////////
AstNode const* getExpressionAst (Ast*) const;
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief _bound as Json, this is either for constant values
/// (_isConstant==true) or for JSON-serialised subexpressions
/// (_isConstant==false).
////////////////////////////////////////////////////////////////////////////////
triagens::basics::Json _bound;
////////////////////////////////////////////////////////////////////////////////
/// @brief _include, flag indicating whether or not bound is included
////////////////////////////////////////////////////////////////////////////////
bool _include;
////////////////////////////////////////////////////////////////////////////////
/// @brief _isConstant, this is true if the bound is a constant value
////////////////////////////////////////////////////////////////////////////////
bool _isConstant;
////////////////////////////////////////////////////////////////////////////////
/// @brief _defined, if this is true if the bound is defined
////////////////////////////////////////////////////////////////////////////////
bool _defined;
////////////////////////////////////////////////////////////////////////////////
/// @brief _expressionAst, this remembers the AST for the expression
/// in the variable case, for constant expressions this is always a nullptr.
/// If the bound is made from Json, then _expressionAst is initially set
/// to nullptr and only later computed by getExpressionAst and then
/// cached. Note that the memory management is done by an object of type
/// Ast outside of this class. Therefore the destructor does not delete
/// the pointer here.
////////////////////////////////////////////////////////////////////////////////
AstNode mutable const* _expressionAst;
};
// -----------------------------------------------------------------------------
// --SECTION-- struct RangeInfo
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief struct to keep a list of RangeInfoBounds for _lows and one for
///_highs, as well as constant _lowConst and _highConst. All constant bounds
/// will be combined into _lowConst and _highConst respectively, they
/// can also be not _defined. All bounds in _lows and _highs are defined
/// and not constant. The flag _defined is only false if the whole RangeInfo
/// is not defined (default constructor).
/// This struct keeps _valid and _equality up to date at all times.
/// _valid is false iff the range is known to be empty. _equality is
/// true iff upper and lower bounds were given as (list of) identical
/// pairs. Note that _equality can be set and yet we only notice that
/// the RangeInfo is empty at runtime, if more than one equality was given!
////////////////////////////////////////////////////////////////////////////////
struct RangeInfo {
////////////////////////////////////////////////////////////////////////////////
/// @brief constructors
////////////////////////////////////////////////////////////////////////////////
RangeInfo (std::string const& var,
std::string const& attr,
RangeInfoBound const& low,
RangeInfoBound const& high,
bool equality)
: _var(var),
_attr(attr),
_valid(true),
_defined(true),
_equality(equality) {
if (low.isConstant()) {
_lowConst.assign(low);
}
else {
_lows.emplace_back(low);
}
if (high.isConstant()) {
_highConst.assign(high);
}
else {
_highs.emplace_back(high);
}
// Maybe the range is known to be invalid right away?
if (_lowConst.isDefined() && _lowConst.isConstant() &&
_highConst.isDefined() && _highConst.isConstant()) {
int cmp = TRI_CompareValuesJson(_lowConst.bound().json(),
_highConst.bound().json(), true);
if (cmp == 1) {
_valid = false;
}
else if (cmp == 0) {
if (_lowConst.inclusive() && _highConst.inclusive()) {
_equality = true;
}
else {
_valid = false;
}
}
}
}
RangeInfo (std::string const& var,
std::string const& attr,
RangeInfoBound const& bound)
: _var(var),
_attr(attr),
_valid(true),
_defined(true),
_equality(true) {
// must be an equality here!
TRI_ASSERT(bound.inclusive());
if (bound.isConstant()) {
_lowConst.assign(bound);
_highConst.assign(bound);
}
else {
_lows.emplace_back(bound);
_highs.emplace_back(bound);
}
}
RangeInfo (std::string const& var,
std::string const& attr)
: _var(var),
_attr(attr),
_valid(true),
_defined(true),
_equality(false) {
}
RangeInfo ()
: _valid(false),
_defined(false),
_equality(false) {
}
RangeInfo (basics::Json const& json);
////////////////////////////////////////////////////////////////////////////////
/// @brief destructor
////////////////////////////////////////////////////////////////////////////////
~RangeInfo () {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief delete assignment operator
////////////////////////////////////////////////////////////////////////////////
RangeInfo& operator= (RangeInfo const& copy) = delete;
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief toJson
////////////////////////////////////////////////////////////////////////////////
triagens::basics::Json toJson () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief toString
////////////////////////////////////////////////////////////////////////////////
std::string toString () const {
return this->toJson().toString();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief is1ValueRangeInfo
////////////////////////////////////////////////////////////////////////////////
// is the range a unique value (i.e. something like x<=1 and x>=1),
// note again that with variable bounds it can turn out only at
// runTime that two or more expressions actually contradict each other.
// In this case this method will return true nevertheless.
bool is1ValueRangeInfo () const {
if (! _defined || ! _valid) {
return false;
}
return _equality;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief isDefined, getter for _defined
////////////////////////////////////////////////////////////////////////////////
bool isDefined () const {
return _defined;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief isValid, getter for _valid
////////////////////////////////////////////////////////////////////////////////
bool isValid () const {
return _valid;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief invalidate
////////////////////////////////////////////////////////////////////////////////
void invalidate () {
_valid = false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief isConstant
////////////////////////////////////////////////////////////////////////////////
bool isConstant () const {
if (! _defined) {
return false;
}
if (! _valid) {
return true;
}
return _lows.size() == 0 && _highs.size() == 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief fuse, fuse two ranges, must be for the same variable and attribute
////////////////////////////////////////////////////////////////////////////////
void fuse (RangeInfo const& that);
// -----------------------------------------------------------------------------
// --SECTION-- public variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief _var, the AQL variable name
////////////////////////////////////////////////////////////////////////////////
std::string _var;
////////////////////////////////////////////////////////////////////////////////
/// @brief _attr, the attribute access in the variable, can have dots meaning
/// deep access
////////////////////////////////////////////////////////////////////////////////
std::string _attr;
////////////////////////////////////////////////////////////////////////////////
/// @brief _lows, all non-constant lower bounds
////////////////////////////////////////////////////////////////////////////////
std::list<RangeInfoBound> _lows;
////////////////////////////////////////////////////////////////////////////////
/// @brief _lowConst, all constant lower bounds combined, or not _defined
////////////////////////////////////////////////////////////////////////////////
RangeInfoBound _lowConst;
////////////////////////////////////////////////////////////////////////////////
/// @brief _highs, all non-constant upper bounds
////////////////////////////////////////////////////////////////////////////////
std::list<RangeInfoBound> _highs;
////////////////////////////////////////////////////////////////////////////////
/// @brief _highConst, all constant upper bounds combined, or not _defined
////////////////////////////////////////////////////////////////////////////////
RangeInfoBound _highConst;
////////////////////////////////////////////////////////////////////////////////
/// @brief revokeEquality, this is used when we withdraw a variable bound,
/// in that case we can no longer trust the _equality bit, no big harm is
/// done, except that we no longer know that the range is only at most a
/// single value
////////////////////////////////////////////////////////////////////////////////
void revokeEquality () {
_equality = false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief clone
////////////////////////////////////////////////////////////////////////////////
RangeInfo clone () const {
RangeInfo copy(_var, _attr);
copy._lowConst.assign(_lowConst);
copy._highConst.assign(_highConst);
for (auto const& x : _lows) {
copy._lows.emplace_back(x);
}
for (auto const& x : _highs) {
copy._highs.emplace_back(x);
}
copy._valid = _valid;
copy._defined = _defined;
copy._equality = _equality;
return copy;
}
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief _valid, this is set to true iff the range is known to be non-empty
////////////////////////////////////////////////////////////////////////////////
bool _valid;
////////////////////////////////////////////////////////////////////////////////
/// @brief _defined, this is set iff the range is defined
////////////////////////////////////////////////////////////////////////////////
bool _defined;
////////////////////////////////////////////////////////////////////////////////
/// @brief _equality, range is known to be an equality
////////////////////////////////////////////////////////////////////////////////
bool _equality;
};
// -----------------------------------------------------------------------------
// --SECTION-- class RangeInfoMap
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief class to keep RangeInfos associated to variable and attribute names.
////////////////////////////////////////////////////////////////////////////////
class RangeInfoMap {
public:
RangeInfoMap (RangeInfoMap const& copy) = delete;
RangeInfoMap& operator= (RangeInfoMap const& copy) = delete;
////////////////////////////////////////////////////////////////////////////////
/// @brief default constructor
////////////////////////////////////////////////////////////////////////////////
RangeInfoMap () :
_ranges() {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief construct RangeInfoMap containing single RangeInfo created from the
/// args
////////////////////////////////////////////////////////////////////////////////
RangeInfoMap (std::string const& var,
std::string const& name,
RangeInfoBound const& low,
RangeInfoBound const& high,
bool equality);
RangeInfoMap (RangeInfo const&);
////////////////////////////////////////////////////////////////////////////////
/// @brief destructor
////////////////////////////////////////////////////////////////////////////////
~RangeInfoMap() {
}
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief find, find all the range infos for variable <var>,
/// ownership is not transferred
////////////////////////////////////////////////////////////////////////////////
std::unordered_map<std::string, RangeInfo> const* find (std::string const& var) const {
auto it = _ranges.find(var);
if (it == _ranges.end()) {
return nullptr;
}
return &((*it).second);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief find, find all the range infos for variable <var>,
/// ownership is not transferred
////////////////////////////////////////////////////////////////////////////////
std::unordered_map<std::string, RangeInfo>* find (std::string const& var) {
auto it = _ranges.find(var);
if (it == _ranges.end()) {
return nullptr;
}
return &((*it).second);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief find, find all the range info for variable <var> and attribute <attr>
/// ownership is not transferred
////////////////////////////////////////////////////////////////////////////////
RangeInfo* find (std::string const& var, std::string const& attr) {
auto map = find(var);
if (map == nullptr) {
return nullptr;
}
auto it = map->find(attr);
if (it == map->end()) {
return nullptr;
}
return &((*it).second);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief insert, insert if it's not already there and otherwise
/// intersection with existing range, for variable values we keep them all.
/// The equality flag should be set if and only if the caller knows that the
/// lower and upper bound are equal, this is particularly important if the
/// bounds are variable and can only be computed at runtime.
////////////////////////////////////////////////////////////////////////////////
void insert (std::string const& var,
std::string const& name,
RangeInfoBound const& low,
RangeInfoBound const& high,
bool equality);
////////////////////////////////////////////////////////////////////////////////
/// @brief insert an equality
////////////////////////////////////////////////////////////////////////////////
void insert (std::string const& var,
std::string const& name,
RangeInfoBound const& bound);
////////////////////////////////////////////////////////////////////////////////
/// @brief insert, directly using a RangeInfo structure
////////////////////////////////////////////////////////////////////////////////
void insert (RangeInfo const& range);
////////////////////////////////////////////////////////////////////////////////
/// @brief erase
////////////////////////////////////////////////////////////////////////////////
void erase (RangeInfo*);
////////////////////////////////////////////////////////////////////////////////
/// @brief size, the number of range infos stored
////////////////////////////////////////////////////////////////////////////////
size_t size () const {
return _ranges.size();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief empty, the number of range infos stored
////////////////////////////////////////////////////////////////////////////////
bool empty () const {
return _ranges.empty();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief toString, via Json
////////////////////////////////////////////////////////////////////////////////
std::string toString() const {
return this->toJson().toString();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief toJson
////////////////////////////////////////////////////////////////////////////////
triagens::basics::Json toJson() const {
triagens::basics::Json list(triagens::basics::Json::Array);
for (auto const& x : _ranges) {
for (auto const& y : x.second) {
triagens::basics::Json item(triagens::basics::Json::Object);
item("variable", triagens::basics::Json(x.first))
("attribute name", triagens::basics::Json(y.first))
("range info", y.second.toJson());
list(item);
}
}
return list;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief clone
////////////////////////////////////////////////////////////////////////////////
RangeInfoMap* clone () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief eraseEmptyOrUndefined remove all empty or undefined RangeInfos for
/// the variable <var> in the RIM
////////////////////////////////////////////////////////////////////////////////
void eraseEmptyOrUndefined (std::string const&);
////////////////////////////////////////////////////////////////////////////////
/// @brief isValid: are all the range infos for the variable <var> valid?
////////////////////////////////////////////////////////////////////////////////
bool isValid (std::string const&) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief attributes: insert attributes of the variable <var> into set
////////////////////////////////////////////////////////////////////////////////
void attributes (std::unordered_set<std::string>& set, std::string const& var) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief return the names of variables contained in the RangeInfoMap
////////////////////////////////////////////////////////////////////////////////
std::unordered_set<std::string> variables() const;
////////////////////////////////////////////////////////////////////////////////
/// @brief private data
/// TODO: make iterators for this i.e. method for begin and end, so that this
/// can be private
////////////////////////////////////////////////////////////////////////////////
std::unordered_map<std::string, std::unordered_map<std::string, RangeInfo>> _ranges;
};
// -----------------------------------------------------------------------------
// --SECTION-- class RangeInfoMapVec
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief class to keep a vector of rangeInfoMapVec associated to variable and
/// attribute names, which will be or-combined
////////////////////////////////////////////////////////////////////////////////
class RangeInfoMapVec {
public:
RangeInfoMapVec (RangeInfoMapVec const& copy) = delete;
RangeInfoMapVec& operator= (RangeInfoMapVec const& copy) = delete;
////////////////////////////////////////////////////////////////////////////////
/// @brief default constructor
////////////////////////////////////////////////////////////////////////////////
RangeInfoMapVec () :
_rangeInfoMapVec() {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor: construct RangeInfoMapVec containing a single
/// RangeInfoMap containing a single RangeInfo.
////////////////////////////////////////////////////////////////////////////////
explicit RangeInfoMapVec (RangeInfoMap* rim);
////////////////////////////////////////////////////////////////////////////////
/// @brief destructor
////////////////////////////////////////////////////////////////////////////////
~RangeInfoMapVec();
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief toString, via Json
////////////////////////////////////////////////////////////////////////////////
std::string toString() const {
return this->toJson().toString();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief toJson
////////////////////////////////////////////////////////////////////////////////
triagens::basics::Json toJson() const {
size_t const n = _rangeInfoMapVec.size();
triagens::basics::Json result(triagens::basics::Json::Array, n);
for (size_t i = 0; i < n; i++) {
result(_rangeInfoMapVec[i]->toJson());
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief operator[]
////////////////////////////////////////////////////////////////////////////////
RangeInfoMap* operator[] (size_t pos) {
return _rangeInfoMapVec[pos];
}
////////////////////////////////////////////////////////////////////////////////
/// @brief size: the number of RangeInfoMaps in the vector
////////////////////////////////////////////////////////////////////////////////
size_t size () const {
return _rangeInfoMapVec.size();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief empty: is the vector of RangeInfoMaps empty
////////////////////////////////////////////////////////////////////////////////
bool empty () const {
return _rangeInfoMapVec.empty();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief reserve space in vector
////////////////////////////////////////////////////////////////////////////////
void reserve (size_t);
////////////////////////////////////////////////////////////////////////////////
/// @brief emplace_back: emplace_back RangeInfoMap in vector
////////////////////////////////////////////////////////////////////////////////
void emplace_back (RangeInfoMap*);
////////////////////////////////////////////////////////////////////////////////
/// @brief eraseEmptyOrUndefined remove all empty or undefined RangeInfos for
/// the variable <var> in every RangeInfoMap in the vector
////////////////////////////////////////////////////////////////////////////////
void eraseEmptyOrUndefined (std::string const& var);
////////////////////////////////////////////////////////////////////////////////
/// @brief find: this is the same as _rangeInfoMapVec[pos]->find(var), i.e. find
/// the map of RangeInfos for the variable <var>.
////////////////////////////////////////////////////////////////////////////////
std::unordered_map<std::string, RangeInfo>* find (std::string const& var, size_t pos) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief differenceRangeInfo: returns the difference of the constant parts of
/// the given RangeInfo and the union of the RangeInfos (for the same var and
/// attr) in the vector. Potentially modifies both the argument and the
/// RangeInfos in the vector.
////////////////////////////////////////////////////////////////////////////////
void differenceRangeInfo (RangeInfo&);
////////////////////////////////////////////////////////////////////////////////
/// @brief isMapped: is the input variable in every RIM in the vector
////////////////////////////////////////////////////////////////////////////////
bool isMapped (std::string const&) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief validPositions: returns a vector of the positions in the RIM vector
/// that contain valid RangeInfoMap for the variable named var
////////////////////////////////////////////////////////////////////////////////
std::vector<size_t> validPositions (std::string const& var) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief attributes: returns a vector of the names of the attributes for the
/// variable var stored in the RIM vector (i.e. stored in some RIM in the
/// vector).
////////////////////////////////////////////////////////////////////////////////
std::unordered_set<std::string> attributes (std::string const& var) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief private data
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
private:
std::vector<RangeInfoMap*> _rangeInfoMapVec;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief andCombineRangeInfoMaps: insert every RangeInfo in the right argument
/// in a new copy of the left argument
////////////////////////////////////////////////////////////////////////////////
RangeInfoMap* andCombineRangeInfoMaps (RangeInfoMap*,
RangeInfoMap const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief orCombineRangeInfoMapVecs: return a new RangeInfoMapVec appending
/// those RIMs in the right arg (which are not identical to an existing RIM) in
/// a copy of the left arg.
///
/// The return RIMV is new unless one of the arguments is empty.
////////////////////////////////////////////////////////////////////////////////
RangeInfoMapVec* orCombineRangeInfoMapVecs (RangeInfoMapVec*,
RangeInfoMapVec*);
////////////////////////////////////////////////////////////////////////////////
/// @brief andCombineRangeInfoMapVecs: return a new RangeInfoMapVec by
/// distributing the AND into the ORs in a condition like:
/// (OR condition) AND (OR condition).
///
/// The return RIMV is new unless one of the arguments is empty.
////////////////////////////////////////////////////////////////////////////////
RangeInfoMapVec* andCombineRangeInfoMapVecs (RangeInfoMapVec*,
RangeInfoMapVec*);
////////////////////////////////////////////////////////////////////////////////
/// @brief andCombineRangeInfoMapVecs: same as before, but will return the
/// mapvec even if one side is a nullptr
////////////////////////////////////////////////////////////////////////////////
RangeInfoMapVec* andCombineRangeInfoMapVecsIgnoreEmpty (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
/// entry is a vector whose entries correspond to the attributes of the
/// index. They are a RangeInfo specifying the condition for that attribute.
/// Note that in the variable range bound case one RangeInfo can contain
/// multiple conditions which are implicitly "AND"ed.
////////////////////////////////////////////////////////////////////////////////
typedef std::vector<RangeInfo> IndexAndCondition;
typedef std::vector<IndexAndCondition> IndexOrCondition;
////////////////////////////////////////////////////////////////////////////////
/// @brief differenceRangeInfos: returns the difference of the constant parts of
/// the given RangeInfos.
///
/// Modifies either lhs or rhs in place, so that the constant parts of lhs
/// and rhs are disjoint, and the union of the modified lhs and rhs equals the
/// union of the originals.
////////////////////////////////////////////////////////////////////////////////
void differenceRangeInfos (RangeInfo&, RangeInfo&);
////////////////////////////////////////////////////////////////////////////////
// @brief areDisjointRangeInfos: returns true if the constant parts of lhs and
// rhs are disjoint and false otherwise.
// Only for range infos with the same variable and attribute
////////////////////////////////////////////////////////////////////////////////
bool areDisjointRangeInfos (RangeInfo const&, RangeInfo const&);
////////////////////////////////////////////////////////////////////////////////
/// @brief areDisjointIndexAndConditions: returns true if the arguments describe
/// disjoint sets.
////////////////////////////////////////////////////////////////////////////////
bool areDisjointIndexAndConditions (IndexAndCondition const&,
IndexAndCondition const&);
////////////////////////////////////////////////////////////////////////////////
/// @brief isContainedIndexAndConditions: returns true if the first argument is
/// contained in the second, and false otherwise.
////////////////////////////////////////////////////////////////////////////////
bool isContainedIndexAndConditions (IndexAndCondition const&,
IndexAndCondition const&);
////////////////////////////////////////////////////////////////////////////////
/// @brief differenceIndexAnd: modifies and1 and and2 in place
/// so that the intersection of the sets they describe is empty and their union
/// is the same as if the function was never called.
////////////////////////////////////////////////////////////////////////////////
void differenceIndexAnd (IndexAndCondition&, IndexAndCondition&);
////////////////////////////////////////////////////////////////////////////////
/// @brief isContainedIndexAndConditions: returns true if the first argument is
/// contained in the second, and false otherwise.
////////////////////////////////////////////////////////////////////////////////
void removeOverlapsIndexOr (IndexOrCondition&);
}
}
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End: