From ba0fb804481116fd59b2b8538f6011607cf375e0 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Thu, 7 Dec 2017 03:21:49 -0500 Subject: [PATCH] Joins in the works --- angel_orm/lib/src/annotations.dart | 8 +- angel_orm/lib/src/query.dart | 3 +- angel_orm/pubspec.yaml | 2 +- .../lib/src/builder/orm/build_context.dart | 15 +- .../lib/src/builder/orm/postgres.dart | 79 ++++- .../builder/orm/postgres_build_context.dart | 49 ++- .../test/models/author.orm.g.dart | 10 + .../test/models/book.orm.g.dart | 12 + .../test/models/car.orm.g.dart | 16 + angel_orm_generator/test/models/customer.dart | 11 + .../test/models/customer.down.g.sql | 1 + .../test/models/customer.g.dart | 47 +++ .../test/models/customer.migration.g.dart | 23 ++ .../test/models/customer.orm.g.dart | 234 ++++++++++++++ .../test/models/customer.service.g.dart | 143 ++++++++ .../test/models/customer.up.g.sql | 6 + .../test/models/foot.orm.g.dart | 12 + .../test/models/fruit.orm.g.dart | 12 + .../test/models/leg.orm.g.dart | 10 + angel_orm_generator/test/models/order.dart | 17 + .../test/models/order.down.g.sql | 1 + angel_orm_generator/test/models/order.g.dart | 78 +++++ .../test/models/order.migration.g.dart | 27 ++ .../test/models/order.orm.g.dart | 305 ++++++++++++++++++ .../test/models/order.service.g.dart | 189 +++++++++++ .../test/models/order.up.g.sql | 10 + .../test/models/role.orm.g.dart | 10 + .../test/models/tree.orm.g.dart | 10 + .../test/models/user.orm.g.dart | 14 + angel_orm_generator/tool/actions.dart | 2 + 30 files changed, 1346 insertions(+), 10 deletions(-) create mode 100644 angel_orm_generator/test/models/customer.dart create mode 100644 angel_orm_generator/test/models/customer.down.g.sql create mode 100644 angel_orm_generator/test/models/customer.g.dart create mode 100644 angel_orm_generator/test/models/customer.migration.g.dart create mode 100644 angel_orm_generator/test/models/customer.orm.g.dart create mode 100644 angel_orm_generator/test/models/customer.service.g.dart create mode 100644 angel_orm_generator/test/models/customer.up.g.sql create mode 100644 angel_orm_generator/test/models/order.dart create mode 100644 angel_orm_generator/test/models/order.down.g.sql create mode 100644 angel_orm_generator/test/models/order.g.dart create mode 100644 angel_orm_generator/test/models/order.migration.g.dart create mode 100644 angel_orm_generator/test/models/order.orm.g.dart create mode 100644 angel_orm_generator/test/models/order.service.g.dart create mode 100644 angel_orm_generator/test/models/order.up.g.sql diff --git a/angel_orm/lib/src/annotations.dart b/angel_orm/lib/src/annotations.dart index 9a263e08..dbe16ad3 100644 --- a/angel_orm/lib/src/annotations.dart +++ b/angel_orm/lib/src/annotations.dart @@ -1,6 +1,12 @@ +const ORM orm = const ORM(); + class ORM { final String tableName; const ORM([this.tableName]); } -const ORM orm = const ORM(); \ No newline at end of file +class CanJoin { + final Type type; + final String foreignKey; + const CanJoin(this.type, this.foreignKey); +} \ No newline at end of file diff --git a/angel_orm/lib/src/query.dart b/angel_orm/lib/src/query.dart index 904ee918..0060f40e 100644 --- a/angel_orm/lib/src/query.dart +++ b/angel_orm/lib/src/query.dart @@ -21,7 +21,8 @@ String sanitizeExpression(String unsafe) { continue; // Otherwise, add the next char, unless it's a null byte. - else if ((ch = scanner.readChar()) != 0 && ch != null) buf.writeCharCode(ch); + else if ((ch = scanner.readChar()) != 0 && ch != null) + buf.writeCharCode(ch); } return buf.toString(); diff --git a/angel_orm/pubspec.yaml b/angel_orm/pubspec.yaml index c050994b..aa5cadfd 100644 --- a/angel_orm/pubspec.yaml +++ b/angel_orm/pubspec.yaml @@ -1,5 +1,5 @@ name: angel_orm -version: 1.0.0-alpha+10 +version: 1.0.0-alpha+12 description: Runtime support for Angel's ORM. author: Tobe O homepage: https://github.com/angel-dart/orm diff --git a/angel_orm_generator/lib/src/builder/orm/build_context.dart b/angel_orm_generator/lib/src/builder/orm/build_context.dart index 2bf880dd..0f99e9d1 100644 --- a/angel_orm_generator/lib/src/builder/orm/build_context.dart +++ b/angel_orm_generator/lib/src/builder/orm/build_context.dart @@ -99,7 +99,7 @@ Future buildContext( var raw = await serialize.buildContext(clazz, null, buildStep, resolver, autoSnakeCaseNames != false, autoIdAndDateFields != false); var ctx = await PostgresBuildContext.create( - raw, annotation, resolver, buildStep, + clazz, raw, annotation, resolver, buildStep, tableName: (annotation.tableName?.isNotEmpty == true) ? annotation.tableName : pluralize(new ReCase(clazz.name).snakeCase), @@ -110,6 +110,19 @@ Future buildContext( for (var field in raw.fields) { fieldNames.add(field.name); + + // Check for joins. + var canJoins = canJoinTypeChecker.annotationsOf(field); + + for (var ann in canJoins) { + var cr = new ConstantReader(ann); + ctx.joins[field.name] ??= []; + ctx.joins[field.name].add(new JoinContext( + resolveModelAncestor(cr.read('type').typeValue), + cr.read('foreignKey').stringValue, + )); + } + // Check for relationship. If so, skip. var relationshipAnnotation = relationshipTypeChecker.firstAnnotationOf(field); diff --git a/angel_orm_generator/lib/src/builder/orm/postgres.dart b/angel_orm_generator/lib/src/builder/orm/postgres.dart index 9b365869..f4efeeea 100644 --- a/angel_orm_generator/lib/src/builder/orm/postgres.dart +++ b/angel_orm_generator/lib/src/builder/orm/postgres.dart @@ -6,6 +6,7 @@ import 'package:build/build.dart'; import 'package:code_builder/dart/async.dart'; import 'package:code_builder/dart/core.dart'; import 'package:code_builder/code_builder.dart'; +import 'package:inflection/inflection.dart'; import 'package:path/path.dart' as p; import 'package:recase/recase.dart'; import 'package:source_gen/source_gen.dart' hide LibraryBuilder; @@ -100,8 +101,12 @@ class PostgresOrmGenerator extends GeneratorForAnnotation { for (var element in contexts.keys) { if (!done.contains(element.name)) { var ctx = contexts[element]; - lib.addMember(await buildQueryClass(ctx)); + var queryClass = await buildQueryClass(ctx); + if (ctx.joins.isNotEmpty) + await buildJoins(queryClass, lib, ctx, resolver, buildStep); + lib.addMember(queryClass); lib.addMember(buildWhereClass(ctx)); + lib.addMember(buildFieldClass(ctx)); done.add(element.name); } } @@ -252,8 +257,10 @@ class PostgresOrmGenerator extends GeneratorForAnnotation { // Write prefix, or default to SELECT var prefix = reference('prefix'); meth.addStatement(buf.invoke('write', [ - prefix.notEquals(literal(null)).ternary(prefix, - literal('SELECT ${await computeSelector(ctx)} FROM "${ctx.tableName}"')) + prefix.notEquals(literal(null)).ternary( + prefix, + literal( + 'SELECT ${await computeSelector(ctx)} FROM "${ctx.tableName}"')) ])); var relationsIfThen = ifThen(prefix.equals(literal(null))); @@ -966,4 +973,70 @@ class PostgresOrmGenerator extends GeneratorForAnnotation { return clazz; } + + ClassBuilder buildFieldClass(PostgresBuildContext ctx) { + var clazz = new ClassBuilder(ctx.reCase.pascalCase + 'Fields'); + + for (var field in ctx.fields) { + clazz.addField( + varConst(field.name, + value: literal(ctx.resolveFieldName(field.name))), + asStatic: true); + } + + return clazz; + } + + Future buildJoins(ClassBuilder queryClass, LibraryBuilder lib, + PostgresBuildContext ctx, Resolver resolver, BuildStep buildStep) async { + Map contexts = {}; + Map> targets = {}; + + for (var fieldName in ctx.joins.keys) { + print('${ctx.originalClassName}:$fieldName'); + var joins = ctx.joins[fieldName]; + + for (var join in joins) { + PostgresBuildContext refType; + + if (contexts.containsKey(join.type.hashCode)) + refType = contexts[join.type.hashCode]; + else { + var clazz = join.type.element as ClassElement; + var annotation = ormTypeChecker.firstAnnotationOf(join.type.element); + var ctx = await buildContext( + clazz, + reviveOrm(new ConstantReader(annotation)), + buildStep, + resolver, + autoSnakeCaseNames, + autoIdAndDateFields, + ); + contexts[join.type.hashCode] = refType = ctx; + } + + var targetMap = targets.putIfAbsent(refType, () => {}); + var localFieldName = ctx.resolveFieldName(fieldName); + targetMap.putIfAbsent(localFieldName, () => join); + } + } + + if (targets.isNotEmpty) { + /* + var result = await OrderQuery.joinCustomers( + connection, + OrderQueryFields.customerId + ); + */ + + for (var refType in targets.keys) { + var refTypeRc = new ReCase(pluralize(refType.modelClassName)); + var refTypePlural = refTypeRc.pascalCase; + var joinMethod = new MethodBuilder('join$refTypePlural'); + queryClass.addMethod(joinMethod, asStatic: true); + joinMethod.addPositional( + parameter('connection', [ctx.postgreSQLConnectionBuilder])); + } + } + } } diff --git a/angel_orm_generator/lib/src/builder/orm/postgres_build_context.dart b/angel_orm_generator/lib/src/builder/orm/postgres_build_context.dart index b28cc4f5..c765bfb5 100644 --- a/angel_orm_generator/lib/src/builder/orm/postgres_build_context.dart +++ b/angel_orm_generator/lib/src/builder/orm/postgres_build_context.dart @@ -3,6 +3,7 @@ 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/generated/resolver.dart'; +import 'package:angel_model/angel_model.dart'; import 'package:angel_orm/angel_orm.dart'; import 'package:angel_serialize_generator/context.dart'; import 'package:build/build.dart'; @@ -12,6 +13,33 @@ import 'package:recase/recase.dart'; import 'package:source_gen/source_gen.dart'; import 'build_context.dart'; +const TypeChecker canJoinTypeChecker = const TypeChecker.fromRuntime(CanJoin); + +DartType resolveModelAncestor(DartType type) { + DartType refType = type; + + while (refType != null) { + if (!const TypeChecker.fromRuntime(Model).isAssignableFromType(refType)) { + var parent = (refType.element as ClassElement).allSupertypes[0]; + if (parent != refType) + refType = parent; + else + refType = null; + } else + break; + } + + if (refType != null) return refType; + + throw '${type.name} does not extend Model.'; +} + +class JoinContext { + final DartType type; + final String foreignKey; + JoinContext(this.type, this.foreignKey); +} + class PostgresBuildContext extends BuildContext { LibraryElement _libraryCache; TypeProvider _typeProviderCache; @@ -23,28 +51,36 @@ class PostgresBuildContext extends BuildContext { final Map _populatedRelationships = {}; final Map columnInfo = {}; final Map indices = {}; + final Map> joins = {}; final Map relationships = {}; final bool autoSnakeCaseNames, autoIdAndDateFields; final String tableName; final ORM ormAnnotation; + final ClassElement element; final BuildContext raw; final Resolver resolver; final BuildStep buildStep; + ReCase _reCase; String primaryKeyName = 'id'; PostgresBuildContext._( - this.raw, this.ormAnnotation, this.resolver, this.buildStep, + this.element, this.raw, this.ormAnnotation, this.resolver, this.buildStep, {this.tableName, this.autoSnakeCaseNames, this.autoIdAndDateFields}) : super(raw.annotation, originalClassName: raw.originalClassName, sourceFilename: raw.sourceFilename); - static Future create(BuildContext raw, - ORM ormAnnotation, Resolver resolver, BuildStep buildStep, + static Future create( + ClassElement element, + BuildContext raw, + ORM ormAnnotation, + Resolver resolver, + BuildStep buildStep, {String tableName, bool autoSnakeCaseNames, bool autoIdAndDateFields}) async { var ctx = new PostgresBuildContext._( + element, raw, ormAnnotation, resolver, @@ -62,6 +98,8 @@ class PostgresBuildContext extends BuildContext { final List fields = [], relationshipFields = []; + ReCase get reCase => _reCase ?? new ReCase(modelClassName); + TypeBuilder get modelClassBuilder => _modelClassBuilder ??= new TypeBuilder(modelClassName); @@ -179,6 +217,11 @@ class PostgresBuildContext extends BuildContext { 'Invalid relationship type: ${relationship.type}'); }); } + + @override + String toString() { + return 'PostgresBuildContext: $originalClassName'; + } } class PopulatedRelationship extends Relationship { diff --git a/angel_orm_generator/test/models/author.orm.g.dart b/angel_orm_generator/test/models/author.orm.g.dart index ed0f9706..844ddd90 100644 --- a/angel_orm_generator/test/models/author.orm.g.dart +++ b/angel_orm_generator/test/models/author.orm.g.dart @@ -241,3 +241,13 @@ class AuthorQueryWhere { : ((keyword != false ? 'WHERE ' : '') + expressions.join(' AND ')); } } + +class AuthorFields { + static const id = 'id'; + + static const name = 'name'; + + static const createdAt = 'created_at'; + + static const updatedAt = 'updated_at'; +} diff --git a/angel_orm_generator/test/models/book.orm.g.dart b/angel_orm_generator/test/models/book.orm.g.dart index 11d16293..c2b19115 100644 --- a/angel_orm_generator/test/models/book.orm.g.dart +++ b/angel_orm_generator/test/models/book.orm.g.dart @@ -263,3 +263,15 @@ class BookQueryWhere { : ((keyword != false ? 'WHERE ' : '') + expressions.join(' AND ')); } } + +class BookFields { + static const id = 'id'; + + static const name = 'name'; + + static const createdAt = 'created_at'; + + static const updatedAt = 'updated_at'; + + static const authorId = 'author_id'; +} diff --git a/angel_orm_generator/test/models/car.orm.g.dart b/angel_orm_generator/test/models/car.orm.g.dart index a6d8135d..4b61e0ac 100644 --- a/angel_orm_generator/test/models/car.orm.g.dart +++ b/angel_orm_generator/test/models/car.orm.g.dart @@ -281,3 +281,19 @@ class CarQueryWhere { : ((keyword != false ? 'WHERE ' : '') + expressions.join(' AND ')); } } + +class CarFields { + static const id = 'id'; + + static const make = 'make'; + + static const description = 'description'; + + static const familyFriendly = 'family_friendly'; + + static const recalledAt = 'recalled_at'; + + static const createdAt = 'created_at'; + + static const updatedAt = 'updated_at'; +} diff --git a/angel_orm_generator/test/models/customer.dart b/angel_orm_generator/test/models/customer.dart new file mode 100644 index 00000000..b38e5631 --- /dev/null +++ b/angel_orm_generator/test/models/customer.dart @@ -0,0 +1,11 @@ +library angel_orm_generator.test.models.customer; + +import 'package:angel_model/angel_model.dart'; +import 'package:angel_orm/angel_orm.dart'; +import 'package:angel_serialize/angel_serialize.dart'; +part 'customer.g.dart'; + +@orm +@serializable +class _Customer extends Model { +} \ No newline at end of file diff --git a/angel_orm_generator/test/models/customer.down.g.sql b/angel_orm_generator/test/models/customer.down.g.sql new file mode 100644 index 00000000..f9fac656 --- /dev/null +++ b/angel_orm_generator/test/models/customer.down.g.sql @@ -0,0 +1 @@ +DROP TABLE "customers"; diff --git a/angel_orm_generator/test/models/customer.g.dart b/angel_orm_generator/test/models/customer.g.dart new file mode 100644 index 00000000..0b3eb61a --- /dev/null +++ b/angel_orm_generator/test/models/customer.g.dart @@ -0,0 +1,47 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of angel_orm_generator.test.models.customer; + +// ************************************************************************** +// Generator: JsonModelGenerator +// ************************************************************************** + +class Customer extends _Customer { + @override + String id; + + @override + DateTime createdAt; + + @override + DateTime updatedAt; + + Customer({this.id, this.createdAt, this.updatedAt}); + + factory Customer.fromJson(Map data) { + return new Customer( + id: data['id'], + createdAt: data['created_at'] is DateTime + ? data['created_at'] + : (data['created_at'] is String + ? DateTime.parse(data['created_at']) + : null), + updatedAt: data['updated_at'] is DateTime + ? data['updated_at'] + : (data['updated_at'] is String + ? DateTime.parse(data['updated_at']) + : null)); + } + + Map toJson() => { + 'id': id, + 'created_at': createdAt == null ? null : createdAt.toIso8601String(), + 'updated_at': updatedAt == null ? null : updatedAt.toIso8601String() + }; + + static Customer parse(Map map) => new Customer.fromJson(map); + + Customer clone() { + return new Customer.fromJson(toJson()); + } +} diff --git a/angel_orm_generator/test/models/customer.migration.g.dart b/angel_orm_generator/test/models/customer.migration.g.dart new file mode 100644 index 00000000..2aa60347 --- /dev/null +++ b/angel_orm_generator/test/models/customer.migration.g.dart @@ -0,0 +1,23 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// Generator: MigrationGenerator +// ************************************************************************** + +import 'package:angel_migration/angel_migration.dart'; + +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'); + } +} diff --git a/angel_orm_generator/test/models/customer.orm.g.dart b/angel_orm_generator/test/models/customer.orm.g.dart new file mode 100644 index 00000000..1a9437d5 --- /dev/null +++ b/angel_orm_generator/test/models/customer.orm.g.dart @@ -0,0 +1,234 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// Generator: PostgresOrmGenerator +// ************************************************************************** + +import 'dart:async'; +import 'package:angel_orm/angel_orm.dart'; +import 'package:postgres/postgres.dart'; +import 'customer.dart'; + +class CustomerQuery { + final Map _unions = {}; + + String _sortKey; + + String _sortMode; + + int limit; + + int offset; + + final List _or = []; + + final CustomerQueryWhere where = new CustomerQueryWhere(); + + void union(CustomerQuery query) { + _unions[query] = false; + } + + void unionAll(CustomerQuery query) { + _unions[query] = true; + } + + void sortDescending(String key) { + _sortMode = 'Descending'; + _sortKey = ('' + key); + } + + void sortAscending(String key) { + _sortMode = 'Ascending'; + _sortKey = ('' + key); + } + + void or(CustomerQueryWhere selector) { + _or.add(selector); + } + + String toSql([String prefix]) { + var buf = new StringBuffer(); + buf.write(prefix != null + ? prefix + : 'SELECT id, created_at, updated_at FROM "customers"'); + if (prefix == null) {} + var whereClause = where.toWhereClause(); + if (whereClause != null) { + buf.write(' ' + whereClause); + } + _or.forEach((x) { + var whereClause = x.toWhereClause(keyword: false); + if (whereClause != null) { + buf.write(' OR (' + whereClause + ')'); + } + }); + if (prefix == null) { + if (limit != null) { + buf.write(' LIMIT ' + limit.toString()); + } + if (offset != null) { + buf.write(' OFFSET ' + offset.toString()); + } + if (_sortMode == 'Descending') { + buf.write(' ORDER BY "' + _sortKey + '" DESC'); + } + if (_sortMode == 'Ascending') { + buf.write(' ORDER BY "' + _sortKey + '" ASC'); + } + _unions.forEach((query, all) { + buf.write(' UNION'); + if (all) { + buf.write(' ALL'); + } + buf.write(' ('); + var sql = query.toSql().replaceAll(';', ''); + buf.write(sql + ')'); + }); + buf.write(';'); + } + return buf.toString(); + } + + static Customer parseRow(List row) { + var result = new Customer.fromJson( + {'id': row[0].toString(), 'created_at': row[1], 'updated_at': row[2]}); + return result; + } + + Stream get(PostgreSQLConnection connection) { + StreamController ctrl = new StreamController(); + connection.query(toSql()).then((rows) async { + var futures = rows.map((row) async { + var parsed = parseRow(row); + return parsed; + }); + var output = await Future.wait(futures); + output.forEach(ctrl.add); + ctrl.close(); + }).catchError(ctrl.addError); + return ctrl.stream; + } + + static Future getOne(int id, PostgreSQLConnection connection) { + var query = new CustomerQuery(); + query.where.id.equals(id); + return query.get(connection).first.catchError((_) => null); + } + + Stream update(PostgreSQLConnection connection, + {DateTime createdAt, DateTime updatedAt}) { + var buf = new StringBuffer( + 'UPDATE "customers" SET ("created_at", "updated_at") = (@createdAt, @updatedAt) '); + var whereClause = where.toWhereClause(); + if (whereClause != null) { + buf.write(whereClause); + } + var __ormNow__ = new DateTime.now(); + var ctrl = new StreamController(); + connection.query( + buf.toString() + ' RETURNING "id", "created_at", "updated_at";', + substitutionValues: { + 'createdAt': createdAt != null ? createdAt : __ormNow__, + 'updatedAt': updatedAt != null ? updatedAt : __ormNow__ + }).then((rows) async { + var futures = rows.map((row) async { + var parsed = parseRow(row); + return parsed; + }); + var output = await Future.wait(futures); + output.forEach(ctrl.add); + ctrl.close(); + }).catchError(ctrl.addError); + return ctrl.stream; + } + + Stream delete(PostgreSQLConnection connection) { + StreamController ctrl = new StreamController(); + connection + .query(toSql('DELETE FROM "customers"') + + ' RETURNING "id", "created_at", "updated_at";') + .then((rows) async { + var futures = rows.map((row) async { + var parsed = parseRow(row); + return parsed; + }); + var output = await Future.wait(futures); + output.forEach(ctrl.add); + ctrl.close(); + }).catchError(ctrl.addError); + return ctrl.stream; + } + + static Future deleteOne(int id, PostgreSQLConnection connection) { + var query = new CustomerQuery(); + query.where.id.equals(id); + return query.delete(connection).first; + } + + static Future insert(PostgreSQLConnection connection, + {DateTime createdAt, DateTime updatedAt}) async { + var __ormNow__ = new DateTime.now(); + var result = await connection.query( + 'INSERT INTO "customers" ("created_at", "updated_at") VALUES (@createdAt, @updatedAt) RETURNING "id", "created_at", "updated_at";', + substitutionValues: { + 'createdAt': createdAt != null ? createdAt : __ormNow__, + 'updatedAt': updatedAt != null ? updatedAt : __ormNow__ + }); + var output = parseRow(result[0]); + return output; + } + + static Future insertCustomer( + PostgreSQLConnection connection, Customer customer) { + return CustomerQuery.insert(connection, + createdAt: customer.createdAt, updatedAt: customer.updatedAt); + } + + static Future updateCustomer( + PostgreSQLConnection connection, Customer customer) { + var query = new CustomerQuery(); + query.where.id.equals(int.parse(customer.id)); + return query + .update(connection, + createdAt: customer.createdAt, updatedAt: customer.updatedAt) + .first; + } + + static Stream getAll(PostgreSQLConnection connection) => + new CustomerQuery().get(connection); +} + +class CustomerQueryWhere { + final NumericSqlExpressionBuilder id = + new NumericSqlExpressionBuilder(); + + final DateTimeSqlExpressionBuilder createdAt = + new DateTimeSqlExpressionBuilder('customers.created_at'); + + final DateTimeSqlExpressionBuilder updatedAt = + new DateTimeSqlExpressionBuilder('customers.updated_at'); + + String toWhereClause({bool keyword}) { + final List expressions = []; + if (id.hasValue) { + expressions.add('customers.id ' + id.compile()); + } + if (createdAt.hasValue) { + expressions.add(createdAt.compile()); + } + if (updatedAt.hasValue) { + expressions.add(updatedAt.compile()); + } + return expressions.isEmpty + ? null + : ((keyword != false ? 'WHERE ' : '') + expressions.join(' AND ')); + } +} + +class CustomerFields { + static const id = 'id'; + + static const createdAt = 'created_at'; + + static const updatedAt = 'updated_at'; +} diff --git a/angel_orm_generator/test/models/customer.service.g.dart b/angel_orm_generator/test/models/customer.service.g.dart new file mode 100644 index 00000000..9dacce0f --- /dev/null +++ b/angel_orm_generator/test/models/customer.service.g.dart @@ -0,0 +1,143 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// Generator: PostgresServiceGenerator +// ************************************************************************** + +import 'dart:async'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:postgres/postgres.dart'; +import 'customer.dart'; +import 'customer.orm.g.dart'; + +class CustomerService extends Service { + final PostgreSQLConnection connection; + + final bool allowRemoveAll; + + final bool allowQuery; + + CustomerService(this.connection, + {this.allowRemoveAll: false, this.allowQuery: false}); + + CustomerQuery buildQuery(Map params) { + var query = new CustomerQuery(); + if (params['query'] is Map) { + query.where.id.equals(params['query']['id']); + query.where.createdAt.equals(params['query']['created_at'] is String + ? DateTime.parse(params['query']['created_at']) + : params['query']['created_at'] != null + ? params['query']['created_at'] is String + ? DateTime.parse(params['query']['created_at']) + : params['query']['created_at'] + : new DateTime.now()); + query.where.updatedAt.equals(params['query']['updated_at'] is String + ? DateTime.parse(params['query']['updated_at']) + : params['query']['updated_at'] != null + ? params['query']['updated_at'] is String + ? DateTime.parse(params['query']['updated_at']) + : params['query']['updated_at'] + : new DateTime.now()); + } + return query; + } + + int toId(id) { + if (id is int) { + return id; + } else { + if (id == 'null' || id == null) { + return null; + } else { + return int.parse(id.toString()); + } + } + } + + Customer applyData(data) { + if (data is Customer || data == null) { + return data; + } + if (data is Map) { + var query = new Customer(); + if (data.containsKey('created_at')) { + query.createdAt = data['created_at'] is String + ? DateTime.parse(data['created_at']) + : data['created_at'] != null + ? data['created_at'] is String + ? DateTime.parse(data['created_at']) + : data['created_at'] + : new DateTime.now(); + } + if (data.containsKey('updated_at')) { + query.updatedAt = data['updated_at'] is String + ? DateTime.parse(data['updated_at']) + : data['updated_at'] != null + ? data['updated_at'] is String + ? DateTime.parse(data['updated_at']) + : data['updated_at'] + : new DateTime.now(); + } + return query; + } else + throw new AngelHttpException.badRequest(message: 'Invalid data.'); + } + + Future> index([Map params]) { + return buildQuery(params).get(connection).toList(); + } + + Future create(data, [Map params]) { + return CustomerQuery.insertCustomer(connection, applyData(data)); + } + + Future read(id, [Map params]) { + var query = buildQuery(params); + query.where.id.equals(toId(id)); + return query.get(connection).first.catchError((_) { + new AngelHttpException.notFound( + message: 'No record found for ID ' + id.toString()); + }); + } + + Future remove(id, [Map params]) { + var query = buildQuery(params); + query.where.id.equals(toId(id)); + return query.delete(connection).first.catchError((_) { + new AngelHttpException.notFound( + message: 'No record found for ID ' + id.toString()); + }); + } + + Future update(id, data, [Map params]) { + return CustomerQuery.updateCustomer(connection, applyData(data)); + } + + Future modify(id, data, [Map params]) async { + var query = await read(toId(id), params); + if (data is Customer) { + query = data; + } + if (data is Map) { + if (data.containsKey('created_at')) { + query.createdAt = data['created_at'] is String + ? DateTime.parse(data['created_at']) + : data['created_at'] != null + ? data['created_at'] is String + ? DateTime.parse(data['created_at']) + : data['created_at'] + : new DateTime.now(); + } + if (data.containsKey('updated_at')) { + query.updatedAt = data['updated_at'] is String + ? DateTime.parse(data['updated_at']) + : data['updated_at'] != null + ? data['updated_at'] is String + ? DateTime.parse(data['updated_at']) + : data['updated_at'] + : new DateTime.now(); + } + } + return await CustomerQuery.updateCustomer(connection, query); + } +} diff --git a/angel_orm_generator/test/models/customer.up.g.sql b/angel_orm_generator/test/models/customer.up.g.sql new file mode 100644 index 00000000..5b182344 --- /dev/null +++ b/angel_orm_generator/test/models/customer.up.g.sql @@ -0,0 +1,6 @@ +CREATE TEMPORARY TABLE "customers" ( + "id" serial, + "created_at" timestamp, + "updated_at" timestamp, + PRIMARY KEY(id) +); diff --git a/angel_orm_generator/test/models/foot.orm.g.dart b/angel_orm_generator/test/models/foot.orm.g.dart index ae48bb14..c2869ff2 100644 --- a/angel_orm_generator/test/models/foot.orm.g.dart +++ b/angel_orm_generator/test/models/foot.orm.g.dart @@ -250,3 +250,15 @@ class FootQueryWhere { : ((keyword != false ? 'WHERE ' : '') + expressions.join(' AND ')); } } + +class FootFields { + static const id = 'id'; + + static const legId = 'leg_id'; + + static const nToes = 'n_toes'; + + static const createdAt = 'created_at'; + + static const updatedAt = 'updated_at'; +} diff --git a/angel_orm_generator/test/models/fruit.orm.g.dart b/angel_orm_generator/test/models/fruit.orm.g.dart index bf59e29a..a0a613b5 100644 --- a/angel_orm_generator/test/models/fruit.orm.g.dart +++ b/angel_orm_generator/test/models/fruit.orm.g.dart @@ -255,3 +255,15 @@ class FruitQueryWhere { : ((keyword != false ? 'WHERE ' : '') + expressions.join(' AND ')); } } + +class FruitFields { + static const id = 'id'; + + static const treeId = 'tree_id'; + + static const commonName = 'common_name'; + + static const createdAt = 'created_at'; + + static const updatedAt = 'updated_at'; +} diff --git a/angel_orm_generator/test/models/leg.orm.g.dart b/angel_orm_generator/test/models/leg.orm.g.dart index a9c18fcb..492f73d2 100644 --- a/angel_orm_generator/test/models/leg.orm.g.dart +++ b/angel_orm_generator/test/models/leg.orm.g.dart @@ -255,3 +255,13 @@ class LegQueryWhere { : ((keyword != false ? 'WHERE ' : '') + expressions.join(' AND ')); } } + +class LegFields { + static const id = 'id'; + + static const name = 'name'; + + static const createdAt = 'created_at'; + + static const updatedAt = 'updated_at'; +} diff --git a/angel_orm_generator/test/models/order.dart b/angel_orm_generator/test/models/order.dart new file mode 100644 index 00000000..1125dd9f --- /dev/null +++ b/angel_orm_generator/test/models/order.dart @@ -0,0 +1,17 @@ +library angel_orm_generator.test.models.order; + +import 'package:angel_model/angel_model.dart'; +import 'package:angel_orm/angel_orm.dart'; +import 'package:angel_serialize/angel_serialize.dart'; +import 'customer.dart'; +part 'order.g.dart'; + +@orm +@serializable +class _Order extends Model { + @CanJoin(Customer, 'id') + int customerId; + int employeeId; + DateTime orderDate; + int shipperId; +} \ No newline at end of file diff --git a/angel_orm_generator/test/models/order.down.g.sql b/angel_orm_generator/test/models/order.down.g.sql new file mode 100644 index 00000000..480da4fe --- /dev/null +++ b/angel_orm_generator/test/models/order.down.g.sql @@ -0,0 +1 @@ +DROP TABLE "orders"; diff --git a/angel_orm_generator/test/models/order.g.dart b/angel_orm_generator/test/models/order.g.dart new file mode 100644 index 00000000..aea06634 --- /dev/null +++ b/angel_orm_generator/test/models/order.g.dart @@ -0,0 +1,78 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of angel_orm_generator.test.models.order; + +// ************************************************************************** +// Generator: JsonModelGenerator +// ************************************************************************** + +class Order extends _Order { + @override + String id; + + @override + int customerId; + + @override + int employeeId; + + @override + DateTime orderDate; + + @override + int shipperId; + + @override + DateTime createdAt; + + @override + DateTime updatedAt; + + Order( + {this.id, + this.customerId, + this.employeeId, + this.orderDate, + this.shipperId, + this.createdAt, + this.updatedAt}); + + factory Order.fromJson(Map data) { + return new Order( + id: data['id'], + customerId: data['customer_id'], + employeeId: data['employee_id'], + orderDate: data['order_date'] is DateTime + ? data['order_date'] + : (data['order_date'] is String + ? DateTime.parse(data['order_date']) + : null), + shipperId: data['shipper_id'], + createdAt: data['created_at'] is DateTime + ? data['created_at'] + : (data['created_at'] is String + ? DateTime.parse(data['created_at']) + : null), + updatedAt: data['updated_at'] is DateTime + ? data['updated_at'] + : (data['updated_at'] is String + ? DateTime.parse(data['updated_at']) + : null)); + } + + Map toJson() => { + 'id': id, + 'customer_id': customerId, + 'employee_id': employeeId, + 'order_date': orderDate == null ? null : orderDate.toIso8601String(), + 'shipper_id': shipperId, + 'created_at': createdAt == null ? null : createdAt.toIso8601String(), + 'updated_at': updatedAt == null ? null : updatedAt.toIso8601String() + }; + + static Order parse(Map map) => new Order.fromJson(map); + + Order clone() { + return new Order.fromJson(toJson()); + } +} diff --git a/angel_orm_generator/test/models/order.migration.g.dart b/angel_orm_generator/test/models/order.migration.g.dart new file mode 100644 index 00000000..53a26a44 --- /dev/null +++ b/angel_orm_generator/test/models/order.migration.g.dart @@ -0,0 +1,27 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// Generator: MigrationGenerator +// ************************************************************************** + +import 'package:angel_migration/angel_migration.dart'; + +class OrderMigration extends Migration { + @override + up(Schema schema) { + schema.create('orders', (table) { + table.serial('id')..primaryKey(); + table.integer('customer_id'); + table.integer('employee_id'); + table.timeStamp('order_date'); + table.integer('shipper_id'); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + }); + } + + @override + down(Schema schema) { + schema.drop('orders'); + } +} diff --git a/angel_orm_generator/test/models/order.orm.g.dart b/angel_orm_generator/test/models/order.orm.g.dart new file mode 100644 index 00000000..8b7afd26 --- /dev/null +++ b/angel_orm_generator/test/models/order.orm.g.dart @@ -0,0 +1,305 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// Generator: PostgresOrmGenerator +// ************************************************************************** + +import 'dart:async'; +import 'package:angel_orm/angel_orm.dart'; +import 'package:postgres/postgres.dart'; +import 'order.dart'; + +class OrderQuery { + final Map _unions = {}; + + String _sortKey; + + String _sortMode; + + int limit; + + int offset; + + final List _or = []; + + final OrderQueryWhere where = new OrderQueryWhere(); + + void union(OrderQuery query) { + _unions[query] = false; + } + + void unionAll(OrderQuery query) { + _unions[query] = true; + } + + void sortDescending(String key) { + _sortMode = 'Descending'; + _sortKey = ('' + key); + } + + void sortAscending(String key) { + _sortMode = 'Ascending'; + _sortKey = ('' + key); + } + + void or(OrderQueryWhere selector) { + _or.add(selector); + } + + String toSql([String prefix]) { + var buf = new StringBuffer(); + buf.write(prefix != null + ? prefix + : 'SELECT id, customer_id, employee_id, order_date, shipper_id, created_at, updated_at FROM "orders"'); + if (prefix == null) {} + var whereClause = where.toWhereClause(); + if (whereClause != null) { + buf.write(' ' + whereClause); + } + _or.forEach((x) { + var whereClause = x.toWhereClause(keyword: false); + if (whereClause != null) { + buf.write(' OR (' + whereClause + ')'); + } + }); + if (prefix == null) { + if (limit != null) { + buf.write(' LIMIT ' + limit.toString()); + } + if (offset != null) { + buf.write(' OFFSET ' + offset.toString()); + } + if (_sortMode == 'Descending') { + buf.write(' ORDER BY "' + _sortKey + '" DESC'); + } + if (_sortMode == 'Ascending') { + buf.write(' ORDER BY "' + _sortKey + '" ASC'); + } + _unions.forEach((query, all) { + buf.write(' UNION'); + if (all) { + buf.write(' ALL'); + } + buf.write(' ('); + var sql = query.toSql().replaceAll(';', ''); + buf.write(sql + ')'); + }); + buf.write(';'); + } + return buf.toString(); + } + + static Order parseRow(List row) { + var result = new Order.fromJson({ + 'id': row[0].toString(), + 'customer_id': row[1], + 'employee_id': row[2], + 'order_date': row[3], + 'shipper_id': row[4], + 'created_at': row[5], + 'updated_at': row[6] + }); + return result; + } + + Stream get(PostgreSQLConnection connection) { + StreamController ctrl = new StreamController(); + connection.query(toSql()).then((rows) async { + var futures = rows.map((row) async { + var parsed = parseRow(row); + return parsed; + }); + var output = await Future.wait(futures); + output.forEach(ctrl.add); + ctrl.close(); + }).catchError(ctrl.addError); + return ctrl.stream; + } + + static Future getOne(int id, PostgreSQLConnection connection) { + var query = new OrderQuery(); + query.where.id.equals(id); + return query.get(connection).first.catchError((_) => null); + } + + Stream update(PostgreSQLConnection connection, + {int customerId, + int employeeId, + DateTime orderDate, + int shipperId, + DateTime createdAt, + DateTime updatedAt}) { + var buf = new StringBuffer( + 'UPDATE "orders" SET ("customer_id", "employee_id", "order_date", "shipper_id", "created_at", "updated_at") = (@customerId, @employeeId, @orderDate, @shipperId, @createdAt, @updatedAt) '); + var whereClause = where.toWhereClause(); + if (whereClause != null) { + buf.write(whereClause); + } + var __ormNow__ = new DateTime.now(); + var ctrl = new StreamController(); + connection.query( + buf.toString() + + ' RETURNING "id", "customer_id", "employee_id", "order_date", "shipper_id", "created_at", "updated_at";', + substitutionValues: { + 'customerId': customerId, + 'employeeId': employeeId, + 'orderDate': orderDate, + 'shipperId': shipperId, + 'createdAt': createdAt != null ? createdAt : __ormNow__, + 'updatedAt': updatedAt != null ? updatedAt : __ormNow__ + }).then((rows) async { + var futures = rows.map((row) async { + var parsed = parseRow(row); + return parsed; + }); + var output = await Future.wait(futures); + output.forEach(ctrl.add); + ctrl.close(); + }).catchError(ctrl.addError); + return ctrl.stream; + } + + Stream delete(PostgreSQLConnection connection) { + StreamController ctrl = new StreamController(); + connection + .query(toSql('DELETE FROM "orders"') + + ' RETURNING "id", "customer_id", "employee_id", "order_date", "shipper_id", "created_at", "updated_at";') + .then((rows) async { + var futures = rows.map((row) async { + var parsed = parseRow(row); + return parsed; + }); + var output = await Future.wait(futures); + output.forEach(ctrl.add); + ctrl.close(); + }).catchError(ctrl.addError); + return ctrl.stream; + } + + static Future deleteOne(int id, PostgreSQLConnection connection) { + var query = new OrderQuery(); + query.where.id.equals(id); + return query.delete(connection).first; + } + + static Future insert(PostgreSQLConnection connection, + {int customerId, + int employeeId, + DateTime orderDate, + int shipperId, + DateTime createdAt, + DateTime updatedAt}) async { + var __ormNow__ = new DateTime.now(); + var result = await connection.query( + 'INSERT INTO "orders" ("customer_id", "employee_id", "order_date", "shipper_id", "created_at", "updated_at") VALUES (@customerId, @employeeId, @orderDate, @shipperId, @createdAt, @updatedAt) RETURNING "id", "customer_id", "employee_id", "order_date", "shipper_id", "created_at", "updated_at";', + substitutionValues: { + 'customerId': customerId, + 'employeeId': employeeId, + 'orderDate': orderDate, + 'shipperId': shipperId, + 'createdAt': createdAt != null ? createdAt : __ormNow__, + 'updatedAt': updatedAt != null ? updatedAt : __ormNow__ + }); + var output = parseRow(result[0]); + return output; + } + + static Future insertOrder( + PostgreSQLConnection connection, Order order) { + return OrderQuery.insert(connection, + customerId: order.customerId, + employeeId: order.employeeId, + orderDate: order.orderDate, + shipperId: order.shipperId, + createdAt: order.createdAt, + updatedAt: order.updatedAt); + } + + static Future updateOrder( + PostgreSQLConnection connection, Order order) { + var query = new OrderQuery(); + query.where.id.equals(int.parse(order.id)); + return query + .update(connection, + customerId: order.customerId, + employeeId: order.employeeId, + orderDate: order.orderDate, + shipperId: order.shipperId, + createdAt: order.createdAt, + updatedAt: order.updatedAt) + .first; + } + + static Stream getAll(PostgreSQLConnection connection) => + new OrderQuery().get(connection); + + static joinCustomers(PostgreSQLConnection connection) { + } +} + +class OrderQueryWhere { + final NumericSqlExpressionBuilder id = + new NumericSqlExpressionBuilder(); + + final NumericSqlExpressionBuilder customerId = + new NumericSqlExpressionBuilder(); + + final NumericSqlExpressionBuilder employeeId = + new NumericSqlExpressionBuilder(); + + final DateTimeSqlExpressionBuilder orderDate = + new DateTimeSqlExpressionBuilder('orders.order_date'); + + final NumericSqlExpressionBuilder shipperId = + new NumericSqlExpressionBuilder(); + + final DateTimeSqlExpressionBuilder createdAt = + new DateTimeSqlExpressionBuilder('orders.created_at'); + + final DateTimeSqlExpressionBuilder updatedAt = + new DateTimeSqlExpressionBuilder('orders.updated_at'); + + String toWhereClause({bool keyword}) { + final List expressions = []; + if (id.hasValue) { + expressions.add('orders.id ' + id.compile()); + } + if (customerId.hasValue) { + expressions.add('orders.customer_id ' + customerId.compile()); + } + if (employeeId.hasValue) { + expressions.add('orders.employee_id ' + employeeId.compile()); + } + if (orderDate.hasValue) { + expressions.add(orderDate.compile()); + } + if (shipperId.hasValue) { + expressions.add('orders.shipper_id ' + shipperId.compile()); + } + if (createdAt.hasValue) { + expressions.add(createdAt.compile()); + } + if (updatedAt.hasValue) { + expressions.add(updatedAt.compile()); + } + return expressions.isEmpty + ? null + : ((keyword != false ? 'WHERE ' : '') + expressions.join(' AND ')); + } +} + +class OrderFields { + static const id = 'id'; + + static const customerId = 'customer_id'; + + static const employeeId = 'employee_id'; + + static const orderDate = 'order_date'; + + static const shipperId = 'shipper_id'; + + static const createdAt = 'created_at'; + + static const updatedAt = 'updated_at'; +} diff --git a/angel_orm_generator/test/models/order.service.g.dart b/angel_orm_generator/test/models/order.service.g.dart new file mode 100644 index 00000000..8ee3d5bb --- /dev/null +++ b/angel_orm_generator/test/models/order.service.g.dart @@ -0,0 +1,189 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// Generator: PostgresServiceGenerator +// ************************************************************************** + +import 'dart:async'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:postgres/postgres.dart'; +import 'order.dart'; +import 'order.orm.g.dart'; + +class OrderService extends Service { + final PostgreSQLConnection connection; + + final bool allowRemoveAll; + + final bool allowQuery; + + OrderService(this.connection, + {this.allowRemoveAll: false, this.allowQuery: false}); + + OrderQuery buildQuery(Map params) { + var query = new OrderQuery(); + if (params['query'] is Map) { + query.where.id.equals(params['query']['id']); + query.where.customerId.equals(params['query']['customer_id']); + query.where.employeeId.equals(params['query']['employee_id']); + query.where.orderDate.equals(params['query']['order_date'] is String + ? DateTime.parse(params['query']['order_date']) + : params['query']['order_date'] != null + ? params['query']['order_date'] is String + ? DateTime.parse(params['query']['order_date']) + : params['query']['order_date'] + : new DateTime.now()); + query.where.shipperId.equals(params['query']['shipper_id']); + query.where.createdAt.equals(params['query']['created_at'] is String + ? DateTime.parse(params['query']['created_at']) + : params['query']['created_at'] != null + ? params['query']['created_at'] is String + ? DateTime.parse(params['query']['created_at']) + : params['query']['created_at'] + : new DateTime.now()); + query.where.updatedAt.equals(params['query']['updated_at'] is String + ? DateTime.parse(params['query']['updated_at']) + : params['query']['updated_at'] != null + ? params['query']['updated_at'] is String + ? DateTime.parse(params['query']['updated_at']) + : params['query']['updated_at'] + : new DateTime.now()); + } + return query; + } + + int toId(id) { + if (id is int) { + return id; + } else { + if (id == 'null' || id == null) { + return null; + } else { + return int.parse(id.toString()); + } + } + } + + Order applyData(data) { + if (data is Order || data == null) { + return data; + } + if (data is Map) { + var query = new Order(); + if (data.containsKey('customer_id')) { + query.customerId = data['customer_id']; + } + if (data.containsKey('employee_id')) { + query.employeeId = data['employee_id']; + } + if (data.containsKey('order_date')) { + query.orderDate = data['order_date'] is String + ? DateTime.parse(data['order_date']) + : data['order_date'] != null + ? data['order_date'] is String + ? DateTime.parse(data['order_date']) + : data['order_date'] + : new DateTime.now(); + } + if (data.containsKey('shipper_id')) { + query.shipperId = data['shipper_id']; + } + if (data.containsKey('created_at')) { + query.createdAt = data['created_at'] is String + ? DateTime.parse(data['created_at']) + : data['created_at'] != null + ? data['created_at'] is String + ? DateTime.parse(data['created_at']) + : data['created_at'] + : new DateTime.now(); + } + if (data.containsKey('updated_at')) { + query.updatedAt = data['updated_at'] is String + ? DateTime.parse(data['updated_at']) + : data['updated_at'] != null + ? data['updated_at'] is String + ? DateTime.parse(data['updated_at']) + : data['updated_at'] + : new DateTime.now(); + } + return query; + } else + throw new AngelHttpException.badRequest(message: 'Invalid data.'); + } + + Future> index([Map params]) { + return buildQuery(params).get(connection).toList(); + } + + Future create(data, [Map params]) { + return OrderQuery.insertOrder(connection, applyData(data)); + } + + Future read(id, [Map params]) { + var query = buildQuery(params); + query.where.id.equals(toId(id)); + return query.get(connection).first.catchError((_) { + new AngelHttpException.notFound( + message: 'No record found for ID ' + id.toString()); + }); + } + + Future remove(id, [Map params]) { + var query = buildQuery(params); + query.where.id.equals(toId(id)); + return query.delete(connection).first.catchError((_) { + new AngelHttpException.notFound( + message: 'No record found for ID ' + id.toString()); + }); + } + + Future update(id, data, [Map params]) { + return OrderQuery.updateOrder(connection, applyData(data)); + } + + Future modify(id, data, [Map params]) async { + var query = await read(toId(id), params); + if (data is Order) { + query = data; + } + if (data is Map) { + if (data.containsKey('customer_id')) { + query.customerId = data['customer_id']; + } + if (data.containsKey('employee_id')) { + query.employeeId = data['employee_id']; + } + if (data.containsKey('order_date')) { + query.orderDate = data['order_date'] is String + ? DateTime.parse(data['order_date']) + : data['order_date'] != null + ? data['order_date'] is String + ? DateTime.parse(data['order_date']) + : data['order_date'] + : new DateTime.now(); + } + if (data.containsKey('shipper_id')) { + query.shipperId = data['shipper_id']; + } + if (data.containsKey('created_at')) { + query.createdAt = data['created_at'] is String + ? DateTime.parse(data['created_at']) + : data['created_at'] != null + ? data['created_at'] is String + ? DateTime.parse(data['created_at']) + : data['created_at'] + : new DateTime.now(); + } + if (data.containsKey('updated_at')) { + query.updatedAt = data['updated_at'] is String + ? DateTime.parse(data['updated_at']) + : data['updated_at'] != null + ? data['updated_at'] is String + ? DateTime.parse(data['updated_at']) + : data['updated_at'] + : new DateTime.now(); + } + } + return await OrderQuery.updateOrder(connection, query); + } +} diff --git a/angel_orm_generator/test/models/order.up.g.sql b/angel_orm_generator/test/models/order.up.g.sql new file mode 100644 index 00000000..19a22403 --- /dev/null +++ b/angel_orm_generator/test/models/order.up.g.sql @@ -0,0 +1,10 @@ +CREATE TEMPORARY TABLE "orders" ( + "id" serial, + "customer_id" int, + "employee_id" int, + "order_date" timestamp, + "shipper_id" int, + "created_at" timestamp, + "updated_at" timestamp, + PRIMARY KEY(id) +); diff --git a/angel_orm_generator/test/models/role.orm.g.dart b/angel_orm_generator/test/models/role.orm.g.dart index 08b23a74..7e0e9b43 100644 --- a/angel_orm_generator/test/models/role.orm.g.dart +++ b/angel_orm_generator/test/models/role.orm.g.dart @@ -235,3 +235,13 @@ class RoleQueryWhere { : ((keyword != false ? 'WHERE ' : '') + expressions.join(' AND ')); } } + +class RoleFields { + static const id = 'id'; + + static const name = 'name'; + + static const createdAt = 'created_at'; + + static const updatedAt = 'updated_at'; +} diff --git a/angel_orm_generator/test/models/tree.orm.g.dart b/angel_orm_generator/test/models/tree.orm.g.dart index 671f546f..ccae50c2 100644 --- a/angel_orm_generator/test/models/tree.orm.g.dart +++ b/angel_orm_generator/test/models/tree.orm.g.dart @@ -260,3 +260,13 @@ class TreeQueryWhere { : ((keyword != false ? 'WHERE ' : '') + expressions.join(' AND ')); } } + +class TreeFields { + static const id = 'id'; + + static const rings = 'rings'; + + static const createdAt = 'created_at'; + + static const updatedAt = 'updated_at'; +} diff --git a/angel_orm_generator/test/models/user.orm.g.dart b/angel_orm_generator/test/models/user.orm.g.dart index ba5dd84c..c4dc3913 100644 --- a/angel_orm_generator/test/models/user.orm.g.dart +++ b/angel_orm_generator/test/models/user.orm.g.dart @@ -283,3 +283,17 @@ class UserQueryWhere { : ((keyword != false ? 'WHERE ' : '') + expressions.join(' AND ')); } } + +class UserFields { + static const id = 'id'; + + static const username = 'username'; + + static const password = 'password'; + + static const email = 'email'; + + static const createdAt = 'created_at'; + + static const updatedAt = 'updated_at'; +} diff --git a/angel_orm_generator/tool/actions.dart b/angel_orm_generator/tool/actions.dart index 1b9b1725..68719bd7 100644 --- a/angel_orm_generator/tool/actions.dart +++ b/angel_orm_generator/tool/actions.dart @@ -10,10 +10,12 @@ const List standaloneModels = const [ 'test/models/car.dart', 'test/models/foot.dart', 'test/models/fruit.dart', + 'test/models/order.dart', 'test/models/role.dart' ]; const List dependentModels = const [ 'test/models/book.dart', + 'test/models/customer.dart', 'test/models/leg.dart', 'test/models/tree.dart', 'test/models/user.dart'