fix lists + double

This commit is contained in:
Tobe O 2019-01-26 23:14:20 -05:00
parent 50c4b394c7
commit 24fb936a86
24 changed files with 295 additions and 91 deletions

View file

@ -1,3 +1,7 @@
# 2.0.0-dev.19
* Implement cast-based `double` support.
* Finish `ListSqlExpressionBuilder`.
# 2.0.0-dev.18
* Add `ListSqlExpressionBuilder` (still in development).

View file

@ -36,6 +36,7 @@ String sanitizeExpression(String unsafe) {
abstract class SqlExpressionBuilder<T> {
final Query query;
final String columnName;
String _cast;
bool _isProperty = false;
String _substitution;
@ -75,7 +76,10 @@ class NumericSqlExpressionBuilder<T extends num>
String compile() {
if (_raw != null) return _raw;
if (_value == null) return null;
return '$_op $_value';
var v = _value.toString();
if (T == double) v = 'CAST ("$v" as decimal)';
if (_cast != null) v = 'CAST ($v AS $_cast)';
return '$_op $v';
}
operator <(T value) => _change('<', value);
@ -306,6 +310,7 @@ class BooleanSqlExpressionBuilder extends SqlExpressionBuilder<bool> {
if (_raw != null) return _raw;
if (_value == null) return null;
var v = _value ? 'TRUE' : 'FALSE';
if (_cast != null) v = 'CAST ($v AS $_cast)';
return '$_op $v';
}
@ -555,17 +560,16 @@ class JsonSqlExpressionBuilderProperty {
throw StateError(
'$nameString is already typed as $_typed, and cannot be changed.');
} else {
_typed = value().._isProperty = true;
_typed = value()
.._cast = 'text'
.._isProperty = true;
return _typed as T;
}
}
String get nameString {
if (isInt) {
return '(${builder.columnName}->>$name)::jsonb';
} else {
return "(${builder.columnName}->>'$name')::jsonb";
}
var n = isInt ? name : "'$name'";
return '${builder.columnName}::jsonb->>$n';
}
void isNotNull() {

View file

@ -7,6 +7,10 @@ bool isAscii(int ch) => ch >= $nul && ch <= $del;
/// A base class for objects that compile to SQL queries, typically within an ORM.
abstract class QueryBase<T> {
/// Casts to perform when querying the database.
Map<String, String> get casts => {};
/// Values to insert into a prepared statement.
final Map<String, dynamic> substitutionValues = {};
/// The list of fields returned by this query.
@ -15,15 +19,18 @@ abstract class QueryBase<T> {
List<String> get fields;
/// A String of all [fields], joined by a comma (`,`).
String get fieldSet => fields.join(', ');
String get fieldSet => fields.map((k) {
var cast = casts[k];
return cast == null ? k : 'CAST ($k AS $cast)';
}).join(', ');
String compile(
String compile(Set<String> trampoline,
{bool includeTableName: false, String preamble, bool withFields: true});
T deserialize(List row);
Future<List<T>> get(QueryExecutor executor) async {
var sql = compile();
var sql = compile(Set());
return executor
.query(sql, substitutionValues)
.then((it) => it.map(deserialize).toList());
@ -187,52 +194,77 @@ abstract class Query<T, Where extends QueryWhere> extends QueryBase<T> {
String _joinAlias() => 'a${_joins.length}';
String _compileJoin(tableName, Set<String> trampoline) {
if (tableName is String) return tableName;
if (tableName is Query) {
var c = tableName.compile(trampoline);
if (c == null) return c;
return '($c)';
}
throw ArgumentError.value(
tableName, 'tableName', 'must be a String or Query');
}
/// Execute an `INNER JOIN` against another table.
void join(String tableName, String localKey, String foreignKey,
{String op: '=', List<String> additionalFields: const []}) {
_joins.add(new JoinBuilder(
JoinType.inner, this, tableName, localKey, foreignKey,
void join(tableName, String localKey, String foreignKey,
{String op: '=',
List<String> additionalFields: const [],
Set<String> trampoline}) {
_joins.add(new JoinBuilder(JoinType.inner, this,
_compileJoin(tableName, trampoline ?? Set()), localKey, foreignKey,
op: op, alias: _joinAlias(), additionalFields: additionalFields));
}
/// Execute a `LEFT JOIN` against another table.
void leftJoin(String tableName, String localKey, String foreignKey,
{String op: '=', List<String> additionalFields: const []}) {
_joins.add(new JoinBuilder(
JoinType.left, this, tableName, localKey, foreignKey,
void leftJoin(tableName, String localKey, String foreignKey,
{String op: '=',
List<String> additionalFields: const [],
Set<String> trampoline}) {
_joins.add(new JoinBuilder(JoinType.left, this,
_compileJoin(tableName, trampoline ?? Set()), localKey, foreignKey,
op: op, alias: _joinAlias(), additionalFields: additionalFields));
}
/// Execute a `RIGHT JOIN` against another table.
void rightJoin(String tableName, String localKey, String foreignKey,
{String op: '=', List<String> additionalFields: const []}) {
_joins.add(new JoinBuilder(
JoinType.right, this, tableName, localKey, foreignKey,
void rightJoin(tableName, String localKey, String foreignKey,
{String op: '=',
List<String> additionalFields: const [],
Set<String> trampoline}) {
_joins.add(new JoinBuilder(JoinType.right, this,
_compileJoin(tableName, trampoline ?? Set()), localKey, foreignKey,
op: op, alias: _joinAlias(), additionalFields: additionalFields));
}
/// Execute a `FULL OUTER JOIN` against another table.
void fullOuterJoin(String tableName, String localKey, String foreignKey,
{String op: '=', List<String> additionalFields: const []}) {
_joins.add(new JoinBuilder(
JoinType.full, this, tableName, localKey, foreignKey,
void fullOuterJoin(tableName, String localKey, String foreignKey,
{String op: '=',
List<String> additionalFields: const [],
Set<String> trampoline}) {
_joins.add(new JoinBuilder(JoinType.full, this,
_compileJoin(tableName, trampoline ?? Set()), localKey, foreignKey,
op: op, alias: _joinAlias(), additionalFields: additionalFields));
}
/// Execute a `SELF JOIN`.
void selfJoin(String tableName, String localKey, String foreignKey,
{String op: '=', List<String> additionalFields: const []}) {
_joins.add(new JoinBuilder(
JoinType.self, this, tableName, localKey, foreignKey,
void selfJoin(tableName, String localKey, String foreignKey,
{String op: '=',
List<String> additionalFields: const [],
Set<String> trampoline}) {
_joins.add(new JoinBuilder(JoinType.self, this,
_compileJoin(tableName, trampoline ?? Set()), localKey, foreignKey,
op: op, alias: _joinAlias(), additionalFields: additionalFields));
}
@override
String compile(
String compile(Set<String> trampoline,
{bool includeTableName: false,
String preamble,
bool withFields: true,
String fromQuery}) {
if (!trampoline.add(tableName)) {
return null;
}
includeTableName = includeTableName || _joins.isNotEmpty;
var b = new StringBuffer(preamble ?? 'SELECT');
b.write(' ');
@ -241,8 +273,12 @@ abstract class Query<T, Where extends QueryWhere> extends QueryBase<T> {
if (fields == null) {
f = ['*'];
} else {
f = new List<String>.from(
fields.map((s) => includeTableName ? '$tableName.$s' : s));
f = new List<String>.from(fields.map((s) {
var ss = includeTableName ? '$tableName.$s' : s;
var cast = casts[s];
if (cast != null) ss = 'CAST ($ss AS $cast)';
return ss;
}));
_joins.forEach((j) {
f
..add(j.fieldName)
@ -256,7 +292,10 @@ abstract class Query<T, Where extends QueryWhere> extends QueryBase<T> {
// No joins if it's not a select.
if (preamble == null) {
if (_crossJoin != null) b.write(' CROSS JOIN $_crossJoin');
for (var join in _joins) b.write(' ${join.compile()}');
for (var join in _joins) {
var c = join.compile();
if (c != null) b.write(' $c');
}
}
var whereClause =
@ -276,7 +315,7 @@ abstract class Query<T, Where extends QueryWhere> extends QueryBase<T> {
}
Future<List<T>> delete(QueryExecutor executor) {
var sql = compile(preamble: 'DELETE', withFields: false);
var sql = compile(Set(), preamble: 'DELETE', withFields: false);
if (_joins.isEmpty) {
return executor
@ -305,7 +344,7 @@ abstract class Query<T, Where extends QueryWhere> extends QueryBase<T> {
} else {
// TODO: How to do this in a non-Postgres DB?
var returning = fields.map(adornWithTableName).join(', ');
var sql = compile();
var sql = compile(Set());
sql = 'WITH $tableName as ($insertion RETURNING $returning) ' + sql;
return executor
.query(sql, substitutionValues)
@ -326,7 +365,7 @@ abstract class Query<T, Where extends QueryWhere> extends QueryBase<T> {
if (_limit != null) updateSql.write(' LIMIT $_limit');
var returning = fields.map(adornWithTableName).join(', ');
var sql = compile();
var sql = compile(Set());
sql = 'WITH $tableName as ($updateSql RETURNING $returning) ' + sql;
return executor
@ -480,10 +519,12 @@ class Union<T> extends QueryBase<T> {
T deserialize(List row) => left.deserialize(row);
@override
String compile(
String compile(Set<String> trampoline,
{bool includeTableName: false, String preamble, bool withFields: true}) {
var selector = all == true ? 'UNION ALL' : 'UNION';
return '(${left.compile(includeTableName: includeTableName)}) $selector (${right.compile(includeTableName: includeTableName)})';
var t1 = Set<String>.from(trampoline);
var t2 = Set<String>.from(trampoline);
return '(${left.compile(t1, includeTableName: includeTableName)}) $selector (${right.compile(t2, includeTableName: includeTableName)})';
}
}
@ -495,7 +536,10 @@ class JoinBuilder {
final List<String> additionalFields;
JoinBuilder(this.type, this.from, this.to, this.key, this.value,
{this.op: '=', this.alias, this.additionalFields: const []});
{this.op: '=', this.alias, this.additionalFields: const []}) {
assert(to != null,
'computation of this join threw an error, and returned null.');
}
String get fieldName {
var right = '$to.$value';
@ -510,6 +554,7 @@ class JoinBuilder {
}
String compile() {
if (to == null) return null;
var b = new StringBuffer();
var left = '${from.tableName}.$key';
var right = fieldName;

View file

@ -1,5 +1,5 @@
name: angel_orm
version: 2.0.0-dev.18
version: 2.0.0-dev.19
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

View file

@ -1,3 +1,7 @@
# 2.0.0-dev.5
* Implement cast-based `double` support.
* Finish `ListSqlExpressionBuilder`.
# 2.0.0-dev.4
* List generation support.

View file

@ -11,6 +11,14 @@ import 'package:source_gen/source_gen.dart';
import 'orm_build_context.dart';
var floatTypes = [
ColumnType.decimal,
ColumnType.float,
ColumnType.numeric,
ColumnType.real,
const ColumnType('double precision'),
];
Builder ormBuilder(BuilderOptions options) {
return new SharedPartBuilder([
new OrmGenerator(
@ -68,6 +76,28 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
]);
});
// Override casts so that we can cast doubles
clazz.methods.add(Method((b) {
b
..name = 'casts'
..annotations.add(refer('override'))
..type = MethodType.getter
..body = Block((b) {
var args = <String, Expression>{};
for (var field in ctx.effectiveFields) {
var name = ctx.buildContext.resolveFieldName(field.name);
var type = ctx.columns[field.name]?.type;
if (type == null) continue;
if (floatTypes.contains(type)) {
args[name] = literalString('text');
}
}
b.addExpression(literalMap(args).returned);
});
}));
// Add values
clazz.fields.add(new Field((b) {
var type = refer('${rc.pascalCase}QueryValues');
@ -158,6 +188,10 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
expr = refer('json')
.property('decode')
.call([expr.asA(refer('String'))]).asA(type);
} else if (floatTypes.contains(ctx.columns[field.name]?.type)) {
expr = refer('double')
.property('parse')
.call([expr.property('toString').call([])]);
} else if (fType is InterfaceType && fType.element.isEnum) {
expr = type.property('values').index(expr.asA(refer('int')));
} else
@ -222,7 +256,18 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
// If there are any relations, we need some overrides.
clazz.constructors.add(new Constructor((b) {
b
..optionalParameters.add(Parameter((b) => b
..named = true
..name = 'trampoline'
..type = TypeReference((b) => b
..symbol = 'Set'
..types.add(refer('String')))))
..body = new Block((b) {
b.statements.addAll([
Code('trampoline ??= Set();'),
Code('trampoline.add(tableName);'),
]);
// Add a constructor that initializes _where
b.addExpression(
refer('_where')
@ -248,16 +293,10 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
var foreignQueryType =
foreign.buildContext.modelClassNameRecase.pascalCase +
'Query';
var compiledSubquery = refer(foreignQueryType)
.newInstance([])
.property('compile')
.call([]);
joinArgs.insert(
0,
literalString('(')
.operatorAdd(compiledSubquery)
.operatorAdd(literalString(')')));
refer(foreignQueryType).newInstance(
[], {'trampoline': refer('trampoline')}));
} else {
joinArgs.insert(0, literalString(foreign.tableName));
}
@ -580,11 +619,13 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
for (var field in ctx.effectiveFields) {
var fType = field.type;
var name = ctx.buildContext.resolveFieldName(field.name);
var type = ctx.columns[field.name]?.type?.name;
var type = ctx.columns[field.name]?.type;
if (type == null) continue;
if (const TypeChecker.fromRuntime(List)
.isAssignableFromType(fType)) {
args[name] = literalString(type);
args[name] = literalString(type.name);
} else if (floatTypes.contains(type)) {
args[name] = literalString(type.name);
}
}
@ -612,6 +653,10 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
value = refer('json')
.property('decode')
.call([value.asA(refer('String'))]).asA(refer('List'));
} else if (floatTypes.contains(ctx.columns[field.name]?.type)) {
value = refer('double')
.property('parse')
.call([value.asA(refer('String'))]);
} else {
value = value.asA(type);
}
@ -631,6 +676,8 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
} else if (const TypeChecker.fromRuntime(List)
.isAssignableFromType(fType)) {
value = refer('json').property('encode').call([value]);
} else if (floatTypes.contains(ctx.columns[field.name]?.type)) {
value = value.property('toString').call([]);
}
b

View file

@ -1,5 +1,5 @@
name: angel_orm_generator
version: 2.0.0-dev.4
version: 2.0.0-dev.5
description: Code generators for Angel's ORM. Generates query builder classes.
author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/orm

View file

@ -54,7 +54,7 @@ main() {
test('select one', () async {
var query = new BookQuery();
query.where.id.equals(int.parse(deathlyHallows.id));
print(query.compile());
print(query.compile(Set()));
var book = await query.getOne(executor);
print(book.toJson());
@ -71,7 +71,7 @@ main() {
var query = new BookQuery()
..where.name.equals('Goblet of Fire')
..orWhere((w) => w.authorId.equals(int.parse(jkRowling.id)));
print(query.compile());
print(query.compile(Set()));
var books = await query.get(executor);
expect(books, hasLength(1));
@ -95,7 +95,7 @@ main() {
query1
..union(query2)
..unionAll(query3);
print(query1.compile());
print(query1.compile(Set()));
var books = await query1.get(executor);
expect(books, hasLength(1));
@ -120,7 +120,7 @@ main() {
test('delete stream', () async {
var query = new BookQuery()..where.name.equals(deathlyHallows.name);
print(query.compile());
print(query.compile(Set()));
var books = await query.delete(executor);
expect(books, hasLength(1));

View file

@ -28,7 +28,7 @@ main() {
test('can fetch one foot', () async {
var footQuery = new FootQuery()
..values.legId = int.parse(originalLeg.id)
..values.nToes = 5;
..values.nToes = 5.64;
var legQuery = new LegQuery()..where.id.equals(int.parse(originalLeg.id));
var foot = await footQuery.insert(executor);
var leg = await legQuery.getOne(executor);
@ -57,7 +57,7 @@ main() {
test('sets foot on update', () async {
var footQuery = new FootQuery()
..values.legId = int.parse(originalLeg.id)
..values.nToes = 5;
..values.nToes = 5.64;
var legQuery = new LegQuery()
..where.id.equals(int.parse(originalLeg.id))
..values.copyFrom(originalLeg.copyWith(name: 'Right'));
@ -73,7 +73,7 @@ main() {
test('sets foot on delete', () async {
var footQuery = new FootQuery()
..values.legId = int.parse(originalLeg.id)
..values.nToes = 5;
..values.nToes = 5.64;
var legQuery = new LegQuery()..where.id.equals(int.parse(originalLeg.id));
var foot = await footQuery.insert(executor);
var leg = await legQuery.deleteOne(executor);

View file

@ -1,4 +1,4 @@
CREATE TEMPORARY TABLE "user_roles" (
CREATE TEMPORARY TABLE "role_users" (
"id" serial PRIMARY KEY,
"user_id" int NOT NULL,
"role_id" int NOT NULL,

View file

@ -28,7 +28,9 @@ class AuthorMigration extends Migration {
// **************************************************************************
class AuthorQuery extends Query<Author, AuthorQueryWhere> {
AuthorQuery() {
AuthorQuery({Set<String> trampoline}) {
trampoline ??= Set();
trampoline.add(tableName);
_where = new AuthorQueryWhere(this);
}
@ -37,6 +39,11 @@ class AuthorQuery extends Query<Author, AuthorQueryWhere> {
AuthorQueryWhere _where;
@override
get casts {
return {};
}
@override
get tableName {
return 'authors';

View file

@ -30,7 +30,9 @@ class BookMigration extends Migration {
// **************************************************************************
class BookQuery extends Query<Book, BookQueryWhere> {
BookQuery() {
BookQuery({Set<String> trampoline}) {
trampoline ??= Set();
trampoline.add(tableName);
_where = new BookQueryWhere(this);
leftJoin('authors', 'author_id', 'id',
additionalFields: const ['name', 'created_at', 'updated_at']);
@ -43,6 +45,11 @@ class BookQuery extends Query<Book, BookQueryWhere> {
BookQueryWhere _where;
@override
get casts {
return {};
}
@override
get tableName {
return 'books';

View file

@ -31,7 +31,9 @@ class CarMigration extends Migration {
// **************************************************************************
class CarQuery extends Query<Car, CarQueryWhere> {
CarQuery() {
CarQuery({Set<String> trampoline}) {
trampoline ??= Set();
trampoline.add(tableName);
_where = new CarQueryWhere(this);
}
@ -40,6 +42,11 @@ class CarQuery extends Query<Car, CarQueryWhere> {
CarQueryWhere _where;
@override
get casts {
return {};
}
@override
get tableName {
return 'cars';

View file

@ -27,7 +27,9 @@ class CustomerMigration extends Migration {
// **************************************************************************
class CustomerQuery extends Query<Customer, CustomerQueryWhere> {
CustomerQuery() {
CustomerQuery({Set<String> trampoline}) {
trampoline ??= Set();
trampoline.add(tableName);
_where = new CustomerQueryWhere(this);
}
@ -36,6 +38,11 @@ class CustomerQuery extends Query<Customer, CustomerQueryWhere> {
CustomerQueryWhere _where;
@override
get casts {
return {};
}
@override
get tableName {
return 'customers';

View file

@ -9,5 +9,7 @@ part 'foot.g.dart';
@serializable
@Orm(tableName: 'feet')
class _Foot extends Model {
int legId, nToes;
int legId;
double nToes;
}

View file

@ -12,7 +12,7 @@ class FootMigration extends Migration {
schema.create('feet', (table) {
table.serial('id')..primaryKey();
table.integer('leg_id');
table.integer('n_toes');
table.declare('n_toes', new ColumnType('decimal'));
table.timeStamp('created_at');
table.timeStamp('updated_at');
});
@ -29,7 +29,9 @@ class FootMigration extends Migration {
// **************************************************************************
class FootQuery extends Query<Foot, FootQueryWhere> {
FootQuery() {
FootQuery({Set<String> trampoline}) {
trampoline ??= Set();
trampoline.add(tableName);
_where = new FootQueryWhere(this);
}
@ -38,6 +40,11 @@ class FootQuery extends Query<Foot, FootQueryWhere> {
FootQueryWhere _where;
@override
get casts {
return {'n_toes': 'text'};
}
@override
get tableName {
return 'feet';
@ -63,7 +70,7 @@ class FootQuery extends Query<Foot, FootQueryWhere> {
var model = new Foot(
id: row[0].toString(),
legId: (row[1] as int),
nToes: (row[2] as int),
nToes: double.parse(row[2].toString()),
createdAt: (row[3] as DateTime),
updatedAt: (row[4] as DateTime));
return model;
@ -79,7 +86,7 @@ class FootQueryWhere extends QueryWhere {
FootQueryWhere(FootQuery query)
: id = new NumericSqlExpressionBuilder<int>(query, 'id'),
legId = new NumericSqlExpressionBuilder<int>(query, 'leg_id'),
nToes = new NumericSqlExpressionBuilder<int>(query, 'n_toes'),
nToes = new NumericSqlExpressionBuilder<double>(query, 'n_toes'),
createdAt = new DateTimeSqlExpressionBuilder(query, 'created_at'),
updatedAt = new DateTimeSqlExpressionBuilder(query, 'updated_at');
@ -87,7 +94,7 @@ class FootQueryWhere extends QueryWhere {
final NumericSqlExpressionBuilder<int> legId;
final NumericSqlExpressionBuilder<int> nToes;
final NumericSqlExpressionBuilder<double> nToes;
final DateTimeSqlExpressionBuilder createdAt;
@ -102,7 +109,7 @@ class FootQueryWhere extends QueryWhere {
class FootQueryValues extends MapQueryValues {
@override
get casts {
return {};
return {'n_toes': 'decimal'};
}
int get id {
@ -115,11 +122,11 @@ class FootQueryValues extends MapQueryValues {
}
set legId(int value) => values['leg_id'] = value;
int get nToes {
return (values['n_toes'] as int);
double get nToes {
return double.parse((values['n_toes'] as String));
}
set nToes(int value) => values['n_toes'] = value;
set nToes(double value) => values['n_toes'] = value.toString();
DateTime get createdAt {
return (values['created_at'] as DateTime);
}
@ -153,7 +160,7 @@ class Foot extends _Foot {
final int legId;
@override
final int nToes;
final double nToes;
@override
final DateTime createdAt;
@ -164,7 +171,7 @@ class Foot extends _Foot {
Foot copyWith(
{String id,
int legId,
int nToes,
double nToes,
DateTime createdAt,
DateTime updatedAt}) {
return new Foot(
@ -203,7 +210,7 @@ abstract class FootSerializer {
return new Foot(
id: map['id'] as String,
legId: map['leg_id'] as int,
nToes: map['n_toes'] as int,
nToes: map['n_toes'] as double,
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? (map['created_at'] as DateTime)

View file

@ -29,7 +29,9 @@ class FruitMigration extends Migration {
// **************************************************************************
class FruitQuery extends Query<Fruit, FruitQueryWhere> {
FruitQuery() {
FruitQuery({Set<String> trampoline}) {
trampoline ??= Set();
trampoline.add(tableName);
_where = new FruitQueryWhere(this);
}
@ -38,6 +40,11 @@ class FruitQuery extends Query<Fruit, FruitQueryWhere> {
FruitQueryWhere _where;
@override
get casts {
return {};
}
@override
get tableName {
return 'fruits';

View file

@ -28,7 +28,9 @@ class HasCarMigration extends Migration {
// **************************************************************************
class HasCarQuery extends Query<HasCar, HasCarQueryWhere> {
HasCarQuery() {
HasCarQuery({Set<String> trampoline}) {
trampoline ??= Set();
trampoline.add(tableName);
_where = new HasCarQueryWhere(this);
}
@ -37,6 +39,11 @@ class HasCarQuery extends Query<HasCar, HasCarQueryWhere> {
HasCarQueryWhere _where;
@override
get casts {
return {};
}
@override
get tableName {
return 'has_cars';

View file

@ -26,7 +26,9 @@ class HasMapMigration extends Migration {
// **************************************************************************
class HasMapQuery extends Query<HasMap, HasMapQueryWhere> {
HasMapQuery() {
HasMapQuery({Set<String> trampoline}) {
trampoline ??= Set();
trampoline.add(tableName);
_where = new HasMapQueryWhere(this);
}
@ -35,6 +37,11 @@ class HasMapQuery extends Query<HasMap, HasMapQueryWhere> {
HasMapQueryWhere _where;
@override
get casts {
return {};
}
@override
get tableName {
return 'has_maps';

View file

@ -28,7 +28,9 @@ class LegMigration extends Migration {
// **************************************************************************
class LegQuery extends Query<Leg, LegQueryWhere> {
LegQuery() {
LegQuery({Set<String> trampoline}) {
trampoline ??= Set();
trampoline.add(tableName);
_where = new LegQueryWhere(this);
leftJoin('feet', 'id', 'leg_id', additionalFields: const [
'leg_id',
@ -43,6 +45,11 @@ class LegQuery extends Query<Leg, LegQueryWhere> {
LegQueryWhere _where;
@override
get casts {
return {};
}
@override
get tableName {
return 'legs';

View file

@ -31,7 +31,9 @@ class OrderMigration extends Migration {
// **************************************************************************
class OrderQuery extends Query<Order, OrderQueryWhere> {
OrderQuery() {
OrderQuery({Set<String> trampoline}) {
trampoline ??= Set();
trampoline.add(tableName);
_where = new OrderQueryWhere(this);
leftJoin('customers', 'customer_id', 'id',
additionalFields: const ['created_at', 'updated_at']);
@ -42,6 +44,11 @@ class OrderQuery extends Query<Order, OrderQueryWhere> {
OrderQueryWhere _where;
@override
get casts {
return {};
}
@override
get tableName {
return 'orders';

View file

@ -28,9 +28,11 @@ class TreeMigration extends Migration {
// **************************************************************************
class TreeQuery extends Query<Tree, TreeQueryWhere> {
TreeQuery() {
TreeQuery({Set<String> trampoline}) {
trampoline ??= Set();
trampoline.add(tableName);
_where = new TreeQueryWhere(this);
leftJoin('(' + new FruitQuery().compile() + ')', 'id', 'tree_id',
leftJoin(new FruitQuery(trampoline: trampoline), 'id', 'tree_id',
additionalFields: const [
'tree_id',
'common_name',
@ -44,6 +46,11 @@ class TreeQuery extends Query<Tree, TreeQueryWhere> {
TreeQueryWhere _where;
@override
get casts {
return {};
}
@override
get tableName {
return 'trees';

View file

@ -65,7 +65,9 @@ class RoleMigration extends Migration {
// **************************************************************************
class UserQuery extends Query<User, UserQueryWhere> {
UserQuery() {
UserQuery({Set<String> trampoline}) {
trampoline ??= Set();
trampoline.add(tableName);
_where = new UserQueryWhere(this);
}
@ -74,6 +76,11 @@ class UserQuery extends Query<User, UserQueryWhere> {
UserQueryWhere _where;
@override
get casts {
return {};
}
@override
get tableName {
return 'users';
@ -192,7 +199,9 @@ class UserQueryValues extends MapQueryValues {
}
class RoleUserQuery extends Query<RoleUser, RoleUserQueryWhere> {
RoleUserQuery() {
RoleUserQuery({Set<String> trampoline}) {
trampoline ??= Set();
trampoline.add(tableName);
_where = new RoleUserQueryWhere(this);
leftJoin('roles', 'role_id', 'id',
additionalFields: const ['name', 'created_at', 'updated_at']);
@ -210,6 +219,11 @@ class RoleUserQuery extends Query<RoleUser, RoleUserQueryWhere> {
RoleUserQueryWhere _where;
@override
get casts {
return {};
}
@override
get tableName {
return 'role_users';
@ -319,7 +333,9 @@ class RoleUserQueryValues extends MapQueryValues {
}
class RoleQuery extends Query<Role, RoleQueryWhere> {
RoleQuery() {
RoleQuery({Set<String> trampoline}) {
trampoline ??= Set();
trampoline.add(tableName);
_where = new RoleQueryWhere(this);
}
@ -328,6 +344,11 @@ class RoleQuery extends Query<Role, RoleQueryWhere> {
RoleQueryWhere _where;
@override
get casts {
return {};
}
@override
get tableName {
return 'roles';

View file

@ -82,7 +82,7 @@ main() {
var query2 = new CarQuery()..where.familyFriendly.isTrue;
var query3 = new CarQuery()..where.description.equals('Submarine');
var union = query1.union(query2).unionAll(query3);
print(union.compile());
print(union.compile(Set()));
var cars = await union.get(connection);
expect(cars, hasLength(1));
});
@ -93,14 +93,14 @@ main() {
..orWhere((where) => where
..familyFriendly.isTrue
..make.equals('Honda'));
print(query.compile());
print(query.compile(Set()));
var cars = await query.get(connection);
expect(cars, hasLength(1));
});
test('limit obeyed', () async {
var query = new CarQuery()..limit(0);
print(query.compile());
print(query.compile(Set()));
var cars = await query.get(connection);
expect(cars, isEmpty);
});
@ -126,7 +126,7 @@ main() {
var query = new CarQuery()
..where.make.equals('Ferrari東')
..orWhere((w) => w.familyFriendly.isTrue);
print(query.compile(preamble: 'DELETE FROM "cars"'));
print(query.compile(Set(), preamble: 'DELETE FROM "cars"'));
var cars = await query.delete(connection);
expect(cars, hasLength(1));