From a0d3029ac0db067b59cb6bf7f78738a21dc12610 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 17:42:55 -0400 Subject: [PATCH 01/44] Split up query.dart into separate files --- angel_orm/lib/angel_orm.dart | 12 +- angel_orm/lib/src/builder.dart | 2 +- angel_orm/lib/src/join_builder.dart | 58 ++++ angel_orm/lib/src/join_on.dart | 8 + angel_orm/lib/src/map_query_values.dart | 0 angel_orm/lib/src/order_by.dart | 8 + angel_orm/lib/src/query.dart | 354 +----------------------- angel_orm/lib/src/query_base.dart | 50 ++++ angel_orm/lib/src/query_executor.dart | 16 ++ angel_orm/lib/src/query_values.dart | 67 +++++ angel_orm/lib/src/query_where.dart | 59 ++++ angel_orm/lib/src/union.dart | 37 +++ angel_orm/lib/src/util.dart | 57 ++++ 13 files changed, 378 insertions(+), 350 deletions(-) create mode 100644 angel_orm/lib/src/join_builder.dart create mode 100644 angel_orm/lib/src/join_on.dart create mode 100644 angel_orm/lib/src/map_query_values.dart create mode 100644 angel_orm/lib/src/order_by.dart create mode 100644 angel_orm/lib/src/query_base.dart create mode 100644 angel_orm/lib/src/query_executor.dart create mode 100644 angel_orm/lib/src/query_values.dart create mode 100644 angel_orm/lib/src/query_where.dart create mode 100644 angel_orm/lib/src/union.dart create mode 100644 angel_orm/lib/src/util.dart diff --git a/angel_orm/lib/angel_orm.dart b/angel_orm/lib/angel_orm.dart index b7931d80..91952278 100644 --- a/angel_orm/lib/angel_orm.dart +++ b/angel_orm/lib/angel_orm.dart @@ -1,5 +1,15 @@ export 'src/annotations.dart'; export 'src/builder.dart'; +export 'src/join_builder.dart'; +export 'src/join_on.dart'; +export 'src/map_query_values.dart'; export 'src/migration.dart'; -export 'src/relations.dart'; +export 'src/order_by.dart'; +export 'src/query_base.dart'; +export 'src/query_executor.dart'; +export 'src/query_values.dart'; +export 'src/query_where.dart'; export 'src/query.dart'; +export 'src/relations.dart'; +export 'src/union.dart'; +export 'src/util.dart'; diff --git a/angel_orm/lib/src/builder.dart b/angel_orm/lib/src/builder.dart index eac463d5..aaca4914 100644 --- a/angel_orm/lib/src/builder.dart +++ b/angel_orm/lib/src/builder.dart @@ -1,9 +1,9 @@ import 'dart:convert'; - import 'package:charcode/ascii.dart'; import 'package:intl/intl.dart' show DateFormat; import 'package:string_scanner/string_scanner.dart'; import 'query.dart'; +import 'util.dart'; final DateFormat dateYmd = DateFormat('yyyy-MM-dd'); final DateFormat dateYmdHms = DateFormat('yyyy-MM-dd HH:mm:ss'); diff --git a/angel_orm/lib/src/join_builder.dart b/angel_orm/lib/src/join_builder.dart new file mode 100644 index 00000000..5b591de6 --- /dev/null +++ b/angel_orm/lib/src/join_builder.dart @@ -0,0 +1,58 @@ +import 'annotations.dart'; +import 'query.dart'; + +/// Builds a SQL `JOIN` query. +class JoinBuilder { + final JoinType type; + final Query from; + final String to, key, value, op, alias; + final List additionalFields; + + JoinBuilder(this.type, this.from, this.to, this.key, this.value, + {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'; + if (alias != null) right = '$alias.$value'; + return right; + } + + String nameFor(String name) { + var right = '$to.$name'; + if (alias != null) right = '$alias.$name'; + return right; + } + + String compile(Set trampoline) { + if (to == null) return null; + var b = StringBuffer(); + var left = '${from.tableName}.$key'; + var right = fieldName; + + switch (type) { + case JoinType.inner: + b.write(' INNER JOIN'); + break; + case JoinType.left: + b.write(' LEFT JOIN'); + break; + case JoinType.right: + b.write(' RIGHT JOIN'); + break; + case JoinType.full: + b.write(' FULL OUTER JOIN'); + break; + case JoinType.self: + b.write(' SELF JOIN'); + break; + } + + b.write(' $to'); + if (alias != null) b.write(' $alias'); + b.write(' ON $left$op$right'); + return b.toString(); + } +} \ No newline at end of file diff --git a/angel_orm/lib/src/join_on.dart b/angel_orm/lib/src/join_on.dart new file mode 100644 index 00000000..acf3ee11 --- /dev/null +++ b/angel_orm/lib/src/join_on.dart @@ -0,0 +1,8 @@ +import 'builder.dart'; + +class JoinOn { + final SqlExpressionBuilder key; + final SqlExpressionBuilder value; + + JoinOn(this.key, this.value); +} \ No newline at end of file diff --git a/angel_orm/lib/src/map_query_values.dart b/angel_orm/lib/src/map_query_values.dart new file mode 100644 index 00000000..e69de29b diff --git a/angel_orm/lib/src/order_by.dart b/angel_orm/lib/src/order_by.dart new file mode 100644 index 00000000..4501cf45 --- /dev/null +++ b/angel_orm/lib/src/order_by.dart @@ -0,0 +1,8 @@ +class OrderBy { + final String key; + final bool descending; + + const OrderBy(this.key, {this.descending = false}); + + String compile() => descending ? '$key DESC' : '$key ASC'; +} diff --git a/angel_orm/lib/src/query.dart b/angel_orm/lib/src/query.dart index 481f5702..5427ef18 100644 --- a/angel_orm/lib/src/query.dart +++ b/angel_orm/lib/src/query.dart @@ -1,115 +1,11 @@ import 'dart:async'; -import 'package:charcode/ascii.dart'; import 'annotations.dart'; -import 'builder.dart'; - -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 { - /// Casts to perform when querying the database. - Map get casts => {}; - - /// Values to insert into a prepared statement. - final Map substitutionValues = {}; - - /// The table against which to execute this query. - String get tableName; - - /// The list of fields returned by this query. - /// - /// If it's `null`, then this query will perform a `SELECT *`. - List get fields; - - /// A String of all [fields], joined by a comma (`,`). - String get fieldSet => fields.map((k) { - var cast = casts[k]; - return cast == null ? k : 'CAST ($k AS $cast)'; - }).join(', '); - - String compile(Set trampoline, - {bool includeTableName = false, String preamble, bool withFields = true}); - - T deserialize(List row); - - Future> get(QueryExecutor executor) async { - var sql = compile(Set()); - return executor - .query(tableName, sql, substitutionValues) - .then((it) => it.map(deserialize).toList()); - } - - Future getOne(QueryExecutor executor) { - return get(executor).then((it) => it.isEmpty ? null : it.first); - } - - Union union(QueryBase other) { - return Union(this, other); - } - - Union unionAll(QueryBase other) { - return Union(this, other, all: true); - } -} - -class OrderBy { - final String key; - final bool descending; - - const OrderBy(this.key, {this.descending = false}); - - String compile() => descending ? '$key DESC' : '$key ASC'; -} - -/// The ORM prefers using substitution values, which allow for prepared queries, -/// and prevent SQL injection attacks. -@deprecated -String toSql(Object obj, {bool withQuotes = true}) { - if (obj is DateTime) { - return withQuotes ? "'${dateYmdHms.format(obj)}'" : dateYmdHms.format(obj); - } else if (obj is bool) { - return obj ? 'TRUE' : 'FALSE'; - } else if (obj == null) { - return 'NULL'; - } else if (obj is String) { - var b = StringBuffer(); - var escaped = false; - var it = obj.runes.iterator; - - while (it.moveNext()) { - if (it.current == $nul) { - continue; // Skip null byte - } else if (it.current == $single_quote) { - escaped = true; - b.write('\\x'); - b.write(it.current.toRadixString(16).padLeft(2, '0')); - } else if (isAscii(it.current)) { - b.writeCharCode(it.current); - } else if (it.currentSize == 1) { - escaped = true; - b.write('\\u'); - b.write(it.current.toRadixString(16).padLeft(4, '0')); - } else if (it.currentSize == 2) { - escaped = true; - b.write('\\U'); - b.write(it.current.toRadixString(16).padLeft(8, '0')); - } else { - throw UnsupportedError( - 'toSql() cannot encode a rune of size (${it.currentSize})'); - } - } - - if (!withQuotes) { - return b.toString(); - } else if (escaped) { - return "E'$b'"; - } else { - return "'$b'"; - } - } else { - return obj.toString(); - } -} +import 'join_builder.dart'; +import 'order_by.dart'; +import 'query_base.dart'; +import 'query_executor.dart'; +import 'query_values.dart'; +import 'query_where.dart'; /// A SQL `SELECT` query builder. abstract class Query extends QueryBase { @@ -424,241 +320,3 @@ abstract class Query extends QueryBase { return update(executor).then((it) => it.isEmpty ? null : it.first); } } - -abstract class QueryValues { - Map get casts => {}; - - Map toMap(); - - String applyCast(String name, String sub) { - if (casts.containsKey(name)) { - var type = casts[name]; - return 'CAST ($sub as $type)'; - } else { - return sub; - } - } - - String compileInsert(Query query, String tableName) { - var data = Map.from(toMap()); - var keys = data.keys.toList(); - keys.where((k) => !query.fields.contains(k)).forEach(data.remove); - if (data.isEmpty) return null; - - var fieldSet = data.keys.join(', '); - var b = StringBuffer('INSERT INTO $tableName ($fieldSet) VALUES ('); - int i = 0; - - for (var entry in data.entries) { - if (i++ > 0) b.write(', '); - - var name = query.reserveName(entry.key); - var s = applyCast(entry.key, '@$name'); - query.substitutionValues[name] = entry.value; - b.write(s); - } - - b.write(')'); - return b.toString(); - } - - String compileForUpdate(Query query) { - var data = toMap(); - if (data.isEmpty) return null; - var b = StringBuffer('SET'); - int i = 0; - - for (var entry in data.entries) { - if (i++ > 0) b.write(','); - b.write(' '); - b.write(entry.key); - b.write('='); - - var name = query.reserveName(entry.key); - var s = applyCast(entry.key, '@$name'); - query.substitutionValues[name] = entry.value; - b.write(s); - } - return b.toString(); - } -} - -/// A [QueryValues] implementation that simply writes to a [Map]. -class MapQueryValues extends QueryValues { - final Map values = {}; - - @override - Map toMap() => values; -} - -/// Builds a SQL `WHERE` clause. -abstract class QueryWhere { - final Set _and = Set(); - final Set _not = Set(); - final Set _or = Set(); - - Iterable get expressionBuilders; - - void and(QueryWhere other) { - _and.add(other); - } - - void not(QueryWhere other) { - _not.add(other); - } - - void or(QueryWhere other) { - _or.add(other); - } - - String compile({String tableName}) { - var b = StringBuffer(); - int i = 0; - - for (var builder in expressionBuilders) { - var key = builder.columnName; - if (tableName != null) key = '$tableName.$key'; - if (builder.hasValue) { - if (i++ > 0) b.write(' AND '); - if (builder is DateTimeSqlExpressionBuilder || - (builder is JsonSqlExpressionBuilder && builder.hasRaw)) { - if (tableName != null) b.write('$tableName.'); - b.write(builder.compile()); - } else { - b.write('$key ${builder.compile()}'); - } - } - } - - for (var other in _and) { - var sql = other.compile(); - if (sql.isNotEmpty) b.write(' AND $sql'); - } - - for (var other in _not) { - var sql = other.compile(); - if (sql.isNotEmpty) b.write(' NOT $sql'); - } - - for (var other in _or) { - var sql = other.compile(); - if (sql.isNotEmpty) b.write(' OR $sql'); - } - - return b.toString(); - } -} - -/// Represents the `UNION` of two subqueries. -class Union extends QueryBase { - /// The subject(s) of this binary operation. - final QueryBase left, right; - - /// Whether this is a `UNION ALL` operation. - final bool all; - - @override - final String tableName; - - Union(this.left, this.right, {this.all = false, String tableName}) - : this.tableName = tableName ?? left.tableName { - substitutionValues - ..addAll(left.substitutionValues) - ..addAll(right.substitutionValues); - } - - @override - List get fields => left.fields; - - @override - T deserialize(List row) => left.deserialize(row); - - @override - String compile(Set trampoline, - {bool includeTableName = false, - String preamble, - bool withFields = true}) { - var selector = all == true ? 'UNION ALL' : 'UNION'; - var t1 = Set.from(trampoline); - var t2 = Set.from(trampoline); - return '(${left.compile(t1, includeTableName: includeTableName)}) $selector (${right.compile(t2, includeTableName: includeTableName)})'; - } -} - -/// Builds a SQL `JOIN` query. -class JoinBuilder { - final JoinType type; - final Query from; - final String to, key, value, op, alias; - final List additionalFields; - - JoinBuilder(this.type, this.from, this.to, this.key, this.value, - {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'; - if (alias != null) right = '$alias.$value'; - return right; - } - - String nameFor(String name) { - var right = '$to.$name'; - if (alias != null) right = '$alias.$name'; - return right; - } - - String compile(Set trampoline) { - if (to == null) return null; - var b = StringBuffer(); - var left = '${from.tableName}.$key'; - var right = fieldName; - - switch (type) { - case JoinType.inner: - b.write(' INNER JOIN'); - break; - case JoinType.left: - b.write(' LEFT JOIN'); - break; - case JoinType.right: - b.write(' RIGHT JOIN'); - break; - case JoinType.full: - b.write(' FULL OUTER JOIN'); - break; - case JoinType.self: - b.write(' SELF JOIN'); - break; - } - - b.write(' $to'); - if (alias != null) b.write(' $alias'); - b.write(' ON $left$op$right'); - return b.toString(); - } -} - -class JoinOn { - final SqlExpressionBuilder key; - final SqlExpressionBuilder value; - - JoinOn(this.key, this.value); -} - -/// An abstract interface that performs queries. -/// -/// This class should be implemented. -abstract class QueryExecutor { - const QueryExecutor(); - - /// Executes a single query. - Future> query( - String tableName, String query, Map substitutionValues, - [List returningFields]); - - /// Begins a database transaction. - Future transaction(FutureOr f()); -} diff --git a/angel_orm/lib/src/query_base.dart b/angel_orm/lib/src/query_base.dart new file mode 100644 index 00000000..8e378636 --- /dev/null +++ b/angel_orm/lib/src/query_base.dart @@ -0,0 +1,50 @@ +import 'dart:async'; +import 'query_executor.dart'; +import 'union.dart'; + +/// A base class for objects that compile to SQL queries, typically within an ORM. +abstract class QueryBase { + /// Casts to perform when querying the database. + Map get casts => {}; + + /// Values to insert into a prepared statement. + final Map substitutionValues = {}; + + /// The table against which to execute this query. + String get tableName; + + /// The list of fields returned by this query. + /// + /// If it's `null`, then this query will perform a `SELECT *`. + List get fields; + + /// A String of all [fields], joined by a comma (`,`). + String get fieldSet => fields.map((k) { + var cast = casts[k]; + return cast == null ? k : 'CAST ($k AS $cast)'; + }).join(', '); + + String compile(Set trampoline, + {bool includeTableName = false, String preamble, bool withFields = true}); + + T deserialize(List row); + + Future> get(QueryExecutor executor) async { + var sql = compile(Set()); + return executor + .query(tableName, sql, substitutionValues) + .then((it) => it.map(deserialize).toList()); + } + + Future getOne(QueryExecutor executor) { + return get(executor).then((it) => it.isEmpty ? null : it.first); + } + + Union union(QueryBase other) { + return Union(this, other); + } + + Union unionAll(QueryBase other) { + return Union(this, other, all: true); + } +} diff --git a/angel_orm/lib/src/query_executor.dart b/angel_orm/lib/src/query_executor.dart new file mode 100644 index 00000000..558a4d9d --- /dev/null +++ b/angel_orm/lib/src/query_executor.dart @@ -0,0 +1,16 @@ +import 'dart:async'; + +/// An abstract interface that performs queries. +/// +/// This class should be implemented. +abstract class QueryExecutor { + const QueryExecutor(); + + /// Executes a single query. + Future> query( + String tableName, String query, Map substitutionValues, + [List returningFields]); + + /// Begins a database transaction. + Future transaction(FutureOr f()); +} diff --git a/angel_orm/lib/src/query_values.dart b/angel_orm/lib/src/query_values.dart new file mode 100644 index 00000000..d576060b --- /dev/null +++ b/angel_orm/lib/src/query_values.dart @@ -0,0 +1,67 @@ +import 'query.dart'; + +abstract class QueryValues { + Map get casts => {}; + + Map toMap(); + + String applyCast(String name, String sub) { + if (casts.containsKey(name)) { + var type = casts[name]; + return 'CAST ($sub as $type)'; + } else { + return sub; + } + } + + String compileInsert(Query query, String tableName) { + var data = Map.from(toMap()); + var keys = data.keys.toList(); + keys.where((k) => !query.fields.contains(k)).forEach(data.remove); + if (data.isEmpty) return null; + + var fieldSet = data.keys.join(', '); + var b = StringBuffer('INSERT INTO $tableName ($fieldSet) VALUES ('); + int i = 0; + + for (var entry in data.entries) { + if (i++ > 0) b.write(', '); + + var name = query.reserveName(entry.key); + var s = applyCast(entry.key, '@$name'); + query.substitutionValues[name] = entry.value; + b.write(s); + } + + b.write(')'); + return b.toString(); + } + + String compileForUpdate(Query query) { + var data = toMap(); + if (data.isEmpty) return null; + var b = StringBuffer('SET'); + int i = 0; + + for (var entry in data.entries) { + if (i++ > 0) b.write(','); + b.write(' '); + b.write(entry.key); + b.write('='); + + var name = query.reserveName(entry.key); + var s = applyCast(entry.key, '@$name'); + query.substitutionValues[name] = entry.value; + b.write(s); + } + return b.toString(); + } +} + +/// A [QueryValues] implementation that simply writes to a [Map]. +class MapQueryValues extends QueryValues { + final Map values = {}; + + @override + Map toMap() => values; +} diff --git a/angel_orm/lib/src/query_where.dart b/angel_orm/lib/src/query_where.dart new file mode 100644 index 00000000..4006b170 --- /dev/null +++ b/angel_orm/lib/src/query_where.dart @@ -0,0 +1,59 @@ +import 'builder.dart'; + +/// Builds a SQL `WHERE` clause. +abstract class QueryWhere { + final Set _and = Set(); + final Set _not = Set(); + final Set _or = Set(); + + Iterable get expressionBuilders; + + void and(QueryWhere other) { + _and.add(other); + } + + void not(QueryWhere other) { + _not.add(other); + } + + void or(QueryWhere other) { + _or.add(other); + } + + String compile({String tableName}) { + var b = StringBuffer(); + int i = 0; + + for (var builder in expressionBuilders) { + var key = builder.columnName; + if (tableName != null) key = '$tableName.$key'; + if (builder.hasValue) { + if (i++ > 0) b.write(' AND '); + if (builder is DateTimeSqlExpressionBuilder || + (builder is JsonSqlExpressionBuilder && builder.hasRaw)) { + if (tableName != null) b.write('$tableName.'); + b.write(builder.compile()); + } else { + b.write('$key ${builder.compile()}'); + } + } + } + + for (var other in _and) { + var sql = other.compile(); + if (sql.isNotEmpty) b.write(' AND $sql'); + } + + for (var other in _not) { + var sql = other.compile(); + if (sql.isNotEmpty) b.write(' NOT $sql'); + } + + for (var other in _or) { + var sql = other.compile(); + if (sql.isNotEmpty) b.write(' OR $sql'); + } + + return b.toString(); + } +} diff --git a/angel_orm/lib/src/union.dart b/angel_orm/lib/src/union.dart new file mode 100644 index 00000000..048ebf31 --- /dev/null +++ b/angel_orm/lib/src/union.dart @@ -0,0 +1,37 @@ +import 'query_base.dart'; + +/// Represents the `UNION` of two subqueries. +class Union extends QueryBase { + /// The subject(s) of this binary operation. + final QueryBase left, right; + + /// Whether this is a `UNION ALL` operation. + final bool all; + + @override + final String tableName; + + Union(this.left, this.right, {this.all = false, String tableName}) + : this.tableName = tableName ?? left.tableName { + substitutionValues + ..addAll(left.substitutionValues) + ..addAll(right.substitutionValues); + } + + @override + List get fields => left.fields; + + @override + T deserialize(List row) => left.deserialize(row); + + @override + String compile(Set trampoline, + {bool includeTableName = false, + String preamble, + bool withFields = true}) { + var selector = all == true ? 'UNION ALL' : 'UNION'; + var t1 = Set.from(trampoline); + var t2 = Set.from(trampoline); + return '(${left.compile(t1, includeTableName: includeTableName)}) $selector (${right.compile(t2, includeTableName: includeTableName)})'; + } +} diff --git a/angel_orm/lib/src/util.dart b/angel_orm/lib/src/util.dart new file mode 100644 index 00000000..cbe814ce --- /dev/null +++ b/angel_orm/lib/src/util.dart @@ -0,0 +1,57 @@ +import 'dart:async'; +import 'package:charcode/ascii.dart'; +import 'annotations.dart'; +import 'builder.dart'; +import 'query_base.dart'; + +bool isAscii(int ch) => ch >= $nul && ch <= $del; + +/// The ORM prefers using substitution values, which allow for prepared queries, +/// and prevent SQL injection attacks. +@deprecated +String toSql(Object obj, {bool withQuotes = true}) { + if (obj is DateTime) { + return withQuotes ? "'${dateYmdHms.format(obj)}'" : dateYmdHms.format(obj); + } else if (obj is bool) { + return obj ? 'TRUE' : 'FALSE'; + } else if (obj == null) { + return 'NULL'; + } else if (obj is String) { + var b = StringBuffer(); + var escaped = false; + var it = obj.runes.iterator; + + while (it.moveNext()) { + if (it.current == $nul) { + continue; // Skip null byte + } else if (it.current == $single_quote) { + escaped = true; + b.write('\\x'); + b.write(it.current.toRadixString(16).padLeft(2, '0')); + } else if (isAscii(it.current)) { + b.writeCharCode(it.current); + } else if (it.currentSize == 1) { + escaped = true; + b.write('\\u'); + b.write(it.current.toRadixString(16).padLeft(4, '0')); + } else if (it.currentSize == 2) { + escaped = true; + b.write('\\U'); + b.write(it.current.toRadixString(16).padLeft(8, '0')); + } else { + throw UnsupportedError( + 'toSql() cannot encode a rune of size (${it.currentSize})'); + } + } + + if (!withQuotes) { + return b.toString(); + } else if (escaped) { + return "E'$b'"; + } else { + return "'$b'"; + } + } else { + return obj.toString(); + } +} From 716d428be01d42e857d8ce66123fcefc62d2c02c Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 17:46:03 -0400 Subject: [PATCH 02/44] Clean up unused imports --- angel_orm/lib/src/util.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/angel_orm/lib/src/util.dart b/angel_orm/lib/src/util.dart index cbe814ce..c6dee3ce 100644 --- a/angel_orm/lib/src/util.dart +++ b/angel_orm/lib/src/util.dart @@ -1,8 +1,5 @@ -import 'dart:async'; import 'package:charcode/ascii.dart'; -import 'annotations.dart'; import 'builder.dart'; -import 'query_base.dart'; bool isAscii(int ch) => ch >= $nul && ch <= $del; From 3e474823d90ae3b9dd80237143300d8b934ed034 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 17:46:47 -0400 Subject: [PATCH 03/44] CHANGELOG --- angel_orm/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/angel_orm/CHANGELOG.md b/angel_orm/CHANGELOG.md index bfee1deb..3de6a208 100644 --- a/angel_orm/CHANGELOG.md +++ b/angel_orm/CHANGELOG.md @@ -1,3 +1,7 @@ +# 2.1.0 +* Split the formerly 600+ line `src/query.dart` up into +separate files. + # 2.0.1 * Apply `package:pedantic` fixes. * `@PrimaryKey()` no longer defaults to `serial`, allowing its type to be From f154013c48dd5a69960b049f29d90a43ca47137f Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 17:47:12 -0400 Subject: [PATCH 04/44] Bump versions in pubspec --- angel_orm/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/angel_orm/pubspec.yaml b/angel_orm/pubspec.yaml index 8862f698..db3d6cba 100644 --- a/angel_orm/pubspec.yaml +++ b/angel_orm/pubspec.yaml @@ -1,10 +1,10 @@ name: angel_orm -version: 2.0.1 +version: 2.1.0 description: Runtime support for Angel's ORM. Includes base classes for queries. author: Tobe O homepage: https://github.com/angel-dart/orm environment: - sdk: '>=2.0.0-dev.1.2 <3.0.0' + sdk: '>=2.0.0 <3.0.0' dependencies: charcode: ^1.0.0 intl: ^0.15.7 From 7e19bb2a470465b3efec2b8cdfd0f204f949f759 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 17:53:23 -0400 Subject: [PATCH 05/44] Add a required `QueryExecutor` argument to `transaction` callbacks. --- angel_orm/CHANGELOG.md | 2 ++ angel_orm/example/main.dart | 2 +- angel_orm/lib/src/query.dart | 4 ++-- angel_orm/lib/src/query_executor.dart | 11 +++++++++-- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/angel_orm/CHANGELOG.md b/angel_orm/CHANGELOG.md index 3de6a208..1b4e73e8 100644 --- a/angel_orm/CHANGELOG.md +++ b/angel_orm/CHANGELOG.md @@ -1,6 +1,8 @@ # 2.1.0 * Split the formerly 600+ line `src/query.dart` up into separate files. +* **BREAKING**: Add a required `QueryExecutor` argument to `transaction` +callbacks. # 2.0.1 * Apply `package:pedantic` fixes. diff --git a/angel_orm/example/main.dart b/angel_orm/example/main.dart index 719500f6..fbf6866d 100644 --- a/angel_orm/example/main.dart +++ b/angel_orm/example/main.dart @@ -34,7 +34,7 @@ class _FakeExecutor extends QueryExecutor { } @override - Future transaction(FutureOr Function() f) { + Future transaction(FutureOr Function(QueryExecutor) f) { throw UnsupportedError('Transactions are not supported.'); } } diff --git a/angel_orm/lib/src/query.dart b/angel_orm/lib/src/query.dart index 5427ef18..0a56b015 100644 --- a/angel_orm/lib/src/query.dart +++ b/angel_orm/lib/src/query.dart @@ -263,9 +263,9 @@ abstract class Query extends QueryBase { fields.map(adornWithTableName).toList()) .then((it) => it.map(deserialize).toList()); } else { - return executor.transaction(() async { + return executor.transaction((tx) async { // TODO: Can this be done with just *one* query? - var existing = await get(executor); + var existing = await get(tx); //var sql = compile(preamble: 'SELECT $tableName.id', withFields: false); return executor .query(tableName, sql, substitutionValues) diff --git a/angel_orm/lib/src/query_executor.dart b/angel_orm/lib/src/query_executor.dart index 558a4d9d..ec6448c0 100644 --- a/angel_orm/lib/src/query_executor.dart +++ b/angel_orm/lib/src/query_executor.dart @@ -11,6 +11,13 @@ abstract class QueryExecutor { String tableName, String query, Map substitutionValues, [List returningFields]); - /// Begins a database transaction. - Future transaction(FutureOr f()); + /// Enters a database transaction, performing the actions within, + /// and returning the results of [f]. + /// + /// If [f] fails, the transaction will be rolled back, and the + /// responsible exception will be re-thrown. + /// + /// Whether nested transactions are supported depends on the + /// underlying driver. + Future transaction(FutureOr Function(QueryExecutor) f); } From 1fa9612c8abf40e2c82f1af50c2025804f237cb2 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 17:58:33 -0400 Subject: [PATCH 06/44] Make `JoinBuilder` take `to` as a `String Function()`. --- angel_orm/CHANGELOG.md | 2 ++ angel_orm/lib/src/join_builder.dart | 8 ++++++-- angel_orm/lib/src/query.dart | 12 +++++++----- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/angel_orm/CHANGELOG.md b/angel_orm/CHANGELOG.md index 1b4e73e8..36b1f852 100644 --- a/angel_orm/CHANGELOG.md +++ b/angel_orm/CHANGELOG.md @@ -3,6 +3,8 @@ separate files. * **BREAKING**: Add a required `QueryExecutor` argument to `transaction` callbacks. +* Make `JoinBuilder` take `to` as a `String Function()`. This will allow +ORM queries to reference their joined subqueries. # 2.0.1 * Apply `package:pedantic` fixes. diff --git a/angel_orm/lib/src/join_builder.dart b/angel_orm/lib/src/join_builder.dart index 5b591de6..abdaa810 100644 --- a/angel_orm/lib/src/join_builder.dart +++ b/angel_orm/lib/src/join_builder.dart @@ -5,7 +5,11 @@ import 'query.dart'; class JoinBuilder { final JoinType type; final Query from; - final String to, key, value, op, alias; + final String key, value, op, alias; + + /// A callback to produces the expression to join against, i.e. + /// a table name, or the result of compiling a query. + final String Function() to; final List additionalFields; JoinBuilder(this.type, this.from, this.to, this.key, this.value, @@ -55,4 +59,4 @@ class JoinBuilder { b.write(' ON $left$op$right'); return b.toString(); } -} \ No newline at end of file +} diff --git a/angel_orm/lib/src/query.dart b/angel_orm/lib/src/query.dart index 0a56b015..23e9a7fc 100644 --- a/angel_orm/lib/src/query.dart +++ b/angel_orm/lib/src/query.dart @@ -107,13 +107,15 @@ abstract class Query extends QueryBase { } } - String _compileJoin(tableName, Set trampoline) { + String Function() _compileJoin(tableName, Set trampoline) { if (tableName is String) { - return tableName; + return () => tableName; } else if (tableName is Query) { - var c = tableName.compile(trampoline); - if (c == null) return c; - return '($c)'; + return () { + var c = tableName.compile(trampoline); + if (c == null) return c; + return '($c)'; + }; } else { throw ArgumentError.value( tableName, 'tableName', 'must be a String or Query'); From fa01fd982e09ff94de3b2ef619aa416f8dcb06b4 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:00:17 -0400 Subject: [PATCH 07/44] Removed deprecated `Join`, `toSql`, `sanitizeExpression`, `isAscii`. --- angel_orm/CHANGELOG.md | 1 + angel_orm/lib/src/annotations.dart | 9 ------ angel_orm/lib/src/builder.dart | 31 ------------------ angel_orm/lib/src/util.dart | 51 ------------------------------ 4 files changed, 1 insertion(+), 91 deletions(-) diff --git a/angel_orm/CHANGELOG.md b/angel_orm/CHANGELOG.md index 36b1f852..1789dfa4 100644 --- a/angel_orm/CHANGELOG.md +++ b/angel_orm/CHANGELOG.md @@ -5,6 +5,7 @@ separate files. callbacks. * Make `JoinBuilder` take `to` as a `String Function()`. This will allow ORM queries to reference their joined subqueries. +* Removed deprecated `Join`, `toSql`, `sanitizeExpression`, `isAscii`. # 2.0.1 * Apply `package:pedantic` fixes. diff --git a/angel_orm/lib/src/annotations.dart b/angel_orm/lib/src/annotations.dart index 4bc7147a..1c06f020 100644 --- a/angel_orm/lib/src/annotations.dart +++ b/angel_orm/lib/src/annotations.dart @@ -27,14 +27,5 @@ class Orm { const Orm({this.tableName, this.generateMigrations = true}); } -@deprecated -class Join { - final Type against; - final String foreignKey; - final JoinType type; - - const Join(this.against, this.foreignKey, {this.type = JoinType.inner}); -} - /// The various types of join. enum JoinType { inner, left, right, full, self } diff --git a/angel_orm/lib/src/builder.dart b/angel_orm/lib/src/builder.dart index aaca4914..113f76f3 100644 --- a/angel_orm/lib/src/builder.dart +++ b/angel_orm/lib/src/builder.dart @@ -1,41 +1,10 @@ import 'dart:convert'; -import 'package:charcode/ascii.dart'; import 'package:intl/intl.dart' show DateFormat; -import 'package:string_scanner/string_scanner.dart'; import 'query.dart'; -import 'util.dart'; final DateFormat dateYmd = DateFormat('yyyy-MM-dd'); final DateFormat dateYmdHms = DateFormat('yyyy-MM-dd HH:mm:ss'); -/// The ORM prefers using substitution values, which allow for prepared queries, -/// and prevent SQL injection attacks. -@deprecated -String sanitizeExpression(String unsafe) { - var buf = StringBuffer(); - var scanner = StringScanner(unsafe); - int ch; - - while (!scanner.isDone) { - // Ignore comment starts - if (scanner.scan('--') || scanner.scan('/*')) { - continue; - } - - // Ignore all single quotes and attempted escape sequences - else if (scanner.scan("'") || scanner.scan('\\')) { - continue; - } - - // Otherwise, add the next char, unless it's a null byte. - else if ((ch = scanner.readChar()) != $nul && ch != null) { - buf.writeCharCode(ch); - } - } - - return toSql(buf.toString(), withQuotes: false); -} - abstract class SqlExpressionBuilder { final Query query; final String columnName; diff --git a/angel_orm/lib/src/util.dart b/angel_orm/lib/src/util.dart index c6dee3ce..939b36c8 100644 --- a/angel_orm/lib/src/util.dart +++ b/angel_orm/lib/src/util.dart @@ -1,54 +1,3 @@ import 'package:charcode/ascii.dart'; -import 'builder.dart'; bool isAscii(int ch) => ch >= $nul && ch <= $del; - -/// The ORM prefers using substitution values, which allow for prepared queries, -/// and prevent SQL injection attacks. -@deprecated -String toSql(Object obj, {bool withQuotes = true}) { - if (obj is DateTime) { - return withQuotes ? "'${dateYmdHms.format(obj)}'" : dateYmdHms.format(obj); - } else if (obj is bool) { - return obj ? 'TRUE' : 'FALSE'; - } else if (obj == null) { - return 'NULL'; - } else if (obj is String) { - var b = StringBuffer(); - var escaped = false; - var it = obj.runes.iterator; - - while (it.moveNext()) { - if (it.current == $nul) { - continue; // Skip null byte - } else if (it.current == $single_quote) { - escaped = true; - b.write('\\x'); - b.write(it.current.toRadixString(16).padLeft(2, '0')); - } else if (isAscii(it.current)) { - b.writeCharCode(it.current); - } else if (it.currentSize == 1) { - escaped = true; - b.write('\\u'); - b.write(it.current.toRadixString(16).padLeft(4, '0')); - } else if (it.currentSize == 2) { - escaped = true; - b.write('\\U'); - b.write(it.current.toRadixString(16).padLeft(8, '0')); - } else { - throw UnsupportedError( - 'toSql() cannot encode a rune of size (${it.currentSize})'); - } - } - - if (!withQuotes) { - return b.toString(); - } else if (escaped) { - return "E'$b'"; - } else { - return "'$b'"; - } - } else { - return obj.toString(); - } -} From f18c23c5f9307a40a67eae6929eef6f77acfed09 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:08:49 -0400 Subject: [PATCH 08/44] * Always put `ORDER BY` before `LIMIT`. --- angel_orm/CHANGELOG.md | 1 + angel_orm/lib/src/query.dart | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/angel_orm/CHANGELOG.md b/angel_orm/CHANGELOG.md index 1789dfa4..949584c7 100644 --- a/angel_orm/CHANGELOG.md +++ b/angel_orm/CHANGELOG.md @@ -6,6 +6,7 @@ callbacks. * Make `JoinBuilder` take `to` as a `String Function()`. This will allow ORM queries to reference their joined subqueries. * Removed deprecated `Join`, `toSql`, `sanitizeExpression`, `isAscii`. +* Always put `ORDER BY` before `LIMIT`. # 2.0.1 * Apply `package:pedantic` fixes. diff --git a/angel_orm/lib/src/query.dart b/angel_orm/lib/src/query.dart index 23e9a7fc..98f93a85 100644 --- a/angel_orm/lib/src/query.dart +++ b/angel_orm/lib/src/query.dart @@ -241,12 +241,12 @@ abstract class Query extends QueryBase { var whereClause = where.compile(tableName: includeTableName ? tableName : null); if (whereClause.isNotEmpty) b.write(' WHERE $whereClause'); - if (_limit != null) b.write(' LIMIT $_limit'); - if (_offset != null) b.write(' OFFSET $_offset'); if (_groupBy != null) b.write(' GROUP BY $_groupBy'); for (var item in _orderBy) { b.write(' ORDER BY ${item.compile()}'); } + if (_limit != null) b.write(' LIMIT $_limit'); + if (_offset != null) b.write(' OFFSET $_offset'); return b.toString(); } From a05f15b3df5e83600e56cb0ca2f391cf671584f9 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:18:39 -0400 Subject: [PATCH 09/44] `and`, `or`, `not` in `QueryWhere` include parentheses. --- angel_orm/CHANGELOG.md | 1 + angel_orm/lib/src/query_where.dart | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/angel_orm/CHANGELOG.md b/angel_orm/CHANGELOG.md index 949584c7..4dffcc95 100644 --- a/angel_orm/CHANGELOG.md +++ b/angel_orm/CHANGELOG.md @@ -7,6 +7,7 @@ callbacks. ORM queries to reference their joined subqueries. * Removed deprecated `Join`, `toSql`, `sanitizeExpression`, `isAscii`. * Always put `ORDER BY` before `LIMIT`. +* `and`, `or`, `not` in `QueryWhere` include parentheses. # 2.0.1 * Apply `package:pedantic` fixes. diff --git a/angel_orm/lib/src/query_where.dart b/angel_orm/lib/src/query_where.dart index 4006b170..ebe6dd7b 100644 --- a/angel_orm/lib/src/query_where.dart +++ b/angel_orm/lib/src/query_where.dart @@ -41,17 +41,17 @@ abstract class QueryWhere { for (var other in _and) { var sql = other.compile(); - if (sql.isNotEmpty) b.write(' AND $sql'); + if (sql.isNotEmpty) b.write(' AND ($sql)'); } for (var other in _not) { var sql = other.compile(); - if (sql.isNotEmpty) b.write(' NOT $sql'); + if (sql.isNotEmpty) b.write(' NOT ($sql)'); } for (var other in _or) { var sql = other.compile(); - if (sql.isNotEmpty) b.write(' OR $sql'); + if (sql.isNotEmpty) b.write(' OR ($sql)'); } return b.toString(); From 860e8029c2b1c0e8ef439d33266c1b5369e0ba16 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:24:54 -0400 Subject: [PATCH 10/44] Add Column.expression --- angel_orm/lib/src/migration.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/angel_orm/lib/src/migration.dart b/angel_orm/lib/src/migration.dart index 159537a0..6d0dd52e 100644 --- a/angel_orm/lib/src/migration.dart +++ b/angel_orm/lib/src/migration.dart @@ -26,11 +26,18 @@ class Column { /// Specifies what kind of index this column is, if any. final IndexType indexType; + /// A custom SQL expression to execute, instead of a named column. + final String expression; + const Column( {this.isNullable = true, this.length, this.type, - this.indexType = IndexType.none}); + this.indexType = IndexType.none, + this.expression}); + + /// Returns `true` if [expression] is not `null`. + bool get hasExpression => expression != null; } class PrimaryKey extends Column { From d55deae96ec1187658cff3dd03e7b0df7e0d572e Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:29:05 -0400 Subject: [PATCH 11/44] Update orm_generator pubspec --- angel_orm_generator/pubspec.yaml | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/angel_orm_generator/pubspec.yaml b/angel_orm_generator/pubspec.yaml index 7c66ed04..51eecdf5 100644 --- a/angel_orm_generator/pubspec.yaml +++ b/angel_orm_generator/pubspec.yaml @@ -1,18 +1,18 @@ name: angel_orm_generator -version: 2.0.5 +version: 2.1.0 description: Code generators for Angel's ORM. Generates query builder classes. author: Tobe O homepage: https://github.com/angel-dart/orm environment: - sdk: ">=2.0.0-dev <3.0.0" + sdk: ">=2.0.0<3.0.0" dependencies: - analyzer: ">=0.27.1 <2.0.0" + analyzer: ">=0.35.0 <2.0.0" angel_model: ^1.0.0 angel_serialize: ^2.0.0 - angel_orm: ^2.0.0-dev + angel_orm: ^2.0.0 angel_serialize_generator: ^2.0.0 - build: ">=0.12.0 <2.0.0" - build_config: ">=0.3.0 <0.5.0" + build: ^1.0.0 + build_config: ^0.4.0 code_builder: ^3.0.0 dart_style: ^1.0.0 inflection2: ^0.4.2 @@ -23,16 +23,14 @@ dependencies: dev_dependencies: angel_framework: ^2.0.0-alpha angel_migration: - git: - url: https://github.com/angel-dart/migration - path: angel_migration + path: ../angel_migration #angel_test: ^1.0.0 build_runner: ^1.0.0 collection: ^1.0.0 postgres: ^1.0.0 test: ^1.0.0 -# dependency_overrides: -# angel_orm: -# path: ../angel_orm +dependency_overrides: + angel_orm: + path: ../angel_orm # angel_serialize_generator: # path: ../../serialize/angel_serialize_generator From b2cc66721b496b006ac249f6b74f2e1769191525 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:32:58 -0400 Subject: [PATCH 12/44] Fix example --- angel_orm_generator/example/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/angel_orm_generator/example/main.dart b/angel_orm_generator/example/main.dart index 7651e8f9..2a19b3c8 100644 --- a/angel_orm_generator/example/main.dart +++ b/angel_orm_generator/example/main.dart @@ -33,7 +33,7 @@ class _FakeExecutor extends QueryExecutor { } @override - Future transaction(FutureOr Function() f) { + Future transaction(FutureOr Function(QueryExecutor) f) { throw new UnsupportedError('Transactions are not supported.'); } } From 9f22b0e3b4c91208130264d2541d829635dfaea6 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:33:30 -0400 Subject: [PATCH 13/44] Add pedantic to orm_gen --- angel_orm_generator/analysis_options.yaml | 1 + angel_orm_generator/pubspec.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/angel_orm_generator/analysis_options.yaml b/angel_orm_generator/analysis_options.yaml index eae1e42a..c230cee7 100644 --- a/angel_orm_generator/analysis_options.yaml +++ b/angel_orm_generator/analysis_options.yaml @@ -1,3 +1,4 @@ +include: package:pedantic/analysis_options.yaml analyzer: strong-mode: implicit-casts: false \ No newline at end of file diff --git a/angel_orm_generator/pubspec.yaml b/angel_orm_generator/pubspec.yaml index 51eecdf5..00470631 100644 --- a/angel_orm_generator/pubspec.yaml +++ b/angel_orm_generator/pubspec.yaml @@ -27,6 +27,7 @@ dev_dependencies: #angel_test: ^1.0.0 build_runner: ^1.0.0 collection: ^1.0.0 + pedantic: ^1.0.0 postgres: ^1.0.0 test: ^1.0.0 dependency_overrides: From 30914cc767ebead5f3dadd6e5d389c1f77edb69c Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:35:55 -0400 Subject: [PATCH 14/44] Apply pedantic lints --- angel_orm_generator/example/main.dart | 8 +- .../lib/src/migration_generator.dart | 63 +++---- .../lib/src/orm_build_context.dart | 73 +++++---- .../lib/src/orm_generator.dart | 155 +++++++++--------- angel_orm_generator/lib/src/readers.dart | 2 +- 5 files changed, 159 insertions(+), 142 deletions(-) diff --git a/angel_orm_generator/example/main.dart b/angel_orm_generator/example/main.dart index 2a19b3c8..b81ac762 100644 --- a/angel_orm_generator/example/main.dart +++ b/angel_orm_generator/example/main.dart @@ -7,13 +7,13 @@ import 'package:angel_serialize/angel_serialize.dart'; part 'main.g.dart'; main() async { - var query = new EmployeeQuery() + var query = EmployeeQuery() ..where.firstName.equals('Rich') ..where.lastName.equals('Person') ..orWhere((w) => w.salary.greaterThanOrEqualTo(75000)) ..join('companies', 'company_id', 'id'); - var richPerson = await query.getOne(new _FakeExecutor()); + var richPerson = await query.getOne(_FakeExecutor()); print(richPerson.toJson()); } @@ -24,7 +24,7 @@ class _FakeExecutor extends QueryExecutor { Future> query( String tableName, String query, Map substitutionValues, [returningFields]) async { - var now = new DateTime.now(); + var now = DateTime.now(); print( '_FakeExecutor received query: $query and values: $substitutionValues'); return [ @@ -34,7 +34,7 @@ class _FakeExecutor extends QueryExecutor { @override Future transaction(FutureOr Function(QueryExecutor) f) { - throw new UnsupportedError('Transactions are not supported.'); + throw UnsupportedError('Transactions are not supported.'); } } diff --git a/angel_orm_generator/lib/src/migration_generator.dart b/angel_orm_generator/lib/src/migration_generator.dart index f5a8901a..eb629f2b 100644 --- a/angel_orm_generator/lib/src/migration_generator.dart +++ b/angel_orm_generator/lib/src/migration_generator.dart @@ -11,14 +11,14 @@ import 'package:source_gen/source_gen.dart' hide LibraryBuilder; import 'orm_build_context.dart'; Builder migrationBuilder(BuilderOptions options) { - return new SharedPartBuilder([ - new MigrationGenerator( + return SharedPartBuilder([ + MigrationGenerator( autoSnakeCaseNames: options.config['auto_snake_case_names'] != false) ], 'angel_migration'); } class MigrationGenerator extends GeneratorForAnnotation { - static final Parameter _schemaParam = new Parameter((b) => b + static final Parameter _schemaParam = Parameter((b) => b ..name = 'schema' ..type = refer('Schema')); static final Reference _schema = refer('schema'); @@ -26,13 +26,14 @@ class MigrationGenerator extends GeneratorForAnnotation { /// If `true` (default), then field names will automatically be (de)serialized as snake_case. final bool autoSnakeCaseNames; - const MigrationGenerator({this.autoSnakeCaseNames: true}); + const MigrationGenerator({this.autoSnakeCaseNames = true}); @override Future generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep) async { - if (element is! ClassElement) + if (element is! ClassElement) { throw 'Only classes can be annotated with @ORM().'; + } var generateMigrations = annotation.peek('generateMigrations')?.boolValue ?? true; @@ -47,13 +48,13 @@ class MigrationGenerator extends GeneratorForAnnotation { var lib = generateMigrationLibrary( ctx, element as ClassElement, resolver, buildStep); if (lib == null) return null; - return new DartFormatter().format(lib.accept(new DartEmitter()).toString()); + return DartFormatter().format(lib.accept(DartEmitter()).toString()); } Library generateMigrationLibrary(OrmBuildContext ctx, ClassElement element, Resolver resolver, BuildStep buildStep) { - return new Library((lib) { - lib.body.add(new Class((clazz) { + return Library((lib) { + lib.body.add(Class((clazz) { clazz ..name = '${ctx.buildContext.modelClassName}Migration' ..extend = refer('Migration') @@ -64,7 +65,7 @@ class MigrationGenerator extends GeneratorForAnnotation { } Method buildUpMigration(OrmBuildContext ctx, LibraryBuilder lib) { - return new Method((meth) { + return Method((meth) { var autoIdAndDateFields = const TypeChecker.fromRuntime(Model) .isAssignableFromType(ctx.buildContext.clazz.type); meth @@ -72,20 +73,20 @@ class MigrationGenerator extends GeneratorForAnnotation { ..annotations.add(refer('override')) ..requiredParameters.add(_schemaParam); - //var closure = new Method.closure()..addPositional(parameter('table')); - var closure = new Method((closure) { + //var closure = Method.closure()..addPositional(parameter('table')); + var closure = Method((closure) { closure - ..requiredParameters.add(new Parameter((b) => b..name = 'table')) - ..body = new Block((closureBody) { + ..requiredParameters.add(Parameter((b) => b..name = 'table')) + ..body = Block((closureBody) { var table = refer('table'); List dup = []; ctx.columns.forEach((name, col) { var key = ctx.buildContext.resolveFieldName(name); - if (dup.contains(key)) + if (dup.contains(key)) { return; - else { + } else { // if (key != 'id' || autoIdAndDateFields == false) { // // Check for relationships that might duplicate // for (var rName in ctx.relations.keys) { @@ -111,15 +112,17 @@ class MigrationGenerator extends GeneratorForAnnotation { List positional = [literal(key)]; Map named = {}; - if (autoIdAndDateFields != false && name == 'id') + if (autoIdAndDateFields != false && name == 'id') { methodName = 'serial'; + } if (methodName == null) { switch (col.type) { case ColumnType.varChar: methodName = 'varChar'; - if (col.length != null) + if (col.length != null) { named['length'] = literal(col.length); + } break; case ColumnType.serial: methodName = 'serial'; @@ -196,13 +199,14 @@ class MigrationGenerator extends GeneratorForAnnotation { // Definitely an analyzer issue. } } else { - defaultExpr = new CodeExpression( - new Code(dartObjectToString(defaultValue)), + defaultExpr = CodeExpression( + Code(dartObjectToString(defaultValue)), ); } - if (defaultExpr != null) + if (defaultExpr != null) { cascade.add(refer('defaultsTo').call([defaultExpr])); + } } if (col.indexType == IndexType.primaryKey || @@ -212,20 +216,20 @@ class MigrationGenerator extends GeneratorForAnnotation { cascade.add(refer('unique').call([])); } - if (col.isNullable != true) + if (col.isNullable != true) { cascade.add(refer('notNull').call([])); + } if (cascade.isNotEmpty) { - var b = new StringBuffer() - ..writeln(field.accept(new DartEmitter())); + var b = StringBuffer()..writeln(field.accept(DartEmitter())); for (var ex in cascade) { b ..write('..') - ..writeln(ex.accept(new DartEmitter())); + ..writeln(ex.accept(DartEmitter())); } - field = new CodeExpression(new Code(b.toString())); + field = CodeExpression(Code(b.toString())); } closureBody.addExpression(field); @@ -259,15 +263,16 @@ class MigrationGenerator extends GeneratorForAnnotation { if (relationship.cascadeOnDelete != false && const [RelationshipType.hasOne, RelationshipType.belongsTo] - .contains(relationship.type)) + .contains(relationship.type)) { ref = ref.property('onDeleteCascade').call([]); + } closureBody.addExpression(ref); } }); }); }); - meth.body = new Block((b) { + meth.body = Block((b) { b.addExpression(_schema.property('create').call([ literal(ctx.tableName), closure.closure, @@ -277,12 +282,12 @@ class MigrationGenerator extends GeneratorForAnnotation { } Method buildDownMigration(OrmBuildContext ctx) { - return new Method((b) { + return Method((b) { b ..name = 'down' ..annotations.add(refer('override')) ..requiredParameters.add(_schemaParam) - ..body = new Block((b) { + ..body = Block((b) { var named = {}; if (ctx.relations.values.any((r) => diff --git a/angel_orm_generator/lib/src/orm_build_context.dart b/angel_orm_generator/lib/src/orm_build_context.dart index f22a7c31..8ac2b5fe 100644 --- a/angel_orm_generator/lib/src/orm_build_context.dart +++ b/angel_orm_generator/lib/src/orm_build_context.dart @@ -43,7 +43,7 @@ FieldElement findPrimaryFieldInList( var columnAnnotation = columnTypeChecker.firstAnnotationOf(element); if (columnAnnotation != null) { - var column = reviveColumn(new ConstantReader(columnAnnotation)); + var column = reviveColumn(ConstantReader(columnAnnotation)); // print( // ' * Found column on ${field.name} with indexType = ${column.indexType}'); // print(element.metadata); @@ -66,7 +66,7 @@ Future buildOrmContext( BuildStep buildStep, Resolver resolver, bool autoSnakeCaseNames, - {bool heedExclude: true}) async { + {bool heedExclude = true}) async { // Check for @generatedSerializable // ignore: unused_local_variable DartObject generatedSerializable; @@ -88,12 +88,12 @@ Future buildOrmContext( var ormAnnotation = reviveORMAnnotation(annotation); // print( // 'tableName (${annotation.objectValue.type.name}) => ${ormAnnotation.tableName} from ${clazz.name} (${annotation.revive().namedArguments})'); - var ctx = new OrmBuildContext( + var ctx = OrmBuildContext( buildCtx, ormAnnotation, (ormAnnotation.tableName?.isNotEmpty == true) ? ormAnnotation.tableName - : pluralize(new ReCase(clazz.name).snakeCase)); + : pluralize(ReCase(clazz.name).snakeCase)); _cache[id] = ctx; // Read all fields @@ -105,7 +105,7 @@ Future buildOrmContext( // print('${element.name} => $columnAnnotation'); if (columnAnnotation != null) { - column = reviveColumn(new ConstantReader(columnAnnotation)); + column = reviveColumn(ConstantReader(columnAnnotation)); } if (column == null && isSpecialId(ctx, field)) { @@ -117,7 +117,7 @@ Future buildOrmContext( if (column == null) { // Guess what kind of column this is... - column = new Column( + column = Column( type: inferColumnType( buildCtx.resolveSerializedFieldType(field.name), ), @@ -125,7 +125,7 @@ Future buildOrmContext( } if (column != null && column.type == null) { - column = new Column( + column = Column( isNullable: column.isNullable, length: column.length, indexType: column.indexType, @@ -139,7 +139,7 @@ Future buildOrmContext( var ann = relationshipTypeChecker.firstAnnotationOf(el); if (ann != null) { - var cr = new ConstantReader(ann); + var cr = ConstantReader(ann); var rc = ctx.buildContext.modelClassNameRecase; var type = cr.read('type').intValue; var localKey = cr.peek('localKey')?.stringValue; @@ -157,7 +157,7 @@ Future buildOrmContext( isListOfModelType(field.type as InterfaceType)) || isModelClass(field.type); if (!canUse) { - throw new UnsupportedError( + throw UnsupportedError( 'Cannot apply relationship to field "${field.name}" - ${field.type} is not assignable to Model.'); } else { try { @@ -174,7 +174,7 @@ Future buildOrmContext( foreign = await buildOrmContext( modelType.element as ClassElement, - new ConstantReader(const TypeChecker.fromRuntime(Orm) + ConstantReader(const TypeChecker.fromRuntime(Orm) .firstAnnotationOf(modelType.element)), buildStep, resolver, @@ -184,7 +184,7 @@ Future buildOrmContext( if (through != null && through is InterfaceType) { throughContext = await buildOrmContext( through.element, - new ConstantReader(const TypeChecker.fromRuntime(Serializable) + ConstantReader(const TypeChecker.fromRuntime(Serializable) .firstAnnotationOf(modelType.element)), buildStep, resolver, @@ -196,20 +196,20 @@ Future buildOrmContext( if (ormAnn != null) { foreignTable = - new ConstantReader(ormAnn).peek('tableName')?.stringValue; + ConstantReader(ormAnn).peek('tableName')?.stringValue; } foreignTable ??= pluralize(foreign.buildContext.modelClassNameRecase.snakeCase); } on StackOverflowError { - throw new UnsupportedError( + throw UnsupportedError( 'There is an infinite cycle between ${clazz.name} and ${field.type.name}. This triggered a stack overflow.'); } } } // Fill in missing keys - var rcc = new ReCase(field.name); + var rcc = ReCase(field.name); String keyName(OrmBuildContext ctx, String missing) { var _keyName = @@ -236,7 +236,7 @@ Future buildOrmContext( localKey ??= '${rcc.snakeCase}_$foreignKey'; } - var relation = new RelationshipReader( + var relation = RelationshipReader( type, localKey: localKey, foreignKey: foreignKey, @@ -251,28 +251,31 @@ Future buildOrmContext( // 'foreignKey=$foreignKey, localKey=$localKey'); if (relation.type == RelationshipType.belongsTo) { - var name = new ReCase(relation.localKey).camelCase; + var name = ReCase(relation.localKey).camelCase; ctx.buildContext.aliases[name] = relation.localKey; if (!ctx.effectiveFields.any((f) => f.name == field.name)) { var foreignField = relation.findForeignField(ctx); var foreign = relation.throughContext ?? relation.foreign; var type = foreignField.type; - if (isSpecialId(foreign, foreignField)) + if (isSpecialId(foreign, foreignField)) { type = field.type.element.context.typeProvider.intType; - var rf = new RelationFieldImpl(name, relation, type, field); + } + var rf = RelationFieldImpl(name, relation, type, field); ctx.effectiveFields.add(rf); } } ctx.relations[field.name] = relation; } else { - if (column?.type == null) + if (column?.type == null) { throw 'Cannot infer SQL column type for field "${ctx.buildContext.originalClassName}.${field.name}" with type "${field.type.displayName}".'; + } ctx.columns[field.name] = column; - if (!ctx.effectiveFields.any((f) => f.name == field.name)) + if (!ctx.effectiveFields.any((f) => f.name == field.name)) { ctx.effectiveFields.add(field); + } } } @@ -280,22 +283,30 @@ Future buildOrmContext( } ColumnType inferColumnType(DartType type) { - if (const TypeChecker.fromRuntime(String).isAssignableFromType(type)) + if (const TypeChecker.fromRuntime(String).isAssignableFromType(type)) { return ColumnType.varChar; - if (const TypeChecker.fromRuntime(int).isAssignableFromType(type)) + } + if (const TypeChecker.fromRuntime(int).isAssignableFromType(type)) { return ColumnType.int; - if (const TypeChecker.fromRuntime(double).isAssignableFromType(type)) + } + if (const TypeChecker.fromRuntime(double).isAssignableFromType(type)) { return ColumnType.decimal; - if (const TypeChecker.fromRuntime(num).isAssignableFromType(type)) + } + if (const TypeChecker.fromRuntime(num).isAssignableFromType(type)) { return ColumnType.numeric; - if (const TypeChecker.fromRuntime(bool).isAssignableFromType(type)) + } + if (const TypeChecker.fromRuntime(bool).isAssignableFromType(type)) { return ColumnType.boolean; - if (const TypeChecker.fromRuntime(DateTime).isAssignableFromType(type)) + } + if (const TypeChecker.fromRuntime(DateTime).isAssignableFromType(type)) { return ColumnType.timeStamp; - if (const TypeChecker.fromRuntime(Map).isAssignableFromType(type)) + } + if (const TypeChecker.fromRuntime(Map).isAssignableFromType(type)) { return ColumnType.jsonb; - if (const TypeChecker.fromRuntime(List).isAssignableFromType(type)) + } + if (const TypeChecker.fromRuntime(List).isAssignableFromType(type)) { return ColumnType.jsonb; + } if (type is InterfaceType && type.element.isEnum) return ColumnType.int; return null; } @@ -317,10 +328,10 @@ Column reviveColumn(ConstantReader cr) { } if (columnObj != null) { - columnType = new _ColumnType(columnObj); + columnType = _ColumnType(columnObj); } - return new Column( + return Column( isNullable: cr.peek('isNullable')?.boolValue, length: cr.peek('length')?.intValue, type: columnType, @@ -329,7 +340,7 @@ Column reviveColumn(ConstantReader cr) { } const TypeChecker relationshipTypeChecker = - const TypeChecker.fromRuntime(Relationship); + TypeChecker.fromRuntime(Relationship); class OrmBuildContext { final BuildContext buildContext; diff --git a/angel_orm_generator/lib/src/orm_generator.dart b/angel_orm_generator/lib/src/orm_generator.dart index e0f3e6b7..e2919a90 100644 --- a/angel_orm_generator/lib/src/orm_generator.dart +++ b/angel_orm_generator/lib/src/orm_generator.dart @@ -17,14 +17,14 @@ var floatTypes = [ ]; Builder ormBuilder(BuilderOptions options) { - return new SharedPartBuilder([ - new OrmGenerator( + return SharedPartBuilder([ + OrmGenerator( autoSnakeCaseNames: options.config['auto_snake_case_names'] != false) ], 'angel_orm'); } TypeReference futureOf(String type) { - return new TypeReference((b) => b + return TypeReference((b) => b ..symbol = 'Future' ..types.add(refer(type))); } @@ -42,14 +42,14 @@ class OrmGenerator extends GeneratorForAnnotation { var ctx = await buildOrmContext(element, annotation, buildStep, buildStep.resolver, autoSnakeCaseNames); var lib = buildOrmLibrary(buildStep.inputId, ctx); - return lib.accept(new DartEmitter()).toString(); + return lib.accept(DartEmitter()).toString(); } else { throw 'The @Orm() annotation can only be applied to classes.'; } } Library buildOrmLibrary(AssetId inputId, OrmBuildContext ctx) { - return new Library((lib) { + return Library((lib) { // Create `FooQuery` class // Create `FooQueryWhere` class lib.body.add(buildQueryClass(ctx)); @@ -59,12 +59,12 @@ class OrmGenerator extends GeneratorForAnnotation { } Class buildQueryClass(OrmBuildContext ctx) { - return new Class((clazz) { + return Class((clazz) { var rc = ctx.buildContext.modelClassNameRecase; var queryWhereType = refer('${rc.pascalCase}QueryWhere'); clazz ..name = '${rc.pascalCase}Query' - ..extend = new TypeReference((b) { + ..extend = TypeReference((b) { b ..symbol = 'Query' ..types.addAll([ @@ -96,7 +96,7 @@ class OrmGenerator extends GeneratorForAnnotation { })); // Add values - clazz.fields.add(new Field((b) { + clazz.fields.add(Field((b) { var type = refer('${rc.pascalCase}QueryValues'); b ..name = 'values' @@ -107,23 +107,23 @@ class OrmGenerator extends GeneratorForAnnotation { })); // Add tableName - clazz.methods.add(new Method((m) { + clazz.methods.add(Method((m) { m ..name = 'tableName' ..annotations.add(refer('override')) ..type = MethodType.getter - ..body = new Block((b) { + ..body = Block((b) { b.addExpression(literalString(ctx.tableName).returned); }); })); // Add fields getter - clazz.methods.add(new Method((m) { + clazz.methods.add(Method((m) { m ..name = 'fields' ..annotations.add(refer('override')) ..type = MethodType.getter - ..body = new Block((b) { + ..body = Block((b) { var names = ctx.effectiveFields .map((f) => literalString(ctx.buildContext.resolveFieldName(f.name))) @@ -133,41 +133,41 @@ class OrmGenerator extends GeneratorForAnnotation { })); // Add _where member - clazz.fields.add(new Field((b) { + clazz.fields.add(Field((b) { b ..name = '_where' ..type = queryWhereType; })); // Add where getter - clazz.methods.add(new Method((b) { + clazz.methods.add(Method((b) { b ..name = 'where' ..type = MethodType.getter ..returns = queryWhereType ..annotations.add(refer('override')) - ..body = new Block((b) => b.addExpression(refer('_where').returned)); + ..body = Block((b) => b.addExpression(refer('_where').returned)); })); // newWhereClause() - clazz.methods.add(new Method((b) { + clazz.methods.add(Method((b) { b ..name = 'newWhereClause' ..annotations.add(refer('override')) ..returns = queryWhereType - ..body = new Block((b) => b.addExpression( + ..body = Block((b) => b.addExpression( queryWhereType.newInstance([refer('this')]).returned)); })); // Add deserialize() - clazz.methods.add(new Method((m) { + clazz.methods.add(Method((m) { m ..name = 'parseRow' ..static = true ..returns = ctx.buildContext.modelClassType - ..requiredParameters.add(new Parameter((b) => b + ..requiredParameters.add(Parameter((b) => b ..name = 'row' ..type = refer('List'))) - ..body = new Block((b) { + ..body = Block((b) { int i = 0; var args = {}; @@ -177,11 +177,11 @@ class OrmGenerator extends GeneratorForAnnotation { if (isSpecialId(ctx, field)) type = refer('int'); var expr = (refer('row').index(literalNum(i++))); - if (isSpecialId(ctx, field)) + if (isSpecialId(ctx, field)) { expr = expr.property('toString').call([]); - else if (field is RelationFieldImpl) + } else if (field is RelationFieldImpl) { continue; - else if (ctx.columns[field.name]?.type == ColumnType.json) { + } else if (ctx.columns[field.name]?.type == ColumnType.json) { expr = refer('json') .property('decode') .call([expr.asA(refer('String'))]).asA(type); @@ -193,14 +193,15 @@ class OrmGenerator extends GeneratorForAnnotation { var isNull = expr.equalTo(literalNull); expr = isNull.conditional(literalNull, type.property('values').index(expr.asA(refer('int')))); - } else + } else { expr = expr.asA(type); + } args[field.name] = expr; } b.statements - .add(new Code('if (row.every((x) => x == null)) return null;')); + .add(Code('if (row.every((x) => x == null)) return null;')); b.addExpression(ctx.buildContext.modelClassType .newInstance([], args).assignVar('model')); @@ -230,11 +231,11 @@ class OrmGenerator extends GeneratorForAnnotation { } var expr = refer('model').property('copyWith').call([], {name: parsed}); - var block = new Block( - (b) => b.addExpression(refer('model').assign(expr))); - var blockStr = block.accept(new DartEmitter()); + var block = + Block((b) => b.addExpression(refer('model').assign(expr))); + var blockStr = block.accept(DartEmitter()); var ifStr = 'if (row.length > $i) { $blockStr }'; - b.statements.add(new Code(ifStr)); + b.statements.add(Code(ifStr)); i += relation.foreign.effectiveFields.length; }); @@ -242,20 +243,20 @@ class OrmGenerator extends GeneratorForAnnotation { }); })); - clazz.methods.add(new Method((m) { + clazz.methods.add(Method((m) { m ..name = 'deserialize' ..annotations.add(refer('override')) - ..requiredParameters.add(new Parameter((b) => b + ..requiredParameters.add(Parameter((b) => b ..name = 'row' ..type = refer('List'))) - ..body = new Block((b) { + ..body = Block((b) { b.addExpression(refer('parseRow').call([refer('row')]).returned); }); })); // If there are any relations, we need some overrides. - clazz.constructors.add(new Constructor((b) { + clazz.constructors.add(Constructor((b) { b ..optionalParameters.add(Parameter((b) => b ..named = true @@ -263,7 +264,7 @@ class OrmGenerator extends GeneratorForAnnotation { ..type = TypeReference((b) => b ..symbol = 'Set' ..types.add(refer('String'))))) - ..body = new Block((b) { + ..body = Block((b) { b.statements.addAll([ Code('trampoline ??= Set();'), Code('trampoline.add(tableName);'), @@ -331,12 +332,11 @@ class OrmGenerator extends GeneratorForAnnotation { }); var out = outExprs.reduce((a, b) => a.and(b)); - clazz.methods.add(new Method((b) { + clazz.methods.add(Method((b) { b ..name = 'canCompile' ..annotations.add(refer('override')) - ..requiredParameters - .add(new Parameter((b) => b..name = 'trampoline')) + ..requiredParameters.add(Parameter((b) => b..name = 'trampoline')) ..returns = refer('bool') ..body = Block((b) { b.addExpression(out.returned); @@ -346,16 +346,16 @@ class OrmGenerator extends GeneratorForAnnotation { // TODO: Ultimately remove the insert override if (false && ctx.relations.isNotEmpty) { - clazz.methods.add(new Method((b) { + clazz.methods.add(Method((b) { b ..name = 'insert' ..annotations.add(refer('override')) - ..requiredParameters.add(new Parameter((b) => b..name = 'executor')) - ..body = new Block((b) { - var inTransaction = new Method((b) { + ..requiredParameters.add(Parameter((b) => b..name = 'executor')) + ..body = Block((b) { + var inTransaction = Method((b) { b ..modifier = MethodModifier.async - ..body = new Block((b) { + ..body = Block((b) { b.addExpression(refer('super') .property('insert') .call([refer('executor')]) @@ -404,24 +404,24 @@ class OrmGenerator extends GeneratorForAnnotation { // Create a Future fetchLinked(T model, QueryExecutor), if necessary. if (false && ctx.relations.values.any((r) => r.type == RelationshipType.hasMany)) { - clazz.methods.add(new Method((b) { + clazz.methods.add(Method((b) { b ..name = 'fetchLinked' ..modifier = MethodModifier.async - ..returns = new TypeReference((b) { + ..returns = TypeReference((b) { b ..symbol = 'Future' ..types.add(ctx.buildContext.modelClassType); }) ..requiredParameters.addAll([ - new Parameter((b) => b + Parameter((b) => b ..name = 'model' ..type = ctx.buildContext.modelClassType), - new Parameter((b) => b + Parameter((b) => b ..name = 'executor' ..type = refer('QueryExecutor')), ]) - ..body = new Block((b) { + ..body = Block((b) { var args = {}; ctx.relations.forEach((name, relation) { @@ -443,9 +443,9 @@ class OrmGenerator extends GeneratorForAnnotation { : 'model.${localField.name}'; var cascadeText = '..where.${foreignField.name}.equals($queryValue)'; - var queryText = queryInstance.accept(new DartEmitter()); + var queryText = queryInstance.accept(DartEmitter()); var combinedExpr = - new CodeExpression(new Code('($queryText$cascadeText)')); + CodeExpression(Code('($queryText$cascadeText)')); // Finally, just call get and await it. var expr = combinedExpr @@ -466,12 +466,12 @@ class OrmGenerator extends GeneratorForAnnotation { // execute in a transaction, and invoke fetchLinked. if (ctx.relations.values.any((r) => r.type == RelationshipType.hasMany)) { for (var methodName in const ['get', 'update', 'delete']) { - clazz.methods.add(new Method((b) { + clazz.methods.add(Method((b) { var type = ctx.buildContext.modelClassType.accept(DartEmitter()); b ..name = methodName ..annotations.add(refer('override')) - ..requiredParameters.add(new Parameter((b) => b + ..requiredParameters.add(Parameter((b) => b ..name = 'executor' ..type = refer('QueryExecutor'))); @@ -500,7 +500,7 @@ class OrmGenerator extends GeneratorForAnnotation { '@HasMany and @ManyToMany relations require a primary key to be defined on the model.'; } - b.body = new Code(''' + b.body = Code(''' return super.$methodName(executor).then((result) { return result.fold>([], (out, model) { var idx = out.indexWhere((m) => m.$keyName == model.$keyName); @@ -521,19 +521,19 @@ class OrmGenerator extends GeneratorForAnnotation { } Class buildWhereClass(OrmBuildContext ctx) { - return new Class((clazz) { + return Class((clazz) { var rc = ctx.buildContext.modelClassNameRecase; clazz ..name = '${rc.pascalCase}QueryWhere' ..extend = refer('QueryWhere'); // Build expressionBuilders getter - clazz.methods.add(new Method((m) { + clazz.methods.add(Method((m) { m ..name = 'expressionBuilders' ..annotations.add(refer('override')) ..type = MethodType.getter - ..body = new Block((b) { + ..body = Block((b) { var references = ctx.effectiveFields.map((f) => refer(f.name)); b.addExpression(literalList(references).returned); }); @@ -557,11 +557,11 @@ class OrmGenerator extends GeneratorForAnnotation { if (const TypeChecker.fromRuntime(int).isExactlyType(type) || const TypeChecker.fromRuntime(double).isExactlyType(type) || isSpecialId(ctx, field)) { - builderType = new TypeReference((b) => b + builderType = TypeReference((b) => b ..symbol = 'NumericSqlExpressionBuilder' ..types.add(refer(isSpecialId(ctx, field) ? 'int' : type.name))); } else if (type is InterfaceType && type.element.isEnum) { - builderType = new TypeReference((b) => b + builderType = TypeReference((b) => b ..symbol = 'EnumSqlExpressionBuilder' ..types.add(convertTypeReference(type))); args.add(CodeExpression(Code('(v) => v.index'))); @@ -580,20 +580,20 @@ class OrmGenerator extends GeneratorForAnnotation { builderType = refer('ListSqlExpressionBuilder'); } else if (ctx.relations.containsKey(field.name)) { var relation = ctx.relations[field.name]; - if (relation.type != RelationshipType.belongsTo) + if (relation.type != RelationshipType.belongsTo) { continue; - else { - builderType = new TypeReference((b) => b + } else { + builderType = TypeReference((b) => b ..symbol = 'NumericSqlExpressionBuilder' ..types.add(refer('int'))); name = relation.localKey; } } else { - throw new UnsupportedError( + throw UnsupportedError( 'Cannot generate ORM code for field of type ${field.type.name}.'); } - clazz.fields.add(new Field((b) { + clazz.fields.add(Field((b) { b ..name = name ..modifier = FieldModifier.final$ @@ -611,9 +611,9 @@ class OrmGenerator extends GeneratorForAnnotation { } // Now, just add a constructor that initializes each builder. - clazz.constructors.add(new Constructor((b) { + clazz.constructors.add(Constructor((b) { b - ..requiredParameters.add(new Parameter((b) => b + ..requiredParameters.add(Parameter((b) => b ..name = 'query' ..type = refer('${rc.pascalCase}Query'))) ..initializers.addAll(initializers); @@ -622,7 +622,7 @@ class OrmGenerator extends GeneratorForAnnotation { } Class buildValuesClass(OrmBuildContext ctx) { - return new Class((clazz) { + return Class((clazz) { var rc = ctx.buildContext.modelClassNameRecase; clazz ..name = '${rc.pascalCase}QueryValues' @@ -660,7 +660,7 @@ class OrmGenerator extends GeneratorForAnnotation { var name = ctx.buildContext.resolveFieldName(field.name); var type = convertTypeReference(field.type); - clazz.methods.add(new Method((b) { + clazz.methods.add(Method((b) { var value = refer('values').index(literalString(name)); if (fType is InterfaceType && fType.element.isEnum) { @@ -684,10 +684,10 @@ class OrmGenerator extends GeneratorForAnnotation { ..name = field.name ..type = MethodType.getter ..returns = type - ..body = new Block((b) => b.addExpression(value.returned)); + ..body = Block((b) => b.addExpression(value.returned)); })); - clazz.methods.add(new Method((b) { + clazz.methods.add(Method((b) { Expression value = refer('value'); if (fType is InterfaceType && fType.element.isEnum) { @@ -702,7 +702,7 @@ class OrmGenerator extends GeneratorForAnnotation { b ..name = field.name ..type = MethodType.setter - ..requiredParameters.add(new Parameter((b) => b + ..requiredParameters.add(Parameter((b) => b ..name = 'value' ..type = type)) ..body = @@ -711,17 +711,18 @@ class OrmGenerator extends GeneratorForAnnotation { } // Add an copyFrom(model) - clazz.methods.add(new Method((b) { + clazz.methods.add(Method((b) { b ..name = 'copyFrom' ..returns = refer('void') - ..requiredParameters.add(new Parameter((b) => b + ..requiredParameters.add(Parameter((b) => b ..name = 'model' ..type = ctx.buildContext.modelClassType)) - ..body = new Block((b) { + ..body = Block((b) { for (var field in ctx.effectiveFields) { - if (isSpecialId(ctx, field) || field is RelationFieldImpl) + if (isSpecialId(ctx, field) || field is RelationFieldImpl) { continue; + } b.addExpression(refer(field.name) .assign(refer('model').property(field.name))); } @@ -744,11 +745,11 @@ class OrmGenerator extends GeneratorForAnnotation { } var cond = prop.notEqualTo(literalNull); - var condStr = cond.accept(new DartEmitter()); + var condStr = cond.accept(DartEmitter()); var blkStr = - new Block((b) => b.addExpression(target.assign(parsedId))) - .accept(new DartEmitter()); - var ifStmt = new Code('if ($condStr) { $blkStr }'); + Block((b) => b.addExpression(target.assign(parsedId))) + .accept(DartEmitter()); + var ifStmt = Code('if ($condStr) { $blkStr }'); b.statements.add(ifStmt); } } diff --git a/angel_orm_generator/lib/src/readers.dart b/angel_orm_generator/lib/src/readers.dart index 4017168b..5c251dd1 100644 --- a/angel_orm_generator/lib/src/readers.dart +++ b/angel_orm_generator/lib/src/readers.dart @@ -5,7 +5,7 @@ import 'package:angel_orm/angel_orm.dart'; import 'package:source_gen/source_gen.dart'; import 'orm_build_context.dart'; -const TypeChecker columnTypeChecker = const TypeChecker.fromRuntime(Column); +const TypeChecker columnTypeChecker = TypeChecker.fromRuntime(Column); Orm reviveORMAnnotation(ConstantReader reader) { return Orm( From eabd89aff50fab6962df1df35ce6b520901285db Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:36:16 -0400 Subject: [PATCH 15/44] Remove dead code --- .../lib/src/orm_generator.dart | 118 ------------------ 1 file changed, 118 deletions(-) diff --git a/angel_orm_generator/lib/src/orm_generator.dart b/angel_orm_generator/lib/src/orm_generator.dart index e2919a90..2eeb2441 100644 --- a/angel_orm_generator/lib/src/orm_generator.dart +++ b/angel_orm_generator/lib/src/orm_generator.dart @@ -344,124 +344,6 @@ class OrmGenerator extends GeneratorForAnnotation { })); } - // TODO: Ultimately remove the insert override - if (false && ctx.relations.isNotEmpty) { - clazz.methods.add(Method((b) { - b - ..name = 'insert' - ..annotations.add(refer('override')) - ..requiredParameters.add(Parameter((b) => b..name = 'executor')) - ..body = Block((b) { - var inTransaction = Method((b) { - b - ..modifier = MethodModifier.async - ..body = Block((b) { - b.addExpression(refer('super') - .property('insert') - .call([refer('executor')]) - .awaited - .assignVar('result')); - - // Just call getOne() again - if (ctx.effectiveFields.any((f) => - isSpecialId(ctx, f) || - (ctx.columns[f.name]?.indexType == - IndexType.primaryKey))) { - b.addExpression(refer('where') - .property('id') - .property('equals') - .call([ - (refer('int') - .property('tryParse') - .call([refer('result').property('id')])) - ])); - - b.addExpression(refer('result').assign( - refer('getOne').call([refer('executor')]).awaited)); - } - - // TODO: Remove - Fetch the results of @hasMany - // ctx.relations.forEach((name, relation) { - // if (relation.type == RelationshipType.hasMany) { - // // Call fetchLinked(); - // var fetchLinked = refer('fetchLinked') - // .call([refer('result'), refer('executor')]).awaited; - // b.addExpression(refer('result').assign(fetchLinked)); - // } - // }); - - b.addExpression(refer('result').returned); - }); - }); - - b.addExpression(refer('executor') - .property('transaction') - .call([inTransaction.closure]).returned); - }); - })); - } - - // Create a Future fetchLinked(T model, QueryExecutor), if necessary. - if (false && - ctx.relations.values.any((r) => r.type == RelationshipType.hasMany)) { - clazz.methods.add(Method((b) { - b - ..name = 'fetchLinked' - ..modifier = MethodModifier.async - ..returns = TypeReference((b) { - b - ..symbol = 'Future' - ..types.add(ctx.buildContext.modelClassType); - }) - ..requiredParameters.addAll([ - Parameter((b) => b - ..name = 'model' - ..type = ctx.buildContext.modelClassType), - Parameter((b) => b - ..name = 'executor' - ..type = refer('QueryExecutor')), - ]) - ..body = Block((b) { - var args = {}; - - ctx.relations.forEach((name, relation) { - // TODO: Should this be entirely removed? - if (relation.type == RelationshipType.hasMany) { - // For each hasMany, we need to create a query of - // the corresponding type. - var foreign = relation.foreign; - var queryType = refer( - '${foreign.buildContext.modelClassNameRecase.pascalCase}Query'); - var queryInstance = queryType.newInstance([]); - - // Next, we need to apply a cascade that sets the correct query value. - var localField = relation.findLocalField(ctx); - var foreignField = relation.findForeignField(ctx); - - var queryValue = (isSpecialId(ctx, localField)) - ? 'int.parse(model.id)' - : 'model.${localField.name}'; - var cascadeText = - '..where.${foreignField.name}.equals($queryValue)'; - var queryText = queryInstance.accept(DartEmitter()); - var combinedExpr = - CodeExpression(Code('($queryText$cascadeText)')); - - // Finally, just call get and await it. - var expr = combinedExpr - .property('get') - .call([refer('executor')]).awaited; - args[name] = expr; - } - }); - - // Just return a copyWith - b.addExpression( - refer('model').property('copyWith').call([], args).returned); - }); - })); - } - // Also, if there is a @HasMany, generate overrides for query methods that // execute in a transaction, and invoke fetchLinked. if (ctx.relations.values.any((r) => r.type == RelationshipType.hasMany)) { From b2632e2945fe20caecf46f16392142d5d88b7143 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:45:12 -0400 Subject: [PATCH 16/44] always generate a field for subquery joins --- .../lib/src/orm_generator.dart | 38 +++++++++++++------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/angel_orm_generator/lib/src/orm_generator.dart b/angel_orm_generator/lib/src/orm_generator.dart index 2eeb2441..05daa59b 100644 --- a/angel_orm_generator/lib/src/orm_generator.dart +++ b/angel_orm_generator/lib/src/orm_generator.dart @@ -293,18 +293,32 @@ class OrmGenerator extends GeneratorForAnnotation { .map(literalString) .toList(); - // Instead of passing the table as-is, we'll compile a subquery. - if (relation.type == RelationshipType.hasMany) { - var foreignQueryType = - foreign.buildContext.modelClassNameRecase.pascalCase + - 'Query'; - joinArgs.insert( - 0, - refer(foreignQueryType).newInstance( - [], {'trampoline': refer('trampoline')})); - } else { - joinArgs.insert(0, literalString(foreign.tableName)); - } + // In the past, we would either do a join on the table name + // itself, or create an instance of a query. + // + // From this point on, however, we will create a field for each + // join, so that users can customize the generated query. + // + // There'll be a private `_field`, and then a getter, named `field`, + // that returns the subqueryb object. + var foreignQueryType = refer( + foreign.buildContext.modelClassNameRecase.pascalCase + + 'Query'); + clazz + ..fields.add(Field((b) => b + ..name = '_$fieldName' + ..type = foreignQueryType)) + ..methods.add(Method((b) => b + ..name = fieldName + ..type = MethodType.getter + ..returns = foreignQueryType + ..body = refer('_$fieldName').returned.statement)); + + // Assign a value to `_field`. + var queryInstantiation = foreignQueryType + .newInstance([], {'trampoline': refer('trampoline')}); + joinArgs.insert( + 0, queryInstantiation.assign(refer('_$fieldName'))); b.addExpression(refer('leftJoin').call(joinArgs, { 'additionalFields': From 703b16206ac3778f6faa5f351a1fbcb20fd7cc20 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:45:47 -0400 Subject: [PATCH 17/44] Tidy up email_indexed.dart --- angel_orm_test/lib/src/models/email_indexed.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/angel_orm_test/lib/src/models/email_indexed.dart b/angel_orm_test/lib/src/models/email_indexed.dart index 3b215365..676bd12e 100644 --- a/angel_orm_test/lib/src/models/email_indexed.dart +++ b/angel_orm_test/lib/src/models/email_indexed.dart @@ -1,5 +1,4 @@ import 'package:angel_migration/angel_migration.dart'; -import 'package:angel_model/angel_model.dart'; import 'package:angel_orm/angel_orm.dart'; import 'package:angel_serialize/angel_serialize.dart'; part 'email_indexed.g.dart'; From 9a97b93eced7b0fdf37459f6ed9ccc5f5fbdcea8 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:46:22 -0400 Subject: [PATCH 18/44] Move MapQueryValues to the proper file --- angel_orm/lib/src/map_query_values.dart | 9 +++++++++ angel_orm/lib/src/query_values.dart | 10 +--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/angel_orm/lib/src/map_query_values.dart b/angel_orm/lib/src/map_query_values.dart index e69de29b..398ba9bf 100644 --- a/angel_orm/lib/src/map_query_values.dart +++ b/angel_orm/lib/src/map_query_values.dart @@ -0,0 +1,9 @@ +import 'query_values.dart'; + +/// A [QueryValues] implementation that simply writes to a [Map]. +class MapQueryValues extends QueryValues { + final Map values = {}; + + @override + Map toMap() => values; +} diff --git a/angel_orm/lib/src/query_values.dart b/angel_orm/lib/src/query_values.dart index d576060b..566ad8e2 100644 --- a/angel_orm/lib/src/query_values.dart +++ b/angel_orm/lib/src/query_values.dart @@ -56,12 +56,4 @@ abstract class QueryValues { } return b.toString(); } -} - -/// A [QueryValues] implementation that simply writes to a [Map]. -class MapQueryValues extends QueryValues { - final Map values = {}; - - @override - Map toMap() => values; -} +} \ No newline at end of file From d3d16855fedd9d36747d756f9767be5682f50eec Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:47:42 -0400 Subject: [PATCH 19/44] Update angel_orm_test pubspec --- angel_orm_test/pubspec.yaml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/angel_orm_test/pubspec.yaml b/angel_orm_test/pubspec.yaml index d22b79a4..d5dde49b 100644 --- a/angel_orm_test/pubspec.yaml +++ b/angel_orm_test/pubspec.yaml @@ -1,16 +1,20 @@ name: angel_orm_test publish_to: none -description: Common tests for Angel ORM backends.s +description: Common tests for Angel ORM backends. environment: sdk: ">=2.0.0 <3.0.0" dependencies: - angel_migration: ^2.0.0-alpha + angel_migration: + path: ../angel_migration angel_model: ^1.0.0 - angel_orm: ^2.0.0-dev + angel_orm: ^2.0.0 angel_serialize: ^2.0.0 test: ^1.0.0 dev_dependencies: angel_orm_generator: path: ../angel_orm_generator - angel_framework: ^2.0.0-alpha - build_runner: ^1.0.0 \ No newline at end of file + angel_framework: ^2.0.0 + build_runner: ^1.0.0 +dependency_overrides: + angel_orm: + path: ../angel_orm \ No newline at end of file From f4b7512c5182203d75d869cc3418a9dbfeb6846d Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:53:27 -0400 Subject: [PATCH 20/44] Regen test models --- .../lib/src/orm_generator.dart | 2 +- angel_orm_test/lib/src/models/book.g.dart | 17 +++++- .../lib/src/models/email_indexed.g.dart | 34 +++++++++-- angel_orm_test/lib/src/models/leg.g.dart | 8 ++- angel_orm_test/lib/src/models/order.g.dart | 9 ++- angel_orm_test/lib/src/models/tree.g.dart | 8 ++- .../lib/src/models/unorthodox.g.dart | 60 ++++++++++++++++--- angel_orm_test/lib/src/models/user.g.dart | 32 ++++++++-- 8 files changed, 149 insertions(+), 21 deletions(-) diff --git a/angel_orm_generator/lib/src/orm_generator.dart b/angel_orm_generator/lib/src/orm_generator.dart index 05daa59b..b5a305c0 100644 --- a/angel_orm_generator/lib/src/orm_generator.dart +++ b/angel_orm_generator/lib/src/orm_generator.dart @@ -318,7 +318,7 @@ class OrmGenerator extends GeneratorForAnnotation { var queryInstantiation = foreignQueryType .newInstance([], {'trampoline': refer('trampoline')}); joinArgs.insert( - 0, queryInstantiation.assign(refer('_$fieldName'))); + 0, refer('_$fieldName').assign(queryInstantiation)); b.addExpression(refer('leftJoin').call(joinArgs, { 'additionalFields': diff --git a/angel_orm_test/lib/src/models/book.g.dart b/angel_orm_test/lib/src/models/book.g.dart index acbfb238..dc6607f0 100644 --- a/angel_orm_test/lib/src/models/book.g.dart +++ b/angel_orm_test/lib/src/models/book.g.dart @@ -55,10 +55,11 @@ class BookQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = BookQueryWhere(this); - leftJoin('authors', 'author_id', 'id', + leftJoin(_author = AuthorQuery(trampoline: trampoline), 'author_id', 'id', additionalFields: const ['id', 'created_at', 'updated_at', 'name'], trampoline: trampoline); - leftJoin('authors', 'partner_author_id', 'id', + leftJoin(_partnerAuthor = AuthorQuery(trampoline: trampoline), + 'partner_author_id', 'id', additionalFields: const ['id', 'created_at', 'updated_at', 'name'], trampoline: trampoline); } @@ -68,6 +69,10 @@ class BookQuery extends Query { BookQueryWhere _where; + AuthorQuery _author; + + AuthorQuery _partnerAuthor; + @override get casts { return {}; @@ -122,6 +127,14 @@ class BookQuery extends Query { deserialize(List row) { return parseRow(row); } + + AuthorQuery get author { + return _author; + } + + AuthorQuery get partnerAuthor { + return _partnerAuthor; + } } class BookQueryWhere extends QueryWhere { diff --git a/angel_orm_test/lib/src/models/email_indexed.g.dart b/angel_orm_test/lib/src/models/email_indexed.g.dart index f8fc5422..d61b85ee 100644 --- a/angel_orm_test/lib/src/models/email_indexed.g.dart +++ b/angel_orm_test/lib/src/models/email_indexed.g.dart @@ -64,7 +64,8 @@ class RoleQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = RoleQueryWhere(this); - leftJoin(RoleUserQuery(trampoline: trampoline), 'role', 'role_role', + leftJoin( + _users = RoleUserQuery(trampoline: trampoline), 'role', 'role_role', additionalFields: const ['email', 'name', 'password'], trampoline: trampoline); } @@ -74,6 +75,8 @@ class RoleQuery extends Query { RoleQueryWhere _where; + RoleUserQuery _users; + @override get casts { return {}; @@ -116,6 +119,10 @@ class RoleQuery extends Query { return parseRow(row); } + RoleUserQuery get users { + return _users; + } + @override bool canCompile(trampoline) { return (!(trampoline.contains('roles') && @@ -213,9 +220,9 @@ class RoleUserQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = RoleUserQueryWhere(this); - leftJoin('roles', 'role_role', 'role', + leftJoin(_role = RoleQuery(trampoline: trampoline), 'role_role', 'role', additionalFields: const ['role'], trampoline: trampoline); - leftJoin('users', 'user_email', 'email', + leftJoin(_user = UserQuery(trampoline: trampoline), 'user_email', 'email', additionalFields: const ['email', 'name', 'password'], trampoline: trampoline); } @@ -225,6 +232,10 @@ class RoleUserQuery extends Query { RoleUserQueryWhere _where; + RoleQuery _role; + + UserQuery _user; + @override get casts { return {}; @@ -268,6 +279,14 @@ class RoleUserQuery extends Query { deserialize(List row) { return parseRow(row); } + + RoleQuery get role { + return _role; + } + + UserQuery get user { + return _user; + } } class RoleUserQueryWhere extends QueryWhere { @@ -316,7 +335,8 @@ class UserQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = UserQueryWhere(this); - leftJoin(RoleUserQuery(trampoline: trampoline), 'email', 'user_email', + leftJoin( + _roles = RoleUserQuery(trampoline: trampoline), 'email', 'user_email', additionalFields: const ['role'], trampoline: trampoline); } @@ -325,6 +345,8 @@ class UserQuery extends Query { UserQueryWhere _where; + RoleUserQuery _roles; + @override get casts { return {}; @@ -370,6 +392,10 @@ class UserQuery extends Query { return parseRow(row); } + RoleUserQuery get roles { + return _roles; + } + @override bool canCompile(trampoline) { return (!(trampoline.contains('users') && diff --git a/angel_orm_test/lib/src/models/leg.g.dart b/angel_orm_test/lib/src/models/leg.g.dart index 28042af5..e3e2079d 100644 --- a/angel_orm_test/lib/src/models/leg.g.dart +++ b/angel_orm_test/lib/src/models/leg.g.dart @@ -50,7 +50,7 @@ class LegQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = LegQueryWhere(this); - leftJoin('feet', 'id', 'leg_id', + leftJoin(_foot = FootQuery(trampoline: trampoline), 'id', 'leg_id', additionalFields: const [ 'id', 'created_at', @@ -66,6 +66,8 @@ class LegQuery extends Query { LegQueryWhere _where; + FootQuery _foot; + @override get casts { return {}; @@ -109,6 +111,10 @@ class LegQuery extends Query { deserialize(List row) { return parseRow(row); } + + FootQuery get foot { + return _foot; + } } class LegQueryWhere extends QueryWhere { diff --git a/angel_orm_test/lib/src/models/order.g.dart b/angel_orm_test/lib/src/models/order.g.dart index b18adb9c..25dfb8f6 100644 --- a/angel_orm_test/lib/src/models/order.g.dart +++ b/angel_orm_test/lib/src/models/order.g.dart @@ -53,7 +53,8 @@ class OrderQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = OrderQueryWhere(this); - leftJoin('customers', 'customer_id', 'id', + leftJoin( + _customer = CustomerQuery(trampoline: trampoline), 'customer_id', 'id', additionalFields: const ['id', 'created_at', 'updated_at'], trampoline: trampoline); } @@ -63,6 +64,8 @@ class OrderQuery extends Query { OrderQueryWhere _where; + CustomerQuery _customer; + @override get casts { return {}; @@ -116,6 +119,10 @@ class OrderQuery extends Query { deserialize(List row) { return parseRow(row); } + + CustomerQuery get customer { + return _customer; + } } class OrderQueryWhere extends QueryWhere { diff --git a/angel_orm_test/lib/src/models/tree.g.dart b/angel_orm_test/lib/src/models/tree.g.dart index 9adfb803..b12e8b9e 100644 --- a/angel_orm_test/lib/src/models/tree.g.dart +++ b/angel_orm_test/lib/src/models/tree.g.dart @@ -50,7 +50,7 @@ class TreeQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = TreeQueryWhere(this); - leftJoin(FruitQuery(trampoline: trampoline), 'id', 'tree_id', + leftJoin(_fruits = FruitQuery(trampoline: trampoline), 'id', 'tree_id', additionalFields: const [ 'id', 'created_at', @@ -66,6 +66,8 @@ class TreeQuery extends Query { TreeQueryWhere _where; + FruitQuery _fruits; + @override get casts { return {}; @@ -112,6 +114,10 @@ class TreeQuery extends Query { return parseRow(row); } + FruitQuery get fruits { + return _fruits; + } + @override get(QueryExecutor executor) { return super.get(executor).then((result) { diff --git a/angel_orm_test/lib/src/models/unorthodox.g.dart b/angel_orm_test/lib/src/models/unorthodox.g.dart index 400d5da6..9042596c 100644 --- a/angel_orm_test/lib/src/models/unorthodox.g.dart +++ b/angel_orm_test/lib/src/models/unorthodox.g.dart @@ -187,9 +187,10 @@ class WeirdJoinQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = WeirdJoinQueryWhere(this); - leftJoin('unorthodoxes', 'join_name', 'name', + leftJoin(_unorthodox = UnorthodoxQuery(trampoline: trampoline), 'join_name', + 'name', additionalFields: const ['name'], trampoline: trampoline); - leftJoin('songs', 'id', 'weird_join_id', + leftJoin(_song = SongQuery(trampoline: trampoline), 'id', 'weird_join_id', additionalFields: const [ 'id', 'created_at', @@ -198,9 +199,10 @@ class WeirdJoinQuery extends Query { 'title' ], trampoline: trampoline); - leftJoin(NumbaQuery(trampoline: trampoline), 'id', 'parent', + leftJoin(_numbas = NumbaQuery(trampoline: trampoline), 'id', 'parent', additionalFields: const ['i', 'parent'], trampoline: trampoline); - leftJoin(FooPivotQuery(trampoline: trampoline), 'id', 'weird_join_id', + leftJoin( + _foos = FooPivotQuery(trampoline: trampoline), 'id', 'weird_join_id', additionalFields: const ['bar'], trampoline: trampoline); } @@ -209,6 +211,14 @@ class WeirdJoinQuery extends Query { WeirdJoinQueryWhere _where; + UnorthodoxQuery _unorthodox; + + SongQuery _song; + + NumbaQuery _numbas; + + FooPivotQuery _foos; + @override get casts { return {}; @@ -265,6 +275,22 @@ class WeirdJoinQuery extends Query { return parseRow(row); } + UnorthodoxQuery get unorthodox { + return _unorthodox; + } + + SongQuery get song { + return _song; + } + + NumbaQuery get numbas { + return _numbas; + } + + FooPivotQuery get foos { + return _foos; + } + @override bool canCompile(trampoline) { return (!(trampoline.contains('weird_joins') && @@ -579,7 +605,8 @@ class FooQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = FooQueryWhere(this); - leftJoin(FooPivotQuery(trampoline: trampoline), 'bar', 'foo_bar', + leftJoin( + _weirdJoins = FooPivotQuery(trampoline: trampoline), 'bar', 'foo_bar', additionalFields: const ['id', 'join_name'], trampoline: trampoline); } @@ -588,6 +615,8 @@ class FooQuery extends Query { FooQueryWhere _where; + FooPivotQuery _weirdJoins; + @override get casts { return {}; @@ -630,6 +659,10 @@ class FooQuery extends Query { return parseRow(row); } + FooPivotQuery get weirdJoins { + return _weirdJoins; + } + @override bool canCompile(trampoline) { return (!(trampoline.contains('foos') && @@ -727,9 +760,10 @@ class FooPivotQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = FooPivotQueryWhere(this); - leftJoin('weird_joins', 'weird_join_id', 'id', + leftJoin(_weirdJoin = WeirdJoinQuery(trampoline: trampoline), + 'weird_join_id', 'id', additionalFields: const ['id', 'join_name'], trampoline: trampoline); - leftJoin('foos', 'foo_bar', 'bar', + leftJoin(_foo = FooQuery(trampoline: trampoline), 'foo_bar', 'bar', additionalFields: const ['bar'], trampoline: trampoline); } @@ -738,6 +772,10 @@ class FooPivotQuery extends Query { FooPivotQueryWhere _where; + WeirdJoinQuery _weirdJoin; + + FooQuery _foo; + @override get casts { return {}; @@ -781,6 +819,14 @@ class FooPivotQuery extends Query { deserialize(List row) { return parseRow(row); } + + WeirdJoinQuery get weirdJoin { + return _weirdJoin; + } + + FooQuery get foo { + return _foo; + } } class FooPivotQueryWhere extends QueryWhere { diff --git a/angel_orm_test/lib/src/models/user.g.dart b/angel_orm_test/lib/src/models/user.g.dart index 19dade2e..c5fd1239 100644 --- a/angel_orm_test/lib/src/models/user.g.dart +++ b/angel_orm_test/lib/src/models/user.g.dart @@ -66,7 +66,7 @@ class UserQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = UserQueryWhere(this); - leftJoin(RoleUserQuery(trampoline: trampoline), 'id', 'user_id', + leftJoin(_roles = RoleUserQuery(trampoline: trampoline), 'id', 'user_id', additionalFields: const ['id', 'created_at', 'updated_at', 'name'], trampoline: trampoline); } @@ -76,6 +76,8 @@ class UserQuery extends Query { UserQueryWhere _where; + RoleUserQuery _roles; + @override get casts { return {}; @@ -131,6 +133,10 @@ class UserQuery extends Query { return parseRow(row); } + RoleUserQuery get roles { + return _roles; + } + @override bool canCompile(trampoline) { return (!(trampoline.contains('users') && @@ -272,10 +278,10 @@ class RoleUserQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = RoleUserQueryWhere(this); - leftJoin('roles', 'role_id', 'id', + leftJoin(_role = RoleQuery(trampoline: trampoline), 'role_id', 'id', additionalFields: const ['id', 'created_at', 'updated_at', 'name'], trampoline: trampoline); - leftJoin('users', 'user_id', 'id', + leftJoin(_user = UserQuery(trampoline: trampoline), 'user_id', 'id', additionalFields: const [ 'id', 'created_at', @@ -292,6 +298,10 @@ class RoleUserQuery extends Query { RoleUserQueryWhere _where; + RoleQuery _role; + + UserQuery _user; + @override get casts { return {}; @@ -335,6 +345,14 @@ class RoleUserQuery extends Query { deserialize(List row) { return parseRow(row); } + + RoleQuery get role { + return _role; + } + + UserQuery get user { + return _user; + } } class RoleUserQueryWhere extends QueryWhere { @@ -383,7 +401,7 @@ class RoleQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = RoleQueryWhere(this); - leftJoin(RoleUserQuery(trampoline: trampoline), 'id', 'role_id', + leftJoin(_users = RoleUserQuery(trampoline: trampoline), 'id', 'role_id', additionalFields: const [ 'id', 'created_at', @@ -400,6 +418,8 @@ class RoleQuery extends Query { RoleQueryWhere _where; + RoleUserQuery _users; + @override get casts { return {}; @@ -446,6 +466,10 @@ class RoleQuery extends Query { return parseRow(row); } + RoleUserQuery get users { + return _users; + } + @override bool canCompile(trampoline) { return (!(trampoline.contains('roles') && From 5b4a063e610e4dad6dfae8203f8ee767453787c6 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 17 Aug 2019 18:57:58 -0400 Subject: [PATCH 21/44] Add joined subquery tests --- angel_orm_test/lib/src/belongs_to_test.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/angel_orm_test/lib/src/belongs_to_test.dart b/angel_orm_test/lib/src/belongs_to_test.dart index cef8344a..75843991 100644 --- a/angel_orm_test/lib/src/belongs_to_test.dart +++ b/angel_orm_test/lib/src/belongs_to_test.dart @@ -146,4 +146,19 @@ belongsToTests(FutureOr Function() createExecutor, expect(book.author, isNotNull); expect(book.author.name, jkRowling.name); }); + + group('joined subquery', () async { + // To verify that the joined subquery is correct, + // we test both a query that return empty, and one + // that should return correctly. + test('returns empty on false subquery', () async { + var query = BookQuery()..author.where.name.equals('Billie Jean'); + expect(await query.get(executor), isEmpty); + }); + + test('returns values on true subquery', () async { + var query = BookQuery()..author.where.name.like('%Rowling%'); + expect(await query.get(executor), [deathlyHallows]); + }); + }); } From 532b6be4b2852343e974b796f05092c1db68e7de Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 10:28:45 -0400 Subject: [PATCH 22/44] Apply pedantic lints --- angel_orm/lib/src/join_on.dart | 2 +- angel_orm/lib/src/query_executor.dart | 2 +- angel_orm/lib/src/query_values.dart | 2 +- angel_orm_mysql/example/main.g.dart | 2 +- angel_orm_mysql/lib/angel_orm_mysql.dart | 2 +- angel_orm_mysql/pubspec.yaml | 5 ++++- angel_orm_service/example/todo.g.dart | 10 +++++----- angel_orm_service/lib/angel_orm_service.dart | 15 ++++++--------- angel_orm_service/pubspec.yaml | 5 ++++- angel_orm_service/test/pokemon.g.dart | 18 +++++++++--------- angel_orm_test/lib/src/models/has_car.dart | 7 +++---- angel_orm_test/lib/src/models/has_map.dart | 4 ++-- 12 files changed, 38 insertions(+), 36 deletions(-) diff --git a/angel_orm/lib/src/join_on.dart b/angel_orm/lib/src/join_on.dart index acf3ee11..7bfed401 100644 --- a/angel_orm/lib/src/join_on.dart +++ b/angel_orm/lib/src/join_on.dart @@ -5,4 +5,4 @@ class JoinOn { final SqlExpressionBuilder value; JoinOn(this.key, this.value); -} \ No newline at end of file +} diff --git a/angel_orm/lib/src/query_executor.dart b/angel_orm/lib/src/query_executor.dart index ec6448c0..85474365 100644 --- a/angel_orm/lib/src/query_executor.dart +++ b/angel_orm/lib/src/query_executor.dart @@ -16,7 +16,7 @@ abstract class QueryExecutor { /// /// If [f] fails, the transaction will be rolled back, and the /// responsible exception will be re-thrown. - /// + /// /// Whether nested transactions are supported depends on the /// underlying driver. Future transaction(FutureOr Function(QueryExecutor) f); diff --git a/angel_orm/lib/src/query_values.dart b/angel_orm/lib/src/query_values.dart index 566ad8e2..368cc8c6 100644 --- a/angel_orm/lib/src/query_values.dart +++ b/angel_orm/lib/src/query_values.dart @@ -56,4 +56,4 @@ abstract class QueryValues { } return b.toString(); } -} \ No newline at end of file +} diff --git a/angel_orm_mysql/example/main.g.dart b/angel_orm_mysql/example/main.g.dart index f35cf8fe..56bcf3e1 100644 --- a/angel_orm_mysql/example/main.g.dart +++ b/angel_orm_mysql/example/main.g.dart @@ -153,7 +153,7 @@ class TodoQueryValues extends MapQueryValues { class Todo extends _Todo { Todo( {this.id, - @required this.isComplete = false, + this.isComplete = false, this.text, this.createdAt, this.updatedAt}); diff --git a/angel_orm_mysql/lib/angel_orm_mysql.dart b/angel_orm_mysql/lib/angel_orm_mysql.dart index 50ac6521..fdda00d8 100644 --- a/angel_orm_mysql/lib/angel_orm_mysql.dart +++ b/angel_orm_mysql/lib/angel_orm_mysql.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:angel_orm/angel_orm.dart'; import 'package:angel_orm/src/query.dart'; import 'package:logging/logging.dart'; -import 'package:pool/pool.dart'; +// import 'package:pool/pool.dart'; import 'package:sqljocky5/connection/connection.dart'; import 'package:sqljocky5/sqljocky.dart'; diff --git a/angel_orm_mysql/pubspec.yaml b/angel_orm_mysql/pubspec.yaml index d7b92dcf..2beabb75 100644 --- a/angel_orm_mysql/pubspec.yaml +++ b/angel_orm_mysql/pubspec.yaml @@ -17,4 +17,7 @@ dev_dependencies: angel_orm_test: path: ../angel_orm_test build_runner: ^1.0.0 - test: ^1.0.0 \ No newline at end of file + test: ^1.0.0 +dependency_overrides: + angel_migration: + path: ../angel_migration \ No newline at end of file diff --git a/angel_orm_service/example/todo.g.dart b/angel_orm_service/example/todo.g.dart index a99cfd4d..6ac25846 100644 --- a/angel_orm_service/example/todo.g.dart +++ b/angel_orm_service/example/todo.g.dart @@ -179,7 +179,7 @@ class Todo extends _Todo { String text, DateTime createdAt, DateTime updatedAt}) { - return new Todo( + return Todo( id: id ?? this.id, isComplete: isComplete ?? this.isComplete, text: text ?? this.text, @@ -215,7 +215,7 @@ class Todo extends _Todo { // SerializerGenerator // ************************************************************************** -const TodoSerializer todoSerializer = const TodoSerializer(); +const TodoSerializer todoSerializer = TodoSerializer(); class TodoEncoder extends Converter { const TodoEncoder(); @@ -240,10 +240,10 @@ class TodoSerializer extends Codec { get decoder => const TodoDecoder(); static Todo fromMap(Map map) { if (map['text'] == null) { - throw new FormatException("Missing required field 'text' on Todo."); + throw FormatException("Missing required field 'text' on Todo."); } - return new Todo( + return Todo( id: map['id'] as String, isComplete: map['is_complete'] as bool ?? false, text: map['text'] as String, @@ -264,7 +264,7 @@ class TodoSerializer extends Codec { return null; } if (model.text == null) { - throw new FormatException("Missing required field 'text' on Todo."); + throw FormatException("Missing required field 'text' on Todo."); } return { diff --git a/angel_orm_service/lib/angel_orm_service.dart b/angel_orm_service/lib/angel_orm_service.dart index 4e6ab6b1..e3b6c57d 100644 --- a/angel_orm_service/lib/angel_orm_service.dart +++ b/angel_orm_service/lib/angel_orm_service.dart @@ -67,9 +67,9 @@ class OrmService> if (v is Map) { v.forEach((key, value) { var descending = false; - if (value is String) + if (value is String) { descending = value == '-1'; - else if (value is num) descending = value.toInt() == -1; + } else if (value is num) descending = value.toInt() == -1; query.orderBy(key.toString(), descending: descending); }); } else if (v is String) { @@ -120,8 +120,7 @@ class OrmService> await _applyQuery(query, params); var result = await query.getOne(executor); if (result != null) return result; - throw new AngelHttpException.notFound( - message: 'No record found for ID $id'); + throw AngelHttpException.notFound(message: 'No record found for ID $id'); } @override @@ -133,7 +132,7 @@ class OrmService> await _applyQuery(query, params); var result = await query.getOne(executor); if (result != null) return result; - throw new AngelHttpException.notFound(message: errorMessage); + throw AngelHttpException.notFound(message: errorMessage); } @override @@ -170,8 +169,7 @@ class OrmService> var result = await query.updateOne(executor); if (result != null) return result; - throw new AngelHttpException.notFound( - message: 'No record found for ID $id'); + throw AngelHttpException.notFound(message: 'No record found for ID $id'); } @override @@ -192,7 +190,6 @@ class OrmService> var result = await query.deleteOne(executor); if (result != null) return result; - throw new AngelHttpException.notFound( - message: 'No record found for ID $id'); + throw AngelHttpException.notFound(message: 'No record found for ID $id'); } } diff --git a/angel_orm_service/pubspec.yaml b/angel_orm_service/pubspec.yaml index 40607677..9ef79e75 100644 --- a/angel_orm_service/pubspec.yaml +++ b/angel_orm_service/pubspec.yaml @@ -23,4 +23,7 @@ dev_dependencies: logging: ^0.11.0 pedantic: ^1.0.0 postgres: ^1.0.0 - test: ^1.0.0 \ No newline at end of file + test: ^1.0.0 +dependency_overrides: + angel_migration: + path: ../angel_migration \ No newline at end of file diff --git a/angel_orm_service/test/pokemon.g.dart b/angel_orm_service/test/pokemon.g.dart index d6e49ed9..aa769e33 100644 --- a/angel_orm_service/test/pokemon.g.dart +++ b/angel_orm_service/test/pokemon.g.dart @@ -238,7 +238,7 @@ class Pokemon extends _Pokemon { PokemonType type2, DateTime createdAt, DateTime updatedAt}) { - return new Pokemon( + return Pokemon( id: id ?? this.id, species: species ?? this.species, name: name ?? this.name, @@ -281,7 +281,7 @@ class Pokemon extends _Pokemon { // SerializerGenerator // ************************************************************************** -const PokemonSerializer pokemonSerializer = const PokemonSerializer(); +const PokemonSerializer pokemonSerializer = PokemonSerializer(); class PokemonEncoder extends Converter { const PokemonEncoder(); @@ -306,18 +306,18 @@ class PokemonSerializer extends Codec { get decoder => const PokemonDecoder(); static Pokemon fromMap(Map map) { if (map['species'] == null) { - throw new FormatException("Missing required field 'species' on Pokemon."); + throw FormatException("Missing required field 'species' on Pokemon."); } if (map['level'] == null) { - throw new FormatException("Missing required field 'level' on Pokemon."); + throw FormatException("Missing required field 'level' on Pokemon."); } if (map['type1'] == null) { - throw new FormatException("Missing required field 'type1' on Pokemon."); + throw FormatException("Missing required field 'type1' on Pokemon."); } - return new Pokemon( + return Pokemon( id: map['id'] as String, species: map['species'] as String, name: map['name'] as String, @@ -349,15 +349,15 @@ class PokemonSerializer extends Codec { return null; } if (model.species == null) { - throw new FormatException("Missing required field 'species' on Pokemon."); + throw FormatException("Missing required field 'species' on Pokemon."); } if (model.level == null) { - throw new FormatException("Missing required field 'level' on Pokemon."); + throw FormatException("Missing required field 'level' on Pokemon."); } if (model.type1 == null) { - throw new FormatException("Missing required field 'type1' on Pokemon."); + throw FormatException("Missing required field 'type1' on Pokemon."); } return { diff --git a/angel_orm_test/lib/src/models/has_car.dart b/angel_orm_test/lib/src/models/has_car.dart index 6e7a7c8e..6a6e6b64 100644 --- a/angel_orm_test/lib/src/models/has_car.dart +++ b/angel_orm_test/lib/src/models/has_car.dart @@ -2,13 +2,12 @@ import 'package:angel_migration/angel_migration.dart'; import 'package:angel_model/angel_model.dart'; import 'package:angel_orm/angel_orm.dart'; import 'package:angel_serialize/angel_serialize.dart'; -import 'package:meta/meta.dart'; -import 'car.dart'; +// import 'car.dart'; part 'has_car.g.dart'; -Map _carToMap(Car car) => car.toJson(); +// Map _carToMap(Car car) => car.toJson(); -Car _carFromMap(map) => CarSerializer.fromMap(map as Map); +// Car _carFromMap(map) => CarSerializer.fromMap(map as Map); enum CarType { sedan, suv, atv } diff --git a/angel_orm_test/lib/src/models/has_map.dart b/angel_orm_test/lib/src/models/has_map.dart index 8414de94..f98de5a7 100644 --- a/angel_orm_test/lib/src/models/has_map.dart +++ b/angel_orm_test/lib/src/models/has_map.dart @@ -5,8 +5,8 @@ import 'package:angel_serialize/angel_serialize.dart'; import 'package:collection/collection.dart'; part 'has_map.g.dart'; -String _boolToCustom(bool v) => v ? 'yes' : 'no'; -bool _customToBool(v) => v == 'yes'; +// String _boolToCustom(bool v) => v ? 'yes' : 'no'; +// bool _customToBool(v) => v == 'yes'; @orm @serializable From f9bce227ba379099bbb81c36d03a4ba0396d4da5 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 10:32:29 -0400 Subject: [PATCH 23/44] Fix "async group" test error --- angel_orm_test/lib/src/belongs_to_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/angel_orm_test/lib/src/belongs_to_test.dart b/angel_orm_test/lib/src/belongs_to_test.dart index 75843991..326240c8 100644 --- a/angel_orm_test/lib/src/belongs_to_test.dart +++ b/angel_orm_test/lib/src/belongs_to_test.dart @@ -147,7 +147,7 @@ belongsToTests(FutureOr Function() createExecutor, expect(book.author.name, jkRowling.name); }); - group('joined subquery', () async { + group('joined subquery', () { // To verify that the joined subquery is correct, // we test both a query that return empty, and one // that should return correctly. From c1c13ddf68e5787007eb035d0d868b8c3d9b5f34 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 10:36:55 -0400 Subject: [PATCH 24/44] Add printSeparator() util --- angel_orm_postgres/pubspec.yaml | 1 + angel_orm_postgres/test/all_test.dart | 9 ++++----- angel_orm_test/lib/src/belongs_to_test.dart | 2 ++ angel_orm_test/lib/src/util.dart | 11 +++++++++++ 4 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 angel_orm_test/lib/src/util.dart diff --git a/angel_orm_postgres/pubspec.yaml b/angel_orm_postgres/pubspec.yaml index 5fabea04..1bf893cb 100644 --- a/angel_orm_postgres/pubspec.yaml +++ b/angel_orm_postgres/pubspec.yaml @@ -13,4 +13,5 @@ dependencies: dev_dependencies: angel_orm_test: path: ../angel_orm_test + pretty_logging: ^1.0.0 test: ^1.0.0 \ No newline at end of file diff --git a/angel_orm_postgres/test/all_test.dart b/angel_orm_postgres/test/all_test.dart index aaa3c4ef..467cd0f5 100644 --- a/angel_orm_postgres/test/all_test.dart +++ b/angel_orm_postgres/test/all_test.dart @@ -1,14 +1,13 @@ import 'package:angel_orm_test/angel_orm_test.dart'; import 'package:logging/logging.dart'; +import 'package:pretty_logging/pretty_logging.dart'; import 'package:test/test.dart'; import 'common.dart'; void main() { - Logger.root.onRecord.listen((rec) { - print(rec); - if (rec.error != null) print(rec.error); - if (rec.stackTrace != null) print(rec.stackTrace); - }); + Logger.root + ..level = Level.ALL + ..onRecord.listen(prettyLog); group('postgresql', () { group('belongsTo', diff --git a/angel_orm_test/lib/src/belongs_to_test.dart b/angel_orm_test/lib/src/belongs_to_test.dart index 326240c8..bd63c2e0 100644 --- a/angel_orm_test/lib/src/belongs_to_test.dart +++ b/angel_orm_test/lib/src/belongs_to_test.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:angel_orm/angel_orm.dart'; import 'package:test/test.dart'; import 'models/book.dart'; +import 'util.dart'; belongsToTests(FutureOr Function() createExecutor, {FutureOr Function(QueryExecutor) close}) { @@ -152,6 +153,7 @@ belongsToTests(FutureOr Function() createExecutor, // we test both a query that return empty, and one // that should return correctly. test('returns empty on false subquery', () async { + printSeparator('False subquery test'); var query = BookQuery()..author.where.name.equals('Billie Jean'); expect(await query.get(executor), isEmpty); }); diff --git a/angel_orm_test/lib/src/util.dart b/angel_orm_test/lib/src/util.dart new file mode 100644 index 00000000..ea791960 --- /dev/null +++ b/angel_orm_test/lib/src/util.dart @@ -0,0 +1,11 @@ +import 'dart:io'; + +void printSeparator(String title) { + var b = StringBuffer(title.toUpperCase()); + for (int i = b.length; i < stdout.terminalColumns; i++) { + b.write('='); + } + for (int i = 0; i < 3; i++) { + print(b); + } +} From 1e16276be4413987e696d20cfa70de7263f9ca3e Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 10:38:44 -0400 Subject: [PATCH 25/44] Add color to printSeparator --- angel_orm_test/lib/src/util.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/angel_orm_test/lib/src/util.dart b/angel_orm_test/lib/src/util.dart index ea791960..eadc05b0 100644 --- a/angel_orm_test/lib/src/util.dart +++ b/angel_orm_test/lib/src/util.dart @@ -1,11 +1,12 @@ import 'dart:io'; +import 'package:io/ansi.dart'; void printSeparator(String title) { - var b = StringBuffer(title.toUpperCase()); - for (int i = b.length; i < stdout.terminalColumns; i++) { + var b = StringBuffer('===' + title.toUpperCase()); + for (int i = b.length; i < stdout.terminalColumns - 3; i++) { b.write('='); } for (int i = 0; i < 3; i++) { - print(b); + print(magenta.wrap(b.toString())); } } From d124ba943bda0ac1bfe99479bd8428143a17b65e Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 10:40:39 -0400 Subject: [PATCH 26/44] Use angel_orm from path in dev --- angel_orm_postgres/pubspec.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/angel_orm_postgres/pubspec.yaml b/angel_orm_postgres/pubspec.yaml index 1bf893cb..f94e71ac 100644 --- a/angel_orm_postgres/pubspec.yaml +++ b/angel_orm_postgres/pubspec.yaml @@ -14,4 +14,7 @@ dev_dependencies: angel_orm_test: path: ../angel_orm_test pretty_logging: ^1.0.0 - test: ^1.0.0 \ No newline at end of file + test: ^1.0.0 +dependency_overrides: + angel_orm: + path: ../angel_orm \ No newline at end of file From 753b8f6ec42aab68f99806c26663f1c3d3954355 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 10:43:50 -0400 Subject: [PATCH 27/44] Update Postgres transaction signatures --- .../lib/angel_orm_postgres.dart | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/angel_orm_postgres/lib/angel_orm_postgres.dart b/angel_orm_postgres/lib/angel_orm_postgres.dart index 182370de..fb522bad 100644 --- a/angel_orm_postgres/lib/angel_orm_postgres.dart +++ b/angel_orm_postgres/lib/angel_orm_postgres.dart @@ -24,7 +24,13 @@ class PostgreSqlExecutor extends QueryExecutor { PostgreSQLExecutionContext get connection => _connection; /// Closes the connection. - Future close() => (_connection as PostgreSQLConnection).close(); + Future close() { + if (_connection is PostgreSQLConnection) { + return (_connection as PostgreSQLConnection).close(); + } else { + return Future.value(); + } + } @override Future> query( @@ -42,18 +48,16 @@ class PostgreSqlExecutor extends QueryExecutor { } @override - Future transaction(FutureOr Function() f) async { - if (_connection is! PostgreSQLConnection) return await f(); - var old = _connection; + Future transaction(FutureOr Function(QueryExecutor) f) async { + if (_connection is! PostgreSQLConnection) return await f(this); T result; try { logger?.fine('Entering transaction'); await (_connection as PostgreSQLConnection).transaction((ctx) async { - _connection = ctx; - result = await f(); + var tx = PostgreSqlExecutor(ctx, logger: logger); + result = await f(tx); }); } finally { - _connection = old; logger?.fine('Exiting transaction'); return result; } @@ -130,7 +134,7 @@ class PostgreSqlExecutorPool extends QueryExecutor { } @override - Future transaction(FutureOr Function() f) { + Future transaction(FutureOr Function(QueryExecutor) f) { return _pool.withResource(() async { var executor = await _next(); return executor.transaction(f); From 6b7af9c0f832e75b55eccf31d50dedd1039258e5 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 10:50:00 -0400 Subject: [PATCH 28/44] Add optional "parent" to query --- angel_orm/lib/src/query.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/angel_orm/lib/src/query.dart b/angel_orm/lib/src/query.dart index 98f93a85..65f38bc8 100644 --- a/angel_orm/lib/src/query.dart +++ b/angel_orm/lib/src/query.dart @@ -13,9 +13,15 @@ abstract class Query extends QueryBase { final Map _names = {}; final List _orderBy = []; + // An optional "parent query". If provided, [reserveName] will operate in + // the parent's context. + final Query parent; + String _crossJoin, _groupBy; int _limit, _offset; + Query({this.parent}); + /// A reference to an abstract query builder. /// /// This is usually a generated class. @@ -32,6 +38,7 @@ abstract class Query extends QueryBase { /// Returns a unique version of [name], which will not produce a collision within /// the context of this [query]. String reserveName(String name) { + if (parent != null) return parent.reserveName(name); var n = _names[name] ??= 0; _names[name]++; return n == 0 ? name : '${name}$n'; From 18abdc6655a54d28aedc1188f251c7910d55276d Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 10:50:06 -0400 Subject: [PATCH 29/44] Call to() in JoinBuilder --- angel_orm/lib/src/join_builder.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/angel_orm/lib/src/join_builder.dart b/angel_orm/lib/src/join_builder.dart index abdaa810..5636dabb 100644 --- a/angel_orm/lib/src/join_builder.dart +++ b/angel_orm/lib/src/join_builder.dart @@ -54,7 +54,7 @@ class JoinBuilder { break; } - b.write(' $to'); + b.write(' ${to()}'); if (alias != null) b.write(' $alias'); b.write(' ON $left$op$right'); return b.toString(); From ee30c3c9f8cba7a754d0faf555586ad3e56e1bd0 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 10:51:53 -0400 Subject: [PATCH 30/44] Add `parent` to constructors --- .../lib/src/orm_generator.dart | 10 +- angel_orm_test/lib/src/models/book.g.dart | 605 ------- angel_orm_test/lib/src/models/car.g.dart | 367 ---- .../lib/src/models/email_indexed.g.dart | 795 --------- angel_orm_test/lib/src/models/has_car.g.dart | 275 --- angel_orm_test/lib/src/models/has_map.g.dart | 208 --- angel_orm_test/lib/src/models/leg.g.dart | 567 ------- angel_orm_test/lib/src/models/order.g.dart | 597 ------- angel_orm_test/lib/src/models/tree.g.dart | 635 ------- .../lib/src/models/unorthodox.g.dart | 1472 ----------------- angel_orm_test/lib/src/models/user.g.dart | 990 ----------- 11 files changed, 8 insertions(+), 6513 deletions(-) delete mode 100644 angel_orm_test/lib/src/models/book.g.dart delete mode 100644 angel_orm_test/lib/src/models/car.g.dart delete mode 100644 angel_orm_test/lib/src/models/email_indexed.g.dart delete mode 100644 angel_orm_test/lib/src/models/has_car.g.dart delete mode 100644 angel_orm_test/lib/src/models/has_map.g.dart delete mode 100644 angel_orm_test/lib/src/models/leg.g.dart delete mode 100644 angel_orm_test/lib/src/models/order.g.dart delete mode 100644 angel_orm_test/lib/src/models/tree.g.dart delete mode 100644 angel_orm_test/lib/src/models/unorthodox.g.dart delete mode 100644 angel_orm_test/lib/src/models/user.g.dart diff --git a/angel_orm_generator/lib/src/orm_generator.dart b/angel_orm_generator/lib/src/orm_generator.dart index b5a305c0..a501698f 100644 --- a/angel_orm_generator/lib/src/orm_generator.dart +++ b/angel_orm_generator/lib/src/orm_generator.dart @@ -258,6 +258,10 @@ class OrmGenerator extends GeneratorForAnnotation { // If there are any relations, we need some overrides. clazz.constructors.add(Constructor((b) { b + ..optionalParameters.add(Parameter((b) => b + ..named = true + ..name = 'parent' + ..type = refer('Query'))) ..optionalParameters.add(Parameter((b) => b ..named = true ..name = 'trampoline' @@ -315,8 +319,10 @@ class OrmGenerator extends GeneratorForAnnotation { ..body = refer('_$fieldName').returned.statement)); // Assign a value to `_field`. - var queryInstantiation = foreignQueryType - .newInstance([], {'trampoline': refer('trampoline')}); + var queryInstantiation = foreignQueryType.newInstance([], { + 'trampoline': refer('trampoline'), + 'parent': refer('this') + }); joinArgs.insert( 0, refer('_$fieldName').assign(queryInstantiation)); diff --git a/angel_orm_test/lib/src/models/book.g.dart b/angel_orm_test/lib/src/models/book.g.dart deleted file mode 100644 index dc6607f0..00000000 --- a/angel_orm_test/lib/src/models/book.g.dart +++ /dev/null @@ -1,605 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of angel_orm.generator.models.book; - -// ************************************************************************** -// MigrationGenerator -// ************************************************************************** - -class BookMigration extends Migration { - @override - up(Schema schema) { - schema.create('books', (table) { - table.serial('id')..primaryKey(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - table.varChar('name'); - table - .declare('author_id', ColumnType('serial')) - .references('authors', 'id'); - table - .declare('partner_author_id', ColumnType('serial')) - .references('authors', 'id'); - }); - } - - @override - down(Schema schema) { - schema.drop('books'); - } -} - -class AuthorMigration extends Migration { - @override - up(Schema schema) { - schema.create('authors', (table) { - table.serial('id')..primaryKey(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - table.varChar('name', length: 255)..defaultsTo('Tobe Osakwe'); - }); - } - - @override - down(Schema schema) { - schema.drop('authors'); - } -} - -// ************************************************************************** -// OrmGenerator -// ************************************************************************** - -class BookQuery extends Query { - BookQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = BookQueryWhere(this); - leftJoin(_author = AuthorQuery(trampoline: trampoline), 'author_id', 'id', - additionalFields: const ['id', 'created_at', 'updated_at', 'name'], - trampoline: trampoline); - leftJoin(_partnerAuthor = AuthorQuery(trampoline: trampoline), - 'partner_author_id', 'id', - additionalFields: const ['id', 'created_at', 'updated_at', 'name'], - trampoline: trampoline); - } - - @override - final BookQueryValues values = BookQueryValues(); - - BookQueryWhere _where; - - AuthorQuery _author; - - AuthorQuery _partnerAuthor; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'books'; - } - - @override - get fields { - return const [ - 'id', - 'created_at', - 'updated_at', - 'author_id', - 'partner_author_id', - 'name' - ]; - } - - @override - BookQueryWhere get where { - return _where; - } - - @override - BookQueryWhere newWhereClause() { - return BookQueryWhere(this); - } - - static Book parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Book( - id: row[0].toString(), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime), - name: (row[5] as String)); - if (row.length > 6) { - model = model.copyWith( - author: AuthorQuery.parseRow(row.skip(6).take(4).toList())); - } - if (row.length > 10) { - model = model.copyWith( - partnerAuthor: AuthorQuery.parseRow(row.skip(10).take(4).toList())); - } - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } - - AuthorQuery get author { - return _author; - } - - AuthorQuery get partnerAuthor { - return _partnerAuthor; - } -} - -class BookQueryWhere extends QueryWhere { - BookQueryWhere(BookQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), - authorId = NumericSqlExpressionBuilder(query, 'author_id'), - partnerAuthorId = - NumericSqlExpressionBuilder(query, 'partner_author_id'), - name = StringSqlExpressionBuilder(query, 'name'); - - final NumericSqlExpressionBuilder id; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - final NumericSqlExpressionBuilder authorId; - - final NumericSqlExpressionBuilder partnerAuthorId; - - final StringSqlExpressionBuilder name; - - @override - get expressionBuilders { - return [id, createdAt, updatedAt, authorId, partnerAuthorId, name]; - } -} - -class BookQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - int get authorId { - return (values['author_id'] as int); - } - - set authorId(int value) => values['author_id'] = value; - int get partnerAuthorId { - return (values['partner_author_id'] as int); - } - - set partnerAuthorId(int value) => values['partner_author_id'] = value; - String get name { - return (values['name'] as String); - } - - set name(String value) => values['name'] = value; - void copyFrom(Book model) { - createdAt = model.createdAt; - updatedAt = model.updatedAt; - name = model.name; - if (model.author != null) { - values['author_id'] = model.author.id; - } - if (model.partnerAuthor != null) { - values['partner_author_id'] = model.partnerAuthor.id; - } - } -} - -class AuthorQuery extends Query { - AuthorQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = AuthorQueryWhere(this); - } - - @override - final AuthorQueryValues values = AuthorQueryValues(); - - AuthorQueryWhere _where; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'authors'; - } - - @override - get fields { - return const ['id', 'created_at', 'updated_at', 'name']; - } - - @override - AuthorQueryWhere get where { - return _where; - } - - @override - AuthorQueryWhere newWhereClause() { - return AuthorQueryWhere(this); - } - - static Author parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Author( - id: row[0].toString(), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime), - name: (row[3] as String)); - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } -} - -class AuthorQueryWhere extends QueryWhere { - AuthorQueryWhere(AuthorQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), - name = StringSqlExpressionBuilder(query, 'name'); - - final NumericSqlExpressionBuilder id; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - final StringSqlExpressionBuilder name; - - @override - get expressionBuilders { - return [id, createdAt, updatedAt, name]; - } -} - -class AuthorQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - String get name { - return (values['name'] as String); - } - - set name(String value) => values['name'] = value; - void copyFrom(Author model) { - createdAt = model.createdAt; - updatedAt = model.updatedAt; - name = model.name; - } -} - -// ************************************************************************** -// JsonModelGenerator -// ************************************************************************** - -@generatedSerializable -class Book extends _Book { - Book( - {this.id, - this.createdAt, - this.updatedAt, - this.author, - this.partnerAuthor, - this.name}); - - /// A unique identifier corresponding to this item. - @override - String id; - - /// The time at which this item was created. - @override - DateTime createdAt; - - /// The last time at which this item was updated. - @override - DateTime updatedAt; - - @override - _Author author; - - @override - _Author partnerAuthor; - - @override - String name; - - Book copyWith( - {String id, - DateTime createdAt, - DateTime updatedAt, - _Author author, - _Author partnerAuthor, - String name}) { - return Book( - id: id ?? this.id, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - author: author ?? this.author, - partnerAuthor: partnerAuthor ?? this.partnerAuthor, - name: name ?? this.name); - } - - bool operator ==(other) { - return other is _Book && - other.id == id && - other.createdAt == createdAt && - other.updatedAt == updatedAt && - other.author == author && - other.partnerAuthor == partnerAuthor && - other.name == name; - } - - @override - int get hashCode { - return hashObjects([id, createdAt, updatedAt, author, partnerAuthor, name]); - } - - @override - String toString() { - return "Book(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, author=$author, partnerAuthor=$partnerAuthor, name=$name)"; - } - - Map toJson() { - return BookSerializer.toMap(this); - } -} - -@generatedSerializable -class Author extends _Author { - Author({this.id, this.createdAt, this.updatedAt, this.name = 'Tobe Osakwe'}); - - /// A unique identifier corresponding to this item. - @override - String id; - - /// The time at which this item was created. - @override - DateTime createdAt; - - /// The last time at which this item was updated. - @override - DateTime updatedAt; - - @override - final String name; - - Author copyWith( - {String id, DateTime createdAt, DateTime updatedAt, String name}) { - return Author( - id: id ?? this.id, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - name: name ?? this.name); - } - - bool operator ==(other) { - return other is _Author && - other.id == id && - other.createdAt == createdAt && - other.updatedAt == updatedAt && - other.name == name; - } - - @override - int get hashCode { - return hashObjects([id, createdAt, updatedAt, name]); - } - - @override - String toString() { - return "Author(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, name=$name)"; - } - - Map toJson() { - return AuthorSerializer.toMap(this); - } -} - -// ************************************************************************** -// SerializerGenerator -// ************************************************************************** - -const BookSerializer bookSerializer = BookSerializer(); - -class BookEncoder extends Converter { - const BookEncoder(); - - @override - Map convert(Book model) => BookSerializer.toMap(model); -} - -class BookDecoder extends Converter { - const BookDecoder(); - - @override - Book convert(Map map) => BookSerializer.fromMap(map); -} - -class BookSerializer extends Codec { - const BookSerializer(); - - @override - get encoder => const BookEncoder(); - @override - get decoder => const BookDecoder(); - static Book fromMap(Map map) { - return Book( - id: map['id'] as String, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null, - author: map['author'] != null - ? AuthorSerializer.fromMap(map['author'] as Map) - : null, - partnerAuthor: map['partner_author'] != null - ? AuthorSerializer.fromMap(map['partner_author'] as Map) - : null, - name: map['name'] as String); - } - - static Map toMap(_Book model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String(), - 'author': AuthorSerializer.toMap(model.author), - 'partner_author': AuthorSerializer.toMap(model.partnerAuthor), - 'name': model.name - }; - } -} - -abstract class BookFields { - static const List allFields = [ - id, - createdAt, - updatedAt, - author, - partnerAuthor, - name - ]; - - static const String id = 'id'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; - - static const String author = 'author'; - - static const String partnerAuthor = 'partner_author'; - - static const String name = 'name'; -} - -const AuthorSerializer authorSerializer = AuthorSerializer(); - -class AuthorEncoder extends Converter { - const AuthorEncoder(); - - @override - Map convert(Author model) => AuthorSerializer.toMap(model); -} - -class AuthorDecoder extends Converter { - const AuthorDecoder(); - - @override - Author convert(Map map) => AuthorSerializer.fromMap(map); -} - -class AuthorSerializer extends Codec { - const AuthorSerializer(); - - @override - get encoder => const AuthorEncoder(); - @override - get decoder => const AuthorDecoder(); - static Author fromMap(Map map) { - return Author( - id: map['id'] as String, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null, - name: map['name'] as String ?? 'Tobe Osakwe'); - } - - static Map toMap(_Author model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String(), - 'name': model.name - }; - } -} - -abstract class AuthorFields { - static const List allFields = [ - id, - createdAt, - updatedAt, - name - ]; - - static const String id = 'id'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; - - static const String name = 'name'; -} diff --git a/angel_orm_test/lib/src/models/car.g.dart b/angel_orm_test/lib/src/models/car.g.dart deleted file mode 100644 index d637ece7..00000000 --- a/angel_orm_test/lib/src/models/car.g.dart +++ /dev/null @@ -1,367 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of angel_orm.generator.models.car; - -// ************************************************************************** -// MigrationGenerator -// ************************************************************************** - -class CarMigration extends Migration { - @override - up(Schema schema) { - schema.create('cars', (table) { - table.serial('id')..primaryKey(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - table.varChar('make'); - table.varChar('description'); - table.boolean('family_friendly'); - table.timeStamp('recalled_at'); - }); - } - - @override - down(Schema schema) { - schema.drop('cars'); - } -} - -// ************************************************************************** -// OrmGenerator -// ************************************************************************** - -class CarQuery extends Query { - CarQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = CarQueryWhere(this); - } - - @override - final CarQueryValues values = CarQueryValues(); - - CarQueryWhere _where; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'cars'; - } - - @override - get fields { - return const [ - 'id', - 'created_at', - 'updated_at', - 'make', - 'description', - 'family_friendly', - 'recalled_at' - ]; - } - - @override - CarQueryWhere get where { - return _where; - } - - @override - CarQueryWhere newWhereClause() { - return CarQueryWhere(this); - } - - static Car parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Car( - id: row[0].toString(), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime), - make: (row[3] as String), - description: (row[4] as String), - familyFriendly: (row[5] as bool), - recalledAt: (row[6] as DateTime)); - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } -} - -class CarQueryWhere extends QueryWhere { - CarQueryWhere(CarQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), - make = StringSqlExpressionBuilder(query, 'make'), - description = StringSqlExpressionBuilder(query, 'description'), - familyFriendly = BooleanSqlExpressionBuilder(query, 'family_friendly'), - recalledAt = DateTimeSqlExpressionBuilder(query, 'recalled_at'); - - final NumericSqlExpressionBuilder id; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - final StringSqlExpressionBuilder make; - - final StringSqlExpressionBuilder description; - - final BooleanSqlExpressionBuilder familyFriendly; - - final DateTimeSqlExpressionBuilder recalledAt; - - @override - get expressionBuilders { - return [ - id, - createdAt, - updatedAt, - make, - description, - familyFriendly, - recalledAt - ]; - } -} - -class CarQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - String get make { - return (values['make'] as String); - } - - set make(String value) => values['make'] = value; - String get description { - return (values['description'] as String); - } - - set description(String value) => values['description'] = value; - bool get familyFriendly { - return (values['family_friendly'] as bool); - } - - set familyFriendly(bool value) => values['family_friendly'] = value; - DateTime get recalledAt { - return (values['recalled_at'] as DateTime); - } - - set recalledAt(DateTime value) => values['recalled_at'] = value; - void copyFrom(Car model) { - createdAt = model.createdAt; - updatedAt = model.updatedAt; - make = model.make; - description = model.description; - familyFriendly = model.familyFriendly; - recalledAt = model.recalledAt; - } -} - -// ************************************************************************** -// JsonModelGenerator -// ************************************************************************** - -@generatedSerializable -class Car extends _Car { - Car( - {this.id, - this.createdAt, - this.updatedAt, - this.make, - this.description, - this.familyFriendly, - this.recalledAt}); - - /// A unique identifier corresponding to this item. - @override - String id; - - /// The time at which this item was created. - @override - DateTime createdAt; - - /// The last time at which this item was updated. - @override - DateTime updatedAt; - - @override - String make; - - @override - String description; - - @override - bool familyFriendly; - - @override - DateTime recalledAt; - - Car copyWith( - {String id, - DateTime createdAt, - DateTime updatedAt, - String make, - String description, - bool familyFriendly, - DateTime recalledAt}) { - return Car( - id: id ?? this.id, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - make: make ?? this.make, - description: description ?? this.description, - familyFriendly: familyFriendly ?? this.familyFriendly, - recalledAt: recalledAt ?? this.recalledAt); - } - - bool operator ==(other) { - return other is _Car && - other.id == id && - other.createdAt == createdAt && - other.updatedAt == updatedAt && - other.make == make && - other.description == description && - other.familyFriendly == familyFriendly && - other.recalledAt == recalledAt; - } - - @override - int get hashCode { - return hashObjects([ - id, - createdAt, - updatedAt, - make, - description, - familyFriendly, - recalledAt - ]); - } - - @override - String toString() { - return "Car(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, make=$make, description=$description, familyFriendly=$familyFriendly, recalledAt=$recalledAt)"; - } - - Map toJson() { - return CarSerializer.toMap(this); - } -} - -// ************************************************************************** -// SerializerGenerator -// ************************************************************************** - -const CarSerializer carSerializer = CarSerializer(); - -class CarEncoder extends Converter { - const CarEncoder(); - - @override - Map convert(Car model) => CarSerializer.toMap(model); -} - -class CarDecoder extends Converter { - const CarDecoder(); - - @override - Car convert(Map map) => CarSerializer.fromMap(map); -} - -class CarSerializer extends Codec { - const CarSerializer(); - - @override - get encoder => const CarEncoder(); - @override - get decoder => const CarDecoder(); - static Car fromMap(Map map) { - return Car( - id: map['id'] as String, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null, - make: map['make'] as String, - description: map['description'] as String, - familyFriendly: map['family_friendly'] as bool, - recalledAt: map['recalled_at'] != null - ? (map['recalled_at'] is DateTime - ? (map['recalled_at'] as DateTime) - : DateTime.parse(map['recalled_at'].toString())) - : null); - } - - static Map toMap(_Car model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String(), - 'make': model.make, - 'description': model.description, - 'family_friendly': model.familyFriendly, - 'recalled_at': model.recalledAt?.toIso8601String() - }; - } -} - -abstract class CarFields { - static const List allFields = [ - id, - createdAt, - updatedAt, - make, - description, - familyFriendly, - recalledAt - ]; - - static const String id = 'id'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; - - static const String make = 'make'; - - static const String description = 'description'; - - static const String familyFriendly = 'family_friendly'; - - static const String recalledAt = 'recalled_at'; -} diff --git a/angel_orm_test/lib/src/models/email_indexed.g.dart b/angel_orm_test/lib/src/models/email_indexed.g.dart deleted file mode 100644 index d61b85ee..00000000 --- a/angel_orm_test/lib/src/models/email_indexed.g.dart +++ /dev/null @@ -1,795 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'email_indexed.dart'; - -// ************************************************************************** -// MigrationGenerator -// ************************************************************************** - -class RoleMigration extends Migration { - @override - up(Schema schema) { - schema.create('roles', (table) { - table.declare('role', ColumnType('varchar'))..primaryKey(); - }); - } - - @override - down(Schema schema) { - schema.drop('roles', cascade: true); - } -} - -class RoleUserMigration extends Migration { - @override - up(Schema schema) { - schema.create('role_users', (table) { - table - .declare('role_role', ColumnType('varchar')) - .references('roles', 'role'); - table - .declare('user_email', ColumnType('varchar')) - .references('users', 'email'); - }); - } - - @override - down(Schema schema) { - schema.drop('role_users'); - } -} - -class UserMigration extends Migration { - @override - up(Schema schema) { - schema.create('users', (table) { - table.varChar('email')..primaryKey(); - table.varChar('name'); - table.varChar('password'); - }); - } - - @override - down(Schema schema) { - schema.drop('users', cascade: true); - } -} - -// ************************************************************************** -// OrmGenerator -// ************************************************************************** - -class RoleQuery extends Query { - RoleQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = RoleQueryWhere(this); - leftJoin( - _users = RoleUserQuery(trampoline: trampoline), 'role', 'role_role', - additionalFields: const ['email', 'name', 'password'], - trampoline: trampoline); - } - - @override - final RoleQueryValues values = RoleQueryValues(); - - RoleQueryWhere _where; - - RoleUserQuery _users; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'roles'; - } - - @override - get fields { - return const ['role']; - } - - @override - RoleQueryWhere get where { - return _where; - } - - @override - RoleQueryWhere newWhereClause() { - return RoleQueryWhere(this); - } - - static Role parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Role(role: (row[0] as String)); - if (row.length > 1) { - model = model.copyWith( - users: [UserQuery.parseRow(row.skip(1).take(3).toList())] - .where((x) => x != null) - .toList()); - } - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } - - RoleUserQuery get users { - return _users; - } - - @override - bool canCompile(trampoline) { - return (!(trampoline.contains('roles') && - trampoline.contains('role_users'))); - } - - @override - get(QueryExecutor executor) { - return super.get(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.role == model.role); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - users: List<_User>.from(l.users ?? []) - ..addAll(model.users ?? [])); - } - }); - }); - } - - @override - update(QueryExecutor executor) { - return super.update(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.role == model.role); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - users: List<_User>.from(l.users ?? []) - ..addAll(model.users ?? [])); - } - }); - }); - } - - @override - delete(QueryExecutor executor) { - return super.delete(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.role == model.role); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - users: List<_User>.from(l.users ?? []) - ..addAll(model.users ?? [])); - } - }); - }); - } -} - -class RoleQueryWhere extends QueryWhere { - RoleQueryWhere(RoleQuery query) - : role = StringSqlExpressionBuilder(query, 'role'); - - final StringSqlExpressionBuilder role; - - @override - get expressionBuilders { - return [role]; - } -} - -class RoleQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get role { - return (values['role'] as String); - } - - set role(String value) => values['role'] = value; - void copyFrom(Role model) { - role = model.role; - } -} - -class RoleUserQuery extends Query { - RoleUserQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = RoleUserQueryWhere(this); - leftJoin(_role = RoleQuery(trampoline: trampoline), 'role_role', 'role', - additionalFields: const ['role'], trampoline: trampoline); - leftJoin(_user = UserQuery(trampoline: trampoline), 'user_email', 'email', - additionalFields: const ['email', 'name', 'password'], - trampoline: trampoline); - } - - @override - final RoleUserQueryValues values = RoleUserQueryValues(); - - RoleUserQueryWhere _where; - - RoleQuery _role; - - UserQuery _user; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'role_users'; - } - - @override - get fields { - return const ['role_role', 'user_email']; - } - - @override - RoleUserQueryWhere get where { - return _where; - } - - @override - RoleUserQueryWhere newWhereClause() { - return RoleUserQueryWhere(this); - } - - static RoleUser parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = RoleUser(); - if (row.length > 2) { - model = model.copyWith( - role: RoleQuery.parseRow(row.skip(2).take(1).toList())); - } - if (row.length > 3) { - model = model.copyWith( - user: UserQuery.parseRow(row.skip(3).take(3).toList())); - } - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } - - RoleQuery get role { - return _role; - } - - UserQuery get user { - return _user; - } -} - -class RoleUserQueryWhere extends QueryWhere { - RoleUserQueryWhere(RoleUserQuery query) - : roleRole = StringSqlExpressionBuilder(query, 'role_role'), - userEmail = StringSqlExpressionBuilder(query, 'user_email'); - - final StringSqlExpressionBuilder roleRole; - - final StringSqlExpressionBuilder userEmail; - - @override - get expressionBuilders { - return [roleRole, userEmail]; - } -} - -class RoleUserQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get roleRole { - return (values['role_role'] as String); - } - - set roleRole(String value) => values['role_role'] = value; - String get userEmail { - return (values['user_email'] as String); - } - - set userEmail(String value) => values['user_email'] = value; - void copyFrom(RoleUser model) { - if (model.role != null) { - values['role_role'] = model.role.role; - } - if (model.user != null) { - values['user_email'] = model.user.email; - } - } -} - -class UserQuery extends Query { - UserQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = UserQueryWhere(this); - leftJoin( - _roles = RoleUserQuery(trampoline: trampoline), 'email', 'user_email', - additionalFields: const ['role'], trampoline: trampoline); - } - - @override - final UserQueryValues values = UserQueryValues(); - - UserQueryWhere _where; - - RoleUserQuery _roles; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'users'; - } - - @override - get fields { - return const ['email', 'name', 'password']; - } - - @override - UserQueryWhere get where { - return _where; - } - - @override - UserQueryWhere newWhereClause() { - return UserQueryWhere(this); - } - - static User parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = User( - email: (row[0] as String), - name: (row[1] as String), - password: (row[2] as String)); - if (row.length > 3) { - model = model.copyWith( - roles: [RoleQuery.parseRow(row.skip(3).take(1).toList())] - .where((x) => x != null) - .toList()); - } - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } - - RoleUserQuery get roles { - return _roles; - } - - @override - bool canCompile(trampoline) { - return (!(trampoline.contains('users') && - trampoline.contains('role_users'))); - } - - @override - get(QueryExecutor executor) { - return super.get(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.email == model.email); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - roles: List<_Role>.from(l.roles ?? []) - ..addAll(model.roles ?? [])); - } - }); - }); - } - - @override - update(QueryExecutor executor) { - return super.update(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.email == model.email); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - roles: List<_Role>.from(l.roles ?? []) - ..addAll(model.roles ?? [])); - } - }); - }); - } - - @override - delete(QueryExecutor executor) { - return super.delete(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.email == model.email); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - roles: List<_Role>.from(l.roles ?? []) - ..addAll(model.roles ?? [])); - } - }); - }); - } -} - -class UserQueryWhere extends QueryWhere { - UserQueryWhere(UserQuery query) - : email = StringSqlExpressionBuilder(query, 'email'), - name = StringSqlExpressionBuilder(query, 'name'), - password = StringSqlExpressionBuilder(query, 'password'); - - final StringSqlExpressionBuilder email; - - final StringSqlExpressionBuilder name; - - final StringSqlExpressionBuilder password; - - @override - get expressionBuilders { - return [email, name, password]; - } -} - -class UserQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get email { - return (values['email'] as String); - } - - set email(String value) => values['email'] = value; - String get name { - return (values['name'] as String); - } - - set name(String value) => values['name'] = value; - String get password { - return (values['password'] as String); - } - - set password(String value) => values['password'] = value; - void copyFrom(User model) { - email = model.email; - name = model.name; - password = model.password; - } -} - -// ************************************************************************** -// JsonModelGenerator -// ************************************************************************** - -@generatedSerializable -class Role implements _Role { - const Role({this.role, this.users}); - - @override - final String role; - - @override - final List<_User> users; - - Role copyWith({String role, List<_User> users}) { - return Role(role: role ?? this.role, users: users ?? this.users); - } - - bool operator ==(other) { - return other is _Role && - other.role == role && - ListEquality<_User>(DefaultEquality<_User>()) - .equals(other.users, users); - } - - @override - int get hashCode { - return hashObjects([role, users]); - } - - @override - String toString() { - return "Role(role=$role, users=$users)"; - } - - Map toJson() { - return RoleSerializer.toMap(this); - } -} - -@generatedSerializable -class RoleUser implements _RoleUser { - const RoleUser({this.role, this.user}); - - @override - final _Role role; - - @override - final _User user; - - RoleUser copyWith({_Role role, _User user}) { - return RoleUser(role: role ?? this.role, user: user ?? this.user); - } - - bool operator ==(other) { - return other is _RoleUser && other.role == role && other.user == user; - } - - @override - int get hashCode { - return hashObjects([role, user]); - } - - @override - String toString() { - return "RoleUser(role=$role, user=$user)"; - } - - Map toJson() { - return RoleUserSerializer.toMap(this); - } -} - -@generatedSerializable -class User implements _User { - const User({this.email, this.name, this.password, this.roles}); - - @override - final String email; - - @override - final String name; - - @override - final String password; - - @override - final List<_Role> roles; - - User copyWith( - {String email, String name, String password, List<_Role> roles}) { - return User( - email: email ?? this.email, - name: name ?? this.name, - password: password ?? this.password, - roles: roles ?? this.roles); - } - - bool operator ==(other) { - return other is _User && - other.email == email && - other.name == name && - other.password == password && - ListEquality<_Role>(DefaultEquality<_Role>()) - .equals(other.roles, roles); - } - - @override - int get hashCode { - return hashObjects([email, name, password, roles]); - } - - @override - String toString() { - return "User(email=$email, name=$name, password=$password, roles=$roles)"; - } - - Map toJson() { - return UserSerializer.toMap(this); - } -} - -// ************************************************************************** -// SerializerGenerator -// ************************************************************************** - -const RoleSerializer roleSerializer = RoleSerializer(); - -class RoleEncoder extends Converter { - const RoleEncoder(); - - @override - Map convert(Role model) => RoleSerializer.toMap(model); -} - -class RoleDecoder extends Converter { - const RoleDecoder(); - - @override - Role convert(Map map) => RoleSerializer.fromMap(map); -} - -class RoleSerializer extends Codec { - const RoleSerializer(); - - @override - get encoder => const RoleEncoder(); - @override - get decoder => const RoleDecoder(); - static Role fromMap(Map map) { - return Role( - role: map['role'] as String, - users: map['users'] is Iterable - ? List.unmodifiable(((map['users'] as Iterable).whereType()) - .map(UserSerializer.fromMap)) - : null); - } - - static Map toMap(_Role model) { - if (model == null) { - return null; - } - return { - 'role': model.role, - 'users': model.users?.map((m) => UserSerializer.toMap(m))?.toList() - }; - } -} - -abstract class RoleFields { - static const List allFields = [role, users]; - - static const String role = 'role'; - - static const String users = 'users'; -} - -const RoleUserSerializer roleUserSerializer = RoleUserSerializer(); - -class RoleUserEncoder extends Converter { - const RoleUserEncoder(); - - @override - Map convert(RoleUser model) => RoleUserSerializer.toMap(model); -} - -class RoleUserDecoder extends Converter { - const RoleUserDecoder(); - - @override - RoleUser convert(Map map) => RoleUserSerializer.fromMap(map); -} - -class RoleUserSerializer extends Codec { - const RoleUserSerializer(); - - @override - get encoder => const RoleUserEncoder(); - @override - get decoder => const RoleUserDecoder(); - static RoleUser fromMap(Map map) { - return RoleUser( - role: map['role'] != null - ? RoleSerializer.fromMap(map['role'] as Map) - : null, - user: map['user'] != null - ? UserSerializer.fromMap(map['user'] as Map) - : null); - } - - static Map toMap(_RoleUser model) { - if (model == null) { - return null; - } - return { - 'role': RoleSerializer.toMap(model.role), - 'user': UserSerializer.toMap(model.user) - }; - } -} - -abstract class RoleUserFields { - static const List allFields = [role, user]; - - static const String role = 'role'; - - static const String user = 'user'; -} - -const UserSerializer userSerializer = UserSerializer(); - -class UserEncoder extends Converter { - const UserEncoder(); - - @override - Map convert(User model) => UserSerializer.toMap(model); -} - -class UserDecoder extends Converter { - const UserDecoder(); - - @override - User convert(Map map) => UserSerializer.fromMap(map); -} - -class UserSerializer extends Codec { - const UserSerializer(); - - @override - get encoder => const UserEncoder(); - @override - get decoder => const UserDecoder(); - static User fromMap(Map map) { - return User( - email: map['email'] as String, - name: map['name'] as String, - password: map['password'] as String, - roles: map['roles'] is Iterable - ? List.unmodifiable(((map['roles'] as Iterable).whereType()) - .map(RoleSerializer.fromMap)) - : null); - } - - static Map toMap(_User model) { - if (model == null) { - return null; - } - return { - 'email': model.email, - 'name': model.name, - 'password': model.password, - 'roles': model.roles?.map((m) => RoleSerializer.toMap(m))?.toList() - }; - } -} - -abstract class UserFields { - static const List allFields = [email, name, password, roles]; - - static const String email = 'email'; - - static const String name = 'name'; - - static const String password = 'password'; - - static const String roles = 'roles'; -} diff --git a/angel_orm_test/lib/src/models/has_car.g.dart b/angel_orm_test/lib/src/models/has_car.g.dart deleted file mode 100644 index 2dd9d0a2..00000000 --- a/angel_orm_test/lib/src/models/has_car.g.dart +++ /dev/null @@ -1,275 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'has_car.dart'; - -// ************************************************************************** -// MigrationGenerator -// ************************************************************************** - -class HasCarMigration extends Migration { - @override - up(Schema schema) { - schema.create('has_cars', (table) { - table.serial('id')..primaryKey(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - table.integer('type'); - }); - } - - @override - down(Schema schema) { - schema.drop('has_cars'); - } -} - -// ************************************************************************** -// OrmGenerator -// ************************************************************************** - -class HasCarQuery extends Query { - HasCarQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = HasCarQueryWhere(this); - } - - @override - final HasCarQueryValues values = HasCarQueryValues(); - - HasCarQueryWhere _where; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'has_cars'; - } - - @override - get fields { - return const ['id', 'created_at', 'updated_at', 'type']; - } - - @override - HasCarQueryWhere get where { - return _where; - } - - @override - HasCarQueryWhere newWhereClause() { - return HasCarQueryWhere(this); - } - - static HasCar parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = HasCar( - id: row[0].toString(), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime), - type: row[3] == null ? null : CarType.values[(row[3] as int)]); - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } -} - -class HasCarQueryWhere extends QueryWhere { - HasCarQueryWhere(HasCarQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), - type = EnumSqlExpressionBuilder(query, 'type', (v) => v.index); - - final NumericSqlExpressionBuilder id; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - final EnumSqlExpressionBuilder type; - - @override - get expressionBuilders { - return [id, createdAt, updatedAt, type]; - } -} - -class HasCarQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - CarType get type { - return CarType.values[(values['type'] as int)]; - } - - set type(CarType value) => values['type'] = value?.index; - void copyFrom(HasCar model) { - createdAt = model.createdAt; - updatedAt = model.updatedAt; - type = model.type; - } -} - -// ************************************************************************** -// JsonModelGenerator -// ************************************************************************** - -@generatedSerializable -class HasCar extends _HasCar { - HasCar({this.id, this.createdAt, this.updatedAt, this.type = CarType.sedan}); - - /// A unique identifier corresponding to this item. - @override - String id; - - /// The time at which this item was created. - @override - DateTime createdAt; - - /// The last time at which this item was updated. - @override - DateTime updatedAt; - - @override - final CarType type; - - HasCar copyWith( - {String id, DateTime createdAt, DateTime updatedAt, CarType type}) { - return HasCar( - id: id ?? this.id, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - type: type ?? this.type); - } - - bool operator ==(other) { - return other is _HasCar && - other.id == id && - other.createdAt == createdAt && - other.updatedAt == updatedAt && - other.type == type; - } - - @override - int get hashCode { - return hashObjects([id, createdAt, updatedAt, type]); - } - - @override - String toString() { - return "HasCar(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, type=$type)"; - } - - Map toJson() { - return HasCarSerializer.toMap(this); - } -} - -// ************************************************************************** -// SerializerGenerator -// ************************************************************************** - -const HasCarSerializer hasCarSerializer = HasCarSerializer(); - -class HasCarEncoder extends Converter { - const HasCarEncoder(); - - @override - Map convert(HasCar model) => HasCarSerializer.toMap(model); -} - -class HasCarDecoder extends Converter { - const HasCarDecoder(); - - @override - HasCar convert(Map map) => HasCarSerializer.fromMap(map); -} - -class HasCarSerializer extends Codec { - const HasCarSerializer(); - - @override - get encoder => const HasCarEncoder(); - @override - get decoder => const HasCarDecoder(); - static HasCar fromMap(Map map) { - if (map['type'] == null) { - throw FormatException("Missing required field 'type' on HasCar."); - } - - return HasCar( - id: map['id'] as String, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null, - type: map['type'] is CarType - ? (map['type'] as CarType) - : (map['type'] is int - ? CarType.values[map['type'] as int] - : CarType.sedan)); - } - - static Map toMap(_HasCar model) { - if (model == null) { - return null; - } - if (model.type == null) { - throw FormatException("Missing required field 'type' on HasCar."); - } - - return { - 'id': model.id, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String(), - 'type': model.type == null ? null : CarType.values.indexOf(model.type) - }; - } -} - -abstract class HasCarFields { - static const List allFields = [ - id, - createdAt, - updatedAt, - type - ]; - - static const String id = 'id'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; - - static const String type = 'type'; -} diff --git a/angel_orm_test/lib/src/models/has_map.g.dart b/angel_orm_test/lib/src/models/has_map.g.dart deleted file mode 100644 index 77418734..00000000 --- a/angel_orm_test/lib/src/models/has_map.g.dart +++ /dev/null @@ -1,208 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'has_map.dart'; - -// ************************************************************************** -// MigrationGenerator -// ************************************************************************** - -class HasMapMigration extends Migration { - @override - up(Schema schema) { - schema.create('has_maps', (table) { - table.declare('value', ColumnType('jsonb')); - table.declare('list', ColumnType('jsonb')); - }); - } - - @override - down(Schema schema) { - schema.drop('has_maps'); - } -} - -// ************************************************************************** -// OrmGenerator -// ************************************************************************** - -class HasMapQuery extends Query { - HasMapQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = HasMapQueryWhere(this); - } - - @override - final HasMapQueryValues values = HasMapQueryValues(); - - HasMapQueryWhere _where; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'has_maps'; - } - - @override - get fields { - return const ['value', 'list']; - } - - @override - HasMapQueryWhere get where { - return _where; - } - - @override - HasMapQueryWhere newWhereClause() { - return HasMapQueryWhere(this); - } - - static HasMap parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = HasMap( - value: (row[0] as Map), - list: (row[1] as List)); - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } -} - -class HasMapQueryWhere extends QueryWhere { - HasMapQueryWhere(HasMapQuery query) - : value = MapSqlExpressionBuilder(query, 'value'), - list = ListSqlExpressionBuilder(query, 'list'); - - final MapSqlExpressionBuilder value; - - final ListSqlExpressionBuilder list; - - @override - get expressionBuilders { - return [value, list]; - } -} - -class HasMapQueryValues extends MapQueryValues { - @override - get casts { - return {'list': 'jsonb'}; - } - - Map get value { - return (values['value'] as Map); - } - - set value(Map value) => values['value'] = value; - List get list { - return (json.decode((values['list'] as String)) as List); - } - - set list(List value) => values['list'] = json.encode(value); - void copyFrom(HasMap model) { - value = model.value; - list = model.list; - } -} - -// ************************************************************************** -// JsonModelGenerator -// ************************************************************************** - -@generatedSerializable -class HasMap implements _HasMap { - const HasMap({this.value, this.list}); - - @override - final Map value; - - @override - final List list; - - HasMap copyWith({Map value, List list}) { - return HasMap(value: value ?? this.value, list: list ?? this.list); - } - - bool operator ==(other) { - return other is _HasMap && - MapEquality( - keys: DefaultEquality(), values: DefaultEquality()) - .equals(other.value, value) && - ListEquality(DefaultEquality()).equals(other.list, list); - } - - @override - int get hashCode { - return hashObjects([value, list]); - } - - @override - String toString() { - return "HasMap(value=$value, list=$list)"; - } - - Map toJson() { - return HasMapSerializer.toMap(this); - } -} - -// ************************************************************************** -// SerializerGenerator -// ************************************************************************** - -const HasMapSerializer hasMapSerializer = HasMapSerializer(); - -class HasMapEncoder extends Converter { - const HasMapEncoder(); - - @override - Map convert(HasMap model) => HasMapSerializer.toMap(model); -} - -class HasMapDecoder extends Converter { - const HasMapDecoder(); - - @override - HasMap convert(Map map) => HasMapSerializer.fromMap(map); -} - -class HasMapSerializer extends Codec { - const HasMapSerializer(); - - @override - get encoder => const HasMapEncoder(); - @override - get decoder => const HasMapDecoder(); - static HasMap fromMap(Map map) { - return HasMap( - value: map['value'] is Map - ? (map['value'] as Map).cast() - : null, - list: map['list'] is Iterable - ? (map['list'] as Iterable).cast().toList() - : null); - } - - static Map toMap(_HasMap model) { - if (model == null) { - return null; - } - return {'value': model.value, 'list': model.list}; - } -} - -abstract class HasMapFields { - static const List allFields = [value, list]; - - static const String value = 'value'; - - static const String list = 'list'; -} diff --git a/angel_orm_test/lib/src/models/leg.g.dart b/angel_orm_test/lib/src/models/leg.g.dart deleted file mode 100644 index e3e2079d..00000000 --- a/angel_orm_test/lib/src/models/leg.g.dart +++ /dev/null @@ -1,567 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of angel_orm_generator.test.models.leg; - -// ************************************************************************** -// MigrationGenerator -// ************************************************************************** - -class LegMigration extends Migration { - @override - up(Schema schema) { - schema.create('legs', (table) { - table.serial('id')..primaryKey(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - table.varChar('name'); - }); - } - - @override - down(Schema schema) { - schema.drop('legs', cascade: true); - } -} - -class FootMigration extends Migration { - @override - up(Schema schema) { - schema.create('feet', (table) { - table.serial('id')..primaryKey(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - table.integer('leg_id'); - table.declare('n_toes', ColumnType('decimal')); - }); - } - - @override - down(Schema schema) { - schema.drop('feet'); - } -} - -// ************************************************************************** -// OrmGenerator -// ************************************************************************** - -class LegQuery extends Query { - LegQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = LegQueryWhere(this); - leftJoin(_foot = FootQuery(trampoline: trampoline), 'id', 'leg_id', - additionalFields: const [ - 'id', - 'created_at', - 'updated_at', - 'leg_id', - 'n_toes' - ], - trampoline: trampoline); - } - - @override - final LegQueryValues values = LegQueryValues(); - - LegQueryWhere _where; - - FootQuery _foot; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'legs'; - } - - @override - get fields { - return const ['id', 'created_at', 'updated_at', 'name']; - } - - @override - LegQueryWhere get where { - return _where; - } - - @override - LegQueryWhere newWhereClause() { - return LegQueryWhere(this); - } - - static Leg parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Leg( - id: row[0].toString(), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime), - name: (row[3] as String)); - if (row.length > 4) { - model = model.copyWith( - foot: FootQuery.parseRow(row.skip(4).take(5).toList())); - } - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } - - FootQuery get foot { - return _foot; - } -} - -class LegQueryWhere extends QueryWhere { - LegQueryWhere(LegQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), - name = StringSqlExpressionBuilder(query, 'name'); - - final NumericSqlExpressionBuilder id; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - final StringSqlExpressionBuilder name; - - @override - get expressionBuilders { - return [id, createdAt, updatedAt, name]; - } -} - -class LegQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - String get name { - return (values['name'] as String); - } - - set name(String value) => values['name'] = value; - void copyFrom(Leg model) { - createdAt = model.createdAt; - updatedAt = model.updatedAt; - name = model.name; - } -} - -class FootQuery extends Query { - FootQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = FootQueryWhere(this); - } - - @override - final FootQueryValues values = FootQueryValues(); - - FootQueryWhere _where; - - @override - get casts { - return {'n_toes': 'text'}; - } - - @override - get tableName { - return 'feet'; - } - - @override - get fields { - return const ['id', 'created_at', 'updated_at', 'leg_id', 'n_toes']; - } - - @override - FootQueryWhere get where { - return _where; - } - - @override - FootQueryWhere newWhereClause() { - return FootQueryWhere(this); - } - - static Foot parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Foot( - id: row[0].toString(), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime), - legId: (row[3] as int), - nToes: double.tryParse(row[4].toString())); - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } -} - -class FootQueryWhere extends QueryWhere { - FootQueryWhere(FootQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), - legId = NumericSqlExpressionBuilder(query, 'leg_id'), - nToes = NumericSqlExpressionBuilder(query, 'n_toes'); - - final NumericSqlExpressionBuilder id; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - final NumericSqlExpressionBuilder legId; - - final NumericSqlExpressionBuilder nToes; - - @override - get expressionBuilders { - return [id, createdAt, updatedAt, legId, nToes]; - } -} - -class FootQueryValues extends MapQueryValues { - @override - get casts { - return {'n_toes': 'decimal'}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - int get legId { - return (values['leg_id'] as int); - } - - set legId(int value) => values['leg_id'] = value; - double get nToes { - return double.tryParse((values['n_toes'] as String)); - } - - set nToes(double value) => values['n_toes'] = value.toString(); - void copyFrom(Foot model) { - createdAt = model.createdAt; - updatedAt = model.updatedAt; - legId = model.legId; - nToes = model.nToes; - } -} - -// ************************************************************************** -// JsonModelGenerator -// ************************************************************************** - -@generatedSerializable -class Leg extends _Leg { - Leg({this.id, this.createdAt, this.updatedAt, this.foot, this.name}); - - /// A unique identifier corresponding to this item. - @override - String id; - - /// The time at which this item was created. - @override - DateTime createdAt; - - /// The last time at which this item was updated. - @override - DateTime updatedAt; - - @override - _Foot foot; - - @override - String name; - - Leg copyWith( - {String id, - DateTime createdAt, - DateTime updatedAt, - _Foot foot, - String name}) { - return Leg( - id: id ?? this.id, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - foot: foot ?? this.foot, - name: name ?? this.name); - } - - bool operator ==(other) { - return other is _Leg && - other.id == id && - other.createdAt == createdAt && - other.updatedAt == updatedAt && - other.foot == foot && - other.name == name; - } - - @override - int get hashCode { - return hashObjects([id, createdAt, updatedAt, foot, name]); - } - - @override - String toString() { - return "Leg(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, foot=$foot, name=$name)"; - } - - Map toJson() { - return LegSerializer.toMap(this); - } -} - -@generatedSerializable -class Foot extends _Foot { - Foot({this.id, this.createdAt, this.updatedAt, this.legId, this.nToes}); - - /// A unique identifier corresponding to this item. - @override - String id; - - /// The time at which this item was created. - @override - DateTime createdAt; - - /// The last time at which this item was updated. - @override - DateTime updatedAt; - - @override - int legId; - - @override - double nToes; - - Foot copyWith( - {String id, - DateTime createdAt, - DateTime updatedAt, - int legId, - double nToes}) { - return Foot( - id: id ?? this.id, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - legId: legId ?? this.legId, - nToes: nToes ?? this.nToes); - } - - bool operator ==(other) { - return other is _Foot && - other.id == id && - other.createdAt == createdAt && - other.updatedAt == updatedAt && - other.legId == legId && - other.nToes == nToes; - } - - @override - int get hashCode { - return hashObjects([id, createdAt, updatedAt, legId, nToes]); - } - - @override - String toString() { - return "Foot(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, legId=$legId, nToes=$nToes)"; - } - - Map toJson() { - return FootSerializer.toMap(this); - } -} - -// ************************************************************************** -// SerializerGenerator -// ************************************************************************** - -const LegSerializer legSerializer = LegSerializer(); - -class LegEncoder extends Converter { - const LegEncoder(); - - @override - Map convert(Leg model) => LegSerializer.toMap(model); -} - -class LegDecoder extends Converter { - const LegDecoder(); - - @override - Leg convert(Map map) => LegSerializer.fromMap(map); -} - -class LegSerializer extends Codec { - const LegSerializer(); - - @override - get encoder => const LegEncoder(); - @override - get decoder => const LegDecoder(); - static Leg fromMap(Map map) { - return Leg( - id: map['id'] as String, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null, - foot: map['foot'] != null - ? FootSerializer.fromMap(map['foot'] as Map) - : null, - name: map['name'] as String); - } - - static Map toMap(_Leg model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String(), - 'foot': FootSerializer.toMap(model.foot), - 'name': model.name - }; - } -} - -abstract class LegFields { - static const List allFields = [ - id, - createdAt, - updatedAt, - foot, - name - ]; - - static const String id = 'id'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; - - static const String foot = 'foot'; - - static const String name = 'name'; -} - -const FootSerializer footSerializer = FootSerializer(); - -class FootEncoder extends Converter { - const FootEncoder(); - - @override - Map convert(Foot model) => FootSerializer.toMap(model); -} - -class FootDecoder extends Converter { - const FootDecoder(); - - @override - Foot convert(Map map) => FootSerializer.fromMap(map); -} - -class FootSerializer extends Codec { - const FootSerializer(); - - @override - get encoder => const FootEncoder(); - @override - get decoder => const FootDecoder(); - static Foot fromMap(Map map) { - return Foot( - id: map['id'] as String, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null, - legId: map['leg_id'] as int, - nToes: map['n_toes'] as double); - } - - static Map toMap(_Foot model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String(), - 'leg_id': model.legId, - 'n_toes': model.nToes - }; - } -} - -abstract class FootFields { - static const List allFields = [ - id, - createdAt, - updatedAt, - legId, - nToes - ]; - - static const String id = 'id'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; - - static const String legId = 'leg_id'; - - static const String nToes = 'n_toes'; -} diff --git a/angel_orm_test/lib/src/models/order.g.dart b/angel_orm_test/lib/src/models/order.g.dart deleted file mode 100644 index 25dfb8f6..00000000 --- a/angel_orm_test/lib/src/models/order.g.dart +++ /dev/null @@ -1,597 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of angel_orm_generator.test.models.order; - -// ************************************************************************** -// MigrationGenerator -// ************************************************************************** - -class OrderMigration extends Migration { - @override - up(Schema schema) { - schema.create('orders', (table) { - table.serial('id')..primaryKey(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - table.integer('employee_id'); - table.timeStamp('order_date'); - table.integer('shipper_id'); - table - .declare('customer_id', ColumnType('serial')) - .references('customers', 'id'); - }); - } - - @override - down(Schema schema) { - schema.drop('orders'); - } -} - -class CustomerMigration extends Migration { - @override - up(Schema schema) { - schema.create('customers', (table) { - table.serial('id')..primaryKey(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - }); - } - - @override - down(Schema schema) { - schema.drop('customers'); - } -} - -// ************************************************************************** -// OrmGenerator -// ************************************************************************** - -class OrderQuery extends Query { - OrderQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = OrderQueryWhere(this); - leftJoin( - _customer = CustomerQuery(trampoline: trampoline), 'customer_id', 'id', - additionalFields: const ['id', 'created_at', 'updated_at'], - trampoline: trampoline); - } - - @override - final OrderQueryValues values = OrderQueryValues(); - - OrderQueryWhere _where; - - CustomerQuery _customer; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'orders'; - } - - @override - get fields { - return const [ - 'id', - 'created_at', - 'updated_at', - 'customer_id', - 'employee_id', - 'order_date', - 'shipper_id' - ]; - } - - @override - OrderQueryWhere get where { - return _where; - } - - @override - OrderQueryWhere newWhereClause() { - return OrderQueryWhere(this); - } - - static Order parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Order( - id: row[0].toString(), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime), - employeeId: (row[4] as int), - orderDate: (row[5] as DateTime), - shipperId: (row[6] as int)); - if (row.length > 7) { - model = model.copyWith( - customer: CustomerQuery.parseRow(row.skip(7).take(3).toList())); - } - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } - - CustomerQuery get customer { - return _customer; - } -} - -class OrderQueryWhere extends QueryWhere { - OrderQueryWhere(OrderQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), - customerId = NumericSqlExpressionBuilder(query, 'customer_id'), - employeeId = NumericSqlExpressionBuilder(query, 'employee_id'), - orderDate = DateTimeSqlExpressionBuilder(query, 'order_date'), - shipperId = NumericSqlExpressionBuilder(query, 'shipper_id'); - - final NumericSqlExpressionBuilder id; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - final NumericSqlExpressionBuilder customerId; - - final NumericSqlExpressionBuilder employeeId; - - final DateTimeSqlExpressionBuilder orderDate; - - final NumericSqlExpressionBuilder shipperId; - - @override - get expressionBuilders { - return [ - id, - createdAt, - updatedAt, - customerId, - employeeId, - orderDate, - shipperId - ]; - } -} - -class OrderQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - int get customerId { - return (values['customer_id'] as int); - } - - set customerId(int value) => values['customer_id'] = value; - int get employeeId { - return (values['employee_id'] as int); - } - - set employeeId(int value) => values['employee_id'] = value; - DateTime get orderDate { - return (values['order_date'] as DateTime); - } - - set orderDate(DateTime value) => values['order_date'] = value; - int get shipperId { - return (values['shipper_id'] as int); - } - - set shipperId(int value) => values['shipper_id'] = value; - void copyFrom(Order model) { - createdAt = model.createdAt; - updatedAt = model.updatedAt; - employeeId = model.employeeId; - orderDate = model.orderDate; - shipperId = model.shipperId; - if (model.customer != null) { - values['customer_id'] = model.customer.id; - } - } -} - -class CustomerQuery extends Query { - CustomerQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = CustomerQueryWhere(this); - } - - @override - final CustomerQueryValues values = CustomerQueryValues(); - - CustomerQueryWhere _where; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'customers'; - } - - @override - get fields { - return const ['id', 'created_at', 'updated_at']; - } - - @override - CustomerQueryWhere get where { - return _where; - } - - @override - CustomerQueryWhere newWhereClause() { - return CustomerQueryWhere(this); - } - - static Customer parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Customer( - id: row[0].toString(), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime)); - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } -} - -class CustomerQueryWhere extends QueryWhere { - CustomerQueryWhere(CustomerQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'); - - final NumericSqlExpressionBuilder id; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - @override - get expressionBuilders { - return [id, createdAt, updatedAt]; - } -} - -class CustomerQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - void copyFrom(Customer model) { - createdAt = model.createdAt; - updatedAt = model.updatedAt; - } -} - -// ************************************************************************** -// JsonModelGenerator -// ************************************************************************** - -@generatedSerializable -class Order extends _Order { - Order( - {this.id, - this.createdAt, - this.updatedAt, - this.customer, - this.employeeId, - this.orderDate, - this.shipperId}); - - /// A unique identifier corresponding to this item. - @override - String id; - - /// The time at which this item was created. - @override - DateTime createdAt; - - /// The last time at which this item was updated. - @override - DateTime updatedAt; - - @override - final _Customer customer; - - @override - final int employeeId; - - @override - final DateTime orderDate; - - @override - final int shipperId; - - Order copyWith( - {String id, - DateTime createdAt, - DateTime updatedAt, - _Customer customer, - int employeeId, - DateTime orderDate, - int shipperId}) { - return Order( - id: id ?? this.id, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - customer: customer ?? this.customer, - employeeId: employeeId ?? this.employeeId, - orderDate: orderDate ?? this.orderDate, - shipperId: shipperId ?? this.shipperId); - } - - bool operator ==(other) { - return other is _Order && - other.id == id && - other.createdAt == createdAt && - other.updatedAt == updatedAt && - other.customer == customer && - other.employeeId == employeeId && - other.orderDate == orderDate && - other.shipperId == shipperId; - } - - @override - int get hashCode { - return hashObjects( - [id, createdAt, updatedAt, customer, employeeId, orderDate, shipperId]); - } - - @override - String toString() { - return "Order(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, customer=$customer, employeeId=$employeeId, orderDate=$orderDate, shipperId=$shipperId)"; - } - - Map toJson() { - return OrderSerializer.toMap(this); - } -} - -@generatedSerializable -class Customer extends _Customer { - Customer({this.id, this.createdAt, this.updatedAt}); - - /// A unique identifier corresponding to this item. - @override - String id; - - /// The time at which this item was created. - @override - DateTime createdAt; - - /// The last time at which this item was updated. - @override - DateTime updatedAt; - - Customer copyWith({String id, DateTime createdAt, DateTime updatedAt}) { - return Customer( - id: id ?? this.id, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt); - } - - bool operator ==(other) { - return other is _Customer && - other.id == id && - other.createdAt == createdAt && - other.updatedAt == updatedAt; - } - - @override - int get hashCode { - return hashObjects([id, createdAt, updatedAt]); - } - - @override - String toString() { - return "Customer(id=$id, createdAt=$createdAt, updatedAt=$updatedAt)"; - } - - Map toJson() { - return CustomerSerializer.toMap(this); - } -} - -// ************************************************************************** -// SerializerGenerator -// ************************************************************************** - -const OrderSerializer orderSerializer = OrderSerializer(); - -class OrderEncoder extends Converter { - const OrderEncoder(); - - @override - Map convert(Order model) => OrderSerializer.toMap(model); -} - -class OrderDecoder extends Converter { - const OrderDecoder(); - - @override - Order convert(Map map) => OrderSerializer.fromMap(map); -} - -class OrderSerializer extends Codec { - const OrderSerializer(); - - @override - get encoder => const OrderEncoder(); - @override - get decoder => const OrderDecoder(); - static Order fromMap(Map map) { - return Order( - id: map['id'] as String, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null, - customer: map['customer'] != null - ? CustomerSerializer.fromMap(map['customer'] as Map) - : null, - employeeId: map['employee_id'] as int, - orderDate: map['order_date'] != null - ? (map['order_date'] is DateTime - ? (map['order_date'] as DateTime) - : DateTime.parse(map['order_date'].toString())) - : null, - shipperId: map['shipper_id'] as int); - } - - static Map toMap(_Order model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String(), - 'customer': CustomerSerializer.toMap(model.customer), - 'employee_id': model.employeeId, - 'order_date': model.orderDate?.toIso8601String(), - 'shipper_id': model.shipperId - }; - } -} - -abstract class OrderFields { - static const List allFields = [ - id, - createdAt, - updatedAt, - customer, - employeeId, - orderDate, - shipperId - ]; - - static const String id = 'id'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; - - static const String customer = 'customer'; - - static const String employeeId = 'employee_id'; - - static const String orderDate = 'order_date'; - - static const String shipperId = 'shipper_id'; -} - -const CustomerSerializer customerSerializer = CustomerSerializer(); - -class CustomerEncoder extends Converter { - const CustomerEncoder(); - - @override - Map convert(Customer model) => CustomerSerializer.toMap(model); -} - -class CustomerDecoder extends Converter { - const CustomerDecoder(); - - @override - Customer convert(Map map) => CustomerSerializer.fromMap(map); -} - -class CustomerSerializer extends Codec { - const CustomerSerializer(); - - @override - get encoder => const CustomerEncoder(); - @override - get decoder => const CustomerDecoder(); - static Customer fromMap(Map map) { - return Customer( - id: map['id'] as String, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null); - } - - static Map toMap(_Customer model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String() - }; - } -} - -abstract class CustomerFields { - static const List allFields = [id, createdAt, updatedAt]; - - static const String id = 'id'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; -} diff --git a/angel_orm_test/lib/src/models/tree.g.dart b/angel_orm_test/lib/src/models/tree.g.dart deleted file mode 100644 index b12e8b9e..00000000 --- a/angel_orm_test/lib/src/models/tree.g.dart +++ /dev/null @@ -1,635 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of angel_orm_generator.test.models.tree; - -// ************************************************************************** -// MigrationGenerator -// ************************************************************************** - -class TreeMigration extends Migration { - @override - up(Schema schema) { - schema.create('trees', (table) { - table.serial('id')..primaryKey(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - table.declare('rings', ColumnType('smallint')); - }); - } - - @override - down(Schema schema) { - schema.drop('trees', cascade: true); - } -} - -class FruitMigration extends Migration { - @override - up(Schema schema) { - schema.create('fruits', (table) { - table.serial('id')..primaryKey(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - table.integer('tree_id'); - table.varChar('common_name'); - }); - } - - @override - down(Schema schema) { - schema.drop('fruits'); - } -} - -// ************************************************************************** -// OrmGenerator -// ************************************************************************** - -class TreeQuery extends Query { - TreeQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = TreeQueryWhere(this); - leftJoin(_fruits = FruitQuery(trampoline: trampoline), 'id', 'tree_id', - additionalFields: const [ - 'id', - 'created_at', - 'updated_at', - 'tree_id', - 'common_name' - ], - trampoline: trampoline); - } - - @override - final TreeQueryValues values = TreeQueryValues(); - - TreeQueryWhere _where; - - FruitQuery _fruits; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'trees'; - } - - @override - get fields { - return const ['id', 'created_at', 'updated_at', 'rings']; - } - - @override - TreeQueryWhere get where { - return _where; - } - - @override - TreeQueryWhere newWhereClause() { - return TreeQueryWhere(this); - } - - static Tree parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Tree( - id: row[0].toString(), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime), - rings: (row[3] as int)); - if (row.length > 4) { - model = model.copyWith( - fruits: [FruitQuery.parseRow(row.skip(4).take(5).toList())] - .where((x) => x != null) - .toList()); - } - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } - - FruitQuery get fruits { - return _fruits; - } - - @override - get(QueryExecutor executor) { - return super.get(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.id == model.id); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - fruits: List<_Fruit>.from(l.fruits ?? []) - ..addAll(model.fruits ?? [])); - } - }); - }); - } - - @override - update(QueryExecutor executor) { - return super.update(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.id == model.id); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - fruits: List<_Fruit>.from(l.fruits ?? []) - ..addAll(model.fruits ?? [])); - } - }); - }); - } - - @override - delete(QueryExecutor executor) { - return super.delete(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.id == model.id); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - fruits: List<_Fruit>.from(l.fruits ?? []) - ..addAll(model.fruits ?? [])); - } - }); - }); - } -} - -class TreeQueryWhere extends QueryWhere { - TreeQueryWhere(TreeQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), - rings = NumericSqlExpressionBuilder(query, 'rings'); - - final NumericSqlExpressionBuilder id; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - final NumericSqlExpressionBuilder rings; - - @override - get expressionBuilders { - return [id, createdAt, updatedAt, rings]; - } -} - -class TreeQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - int get rings { - return (values['rings'] as int); - } - - set rings(int value) => values['rings'] = value; - void copyFrom(Tree model) { - createdAt = model.createdAt; - updatedAt = model.updatedAt; - rings = model.rings; - } -} - -class FruitQuery extends Query { - FruitQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = FruitQueryWhere(this); - } - - @override - final FruitQueryValues values = FruitQueryValues(); - - FruitQueryWhere _where; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'fruits'; - } - - @override - get fields { - return const ['id', 'created_at', 'updated_at', 'tree_id', 'common_name']; - } - - @override - FruitQueryWhere get where { - return _where; - } - - @override - FruitQueryWhere newWhereClause() { - return FruitQueryWhere(this); - } - - static Fruit parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Fruit( - id: row[0].toString(), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime), - treeId: (row[3] as int), - commonName: (row[4] as String)); - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } -} - -class FruitQueryWhere extends QueryWhere { - FruitQueryWhere(FruitQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), - treeId = NumericSqlExpressionBuilder(query, 'tree_id'), - commonName = StringSqlExpressionBuilder(query, 'common_name'); - - final NumericSqlExpressionBuilder id; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - final NumericSqlExpressionBuilder treeId; - - final StringSqlExpressionBuilder commonName; - - @override - get expressionBuilders { - return [id, createdAt, updatedAt, treeId, commonName]; - } -} - -class FruitQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - int get treeId { - return (values['tree_id'] as int); - } - - set treeId(int value) => values['tree_id'] = value; - String get commonName { - return (values['common_name'] as String); - } - - set commonName(String value) => values['common_name'] = value; - void copyFrom(Fruit model) { - createdAt = model.createdAt; - updatedAt = model.updatedAt; - treeId = model.treeId; - commonName = model.commonName; - } -} - -// ************************************************************************** -// JsonModelGenerator -// ************************************************************************** - -@generatedSerializable -class Tree extends _Tree { - Tree( - {this.id, - this.createdAt, - this.updatedAt, - this.rings, - List<_Fruit> fruits}) - : this.fruits = List.unmodifiable(fruits ?? []); - - /// A unique identifier corresponding to this item. - @override - String id; - - /// The time at which this item was created. - @override - DateTime createdAt; - - /// The last time at which this item was updated. - @override - DateTime updatedAt; - - @override - int rings; - - @override - List<_Fruit> fruits; - - Tree copyWith( - {String id, - DateTime createdAt, - DateTime updatedAt, - int rings, - List<_Fruit> fruits}) { - return Tree( - id: id ?? this.id, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - rings: rings ?? this.rings, - fruits: fruits ?? this.fruits); - } - - bool operator ==(other) { - return other is _Tree && - other.id == id && - other.createdAt == createdAt && - other.updatedAt == updatedAt && - other.rings == rings && - ListEquality<_Fruit>(DefaultEquality<_Fruit>()) - .equals(other.fruits, fruits); - } - - @override - int get hashCode { - return hashObjects([id, createdAt, updatedAt, rings, fruits]); - } - - @override - String toString() { - return "Tree(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, rings=$rings, fruits=$fruits)"; - } - - Map toJson() { - return TreeSerializer.toMap(this); - } -} - -@generatedSerializable -class Fruit extends _Fruit { - Fruit( - {this.id, this.createdAt, this.updatedAt, this.treeId, this.commonName}); - - /// A unique identifier corresponding to this item. - @override - String id; - - /// The time at which this item was created. - @override - DateTime createdAt; - - /// The last time at which this item was updated. - @override - DateTime updatedAt; - - @override - int treeId; - - @override - String commonName; - - Fruit copyWith( - {String id, - DateTime createdAt, - DateTime updatedAt, - int treeId, - String commonName}) { - return Fruit( - id: id ?? this.id, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - treeId: treeId ?? this.treeId, - commonName: commonName ?? this.commonName); - } - - bool operator ==(other) { - return other is _Fruit && - other.id == id && - other.createdAt == createdAt && - other.updatedAt == updatedAt && - other.treeId == treeId && - other.commonName == commonName; - } - - @override - int get hashCode { - return hashObjects([id, createdAt, updatedAt, treeId, commonName]); - } - - @override - String toString() { - return "Fruit(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, treeId=$treeId, commonName=$commonName)"; - } - - Map toJson() { - return FruitSerializer.toMap(this); - } -} - -// ************************************************************************** -// SerializerGenerator -// ************************************************************************** - -const TreeSerializer treeSerializer = TreeSerializer(); - -class TreeEncoder extends Converter { - const TreeEncoder(); - - @override - Map convert(Tree model) => TreeSerializer.toMap(model); -} - -class TreeDecoder extends Converter { - const TreeDecoder(); - - @override - Tree convert(Map map) => TreeSerializer.fromMap(map); -} - -class TreeSerializer extends Codec { - const TreeSerializer(); - - @override - get encoder => const TreeEncoder(); - @override - get decoder => const TreeDecoder(); - static Tree fromMap(Map map) { - return Tree( - id: map['id'] as String, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null, - rings: map['rings'] as int, - fruits: map['fruits'] is Iterable - ? List.unmodifiable(((map['fruits'] as Iterable).whereType()) - .map(FruitSerializer.fromMap)) - : null); - } - - static Map toMap(_Tree model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String(), - 'rings': model.rings, - 'fruits': model.fruits?.map((m) => FruitSerializer.toMap(m))?.toList() - }; - } -} - -abstract class TreeFields { - static const List allFields = [ - id, - createdAt, - updatedAt, - rings, - fruits - ]; - - static const String id = 'id'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; - - static const String rings = 'rings'; - - static const String fruits = 'fruits'; -} - -const FruitSerializer fruitSerializer = FruitSerializer(); - -class FruitEncoder extends Converter { - const FruitEncoder(); - - @override - Map convert(Fruit model) => FruitSerializer.toMap(model); -} - -class FruitDecoder extends Converter { - const FruitDecoder(); - - @override - Fruit convert(Map map) => FruitSerializer.fromMap(map); -} - -class FruitSerializer extends Codec { - const FruitSerializer(); - - @override - get encoder => const FruitEncoder(); - @override - get decoder => const FruitDecoder(); - static Fruit fromMap(Map map) { - return Fruit( - id: map['id'] as String, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null, - treeId: map['tree_id'] as int, - commonName: map['common_name'] as String); - } - - static Map toMap(_Fruit model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String(), - 'tree_id': model.treeId, - 'common_name': model.commonName - }; - } -} - -abstract class FruitFields { - static const List allFields = [ - id, - createdAt, - updatedAt, - treeId, - commonName - ]; - - static const String id = 'id'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; - - static const String treeId = 'tree_id'; - - static const String commonName = 'common_name'; -} diff --git a/angel_orm_test/lib/src/models/unorthodox.g.dart b/angel_orm_test/lib/src/models/unorthodox.g.dart deleted file mode 100644 index 9042596c..00000000 --- a/angel_orm_test/lib/src/models/unorthodox.g.dart +++ /dev/null @@ -1,1472 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'unorthodox.dart'; - -// ************************************************************************** -// MigrationGenerator -// ************************************************************************** - -class UnorthodoxMigration extends Migration { - @override - up(Schema schema) { - schema.create('unorthodoxes', (table) { - table.varChar('name'); - }); - } - - @override - down(Schema schema) { - schema.drop('unorthodoxes'); - } -} - -class WeirdJoinMigration extends Migration { - @override - up(Schema schema) { - schema.create('weird_joins', (table) { - table.integer('id')..primaryKey(); - table - .declare('join_name', ColumnType('varchar')) - .references('unorthodoxes', 'name'); - }); - } - - @override - down(Schema schema) { - schema.drop('weird_joins', cascade: true); - } -} - -class SongMigration extends Migration { - @override - up(Schema schema) { - schema.create('songs', (table) { - table.serial('id')..primaryKey(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - table.integer('weird_join_id'); - table.varChar('title'); - }); - } - - @override - down(Schema schema) { - schema.drop('songs'); - } -} - -class NumbaMigration extends Migration { - @override - up(Schema schema) { - schema.create('numbas', (table) { - table.integer('i')..primaryKey(); - table.integer('parent'); - }); - } - - @override - down(Schema schema) { - schema.drop('numbas'); - } -} - -class FooMigration extends Migration { - @override - up(Schema schema) { - schema.create('foos', (table) { - table.varChar('bar')..primaryKey(); - }); - } - - @override - down(Schema schema) { - schema.drop('foos', cascade: true); - } -} - -class FooPivotMigration extends Migration { - @override - up(Schema schema) { - schema.create('foo_pivots', (table) { - table - .declare('weird_join_id', ColumnType('int')) - .references('weird_joins', 'id'); - table.declare('foo_bar', ColumnType('varchar')).references('foos', 'bar'); - }); - } - - @override - down(Schema schema) { - schema.drop('foo_pivots'); - } -} - -// ************************************************************************** -// OrmGenerator -// ************************************************************************** - -class UnorthodoxQuery extends Query { - UnorthodoxQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = UnorthodoxQueryWhere(this); - } - - @override - final UnorthodoxQueryValues values = UnorthodoxQueryValues(); - - UnorthodoxQueryWhere _where; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'unorthodoxes'; - } - - @override - get fields { - return const ['name']; - } - - @override - UnorthodoxQueryWhere get where { - return _where; - } - - @override - UnorthodoxQueryWhere newWhereClause() { - return UnorthodoxQueryWhere(this); - } - - static Unorthodox parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Unorthodox(name: (row[0] as String)); - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } -} - -class UnorthodoxQueryWhere extends QueryWhere { - UnorthodoxQueryWhere(UnorthodoxQuery query) - : name = StringSqlExpressionBuilder(query, 'name'); - - final StringSqlExpressionBuilder name; - - @override - get expressionBuilders { - return [name]; - } -} - -class UnorthodoxQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get name { - return (values['name'] as String); - } - - set name(String value) => values['name'] = value; - void copyFrom(Unorthodox model) { - name = model.name; - } -} - -class WeirdJoinQuery extends Query { - WeirdJoinQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = WeirdJoinQueryWhere(this); - leftJoin(_unorthodox = UnorthodoxQuery(trampoline: trampoline), 'join_name', - 'name', - additionalFields: const ['name'], trampoline: trampoline); - leftJoin(_song = SongQuery(trampoline: trampoline), 'id', 'weird_join_id', - additionalFields: const [ - 'id', - 'created_at', - 'updated_at', - 'weird_join_id', - 'title' - ], - trampoline: trampoline); - leftJoin(_numbas = NumbaQuery(trampoline: trampoline), 'id', 'parent', - additionalFields: const ['i', 'parent'], trampoline: trampoline); - leftJoin( - _foos = FooPivotQuery(trampoline: trampoline), 'id', 'weird_join_id', - additionalFields: const ['bar'], trampoline: trampoline); - } - - @override - final WeirdJoinQueryValues values = WeirdJoinQueryValues(); - - WeirdJoinQueryWhere _where; - - UnorthodoxQuery _unorthodox; - - SongQuery _song; - - NumbaQuery _numbas; - - FooPivotQuery _foos; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'weird_joins'; - } - - @override - get fields { - return const ['id', 'join_name']; - } - - @override - WeirdJoinQueryWhere get where { - return _where; - } - - @override - WeirdJoinQueryWhere newWhereClause() { - return WeirdJoinQueryWhere(this); - } - - static WeirdJoin parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = WeirdJoin(id: (row[0] as int)); - if (row.length > 2) { - model = model.copyWith( - unorthodox: UnorthodoxQuery.parseRow(row.skip(2).take(1).toList())); - } - if (row.length > 3) { - model = model.copyWith( - song: SongQuery.parseRow(row.skip(3).take(5).toList())); - } - if (row.length > 8) { - model = model.copyWith( - numbas: [NumbaQuery.parseRow(row.skip(8).take(2).toList())] - .where((x) => x != null) - .toList()); - } - if (row.length > 10) { - model = model.copyWith( - foos: [FooQuery.parseRow(row.skip(10).take(1).toList())] - .where((x) => x != null) - .toList()); - } - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } - - UnorthodoxQuery get unorthodox { - return _unorthodox; - } - - SongQuery get song { - return _song; - } - - NumbaQuery get numbas { - return _numbas; - } - - FooPivotQuery get foos { - return _foos; - } - - @override - bool canCompile(trampoline) { - return (!(trampoline.contains('weird_joins') && - trampoline.contains('foo_pivots'))); - } - - @override - get(QueryExecutor executor) { - return super.get(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.id == model.id); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - numbas: List<_Numba>.from(l.numbas ?? []) - ..addAll(model.numbas ?? []), - foos: List<_Foo>.from(l.foos ?? [])..addAll(model.foos ?? [])); - } - }); - }); - } - - @override - update(QueryExecutor executor) { - return super.update(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.id == model.id); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - numbas: List<_Numba>.from(l.numbas ?? []) - ..addAll(model.numbas ?? []), - foos: List<_Foo>.from(l.foos ?? [])..addAll(model.foos ?? [])); - } - }); - }); - } - - @override - delete(QueryExecutor executor) { - return super.delete(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.id == model.id); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - numbas: List<_Numba>.from(l.numbas ?? []) - ..addAll(model.numbas ?? []), - foos: List<_Foo>.from(l.foos ?? [])..addAll(model.foos ?? [])); - } - }); - }); - } -} - -class WeirdJoinQueryWhere extends QueryWhere { - WeirdJoinQueryWhere(WeirdJoinQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - joinName = StringSqlExpressionBuilder(query, 'join_name'); - - final NumericSqlExpressionBuilder id; - - final StringSqlExpressionBuilder joinName; - - @override - get expressionBuilders { - return [id, joinName]; - } -} - -class WeirdJoinQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - int get id { - return (values['id'] as int); - } - - set id(int value) => values['id'] = value; - String get joinName { - return (values['join_name'] as String); - } - - set joinName(String value) => values['join_name'] = value; - void copyFrom(WeirdJoin model) { - id = model.id; - if (model.unorthodox != null) { - values['join_name'] = model.unorthodox.name; - } - } -} - -class SongQuery extends Query { - SongQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = SongQueryWhere(this); - } - - @override - final SongQueryValues values = SongQueryValues(); - - SongQueryWhere _where; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'songs'; - } - - @override - get fields { - return const ['id', 'created_at', 'updated_at', 'weird_join_id', 'title']; - } - - @override - SongQueryWhere get where { - return _where; - } - - @override - SongQueryWhere newWhereClause() { - return SongQueryWhere(this); - } - - static Song parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Song( - id: row[0].toString(), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime), - weirdJoinId: (row[3] as int), - title: (row[4] as String)); - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } -} - -class SongQueryWhere extends QueryWhere { - SongQueryWhere(SongQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), - weirdJoinId = NumericSqlExpressionBuilder(query, 'weird_join_id'), - title = StringSqlExpressionBuilder(query, 'title'); - - final NumericSqlExpressionBuilder id; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - final NumericSqlExpressionBuilder weirdJoinId; - - final StringSqlExpressionBuilder title; - - @override - get expressionBuilders { - return [id, createdAt, updatedAt, weirdJoinId, title]; - } -} - -class SongQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - int get weirdJoinId { - return (values['weird_join_id'] as int); - } - - set weirdJoinId(int value) => values['weird_join_id'] = value; - String get title { - return (values['title'] as String); - } - - set title(String value) => values['title'] = value; - void copyFrom(Song model) { - createdAt = model.createdAt; - updatedAt = model.updatedAt; - weirdJoinId = model.weirdJoinId; - title = model.title; - } -} - -class NumbaQuery extends Query { - NumbaQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = NumbaQueryWhere(this); - } - - @override - final NumbaQueryValues values = NumbaQueryValues(); - - NumbaQueryWhere _where; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'numbas'; - } - - @override - get fields { - return const ['i', 'parent']; - } - - @override - NumbaQueryWhere get where { - return _where; - } - - @override - NumbaQueryWhere newWhereClause() { - return NumbaQueryWhere(this); - } - - static Numba parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Numba(i: (row[0] as int), parent: (row[1] as int)); - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } -} - -class NumbaQueryWhere extends QueryWhere { - NumbaQueryWhere(NumbaQuery query) - : i = NumericSqlExpressionBuilder(query, 'i'), - parent = NumericSqlExpressionBuilder(query, 'parent'); - - final NumericSqlExpressionBuilder i; - - final NumericSqlExpressionBuilder parent; - - @override - get expressionBuilders { - return [i, parent]; - } -} - -class NumbaQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - int get i { - return (values['i'] as int); - } - - set i(int value) => values['i'] = value; - int get parent { - return (values['parent'] as int); - } - - set parent(int value) => values['parent'] = value; - void copyFrom(Numba model) { - i = model.i; - parent = model.parent; - } -} - -class FooQuery extends Query { - FooQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = FooQueryWhere(this); - leftJoin( - _weirdJoins = FooPivotQuery(trampoline: trampoline), 'bar', 'foo_bar', - additionalFields: const ['id', 'join_name'], trampoline: trampoline); - } - - @override - final FooQueryValues values = FooQueryValues(); - - FooQueryWhere _where; - - FooPivotQuery _weirdJoins; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'foos'; - } - - @override - get fields { - return const ['bar']; - } - - @override - FooQueryWhere get where { - return _where; - } - - @override - FooQueryWhere newWhereClause() { - return FooQueryWhere(this); - } - - static Foo parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Foo(bar: (row[0] as String)); - if (row.length > 1) { - model = model.copyWith( - weirdJoins: [WeirdJoinQuery.parseRow(row.skip(1).take(2).toList())] - .where((x) => x != null) - .toList()); - } - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } - - FooPivotQuery get weirdJoins { - return _weirdJoins; - } - - @override - bool canCompile(trampoline) { - return (!(trampoline.contains('foos') && - trampoline.contains('foo_pivots'))); - } - - @override - get(QueryExecutor executor) { - return super.get(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.bar == model.bar); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - weirdJoins: List<_WeirdJoin>.from(l.weirdJoins ?? []) - ..addAll(model.weirdJoins ?? [])); - } - }); - }); - } - - @override - update(QueryExecutor executor) { - return super.update(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.bar == model.bar); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - weirdJoins: List<_WeirdJoin>.from(l.weirdJoins ?? []) - ..addAll(model.weirdJoins ?? [])); - } - }); - }); - } - - @override - delete(QueryExecutor executor) { - return super.delete(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.bar == model.bar); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - weirdJoins: List<_WeirdJoin>.from(l.weirdJoins ?? []) - ..addAll(model.weirdJoins ?? [])); - } - }); - }); - } -} - -class FooQueryWhere extends QueryWhere { - FooQueryWhere(FooQuery query) - : bar = StringSqlExpressionBuilder(query, 'bar'); - - final StringSqlExpressionBuilder bar; - - @override - get expressionBuilders { - return [bar]; - } -} - -class FooQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get bar { - return (values['bar'] as String); - } - - set bar(String value) => values['bar'] = value; - void copyFrom(Foo model) { - bar = model.bar; - } -} - -class FooPivotQuery extends Query { - FooPivotQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = FooPivotQueryWhere(this); - leftJoin(_weirdJoin = WeirdJoinQuery(trampoline: trampoline), - 'weird_join_id', 'id', - additionalFields: const ['id', 'join_name'], trampoline: trampoline); - leftJoin(_foo = FooQuery(trampoline: trampoline), 'foo_bar', 'bar', - additionalFields: const ['bar'], trampoline: trampoline); - } - - @override - final FooPivotQueryValues values = FooPivotQueryValues(); - - FooPivotQueryWhere _where; - - WeirdJoinQuery _weirdJoin; - - FooQuery _foo; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'foo_pivots'; - } - - @override - get fields { - return const ['weird_join_id', 'foo_bar']; - } - - @override - FooPivotQueryWhere get where { - return _where; - } - - @override - FooPivotQueryWhere newWhereClause() { - return FooPivotQueryWhere(this); - } - - static FooPivot parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = FooPivot(); - if (row.length > 2) { - model = model.copyWith( - weirdJoin: WeirdJoinQuery.parseRow(row.skip(2).take(2).toList())); - } - if (row.length > 4) { - model = - model.copyWith(foo: FooQuery.parseRow(row.skip(4).take(1).toList())); - } - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } - - WeirdJoinQuery get weirdJoin { - return _weirdJoin; - } - - FooQuery get foo { - return _foo; - } -} - -class FooPivotQueryWhere extends QueryWhere { - FooPivotQueryWhere(FooPivotQuery query) - : weirdJoinId = NumericSqlExpressionBuilder(query, 'weird_join_id'), - fooBar = StringSqlExpressionBuilder(query, 'foo_bar'); - - final NumericSqlExpressionBuilder weirdJoinId; - - final StringSqlExpressionBuilder fooBar; - - @override - get expressionBuilders { - return [weirdJoinId, fooBar]; - } -} - -class FooPivotQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - int get weirdJoinId { - return (values['weird_join_id'] as int); - } - - set weirdJoinId(int value) => values['weird_join_id'] = value; - String get fooBar { - return (values['foo_bar'] as String); - } - - set fooBar(String value) => values['foo_bar'] = value; - void copyFrom(FooPivot model) { - if (model.weirdJoin != null) { - values['weird_join_id'] = model.weirdJoin.id; - } - if (model.foo != null) { - values['foo_bar'] = model.foo.bar; - } - } -} - -// ************************************************************************** -// JsonModelGenerator -// ************************************************************************** - -@generatedSerializable -class Unorthodox implements _Unorthodox { - const Unorthodox({this.name}); - - @override - final String name; - - Unorthodox copyWith({String name}) { - return Unorthodox(name: name ?? this.name); - } - - bool operator ==(other) { - return other is _Unorthodox && other.name == name; - } - - @override - int get hashCode { - return hashObjects([name]); - } - - @override - String toString() { - return "Unorthodox(name=$name)"; - } - - Map toJson() { - return UnorthodoxSerializer.toMap(this); - } -} - -@generatedSerializable -class WeirdJoin implements _WeirdJoin { - const WeirdJoin( - {this.id, this.unorthodox, this.song, this.numbas, this.foos}); - - @override - final int id; - - @override - final _Unorthodox unorthodox; - - @override - final _Song song; - - @override - final List<_Numba> numbas; - - @override - final List<_Foo> foos; - - WeirdJoin copyWith( - {int id, - _Unorthodox unorthodox, - _Song song, - List<_Numba> numbas, - List<_Foo> foos}) { - return WeirdJoin( - id: id ?? this.id, - unorthodox: unorthodox ?? this.unorthodox, - song: song ?? this.song, - numbas: numbas ?? this.numbas, - foos: foos ?? this.foos); - } - - bool operator ==(other) { - return other is _WeirdJoin && - other.id == id && - other.unorthodox == unorthodox && - other.song == song && - ListEquality<_Numba>(DefaultEquality<_Numba>()) - .equals(other.numbas, numbas) && - ListEquality<_Foo>(DefaultEquality<_Foo>()).equals(other.foos, foos); - } - - @override - int get hashCode { - return hashObjects([id, unorthodox, song, numbas, foos]); - } - - @override - String toString() { - return "WeirdJoin(id=$id, unorthodox=$unorthodox, song=$song, numbas=$numbas, foos=$foos)"; - } - - Map toJson() { - return WeirdJoinSerializer.toMap(this); - } -} - -@generatedSerializable -class Song extends _Song { - Song({this.id, this.createdAt, this.updatedAt, this.weirdJoinId, this.title}); - - /// A unique identifier corresponding to this item. - @override - String id; - - /// The time at which this item was created. - @override - DateTime createdAt; - - /// The last time at which this item was updated. - @override - DateTime updatedAt; - - @override - final int weirdJoinId; - - @override - final String title; - - Song copyWith( - {String id, - DateTime createdAt, - DateTime updatedAt, - int weirdJoinId, - String title}) { - return Song( - id: id ?? this.id, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - weirdJoinId: weirdJoinId ?? this.weirdJoinId, - title: title ?? this.title); - } - - bool operator ==(other) { - return other is _Song && - other.id == id && - other.createdAt == createdAt && - other.updatedAt == updatedAt && - other.weirdJoinId == weirdJoinId && - other.title == title; - } - - @override - int get hashCode { - return hashObjects([id, createdAt, updatedAt, weirdJoinId, title]); - } - - @override - String toString() { - return "Song(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, weirdJoinId=$weirdJoinId, title=$title)"; - } - - Map toJson() { - return SongSerializer.toMap(this); - } -} - -@generatedSerializable -class Numba extends _Numba { - Numba({this.i, this.parent}); - - @override - int i; - - @override - int parent; - - Numba copyWith({int i, int parent}) { - return Numba(i: i ?? this.i, parent: parent ?? this.parent); - } - - bool operator ==(other) { - return other is _Numba && other.i == i && other.parent == parent; - } - - @override - int get hashCode { - return hashObjects([i, parent]); - } - - @override - String toString() { - return "Numba(i=$i, parent=$parent)"; - } - - Map toJson() { - return NumbaSerializer.toMap(this); - } -} - -@generatedSerializable -class Foo implements _Foo { - const Foo({this.bar, this.weirdJoins}); - - @override - final String bar; - - @override - final List<_WeirdJoin> weirdJoins; - - Foo copyWith({String bar, List<_WeirdJoin> weirdJoins}) { - return Foo(bar: bar ?? this.bar, weirdJoins: weirdJoins ?? this.weirdJoins); - } - - bool operator ==(other) { - return other is _Foo && - other.bar == bar && - ListEquality<_WeirdJoin>(DefaultEquality<_WeirdJoin>()) - .equals(other.weirdJoins, weirdJoins); - } - - @override - int get hashCode { - return hashObjects([bar, weirdJoins]); - } - - @override - String toString() { - return "Foo(bar=$bar, weirdJoins=$weirdJoins)"; - } - - Map toJson() { - return FooSerializer.toMap(this); - } -} - -@generatedSerializable -class FooPivot implements _FooPivot { - const FooPivot({this.weirdJoin, this.foo}); - - @override - final _WeirdJoin weirdJoin; - - @override - final _Foo foo; - - FooPivot copyWith({_WeirdJoin weirdJoin, _Foo foo}) { - return FooPivot( - weirdJoin: weirdJoin ?? this.weirdJoin, foo: foo ?? this.foo); - } - - bool operator ==(other) { - return other is _FooPivot && - other.weirdJoin == weirdJoin && - other.foo == foo; - } - - @override - int get hashCode { - return hashObjects([weirdJoin, foo]); - } - - @override - String toString() { - return "FooPivot(weirdJoin=$weirdJoin, foo=$foo)"; - } - - Map toJson() { - return FooPivotSerializer.toMap(this); - } -} - -// ************************************************************************** -// SerializerGenerator -// ************************************************************************** - -const UnorthodoxSerializer unorthodoxSerializer = UnorthodoxSerializer(); - -class UnorthodoxEncoder extends Converter { - const UnorthodoxEncoder(); - - @override - Map convert(Unorthodox model) => UnorthodoxSerializer.toMap(model); -} - -class UnorthodoxDecoder extends Converter { - const UnorthodoxDecoder(); - - @override - Unorthodox convert(Map map) => UnorthodoxSerializer.fromMap(map); -} - -class UnorthodoxSerializer extends Codec { - const UnorthodoxSerializer(); - - @override - get encoder => const UnorthodoxEncoder(); - @override - get decoder => const UnorthodoxDecoder(); - static Unorthodox fromMap(Map map) { - return Unorthodox(name: map['name'] as String); - } - - static Map toMap(_Unorthodox model) { - if (model == null) { - return null; - } - return {'name': model.name}; - } -} - -abstract class UnorthodoxFields { - static const List allFields = [name]; - - static const String name = 'name'; -} - -const WeirdJoinSerializer weirdJoinSerializer = WeirdJoinSerializer(); - -class WeirdJoinEncoder extends Converter { - const WeirdJoinEncoder(); - - @override - Map convert(WeirdJoin model) => WeirdJoinSerializer.toMap(model); -} - -class WeirdJoinDecoder extends Converter { - const WeirdJoinDecoder(); - - @override - WeirdJoin convert(Map map) => WeirdJoinSerializer.fromMap(map); -} - -class WeirdJoinSerializer extends Codec { - const WeirdJoinSerializer(); - - @override - get encoder => const WeirdJoinEncoder(); - @override - get decoder => const WeirdJoinDecoder(); - static WeirdJoin fromMap(Map map) { - return WeirdJoin( - id: map['id'] as int, - unorthodox: map['unorthodox'] != null - ? UnorthodoxSerializer.fromMap(map['unorthodox'] as Map) - : null, - song: map['song'] != null - ? SongSerializer.fromMap(map['song'] as Map) - : null, - numbas: map['numbas'] is Iterable - ? List.unmodifiable(((map['numbas'] as Iterable).whereType()) - .map(NumbaSerializer.fromMap)) - : null, - foos: map['foos'] is Iterable - ? List.unmodifiable(((map['foos'] as Iterable).whereType()) - .map(FooSerializer.fromMap)) - : null); - } - - static Map toMap(_WeirdJoin model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'unorthodox': UnorthodoxSerializer.toMap(model.unorthodox), - 'song': SongSerializer.toMap(model.song), - 'numbas': model.numbas?.map((m) => NumbaSerializer.toMap(m))?.toList(), - 'foos': model.foos?.map((m) => FooSerializer.toMap(m))?.toList() - }; - } -} - -abstract class WeirdJoinFields { - static const List allFields = [ - id, - unorthodox, - song, - numbas, - foos - ]; - - static const String id = 'id'; - - static const String unorthodox = 'unorthodox'; - - static const String song = 'song'; - - static const String numbas = 'numbas'; - - static const String foos = 'foos'; -} - -const SongSerializer songSerializer = SongSerializer(); - -class SongEncoder extends Converter { - const SongEncoder(); - - @override - Map convert(Song model) => SongSerializer.toMap(model); -} - -class SongDecoder extends Converter { - const SongDecoder(); - - @override - Song convert(Map map) => SongSerializer.fromMap(map); -} - -class SongSerializer extends Codec { - const SongSerializer(); - - @override - get encoder => const SongEncoder(); - @override - get decoder => const SongDecoder(); - static Song fromMap(Map map) { - return Song( - id: map['id'] as String, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null, - weirdJoinId: map['weird_join_id'] as int, - title: map['title'] as String); - } - - static Map toMap(_Song model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String(), - 'weird_join_id': model.weirdJoinId, - 'title': model.title - }; - } -} - -abstract class SongFields { - static const List allFields = [ - id, - createdAt, - updatedAt, - weirdJoinId, - title - ]; - - static const String id = 'id'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; - - static const String weirdJoinId = 'weird_join_id'; - - static const String title = 'title'; -} - -const NumbaSerializer numbaSerializer = NumbaSerializer(); - -class NumbaEncoder extends Converter { - const NumbaEncoder(); - - @override - Map convert(Numba model) => NumbaSerializer.toMap(model); -} - -class NumbaDecoder extends Converter { - const NumbaDecoder(); - - @override - Numba convert(Map map) => NumbaSerializer.fromMap(map); -} - -class NumbaSerializer extends Codec { - const NumbaSerializer(); - - @override - get encoder => const NumbaEncoder(); - @override - get decoder => const NumbaDecoder(); - static Numba fromMap(Map map) { - return Numba(i: map['i'] as int, parent: map['parent'] as int); - } - - static Map toMap(_Numba model) { - if (model == null) { - return null; - } - return {'i': model.i, 'parent': model.parent}; - } -} - -abstract class NumbaFields { - static const List allFields = [i, parent]; - - static const String i = 'i'; - - static const String parent = 'parent'; -} - -const FooSerializer fooSerializer = FooSerializer(); - -class FooEncoder extends Converter { - const FooEncoder(); - - @override - Map convert(Foo model) => FooSerializer.toMap(model); -} - -class FooDecoder extends Converter { - const FooDecoder(); - - @override - Foo convert(Map map) => FooSerializer.fromMap(map); -} - -class FooSerializer extends Codec { - const FooSerializer(); - - @override - get encoder => const FooEncoder(); - @override - get decoder => const FooDecoder(); - static Foo fromMap(Map map) { - return Foo( - bar: map['bar'] as String, - weirdJoins: map['weird_joins'] is Iterable - ? List.unmodifiable( - ((map['weird_joins'] as Iterable).whereType()) - .map(WeirdJoinSerializer.fromMap)) - : null); - } - - static Map toMap(_Foo model) { - if (model == null) { - return null; - } - return { - 'bar': model.bar, - 'weird_joins': - model.weirdJoins?.map((m) => WeirdJoinSerializer.toMap(m))?.toList() - }; - } -} - -abstract class FooFields { - static const List allFields = [bar, weirdJoins]; - - static const String bar = 'bar'; - - static const String weirdJoins = 'weird_joins'; -} - -const FooPivotSerializer fooPivotSerializer = FooPivotSerializer(); - -class FooPivotEncoder extends Converter { - const FooPivotEncoder(); - - @override - Map convert(FooPivot model) => FooPivotSerializer.toMap(model); -} - -class FooPivotDecoder extends Converter { - const FooPivotDecoder(); - - @override - FooPivot convert(Map map) => FooPivotSerializer.fromMap(map); -} - -class FooPivotSerializer extends Codec { - const FooPivotSerializer(); - - @override - get encoder => const FooPivotEncoder(); - @override - get decoder => const FooPivotDecoder(); - static FooPivot fromMap(Map map) { - return FooPivot( - weirdJoin: map['weird_join'] != null - ? WeirdJoinSerializer.fromMap(map['weird_join'] as Map) - : null, - foo: map['foo'] != null - ? FooSerializer.fromMap(map['foo'] as Map) - : null); - } - - static Map toMap(_FooPivot model) { - if (model == null) { - return null; - } - return { - 'weird_join': WeirdJoinSerializer.toMap(model.weirdJoin), - 'foo': FooSerializer.toMap(model.foo) - }; - } -} - -abstract class FooPivotFields { - static const List allFields = [weirdJoin, foo]; - - static const String weirdJoin = 'weird_join'; - - static const String foo = 'foo'; -} diff --git a/angel_orm_test/lib/src/models/user.g.dart b/angel_orm_test/lib/src/models/user.g.dart deleted file mode 100644 index c5fd1239..00000000 --- a/angel_orm_test/lib/src/models/user.g.dart +++ /dev/null @@ -1,990 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of angel_orm_generator.test.models.user; - -// ************************************************************************** -// MigrationGenerator -// ************************************************************************** - -class UserMigration extends Migration { - @override - up(Schema schema) { - schema.create('users', (table) { - table.serial('id')..primaryKey(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - table.varChar('username'); - table.varChar('password'); - table.varChar('email'); - }); - } - - @override - down(Schema schema) { - schema.drop('users', cascade: true); - } -} - -class RoleUserMigration extends Migration { - @override - up(Schema schema) { - schema.create('role_users', (table) { - table.declare('role_id', ColumnType('serial')).references('roles', 'id'); - table.declare('user_id', ColumnType('serial')).references('users', 'id'); - }); - } - - @override - down(Schema schema) { - schema.drop('role_users'); - } -} - -class RoleMigration extends Migration { - @override - up(Schema schema) { - schema.create('roles', (table) { - table.serial('id')..primaryKey(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - table.varChar('name'); - }); - } - - @override - down(Schema schema) { - schema.drop('roles', cascade: true); - } -} - -// ************************************************************************** -// OrmGenerator -// ************************************************************************** - -class UserQuery extends Query { - UserQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = UserQueryWhere(this); - leftJoin(_roles = RoleUserQuery(trampoline: trampoline), 'id', 'user_id', - additionalFields: const ['id', 'created_at', 'updated_at', 'name'], - trampoline: trampoline); - } - - @override - final UserQueryValues values = UserQueryValues(); - - UserQueryWhere _where; - - RoleUserQuery _roles; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'users'; - } - - @override - get fields { - return const [ - 'id', - 'created_at', - 'updated_at', - 'username', - 'password', - 'email' - ]; - } - - @override - UserQueryWhere get where { - return _where; - } - - @override - UserQueryWhere newWhereClause() { - return UserQueryWhere(this); - } - - static User parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = User( - id: row[0].toString(), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime), - username: (row[3] as String), - password: (row[4] as String), - email: (row[5] as String)); - if (row.length > 6) { - model = model.copyWith( - roles: [RoleQuery.parseRow(row.skip(6).take(4).toList())] - .where((x) => x != null) - .toList()); - } - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } - - RoleUserQuery get roles { - return _roles; - } - - @override - bool canCompile(trampoline) { - return (!(trampoline.contains('users') && - trampoline.contains('role_users'))); - } - - @override - get(QueryExecutor executor) { - return super.get(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.id == model.id); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - roles: List<_Role>.from(l.roles ?? []) - ..addAll(model.roles ?? [])); - } - }); - }); - } - - @override - update(QueryExecutor executor) { - return super.update(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.id == model.id); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - roles: List<_Role>.from(l.roles ?? []) - ..addAll(model.roles ?? [])); - } - }); - }); - } - - @override - delete(QueryExecutor executor) { - return super.delete(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.id == model.id); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - roles: List<_Role>.from(l.roles ?? []) - ..addAll(model.roles ?? [])); - } - }); - }); - } -} - -class UserQueryWhere extends QueryWhere { - UserQueryWhere(UserQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), - username = StringSqlExpressionBuilder(query, 'username'), - password = StringSqlExpressionBuilder(query, 'password'), - email = StringSqlExpressionBuilder(query, 'email'); - - final NumericSqlExpressionBuilder id; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - final StringSqlExpressionBuilder username; - - final StringSqlExpressionBuilder password; - - final StringSqlExpressionBuilder email; - - @override - get expressionBuilders { - return [id, createdAt, updatedAt, username, password, email]; - } -} - -class UserQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - String get username { - return (values['username'] as String); - } - - set username(String value) => values['username'] = value; - String get password { - return (values['password'] as String); - } - - set password(String value) => values['password'] = value; - String get email { - return (values['email'] as String); - } - - set email(String value) => values['email'] = value; - void copyFrom(User model) { - createdAt = model.createdAt; - updatedAt = model.updatedAt; - username = model.username; - password = model.password; - email = model.email; - } -} - -class RoleUserQuery extends Query { - RoleUserQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = RoleUserQueryWhere(this); - leftJoin(_role = RoleQuery(trampoline: trampoline), 'role_id', 'id', - additionalFields: const ['id', 'created_at', 'updated_at', 'name'], - trampoline: trampoline); - leftJoin(_user = UserQuery(trampoline: trampoline), 'user_id', 'id', - additionalFields: const [ - 'id', - 'created_at', - 'updated_at', - 'username', - 'password', - 'email' - ], - trampoline: trampoline); - } - - @override - final RoleUserQueryValues values = RoleUserQueryValues(); - - RoleUserQueryWhere _where; - - RoleQuery _role; - - UserQuery _user; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'role_users'; - } - - @override - get fields { - return const ['role_id', 'user_id']; - } - - @override - RoleUserQueryWhere get where { - return _where; - } - - @override - RoleUserQueryWhere newWhereClause() { - return RoleUserQueryWhere(this); - } - - static RoleUser parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = RoleUser(); - if (row.length > 2) { - model = model.copyWith( - role: RoleQuery.parseRow(row.skip(2).take(4).toList())); - } - if (row.length > 6) { - model = model.copyWith( - user: UserQuery.parseRow(row.skip(6).take(6).toList())); - } - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } - - RoleQuery get role { - return _role; - } - - UserQuery get user { - return _user; - } -} - -class RoleUserQueryWhere extends QueryWhere { - RoleUserQueryWhere(RoleUserQuery query) - : roleId = NumericSqlExpressionBuilder(query, 'role_id'), - userId = NumericSqlExpressionBuilder(query, 'user_id'); - - final NumericSqlExpressionBuilder roleId; - - final NumericSqlExpressionBuilder userId; - - @override - get expressionBuilders { - return [roleId, userId]; - } -} - -class RoleUserQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - int get roleId { - return (values['role_id'] as int); - } - - set roleId(int value) => values['role_id'] = value; - int get userId { - return (values['user_id'] as int); - } - - set userId(int value) => values['user_id'] = value; - void copyFrom(RoleUser model) { - if (model.role != null) { - values['role_id'] = model.role.id; - } - if (model.user != null) { - values['user_id'] = model.user.id; - } - } -} - -class RoleQuery extends Query { - RoleQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = RoleQueryWhere(this); - leftJoin(_users = RoleUserQuery(trampoline: trampoline), 'id', 'role_id', - additionalFields: const [ - 'id', - 'created_at', - 'updated_at', - 'username', - 'password', - 'email' - ], - trampoline: trampoline); - } - - @override - final RoleQueryValues values = RoleQueryValues(); - - RoleQueryWhere _where; - - RoleUserQuery _users; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'roles'; - } - - @override - get fields { - return const ['id', 'created_at', 'updated_at', 'name']; - } - - @override - RoleQueryWhere get where { - return _where; - } - - @override - RoleQueryWhere newWhereClause() { - return RoleQueryWhere(this); - } - - static Role parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Role( - id: row[0].toString(), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime), - name: (row[3] as String)); - if (row.length > 4) { - model = model.copyWith( - users: [UserQuery.parseRow(row.skip(4).take(6).toList())] - .where((x) => x != null) - .toList()); - } - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } - - RoleUserQuery get users { - return _users; - } - - @override - bool canCompile(trampoline) { - return (!(trampoline.contains('roles') && - trampoline.contains('role_users'))); - } - - @override - get(QueryExecutor executor) { - return super.get(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.id == model.id); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - users: List<_User>.from(l.users ?? []) - ..addAll(model.users ?? [])); - } - }); - }); - } - - @override - update(QueryExecutor executor) { - return super.update(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.id == model.id); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - users: List<_User>.from(l.users ?? []) - ..addAll(model.users ?? [])); - } - }); - }); - } - - @override - delete(QueryExecutor executor) { - return super.delete(executor).then((result) { - return result.fold>([], (out, model) { - var idx = out.indexWhere((m) => m.id == model.id); - - if (idx == -1) { - return out..add(model); - } else { - var l = out[idx]; - return out - ..[idx] = l.copyWith( - users: List<_User>.from(l.users ?? []) - ..addAll(model.users ?? [])); - } - }); - }); - } -} - -class RoleQueryWhere extends QueryWhere { - RoleQueryWhere(RoleQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), - name = StringSqlExpressionBuilder(query, 'name'); - - final NumericSqlExpressionBuilder id; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - final StringSqlExpressionBuilder name; - - @override - get expressionBuilders { - return [id, createdAt, updatedAt, name]; - } -} - -class RoleQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - String get name { - return (values['name'] as String); - } - - set name(String value) => values['name'] = value; - void copyFrom(Role model) { - createdAt = model.createdAt; - updatedAt = model.updatedAt; - name = model.name; - } -} - -// ************************************************************************** -// JsonModelGenerator -// ************************************************************************** - -@generatedSerializable -class User extends _User { - User( - {this.id, - this.createdAt, - this.updatedAt, - this.username, - this.password, - this.email, - List<_Role> roles}) - : this.roles = List.unmodifiable(roles ?? []); - - /// A unique identifier corresponding to this item. - @override - String id; - - /// The time at which this item was created. - @override - DateTime createdAt; - - /// The last time at which this item was updated. - @override - DateTime updatedAt; - - @override - final String username; - - @override - final String password; - - @override - final String email; - - @override - final List<_Role> roles; - - User copyWith( - {String id, - DateTime createdAt, - DateTime updatedAt, - String username, - String password, - String email, - List<_Role> roles}) { - return User( - id: id ?? this.id, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - username: username ?? this.username, - password: password ?? this.password, - email: email ?? this.email, - roles: roles ?? this.roles); - } - - bool operator ==(other) { - return other is _User && - other.id == id && - other.createdAt == createdAt && - other.updatedAt == updatedAt && - other.username == username && - other.password == password && - other.email == email && - ListEquality<_Role>(DefaultEquality<_Role>()) - .equals(other.roles, roles); - } - - @override - int get hashCode { - return hashObjects( - [id, createdAt, updatedAt, username, password, email, roles]); - } - - @override - String toString() { - return "User(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, username=$username, password=$password, email=$email, roles=$roles)"; - } - - Map toJson() { - return UserSerializer.toMap(this); - } -} - -@generatedSerializable -class RoleUser implements _RoleUser { - const RoleUser({this.role, this.user}); - - @override - final _Role role; - - @override - final _User user; - - RoleUser copyWith({_Role role, _User user}) { - return RoleUser(role: role ?? this.role, user: user ?? this.user); - } - - bool operator ==(other) { - return other is _RoleUser && other.role == role && other.user == user; - } - - @override - int get hashCode { - return hashObjects([role, user]); - } - - @override - String toString() { - return "RoleUser(role=$role, user=$user)"; - } - - Map toJson() { - return RoleUserSerializer.toMap(this); - } -} - -@generatedSerializable -class Role extends _Role { - Role({this.id, this.createdAt, this.updatedAt, this.name, List<_User> users}) - : this.users = List.unmodifiable(users ?? []); - - /// A unique identifier corresponding to this item. - @override - String id; - - /// The time at which this item was created. - @override - DateTime createdAt; - - /// The last time at which this item was updated. - @override - DateTime updatedAt; - - @override - String name; - - @override - final List<_User> users; - - Role copyWith( - {String id, - DateTime createdAt, - DateTime updatedAt, - String name, - List<_User> users}) { - return Role( - id: id ?? this.id, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - name: name ?? this.name, - users: users ?? this.users); - } - - bool operator ==(other) { - return other is _Role && - other.id == id && - other.createdAt == createdAt && - other.updatedAt == updatedAt && - other.name == name && - ListEquality<_User>(DefaultEquality<_User>()) - .equals(other.users, users); - } - - @override - int get hashCode { - return hashObjects([id, createdAt, updatedAt, name, users]); - } - - @override - String toString() { - return "Role(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, name=$name, users=$users)"; - } - - Map toJson() { - return RoleSerializer.toMap(this); - } -} - -// ************************************************************************** -// SerializerGenerator -// ************************************************************************** - -const UserSerializer userSerializer = UserSerializer(); - -class UserEncoder extends Converter { - const UserEncoder(); - - @override - Map convert(User model) => UserSerializer.toMap(model); -} - -class UserDecoder extends Converter { - const UserDecoder(); - - @override - User convert(Map map) => UserSerializer.fromMap(map); -} - -class UserSerializer extends Codec { - const UserSerializer(); - - @override - get encoder => const UserEncoder(); - @override - get decoder => const UserDecoder(); - static User fromMap(Map map) { - return User( - id: map['id'] as String, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null, - username: map['username'] as String, - password: map['password'] as String, - email: map['email'] as String, - roles: map['roles'] is Iterable - ? List.unmodifiable(((map['roles'] as Iterable).whereType()) - .map(RoleSerializer.fromMap)) - : null); - } - - static Map toMap(_User model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String(), - 'username': model.username, - 'password': model.password, - 'email': model.email, - 'roles': model.roles?.map((m) => RoleSerializer.toMap(m))?.toList() - }; - } -} - -abstract class UserFields { - static const List allFields = [ - id, - createdAt, - updatedAt, - username, - password, - email, - roles - ]; - - static const String id = 'id'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; - - static const String username = 'username'; - - static const String password = 'password'; - - static const String email = 'email'; - - static const String roles = 'roles'; -} - -const RoleUserSerializer roleUserSerializer = RoleUserSerializer(); - -class RoleUserEncoder extends Converter { - const RoleUserEncoder(); - - @override - Map convert(RoleUser model) => RoleUserSerializer.toMap(model); -} - -class RoleUserDecoder extends Converter { - const RoleUserDecoder(); - - @override - RoleUser convert(Map map) => RoleUserSerializer.fromMap(map); -} - -class RoleUserSerializer extends Codec { - const RoleUserSerializer(); - - @override - get encoder => const RoleUserEncoder(); - @override - get decoder => const RoleUserDecoder(); - static RoleUser fromMap(Map map) { - return RoleUser( - role: map['role'] != null - ? RoleSerializer.fromMap(map['role'] as Map) - : null, - user: map['user'] != null - ? UserSerializer.fromMap(map['user'] as Map) - : null); - } - - static Map toMap(_RoleUser model) { - if (model == null) { - return null; - } - return { - 'role': RoleSerializer.toMap(model.role), - 'user': UserSerializer.toMap(model.user) - }; - } -} - -abstract class RoleUserFields { - static const List allFields = [role, user]; - - static const String role = 'role'; - - static const String user = 'user'; -} - -const RoleSerializer roleSerializer = RoleSerializer(); - -class RoleEncoder extends Converter { - const RoleEncoder(); - - @override - Map convert(Role model) => RoleSerializer.toMap(model); -} - -class RoleDecoder extends Converter { - const RoleDecoder(); - - @override - Role convert(Map map) => RoleSerializer.fromMap(map); -} - -class RoleSerializer extends Codec { - const RoleSerializer(); - - @override - get encoder => const RoleEncoder(); - @override - get decoder => const RoleDecoder(); - static Role fromMap(Map map) { - return Role( - id: map['id'] as String, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null, - name: map['name'] as String, - users: map['users'] is Iterable - ? List.unmodifiable(((map['users'] as Iterable).whereType()) - .map(UserSerializer.fromMap)) - : null); - } - - static Map toMap(_Role model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String(), - 'name': model.name, - 'users': model.users?.map((m) => UserSerializer.toMap(m))?.toList() - }; - } -} - -abstract class RoleFields { - static const List allFields = [ - id, - createdAt, - updatedAt, - name, - users - ]; - - static const String id = 'id'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; - - static const String name = 'name'; - - static const String users = 'users'; -} From 44abb49dd86b3c9f11ccbdecd194234e26c00c63 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 10:55:18 -0400 Subject: [PATCH 31/44] Pass parent in constructor --- .../lib/src/orm_generator.dart | 1 + angel_orm_test/lib/src/models/book.g.dart | 606 +++++++ angel_orm_test/lib/src/models/car.g.dart | 367 ++++ .../lib/src/models/email_indexed.g.dart | 798 +++++++++ angel_orm_test/lib/src/models/has_car.g.dart | 275 +++ angel_orm_test/lib/src/models/has_map.g.dart | 208 +++ angel_orm_test/lib/src/models/leg.g.dart | 568 +++++++ angel_orm_test/lib/src/models/order.g.dart | 598 +++++++ angel_orm_test/lib/src/models/tree.g.dart | 636 +++++++ .../lib/src/models/unorthodox.g.dart | 1481 +++++++++++++++++ angel_orm_test/lib/src/models/user.g.dart | 995 +++++++++++ 11 files changed, 6533 insertions(+) create mode 100644 angel_orm_test/lib/src/models/book.g.dart create mode 100644 angel_orm_test/lib/src/models/car.g.dart create mode 100644 angel_orm_test/lib/src/models/email_indexed.g.dart create mode 100644 angel_orm_test/lib/src/models/has_car.g.dart create mode 100644 angel_orm_test/lib/src/models/has_map.g.dart create mode 100644 angel_orm_test/lib/src/models/leg.g.dart create mode 100644 angel_orm_test/lib/src/models/order.g.dart create mode 100644 angel_orm_test/lib/src/models/tree.g.dart create mode 100644 angel_orm_test/lib/src/models/unorthodox.g.dart create mode 100644 angel_orm_test/lib/src/models/user.g.dart diff --git a/angel_orm_generator/lib/src/orm_generator.dart b/angel_orm_generator/lib/src/orm_generator.dart index a501698f..87096780 100644 --- a/angel_orm_generator/lib/src/orm_generator.dart +++ b/angel_orm_generator/lib/src/orm_generator.dart @@ -268,6 +268,7 @@ class OrmGenerator extends GeneratorForAnnotation { ..type = TypeReference((b) => b ..symbol = 'Set' ..types.add(refer('String'))))) + ..initializers.add(Code('super(parent: parent)')) ..body = Block((b) { b.statements.addAll([ Code('trampoline ??= Set();'), diff --git a/angel_orm_test/lib/src/models/book.g.dart b/angel_orm_test/lib/src/models/book.g.dart new file mode 100644 index 00000000..b72cdd3f --- /dev/null +++ b/angel_orm_test/lib/src/models/book.g.dart @@ -0,0 +1,606 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of angel_orm.generator.models.book; + +// ************************************************************************** +// MigrationGenerator +// ************************************************************************** + +class BookMigration extends Migration { + @override + up(Schema schema) { + schema.create('books', (table) { + table.serial('id')..primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.varChar('name'); + table + .declare('author_id', ColumnType('serial')) + .references('authors', 'id'); + table + .declare('partner_author_id', ColumnType('serial')) + .references('authors', 'id'); + }); + } + + @override + down(Schema schema) { + schema.drop('books'); + } +} + +class AuthorMigration extends Migration { + @override + up(Schema schema) { + schema.create('authors', (table) { + table.serial('id')..primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.varChar('name', length: 255)..defaultsTo('Tobe Osakwe'); + }); + } + + @override + down(Schema schema) { + schema.drop('authors'); + } +} + +// ************************************************************************** +// OrmGenerator +// ************************************************************************** + +class BookQuery extends Query { + BookQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = BookQueryWhere(this); + leftJoin(_author = AuthorQuery(trampoline: trampoline, parent: this), + 'author_id', 'id', + additionalFields: const ['id', 'created_at', 'updated_at', 'name'], + trampoline: trampoline); + leftJoin(_partnerAuthor = AuthorQuery(trampoline: trampoline, parent: this), + 'partner_author_id', 'id', + additionalFields: const ['id', 'created_at', 'updated_at', 'name'], + trampoline: trampoline); + } + + @override + final BookQueryValues values = BookQueryValues(); + + BookQueryWhere _where; + + AuthorQuery _author; + + AuthorQuery _partnerAuthor; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'books'; + } + + @override + get fields { + return const [ + 'id', + 'created_at', + 'updated_at', + 'author_id', + 'partner_author_id', + 'name' + ]; + } + + @override + BookQueryWhere get where { + return _where; + } + + @override + BookQueryWhere newWhereClause() { + return BookQueryWhere(this); + } + + static Book parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Book( + id: row[0].toString(), + createdAt: (row[1] as DateTime), + updatedAt: (row[2] as DateTime), + name: (row[5] as String)); + if (row.length > 6) { + model = model.copyWith( + author: AuthorQuery.parseRow(row.skip(6).take(4).toList())); + } + if (row.length > 10) { + model = model.copyWith( + partnerAuthor: AuthorQuery.parseRow(row.skip(10).take(4).toList())); + } + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } + + AuthorQuery get author { + return _author; + } + + AuthorQuery get partnerAuthor { + return _partnerAuthor; + } +} + +class BookQueryWhere extends QueryWhere { + BookQueryWhere(BookQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), + authorId = NumericSqlExpressionBuilder(query, 'author_id'), + partnerAuthorId = + NumericSqlExpressionBuilder(query, 'partner_author_id'), + name = StringSqlExpressionBuilder(query, 'name'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final NumericSqlExpressionBuilder authorId; + + final NumericSqlExpressionBuilder partnerAuthorId; + + final StringSqlExpressionBuilder name; + + @override + get expressionBuilders { + return [id, createdAt, updatedAt, authorId, partnerAuthorId, name]; + } +} + +class BookQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + int get authorId { + return (values['author_id'] as int); + } + + set authorId(int value) => values['author_id'] = value; + int get partnerAuthorId { + return (values['partner_author_id'] as int); + } + + set partnerAuthorId(int value) => values['partner_author_id'] = value; + String get name { + return (values['name'] as String); + } + + set name(String value) => values['name'] = value; + void copyFrom(Book model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + name = model.name; + if (model.author != null) { + values['author_id'] = model.author.id; + } + if (model.partnerAuthor != null) { + values['partner_author_id'] = model.partnerAuthor.id; + } + } +} + +class AuthorQuery extends Query { + AuthorQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = AuthorQueryWhere(this); + } + + @override + final AuthorQueryValues values = AuthorQueryValues(); + + AuthorQueryWhere _where; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'authors'; + } + + @override + get fields { + return const ['id', 'created_at', 'updated_at', 'name']; + } + + @override + AuthorQueryWhere get where { + return _where; + } + + @override + AuthorQueryWhere newWhereClause() { + return AuthorQueryWhere(this); + } + + static Author parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Author( + id: row[0].toString(), + createdAt: (row[1] as DateTime), + updatedAt: (row[2] as DateTime), + name: (row[3] as String)); + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } +} + +class AuthorQueryWhere extends QueryWhere { + AuthorQueryWhere(AuthorQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), + name = StringSqlExpressionBuilder(query, 'name'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final StringSqlExpressionBuilder name; + + @override + get expressionBuilders { + return [id, createdAt, updatedAt, name]; + } +} + +class AuthorQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + String get name { + return (values['name'] as String); + } + + set name(String value) => values['name'] = value; + void copyFrom(Author model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + name = model.name; + } +} + +// ************************************************************************** +// JsonModelGenerator +// ************************************************************************** + +@generatedSerializable +class Book extends _Book { + Book( + {this.id, + this.createdAt, + this.updatedAt, + this.author, + this.partnerAuthor, + this.name}); + + /// A unique identifier corresponding to this item. + @override + String id; + + /// The time at which this item was created. + @override + DateTime createdAt; + + /// The last time at which this item was updated. + @override + DateTime updatedAt; + + @override + _Author author; + + @override + _Author partnerAuthor; + + @override + String name; + + Book copyWith( + {String id, + DateTime createdAt, + DateTime updatedAt, + _Author author, + _Author partnerAuthor, + String name}) { + return Book( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + author: author ?? this.author, + partnerAuthor: partnerAuthor ?? this.partnerAuthor, + name: name ?? this.name); + } + + bool operator ==(other) { + return other is _Book && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.author == author && + other.partnerAuthor == partnerAuthor && + other.name == name; + } + + @override + int get hashCode { + return hashObjects([id, createdAt, updatedAt, author, partnerAuthor, name]); + } + + @override + String toString() { + return "Book(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, author=$author, partnerAuthor=$partnerAuthor, name=$name)"; + } + + Map toJson() { + return BookSerializer.toMap(this); + } +} + +@generatedSerializable +class Author extends _Author { + Author({this.id, this.createdAt, this.updatedAt, this.name = 'Tobe Osakwe'}); + + /// A unique identifier corresponding to this item. + @override + String id; + + /// The time at which this item was created. + @override + DateTime createdAt; + + /// The last time at which this item was updated. + @override + DateTime updatedAt; + + @override + final String name; + + Author copyWith( + {String id, DateTime createdAt, DateTime updatedAt, String name}) { + return Author( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + name: name ?? this.name); + } + + bool operator ==(other) { + return other is _Author && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.name == name; + } + + @override + int get hashCode { + return hashObjects([id, createdAt, updatedAt, name]); + } + + @override + String toString() { + return "Author(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, name=$name)"; + } + + Map toJson() { + return AuthorSerializer.toMap(this); + } +} + +// ************************************************************************** +// SerializerGenerator +// ************************************************************************** + +const BookSerializer bookSerializer = BookSerializer(); + +class BookEncoder extends Converter { + const BookEncoder(); + + @override + Map convert(Book model) => BookSerializer.toMap(model); +} + +class BookDecoder extends Converter { + const BookDecoder(); + + @override + Book convert(Map map) => BookSerializer.fromMap(map); +} + +class BookSerializer extends Codec { + const BookSerializer(); + + @override + get encoder => const BookEncoder(); + @override + get decoder => const BookDecoder(); + static Book fromMap(Map map) { + return Book( + id: map['id'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null, + author: map['author'] != null + ? AuthorSerializer.fromMap(map['author'] as Map) + : null, + partnerAuthor: map['partner_author'] != null + ? AuthorSerializer.fromMap(map['partner_author'] as Map) + : null, + name: map['name'] as String); + } + + static Map toMap(_Book model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String(), + 'author': AuthorSerializer.toMap(model.author), + 'partner_author': AuthorSerializer.toMap(model.partnerAuthor), + 'name': model.name + }; + } +} + +abstract class BookFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + author, + partnerAuthor, + name + ]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; + + static const String author = 'author'; + + static const String partnerAuthor = 'partner_author'; + + static const String name = 'name'; +} + +const AuthorSerializer authorSerializer = AuthorSerializer(); + +class AuthorEncoder extends Converter { + const AuthorEncoder(); + + @override + Map convert(Author model) => AuthorSerializer.toMap(model); +} + +class AuthorDecoder extends Converter { + const AuthorDecoder(); + + @override + Author convert(Map map) => AuthorSerializer.fromMap(map); +} + +class AuthorSerializer extends Codec { + const AuthorSerializer(); + + @override + get encoder => const AuthorEncoder(); + @override + get decoder => const AuthorDecoder(); + static Author fromMap(Map map) { + return Author( + id: map['id'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null, + name: map['name'] as String ?? 'Tobe Osakwe'); + } + + static Map toMap(_Author model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String(), + 'name': model.name + }; + } +} + +abstract class AuthorFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + name + ]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; + + static const String name = 'name'; +} diff --git a/angel_orm_test/lib/src/models/car.g.dart b/angel_orm_test/lib/src/models/car.g.dart new file mode 100644 index 00000000..9de60a6b --- /dev/null +++ b/angel_orm_test/lib/src/models/car.g.dart @@ -0,0 +1,367 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of angel_orm.generator.models.car; + +// ************************************************************************** +// MigrationGenerator +// ************************************************************************** + +class CarMigration extends Migration { + @override + up(Schema schema) { + schema.create('cars', (table) { + table.serial('id')..primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.varChar('make'); + table.varChar('description'); + table.boolean('family_friendly'); + table.timeStamp('recalled_at'); + }); + } + + @override + down(Schema schema) { + schema.drop('cars'); + } +} + +// ************************************************************************** +// OrmGenerator +// ************************************************************************** + +class CarQuery extends Query { + CarQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = CarQueryWhere(this); + } + + @override + final CarQueryValues values = CarQueryValues(); + + CarQueryWhere _where; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'cars'; + } + + @override + get fields { + return const [ + 'id', + 'created_at', + 'updated_at', + 'make', + 'description', + 'family_friendly', + 'recalled_at' + ]; + } + + @override + CarQueryWhere get where { + return _where; + } + + @override + CarQueryWhere newWhereClause() { + return CarQueryWhere(this); + } + + static Car parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Car( + id: row[0].toString(), + createdAt: (row[1] as DateTime), + updatedAt: (row[2] as DateTime), + make: (row[3] as String), + description: (row[4] as String), + familyFriendly: (row[5] as bool), + recalledAt: (row[6] as DateTime)); + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } +} + +class CarQueryWhere extends QueryWhere { + CarQueryWhere(CarQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), + make = StringSqlExpressionBuilder(query, 'make'), + description = StringSqlExpressionBuilder(query, 'description'), + familyFriendly = BooleanSqlExpressionBuilder(query, 'family_friendly'), + recalledAt = DateTimeSqlExpressionBuilder(query, 'recalled_at'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final StringSqlExpressionBuilder make; + + final StringSqlExpressionBuilder description; + + final BooleanSqlExpressionBuilder familyFriendly; + + final DateTimeSqlExpressionBuilder recalledAt; + + @override + get expressionBuilders { + return [ + id, + createdAt, + updatedAt, + make, + description, + familyFriendly, + recalledAt + ]; + } +} + +class CarQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + String get make { + return (values['make'] as String); + } + + set make(String value) => values['make'] = value; + String get description { + return (values['description'] as String); + } + + set description(String value) => values['description'] = value; + bool get familyFriendly { + return (values['family_friendly'] as bool); + } + + set familyFriendly(bool value) => values['family_friendly'] = value; + DateTime get recalledAt { + return (values['recalled_at'] as DateTime); + } + + set recalledAt(DateTime value) => values['recalled_at'] = value; + void copyFrom(Car model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + make = model.make; + description = model.description; + familyFriendly = model.familyFriendly; + recalledAt = model.recalledAt; + } +} + +// ************************************************************************** +// JsonModelGenerator +// ************************************************************************** + +@generatedSerializable +class Car extends _Car { + Car( + {this.id, + this.createdAt, + this.updatedAt, + this.make, + this.description, + this.familyFriendly, + this.recalledAt}); + + /// A unique identifier corresponding to this item. + @override + String id; + + /// The time at which this item was created. + @override + DateTime createdAt; + + /// The last time at which this item was updated. + @override + DateTime updatedAt; + + @override + String make; + + @override + String description; + + @override + bool familyFriendly; + + @override + DateTime recalledAt; + + Car copyWith( + {String id, + DateTime createdAt, + DateTime updatedAt, + String make, + String description, + bool familyFriendly, + DateTime recalledAt}) { + return Car( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + make: make ?? this.make, + description: description ?? this.description, + familyFriendly: familyFriendly ?? this.familyFriendly, + recalledAt: recalledAt ?? this.recalledAt); + } + + bool operator ==(other) { + return other is _Car && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.make == make && + other.description == description && + other.familyFriendly == familyFriendly && + other.recalledAt == recalledAt; + } + + @override + int get hashCode { + return hashObjects([ + id, + createdAt, + updatedAt, + make, + description, + familyFriendly, + recalledAt + ]); + } + + @override + String toString() { + return "Car(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, make=$make, description=$description, familyFriendly=$familyFriendly, recalledAt=$recalledAt)"; + } + + Map toJson() { + return CarSerializer.toMap(this); + } +} + +// ************************************************************************** +// SerializerGenerator +// ************************************************************************** + +const CarSerializer carSerializer = CarSerializer(); + +class CarEncoder extends Converter { + const CarEncoder(); + + @override + Map convert(Car model) => CarSerializer.toMap(model); +} + +class CarDecoder extends Converter { + const CarDecoder(); + + @override + Car convert(Map map) => CarSerializer.fromMap(map); +} + +class CarSerializer extends Codec { + const CarSerializer(); + + @override + get encoder => const CarEncoder(); + @override + get decoder => const CarDecoder(); + static Car fromMap(Map map) { + return Car( + id: map['id'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null, + make: map['make'] as String, + description: map['description'] as String, + familyFriendly: map['family_friendly'] as bool, + recalledAt: map['recalled_at'] != null + ? (map['recalled_at'] is DateTime + ? (map['recalled_at'] as DateTime) + : DateTime.parse(map['recalled_at'].toString())) + : null); + } + + static Map toMap(_Car model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String(), + 'make': model.make, + 'description': model.description, + 'family_friendly': model.familyFriendly, + 'recalled_at': model.recalledAt?.toIso8601String() + }; + } +} + +abstract class CarFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + make, + description, + familyFriendly, + recalledAt + ]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; + + static const String make = 'make'; + + static const String description = 'description'; + + static const String familyFriendly = 'family_friendly'; + + static const String recalledAt = 'recalled_at'; +} diff --git a/angel_orm_test/lib/src/models/email_indexed.g.dart b/angel_orm_test/lib/src/models/email_indexed.g.dart new file mode 100644 index 00000000..85fffb87 --- /dev/null +++ b/angel_orm_test/lib/src/models/email_indexed.g.dart @@ -0,0 +1,798 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'email_indexed.dart'; + +// ************************************************************************** +// MigrationGenerator +// ************************************************************************** + +class RoleMigration extends Migration { + @override + up(Schema schema) { + schema.create('roles', (table) { + table.declare('role', ColumnType('varchar'))..primaryKey(); + }); + } + + @override + down(Schema schema) { + schema.drop('roles', cascade: true); + } +} + +class RoleUserMigration extends Migration { + @override + up(Schema schema) { + schema.create('role_users', (table) { + table + .declare('role_role', ColumnType('varchar')) + .references('roles', 'role'); + table + .declare('user_email', ColumnType('varchar')) + .references('users', 'email'); + }); + } + + @override + down(Schema schema) { + schema.drop('role_users'); + } +} + +class UserMigration extends Migration { + @override + up(Schema schema) { + schema.create('users', (table) { + table.varChar('email')..primaryKey(); + table.varChar('name'); + table.varChar('password'); + }); + } + + @override + down(Schema schema) { + schema.drop('users', cascade: true); + } +} + +// ************************************************************************** +// OrmGenerator +// ************************************************************************** + +class RoleQuery extends Query { + RoleQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = RoleQueryWhere(this); + leftJoin(_users = RoleUserQuery(trampoline: trampoline, parent: this), + 'role', 'role_role', + additionalFields: const ['email', 'name', 'password'], + trampoline: trampoline); + } + + @override + final RoleQueryValues values = RoleQueryValues(); + + RoleQueryWhere _where; + + RoleUserQuery _users; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'roles'; + } + + @override + get fields { + return const ['role']; + } + + @override + RoleQueryWhere get where { + return _where; + } + + @override + RoleQueryWhere newWhereClause() { + return RoleQueryWhere(this); + } + + static Role parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Role(role: (row[0] as String)); + if (row.length > 1) { + model = model.copyWith( + users: [UserQuery.parseRow(row.skip(1).take(3).toList())] + .where((x) => x != null) + .toList()); + } + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } + + RoleUserQuery get users { + return _users; + } + + @override + bool canCompile(trampoline) { + return (!(trampoline.contains('roles') && + trampoline.contains('role_users'))); + } + + @override + get(QueryExecutor executor) { + return super.get(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.role == model.role); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + users: List<_User>.from(l.users ?? []) + ..addAll(model.users ?? [])); + } + }); + }); + } + + @override + update(QueryExecutor executor) { + return super.update(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.role == model.role); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + users: List<_User>.from(l.users ?? []) + ..addAll(model.users ?? [])); + } + }); + }); + } + + @override + delete(QueryExecutor executor) { + return super.delete(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.role == model.role); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + users: List<_User>.from(l.users ?? []) + ..addAll(model.users ?? [])); + } + }); + }); + } +} + +class RoleQueryWhere extends QueryWhere { + RoleQueryWhere(RoleQuery query) + : role = StringSqlExpressionBuilder(query, 'role'); + + final StringSqlExpressionBuilder role; + + @override + get expressionBuilders { + return [role]; + } +} + +class RoleQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get role { + return (values['role'] as String); + } + + set role(String value) => values['role'] = value; + void copyFrom(Role model) { + role = model.role; + } +} + +class RoleUserQuery extends Query { + RoleUserQuery({Query parent, Set trampoline}) + : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = RoleUserQueryWhere(this); + leftJoin(_role = RoleQuery(trampoline: trampoline, parent: this), + 'role_role', 'role', + additionalFields: const ['role'], trampoline: trampoline); + leftJoin(_user = UserQuery(trampoline: trampoline, parent: this), + 'user_email', 'email', + additionalFields: const ['email', 'name', 'password'], + trampoline: trampoline); + } + + @override + final RoleUserQueryValues values = RoleUserQueryValues(); + + RoleUserQueryWhere _where; + + RoleQuery _role; + + UserQuery _user; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'role_users'; + } + + @override + get fields { + return const ['role_role', 'user_email']; + } + + @override + RoleUserQueryWhere get where { + return _where; + } + + @override + RoleUserQueryWhere newWhereClause() { + return RoleUserQueryWhere(this); + } + + static RoleUser parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = RoleUser(); + if (row.length > 2) { + model = model.copyWith( + role: RoleQuery.parseRow(row.skip(2).take(1).toList())); + } + if (row.length > 3) { + model = model.copyWith( + user: UserQuery.parseRow(row.skip(3).take(3).toList())); + } + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } + + RoleQuery get role { + return _role; + } + + UserQuery get user { + return _user; + } +} + +class RoleUserQueryWhere extends QueryWhere { + RoleUserQueryWhere(RoleUserQuery query) + : roleRole = StringSqlExpressionBuilder(query, 'role_role'), + userEmail = StringSqlExpressionBuilder(query, 'user_email'); + + final StringSqlExpressionBuilder roleRole; + + final StringSqlExpressionBuilder userEmail; + + @override + get expressionBuilders { + return [roleRole, userEmail]; + } +} + +class RoleUserQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get roleRole { + return (values['role_role'] as String); + } + + set roleRole(String value) => values['role_role'] = value; + String get userEmail { + return (values['user_email'] as String); + } + + set userEmail(String value) => values['user_email'] = value; + void copyFrom(RoleUser model) { + if (model.role != null) { + values['role_role'] = model.role.role; + } + if (model.user != null) { + values['user_email'] = model.user.email; + } + } +} + +class UserQuery extends Query { + UserQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = UserQueryWhere(this); + leftJoin(_roles = RoleUserQuery(trampoline: trampoline, parent: this), + 'email', 'user_email', + additionalFields: const ['role'], trampoline: trampoline); + } + + @override + final UserQueryValues values = UserQueryValues(); + + UserQueryWhere _where; + + RoleUserQuery _roles; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'users'; + } + + @override + get fields { + return const ['email', 'name', 'password']; + } + + @override + UserQueryWhere get where { + return _where; + } + + @override + UserQueryWhere newWhereClause() { + return UserQueryWhere(this); + } + + static User parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = User( + email: (row[0] as String), + name: (row[1] as String), + password: (row[2] as String)); + if (row.length > 3) { + model = model.copyWith( + roles: [RoleQuery.parseRow(row.skip(3).take(1).toList())] + .where((x) => x != null) + .toList()); + } + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } + + RoleUserQuery get roles { + return _roles; + } + + @override + bool canCompile(trampoline) { + return (!(trampoline.contains('users') && + trampoline.contains('role_users'))); + } + + @override + get(QueryExecutor executor) { + return super.get(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.email == model.email); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + roles: List<_Role>.from(l.roles ?? []) + ..addAll(model.roles ?? [])); + } + }); + }); + } + + @override + update(QueryExecutor executor) { + return super.update(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.email == model.email); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + roles: List<_Role>.from(l.roles ?? []) + ..addAll(model.roles ?? [])); + } + }); + }); + } + + @override + delete(QueryExecutor executor) { + return super.delete(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.email == model.email); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + roles: List<_Role>.from(l.roles ?? []) + ..addAll(model.roles ?? [])); + } + }); + }); + } +} + +class UserQueryWhere extends QueryWhere { + UserQueryWhere(UserQuery query) + : email = StringSqlExpressionBuilder(query, 'email'), + name = StringSqlExpressionBuilder(query, 'name'), + password = StringSqlExpressionBuilder(query, 'password'); + + final StringSqlExpressionBuilder email; + + final StringSqlExpressionBuilder name; + + final StringSqlExpressionBuilder password; + + @override + get expressionBuilders { + return [email, name, password]; + } +} + +class UserQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get email { + return (values['email'] as String); + } + + set email(String value) => values['email'] = value; + String get name { + return (values['name'] as String); + } + + set name(String value) => values['name'] = value; + String get password { + return (values['password'] as String); + } + + set password(String value) => values['password'] = value; + void copyFrom(User model) { + email = model.email; + name = model.name; + password = model.password; + } +} + +// ************************************************************************** +// JsonModelGenerator +// ************************************************************************** + +@generatedSerializable +class Role implements _Role { + const Role({this.role, this.users}); + + @override + final String role; + + @override + final List<_User> users; + + Role copyWith({String role, List<_User> users}) { + return Role(role: role ?? this.role, users: users ?? this.users); + } + + bool operator ==(other) { + return other is _Role && + other.role == role && + ListEquality<_User>(DefaultEquality<_User>()) + .equals(other.users, users); + } + + @override + int get hashCode { + return hashObjects([role, users]); + } + + @override + String toString() { + return "Role(role=$role, users=$users)"; + } + + Map toJson() { + return RoleSerializer.toMap(this); + } +} + +@generatedSerializable +class RoleUser implements _RoleUser { + const RoleUser({this.role, this.user}); + + @override + final _Role role; + + @override + final _User user; + + RoleUser copyWith({_Role role, _User user}) { + return RoleUser(role: role ?? this.role, user: user ?? this.user); + } + + bool operator ==(other) { + return other is _RoleUser && other.role == role && other.user == user; + } + + @override + int get hashCode { + return hashObjects([role, user]); + } + + @override + String toString() { + return "RoleUser(role=$role, user=$user)"; + } + + Map toJson() { + return RoleUserSerializer.toMap(this); + } +} + +@generatedSerializable +class User implements _User { + const User({this.email, this.name, this.password, this.roles}); + + @override + final String email; + + @override + final String name; + + @override + final String password; + + @override + final List<_Role> roles; + + User copyWith( + {String email, String name, String password, List<_Role> roles}) { + return User( + email: email ?? this.email, + name: name ?? this.name, + password: password ?? this.password, + roles: roles ?? this.roles); + } + + bool operator ==(other) { + return other is _User && + other.email == email && + other.name == name && + other.password == password && + ListEquality<_Role>(DefaultEquality<_Role>()) + .equals(other.roles, roles); + } + + @override + int get hashCode { + return hashObjects([email, name, password, roles]); + } + + @override + String toString() { + return "User(email=$email, name=$name, password=$password, roles=$roles)"; + } + + Map toJson() { + return UserSerializer.toMap(this); + } +} + +// ************************************************************************** +// SerializerGenerator +// ************************************************************************** + +const RoleSerializer roleSerializer = RoleSerializer(); + +class RoleEncoder extends Converter { + const RoleEncoder(); + + @override + Map convert(Role model) => RoleSerializer.toMap(model); +} + +class RoleDecoder extends Converter { + const RoleDecoder(); + + @override + Role convert(Map map) => RoleSerializer.fromMap(map); +} + +class RoleSerializer extends Codec { + const RoleSerializer(); + + @override + get encoder => const RoleEncoder(); + @override + get decoder => const RoleDecoder(); + static Role fromMap(Map map) { + return Role( + role: map['role'] as String, + users: map['users'] is Iterable + ? List.unmodifiable(((map['users'] as Iterable).whereType()) + .map(UserSerializer.fromMap)) + : null); + } + + static Map toMap(_Role model) { + if (model == null) { + return null; + } + return { + 'role': model.role, + 'users': model.users?.map((m) => UserSerializer.toMap(m))?.toList() + }; + } +} + +abstract class RoleFields { + static const List allFields = [role, users]; + + static const String role = 'role'; + + static const String users = 'users'; +} + +const RoleUserSerializer roleUserSerializer = RoleUserSerializer(); + +class RoleUserEncoder extends Converter { + const RoleUserEncoder(); + + @override + Map convert(RoleUser model) => RoleUserSerializer.toMap(model); +} + +class RoleUserDecoder extends Converter { + const RoleUserDecoder(); + + @override + RoleUser convert(Map map) => RoleUserSerializer.fromMap(map); +} + +class RoleUserSerializer extends Codec { + const RoleUserSerializer(); + + @override + get encoder => const RoleUserEncoder(); + @override + get decoder => const RoleUserDecoder(); + static RoleUser fromMap(Map map) { + return RoleUser( + role: map['role'] != null + ? RoleSerializer.fromMap(map['role'] as Map) + : null, + user: map['user'] != null + ? UserSerializer.fromMap(map['user'] as Map) + : null); + } + + static Map toMap(_RoleUser model) { + if (model == null) { + return null; + } + return { + 'role': RoleSerializer.toMap(model.role), + 'user': UserSerializer.toMap(model.user) + }; + } +} + +abstract class RoleUserFields { + static const List allFields = [role, user]; + + static const String role = 'role'; + + static const String user = 'user'; +} + +const UserSerializer userSerializer = UserSerializer(); + +class UserEncoder extends Converter { + const UserEncoder(); + + @override + Map convert(User model) => UserSerializer.toMap(model); +} + +class UserDecoder extends Converter { + const UserDecoder(); + + @override + User convert(Map map) => UserSerializer.fromMap(map); +} + +class UserSerializer extends Codec { + const UserSerializer(); + + @override + get encoder => const UserEncoder(); + @override + get decoder => const UserDecoder(); + static User fromMap(Map map) { + return User( + email: map['email'] as String, + name: map['name'] as String, + password: map['password'] as String, + roles: map['roles'] is Iterable + ? List.unmodifiable(((map['roles'] as Iterable).whereType()) + .map(RoleSerializer.fromMap)) + : null); + } + + static Map toMap(_User model) { + if (model == null) { + return null; + } + return { + 'email': model.email, + 'name': model.name, + 'password': model.password, + 'roles': model.roles?.map((m) => RoleSerializer.toMap(m))?.toList() + }; + } +} + +abstract class UserFields { + static const List allFields = [email, name, password, roles]; + + static const String email = 'email'; + + static const String name = 'name'; + + static const String password = 'password'; + + static const String roles = 'roles'; +} diff --git a/angel_orm_test/lib/src/models/has_car.g.dart b/angel_orm_test/lib/src/models/has_car.g.dart new file mode 100644 index 00000000..b8adf3d5 --- /dev/null +++ b/angel_orm_test/lib/src/models/has_car.g.dart @@ -0,0 +1,275 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'has_car.dart'; + +// ************************************************************************** +// MigrationGenerator +// ************************************************************************** + +class HasCarMigration extends Migration { + @override + up(Schema schema) { + schema.create('has_cars', (table) { + table.serial('id')..primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.integer('type'); + }); + } + + @override + down(Schema schema) { + schema.drop('has_cars'); + } +} + +// ************************************************************************** +// OrmGenerator +// ************************************************************************** + +class HasCarQuery extends Query { + HasCarQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = HasCarQueryWhere(this); + } + + @override + final HasCarQueryValues values = HasCarQueryValues(); + + HasCarQueryWhere _where; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'has_cars'; + } + + @override + get fields { + return const ['id', 'created_at', 'updated_at', 'type']; + } + + @override + HasCarQueryWhere get where { + return _where; + } + + @override + HasCarQueryWhere newWhereClause() { + return HasCarQueryWhere(this); + } + + static HasCar parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = HasCar( + id: row[0].toString(), + createdAt: (row[1] as DateTime), + updatedAt: (row[2] as DateTime), + type: row[3] == null ? null : CarType.values[(row[3] as int)]); + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } +} + +class HasCarQueryWhere extends QueryWhere { + HasCarQueryWhere(HasCarQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), + type = EnumSqlExpressionBuilder(query, 'type', (v) => v.index); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final EnumSqlExpressionBuilder type; + + @override + get expressionBuilders { + return [id, createdAt, updatedAt, type]; + } +} + +class HasCarQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + CarType get type { + return CarType.values[(values['type'] as int)]; + } + + set type(CarType value) => values['type'] = value?.index; + void copyFrom(HasCar model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + type = model.type; + } +} + +// ************************************************************************** +// JsonModelGenerator +// ************************************************************************** + +@generatedSerializable +class HasCar extends _HasCar { + HasCar({this.id, this.createdAt, this.updatedAt, this.type = CarType.sedan}); + + /// A unique identifier corresponding to this item. + @override + String id; + + /// The time at which this item was created. + @override + DateTime createdAt; + + /// The last time at which this item was updated. + @override + DateTime updatedAt; + + @override + final CarType type; + + HasCar copyWith( + {String id, DateTime createdAt, DateTime updatedAt, CarType type}) { + return HasCar( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + type: type ?? this.type); + } + + bool operator ==(other) { + return other is _HasCar && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.type == type; + } + + @override + int get hashCode { + return hashObjects([id, createdAt, updatedAt, type]); + } + + @override + String toString() { + return "HasCar(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, type=$type)"; + } + + Map toJson() { + return HasCarSerializer.toMap(this); + } +} + +// ************************************************************************** +// SerializerGenerator +// ************************************************************************** + +const HasCarSerializer hasCarSerializer = HasCarSerializer(); + +class HasCarEncoder extends Converter { + const HasCarEncoder(); + + @override + Map convert(HasCar model) => HasCarSerializer.toMap(model); +} + +class HasCarDecoder extends Converter { + const HasCarDecoder(); + + @override + HasCar convert(Map map) => HasCarSerializer.fromMap(map); +} + +class HasCarSerializer extends Codec { + const HasCarSerializer(); + + @override + get encoder => const HasCarEncoder(); + @override + get decoder => const HasCarDecoder(); + static HasCar fromMap(Map map) { + if (map['type'] == null) { + throw FormatException("Missing required field 'type' on HasCar."); + } + + return HasCar( + id: map['id'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null, + type: map['type'] is CarType + ? (map['type'] as CarType) + : (map['type'] is int + ? CarType.values[map['type'] as int] + : CarType.sedan)); + } + + static Map toMap(_HasCar model) { + if (model == null) { + return null; + } + if (model.type == null) { + throw FormatException("Missing required field 'type' on HasCar."); + } + + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String(), + 'type': model.type == null ? null : CarType.values.indexOf(model.type) + }; + } +} + +abstract class HasCarFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + type + ]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; + + static const String type = 'type'; +} diff --git a/angel_orm_test/lib/src/models/has_map.g.dart b/angel_orm_test/lib/src/models/has_map.g.dart new file mode 100644 index 00000000..71a612f7 --- /dev/null +++ b/angel_orm_test/lib/src/models/has_map.g.dart @@ -0,0 +1,208 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'has_map.dart'; + +// ************************************************************************** +// MigrationGenerator +// ************************************************************************** + +class HasMapMigration extends Migration { + @override + up(Schema schema) { + schema.create('has_maps', (table) { + table.declare('value', ColumnType('jsonb')); + table.declare('list', ColumnType('jsonb')); + }); + } + + @override + down(Schema schema) { + schema.drop('has_maps'); + } +} + +// ************************************************************************** +// OrmGenerator +// ************************************************************************** + +class HasMapQuery extends Query { + HasMapQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = HasMapQueryWhere(this); + } + + @override + final HasMapQueryValues values = HasMapQueryValues(); + + HasMapQueryWhere _where; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'has_maps'; + } + + @override + get fields { + return const ['value', 'list']; + } + + @override + HasMapQueryWhere get where { + return _where; + } + + @override + HasMapQueryWhere newWhereClause() { + return HasMapQueryWhere(this); + } + + static HasMap parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = HasMap( + value: (row[0] as Map), + list: (row[1] as List)); + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } +} + +class HasMapQueryWhere extends QueryWhere { + HasMapQueryWhere(HasMapQuery query) + : value = MapSqlExpressionBuilder(query, 'value'), + list = ListSqlExpressionBuilder(query, 'list'); + + final MapSqlExpressionBuilder value; + + final ListSqlExpressionBuilder list; + + @override + get expressionBuilders { + return [value, list]; + } +} + +class HasMapQueryValues extends MapQueryValues { + @override + get casts { + return {'list': 'jsonb'}; + } + + Map get value { + return (values['value'] as Map); + } + + set value(Map value) => values['value'] = value; + List get list { + return (json.decode((values['list'] as String)) as List); + } + + set list(List value) => values['list'] = json.encode(value); + void copyFrom(HasMap model) { + value = model.value; + list = model.list; + } +} + +// ************************************************************************** +// JsonModelGenerator +// ************************************************************************** + +@generatedSerializable +class HasMap implements _HasMap { + const HasMap({this.value, this.list}); + + @override + final Map value; + + @override + final List list; + + HasMap copyWith({Map value, List list}) { + return HasMap(value: value ?? this.value, list: list ?? this.list); + } + + bool operator ==(other) { + return other is _HasMap && + MapEquality( + keys: DefaultEquality(), values: DefaultEquality()) + .equals(other.value, value) && + ListEquality(DefaultEquality()).equals(other.list, list); + } + + @override + int get hashCode { + return hashObjects([value, list]); + } + + @override + String toString() { + return "HasMap(value=$value, list=$list)"; + } + + Map toJson() { + return HasMapSerializer.toMap(this); + } +} + +// ************************************************************************** +// SerializerGenerator +// ************************************************************************** + +const HasMapSerializer hasMapSerializer = HasMapSerializer(); + +class HasMapEncoder extends Converter { + const HasMapEncoder(); + + @override + Map convert(HasMap model) => HasMapSerializer.toMap(model); +} + +class HasMapDecoder extends Converter { + const HasMapDecoder(); + + @override + HasMap convert(Map map) => HasMapSerializer.fromMap(map); +} + +class HasMapSerializer extends Codec { + const HasMapSerializer(); + + @override + get encoder => const HasMapEncoder(); + @override + get decoder => const HasMapDecoder(); + static HasMap fromMap(Map map) { + return HasMap( + value: map['value'] is Map + ? (map['value'] as Map).cast() + : null, + list: map['list'] is Iterable + ? (map['list'] as Iterable).cast().toList() + : null); + } + + static Map toMap(_HasMap model) { + if (model == null) { + return null; + } + return {'value': model.value, 'list': model.list}; + } +} + +abstract class HasMapFields { + static const List allFields = [value, list]; + + static const String value = 'value'; + + static const String list = 'list'; +} diff --git a/angel_orm_test/lib/src/models/leg.g.dart b/angel_orm_test/lib/src/models/leg.g.dart new file mode 100644 index 00000000..1575ddfb --- /dev/null +++ b/angel_orm_test/lib/src/models/leg.g.dart @@ -0,0 +1,568 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of angel_orm_generator.test.models.leg; + +// ************************************************************************** +// MigrationGenerator +// ************************************************************************** + +class LegMigration extends Migration { + @override + up(Schema schema) { + schema.create('legs', (table) { + table.serial('id')..primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.varChar('name'); + }); + } + + @override + down(Schema schema) { + schema.drop('legs', cascade: true); + } +} + +class FootMigration extends Migration { + @override + up(Schema schema) { + schema.create('feet', (table) { + table.serial('id')..primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.integer('leg_id'); + table.declare('n_toes', ColumnType('decimal')); + }); + } + + @override + down(Schema schema) { + schema.drop('feet'); + } +} + +// ************************************************************************** +// OrmGenerator +// ************************************************************************** + +class LegQuery extends Query { + LegQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = LegQueryWhere(this); + leftJoin( + _foot = FootQuery(trampoline: trampoline, parent: this), 'id', 'leg_id', + additionalFields: const [ + 'id', + 'created_at', + 'updated_at', + 'leg_id', + 'n_toes' + ], + trampoline: trampoline); + } + + @override + final LegQueryValues values = LegQueryValues(); + + LegQueryWhere _where; + + FootQuery _foot; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'legs'; + } + + @override + get fields { + return const ['id', 'created_at', 'updated_at', 'name']; + } + + @override + LegQueryWhere get where { + return _where; + } + + @override + LegQueryWhere newWhereClause() { + return LegQueryWhere(this); + } + + static Leg parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Leg( + id: row[0].toString(), + createdAt: (row[1] as DateTime), + updatedAt: (row[2] as DateTime), + name: (row[3] as String)); + if (row.length > 4) { + model = model.copyWith( + foot: FootQuery.parseRow(row.skip(4).take(5).toList())); + } + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } + + FootQuery get foot { + return _foot; + } +} + +class LegQueryWhere extends QueryWhere { + LegQueryWhere(LegQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), + name = StringSqlExpressionBuilder(query, 'name'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final StringSqlExpressionBuilder name; + + @override + get expressionBuilders { + return [id, createdAt, updatedAt, name]; + } +} + +class LegQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + String get name { + return (values['name'] as String); + } + + set name(String value) => values['name'] = value; + void copyFrom(Leg model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + name = model.name; + } +} + +class FootQuery extends Query { + FootQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = FootQueryWhere(this); + } + + @override + final FootQueryValues values = FootQueryValues(); + + FootQueryWhere _where; + + @override + get casts { + return {'n_toes': 'text'}; + } + + @override + get tableName { + return 'feet'; + } + + @override + get fields { + return const ['id', 'created_at', 'updated_at', 'leg_id', 'n_toes']; + } + + @override + FootQueryWhere get where { + return _where; + } + + @override + FootQueryWhere newWhereClause() { + return FootQueryWhere(this); + } + + static Foot parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Foot( + id: row[0].toString(), + createdAt: (row[1] as DateTime), + updatedAt: (row[2] as DateTime), + legId: (row[3] as int), + nToes: double.tryParse(row[4].toString())); + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } +} + +class FootQueryWhere extends QueryWhere { + FootQueryWhere(FootQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), + legId = NumericSqlExpressionBuilder(query, 'leg_id'), + nToes = NumericSqlExpressionBuilder(query, 'n_toes'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final NumericSqlExpressionBuilder legId; + + final NumericSqlExpressionBuilder nToes; + + @override + get expressionBuilders { + return [id, createdAt, updatedAt, legId, nToes]; + } +} + +class FootQueryValues extends MapQueryValues { + @override + get casts { + return {'n_toes': 'decimal'}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + int get legId { + return (values['leg_id'] as int); + } + + set legId(int value) => values['leg_id'] = value; + double get nToes { + return double.tryParse((values['n_toes'] as String)); + } + + set nToes(double value) => values['n_toes'] = value.toString(); + void copyFrom(Foot model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + legId = model.legId; + nToes = model.nToes; + } +} + +// ************************************************************************** +// JsonModelGenerator +// ************************************************************************** + +@generatedSerializable +class Leg extends _Leg { + Leg({this.id, this.createdAt, this.updatedAt, this.foot, this.name}); + + /// A unique identifier corresponding to this item. + @override + String id; + + /// The time at which this item was created. + @override + DateTime createdAt; + + /// The last time at which this item was updated. + @override + DateTime updatedAt; + + @override + _Foot foot; + + @override + String name; + + Leg copyWith( + {String id, + DateTime createdAt, + DateTime updatedAt, + _Foot foot, + String name}) { + return Leg( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + foot: foot ?? this.foot, + name: name ?? this.name); + } + + bool operator ==(other) { + return other is _Leg && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.foot == foot && + other.name == name; + } + + @override + int get hashCode { + return hashObjects([id, createdAt, updatedAt, foot, name]); + } + + @override + String toString() { + return "Leg(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, foot=$foot, name=$name)"; + } + + Map toJson() { + return LegSerializer.toMap(this); + } +} + +@generatedSerializable +class Foot extends _Foot { + Foot({this.id, this.createdAt, this.updatedAt, this.legId, this.nToes}); + + /// A unique identifier corresponding to this item. + @override + String id; + + /// The time at which this item was created. + @override + DateTime createdAt; + + /// The last time at which this item was updated. + @override + DateTime updatedAt; + + @override + int legId; + + @override + double nToes; + + Foot copyWith( + {String id, + DateTime createdAt, + DateTime updatedAt, + int legId, + double nToes}) { + return Foot( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + legId: legId ?? this.legId, + nToes: nToes ?? this.nToes); + } + + bool operator ==(other) { + return other is _Foot && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.legId == legId && + other.nToes == nToes; + } + + @override + int get hashCode { + return hashObjects([id, createdAt, updatedAt, legId, nToes]); + } + + @override + String toString() { + return "Foot(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, legId=$legId, nToes=$nToes)"; + } + + Map toJson() { + return FootSerializer.toMap(this); + } +} + +// ************************************************************************** +// SerializerGenerator +// ************************************************************************** + +const LegSerializer legSerializer = LegSerializer(); + +class LegEncoder extends Converter { + const LegEncoder(); + + @override + Map convert(Leg model) => LegSerializer.toMap(model); +} + +class LegDecoder extends Converter { + const LegDecoder(); + + @override + Leg convert(Map map) => LegSerializer.fromMap(map); +} + +class LegSerializer extends Codec { + const LegSerializer(); + + @override + get encoder => const LegEncoder(); + @override + get decoder => const LegDecoder(); + static Leg fromMap(Map map) { + return Leg( + id: map['id'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null, + foot: map['foot'] != null + ? FootSerializer.fromMap(map['foot'] as Map) + : null, + name: map['name'] as String); + } + + static Map toMap(_Leg model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String(), + 'foot': FootSerializer.toMap(model.foot), + 'name': model.name + }; + } +} + +abstract class LegFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + foot, + name + ]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; + + static const String foot = 'foot'; + + static const String name = 'name'; +} + +const FootSerializer footSerializer = FootSerializer(); + +class FootEncoder extends Converter { + const FootEncoder(); + + @override + Map convert(Foot model) => FootSerializer.toMap(model); +} + +class FootDecoder extends Converter { + const FootDecoder(); + + @override + Foot convert(Map map) => FootSerializer.fromMap(map); +} + +class FootSerializer extends Codec { + const FootSerializer(); + + @override + get encoder => const FootEncoder(); + @override + get decoder => const FootDecoder(); + static Foot fromMap(Map map) { + return Foot( + id: map['id'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null, + legId: map['leg_id'] as int, + nToes: map['n_toes'] as double); + } + + static Map toMap(_Foot model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String(), + 'leg_id': model.legId, + 'n_toes': model.nToes + }; + } +} + +abstract class FootFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + legId, + nToes + ]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; + + static const String legId = 'leg_id'; + + static const String nToes = 'n_toes'; +} diff --git a/angel_orm_test/lib/src/models/order.g.dart b/angel_orm_test/lib/src/models/order.g.dart new file mode 100644 index 00000000..edff71ca --- /dev/null +++ b/angel_orm_test/lib/src/models/order.g.dart @@ -0,0 +1,598 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of angel_orm_generator.test.models.order; + +// ************************************************************************** +// MigrationGenerator +// ************************************************************************** + +class OrderMigration extends Migration { + @override + up(Schema schema) { + schema.create('orders', (table) { + table.serial('id')..primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.integer('employee_id'); + table.timeStamp('order_date'); + table.integer('shipper_id'); + table + .declare('customer_id', ColumnType('serial')) + .references('customers', 'id'); + }); + } + + @override + down(Schema schema) { + schema.drop('orders'); + } +} + +class CustomerMigration extends Migration { + @override + up(Schema schema) { + schema.create('customers', (table) { + table.serial('id')..primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + }); + } + + @override + down(Schema schema) { + schema.drop('customers'); + } +} + +// ************************************************************************** +// OrmGenerator +// ************************************************************************** + +class OrderQuery extends Query { + OrderQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = OrderQueryWhere(this); + leftJoin(_customer = CustomerQuery(trampoline: trampoline, parent: this), + 'customer_id', 'id', + additionalFields: const ['id', 'created_at', 'updated_at'], + trampoline: trampoline); + } + + @override + final OrderQueryValues values = OrderQueryValues(); + + OrderQueryWhere _where; + + CustomerQuery _customer; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'orders'; + } + + @override + get fields { + return const [ + 'id', + 'created_at', + 'updated_at', + 'customer_id', + 'employee_id', + 'order_date', + 'shipper_id' + ]; + } + + @override + OrderQueryWhere get where { + return _where; + } + + @override + OrderQueryWhere newWhereClause() { + return OrderQueryWhere(this); + } + + static Order parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Order( + id: row[0].toString(), + createdAt: (row[1] as DateTime), + updatedAt: (row[2] as DateTime), + employeeId: (row[4] as int), + orderDate: (row[5] as DateTime), + shipperId: (row[6] as int)); + if (row.length > 7) { + model = model.copyWith( + customer: CustomerQuery.parseRow(row.skip(7).take(3).toList())); + } + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } + + CustomerQuery get customer { + return _customer; + } +} + +class OrderQueryWhere extends QueryWhere { + OrderQueryWhere(OrderQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), + customerId = NumericSqlExpressionBuilder(query, 'customer_id'), + employeeId = NumericSqlExpressionBuilder(query, 'employee_id'), + orderDate = DateTimeSqlExpressionBuilder(query, 'order_date'), + shipperId = NumericSqlExpressionBuilder(query, 'shipper_id'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final NumericSqlExpressionBuilder customerId; + + final NumericSqlExpressionBuilder employeeId; + + final DateTimeSqlExpressionBuilder orderDate; + + final NumericSqlExpressionBuilder shipperId; + + @override + get expressionBuilders { + return [ + id, + createdAt, + updatedAt, + customerId, + employeeId, + orderDate, + shipperId + ]; + } +} + +class OrderQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + int get customerId { + return (values['customer_id'] as int); + } + + set customerId(int value) => values['customer_id'] = value; + int get employeeId { + return (values['employee_id'] as int); + } + + set employeeId(int value) => values['employee_id'] = value; + DateTime get orderDate { + return (values['order_date'] as DateTime); + } + + set orderDate(DateTime value) => values['order_date'] = value; + int get shipperId { + return (values['shipper_id'] as int); + } + + set shipperId(int value) => values['shipper_id'] = value; + void copyFrom(Order model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + employeeId = model.employeeId; + orderDate = model.orderDate; + shipperId = model.shipperId; + if (model.customer != null) { + values['customer_id'] = model.customer.id; + } + } +} + +class CustomerQuery extends Query { + CustomerQuery({Query parent, Set trampoline}) + : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = CustomerQueryWhere(this); + } + + @override + final CustomerQueryValues values = CustomerQueryValues(); + + CustomerQueryWhere _where; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'customers'; + } + + @override + get fields { + return const ['id', 'created_at', 'updated_at']; + } + + @override + CustomerQueryWhere get where { + return _where; + } + + @override + CustomerQueryWhere newWhereClause() { + return CustomerQueryWhere(this); + } + + static Customer parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Customer( + id: row[0].toString(), + createdAt: (row[1] as DateTime), + updatedAt: (row[2] as DateTime)); + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } +} + +class CustomerQueryWhere extends QueryWhere { + CustomerQueryWhere(CustomerQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + @override + get expressionBuilders { + return [id, createdAt, updatedAt]; + } +} + +class CustomerQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + void copyFrom(Customer model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + } +} + +// ************************************************************************** +// JsonModelGenerator +// ************************************************************************** + +@generatedSerializable +class Order extends _Order { + Order( + {this.id, + this.createdAt, + this.updatedAt, + this.customer, + this.employeeId, + this.orderDate, + this.shipperId}); + + /// A unique identifier corresponding to this item. + @override + String id; + + /// The time at which this item was created. + @override + DateTime createdAt; + + /// The last time at which this item was updated. + @override + DateTime updatedAt; + + @override + final _Customer customer; + + @override + final int employeeId; + + @override + final DateTime orderDate; + + @override + final int shipperId; + + Order copyWith( + {String id, + DateTime createdAt, + DateTime updatedAt, + _Customer customer, + int employeeId, + DateTime orderDate, + int shipperId}) { + return Order( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + customer: customer ?? this.customer, + employeeId: employeeId ?? this.employeeId, + orderDate: orderDate ?? this.orderDate, + shipperId: shipperId ?? this.shipperId); + } + + bool operator ==(other) { + return other is _Order && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.customer == customer && + other.employeeId == employeeId && + other.orderDate == orderDate && + other.shipperId == shipperId; + } + + @override + int get hashCode { + return hashObjects( + [id, createdAt, updatedAt, customer, employeeId, orderDate, shipperId]); + } + + @override + String toString() { + return "Order(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, customer=$customer, employeeId=$employeeId, orderDate=$orderDate, shipperId=$shipperId)"; + } + + Map toJson() { + return OrderSerializer.toMap(this); + } +} + +@generatedSerializable +class Customer extends _Customer { + Customer({this.id, this.createdAt, this.updatedAt}); + + /// A unique identifier corresponding to this item. + @override + String id; + + /// The time at which this item was created. + @override + DateTime createdAt; + + /// The last time at which this item was updated. + @override + DateTime updatedAt; + + Customer copyWith({String id, DateTime createdAt, DateTime updatedAt}) { + return Customer( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt); + } + + bool operator ==(other) { + return other is _Customer && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt; + } + + @override + int get hashCode { + return hashObjects([id, createdAt, updatedAt]); + } + + @override + String toString() { + return "Customer(id=$id, createdAt=$createdAt, updatedAt=$updatedAt)"; + } + + Map toJson() { + return CustomerSerializer.toMap(this); + } +} + +// ************************************************************************** +// SerializerGenerator +// ************************************************************************** + +const OrderSerializer orderSerializer = OrderSerializer(); + +class OrderEncoder extends Converter { + const OrderEncoder(); + + @override + Map convert(Order model) => OrderSerializer.toMap(model); +} + +class OrderDecoder extends Converter { + const OrderDecoder(); + + @override + Order convert(Map map) => OrderSerializer.fromMap(map); +} + +class OrderSerializer extends Codec { + const OrderSerializer(); + + @override + get encoder => const OrderEncoder(); + @override + get decoder => const OrderDecoder(); + static Order fromMap(Map map) { + return Order( + id: map['id'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null, + customer: map['customer'] != null + ? CustomerSerializer.fromMap(map['customer'] as Map) + : null, + employeeId: map['employee_id'] as int, + orderDate: map['order_date'] != null + ? (map['order_date'] is DateTime + ? (map['order_date'] as DateTime) + : DateTime.parse(map['order_date'].toString())) + : null, + shipperId: map['shipper_id'] as int); + } + + static Map toMap(_Order model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String(), + 'customer': CustomerSerializer.toMap(model.customer), + 'employee_id': model.employeeId, + 'order_date': model.orderDate?.toIso8601String(), + 'shipper_id': model.shipperId + }; + } +} + +abstract class OrderFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + customer, + employeeId, + orderDate, + shipperId + ]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; + + static const String customer = 'customer'; + + static const String employeeId = 'employee_id'; + + static const String orderDate = 'order_date'; + + static const String shipperId = 'shipper_id'; +} + +const CustomerSerializer customerSerializer = CustomerSerializer(); + +class CustomerEncoder extends Converter { + const CustomerEncoder(); + + @override + Map convert(Customer model) => CustomerSerializer.toMap(model); +} + +class CustomerDecoder extends Converter { + const CustomerDecoder(); + + @override + Customer convert(Map map) => CustomerSerializer.fromMap(map); +} + +class CustomerSerializer extends Codec { + const CustomerSerializer(); + + @override + get encoder => const CustomerEncoder(); + @override + get decoder => const CustomerDecoder(); + static Customer fromMap(Map map) { + return Customer( + id: map['id'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null); + } + + static Map toMap(_Customer model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String() + }; + } +} + +abstract class CustomerFields { + static const List allFields = [id, createdAt, updatedAt]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; +} diff --git a/angel_orm_test/lib/src/models/tree.g.dart b/angel_orm_test/lib/src/models/tree.g.dart new file mode 100644 index 00000000..b20ca724 --- /dev/null +++ b/angel_orm_test/lib/src/models/tree.g.dart @@ -0,0 +1,636 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of angel_orm_generator.test.models.tree; + +// ************************************************************************** +// MigrationGenerator +// ************************************************************************** + +class TreeMigration extends Migration { + @override + up(Schema schema) { + schema.create('trees', (table) { + table.serial('id')..primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.declare('rings', ColumnType('smallint')); + }); + } + + @override + down(Schema schema) { + schema.drop('trees', cascade: true); + } +} + +class FruitMigration extends Migration { + @override + up(Schema schema) { + schema.create('fruits', (table) { + table.serial('id')..primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.integer('tree_id'); + table.varChar('common_name'); + }); + } + + @override + down(Schema schema) { + schema.drop('fruits'); + } +} + +// ************************************************************************** +// OrmGenerator +// ************************************************************************** + +class TreeQuery extends Query { + TreeQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = TreeQueryWhere(this); + leftJoin(_fruits = FruitQuery(trampoline: trampoline, parent: this), 'id', + 'tree_id', + additionalFields: const [ + 'id', + 'created_at', + 'updated_at', + 'tree_id', + 'common_name' + ], + trampoline: trampoline); + } + + @override + final TreeQueryValues values = TreeQueryValues(); + + TreeQueryWhere _where; + + FruitQuery _fruits; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'trees'; + } + + @override + get fields { + return const ['id', 'created_at', 'updated_at', 'rings']; + } + + @override + TreeQueryWhere get where { + return _where; + } + + @override + TreeQueryWhere newWhereClause() { + return TreeQueryWhere(this); + } + + static Tree parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Tree( + id: row[0].toString(), + createdAt: (row[1] as DateTime), + updatedAt: (row[2] as DateTime), + rings: (row[3] as int)); + if (row.length > 4) { + model = model.copyWith( + fruits: [FruitQuery.parseRow(row.skip(4).take(5).toList())] + .where((x) => x != null) + .toList()); + } + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } + + FruitQuery get fruits { + return _fruits; + } + + @override + get(QueryExecutor executor) { + return super.get(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.id == model.id); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + fruits: List<_Fruit>.from(l.fruits ?? []) + ..addAll(model.fruits ?? [])); + } + }); + }); + } + + @override + update(QueryExecutor executor) { + return super.update(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.id == model.id); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + fruits: List<_Fruit>.from(l.fruits ?? []) + ..addAll(model.fruits ?? [])); + } + }); + }); + } + + @override + delete(QueryExecutor executor) { + return super.delete(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.id == model.id); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + fruits: List<_Fruit>.from(l.fruits ?? []) + ..addAll(model.fruits ?? [])); + } + }); + }); + } +} + +class TreeQueryWhere extends QueryWhere { + TreeQueryWhere(TreeQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), + rings = NumericSqlExpressionBuilder(query, 'rings'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final NumericSqlExpressionBuilder rings; + + @override + get expressionBuilders { + return [id, createdAt, updatedAt, rings]; + } +} + +class TreeQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + int get rings { + return (values['rings'] as int); + } + + set rings(int value) => values['rings'] = value; + void copyFrom(Tree model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + rings = model.rings; + } +} + +class FruitQuery extends Query { + FruitQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = FruitQueryWhere(this); + } + + @override + final FruitQueryValues values = FruitQueryValues(); + + FruitQueryWhere _where; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'fruits'; + } + + @override + get fields { + return const ['id', 'created_at', 'updated_at', 'tree_id', 'common_name']; + } + + @override + FruitQueryWhere get where { + return _where; + } + + @override + FruitQueryWhere newWhereClause() { + return FruitQueryWhere(this); + } + + static Fruit parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Fruit( + id: row[0].toString(), + createdAt: (row[1] as DateTime), + updatedAt: (row[2] as DateTime), + treeId: (row[3] as int), + commonName: (row[4] as String)); + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } +} + +class FruitQueryWhere extends QueryWhere { + FruitQueryWhere(FruitQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), + treeId = NumericSqlExpressionBuilder(query, 'tree_id'), + commonName = StringSqlExpressionBuilder(query, 'common_name'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final NumericSqlExpressionBuilder treeId; + + final StringSqlExpressionBuilder commonName; + + @override + get expressionBuilders { + return [id, createdAt, updatedAt, treeId, commonName]; + } +} + +class FruitQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + int get treeId { + return (values['tree_id'] as int); + } + + set treeId(int value) => values['tree_id'] = value; + String get commonName { + return (values['common_name'] as String); + } + + set commonName(String value) => values['common_name'] = value; + void copyFrom(Fruit model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + treeId = model.treeId; + commonName = model.commonName; + } +} + +// ************************************************************************** +// JsonModelGenerator +// ************************************************************************** + +@generatedSerializable +class Tree extends _Tree { + Tree( + {this.id, + this.createdAt, + this.updatedAt, + this.rings, + List<_Fruit> fruits}) + : this.fruits = List.unmodifiable(fruits ?? []); + + /// A unique identifier corresponding to this item. + @override + String id; + + /// The time at which this item was created. + @override + DateTime createdAt; + + /// The last time at which this item was updated. + @override + DateTime updatedAt; + + @override + int rings; + + @override + List<_Fruit> fruits; + + Tree copyWith( + {String id, + DateTime createdAt, + DateTime updatedAt, + int rings, + List<_Fruit> fruits}) { + return Tree( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + rings: rings ?? this.rings, + fruits: fruits ?? this.fruits); + } + + bool operator ==(other) { + return other is _Tree && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.rings == rings && + ListEquality<_Fruit>(DefaultEquality<_Fruit>()) + .equals(other.fruits, fruits); + } + + @override + int get hashCode { + return hashObjects([id, createdAt, updatedAt, rings, fruits]); + } + + @override + String toString() { + return "Tree(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, rings=$rings, fruits=$fruits)"; + } + + Map toJson() { + return TreeSerializer.toMap(this); + } +} + +@generatedSerializable +class Fruit extends _Fruit { + Fruit( + {this.id, this.createdAt, this.updatedAt, this.treeId, this.commonName}); + + /// A unique identifier corresponding to this item. + @override + String id; + + /// The time at which this item was created. + @override + DateTime createdAt; + + /// The last time at which this item was updated. + @override + DateTime updatedAt; + + @override + int treeId; + + @override + String commonName; + + Fruit copyWith( + {String id, + DateTime createdAt, + DateTime updatedAt, + int treeId, + String commonName}) { + return Fruit( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + treeId: treeId ?? this.treeId, + commonName: commonName ?? this.commonName); + } + + bool operator ==(other) { + return other is _Fruit && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.treeId == treeId && + other.commonName == commonName; + } + + @override + int get hashCode { + return hashObjects([id, createdAt, updatedAt, treeId, commonName]); + } + + @override + String toString() { + return "Fruit(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, treeId=$treeId, commonName=$commonName)"; + } + + Map toJson() { + return FruitSerializer.toMap(this); + } +} + +// ************************************************************************** +// SerializerGenerator +// ************************************************************************** + +const TreeSerializer treeSerializer = TreeSerializer(); + +class TreeEncoder extends Converter { + const TreeEncoder(); + + @override + Map convert(Tree model) => TreeSerializer.toMap(model); +} + +class TreeDecoder extends Converter { + const TreeDecoder(); + + @override + Tree convert(Map map) => TreeSerializer.fromMap(map); +} + +class TreeSerializer extends Codec { + const TreeSerializer(); + + @override + get encoder => const TreeEncoder(); + @override + get decoder => const TreeDecoder(); + static Tree fromMap(Map map) { + return Tree( + id: map['id'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null, + rings: map['rings'] as int, + fruits: map['fruits'] is Iterable + ? List.unmodifiable(((map['fruits'] as Iterable).whereType()) + .map(FruitSerializer.fromMap)) + : null); + } + + static Map toMap(_Tree model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String(), + 'rings': model.rings, + 'fruits': model.fruits?.map((m) => FruitSerializer.toMap(m))?.toList() + }; + } +} + +abstract class TreeFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + rings, + fruits + ]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; + + static const String rings = 'rings'; + + static const String fruits = 'fruits'; +} + +const FruitSerializer fruitSerializer = FruitSerializer(); + +class FruitEncoder extends Converter { + const FruitEncoder(); + + @override + Map convert(Fruit model) => FruitSerializer.toMap(model); +} + +class FruitDecoder extends Converter { + const FruitDecoder(); + + @override + Fruit convert(Map map) => FruitSerializer.fromMap(map); +} + +class FruitSerializer extends Codec { + const FruitSerializer(); + + @override + get encoder => const FruitEncoder(); + @override + get decoder => const FruitDecoder(); + static Fruit fromMap(Map map) { + return Fruit( + id: map['id'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null, + treeId: map['tree_id'] as int, + commonName: map['common_name'] as String); + } + + static Map toMap(_Fruit model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String(), + 'tree_id': model.treeId, + 'common_name': model.commonName + }; + } +} + +abstract class FruitFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + treeId, + commonName + ]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; + + static const String treeId = 'tree_id'; + + static const String commonName = 'common_name'; +} diff --git a/angel_orm_test/lib/src/models/unorthodox.g.dart b/angel_orm_test/lib/src/models/unorthodox.g.dart new file mode 100644 index 00000000..558674e0 --- /dev/null +++ b/angel_orm_test/lib/src/models/unorthodox.g.dart @@ -0,0 +1,1481 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'unorthodox.dart'; + +// ************************************************************************** +// MigrationGenerator +// ************************************************************************** + +class UnorthodoxMigration extends Migration { + @override + up(Schema schema) { + schema.create('unorthodoxes', (table) { + table.varChar('name'); + }); + } + + @override + down(Schema schema) { + schema.drop('unorthodoxes'); + } +} + +class WeirdJoinMigration extends Migration { + @override + up(Schema schema) { + schema.create('weird_joins', (table) { + table.integer('id')..primaryKey(); + table + .declare('join_name', ColumnType('varchar')) + .references('unorthodoxes', 'name'); + }); + } + + @override + down(Schema schema) { + schema.drop('weird_joins', cascade: true); + } +} + +class SongMigration extends Migration { + @override + up(Schema schema) { + schema.create('songs', (table) { + table.serial('id')..primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.integer('weird_join_id'); + table.varChar('title'); + }); + } + + @override + down(Schema schema) { + schema.drop('songs'); + } +} + +class NumbaMigration extends Migration { + @override + up(Schema schema) { + schema.create('numbas', (table) { + table.integer('i')..primaryKey(); + table.integer('parent'); + }); + } + + @override + down(Schema schema) { + schema.drop('numbas'); + } +} + +class FooMigration extends Migration { + @override + up(Schema schema) { + schema.create('foos', (table) { + table.varChar('bar')..primaryKey(); + }); + } + + @override + down(Schema schema) { + schema.drop('foos', cascade: true); + } +} + +class FooPivotMigration extends Migration { + @override + up(Schema schema) { + schema.create('foo_pivots', (table) { + table + .declare('weird_join_id', ColumnType('int')) + .references('weird_joins', 'id'); + table.declare('foo_bar', ColumnType('varchar')).references('foos', 'bar'); + }); + } + + @override + down(Schema schema) { + schema.drop('foo_pivots'); + } +} + +// ************************************************************************** +// OrmGenerator +// ************************************************************************** + +class UnorthodoxQuery extends Query { + UnorthodoxQuery({Query parent, Set trampoline}) + : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = UnorthodoxQueryWhere(this); + } + + @override + final UnorthodoxQueryValues values = UnorthodoxQueryValues(); + + UnorthodoxQueryWhere _where; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'unorthodoxes'; + } + + @override + get fields { + return const ['name']; + } + + @override + UnorthodoxQueryWhere get where { + return _where; + } + + @override + UnorthodoxQueryWhere newWhereClause() { + return UnorthodoxQueryWhere(this); + } + + static Unorthodox parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Unorthodox(name: (row[0] as String)); + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } +} + +class UnorthodoxQueryWhere extends QueryWhere { + UnorthodoxQueryWhere(UnorthodoxQuery query) + : name = StringSqlExpressionBuilder(query, 'name'); + + final StringSqlExpressionBuilder name; + + @override + get expressionBuilders { + return [name]; + } +} + +class UnorthodoxQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get name { + return (values['name'] as String); + } + + set name(String value) => values['name'] = value; + void copyFrom(Unorthodox model) { + name = model.name; + } +} + +class WeirdJoinQuery extends Query { + WeirdJoinQuery({Query parent, Set trampoline}) + : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = WeirdJoinQueryWhere(this); + leftJoin( + _unorthodox = UnorthodoxQuery(trampoline: trampoline, parent: this), + 'join_name', + 'name', + additionalFields: const ['name'], + trampoline: trampoline); + leftJoin(_song = SongQuery(trampoline: trampoline, parent: this), 'id', + 'weird_join_id', + additionalFields: const [ + 'id', + 'created_at', + 'updated_at', + 'weird_join_id', + 'title' + ], + trampoline: trampoline); + leftJoin(_numbas = NumbaQuery(trampoline: trampoline, parent: this), 'id', + 'parent', + additionalFields: const ['i', 'parent'], trampoline: trampoline); + leftJoin(_foos = FooPivotQuery(trampoline: trampoline, parent: this), 'id', + 'weird_join_id', + additionalFields: const ['bar'], trampoline: trampoline); + } + + @override + final WeirdJoinQueryValues values = WeirdJoinQueryValues(); + + WeirdJoinQueryWhere _where; + + UnorthodoxQuery _unorthodox; + + SongQuery _song; + + NumbaQuery _numbas; + + FooPivotQuery _foos; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'weird_joins'; + } + + @override + get fields { + return const ['id', 'join_name']; + } + + @override + WeirdJoinQueryWhere get where { + return _where; + } + + @override + WeirdJoinQueryWhere newWhereClause() { + return WeirdJoinQueryWhere(this); + } + + static WeirdJoin parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = WeirdJoin(id: (row[0] as int)); + if (row.length > 2) { + model = model.copyWith( + unorthodox: UnorthodoxQuery.parseRow(row.skip(2).take(1).toList())); + } + if (row.length > 3) { + model = model.copyWith( + song: SongQuery.parseRow(row.skip(3).take(5).toList())); + } + if (row.length > 8) { + model = model.copyWith( + numbas: [NumbaQuery.parseRow(row.skip(8).take(2).toList())] + .where((x) => x != null) + .toList()); + } + if (row.length > 10) { + model = model.copyWith( + foos: [FooQuery.parseRow(row.skip(10).take(1).toList())] + .where((x) => x != null) + .toList()); + } + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } + + UnorthodoxQuery get unorthodox { + return _unorthodox; + } + + SongQuery get song { + return _song; + } + + NumbaQuery get numbas { + return _numbas; + } + + FooPivotQuery get foos { + return _foos; + } + + @override + bool canCompile(trampoline) { + return (!(trampoline.contains('weird_joins') && + trampoline.contains('foo_pivots'))); + } + + @override + get(QueryExecutor executor) { + return super.get(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.id == model.id); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + numbas: List<_Numba>.from(l.numbas ?? []) + ..addAll(model.numbas ?? []), + foos: List<_Foo>.from(l.foos ?? [])..addAll(model.foos ?? [])); + } + }); + }); + } + + @override + update(QueryExecutor executor) { + return super.update(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.id == model.id); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + numbas: List<_Numba>.from(l.numbas ?? []) + ..addAll(model.numbas ?? []), + foos: List<_Foo>.from(l.foos ?? [])..addAll(model.foos ?? [])); + } + }); + }); + } + + @override + delete(QueryExecutor executor) { + return super.delete(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.id == model.id); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + numbas: List<_Numba>.from(l.numbas ?? []) + ..addAll(model.numbas ?? []), + foos: List<_Foo>.from(l.foos ?? [])..addAll(model.foos ?? [])); + } + }); + }); + } +} + +class WeirdJoinQueryWhere extends QueryWhere { + WeirdJoinQueryWhere(WeirdJoinQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + joinName = StringSqlExpressionBuilder(query, 'join_name'); + + final NumericSqlExpressionBuilder id; + + final StringSqlExpressionBuilder joinName; + + @override + get expressionBuilders { + return [id, joinName]; + } +} + +class WeirdJoinQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + int get id { + return (values['id'] as int); + } + + set id(int value) => values['id'] = value; + String get joinName { + return (values['join_name'] as String); + } + + set joinName(String value) => values['join_name'] = value; + void copyFrom(WeirdJoin model) { + id = model.id; + if (model.unorthodox != null) { + values['join_name'] = model.unorthodox.name; + } + } +} + +class SongQuery extends Query { + SongQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = SongQueryWhere(this); + } + + @override + final SongQueryValues values = SongQueryValues(); + + SongQueryWhere _where; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'songs'; + } + + @override + get fields { + return const ['id', 'created_at', 'updated_at', 'weird_join_id', 'title']; + } + + @override + SongQueryWhere get where { + return _where; + } + + @override + SongQueryWhere newWhereClause() { + return SongQueryWhere(this); + } + + static Song parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Song( + id: row[0].toString(), + createdAt: (row[1] as DateTime), + updatedAt: (row[2] as DateTime), + weirdJoinId: (row[3] as int), + title: (row[4] as String)); + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } +} + +class SongQueryWhere extends QueryWhere { + SongQueryWhere(SongQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), + weirdJoinId = NumericSqlExpressionBuilder(query, 'weird_join_id'), + title = StringSqlExpressionBuilder(query, 'title'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final NumericSqlExpressionBuilder weirdJoinId; + + final StringSqlExpressionBuilder title; + + @override + get expressionBuilders { + return [id, createdAt, updatedAt, weirdJoinId, title]; + } +} + +class SongQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + int get weirdJoinId { + return (values['weird_join_id'] as int); + } + + set weirdJoinId(int value) => values['weird_join_id'] = value; + String get title { + return (values['title'] as String); + } + + set title(String value) => values['title'] = value; + void copyFrom(Song model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + weirdJoinId = model.weirdJoinId; + title = model.title; + } +} + +class NumbaQuery extends Query { + NumbaQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = NumbaQueryWhere(this); + } + + @override + final NumbaQueryValues values = NumbaQueryValues(); + + NumbaQueryWhere _where; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'numbas'; + } + + @override + get fields { + return const ['i', 'parent']; + } + + @override + NumbaQueryWhere get where { + return _where; + } + + @override + NumbaQueryWhere newWhereClause() { + return NumbaQueryWhere(this); + } + + static Numba parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Numba(i: (row[0] as int), parent: (row[1] as int)); + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } +} + +class NumbaQueryWhere extends QueryWhere { + NumbaQueryWhere(NumbaQuery query) + : i = NumericSqlExpressionBuilder(query, 'i'), + parent = NumericSqlExpressionBuilder(query, 'parent'); + + final NumericSqlExpressionBuilder i; + + final NumericSqlExpressionBuilder parent; + + @override + get expressionBuilders { + return [i, parent]; + } +} + +class NumbaQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + int get i { + return (values['i'] as int); + } + + set i(int value) => values['i'] = value; + int get parent { + return (values['parent'] as int); + } + + set parent(int value) => values['parent'] = value; + void copyFrom(Numba model) { + i = model.i; + parent = model.parent; + } +} + +class FooQuery extends Query { + FooQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = FooQueryWhere(this); + leftJoin(_weirdJoins = FooPivotQuery(trampoline: trampoline, parent: this), + 'bar', 'foo_bar', + additionalFields: const ['id', 'join_name'], trampoline: trampoline); + } + + @override + final FooQueryValues values = FooQueryValues(); + + FooQueryWhere _where; + + FooPivotQuery _weirdJoins; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'foos'; + } + + @override + get fields { + return const ['bar']; + } + + @override + FooQueryWhere get where { + return _where; + } + + @override + FooQueryWhere newWhereClause() { + return FooQueryWhere(this); + } + + static Foo parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Foo(bar: (row[0] as String)); + if (row.length > 1) { + model = model.copyWith( + weirdJoins: [WeirdJoinQuery.parseRow(row.skip(1).take(2).toList())] + .where((x) => x != null) + .toList()); + } + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } + + FooPivotQuery get weirdJoins { + return _weirdJoins; + } + + @override + bool canCompile(trampoline) { + return (!(trampoline.contains('foos') && + trampoline.contains('foo_pivots'))); + } + + @override + get(QueryExecutor executor) { + return super.get(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.bar == model.bar); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + weirdJoins: List<_WeirdJoin>.from(l.weirdJoins ?? []) + ..addAll(model.weirdJoins ?? [])); + } + }); + }); + } + + @override + update(QueryExecutor executor) { + return super.update(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.bar == model.bar); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + weirdJoins: List<_WeirdJoin>.from(l.weirdJoins ?? []) + ..addAll(model.weirdJoins ?? [])); + } + }); + }); + } + + @override + delete(QueryExecutor executor) { + return super.delete(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.bar == model.bar); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + weirdJoins: List<_WeirdJoin>.from(l.weirdJoins ?? []) + ..addAll(model.weirdJoins ?? [])); + } + }); + }); + } +} + +class FooQueryWhere extends QueryWhere { + FooQueryWhere(FooQuery query) + : bar = StringSqlExpressionBuilder(query, 'bar'); + + final StringSqlExpressionBuilder bar; + + @override + get expressionBuilders { + return [bar]; + } +} + +class FooQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get bar { + return (values['bar'] as String); + } + + set bar(String value) => values['bar'] = value; + void copyFrom(Foo model) { + bar = model.bar; + } +} + +class FooPivotQuery extends Query { + FooPivotQuery({Query parent, Set trampoline}) + : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = FooPivotQueryWhere(this); + leftJoin(_weirdJoin = WeirdJoinQuery(trampoline: trampoline, parent: this), + 'weird_join_id', 'id', + additionalFields: const ['id', 'join_name'], trampoline: trampoline); + leftJoin( + _foo = FooQuery(trampoline: trampoline, parent: this), 'foo_bar', 'bar', + additionalFields: const ['bar'], trampoline: trampoline); + } + + @override + final FooPivotQueryValues values = FooPivotQueryValues(); + + FooPivotQueryWhere _where; + + WeirdJoinQuery _weirdJoin; + + FooQuery _foo; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'foo_pivots'; + } + + @override + get fields { + return const ['weird_join_id', 'foo_bar']; + } + + @override + FooPivotQueryWhere get where { + return _where; + } + + @override + FooPivotQueryWhere newWhereClause() { + return FooPivotQueryWhere(this); + } + + static FooPivot parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = FooPivot(); + if (row.length > 2) { + model = model.copyWith( + weirdJoin: WeirdJoinQuery.parseRow(row.skip(2).take(2).toList())); + } + if (row.length > 4) { + model = + model.copyWith(foo: FooQuery.parseRow(row.skip(4).take(1).toList())); + } + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } + + WeirdJoinQuery get weirdJoin { + return _weirdJoin; + } + + FooQuery get foo { + return _foo; + } +} + +class FooPivotQueryWhere extends QueryWhere { + FooPivotQueryWhere(FooPivotQuery query) + : weirdJoinId = NumericSqlExpressionBuilder(query, 'weird_join_id'), + fooBar = StringSqlExpressionBuilder(query, 'foo_bar'); + + final NumericSqlExpressionBuilder weirdJoinId; + + final StringSqlExpressionBuilder fooBar; + + @override + get expressionBuilders { + return [weirdJoinId, fooBar]; + } +} + +class FooPivotQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + int get weirdJoinId { + return (values['weird_join_id'] as int); + } + + set weirdJoinId(int value) => values['weird_join_id'] = value; + String get fooBar { + return (values['foo_bar'] as String); + } + + set fooBar(String value) => values['foo_bar'] = value; + void copyFrom(FooPivot model) { + if (model.weirdJoin != null) { + values['weird_join_id'] = model.weirdJoin.id; + } + if (model.foo != null) { + values['foo_bar'] = model.foo.bar; + } + } +} + +// ************************************************************************** +// JsonModelGenerator +// ************************************************************************** + +@generatedSerializable +class Unorthodox implements _Unorthodox { + const Unorthodox({this.name}); + + @override + final String name; + + Unorthodox copyWith({String name}) { + return Unorthodox(name: name ?? this.name); + } + + bool operator ==(other) { + return other is _Unorthodox && other.name == name; + } + + @override + int get hashCode { + return hashObjects([name]); + } + + @override + String toString() { + return "Unorthodox(name=$name)"; + } + + Map toJson() { + return UnorthodoxSerializer.toMap(this); + } +} + +@generatedSerializable +class WeirdJoin implements _WeirdJoin { + const WeirdJoin( + {this.id, this.unorthodox, this.song, this.numbas, this.foos}); + + @override + final int id; + + @override + final _Unorthodox unorthodox; + + @override + final _Song song; + + @override + final List<_Numba> numbas; + + @override + final List<_Foo> foos; + + WeirdJoin copyWith( + {int id, + _Unorthodox unorthodox, + _Song song, + List<_Numba> numbas, + List<_Foo> foos}) { + return WeirdJoin( + id: id ?? this.id, + unorthodox: unorthodox ?? this.unorthodox, + song: song ?? this.song, + numbas: numbas ?? this.numbas, + foos: foos ?? this.foos); + } + + bool operator ==(other) { + return other is _WeirdJoin && + other.id == id && + other.unorthodox == unorthodox && + other.song == song && + ListEquality<_Numba>(DefaultEquality<_Numba>()) + .equals(other.numbas, numbas) && + ListEquality<_Foo>(DefaultEquality<_Foo>()).equals(other.foos, foos); + } + + @override + int get hashCode { + return hashObjects([id, unorthodox, song, numbas, foos]); + } + + @override + String toString() { + return "WeirdJoin(id=$id, unorthodox=$unorthodox, song=$song, numbas=$numbas, foos=$foos)"; + } + + Map toJson() { + return WeirdJoinSerializer.toMap(this); + } +} + +@generatedSerializable +class Song extends _Song { + Song({this.id, this.createdAt, this.updatedAt, this.weirdJoinId, this.title}); + + /// A unique identifier corresponding to this item. + @override + String id; + + /// The time at which this item was created. + @override + DateTime createdAt; + + /// The last time at which this item was updated. + @override + DateTime updatedAt; + + @override + final int weirdJoinId; + + @override + final String title; + + Song copyWith( + {String id, + DateTime createdAt, + DateTime updatedAt, + int weirdJoinId, + String title}) { + return Song( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + weirdJoinId: weirdJoinId ?? this.weirdJoinId, + title: title ?? this.title); + } + + bool operator ==(other) { + return other is _Song && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.weirdJoinId == weirdJoinId && + other.title == title; + } + + @override + int get hashCode { + return hashObjects([id, createdAt, updatedAt, weirdJoinId, title]); + } + + @override + String toString() { + return "Song(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, weirdJoinId=$weirdJoinId, title=$title)"; + } + + Map toJson() { + return SongSerializer.toMap(this); + } +} + +@generatedSerializable +class Numba extends _Numba { + Numba({this.i, this.parent}); + + @override + int i; + + @override + int parent; + + Numba copyWith({int i, int parent}) { + return Numba(i: i ?? this.i, parent: parent ?? this.parent); + } + + bool operator ==(other) { + return other is _Numba && other.i == i && other.parent == parent; + } + + @override + int get hashCode { + return hashObjects([i, parent]); + } + + @override + String toString() { + return "Numba(i=$i, parent=$parent)"; + } + + Map toJson() { + return NumbaSerializer.toMap(this); + } +} + +@generatedSerializable +class Foo implements _Foo { + const Foo({this.bar, this.weirdJoins}); + + @override + final String bar; + + @override + final List<_WeirdJoin> weirdJoins; + + Foo copyWith({String bar, List<_WeirdJoin> weirdJoins}) { + return Foo(bar: bar ?? this.bar, weirdJoins: weirdJoins ?? this.weirdJoins); + } + + bool operator ==(other) { + return other is _Foo && + other.bar == bar && + ListEquality<_WeirdJoin>(DefaultEquality<_WeirdJoin>()) + .equals(other.weirdJoins, weirdJoins); + } + + @override + int get hashCode { + return hashObjects([bar, weirdJoins]); + } + + @override + String toString() { + return "Foo(bar=$bar, weirdJoins=$weirdJoins)"; + } + + Map toJson() { + return FooSerializer.toMap(this); + } +} + +@generatedSerializable +class FooPivot implements _FooPivot { + const FooPivot({this.weirdJoin, this.foo}); + + @override + final _WeirdJoin weirdJoin; + + @override + final _Foo foo; + + FooPivot copyWith({_WeirdJoin weirdJoin, _Foo foo}) { + return FooPivot( + weirdJoin: weirdJoin ?? this.weirdJoin, foo: foo ?? this.foo); + } + + bool operator ==(other) { + return other is _FooPivot && + other.weirdJoin == weirdJoin && + other.foo == foo; + } + + @override + int get hashCode { + return hashObjects([weirdJoin, foo]); + } + + @override + String toString() { + return "FooPivot(weirdJoin=$weirdJoin, foo=$foo)"; + } + + Map toJson() { + return FooPivotSerializer.toMap(this); + } +} + +// ************************************************************************** +// SerializerGenerator +// ************************************************************************** + +const UnorthodoxSerializer unorthodoxSerializer = UnorthodoxSerializer(); + +class UnorthodoxEncoder extends Converter { + const UnorthodoxEncoder(); + + @override + Map convert(Unorthodox model) => UnorthodoxSerializer.toMap(model); +} + +class UnorthodoxDecoder extends Converter { + const UnorthodoxDecoder(); + + @override + Unorthodox convert(Map map) => UnorthodoxSerializer.fromMap(map); +} + +class UnorthodoxSerializer extends Codec { + const UnorthodoxSerializer(); + + @override + get encoder => const UnorthodoxEncoder(); + @override + get decoder => const UnorthodoxDecoder(); + static Unorthodox fromMap(Map map) { + return Unorthodox(name: map['name'] as String); + } + + static Map toMap(_Unorthodox model) { + if (model == null) { + return null; + } + return {'name': model.name}; + } +} + +abstract class UnorthodoxFields { + static const List allFields = [name]; + + static const String name = 'name'; +} + +const WeirdJoinSerializer weirdJoinSerializer = WeirdJoinSerializer(); + +class WeirdJoinEncoder extends Converter { + const WeirdJoinEncoder(); + + @override + Map convert(WeirdJoin model) => WeirdJoinSerializer.toMap(model); +} + +class WeirdJoinDecoder extends Converter { + const WeirdJoinDecoder(); + + @override + WeirdJoin convert(Map map) => WeirdJoinSerializer.fromMap(map); +} + +class WeirdJoinSerializer extends Codec { + const WeirdJoinSerializer(); + + @override + get encoder => const WeirdJoinEncoder(); + @override + get decoder => const WeirdJoinDecoder(); + static WeirdJoin fromMap(Map map) { + return WeirdJoin( + id: map['id'] as int, + unorthodox: map['unorthodox'] != null + ? UnorthodoxSerializer.fromMap(map['unorthodox'] as Map) + : null, + song: map['song'] != null + ? SongSerializer.fromMap(map['song'] as Map) + : null, + numbas: map['numbas'] is Iterable + ? List.unmodifiable(((map['numbas'] as Iterable).whereType()) + .map(NumbaSerializer.fromMap)) + : null, + foos: map['foos'] is Iterable + ? List.unmodifiable(((map['foos'] as Iterable).whereType()) + .map(FooSerializer.fromMap)) + : null); + } + + static Map toMap(_WeirdJoin model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'unorthodox': UnorthodoxSerializer.toMap(model.unorthodox), + 'song': SongSerializer.toMap(model.song), + 'numbas': model.numbas?.map((m) => NumbaSerializer.toMap(m))?.toList(), + 'foos': model.foos?.map((m) => FooSerializer.toMap(m))?.toList() + }; + } +} + +abstract class WeirdJoinFields { + static const List allFields = [ + id, + unorthodox, + song, + numbas, + foos + ]; + + static const String id = 'id'; + + static const String unorthodox = 'unorthodox'; + + static const String song = 'song'; + + static const String numbas = 'numbas'; + + static const String foos = 'foos'; +} + +const SongSerializer songSerializer = SongSerializer(); + +class SongEncoder extends Converter { + const SongEncoder(); + + @override + Map convert(Song model) => SongSerializer.toMap(model); +} + +class SongDecoder extends Converter { + const SongDecoder(); + + @override + Song convert(Map map) => SongSerializer.fromMap(map); +} + +class SongSerializer extends Codec { + const SongSerializer(); + + @override + get encoder => const SongEncoder(); + @override + get decoder => const SongDecoder(); + static Song fromMap(Map map) { + return Song( + id: map['id'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null, + weirdJoinId: map['weird_join_id'] as int, + title: map['title'] as String); + } + + static Map toMap(_Song model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String(), + 'weird_join_id': model.weirdJoinId, + 'title': model.title + }; + } +} + +abstract class SongFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + weirdJoinId, + title + ]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; + + static const String weirdJoinId = 'weird_join_id'; + + static const String title = 'title'; +} + +const NumbaSerializer numbaSerializer = NumbaSerializer(); + +class NumbaEncoder extends Converter { + const NumbaEncoder(); + + @override + Map convert(Numba model) => NumbaSerializer.toMap(model); +} + +class NumbaDecoder extends Converter { + const NumbaDecoder(); + + @override + Numba convert(Map map) => NumbaSerializer.fromMap(map); +} + +class NumbaSerializer extends Codec { + const NumbaSerializer(); + + @override + get encoder => const NumbaEncoder(); + @override + get decoder => const NumbaDecoder(); + static Numba fromMap(Map map) { + return Numba(i: map['i'] as int, parent: map['parent'] as int); + } + + static Map toMap(_Numba model) { + if (model == null) { + return null; + } + return {'i': model.i, 'parent': model.parent}; + } +} + +abstract class NumbaFields { + static const List allFields = [i, parent]; + + static const String i = 'i'; + + static const String parent = 'parent'; +} + +const FooSerializer fooSerializer = FooSerializer(); + +class FooEncoder extends Converter { + const FooEncoder(); + + @override + Map convert(Foo model) => FooSerializer.toMap(model); +} + +class FooDecoder extends Converter { + const FooDecoder(); + + @override + Foo convert(Map map) => FooSerializer.fromMap(map); +} + +class FooSerializer extends Codec { + const FooSerializer(); + + @override + get encoder => const FooEncoder(); + @override + get decoder => const FooDecoder(); + static Foo fromMap(Map map) { + return Foo( + bar: map['bar'] as String, + weirdJoins: map['weird_joins'] is Iterable + ? List.unmodifiable( + ((map['weird_joins'] as Iterable).whereType()) + .map(WeirdJoinSerializer.fromMap)) + : null); + } + + static Map toMap(_Foo model) { + if (model == null) { + return null; + } + return { + 'bar': model.bar, + 'weird_joins': + model.weirdJoins?.map((m) => WeirdJoinSerializer.toMap(m))?.toList() + }; + } +} + +abstract class FooFields { + static const List allFields = [bar, weirdJoins]; + + static const String bar = 'bar'; + + static const String weirdJoins = 'weird_joins'; +} + +const FooPivotSerializer fooPivotSerializer = FooPivotSerializer(); + +class FooPivotEncoder extends Converter { + const FooPivotEncoder(); + + @override + Map convert(FooPivot model) => FooPivotSerializer.toMap(model); +} + +class FooPivotDecoder extends Converter { + const FooPivotDecoder(); + + @override + FooPivot convert(Map map) => FooPivotSerializer.fromMap(map); +} + +class FooPivotSerializer extends Codec { + const FooPivotSerializer(); + + @override + get encoder => const FooPivotEncoder(); + @override + get decoder => const FooPivotDecoder(); + static FooPivot fromMap(Map map) { + return FooPivot( + weirdJoin: map['weird_join'] != null + ? WeirdJoinSerializer.fromMap(map['weird_join'] as Map) + : null, + foo: map['foo'] != null + ? FooSerializer.fromMap(map['foo'] as Map) + : null); + } + + static Map toMap(_FooPivot model) { + if (model == null) { + return null; + } + return { + 'weird_join': WeirdJoinSerializer.toMap(model.weirdJoin), + 'foo': FooSerializer.toMap(model.foo) + }; + } +} + +abstract class FooPivotFields { + static const List allFields = [weirdJoin, foo]; + + static const String weirdJoin = 'weird_join'; + + static const String foo = 'foo'; +} diff --git a/angel_orm_test/lib/src/models/user.g.dart b/angel_orm_test/lib/src/models/user.g.dart new file mode 100644 index 00000000..5bcad71f --- /dev/null +++ b/angel_orm_test/lib/src/models/user.g.dart @@ -0,0 +1,995 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of angel_orm_generator.test.models.user; + +// ************************************************************************** +// MigrationGenerator +// ************************************************************************** + +class UserMigration extends Migration { + @override + up(Schema schema) { + schema.create('users', (table) { + table.serial('id')..primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.varChar('username'); + table.varChar('password'); + table.varChar('email'); + }); + } + + @override + down(Schema schema) { + schema.drop('users', cascade: true); + } +} + +class RoleUserMigration extends Migration { + @override + up(Schema schema) { + schema.create('role_users', (table) { + table.declare('role_id', ColumnType('serial')).references('roles', 'id'); + table.declare('user_id', ColumnType('serial')).references('users', 'id'); + }); + } + + @override + down(Schema schema) { + schema.drop('role_users'); + } +} + +class RoleMigration extends Migration { + @override + up(Schema schema) { + schema.create('roles', (table) { + table.serial('id')..primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.varChar('name'); + }); + } + + @override + down(Schema schema) { + schema.drop('roles', cascade: true); + } +} + +// ************************************************************************** +// OrmGenerator +// ************************************************************************** + +class UserQuery extends Query { + UserQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = UserQueryWhere(this); + leftJoin(_roles = RoleUserQuery(trampoline: trampoline, parent: this), 'id', + 'user_id', + additionalFields: const ['id', 'created_at', 'updated_at', 'name'], + trampoline: trampoline); + } + + @override + final UserQueryValues values = UserQueryValues(); + + UserQueryWhere _where; + + RoleUserQuery _roles; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'users'; + } + + @override + get fields { + return const [ + 'id', + 'created_at', + 'updated_at', + 'username', + 'password', + 'email' + ]; + } + + @override + UserQueryWhere get where { + return _where; + } + + @override + UserQueryWhere newWhereClause() { + return UserQueryWhere(this); + } + + static User parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = User( + id: row[0].toString(), + createdAt: (row[1] as DateTime), + updatedAt: (row[2] as DateTime), + username: (row[3] as String), + password: (row[4] as String), + email: (row[5] as String)); + if (row.length > 6) { + model = model.copyWith( + roles: [RoleQuery.parseRow(row.skip(6).take(4).toList())] + .where((x) => x != null) + .toList()); + } + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } + + RoleUserQuery get roles { + return _roles; + } + + @override + bool canCompile(trampoline) { + return (!(trampoline.contains('users') && + trampoline.contains('role_users'))); + } + + @override + get(QueryExecutor executor) { + return super.get(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.id == model.id); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + roles: List<_Role>.from(l.roles ?? []) + ..addAll(model.roles ?? [])); + } + }); + }); + } + + @override + update(QueryExecutor executor) { + return super.update(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.id == model.id); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + roles: List<_Role>.from(l.roles ?? []) + ..addAll(model.roles ?? [])); + } + }); + }); + } + + @override + delete(QueryExecutor executor) { + return super.delete(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.id == model.id); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + roles: List<_Role>.from(l.roles ?? []) + ..addAll(model.roles ?? [])); + } + }); + }); + } +} + +class UserQueryWhere extends QueryWhere { + UserQueryWhere(UserQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), + username = StringSqlExpressionBuilder(query, 'username'), + password = StringSqlExpressionBuilder(query, 'password'), + email = StringSqlExpressionBuilder(query, 'email'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final StringSqlExpressionBuilder username; + + final StringSqlExpressionBuilder password; + + final StringSqlExpressionBuilder email; + + @override + get expressionBuilders { + return [id, createdAt, updatedAt, username, password, email]; + } +} + +class UserQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + String get username { + return (values['username'] as String); + } + + set username(String value) => values['username'] = value; + String get password { + return (values['password'] as String); + } + + set password(String value) => values['password'] = value; + String get email { + return (values['email'] as String); + } + + set email(String value) => values['email'] = value; + void copyFrom(User model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + username = model.username; + password = model.password; + email = model.email; + } +} + +class RoleUserQuery extends Query { + RoleUserQuery({Query parent, Set trampoline}) + : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = RoleUserQueryWhere(this); + leftJoin(_role = RoleQuery(trampoline: trampoline, parent: this), 'role_id', + 'id', + additionalFields: const ['id', 'created_at', 'updated_at', 'name'], + trampoline: trampoline); + leftJoin(_user = UserQuery(trampoline: trampoline, parent: this), 'user_id', + 'id', + additionalFields: const [ + 'id', + 'created_at', + 'updated_at', + 'username', + 'password', + 'email' + ], + trampoline: trampoline); + } + + @override + final RoleUserQueryValues values = RoleUserQueryValues(); + + RoleUserQueryWhere _where; + + RoleQuery _role; + + UserQuery _user; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'role_users'; + } + + @override + get fields { + return const ['role_id', 'user_id']; + } + + @override + RoleUserQueryWhere get where { + return _where; + } + + @override + RoleUserQueryWhere newWhereClause() { + return RoleUserQueryWhere(this); + } + + static RoleUser parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = RoleUser(); + if (row.length > 2) { + model = model.copyWith( + role: RoleQuery.parseRow(row.skip(2).take(4).toList())); + } + if (row.length > 6) { + model = model.copyWith( + user: UserQuery.parseRow(row.skip(6).take(6).toList())); + } + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } + + RoleQuery get role { + return _role; + } + + UserQuery get user { + return _user; + } +} + +class RoleUserQueryWhere extends QueryWhere { + RoleUserQueryWhere(RoleUserQuery query) + : roleId = NumericSqlExpressionBuilder(query, 'role_id'), + userId = NumericSqlExpressionBuilder(query, 'user_id'); + + final NumericSqlExpressionBuilder roleId; + + final NumericSqlExpressionBuilder userId; + + @override + get expressionBuilders { + return [roleId, userId]; + } +} + +class RoleUserQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + int get roleId { + return (values['role_id'] as int); + } + + set roleId(int value) => values['role_id'] = value; + int get userId { + return (values['user_id'] as int); + } + + set userId(int value) => values['user_id'] = value; + void copyFrom(RoleUser model) { + if (model.role != null) { + values['role_id'] = model.role.id; + } + if (model.user != null) { + values['user_id'] = model.user.id; + } + } +} + +class RoleQuery extends Query { + RoleQuery({Query parent, Set trampoline}) : super(parent: parent) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = RoleQueryWhere(this); + leftJoin(_users = RoleUserQuery(trampoline: trampoline, parent: this), 'id', + 'role_id', + additionalFields: const [ + 'id', + 'created_at', + 'updated_at', + 'username', + 'password', + 'email' + ], + trampoline: trampoline); + } + + @override + final RoleQueryValues values = RoleQueryValues(); + + RoleQueryWhere _where; + + RoleUserQuery _users; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'roles'; + } + + @override + get fields { + return const ['id', 'created_at', 'updated_at', 'name']; + } + + @override + RoleQueryWhere get where { + return _where; + } + + @override + RoleQueryWhere newWhereClause() { + return RoleQueryWhere(this); + } + + static Role parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Role( + id: row[0].toString(), + createdAt: (row[1] as DateTime), + updatedAt: (row[2] as DateTime), + name: (row[3] as String)); + if (row.length > 4) { + model = model.copyWith( + users: [UserQuery.parseRow(row.skip(4).take(6).toList())] + .where((x) => x != null) + .toList()); + } + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } + + RoleUserQuery get users { + return _users; + } + + @override + bool canCompile(trampoline) { + return (!(trampoline.contains('roles') && + trampoline.contains('role_users'))); + } + + @override + get(QueryExecutor executor) { + return super.get(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.id == model.id); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + users: List<_User>.from(l.users ?? []) + ..addAll(model.users ?? [])); + } + }); + }); + } + + @override + update(QueryExecutor executor) { + return super.update(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.id == model.id); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + users: List<_User>.from(l.users ?? []) + ..addAll(model.users ?? [])); + } + }); + }); + } + + @override + delete(QueryExecutor executor) { + return super.delete(executor).then((result) { + return result.fold>([], (out, model) { + var idx = out.indexWhere((m) => m.id == model.id); + + if (idx == -1) { + return out..add(model); + } else { + var l = out[idx]; + return out + ..[idx] = l.copyWith( + users: List<_User>.from(l.users ?? []) + ..addAll(model.users ?? [])); + } + }); + }); + } +} + +class RoleQueryWhere extends QueryWhere { + RoleQueryWhere(RoleQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), + name = StringSqlExpressionBuilder(query, 'name'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final StringSqlExpressionBuilder name; + + @override + get expressionBuilders { + return [id, createdAt, updatedAt, name]; + } +} + +class RoleQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + String get name { + return (values['name'] as String); + } + + set name(String value) => values['name'] = value; + void copyFrom(Role model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + name = model.name; + } +} + +// ************************************************************************** +// JsonModelGenerator +// ************************************************************************** + +@generatedSerializable +class User extends _User { + User( + {this.id, + this.createdAt, + this.updatedAt, + this.username, + this.password, + this.email, + List<_Role> roles}) + : this.roles = List.unmodifiable(roles ?? []); + + /// A unique identifier corresponding to this item. + @override + String id; + + /// The time at which this item was created. + @override + DateTime createdAt; + + /// The last time at which this item was updated. + @override + DateTime updatedAt; + + @override + final String username; + + @override + final String password; + + @override + final String email; + + @override + final List<_Role> roles; + + User copyWith( + {String id, + DateTime createdAt, + DateTime updatedAt, + String username, + String password, + String email, + List<_Role> roles}) { + return User( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + username: username ?? this.username, + password: password ?? this.password, + email: email ?? this.email, + roles: roles ?? this.roles); + } + + bool operator ==(other) { + return other is _User && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.username == username && + other.password == password && + other.email == email && + ListEquality<_Role>(DefaultEquality<_Role>()) + .equals(other.roles, roles); + } + + @override + int get hashCode { + return hashObjects( + [id, createdAt, updatedAt, username, password, email, roles]); + } + + @override + String toString() { + return "User(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, username=$username, password=$password, email=$email, roles=$roles)"; + } + + Map toJson() { + return UserSerializer.toMap(this); + } +} + +@generatedSerializable +class RoleUser implements _RoleUser { + const RoleUser({this.role, this.user}); + + @override + final _Role role; + + @override + final _User user; + + RoleUser copyWith({_Role role, _User user}) { + return RoleUser(role: role ?? this.role, user: user ?? this.user); + } + + bool operator ==(other) { + return other is _RoleUser && other.role == role && other.user == user; + } + + @override + int get hashCode { + return hashObjects([role, user]); + } + + @override + String toString() { + return "RoleUser(role=$role, user=$user)"; + } + + Map toJson() { + return RoleUserSerializer.toMap(this); + } +} + +@generatedSerializable +class Role extends _Role { + Role({this.id, this.createdAt, this.updatedAt, this.name, List<_User> users}) + : this.users = List.unmodifiable(users ?? []); + + /// A unique identifier corresponding to this item. + @override + String id; + + /// The time at which this item was created. + @override + DateTime createdAt; + + /// The last time at which this item was updated. + @override + DateTime updatedAt; + + @override + String name; + + @override + final List<_User> users; + + Role copyWith( + {String id, + DateTime createdAt, + DateTime updatedAt, + String name, + List<_User> users}) { + return Role( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + name: name ?? this.name, + users: users ?? this.users); + } + + bool operator ==(other) { + return other is _Role && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.name == name && + ListEquality<_User>(DefaultEquality<_User>()) + .equals(other.users, users); + } + + @override + int get hashCode { + return hashObjects([id, createdAt, updatedAt, name, users]); + } + + @override + String toString() { + return "Role(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, name=$name, users=$users)"; + } + + Map toJson() { + return RoleSerializer.toMap(this); + } +} + +// ************************************************************************** +// SerializerGenerator +// ************************************************************************** + +const UserSerializer userSerializer = UserSerializer(); + +class UserEncoder extends Converter { + const UserEncoder(); + + @override + Map convert(User model) => UserSerializer.toMap(model); +} + +class UserDecoder extends Converter { + const UserDecoder(); + + @override + User convert(Map map) => UserSerializer.fromMap(map); +} + +class UserSerializer extends Codec { + const UserSerializer(); + + @override + get encoder => const UserEncoder(); + @override + get decoder => const UserDecoder(); + static User fromMap(Map map) { + return User( + id: map['id'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null, + username: map['username'] as String, + password: map['password'] as String, + email: map['email'] as String, + roles: map['roles'] is Iterable + ? List.unmodifiable(((map['roles'] as Iterable).whereType()) + .map(RoleSerializer.fromMap)) + : null); + } + + static Map toMap(_User model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String(), + 'username': model.username, + 'password': model.password, + 'email': model.email, + 'roles': model.roles?.map((m) => RoleSerializer.toMap(m))?.toList() + }; + } +} + +abstract class UserFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + username, + password, + email, + roles + ]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; + + static const String username = 'username'; + + static const String password = 'password'; + + static const String email = 'email'; + + static const String roles = 'roles'; +} + +const RoleUserSerializer roleUserSerializer = RoleUserSerializer(); + +class RoleUserEncoder extends Converter { + const RoleUserEncoder(); + + @override + Map convert(RoleUser model) => RoleUserSerializer.toMap(model); +} + +class RoleUserDecoder extends Converter { + const RoleUserDecoder(); + + @override + RoleUser convert(Map map) => RoleUserSerializer.fromMap(map); +} + +class RoleUserSerializer extends Codec { + const RoleUserSerializer(); + + @override + get encoder => const RoleUserEncoder(); + @override + get decoder => const RoleUserDecoder(); + static RoleUser fromMap(Map map) { + return RoleUser( + role: map['role'] != null + ? RoleSerializer.fromMap(map['role'] as Map) + : null, + user: map['user'] != null + ? UserSerializer.fromMap(map['user'] as Map) + : null); + } + + static Map toMap(_RoleUser model) { + if (model == null) { + return null; + } + return { + 'role': RoleSerializer.toMap(model.role), + 'user': UserSerializer.toMap(model.user) + }; + } +} + +abstract class RoleUserFields { + static const List allFields = [role, user]; + + static const String role = 'role'; + + static const String user = 'user'; +} + +const RoleSerializer roleSerializer = RoleSerializer(); + +class RoleEncoder extends Converter { + const RoleEncoder(); + + @override + Map convert(Role model) => RoleSerializer.toMap(model); +} + +class RoleDecoder extends Converter { + const RoleDecoder(); + + @override + Role convert(Map map) => RoleSerializer.fromMap(map); +} + +class RoleSerializer extends Codec { + const RoleSerializer(); + + @override + get encoder => const RoleEncoder(); + @override + get decoder => const RoleDecoder(); + static Role fromMap(Map map) { + return Role( + id: map['id'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null, + name: map['name'] as String, + users: map['users'] is Iterable + ? List.unmodifiable(((map['users'] as Iterable).whereType()) + .map(UserSerializer.fromMap)) + : null); + } + + static Map toMap(_Role model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String(), + 'name': model.name, + 'users': model.users?.map((m) => UserSerializer.toMap(m))?.toList() + }; + } +} + +abstract class RoleFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + name, + users + ]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; + + static const String name = 'name'; + + static const String users = 'users'; +} From 2533902e719bec4ff11b5d2a70ac4478d083d69a Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 10:55:29 -0400 Subject: [PATCH 32/44] Share subValues with parent if any --- angel_orm/lib/src/query.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/angel_orm/lib/src/query.dart b/angel_orm/lib/src/query.dart index 65f38bc8..f20b21ca 100644 --- a/angel_orm/lib/src/query.dart +++ b/angel_orm/lib/src/query.dart @@ -22,6 +22,9 @@ abstract class Query extends QueryBase { Query({this.parent}); + Map get substitutionValues => + parent?.substitutionValues ?? super.substitutionValues; + /// A reference to an abstract query builder. /// /// This is usually a generated class. From fdac775e41f1cdc68b71b3f3aa8954f600acd19a Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 11:18:58 -0400 Subject: [PATCH 33/44] Add joinType to Relationship --- angel_orm/lib/src/relations.dart | 33 +++++++++++++++------ angel_orm_test/lib/src/belongs_to_test.dart | 1 + 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/angel_orm/lib/src/relations.dart b/angel_orm/lib/src/relations.dart index 0d736925..5edeed39 100644 --- a/angel_orm/lib/src/relations.dart +++ b/angel_orm/lib/src/relations.dart @@ -1,3 +1,5 @@ +import 'annotations.dart'; + abstract class RelationshipType { static const int hasMany = 0; static const int hasOne = 1; @@ -11,12 +13,14 @@ class Relationship { final String foreignKey; final String foreignTable; final bool cascadeOnDelete; + final JoinType joinType; const Relationship(this.type, {this.localKey, this.foreignKey, this.foreignTable, - this.cascadeOnDelete}); + this.cascadeOnDelete, + this.joinType}); } class HasMany extends Relationship { @@ -24,12 +28,14 @@ class HasMany extends Relationship { {String localKey, String foreignKey, String foreignTable, - bool cascadeOnDelete = false}) + bool cascadeOnDelete = false, + JoinType joinType = JoinType.left}) : super(RelationshipType.hasMany, localKey: localKey, foreignKey: foreignKey, foreignTable: foreignTable, - cascadeOnDelete: cascadeOnDelete == true); + cascadeOnDelete: cascadeOnDelete == true, + joinType: joinType); } const HasMany hasMany = HasMany(); @@ -39,22 +45,29 @@ class HasOne extends Relationship { {String localKey, String foreignKey, String foreignTable, - bool cascadeOnDelete = false}) + bool cascadeOnDelete = false, + JoinType joinType = JoinType.left}) : super(RelationshipType.hasOne, localKey: localKey, foreignKey: foreignKey, foreignTable: foreignTable, - cascadeOnDelete: cascadeOnDelete == true); + cascadeOnDelete: cascadeOnDelete == true, + joinType: joinType); } const HasOne hasOne = HasOne(); class BelongsTo extends Relationship { - const BelongsTo({String localKey, String foreignKey, String foreignTable}) + const BelongsTo( + {String localKey, + String foreignKey, + String foreignTable, + JoinType joinType = JoinType.left}) : super(RelationshipType.belongsTo, localKey: localKey, foreignKey: foreignKey, - foreignTable: foreignTable); + foreignTable: foreignTable, + joinType: joinType); } const BelongsTo belongsTo = BelongsTo(); @@ -66,11 +79,13 @@ class ManyToMany extends Relationship { {String localKey, String foreignKey, String foreignTable, - bool cascadeOnDelete = false}) + bool cascadeOnDelete = false, + JoinType joinType = JoinType.left}) : super( RelationshipType.hasMany, // Many-to-Many is actually just a hasMany localKey: localKey, foreignKey: foreignKey, foreignTable: foreignTable, - cascadeOnDelete: cascadeOnDelete == true); + cascadeOnDelete: cascadeOnDelete == true, + joinType: joinType); } diff --git a/angel_orm_test/lib/src/belongs_to_test.dart b/angel_orm_test/lib/src/belongs_to_test.dart index bd63c2e0..09342317 100644 --- a/angel_orm_test/lib/src/belongs_to_test.dart +++ b/angel_orm_test/lib/src/belongs_to_test.dart @@ -159,6 +159,7 @@ belongsToTests(FutureOr Function() createExecutor, }); test('returns values on true subquery', () async { + printSeparator('True subquery test'); var query = BookQuery()..author.where.name.like('%Rowling%'); expect(await query.get(executor), [deathlyHallows]); }); From 69106dd0e74e6e9ac41375cd4802116036a5d450 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 11:26:27 -0400 Subject: [PATCH 34/44] Allow specifying join type --- angel_orm_generator/lib/src/orm_build_context.dart | 11 +++++++++++ angel_orm_generator/lib/src/readers.dart | 6 +++++- angel_orm_test/lib/src/models/book.dart | 4 ++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/angel_orm_generator/lib/src/orm_build_context.dart b/angel_orm_generator/lib/src/orm_build_context.dart index 8ac2b5fe..8a94dcb8 100644 --- a/angel_orm_generator/lib/src/orm_build_context.dart +++ b/angel_orm_generator/lib/src/orm_build_context.dart @@ -236,6 +236,16 @@ Future buildOrmContext( localKey ??= '${rcc.snakeCase}_$foreignKey'; } + // Figure out the join type. + var joinType = JoinType.left; + var joinTypeRdr = cr.peek('joinType')?.objectValue; + if (joinTypeRdr != null) { + var idx = joinTypeRdr.getField('index')?.toIntValue(); + if (idx != null) { + joinType = JoinType.values[idx]; + } + } + var relation = RelationshipReader( type, localKey: localKey, @@ -245,6 +255,7 @@ Future buildOrmContext( through: through, foreign: foreign, throughContext: throughContext, + joinType: joinType ?? JoinType.left, ); // print('Relation on ${buildCtx.originalClassName}.${field.name} => ' diff --git a/angel_orm_generator/lib/src/readers.dart b/angel_orm_generator/lib/src/readers.dart index 5c251dd1..a1039514 100644 --- a/angel_orm_generator/lib/src/readers.dart +++ b/angel_orm_generator/lib/src/readers.dart @@ -34,6 +34,7 @@ class RelationshipReader { final DartType through; final OrmBuildContext foreign; final OrmBuildContext throughContext; + final JoinType joinType; const RelationshipReader(this.type, {this.localKey, @@ -42,11 +43,14 @@ class RelationshipReader { this.cascadeOnDelete, this.through, this.foreign, - this.throughContext}); + this.throughContext, + this.joinType = JoinType.left}); bool get isManyToMany => type == RelationshipType.hasMany && throughContext != null; + String get joinTypeString => joinType.toString().replaceAll('JoinType.', ''); + FieldElement findLocalField(OrmBuildContext ctx) { return ctx.effectiveFields.firstWhere( (f) => ctx.buildContext.resolveFieldName(f.name) == localKey, diff --git a/angel_orm_test/lib/src/models/book.dart b/angel_orm_test/lib/src/models/book.dart index 1d515c67..b89b171d 100644 --- a/angel_orm_test/lib/src/models/book.dart +++ b/angel_orm_test/lib/src/models/book.dart @@ -9,10 +9,10 @@ part 'book.g.dart'; @serializable @orm class _Book extends Model { - @belongsTo + @BelongsTo(joinType: JoinType.inner) _Author author; - @BelongsTo(localKey: "partner_author_id") + @BelongsTo(localKey: "partner_author_id", joinType: JoinType.inner) _Author partnerAuthor; String name; From 0ae331d38c467a96b0a55545d92df74b4c7124d1 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 12:06:40 -0400 Subject: [PATCH 35/44] Detect join type from enum --- angel_orm/CHANGELOG.md | 1 + angel_orm/lib/src/relations.dart | 8 ++++---- angel_orm_generator/CHANGELOG.md | 5 +++++ .../lib/src/orm_build_context.dart | 17 +++++++++++++---- .../lib/src/orm_generator.dart | 3 ++- angel_orm_generator/lib/src/readers.dart | 19 +++++++++++++++++-- angel_orm_test/lib/src/models/book.g.dart | 4 ++-- 7 files changed, 44 insertions(+), 13 deletions(-) diff --git a/angel_orm/CHANGELOG.md b/angel_orm/CHANGELOG.md index ee958cf5..4821a3cf 100644 --- a/angel_orm/CHANGELOG.md +++ b/angel_orm/CHANGELOG.md @@ -8,6 +8,7 @@ ORM queries to reference their joined subqueries. * Removed deprecated `Join`, `toSql`, `sanitizeExpression`, `isAscii`. * Always put `ORDER BY` before `LIMIT`. * `and`, `or`, `not` in `QueryWhere` include parentheses. +* Add `joinType` to `Relationship` class. # 2.0.2 * Place `LIMIT` and `OFFSET` after `ORDER BY`. diff --git a/angel_orm/lib/src/relations.dart b/angel_orm/lib/src/relations.dart index 5edeed39..1ca6e357 100644 --- a/angel_orm/lib/src/relations.dart +++ b/angel_orm/lib/src/relations.dart @@ -29,7 +29,7 @@ class HasMany extends Relationship { String foreignKey, String foreignTable, bool cascadeOnDelete = false, - JoinType joinType = JoinType.left}) + JoinType joinType}) : super(RelationshipType.hasMany, localKey: localKey, foreignKey: foreignKey, @@ -46,7 +46,7 @@ class HasOne extends Relationship { String foreignKey, String foreignTable, bool cascadeOnDelete = false, - JoinType joinType = JoinType.left}) + JoinType joinType}) : super(RelationshipType.hasOne, localKey: localKey, foreignKey: foreignKey, @@ -62,7 +62,7 @@ class BelongsTo extends Relationship { {String localKey, String foreignKey, String foreignTable, - JoinType joinType = JoinType.left}) + JoinType joinType}) : super(RelationshipType.belongsTo, localKey: localKey, foreignKey: foreignKey, @@ -80,7 +80,7 @@ class ManyToMany extends Relationship { String foreignKey, String foreignTable, bool cascadeOnDelete = false, - JoinType joinType = JoinType.left}) + JoinType joinType}) : super( RelationshipType.hasMany, // Many-to-Many is actually just a hasMany localKey: localKey, diff --git a/angel_orm_generator/CHANGELOG.md b/angel_orm_generator/CHANGELOG.md index a35e8481..68cfe691 100644 --- a/angel_orm_generator/CHANGELOG.md +++ b/angel_orm_generator/CHANGELOG.md @@ -1,3 +1,8 @@ +# 2.1.0 +* Relationships have always generated subqueries; now these subqueries are +available as `Query` objects on generated classes. +* Support explicitly-defined join types for relations. + # 2.0.5 * Remove `ShimFieldImpl` check, which broke relations. * Fix bug where primary key type would not be emitted in migrations. diff --git a/angel_orm_generator/lib/src/orm_build_context.dart b/angel_orm_generator/lib/src/orm_build_context.dart index 8a94dcb8..134b65cc 100644 --- a/angel_orm_generator/lib/src/orm_build_context.dart +++ b/angel_orm_generator/lib/src/orm_build_context.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; +import 'package:analyzer/src/dart/constant/value.dart'; import 'package:angel_model/angel_model.dart'; import 'package:angel_orm/angel_orm.dart'; import 'package:angel_serialize/angel_serialize.dart'; @@ -240,9 +241,17 @@ Future buildOrmContext( var joinType = JoinType.left; var joinTypeRdr = cr.peek('joinType')?.objectValue; if (joinTypeRdr != null) { - var idx = joinTypeRdr.getField('index')?.toIntValue(); - if (idx != null) { - joinType = JoinType.values[idx]; + // Unfortunately, the analyzer library provides little to nothing + // in the way of reading enums from source, so here's a hack. + var joinTypeType = (joinTypeRdr.type as InterfaceType); + var enumFields = + joinTypeType.element.fields.where((f) => f.isEnumConstant).toList(); + + for (int i = 0; i < enumFields.length; i++) { + if (enumFields[i].constantValue == joinTypeRdr) { + joinType = JoinType.values[i]; + break; + } } } @@ -255,7 +264,7 @@ Future buildOrmContext( through: through, foreign: foreign, throughContext: throughContext, - joinType: joinType ?? JoinType.left, + joinType: joinType, ); // print('Relation on ${buildCtx.originalClassName}.${field.name} => ' diff --git a/angel_orm_generator/lib/src/orm_generator.dart b/angel_orm_generator/lib/src/orm_generator.dart index 87096780..6077456e 100644 --- a/angel_orm_generator/lib/src/orm_generator.dart +++ b/angel_orm_generator/lib/src/orm_generator.dart @@ -327,7 +327,8 @@ class OrmGenerator extends GeneratorForAnnotation { joinArgs.insert( 0, refer('_$fieldName').assign(queryInstantiation)); - b.addExpression(refer('leftJoin').call(joinArgs, { + var joinType = relation.joinTypeString; + b.addExpression(refer(joinType).call(joinArgs, { 'additionalFields': literalConstList(additionalFields.toList()), 'trampoline': refer('trampoline'), diff --git a/angel_orm_generator/lib/src/readers.dart b/angel_orm_generator/lib/src/readers.dart index a1039514..bef5f0f2 100644 --- a/angel_orm_generator/lib/src/readers.dart +++ b/angel_orm_generator/lib/src/readers.dart @@ -44,12 +44,27 @@ class RelationshipReader { this.through, this.foreign, this.throughContext, - this.joinType = JoinType.left}); + this.joinType}); bool get isManyToMany => type == RelationshipType.hasMany && throughContext != null; - String get joinTypeString => joinType.toString().replaceAll('JoinType.', ''); + String get joinTypeString { + switch (joinType ?? JoinType.left) { + case JoinType.inner: + return 'join'; + case JoinType.left: + return 'leftJoin'; + case JoinType.right: + return 'rightJoin'; + case JoinType.full: + return 'fullOuterJoin'; + case JoinType.self: + return 'selfJoin'; + default: + return 'join'; + } + } FieldElement findLocalField(OrmBuildContext ctx) { return ctx.effectiveFields.firstWhere( diff --git a/angel_orm_test/lib/src/models/book.g.dart b/angel_orm_test/lib/src/models/book.g.dart index b72cdd3f..9b0d1bdf 100644 --- a/angel_orm_test/lib/src/models/book.g.dart +++ b/angel_orm_test/lib/src/models/book.g.dart @@ -55,11 +55,11 @@ class BookQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = BookQueryWhere(this); - leftJoin(_author = AuthorQuery(trampoline: trampoline, parent: this), + join(_author = AuthorQuery(trampoline: trampoline, parent: this), 'author_id', 'id', additionalFields: const ['id', 'created_at', 'updated_at', 'name'], trampoline: trampoline); - leftJoin(_partnerAuthor = AuthorQuery(trampoline: trampoline, parent: this), + join(_partnerAuthor = AuthorQuery(trampoline: trampoline, parent: this), 'partner_author_id', 'id', additionalFields: const ['id', 'created_at', 'updated_at', 'name'], trampoline: trampoline); From b6e0dfa8c993cb838a94e2cb6de59448db1c6b1b Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 12:13:25 -0400 Subject: [PATCH 36/44] Use transaction executor in delete --- angel_orm/lib/src/query.dart | 2 +- angel_orm_test/lib/src/belongs_to_test.dart | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/angel_orm/lib/src/query.dart b/angel_orm/lib/src/query.dart index f20b21ca..7addbbe7 100644 --- a/angel_orm/lib/src/query.dart +++ b/angel_orm/lib/src/query.dart @@ -279,7 +279,7 @@ abstract class Query extends QueryBase { // TODO: Can this be done with just *one* query? var existing = await get(tx); //var sql = compile(preamble: 'SELECT $tableName.id', withFields: false); - return executor + return tx .query(tableName, sql, substitutionValues) .then((_) => existing); }); diff --git a/angel_orm_test/lib/src/belongs_to_test.dart b/angel_orm_test/lib/src/belongs_to_test.dart index 09342317..c58dc7f8 100644 --- a/angel_orm_test/lib/src/belongs_to_test.dart +++ b/angel_orm_test/lib/src/belongs_to_test.dart @@ -125,8 +125,9 @@ belongsToTests(FutureOr Function() createExecutor, }); test('delete stream', () async { + printSeparator('Delete stream test'); var query = new BookQuery()..where.name.equals(deathlyHallows.name); - print(query.compile(Set())); + print(query.compile(Set(), preamble: 'DELETE', withFields: false)); var books = await query.delete(executor); expect(books, hasLength(1)); From 975935cffd0a92c72d519a1e3da1d68d0b7032cb Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 12:18:02 -0400 Subject: [PATCH 37/44] hasMany subquery test --- angel_orm_test/lib/src/has_many_test.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/angel_orm_test/lib/src/has_many_test.dart b/angel_orm_test/lib/src/has_many_test.dart index c96add0a..17e93821 100644 --- a/angel_orm_test/lib/src/has_many_test.dart +++ b/angel_orm_test/lib/src/has_many_test.dart @@ -68,5 +68,13 @@ hasManyTests(FutureOr Function() createExecutor, var tree = await tq.deleteOne(executor); verify(tree); }); + + test('returns empty on false subquery', () async { + var tq = new TreeQuery() + ..where.id.equals(treeId) + ..fruits.where.commonName.equals('Kiwi'); + var tree = await tq.getOne(executor); + expect(tree.fruits, isEmpty); + }); }); } From 2948304df1e5207e849611265a381fda50fd45ca Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 12:20:45 -0400 Subject: [PATCH 38/44] hasOne false subquery test --- angel_orm_test/lib/src/has_one_test.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/angel_orm_test/lib/src/has_one_test.dart b/angel_orm_test/lib/src/has_one_test.dart index ba1abe0a..9daeb169 100644 --- a/angel_orm_test/lib/src/has_one_test.dart +++ b/angel_orm_test/lib/src/has_one_test.dart @@ -85,4 +85,12 @@ hasOneTests(FutureOr Function() createExecutor, expect(leg.foot.id, foot.id); expect(leg.foot.nToes, foot.nToes); }); + + test('sets null on false subquery', () async { + var legQuery = new LegQuery() + ..where.id.equals(originalLeg.idAsInt) + ..foot.where.legId.equals(originalLeg.idAsInt + 1024); + var leg = await legQuery.getOne(executor); + expect(leg.foot, isNull); + }); } From 5442ba6f2ff2fe6fe2a040392cfbd90ab90eea7a Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 14:05:53 -0400 Subject: [PATCH 39/44] Fix many-to-many --- angel_orm/lib/src/join_builder.dart | 9 +- angel_orm/lib/src/query.dart | 18 ++- .../lib/src/orm_build_context.dart | 1 - .../lib/src/orm_generator.dart | 123 +++++++++++++----- angel_orm_test/lib/src/many_to_many_test.dart | 25 +++- .../lib/src/models/email_indexed.g.dart | 27 ++-- .../lib/src/models/unorthodox.g.dart | 28 ++-- angel_orm_test/lib/src/models/user.g.dart | 20 +-- 8 files changed, 162 insertions(+), 89 deletions(-) diff --git a/angel_orm/lib/src/join_builder.dart b/angel_orm/lib/src/join_builder.dart index 5636dabb..bf5836dd 100644 --- a/angel_orm/lib/src/join_builder.dart +++ b/angel_orm/lib/src/join_builder.dart @@ -31,7 +31,12 @@ class JoinBuilder { } String compile(Set trampoline) { - if (to == null) return null; + var compiledTo = to(); + if (compiledTo == null) { + print( + 'NULLLLL $to; from $from; key: $key, value: $value, addl: $additionalFields'); + } + if (compiledTo == null) return null; var b = StringBuffer(); var left = '${from.tableName}.$key'; var right = fieldName; @@ -54,7 +59,7 @@ class JoinBuilder { break; } - b.write(' ${to()}'); + b.write(' $compiledTo'); if (alias != null) b.write(' $alias'); b.write(' ON $left$op$right'); return b.toString(); diff --git a/angel_orm/lib/src/query.dart b/angel_orm/lib/src/query.dart index 7addbbe7..ce066897 100644 --- a/angel_orm/lib/src/query.dart +++ b/angel_orm/lib/src/query.dart @@ -219,6 +219,8 @@ abstract class Query extends QueryBase { b.write(' '); List f; + var compiledJoins = {}; + if (fields == null) { f = ['*']; } else { @@ -229,10 +231,16 @@ abstract class Query extends QueryBase { return ss; })); _joins.forEach((j) { - var additional = j.additionalFields.map(j.nameFor).toList(); - // if (!additional.contains(j.fieldName)) - // additional.insert(0, j.fieldName); - f.addAll(additional); + var c = compiledJoins[j] = j.compile(trampoline); + if (c != null) { + var additional = j.additionalFields.map(j.nameFor).toList(); + f.addAll(additional); + } else { + // If compilation failed, fill in NULL placeholders. + for (var i = 0; i < j.additionalFields.length; i++) { + f.add('NULL'); + } + } }); } if (withFields) b.write(f.join(', ')); @@ -243,7 +251,7 @@ abstract class Query extends QueryBase { if (preamble == null) { if (_crossJoin != null) b.write(' CROSS JOIN $_crossJoin'); for (var join in _joins) { - var c = join.compile(trampoline); + var c = compiledJoins[join]; if (c != null) b.write(' $c'); } } diff --git a/angel_orm_generator/lib/src/orm_build_context.dart b/angel_orm_generator/lib/src/orm_build_context.dart index 134b65cc..6013c63f 100644 --- a/angel_orm_generator/lib/src/orm_build_context.dart +++ b/angel_orm_generator/lib/src/orm_build_context.dart @@ -3,7 +3,6 @@ import 'dart:async'; import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; -import 'package:analyzer/src/dart/constant/value.dart'; import 'package:angel_model/angel_model.dart'; import 'package:angel_orm/angel_orm.dart'; import 'package:angel_serialize/angel_serialize.dart'; diff --git a/angel_orm_generator/lib/src/orm_generator.dart b/angel_orm_generator/lib/src/orm_generator.dart index 6077456e..b7f7dc93 100644 --- a/angel_orm_generator/lib/src/orm_generator.dart +++ b/angel_orm_generator/lib/src/orm_generator.dart @@ -281,6 +281,7 @@ class OrmGenerator extends GeneratorForAnnotation { .assign(queryWhereType.newInstance([refer('this')])), ); + // Note: this is where subquery fields for relations are added. ctx.relations.forEach((fieldName, relation) { //var name = ctx.buildContext.resolveFieldName(fieldName); if (relation.type == RelationshipType.belongsTo || @@ -289,43 +290,103 @@ class OrmGenerator extends GeneratorForAnnotation { var foreign = relation.throughContext ?? relation.foreign; // If this is a many-to-many, add the fields from the other object. - var additionalFields = relation.foreign.effectiveFields - // .where((f) => f.name != 'id' || !isSpecialId(ctx, f)) - .map((f) => literalString(relation.foreign.buildContext - .resolveFieldName(f.name))); + + var additionalStrs = relation.foreign.effectiveFields.map((f) => + relation.foreign.buildContext.resolveFieldName(f.name)); + var additionalFields = additionalStrs.map(literalString); var joinArgs = [relation.localKey, relation.foreignKey] .map(literalString) .toList(); - // In the past, we would either do a join on the table name - // itself, or create an instance of a query. - // - // From this point on, however, we will create a field for each - // join, so that users can customize the generated query. - // - // There'll be a private `_field`, and then a getter, named `field`, - // that returns the subqueryb object. - var foreignQueryType = refer( - foreign.buildContext.modelClassNameRecase.pascalCase + - 'Query'); - clazz - ..fields.add(Field((b) => b - ..name = '_$fieldName' - ..type = foreignQueryType)) - ..methods.add(Method((b) => b - ..name = fieldName - ..type = MethodType.getter - ..returns = foreignQueryType - ..body = refer('_$fieldName').returned.statement)); + // In the case of a many-to-many, we don't generate a subquery field, + // as it easily leads to stack overflows. + if (relation.isManyToMany) { + // We can't simply join against the "through" table; this itself must + // be a join. + // (SELECT role_users.role_id, + // FROM users + // LEFT JOIN role_users ON role_users.user_id=users.id) + var foreignFields = additionalStrs + .map((f) => '${relation.foreign.tableName}.$f'); + var b = StringBuffer('(SELECT '); + // role_users.role_id + b.write('${relation.throughContext.tableName}'); + b.write('.${relation.foreignKey}'); + // , + b.write(foreignFields.isEmpty + ? '' + : ', ' + foreignFields.join(', ')); + // FROM users + b.write(' FROM '); + b.write(relation.foreign.tableName); + // LEFT JOIN role_users + b.write(' LEFT JOIN ${relation.throughContext.tableName}'); + // Figure out which field on the "through" table points to users (foreign). + var throughRelation = + relation.throughContext.relations.values.firstWhere((e) { + return e.foreignTable == relation.foreign.tableName; + }, orElse: () { + // _Role has a many-to-many to _User through _RoleUser, but + // _RoleUser has no relation pointing to _User. + var b = StringBuffer(); + b.write(ctx.buildContext.modelClassName); + b.write('has a many-to-many relationship to '); + b.write(relation.foreign.buildContext.modelClassName); + b.write(' through '); + b.write( + relation.throughContext.buildContext.modelClassName); + b.write(', but '); + b.write( + relation.throughContext.buildContext.modelClassName); + b.write('has no relation pointing to '); + b.write(relation.foreign.buildContext.modelClassName); + b.write('.'); + throw b.toString(); + }); - // Assign a value to `_field`. - var queryInstantiation = foreignQueryType.newInstance([], { - 'trampoline': refer('trampoline'), - 'parent': refer('this') - }); - joinArgs.insert( - 0, refer('_$fieldName').assign(queryInstantiation)); + // ON role_users.user_id=users.id) + b.write(' ON '); + b.write('${relation.throughContext.tableName}'); + b.write('.'); + b.write(throughRelation.localKey); + b.write('='); + b.write(relation.foreign.tableName); + b.write('.'); + b.write(throughRelation.foreignKey); + b.write(')'); + + joinArgs.insert(0, literalString(b.toString())); + } else { + // In the past, we would either do a join on the table name + // itself, or create an instance of a query. + // + // From this point on, however, we will create a field for each + // join, so that users can customize the generated query. + // + // There'll be a private `_field`, and then a getter, named `field`, + // that returns the subquery object. + var foreignQueryType = refer( + foreign.buildContext.modelClassNameRecase.pascalCase + + 'Query'); + clazz + ..fields.add(Field((b) => b + ..name = '_$fieldName' + ..type = foreignQueryType)) + ..methods.add(Method((b) => b + ..name = fieldName + ..type = MethodType.getter + ..returns = foreignQueryType + ..body = refer('_$fieldName').returned.statement)); + + // Assign a value to `_field`. + var queryInstantiation = foreignQueryType.newInstance([], { + 'trampoline': refer('trampoline'), + 'parent': refer('this') + }); + joinArgs.insert( + 0, refer('_$fieldName').assign(queryInstantiation)); + } var joinType = relation.joinTypeString; b.addExpression(refer(joinType).call(joinArgs, { diff --git a/angel_orm_test/lib/src/many_to_many_test.dart b/angel_orm_test/lib/src/many_to_many_test.dart index c5588b6f..531c88e3 100644 --- a/angel_orm_test/lib/src/many_to_many_test.dart +++ b/angel_orm_test/lib/src/many_to_many_test.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:angel_orm/angel_orm.dart'; import 'package:test/test.dart'; import 'models/user.dart'; +import 'util.dart'; manyToManyTests(FutureOr Function() createExecutor, {FutureOr Function(QueryExecutor) close}) { @@ -61,6 +62,7 @@ manyToManyTests(FutureOr Function() createExecutor, print('=== THOSAKWE: ${thosakwe?.toJson()}'); // Allow thosakwe to publish... + printSeparator('Allow thosakwe to publish'); var thosakwePubQuery = RoleUserQuery(); thosakwePubQuery.values ..userId = int.parse(thosakwe.id) @@ -68,6 +70,7 @@ manyToManyTests(FutureOr Function() createExecutor, await thosakwePubQuery.insert(executor); // Allow thosakwe to subscribe... + printSeparator('Allow thosakwe to subscribe'); var thosakweSubQuery = RoleUserQuery(); thosakweSubQuery.values ..userId = int.parse(thosakwe.id) @@ -78,8 +81,8 @@ manyToManyTests(FutureOr Function() createExecutor, // await dumpQuery('select * from users;'); // await dumpQuery('select * from roles;'); // await dumpQuery('select * from role_users;'); - var query = RoleQuery()..where.id.equals(canPub.idAsInt); - await dumpQuery(query.compile(Set())); + // var query = RoleQuery()..where.id.equals(canPub.idAsInt); + // await dumpQuery(query.compile(Set())); print('\n'); print('=================================================='); @@ -95,6 +98,7 @@ manyToManyTests(FutureOr Function() createExecutor, } test('fetch roles for user', () async { + printSeparator('Fetch roles for user test'); var user = await fetchThosakwe(); expect(user.roles, hasLength(2)); expect(user.roles, contains(canPub)); @@ -108,4 +112,21 @@ manyToManyTests(FutureOr Function() createExecutor, expect(r.users.toList(), [thosakwe]); } }); + + test('only fetches linked', () async { + // Create a new user. The roles list should be empty, + // be there are no related rules. + var userQuery = UserQuery(); + userQuery.values + ..username = 'Prince' + ..password = 'Rogers' + ..email = 'Nelson'; + var user = await userQuery.insert(executor); + expect(user.roles, isEmpty); + + // Fetch again, just to be doubly sure. + var query = UserQuery()..where.id.equals(user.idAsInt); + var fetched = await query.getOne(executor); + expect(fetched.roles, isEmpty); + }); } diff --git a/angel_orm_test/lib/src/models/email_indexed.g.dart b/angel_orm_test/lib/src/models/email_indexed.g.dart index 85fffb87..42c387fe 100644 --- a/angel_orm_test/lib/src/models/email_indexed.g.dart +++ b/angel_orm_test/lib/src/models/email_indexed.g.dart @@ -64,8 +64,10 @@ class RoleQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = RoleQueryWhere(this); - leftJoin(_users = RoleUserQuery(trampoline: trampoline, parent: this), - 'role', 'role_role', + leftJoin( + '(SELECT role_users.role_role , users.email, users.name, users.password FROM users LEFT JOIN role_users ON role_users.user_email=users.email)', + 'role', + 'role_role', additionalFields: const ['email', 'name', 'password'], trampoline: trampoline); } @@ -75,8 +77,6 @@ class RoleQuery extends Query { RoleQueryWhere _where; - RoleUserQuery _users; - @override get casts { return {}; @@ -119,10 +119,6 @@ class RoleQuery extends Query { return parseRow(row); } - RoleUserQuery get users { - return _users; - } - @override bool canCompile(trampoline) { return (!(trampoline.contains('roles') && @@ -338,9 +334,12 @@ class UserQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = UserQueryWhere(this); - leftJoin(_roles = RoleUserQuery(trampoline: trampoline, parent: this), - 'email', 'user_email', - additionalFields: const ['role'], trampoline: trampoline); + leftJoin( + '(SELECT role_users.user_email , roles.role FROM roles LEFT JOIN role_users ON role_users.role_role=roles.role)', + 'email', + 'user_email', + additionalFields: const ['role'], + trampoline: trampoline); } @override @@ -348,8 +347,6 @@ class UserQuery extends Query { UserQueryWhere _where; - RoleUserQuery _roles; - @override get casts { return {}; @@ -395,10 +392,6 @@ class UserQuery extends Query { return parseRow(row); } - RoleUserQuery get roles { - return _roles; - } - @override bool canCompile(trampoline) { return (!(trampoline.contains('users') && diff --git a/angel_orm_test/lib/src/models/unorthodox.g.dart b/angel_orm_test/lib/src/models/unorthodox.g.dart index 558674e0..976ced94 100644 --- a/angel_orm_test/lib/src/models/unorthodox.g.dart +++ b/angel_orm_test/lib/src/models/unorthodox.g.dart @@ -208,9 +208,12 @@ class WeirdJoinQuery extends Query { leftJoin(_numbas = NumbaQuery(trampoline: trampoline, parent: this), 'id', 'parent', additionalFields: const ['i', 'parent'], trampoline: trampoline); - leftJoin(_foos = FooPivotQuery(trampoline: trampoline, parent: this), 'id', + leftJoin( + '(SELECT foo_pivots.weird_join_id , foos.bar FROM foos LEFT JOIN foo_pivots ON foo_pivots.foo_bar=foos.bar)', + 'id', 'weird_join_id', - additionalFields: const ['bar'], trampoline: trampoline); + additionalFields: const ['bar'], + trampoline: trampoline); } @override @@ -224,8 +227,6 @@ class WeirdJoinQuery extends Query { NumbaQuery _numbas; - FooPivotQuery _foos; - @override get casts { return {}; @@ -294,10 +295,6 @@ class WeirdJoinQuery extends Query { return _numbas; } - FooPivotQuery get foos { - return _foos; - } - @override bool canCompile(trampoline) { return (!(trampoline.contains('weird_joins') && @@ -612,9 +609,12 @@ class FooQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = FooQueryWhere(this); - leftJoin(_weirdJoins = FooPivotQuery(trampoline: trampoline, parent: this), - 'bar', 'foo_bar', - additionalFields: const ['id', 'join_name'], trampoline: trampoline); + leftJoin( + '(SELECT foo_pivots.foo_bar , weird_joins.id, weird_joins.join_name FROM weird_joins LEFT JOIN foo_pivots ON foo_pivots.weird_join_id=weird_joins.id)', + 'bar', + 'foo_bar', + additionalFields: const ['id', 'join_name'], + trampoline: trampoline); } @override @@ -622,8 +622,6 @@ class FooQuery extends Query { FooQueryWhere _where; - FooPivotQuery _weirdJoins; - @override get casts { return {}; @@ -666,10 +664,6 @@ class FooQuery extends Query { return parseRow(row); } - FooPivotQuery get weirdJoins { - return _weirdJoins; - } - @override bool canCompile(trampoline) { return (!(trampoline.contains('foos') && diff --git a/angel_orm_test/lib/src/models/user.g.dart b/angel_orm_test/lib/src/models/user.g.dart index 5bcad71f..2e113ab5 100644 --- a/angel_orm_test/lib/src/models/user.g.dart +++ b/angel_orm_test/lib/src/models/user.g.dart @@ -66,7 +66,9 @@ class UserQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = UserQueryWhere(this); - leftJoin(_roles = RoleUserQuery(trampoline: trampoline, parent: this), 'id', + leftJoin( + '(SELECT role_users.user_id , roles.id, roles.created_at, roles.updated_at, roles.name FROM roles LEFT JOIN role_users ON role_users.role_id=roles.id)', + 'id', 'user_id', additionalFields: const ['id', 'created_at', 'updated_at', 'name'], trampoline: trampoline); @@ -77,8 +79,6 @@ class UserQuery extends Query { UserQueryWhere _where; - RoleUserQuery _roles; - @override get casts { return {}; @@ -134,10 +134,6 @@ class UserQuery extends Query { return parseRow(row); } - RoleUserQuery get roles { - return _roles; - } - @override bool canCompile(trampoline) { return (!(trampoline.contains('users') && @@ -405,7 +401,9 @@ class RoleQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = RoleQueryWhere(this); - leftJoin(_users = RoleUserQuery(trampoline: trampoline, parent: this), 'id', + leftJoin( + '(SELECT role_users.role_id , users.id, users.created_at, users.updated_at, users.username, users.password, users.email FROM users LEFT JOIN role_users ON role_users.user_id=users.id)', + 'id', 'role_id', additionalFields: const [ 'id', @@ -423,8 +421,6 @@ class RoleQuery extends Query { RoleQueryWhere _where; - RoleUserQuery _users; - @override get casts { return {}; @@ -471,10 +467,6 @@ class RoleQuery extends Query { return parseRow(row); } - RoleUserQuery get users { - return _users; - } - @override bool canCompile(trampoline) { return (!(trampoline.contains('roles') && From bdbfe25de90a9306801000bac30074cb278c2391 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 14:08:41 -0400 Subject: [PATCH 40/44] angel_orm 2.1.0-beta --- angel_orm/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/angel_orm/pubspec.yaml b/angel_orm/pubspec.yaml index db3d6cba..dcd2ba3e 100644 --- a/angel_orm/pubspec.yaml +++ b/angel_orm/pubspec.yaml @@ -1,5 +1,5 @@ name: angel_orm -version: 2.1.0 +version: 2.1.0-beta description: Runtime support for Angel's ORM. Includes base classes for queries. author: Tobe O homepage: https://github.com/angel-dart/orm From eff3d7c974d5bc9c64a07e6a05a17a8c43c15ae2 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 14:09:14 -0400 Subject: [PATCH 41/44] Update changelog --- angel_orm/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/angel_orm/CHANGELOG.md b/angel_orm/CHANGELOG.md index 4821a3cf..cc359b6c 100644 --- a/angel_orm/CHANGELOG.md +++ b/angel_orm/CHANGELOG.md @@ -1,4 +1,4 @@ -# 2.1.0 +# 2.1.0-beta * Split the formerly 600+ line `src/query.dart` up into separate files. * **BREAKING**: Add a required `QueryExecutor` argument to `transaction` From 1e2e7e52bcd00971b668a5c3abd9c239a84de350 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 14:10:02 -0400 Subject: [PATCH 42/44] gen@2.1.0-beta --- angel_orm_generator/CHANGELOG.md | 2 +- angel_orm_generator/pubspec.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/angel_orm_generator/CHANGELOG.md b/angel_orm_generator/CHANGELOG.md index 68cfe691..f34dd29a 100644 --- a/angel_orm_generator/CHANGELOG.md +++ b/angel_orm_generator/CHANGELOG.md @@ -1,4 +1,4 @@ -# 2.1.0 +# 2.1.0-beta * Relationships have always generated subqueries; now these subqueries are available as `Query` objects on generated classes. * Support explicitly-defined join types for relations. diff --git a/angel_orm_generator/pubspec.yaml b/angel_orm_generator/pubspec.yaml index 00470631..f86f6027 100644 --- a/angel_orm_generator/pubspec.yaml +++ b/angel_orm_generator/pubspec.yaml @@ -1,5 +1,5 @@ name: angel_orm_generator -version: 2.1.0 +version: 2.1.0-beta description: Code generators for Angel's ORM. Generates query builder classes. author: Tobe O homepage: https://github.com/angel-dart/orm @@ -9,7 +9,7 @@ dependencies: analyzer: ">=0.35.0 <2.0.0" angel_model: ^1.0.0 angel_serialize: ^2.0.0 - angel_orm: ^2.0.0 + angel_orm: ^2.1.0-beta angel_serialize_generator: ^2.0.0 build: ^1.0.0 build_config: ^0.4.0 @@ -30,8 +30,8 @@ dev_dependencies: pedantic: ^1.0.0 postgres: ^1.0.0 test: ^1.0.0 -dependency_overrides: - angel_orm: - path: ../angel_orm +# dependency_overrides: +# angel_orm: +# path: ../angel_orm # angel_serialize_generator: # path: ../../serialize/angel_serialize_generator From e99e040a50087d91978053c96d03efc83173e866 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 14:11:44 -0400 Subject: [PATCH 43/44] pg@1.1.0-beta --- angel_orm_postgres/CHANGELOG.md | 3 +++ angel_orm_postgres/pubspec.yaml | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/angel_orm_postgres/CHANGELOG.md b/angel_orm_postgres/CHANGELOG.md index 160eb6e3..0d8c522a 100644 --- a/angel_orm_postgres/CHANGELOG.md +++ b/angel_orm_postgres/CHANGELOG.md @@ -1,3 +1,6 @@ +# 1.1.0-beta +* Updates for `package:angel_orm@2.1.0-beta`. + # 1.0.0 * Bump to `1.0.0`. This package has actually been stable for several months. diff --git a/angel_orm_postgres/pubspec.yaml b/angel_orm_postgres/pubspec.yaml index f94e71ac..2015c692 100644 --- a/angel_orm_postgres/pubspec.yaml +++ b/angel_orm_postgres/pubspec.yaml @@ -1,12 +1,12 @@ name: angel_orm_postgres -version: 1.0.0 +version: 1.1.0-beta description: PostgreSQL support for Angel's ORM. Includes functionality for querying and transactions. author: Tobe O homepage: https://github.com/angel-dart/orm environment: sdk: '>=2.0.0-dev.1.2 <3.0.0' dependencies: - angel_orm: ^2.0.0-dev + angel_orm: ^2.1.0-beta logging: ^0.11.0 pool: ^1.0.0 postgres: ^1.0.0 @@ -15,6 +15,6 @@ dev_dependencies: path: ../angel_orm_test pretty_logging: ^1.0.0 test: ^1.0.0 -dependency_overrides: - angel_orm: - path: ../angel_orm \ No newline at end of file +# dependency_overrides: +# angel_orm: +# path: ../angel_orm \ No newline at end of file From c14a2838612b55fb15beab30a776c0d605d95a14 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Wed, 9 Oct 2019 15:39:25 -0400 Subject: [PATCH 44/44] gen 2.1.0-beta.1 --- angel_orm_generator/CHANGELOG.md | 5 +++++ angel_orm_generator/lib/src/migration_generator.dart | 2 +- angel_orm_generator/lib/src/orm_build_context.dart | 11 ++++++----- angel_orm_generator/lib/src/orm_generator.dart | 2 +- angel_orm_generator/pubspec.yaml | 2 +- angel_orm_test/lib/src/models/email_indexed.g.dart | 4 ++-- angel_orm_test/lib/src/models/unorthodox.g.dart | 4 ++-- angel_orm_test/lib/src/models/user.g.dart | 4 ++-- 8 files changed, 20 insertions(+), 14 deletions(-) diff --git a/angel_orm_generator/CHANGELOG.md b/angel_orm_generator/CHANGELOG.md index f34dd29a..4feb0230 100644 --- a/angel_orm_generator/CHANGELOG.md +++ b/angel_orm_generator/CHANGELOG.md @@ -1,3 +1,8 @@ +# 2.1.0-beta.1 +* `OrmBuildContext` caching is now local to a `Builder`, so `watch` +*should* finally always run when required. Should resolve +[#85](https://github.com/angel-dart/orm/issues/85). + # 2.1.0-beta * Relationships have always generated subqueries; now these subqueries are available as `Query` objects on generated classes. diff --git a/angel_orm_generator/lib/src/migration_generator.dart b/angel_orm_generator/lib/src/migration_generator.dart index eb629f2b..d54f0cba 100644 --- a/angel_orm_generator/lib/src/migration_generator.dart +++ b/angel_orm_generator/lib/src/migration_generator.dart @@ -43,7 +43,7 @@ class MigrationGenerator extends GeneratorForAnnotation { } var resolver = await buildStep.resolver; - var ctx = await buildOrmContext(element as ClassElement, annotation, + var ctx = await buildOrmContext({}, element as ClassElement, annotation, buildStep, resolver, autoSnakeCaseNames != false); var lib = generateMigrationLibrary( ctx, element as ClassElement, resolver, buildStep); diff --git a/angel_orm_generator/lib/src/orm_build_context.dart b/angel_orm_generator/lib/src/orm_build_context.dart index 6013c63f..4ceea5a0 100644 --- a/angel_orm_generator/lib/src/orm_build_context.dart +++ b/angel_orm_generator/lib/src/orm_build_context.dart @@ -58,9 +58,8 @@ FieldElement findPrimaryFieldInList( return specialId; } -final Map _cache = {}; - Future buildOrmContext( + Map cache, ClassElement clazz, ConstantReader annotation, BuildStep buildStep, @@ -79,8 +78,8 @@ Future buildOrmContext( } var id = clazz.location.components.join('-'); - if (_cache.containsKey(id)) { - return _cache[id]; + if (cache.containsKey(id)) { + return cache[id]; } var buildCtx = await buildContext( clazz, annotation, buildStep, resolver, autoSnakeCaseNames, @@ -94,7 +93,7 @@ Future buildOrmContext( (ormAnnotation.tableName?.isNotEmpty == true) ? ormAnnotation.tableName : pluralize(ReCase(clazz.name).snakeCase)); - _cache[id] = ctx; + cache[id] = ctx; // Read all fields for (var field in buildCtx.fields) { @@ -173,6 +172,7 @@ Future buildOrmContext( var modelType = firstModelAncestor(refType) ?? refType; foreign = await buildOrmContext( + cache, modelType.element as ClassElement, ConstantReader(const TypeChecker.fromRuntime(Orm) .firstAnnotationOf(modelType.element)), @@ -183,6 +183,7 @@ Future buildOrmContext( // Resolve throughType as well if (through != null && through is InterfaceType) { throughContext = await buildOrmContext( + cache, through.element, ConstantReader(const TypeChecker.fromRuntime(Serializable) .firstAnnotationOf(modelType.element)), diff --git a/angel_orm_generator/lib/src/orm_generator.dart b/angel_orm_generator/lib/src/orm_generator.dart index b7f7dc93..d2e13637 100644 --- a/angel_orm_generator/lib/src/orm_generator.dart +++ b/angel_orm_generator/lib/src/orm_generator.dart @@ -39,7 +39,7 @@ class OrmGenerator extends GeneratorForAnnotation { Future generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep) async { if (element is ClassElement) { - var ctx = await buildOrmContext(element, annotation, buildStep, + var ctx = await buildOrmContext({}, element, annotation, buildStep, buildStep.resolver, autoSnakeCaseNames); var lib = buildOrmLibrary(buildStep.inputId, ctx); return lib.accept(DartEmitter()).toString(); diff --git a/angel_orm_generator/pubspec.yaml b/angel_orm_generator/pubspec.yaml index f86f6027..75f33075 100644 --- a/angel_orm_generator/pubspec.yaml +++ b/angel_orm_generator/pubspec.yaml @@ -1,5 +1,5 @@ name: angel_orm_generator -version: 2.1.0-beta +version: 2.1.0-beta.1 description: Code generators for Angel's ORM. Generates query builder classes. author: Tobe O homepage: https://github.com/angel-dart/orm diff --git a/angel_orm_test/lib/src/models/email_indexed.g.dart b/angel_orm_test/lib/src/models/email_indexed.g.dart index 42c387fe..4933ad99 100644 --- a/angel_orm_test/lib/src/models/email_indexed.g.dart +++ b/angel_orm_test/lib/src/models/email_indexed.g.dart @@ -65,7 +65,7 @@ class RoleQuery extends Query { trampoline.add(tableName); _where = RoleQueryWhere(this); leftJoin( - '(SELECT role_users.role_role , users.email, users.name, users.password FROM users LEFT JOIN role_users ON role_users.user_email=users.email)', + '(SELECT role_users.role_role, users.email, users.name, users.password FROM users LEFT JOIN role_users ON role_users.user_email=users.email)', 'role', 'role_role', additionalFields: const ['email', 'name', 'password'], @@ -335,7 +335,7 @@ class UserQuery extends Query { trampoline.add(tableName); _where = UserQueryWhere(this); leftJoin( - '(SELECT role_users.user_email , roles.role FROM roles LEFT JOIN role_users ON role_users.role_role=roles.role)', + '(SELECT role_users.user_email, roles.role FROM roles LEFT JOIN role_users ON role_users.role_role=roles.role)', 'email', 'user_email', additionalFields: const ['role'], diff --git a/angel_orm_test/lib/src/models/unorthodox.g.dart b/angel_orm_test/lib/src/models/unorthodox.g.dart index 976ced94..7a803db9 100644 --- a/angel_orm_test/lib/src/models/unorthodox.g.dart +++ b/angel_orm_test/lib/src/models/unorthodox.g.dart @@ -209,7 +209,7 @@ class WeirdJoinQuery extends Query { 'parent', additionalFields: const ['i', 'parent'], trampoline: trampoline); leftJoin( - '(SELECT foo_pivots.weird_join_id , foos.bar FROM foos LEFT JOIN foo_pivots ON foo_pivots.foo_bar=foos.bar)', + '(SELECT foo_pivots.weird_join_id, foos.bar FROM foos LEFT JOIN foo_pivots ON foo_pivots.foo_bar=foos.bar)', 'id', 'weird_join_id', additionalFields: const ['bar'], @@ -610,7 +610,7 @@ class FooQuery extends Query { trampoline.add(tableName); _where = FooQueryWhere(this); leftJoin( - '(SELECT foo_pivots.foo_bar , weird_joins.id, weird_joins.join_name FROM weird_joins LEFT JOIN foo_pivots ON foo_pivots.weird_join_id=weird_joins.id)', + '(SELECT foo_pivots.foo_bar, weird_joins.id, weird_joins.join_name FROM weird_joins LEFT JOIN foo_pivots ON foo_pivots.weird_join_id=weird_joins.id)', 'bar', 'foo_bar', additionalFields: const ['id', 'join_name'], diff --git a/angel_orm_test/lib/src/models/user.g.dart b/angel_orm_test/lib/src/models/user.g.dart index 2e113ab5..d8ecab33 100644 --- a/angel_orm_test/lib/src/models/user.g.dart +++ b/angel_orm_test/lib/src/models/user.g.dart @@ -67,7 +67,7 @@ class UserQuery extends Query { trampoline.add(tableName); _where = UserQueryWhere(this); leftJoin( - '(SELECT role_users.user_id , roles.id, roles.created_at, roles.updated_at, roles.name FROM roles LEFT JOIN role_users ON role_users.role_id=roles.id)', + '(SELECT role_users.user_id, roles.id, roles.created_at, roles.updated_at, roles.name FROM roles LEFT JOIN role_users ON role_users.role_id=roles.id)', 'id', 'user_id', additionalFields: const ['id', 'created_at', 'updated_at', 'name'], @@ -402,7 +402,7 @@ class RoleQuery extends Query { trampoline.add(tableName); _where = RoleQueryWhere(this); leftJoin( - '(SELECT role_users.role_id , users.id, users.created_at, users.updated_at, users.username, users.password, users.email FROM users LEFT JOIN role_users ON role_users.user_id=users.id)', + '(SELECT role_users.role_id, users.id, users.created_at, users.updated_at, users.username, users.password, users.email FROM users LEFT JOIN role_users ON role_users.user_id=users.id)', 'id', 'role_id', additionalFields: const [