This commit is contained in:
Tobe O 2019-01-22 19:46:49 -05:00
parent 5ed22259c3
commit 554407d159
4 changed files with 134 additions and 14 deletions

View file

@ -1,3 +1,6 @@
# 2.0.0-dev.16
* Add `MapSqlExpressionBuilder` for JSON/JSONB support.
# 2.0.0-dev.15
* Remove `Column.defaultValue`.
* Deprecate `toSql` and `sanitizeExpression`.

View file

@ -34,11 +34,15 @@ String sanitizeExpression(String unsafe) {
abstract class SqlExpressionBuilder<T> {
final Query query;
final String columnName;
bool _isProperty = false;
String _substitution;
SqlExpressionBuilder(this.query, this.columnName);
String get substitution => _substitution ??= query.reserveName(columnName);
String get substitution {
var c = _isProperty ? 'prop' : columnName;
return _substitution ??= query.reserveName(c);
}
bool get hasValue;
@ -400,28 +404,71 @@ class DateTimeSqlExpressionBuilder extends SqlExpressionBuilder<DateTime> {
}
}
class MapSqlExpressionBuilder<K, V, Key extends SqlExpressionBuilder<K>,
Value extends SqlExpressionBuilder<V>> extends SqlExpressionBuilder {
final Key key;
final Value value;
class MapSqlExpressionBuilder extends SqlExpressionBuilder {
bool _hasValue = false;
Map _value;
String _op;
String _raw;
MapSqlExpressionBuilder(Query query, String columnName, this.key, this.value)
MapSqlExpressionBuilder(Query query, String columnName)
: super(query, columnName);
MapSqlExpressionBuilderProperty operator [](String name) {
return MapSqlExpressionBuilderProperty(this, name);
}
bool get hasRaw => _raw != null;
@override
bool get hasValue => _hasValue;
UnsupportedError _unsupported() =>
UnsupportedError('JSON/JSONB does not support this operation.');
@override
String compile() {
var parts = <String>[_raw, key.compile(), value.compile()];
parts.removeWhere((s) => s == null);
return parts.isEmpty ? null : parts.join(' && ');
void _append(SqlExpressionBuilder b) {
var c = b.compile();
if (c != null) {
_hasValue = true;
_raw ??= '';
if (b is! DateTimeSqlExpressionBuilder) {
_raw += '${b.columnName} ';
}
_raw += c;
}
}
bool _change(String op, Map value) {
_raw = null;
_op = op;
_value = value;
query.substitutionValues[substitution] = _value;
return _hasValue = true;
}
@override
bool get hasValue => key.hasValue || value.hasValue || _hasValue;
String compile() {
if (_raw != null) return _raw;
if (_value == null) return null;
return "::jsonb $_op @$substitution::jsonb";
}
void contains(Map value) {
_change('@>', value);
}
void containsKey(String key) {
this[key].isNotNull();
}
void containsPair(key, value) {
contains({key: value});
}
void equals(Map value) {
_change('=', value);
}
@override
void isBetween(lower, upper) => throw _unsupported();
@ -435,3 +482,72 @@ class MapSqlExpressionBuilder<K, V, Key extends SqlExpressionBuilder<K>,
@override
void isNotIn(Iterable values) => throw _unsupported();
}
class MapSqlExpressionBuilderProperty {
final MapSqlExpressionBuilder builder;
final String name;
MapSqlExpressionBuilderProperty(this.builder, this.name);
void isNotNull() {
builder
.._hasValue = true
.._raw ??= ''
.._raw += "${builder.columnName}->>'$name' IS NOT NULL";
}
void isNull() {
builder
.._hasValue = true
.._raw ??= ''
.._raw += "${builder.columnName}->>'$name' IS NULL";
}
void asString(void Function(StringSqlExpressionBuilder) f) {
var b = StringSqlExpressionBuilder(
builder.query, "${builder.columnName}->>'$name'")
.._isProperty = true;
f(b);
builder._append(b);
}
void asBool(void Function(BooleanSqlExpressionBuilder) f) {
var b = BooleanSqlExpressionBuilder(
builder.query, "${builder.columnName}->>'$name'")
.._isProperty = true;
f(b);
builder._append(b);
}
void asDateTime(void Function(DateTimeSqlExpressionBuilder) f) {
var b = DateTimeSqlExpressionBuilder(
builder.query, "${builder.columnName}->>'$name'")
.._isProperty = true;
f(b);
builder._append(b);
}
void asDouble(void Function(NumericSqlExpressionBuilder<double>) f) {
var b = NumericSqlExpressionBuilder<double>(
builder.query, "${builder.columnName}->>'$name'")
.._isProperty = true;
f(b);
builder._append(b);
}
void asInt(void Function(NumericSqlExpressionBuilder<int>) f) {
var b = NumericSqlExpressionBuilder<int>(
builder.query, "${builder.columnName}->>'$name'")
.._isProperty = true;
f(b);
builder._append(b);
}
void asMap(void Function(MapSqlExpressionBuilder) f) {
var b = MapSqlExpressionBuilder(
builder.query, "${builder.columnName}->>'$name'")
.._isProperty = true;
f(b);
builder._append(b);
}
}

View file

@ -420,7 +420,8 @@ abstract class QueryWhere {
if (tableName != null) key = '$tableName.$key';
if (builder.hasValue) {
if (i++ > 0) b.write(' AND ');
if (builder is DateTimeSqlExpressionBuilder) {
if (builder is DateTimeSqlExpressionBuilder ||
(builder is MapSqlExpressionBuilder && builder.hasRaw)) {
if (tableName != null) b.write('$tableName.');
b.write(builder.compile());
} else {

View file

@ -1,5 +1,5 @@
name: angel_orm
version: 2.0.0-dev.15
version: 2.0.0-dev.16
description: Runtime support for Angel's ORM. Includes base classes for queries.
author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/orm