platform/angel_orm/lib/src/query.dart

115 lines
3.6 KiB
Dart
Raw Normal View History

/// Expects a field to be equal to a given [value].
Predicate<T> equals<T>(T value) =>
new Predicate<T>._(PredicateType.equals, value);
2017-06-18 04:19:05 +00:00
/// Expects at least one of the given [predicates] to be true.
Predicate<T> anyOf<T>(Iterable<Predicate<T>> predicates) =>
new MultiPredicate<T>._(PredicateType.any, predicates);
2017-06-24 21:21:32 +00:00
/// Expects a field to be contained within a set of [values].
Predicate<T> isIn<T>(Iterable<T> values) => new Predicate<T>._(PredicateType.isIn, null, values);
2017-07-14 22:04:58 +00:00
/// Expects a field to be `null`.
Predicate<T> isNull<T>() => equals(null);
2017-07-14 22:04:58 +00:00
/// Expects a given [predicate] to not be true.
Predicate<T> not<T>(Predicate<T> predicate) =>
new MultiPredicate<T>._(PredicateType.negate, [predicate]);
2017-07-14 22:04:58 +00:00
/// Expects a field to be not be `null`.
Predicate<T> notNull<T>() => not(isNull());
2017-06-18 04:19:05 +00:00
/// Expects a field to be less than a given [value].
Predicate<T> lessThan<T>(T value) =>
new Predicate<T>._(PredicateType.less, value);
2017-06-18 04:19:05 +00:00
/// Expects a field to be less than or equal to a given [value].
Predicate<T> lessThanOrEqual<T>(T value) => lessThan(value) | equals(value);
2017-06-18 04:19:05 +00:00
/// Expects a field to be greater than a given [value].
Predicate<T> greaterThan<T>(T value) =>
new Predicate<T>._(PredicateType.greater, value);
2017-06-18 04:19:05 +00:00
/// Expects a field to be greater than or equal to a given [value].
Predicate<T> greaterThanOrEqual<T>(T value) =>
greaterThan(value) | equals(value);
2017-06-18 04:19:05 +00:00
/// A generic query class.
///
/// Angel services can translate these into driver-specific queries.
/// This allows the Angel ORM to be flexible and support multiple platforms.
class Query {
final Map<String, Predicate> _fields = {};
final Map<String, SortType> _sort = {};
2017-06-18 04:19:05 +00:00
/// Each field in a query is actually a [Predicate], and therefore acts as a contract
/// with the underlying service.
Map<String, Predicate> get fields =>
new Map<String, Predicate>.unmodifiable(_fields);
2017-06-18 04:19:05 +00:00
/// The sorting order applied to this query.
Map<String, SortType> get sorting =>
new Map<String, SortType>.unmodifiable(_sort);
2017-06-18 04:19:05 +00:00
/// Sets the [Predicate] assigned to the given [key].
void operator []=(String key, Predicate value) => _fields[key] = value;
2017-06-18 04:19:05 +00:00
/// Gets the [Predicate] assigned to the given [key].
Predicate operator [](String key) => _fields[key];
2017-07-14 22:04:58 +00:00
/// Sort output by the given [key].
void sortBy(String key, [SortType type = SortType.descending]) =>
_sort[key] = type;
2017-06-18 04:19:05 +00:00
}
/// A mechanism used to express an expectation about some object ([target]).
class Predicate<T> {
/// The type of expectation we are declaring.
final PredicateType type;
2017-06-18 04:19:05 +00:00
/// The single argument of this target.
final T target;
final Iterable<T> args;
2017-06-18 04:19:05 +00:00
Predicate._(this.type, this.target, [this.args]);
2017-06-18 04:19:05 +00:00
Predicate<T> operator &(Predicate<T> other) => and(other);
2017-07-14 22:04:58 +00:00
Predicate<T> operator |(Predicate<T> other) => or(other);
2017-07-14 22:04:58 +00:00
Predicate<T> and(Predicate<T> other) {
return new MultiPredicate._(PredicateType.and, [this, other]);
2017-07-14 22:04:58 +00:00
}
Predicate<T> or(Predicate<T> other) {
return new MultiPredicate._(PredicateType.or, [this, other]);
2017-07-14 22:04:58 +00:00
}
2017-06-18 04:19:05 +00:00
}
/// An advanced [Predicate] that performs an operation of multiple other predicates.
class MultiPredicate<T> extends Predicate<T> {
final Iterable<Predicate<T>> targets;
2017-07-14 22:04:58 +00:00
MultiPredicate._(PredicateType type, this.targets) : super._(type, null);
2017-07-14 22:04:58 +00:00
/// Use [targets] instead.
@deprecated
T get target => throw new UnsupportedError(
'IterablePredicate has no `target`. Use `targets` instead.');
2017-06-18 04:19:05 +00:00
}
/// The various types of predicate.
enum PredicateType {
equals,
any,
isIn,
negate,
and,
or,
less,
greater,
2017-06-18 04:19:05 +00:00
}
/// The various modes of sorting.
enum SortType { ascending, descending }