Replace utils::Border with utils::Bound

Summary:
The new Bound class does not have comparison operators defined. The
reason being, we want to support having values which we may not want to
compare. For example, having an Expression which should first be
evaluated and then compared.

Reviewers: florijan, mislav.bradac, buda

Reviewed By: florijan

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D520
This commit is contained in:
Teon Banek 2017-07-03 16:41:10 +02:00
parent 1841ff9616
commit 1f7a146b95
4 changed files with 42 additions and 77 deletions

View File

@ -294,17 +294,17 @@ std::unique_ptr<Cursor> ScanAllByLabelPropertyRange::MakeCursor(
auto vertices = [this, &db, is_less](Frame &frame, auto vertices = [this, &db, is_less](Frame &frame,
const SymbolTable &symbol_table) { const SymbolTable &symbol_table) {
ExpressionEvaluator evaluator(frame, symbol_table, db, graph_view_); ExpressionEvaluator evaluator(frame, symbol_table, db, graph_view_);
auto lower_val = lower_bound_ ? lower_bound_->expression->Accept(evaluator) auto lower_val = lower_bound_ ? lower_bound_->value()->Accept(evaluator)
: TypedValue::Null; : TypedValue::Null;
auto upper_val = upper_bound_ ? upper_bound_->expression->Accept(evaluator) auto upper_val = upper_bound_ ? upper_bound_->value()->Accept(evaluator)
: TypedValue::Null; : TypedValue::Null;
return iter::filter( return iter::filter(
[this, lower_val, upper_val, is_less](const VertexAccessor &vertex) { [this, lower_val, upper_val, is_less](const VertexAccessor &vertex) {
TypedValue value = vertex.PropsAt(property_); TypedValue value = vertex.PropsAt(property_);
debug_assert(!value.IsNull(), "Unexpected property with Null value"); debug_assert(!value.IsNull(), "Unexpected property with Null value");
if (lower_bound_ && is_less(value, lower_val, lower_bound_->type)) if (lower_bound_ && is_less(value, lower_val, lower_bound_->type()))
return false; return false;
if (upper_bound_ && is_less(upper_val, value, upper_bound_->type)) if (upper_bound_ && is_less(upper_val, value, upper_bound_->type()))
return false; return false;
return true; return true;
}, },

View File

@ -14,6 +14,7 @@
#include "query/common.hpp" #include "query/common.hpp"
#include "query/exceptions.hpp" #include "query/exceptions.hpp"
#include "query/frontend/semantic/symbol_table.hpp" #include "query/frontend/semantic/symbol_table.hpp"
#include "utils/bound.hpp"
#include "utils/hashing/fnv.hpp" #include "utils/hashing/fnv.hpp"
#include "utils/visitor.hpp" #include "utils/visitor.hpp"
@ -353,20 +354,8 @@ class ScanAllByLabel : public ScanAll {
*/ */
class ScanAllByLabelPropertyRange : public ScanAll { class ScanAllByLabelPropertyRange : public ScanAll {
public: public:
/** Defines a bounding value for a range. */ /** Bound with expression which when evaluated produces the bound value. */
struct Bound { using Bound = utils::Bound<Expression *>;
/**
* Determines whether the value of bound expression should be included or
* excluded.
*/
enum class Type { INCLUSIVE, EXCLUSIVE };
/** Expression which when evaluated will produce a value for the bound. */
Expression *expression;
/** Whether the bound is inclusive or exclusive. */
Type type;
};
/** /**
* Constructs the operator for given label and property value in range * Constructs the operator for given label and property value in range
* (inclusive). * (inclusive).

View File

@ -1,59 +0,0 @@
#pragma once
#include "utils/option.hpp"
#include "utils/total_ordering.hpp"
// Defines Including as [ and Excluding < for ranges.
enum BorderType {
Including = 0,
Excluding = 1,
};
// If key is not present he is both the largest and the smallest of the keys.
template <class T>
class Border {
public:
Border() : key(Option<T>()), type(Including) {}
Border(T Tey, BorderType type) : key(Option<T>(std::move(key))), type(type) {}
// Border(Border &other) = default;
Border(Border &other) = default;
Border(Border &&other) = default;
Border &operator=(Border &&other) = default;
Border &operator=(Border &other) = default;
friend bool operator<(const Border<T> &a, const T &other) {
return !a.key.is_present() ||
(a.type == Excluding && a.key.get() <= other) ||
(a.type == Including && a.key.get() < other);
}
friend bool operator==(const Border<T> &a, const T &other) {
return a.type == Including && a.key.is_present() && a.key.get() == other;
}
friend bool operator>(const Border<T> &a, const T &other) {
return !a.key.is_present() ||
(a.type == Excluding && a.key.get() >= other) ||
(a.type == Including && a.key.get() > other);
}
friend bool operator!=(const Border<T> &a, const T &b) { return !(a == b); }
friend bool operator<=(const Border<T> &a, const T &b) {
return a < b || a == b;
}
friend bool operator>=(const Border<T> &a, const T &b) {
return a > b || a == b;
}
Option<T> key;
BorderType type;
};
template <class T>
auto make_inf_border() {
return Border<T>();
}

35
src/utils/bound.hpp Normal file
View File

@ -0,0 +1,35 @@
#pragma once
namespace utils {
/**
* Determines whether the value of bound expression should be included or
* excluded.
*/
enum class BoundType { INCLUSIVE, EXCLUSIVE };
/** Defines a bounding value for a range. */
template <typename TValue>
class Bound {
public:
using Type = BoundType;
Bound(TValue value, Type type) : value_(value), type_(type) {}
Bound(const Bound &other) = default;
Bound(Bound &&other) = default;
Bound &operator=(const Bound &other) = default;
Bound &operator=(Bound &&other) = default;
/** Value for the bound. */
const auto &value() const { return value_; }
/** Whether the bound is inclusive or exclusive. */
auto type() const { return type_; }
private:
TValue value_;
Type type_;
};
} // namespace utils