From a714059cb99510f694ecf3f72eec9c87c7d80259 Mon Sep 17 00:00:00 2001 From: "thomashii@dukefirehawk.com" Date: Sat, 4 Jun 2022 09:50:58 +0800 Subject: [PATCH 01/13] Fixed issue 68 --- packages/orm/angel_orm/CHANGELOG.md | 5 + packages/orm/angel_orm/lib/src/migration.dart | 1 + packages/orm/angel_orm/lib/src/util.dart | 8 +- packages/orm/angel_orm/pubspec.yaml | 4 +- packages/orm/angel_orm_generator/CHANGELOG.md | 5 + .../lib/src/migration_generator.dart | 3 + .../lib/src/orm_build_context.dart | 4 +- .../lib/src/orm_generator.dart | 26 +- packages/orm/angel_orm_generator/pubspec.yaml | 14 +- packages/orm/angel_orm_test/CHANGELOG.md | 3 +- .../angel_orm_test/lib/src/models/asset.dart | 23 + .../lib/src/models/asset.g.dart | 658 ++++++++++++++++++ .../angel_orm_test/lib/src/models/bike.dart | 22 + .../angel_orm_test/lib/src/models/bike.g.dart | 435 ++++++++++++ .../angel_orm_test/lib/src/models/boat.dart | 28 + .../angel_orm_test/lib/src/models/boat.g.dart | 435 ++++++++++++ .../angel_orm_test/lib/src/models/leg.g.dart | 7 +- .../lib/src/models/person_order.g.dart | 11 +- packages/orm/angel_orm_test/pubspec.yaml | 16 +- .../angel_serialize_generator/CHANGELOG.md | 5 + .../lib/serialize.dart | 16 +- .../angel_serialize_generator/pubspec.yaml | 4 +- 22 files changed, 1693 insertions(+), 40 deletions(-) create mode 100644 packages/orm/angel_orm_test/lib/src/models/asset.dart create mode 100644 packages/orm/angel_orm_test/lib/src/models/asset.g.dart create mode 100644 packages/orm/angel_orm_test/lib/src/models/bike.dart create mode 100644 packages/orm/angel_orm_test/lib/src/models/bike.g.dart create mode 100644 packages/orm/angel_orm_test/lib/src/models/boat.dart create mode 100644 packages/orm/angel_orm_test/lib/src/models/boat.g.dart diff --git a/packages/orm/angel_orm/CHANGELOG.md b/packages/orm/angel_orm/CHANGELOG.md index 002b8d51..f7108264 100644 --- a/packages/orm/angel_orm/CHANGELOG.md +++ b/packages/orm/angel_orm/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 6.0.2 + +* Fixed issue #68: Support for non-nullable type +* Upgraded to `lints` 2.x.x + ## 6.0.1 * Added `mapToDateTime` diff --git a/packages/orm/angel_orm/lib/src/migration.dart b/packages/orm/angel_orm/lib/src/migration.dart index 9af765e4..0e48dea2 100644 --- a/packages/orm/angel_orm/lib/src/migration.dart +++ b/packages/orm/angel_orm/lib/src/migration.dart @@ -93,6 +93,7 @@ class ColumnType { static const ColumnType smallMoney = ColumnType('smallmoney'); static const ColumnType float = ColumnType('float'); static const ColumnType real = ColumnType('real'); + static const ColumnType double = ColumnType('double'); // Dates and times static const ColumnType dateTime = ColumnType('datetime'); diff --git a/packages/orm/angel_orm/lib/src/util.dart b/packages/orm/angel_orm/lib/src/util.dart index 74421b74..28604fef 100644 --- a/packages/orm/angel_orm/lib/src/util.dart +++ b/packages/orm/angel_orm/lib/src/util.dart @@ -2,6 +2,8 @@ import 'package:charcode/ascii.dart'; bool isAscii(int ch) => ch >= $nul && ch <= $del; +final DateTime defaultDate = DateTime.parse("1970-01-01 00:00:00"); + bool mapToBool(dynamic value) { if (value is int) { return value != 0; @@ -20,12 +22,12 @@ String mapToText(dynamic value) { return value; } -DateTime? mapToDateTime(dynamic value) { +DateTime mapToDateTime(dynamic value) { if (value == null) { - return value; + return defaultDate; } if (value is String) { - return DateTime.tryParse(value); + return DateTime.tryParse(value) ?? defaultDate; } return value; } diff --git a/packages/orm/angel_orm/pubspec.yaml b/packages/orm/angel_orm/pubspec.yaml index 9d489a47..e2abc462 100644 --- a/packages/orm/angel_orm/pubspec.yaml +++ b/packages/orm/angel_orm/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_orm -version: 6.0.1 +version: 6.0.2 description: Runtime support for Angel3 ORM. Includes base classes for queries. homepage: https://angel3-framework.web.app/ repository: https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_orm @@ -18,7 +18,7 @@ dev_dependencies: angel3_serialize_generator: ^6.0.0 build_runner: ^2.1.1 test: ^1.17.4 - lints: ^1.0.0 + lints: ^2.0.0 # dependency_overrides: # angel3_serialize: # path: ../../serialize/angel_serialize diff --git a/packages/orm/angel_orm_generator/CHANGELOG.md b/packages/orm/angel_orm_generator/CHANGELOG.md index 10cdb2ad..4c011eb0 100644 --- a/packages/orm/angel_orm_generator/CHANGELOG.md +++ b/packages/orm/angel_orm_generator/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 6.1.1 + +* Fixed issue #68: Support for non-nullable type +* Upgraded to `lints` 2.x.x + ## 6.1.0 * Updated to `analyzer` 4.x.x diff --git a/packages/orm/angel_orm_generator/lib/src/migration_generator.dart b/packages/orm/angel_orm_generator/lib/src/migration_generator.dart index 96cc1127..a9a5d66c 100644 --- a/packages/orm/angel_orm_generator/lib/src/migration_generator.dart +++ b/packages/orm/angel_orm_generator/lib/src/migration_generator.dart @@ -149,6 +149,9 @@ class MigrationGenerator extends GeneratorForAnnotation { case ColumnType.numeric: methodName = 'numeric'; break; + case ColumnType.double: + methodName = 'float'; + break; case ColumnType.boolean: methodName = 'boolean'; break; diff --git a/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart b/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart index 0a2a853f..f9a12856 100644 --- a/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart +++ b/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart @@ -342,10 +342,10 @@ ColumnType inferColumnType(DartType type) { return ColumnType.int; } if (const TypeChecker.fromRuntime(double).isAssignableFromType(type)) { - return ColumnType.decimal; + return ColumnType.double; } if (const TypeChecker.fromRuntime(num).isAssignableFromType(type)) { - return ColumnType.numeric; + return ColumnType.double; } if (const TypeChecker.fromRuntime(bool).isAssignableFromType(type)) { return ColumnType.boolean; diff --git a/packages/orm/angel_orm_generator/lib/src/orm_generator.dart b/packages/orm/angel_orm_generator/lib/src/orm_generator.dart index 913fab41..bf597ecf 100644 --- a/packages/orm/angel_orm_generator/lib/src/orm_generator.dart +++ b/packages/orm/angel_orm_generator/lib/src/orm_generator.dart @@ -14,6 +14,7 @@ var floatTypes = [ ColumnType.float, ColumnType.numeric, ColumnType.real, + ColumnType.double, const ColumnType('double precision'), ]; @@ -241,7 +242,7 @@ class OrmGenerator extends GeneratorForAnnotation { ..body = Block((b) { var i = 0; - // Build the argurments for model + // Build the arguments for model var args = {}; for (var field in ctx.effectiveFields) { var fType = field.type; @@ -274,16 +275,32 @@ class OrmGenerator extends GeneratorForAnnotation { // Generated Code: mapToBool(row[i]) expr = refer('mapToBool').call([expr]); } else if (fType.element?.displayName == 'DateTime') { - //print("fType: ${fType.element?.displayName}"); + // print("fType: ${fType.element?.displayName}"); // Generated Code: mapToDateTime(row[i]) expr = refer('mapToDateTime').call([expr]); } else { // Generated Code: (row[i] as type?) expr = expr.asA(type); } + + Expression defaultRef = refer('null'); + if (fType.nullabilitySuffix != NullabilitySuffix.question) { + if (fType.isDartCoreString) { + defaultRef = CodeExpression(Code('\'\'')); + } else if (fType.isDartCoreBool) { + defaultRef = CodeExpression(Code('false')); + } else if (fType.isDartCoreDouble) { + defaultRef = CodeExpression(Code('0.0')); + } else if (fType.isDartCoreInt || fType.isDartCoreNum) { + defaultRef = CodeExpression(Code('0')); + } else if (fType.element?.displayName == 'DateTime') { + defaultRef = CodeExpression( + Code('DateTime.parse("1970-01-01 00:00:00")')); + } + } expr = refer('fields').property('contains').call([ literalString(ctx.buildContext.resolveFieldName(field.name)!) - ]).conditional(expr, refer('null')); + ]).conditional(expr, defaultRef); args[field.name] = expr; } @@ -866,7 +883,8 @@ class OrmGenerator extends GeneratorForAnnotation { } else if (floatTypes.contains(ctx.columns[field.name]?.type)) { value = refer('double') .property('tryParse') - .call([value.asA(refer('String'))]); + .call([value.asA(refer('String'))]).ifNullThen( + CodeExpression(Code('0.0'))); } else { value = value.asA(type); } diff --git a/packages/orm/angel_orm_generator/pubspec.yaml b/packages/orm/angel_orm_generator/pubspec.yaml index 91ffcc7e..e417d41a 100644 --- a/packages/orm/angel_orm_generator/pubspec.yaml +++ b/packages/orm/angel_orm_generator/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_orm_generator -version: 6.1.0 +version: 6.1.1 description: Code generators for Angel3 ORM. Generates query builder classes. homepage: https://angel3-framework.web.app/ repository: https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_orm_generator @@ -29,8 +29,8 @@ dev_dependencies: build_runner: ^2.0.1 postgres: ^2.4.0 test: ^1.21.0 - lints: ^1.0.0 -# dependency_overrides: + lints: ^2.0.0 +dependency_overrides: # angel3_container: # path: ../../container/angel_container # angel3_framework: @@ -45,10 +45,10 @@ dev_dependencies: # path: ../../mock_request # angel3_serialize: # path: ../../serialize/angel_serialize -# angel3_serialize_generator: -# path: ../../serialize/angel_serialize_generator -# angel3_orm: -# path: ../angel_orm + angel3_serialize_generator: + path: ../../serialize/angel_serialize_generator + angel3_orm: + path: ../angel_orm # angel3_migration: # path: ../angel_migration \ No newline at end of file diff --git a/packages/orm/angel_orm_test/CHANGELOG.md b/packages/orm/angel_orm_test/CHANGELOG.md index 72ee8360..f6493369 100644 --- a/packages/orm/angel_orm_test/CHANGELOG.md +++ b/packages/orm/angel_orm_test/CHANGELOG.md @@ -2,7 +2,8 @@ ## 6.0.1 -* Updated generated test cases +* Added test cases for non nullable type +* Upgraded to `lints` 2.x.x ## 6.0.0 diff --git a/packages/orm/angel_orm_test/lib/src/models/asset.dart b/packages/orm/angel_orm_test/lib/src/models/asset.dart new file mode 100644 index 00000000..96896c85 --- /dev/null +++ b/packages/orm/angel_orm_test/lib/src/models/asset.dart @@ -0,0 +1,23 @@ +import 'package:angel3_orm/angel3_orm.dart'; +import 'package:angel3_serialize/angel3_serialize.dart'; +import 'package:angel3_migration/angel3_migration.dart'; +import 'package:optional/optional.dart'; + +part 'asset.g.dart'; + +@serializable +@orm +abstract class _Item extends Model { + String get description; +} + +@serializable +@orm +abstract class _Asset extends Model { + String get description; + + String get name; + + @hasMany + List<_Item> get items; +} diff --git a/packages/orm/angel_orm_test/lib/src/models/asset.g.dart b/packages/orm/angel_orm_test/lib/src/models/asset.g.dart new file mode 100644 index 00000000..d17c1eef --- /dev/null +++ b/packages/orm/angel_orm_test/lib/src/models/asset.g.dart @@ -0,0 +1,658 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'asset.dart'; + +// ************************************************************************** +// MigrationGenerator +// ************************************************************************** + +class ItemMigration extends Migration { + @override + void up(Schema schema) { + schema.create('items', (table) { + table.serial('id').primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.varChar('description', length: 255); + }); + } + + @override + void down(Schema schema) { + schema.drop('items'); + } +} + +class AssetMigration extends Migration { + @override + void up(Schema schema) { + schema.create('assets', (table) { + table.serial('id').primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.varChar('description', length: 255); + table.varChar('name', length: 255); + }); + } + + @override + void down(Schema schema) { + schema.drop('assets', cascade: true); + } +} + +// ************************************************************************** +// OrmGenerator +// ************************************************************************** + +class ItemQuery extends Query { + ItemQuery({Query? parent, Set? trampoline}) : super(parent: parent) { + trampoline ??= {}; + trampoline.add(tableName); + _where = ItemQueryWhere(this); + } + + @override + final ItemQueryValues values = ItemQueryValues(); + + List _selectedFields = []; + + ItemQueryWhere? _where; + + @override + Map get casts { + return {}; + } + + @override + String get tableName { + return 'items'; + } + + @override + List get fields { + const _fields = ['id', 'created_at', 'updated_at', 'description']; + return _selectedFields.isEmpty + ? _fields + : _fields.where((field) => _selectedFields.contains(field)).toList(); + } + + ItemQuery select(List selectedFields) { + _selectedFields = selectedFields; + return this; + } + + @override + ItemQueryWhere? get where { + return _where; + } + + @override + ItemQueryWhere newWhereClause() { + return ItemQueryWhere(this); + } + + Optional parseRow(List row) { + if (row.every((x) => x == null)) { + return Optional.empty(); + } + var model = Item( + id: fields.contains('id') ? row[0].toString() : null, + createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, + updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + description: fields.contains('description') ? (row[3] as String) : ''); + return Optional.of(model); + } + + @override + Optional deserialize(List row) { + return parseRow(row); + } +} + +class ItemQueryWhere extends QueryWhere { + ItemQueryWhere(ItemQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), + description = StringSqlExpressionBuilder(query, 'description'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final StringSqlExpressionBuilder description; + + @override + List get expressionBuilders { + return [id, createdAt, updatedAt, description]; + } +} + +class ItemQueryValues extends MapQueryValues { + @override + Map 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 description { + return (values['description'] as String); + } + + set description(String value) => values['description'] = value; + void copyFrom(Item model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + description = model.description; + } +} + +class AssetQuery extends Query { + AssetQuery({Query? parent, Set? trampoline}) : super(parent: parent) { + trampoline ??= {}; + trampoline.add(tableName); + _where = AssetQueryWhere(this); + leftJoin(_items = ItemQuery(trampoline: trampoline, parent: this), 'id', + 'asset_id', + additionalFields: const [ + 'id', + 'created_at', + 'updated_at', + 'description' + ], + trampoline: trampoline); + } + + @override + final AssetQueryValues values = AssetQueryValues(); + + List _selectedFields = []; + + AssetQueryWhere? _where; + + late ItemQuery _items; + + @override + Map get casts { + return {}; + } + + @override + String get tableName { + return 'assets'; + } + + @override + List get fields { + const _fields = ['id', 'created_at', 'updated_at', 'description', 'name']; + return _selectedFields.isEmpty + ? _fields + : _fields.where((field) => _selectedFields.contains(field)).toList(); + } + + AssetQuery select(List selectedFields) { + _selectedFields = selectedFields; + return this; + } + + @override + AssetQueryWhere? get where { + return _where; + } + + @override + AssetQueryWhere newWhereClause() { + return AssetQueryWhere(this); + } + + Optional parseRow(List row) { + if (row.every((x) => x == null)) { + return Optional.empty(); + } + var model = Asset( + id: fields.contains('id') ? row[0].toString() : null, + createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, + updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + description: fields.contains('description') ? (row[3] as String) : '', + name: fields.contains('name') ? (row[4] as String) : ''); + if (row.length > 5) { + var modelOpt = ItemQuery().parseRow(row.skip(5).take(4).toList()); + modelOpt.ifPresent((m) { + model = model.copyWith(items: [m]); + }); + } + return Optional.of(model); + } + + @override + Optional deserialize(List row) { + return parseRow(row); + } + + ItemQuery get items { + return _items; + } + + @override + Future> 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( + items: List<_Item>.from(l.items)..addAll(model.items)); + } + }); + }); + } + + @override + Future> 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( + items: List<_Item>.from(l.items)..addAll(model.items)); + } + }); + }); + } + + @override + Future> 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( + items: List<_Item>.from(l.items)..addAll(model.items)); + } + }); + }); + } +} + +class AssetQueryWhere extends QueryWhere { + AssetQueryWhere(AssetQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), + description = StringSqlExpressionBuilder(query, 'description'), + name = StringSqlExpressionBuilder(query, 'name'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final StringSqlExpressionBuilder description; + + final StringSqlExpressionBuilder name; + + @override + List get expressionBuilders { + return [id, createdAt, updatedAt, description, name]; + } +} + +class AssetQueryValues extends MapQueryValues { + @override + Map 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 description { + return (values['description'] as String); + } + + set description(String value) => values['description'] = value; + String get name { + return (values['name'] as String); + } + + set name(String value) => values['name'] = value; + void copyFrom(Asset model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + description = model.description; + name = model.name; + } +} + +// ************************************************************************** +// JsonModelGenerator +// ************************************************************************** + +@generatedSerializable +class Item extends _Item { + Item({this.id, this.createdAt, this.updatedAt, required this.description}); + + /// 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 description; + + Item copyWith( + {String? id, + DateTime? createdAt, + DateTime? updatedAt, + String? description}) { + return Item( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + description: description ?? this.description); + } + + @override + bool operator ==(other) { + return other is _Item && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.description == description; + } + + @override + int get hashCode { + return hashObjects([id, createdAt, updatedAt, description]); + } + + @override + String toString() { + return 'Item(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, description=$description)'; + } + + Map toJson() { + return ItemSerializer.toMap(this); + } +} + +@generatedSerializable +class Asset extends _Asset { + Asset( + {this.id, + this.createdAt, + this.updatedAt, + required this.description, + required this.name, + List<_Item> items = const []}) + : items = List.unmodifiable(items); + + /// 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 description; + + @override + String name; + + @override + List<_Item> items; + + Asset copyWith( + {String? id, + DateTime? createdAt, + DateTime? updatedAt, + String? description, + String? name, + List<_Item>? items}) { + return Asset( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + description: description ?? this.description, + name: name ?? this.name, + items: items ?? this.items); + } + + @override + bool operator ==(other) { + return other is _Asset && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.description == description && + other.name == name && + ListEquality<_Item>(DefaultEquality<_Item>()) + .equals(other.items, items); + } + + @override + int get hashCode { + return hashObjects([id, createdAt, updatedAt, description, name, items]); + } + + @override + String toString() { + return 'Asset(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, description=$description, name=$name, items=$items)'; + } + + Map toJson() { + return AssetSerializer.toMap(this); + } +} + +// ************************************************************************** +// SerializerGenerator +// ************************************************************************** + +const ItemSerializer itemSerializer = ItemSerializer(); + +class ItemEncoder extends Converter { + const ItemEncoder(); + + @override + Map convert(Item model) => ItemSerializer.toMap(model); +} + +class ItemDecoder extends Converter { + const ItemDecoder(); + + @override + Item convert(Map map) => ItemSerializer.fromMap(map); +} + +class ItemSerializer extends Codec { + const ItemSerializer(); + + @override + ItemEncoder get encoder => const ItemEncoder(); + @override + ItemDecoder get decoder => const ItemDecoder(); + static Item fromMap(Map map) { + return Item( + 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, + description: map['description'] as String); + } + + static Map toMap(_Item? model) { + if (model == null) { + throw FormatException("Required field [model] cannot be null"); + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String(), + 'description': model.description + }; + } +} + +abstract class ItemFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + description + ]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; + + static const String description = 'description'; +} + +const AssetSerializer assetSerializer = AssetSerializer(); + +class AssetEncoder extends Converter { + const AssetEncoder(); + + @override + Map convert(Asset model) => AssetSerializer.toMap(model); +} + +class AssetDecoder extends Converter { + const AssetDecoder(); + + @override + Asset convert(Map map) => AssetSerializer.fromMap(map); +} + +class AssetSerializer extends Codec { + const AssetSerializer(); + + @override + AssetEncoder get encoder => const AssetEncoder(); + @override + AssetDecoder get decoder => const AssetDecoder(); + static Asset fromMap(Map map) { + return Asset( + 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, + description: map['description'] as String, + name: map['name'] as String, + items: map['items'] is Iterable + ? List.unmodifiable(((map['items'] as Iterable).whereType()) + .map(ItemSerializer.fromMap)) + : []); + } + + static Map toMap(_Asset? model) { + if (model == null) { + throw FormatException("Required field [model] cannot be null"); + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String(), + 'description': model.description, + 'name': model.name, + 'items': model.items.map((m) => ItemSerializer.toMap(m)).toList() + }; + } +} + +abstract class AssetFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + description, + name, + items + ]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; + + static const String description = 'description'; + + static const String name = 'name'; + + static const String items = 'items'; +} diff --git a/packages/orm/angel_orm_test/lib/src/models/bike.dart b/packages/orm/angel_orm_test/lib/src/models/bike.dart new file mode 100644 index 00000000..08db8929 --- /dev/null +++ b/packages/orm/angel_orm_test/lib/src/models/bike.dart @@ -0,0 +1,22 @@ +import 'package:angel3_orm/angel3_orm.dart'; +import 'package:angel3_serialize/angel3_serialize.dart'; +import 'package:angel3_migration/angel3_migration.dart'; +import 'package:optional/optional.dart'; + +part 'bike.g.dart'; + +@serializable +@orm +abstract class _Bike extends Model { + String get make; + + String get description; + + bool get familyFriendly; + + DateTime get recalledAt; + + double get price; + + int get width; +} diff --git a/packages/orm/angel_orm_test/lib/src/models/bike.g.dart b/packages/orm/angel_orm_test/lib/src/models/bike.g.dart new file mode 100644 index 00000000..5ade9210 --- /dev/null +++ b/packages/orm/angel_orm_test/lib/src/models/bike.g.dart @@ -0,0 +1,435 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'bike.dart'; + +// ************************************************************************** +// MigrationGenerator +// ************************************************************************** + +class BikeMigration extends Migration { + @override + void up(Schema schema) { + schema.create('bikes', (table) { + table.serial('id').primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.varChar('make', length: 255); + table.varChar('description', length: 255); + table.boolean('family_friendly'); + table.timeStamp('recalled_at'); + table.float('price'); + table.integer('width'); + }); + } + + @override + void down(Schema schema) { + schema.drop('bikes'); + } +} + +// ************************************************************************** +// OrmGenerator +// ************************************************************************** + +class BikeQuery extends Query { + BikeQuery({Query? parent, Set? trampoline}) : super(parent: parent) { + trampoline ??= {}; + trampoline.add(tableName); + _where = BikeQueryWhere(this); + } + + @override + final BikeQueryValues values = BikeQueryValues(); + + List _selectedFields = []; + + BikeQueryWhere? _where; + + @override + Map get casts { + return {'price': 'char'}; + } + + @override + String get tableName { + return 'bikes'; + } + + @override + List get fields { + const _fields = [ + 'id', + 'created_at', + 'updated_at', + 'make', + 'description', + 'family_friendly', + 'recalled_at', + 'price', + 'width' + ]; + return _selectedFields.isEmpty + ? _fields + : _fields.where((field) => _selectedFields.contains(field)).toList(); + } + + BikeQuery select(List selectedFields) { + _selectedFields = selectedFields; + return this; + } + + @override + BikeQueryWhere? get where { + return _where; + } + + @override + BikeQueryWhere newWhereClause() { + return BikeQueryWhere(this); + } + + Optional parseRow(List row) { + if (row.every((x) => x == null)) { + return Optional.empty(); + } + var model = Bike( + id: fields.contains('id') ? row[0].toString() : null, + createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, + updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + make: fields.contains('make') ? (row[3] as String) : '', + description: fields.contains('description') ? (row[4] as String) : '', + familyFriendly: + fields.contains('family_friendly') ? mapToBool(row[5]) : false, + recalledAt: fields.contains('recalled_at') + ? mapToDateTime(row[6]) + : DateTime.parse("1970-01-01 00:00:00"), + price: fields.contains('price') ? mapToDouble(row[7]) : 0.0, + width: fields.contains('width') ? (row[8] as int) : 0); + return Optional.of(model); + } + + @override + Optional deserialize(List row) { + return parseRow(row); + } +} + +class BikeQueryWhere extends QueryWhere { + BikeQueryWhere(BikeQuery 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'), + price = NumericSqlExpressionBuilder(query, 'price'), + width = NumericSqlExpressionBuilder(query, 'width'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final StringSqlExpressionBuilder make; + + final StringSqlExpressionBuilder description; + + final BooleanSqlExpressionBuilder familyFriendly; + + final DateTimeSqlExpressionBuilder recalledAt; + + final NumericSqlExpressionBuilder price; + + final NumericSqlExpressionBuilder width; + + @override + List get expressionBuilders { + return [ + id, + createdAt, + updatedAt, + make, + description, + familyFriendly, + recalledAt, + price, + width + ]; + } +} + +class BikeQueryValues extends MapQueryValues { + @override + Map get casts { + return {'price': 'double'}; + } + + 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; + double get price { + return double.tryParse((values['price'] as String)) ?? 0.0; + } + + set price(double value) => values['price'] = value.toString(); + int get width { + return (values['width'] as int); + } + + set width(int value) => values['width'] = value; + void copyFrom(Bike model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + make = model.make; + description = model.description; + familyFriendly = model.familyFriendly; + recalledAt = model.recalledAt; + price = model.price; + width = model.width; + } +} + +// ************************************************************************** +// JsonModelGenerator +// ************************************************************************** + +@generatedSerializable +class Bike extends _Bike { + Bike( + {this.id, + this.createdAt, + this.updatedAt, + required this.make, + required this.description, + required this.familyFriendly, + required this.recalledAt, + required this.price, + required this.width}); + + /// 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; + + @override + double price; + + @override + int width; + + Bike copyWith( + {String? id, + DateTime? createdAt, + DateTime? updatedAt, + String? make, + String? description, + bool? familyFriendly, + DateTime? recalledAt, + double? price, + int? width}) { + return Bike( + 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, + price: price ?? this.price, + width: width ?? this.width); + } + + @override + bool operator ==(other) { + return other is _Bike && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.make == make && + other.description == description && + other.familyFriendly == familyFriendly && + other.recalledAt == recalledAt && + other.price == price && + other.width == width; + } + + @override + int get hashCode { + return hashObjects([ + id, + createdAt, + updatedAt, + make, + description, + familyFriendly, + recalledAt, + price, + width + ]); + } + + @override + String toString() { + return 'Bike(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, make=$make, description=$description, familyFriendly=$familyFriendly, recalledAt=$recalledAt, price=$price, width=$width)'; + } + + Map toJson() { + return BikeSerializer.toMap(this); + } +} + +// ************************************************************************** +// SerializerGenerator +// ************************************************************************** + +const BikeSerializer bikeSerializer = BikeSerializer(); + +class BikeEncoder extends Converter { + const BikeEncoder(); + + @override + Map convert(Bike model) => BikeSerializer.toMap(model); +} + +class BikeDecoder extends Converter { + const BikeDecoder(); + + @override + Bike convert(Map map) => BikeSerializer.fromMap(map); +} + +class BikeSerializer extends Codec { + const BikeSerializer(); + + @override + BikeEncoder get encoder => const BikeEncoder(); + @override + BikeDecoder get decoder => const BikeDecoder(); + static Bike fromMap(Map map) { + return Bike( + 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())) + : DateTime.parse("1970-01-01 00:00:00"), + price: map['price'] as double, + width: map['width'] as int); + } + + static Map toMap(_Bike? model) { + if (model == null) { + throw FormatException("Required field [model] cannot be 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(), + 'price': model.price, + 'width': model.width + }; + } +} + +abstract class BikeFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + make, + description, + familyFriendly, + recalledAt, + price, + width + ]; + + 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'; + + static const String price = 'price'; + + static const String width = 'width'; +} diff --git a/packages/orm/angel_orm_test/lib/src/models/boat.dart b/packages/orm/angel_orm_test/lib/src/models/boat.dart new file mode 100644 index 00000000..f98d8610 --- /dev/null +++ b/packages/orm/angel_orm_test/lib/src/models/boat.dart @@ -0,0 +1,28 @@ +import 'package:angel3_orm/angel3_orm.dart'; +import 'package:angel3_serialize/angel3_serialize.dart'; +import 'package:angel3_migration/angel3_migration.dart'; +import 'package:optional/optional.dart'; + +part 'boat.g.dart'; + +@serializable +@orm +abstract class _Boat extends Model { + @SerializableField(defaultValue: '') + String get make; + + @SerializableField(defaultValue: 'none') + String get description; + + @SerializableField(defaultValue: false) + bool get familyFriendly; + + //@SerializableField(defaultValue: '1970-01-01 00:00:00') + DateTime get recalledAt; + + @SerializableField(defaultValue: 0.0) + double get price; + + @SerializableField(defaultValue: 0) + int get width; +} diff --git a/packages/orm/angel_orm_test/lib/src/models/boat.g.dart b/packages/orm/angel_orm_test/lib/src/models/boat.g.dart new file mode 100644 index 00000000..1f05b986 --- /dev/null +++ b/packages/orm/angel_orm_test/lib/src/models/boat.g.dart @@ -0,0 +1,435 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'boat.dart'; + +// ************************************************************************** +// MigrationGenerator +// ************************************************************************** + +class BoatMigration extends Migration { + @override + void up(Schema schema) { + schema.create('boats', (table) { + table.serial('id').primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + table.varChar('make', length: 255).defaultsTo(''); + table.varChar('description', length: 255).defaultsTo('none'); + table.boolean('family_friendly').defaultsTo(false); + table.timeStamp('recalled_at'); + table.float('price').defaultsTo(0.0); + table.integer('width').defaultsTo(0); + }); + } + + @override + void down(Schema schema) { + schema.drop('boats'); + } +} + +// ************************************************************************** +// OrmGenerator +// ************************************************************************** + +class BoatQuery extends Query { + BoatQuery({Query? parent, Set? trampoline}) : super(parent: parent) { + trampoline ??= {}; + trampoline.add(tableName); + _where = BoatQueryWhere(this); + } + + @override + final BoatQueryValues values = BoatQueryValues(); + + List _selectedFields = []; + + BoatQueryWhere? _where; + + @override + Map get casts { + return {'price': 'char'}; + } + + @override + String get tableName { + return 'boats'; + } + + @override + List get fields { + const _fields = [ + 'id', + 'created_at', + 'updated_at', + 'make', + 'description', + 'family_friendly', + 'recalled_at', + 'price', + 'width' + ]; + return _selectedFields.isEmpty + ? _fields + : _fields.where((field) => _selectedFields.contains(field)).toList(); + } + + BoatQuery select(List selectedFields) { + _selectedFields = selectedFields; + return this; + } + + @override + BoatQueryWhere? get where { + return _where; + } + + @override + BoatQueryWhere newWhereClause() { + return BoatQueryWhere(this); + } + + Optional parseRow(List row) { + if (row.every((x) => x == null)) { + return Optional.empty(); + } + var model = Boat( + id: fields.contains('id') ? row[0].toString() : null, + createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, + updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + make: fields.contains('make') ? (row[3] as String) : '', + description: fields.contains('description') ? (row[4] as String) : '', + familyFriendly: + fields.contains('family_friendly') ? mapToBool(row[5]) : false, + recalledAt: fields.contains('recalled_at') + ? mapToDateTime(row[6]) + : DateTime.parse("1970-01-01 00:00:00"), + price: fields.contains('price') ? mapToDouble(row[7]) : 0.0, + width: fields.contains('width') ? (row[8] as int) : 0); + return Optional.of(model); + } + + @override + Optional deserialize(List row) { + return parseRow(row); + } +} + +class BoatQueryWhere extends QueryWhere { + BoatQueryWhere(BoatQuery 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'), + price = NumericSqlExpressionBuilder(query, 'price'), + width = NumericSqlExpressionBuilder(query, 'width'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + final StringSqlExpressionBuilder make; + + final StringSqlExpressionBuilder description; + + final BooleanSqlExpressionBuilder familyFriendly; + + final DateTimeSqlExpressionBuilder recalledAt; + + final NumericSqlExpressionBuilder price; + + final NumericSqlExpressionBuilder width; + + @override + List get expressionBuilders { + return [ + id, + createdAt, + updatedAt, + make, + description, + familyFriendly, + recalledAt, + price, + width + ]; + } +} + +class BoatQueryValues extends MapQueryValues { + @override + Map get casts { + return {'price': 'double'}; + } + + 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; + double get price { + return double.tryParse((values['price'] as String)) ?? 0.0; + } + + set price(double value) => values['price'] = value.toString(); + int get width { + return (values['width'] as int); + } + + set width(int value) => values['width'] = value; + void copyFrom(Boat model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + make = model.make; + description = model.description; + familyFriendly = model.familyFriendly; + recalledAt = model.recalledAt; + price = model.price; + width = model.width; + } +} + +// ************************************************************************** +// JsonModelGenerator +// ************************************************************************** + +@generatedSerializable +class Boat extends _Boat { + Boat( + {this.id, + this.createdAt, + this.updatedAt, + this.make = '', + this.description = 'none', + this.familyFriendly = false, + required this.recalledAt, + this.price = 0.0, + this.width = 0}); + + /// 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; + + @override + double price; + + @override + int width; + + Boat copyWith( + {String? id, + DateTime? createdAt, + DateTime? updatedAt, + String? make, + String? description, + bool? familyFriendly, + DateTime? recalledAt, + double? price, + int? width}) { + return Boat( + 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, + price: price ?? this.price, + width: width ?? this.width); + } + + @override + bool operator ==(other) { + return other is _Boat && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.make == make && + other.description == description && + other.familyFriendly == familyFriendly && + other.recalledAt == recalledAt && + other.price == price && + other.width == width; + } + + @override + int get hashCode { + return hashObjects([ + id, + createdAt, + updatedAt, + make, + description, + familyFriendly, + recalledAt, + price, + width + ]); + } + + @override + String toString() { + return 'Boat(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, make=$make, description=$description, familyFriendly=$familyFriendly, recalledAt=$recalledAt, price=$price, width=$width)'; + } + + Map toJson() { + return BoatSerializer.toMap(this); + } +} + +// ************************************************************************** +// SerializerGenerator +// ************************************************************************** + +const BoatSerializer boatSerializer = BoatSerializer(); + +class BoatEncoder extends Converter { + const BoatEncoder(); + + @override + Map convert(Boat model) => BoatSerializer.toMap(model); +} + +class BoatDecoder extends Converter { + const BoatDecoder(); + + @override + Boat convert(Map map) => BoatSerializer.fromMap(map); +} + +class BoatSerializer extends Codec { + const BoatSerializer(); + + @override + BoatEncoder get encoder => const BoatEncoder(); + @override + BoatDecoder get decoder => const BoatDecoder(); + static Boat fromMap(Map map) { + return Boat( + 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? ?? 'none', + familyFriendly: map['family_friendly'] as bool? ?? false, + recalledAt: map['recalled_at'] != null + ? (map['recalled_at'] is DateTime + ? (map['recalled_at'] as DateTime) + : DateTime.parse(map['recalled_at'].toString())) + : DateTime.parse("1970-01-01 00:00:00"), + price: map['price'] as double? ?? 0.0, + width: map['width'] as int? ?? 0); + } + + static Map toMap(_Boat? model) { + if (model == null) { + throw FormatException("Required field [model] cannot be 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(), + 'price': model.price, + 'width': model.width + }; + } +} + +abstract class BoatFields { + static const List allFields = [ + id, + createdAt, + updatedAt, + make, + description, + familyFriendly, + recalledAt, + price, + width + ]; + + 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'; + + static const String price = 'price'; + + static const String width = 'width'; +} diff --git a/packages/orm/angel_orm_test/lib/src/models/leg.g.dart b/packages/orm/angel_orm_test/lib/src/models/leg.g.dart index cd7a7a3b..f930d54f 100644 --- a/packages/orm/angel_orm_test/lib/src/models/leg.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/leg.g.dart @@ -31,8 +31,7 @@ class FootMigration extends Migration { table.timeStamp('created_at'); table.timeStamp('updated_at'); table.integer('leg_id'); - table.declareColumn( - 'n_toes', Column(type: ColumnType('decimal'), length: 255)); + table.float('n_toes'); }); } @@ -280,7 +279,7 @@ class FootQueryWhere extends QueryWhere { class FootQueryValues extends MapQueryValues { @override Map get casts { - return {'n_toes': 'decimal'}; + return {'n_toes': 'double'}; } String? get id { @@ -304,7 +303,7 @@ class FootQueryValues extends MapQueryValues { set legId(int? value) => values['leg_id'] = value; double? get nToes { - return double.tryParse((values['n_toes'] as String)); + return double.tryParse((values['n_toes'] as String)) ?? 0.0; } set nToes(double? value) => values['n_toes'] = value.toString(); diff --git a/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart b/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart index f02b83db..d7908428 100644 --- a/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart @@ -15,8 +15,7 @@ class PersonOrderMigration extends Migration { table.timeStamp('updated_at'); table.integer('person_id'); table.varChar('name', length: 255); - table.declareColumn( - 'price', Column(type: ColumnType('decimal'), length: 255)); + table.float('price'); table.boolean('deleted'); }); } @@ -141,7 +140,7 @@ class PersonOrderQueryWhere extends QueryWhere { class PersonOrderQueryValues extends MapQueryValues { @override Map get casts { - return {'price': 'decimal'}; + return {'price': 'double'}; } String? get id { @@ -170,7 +169,7 @@ class PersonOrderQueryValues extends MapQueryValues { set name(String? value) => values['name'] = value; double? get price { - return double.tryParse((values['price'] as String)); + return double.tryParse((values['price'] as String)) ?? 0.0; } set price(double? value) => values['price'] = value.toString(); @@ -302,7 +301,7 @@ class OrderWithPersonInfoQueryWhere extends QueryWhere { class OrderWithPersonInfoQueryValues extends MapQueryValues { @override Map get casts { - return {'price': 'decimal'}; + return {'price': 'double'}; } String? get id { @@ -326,7 +325,7 @@ class OrderWithPersonInfoQueryValues extends MapQueryValues { set name(String? value) => values['name'] = value; double? get price { - return double.tryParse((values['price'] as String)); + return double.tryParse((values['price'] as String)) ?? 0.0; } set price(double? value) => values['price'] = value.toString(); diff --git a/packages/orm/angel_orm_test/pubspec.yaml b/packages/orm/angel_orm_test/pubspec.yaml index 61815dbc..140beeed 100644 --- a/packages/orm/angel_orm_test/pubspec.yaml +++ b/packages/orm/angel_orm_test/pubspec.yaml @@ -18,8 +18,8 @@ dev_dependencies: angel3_orm_generator: ^6.0.0 angel3_framework: ^6.0.0 build_runner: ^2.0.1 - lints: ^1.0.0 -# dependency_overrides: + lints: ^2.0.0 +dependency_overrides: # angel3_container: # path: ../../container/angel_container # angel3_framework: @@ -34,11 +34,11 @@ dev_dependencies: # path: ../../mock_request # angel3_serialize: # path: ../../serialize/angel_serialize - # angel3_serialize_generator: - # path: ../../serialize/angel_serialize_generator - # angel3_orm: - # path: ../angel_orm + angel3_serialize_generator: + path: ../../serialize/angel_serialize_generator + angel3_orm: + path: ../angel_orm # angel3_migration: # path: ../angel_migration - # angel3_orm_generator: - # path: ../angel_orm_generator + angel3_orm_generator: + path: ../angel_orm_generator diff --git a/packages/serialize/angel_serialize_generator/CHANGELOG.md b/packages/serialize/angel_serialize_generator/CHANGELOG.md index aabe632b..ff91d5e4 100644 --- a/packages/serialize/angel_serialize_generator/CHANGELOG.md +++ b/packages/serialize/angel_serialize_generator/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 6.1.1 + +* Fixed issue #68: Support for non-nullable type +* Upgraded to `lints` 2.x.x + ## 6.1.0 * Updated to `analyzer` 4.x.x diff --git a/packages/serialize/angel_serialize_generator/lib/serialize.dart b/packages/serialize/angel_serialize_generator/lib/serialize.dart index 3c91f21e..bede5a26 100644 --- a/packages/serialize/angel_serialize_generator/lib/serialize.dart +++ b/packages/serialize/angel_serialize_generator/lib/serialize.dart @@ -114,6 +114,7 @@ class ${pascal}Decoder extends Converter { })); } + // Generate toMapMethod void generateToMapMethod( ClassBuilder clazz, BuildContext ctx, LibraryBuilder file) { var originalClassName = ctx.originalClassName; @@ -178,7 +179,12 @@ class ${pascal}Decoder extends Converter { // Serialize dates else if (dateTimeTypeChecker.isAssignableFromType(type)) { - serializedRepresentation = 'model.${field.name}?.toIso8601String()'; + var question = + field.type.nullabilitySuffix == NullabilitySuffix.question + ? "?" + : ""; + serializedRepresentation = + 'model.${field.name}$question.toIso8601String()'; } // Serialize model classes via `XSerializer.toMap` @@ -246,6 +252,7 @@ class ${pascal}Decoder extends Converter { })); } + // Generate fromMapMethod void generateFromMapMethod( ClassBuilder clazz, BuildContext ctx, LibraryBuilder file) { clazz.methods.add(Method((method) { @@ -336,6 +343,13 @@ class ${pascal}Decoder extends Converter { var name = MirrorSystem.getName(fieldNameDeserializer); deserializedRepresentation = "$name(map['$alias'])"; } else if (dateTimeTypeChecker.isAssignableFromType(type)) { + if (field.type.nullabilitySuffix != NullabilitySuffix.question) { + if (defaultValue.toLowerCase() == 'null') { + defaultValue = 'DateTime.parse("1970-01-01 00:00:00")'; + } else { + defaultValue = 'DateTime.parse("$defaultValue")'; + } + } deserializedRepresentation = "map['$alias'] != null ? " "(map['$alias'] is DateTime ? (map['$alias'] as DateTime) : DateTime.parse(map['$alias'].toString()))" ' : $defaultValue'; diff --git a/packages/serialize/angel_serialize_generator/pubspec.yaml b/packages/serialize/angel_serialize_generator/pubspec.yaml index 2067cfb5..1d7b5778 100644 --- a/packages/serialize/angel_serialize_generator/pubspec.yaml +++ b/packages/serialize/angel_serialize_generator/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_serialize_generator -version: 6.1.0 +version: 6.1.1 description: Angel3 model serialization generators, designed for use with Angel. Combine with angel_serialize for flexible modeling. homepage: https://angel3-framework.web.app/ repository: https://github.com/dukefirehawk/angel/tree/master/packages/serialize/angel_serialize_generator @@ -22,7 +22,7 @@ dependencies: dev_dependencies: build_runner: ^2.0.1 collection: ^1.15.0 - lints: ^1.0.0 + lints: ^2.0.0 test: ^1.21.0 # dependency_overrides: # angel3_model: From da5b87043dd563fcd6b4f7e24a4de37b6b9d8130 Mon Sep 17 00:00:00 2001 From: thomashii Date: Sat, 11 Jun 2022 00:44:09 +0800 Subject: [PATCH 02/13] Updated ORM --- packages/orm/angel_migration/CHANGELOG.md | 4 ++ .../orm/angel_migration/lib/src/table.dart | 10 ++- packages/orm/angel_migration/pubspec.yaml | 10 +-- .../orm/angel_migration_runner/CHANGELOG.md | 4 ++ .../orm/angel_migration_runner/pubspec.yaml | 4 +- packages/orm/angel_orm/lib/src/migration.dart | 72 ++++++++++++------- packages/orm/angel_orm/lib/src/query.dart | 4 +- .../lib/src/migration_generator.dart | 8 +-- .../lib/src/orm_build_context.dart | 15 +++- .../lib/src/orm_generator.dart | 8 +-- packages/orm/angel_orm_generator/pubspec.yaml | 4 +- packages/orm/angel_orm_postgres/CHANGELOG.md | 4 ++ packages/orm/angel_orm_postgres/pubspec.yaml | 8 +-- .../test/migrations/person_order.sql | 2 +- .../angel_orm_test/lib/src/models/bike.g.dart | 2 +- .../angel_orm_test/lib/src/models/boat.g.dart | 2 +- .../angel_orm_test/lib/src/models/leg.g.dart | 2 +- .../angel_orm_test/lib/src/models/person.dart | 2 +- .../lib/src/models/person.g.dart | 12 ++-- .../lib/src/models/person_order.g.dart | 4 +- packages/orm/angel_orm_test/pubspec.yaml | 4 +- 21 files changed, 117 insertions(+), 68 deletions(-) diff --git a/packages/orm/angel_migration/CHANGELOG.md b/packages/orm/angel_migration/CHANGELOG.md index 375379d2..bb59d67a 100755 --- a/packages/orm/angel_migration/CHANGELOG.md +++ b/packages/orm/angel_migration/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 6.0.1 + +* Upgraded to `lints` 2.x.x + ## 6.0.0 * Updated to SDK 2.16.x diff --git a/packages/orm/angel_migration/lib/src/table.dart b/packages/orm/angel_migration/lib/src/table.dart index 15deb5c3..c7968848 100755 --- a/packages/orm/angel_migration/lib/src/table.dart +++ b/packages/orm/angel_migration/lib/src/table.dart @@ -13,7 +13,11 @@ abstract class Table { MigrationColumn float(String name) => declare(name, ColumnType.float); - MigrationColumn numeric(String name) => declare(name, ColumnType.numeric); + MigrationColumn double(String name) => declare(name, ColumnType.double); + + MigrationColumn numeric(String name, {int precision = 17, int scale = 3}) { + return declare(name, ColumnType.numeric); + } MigrationColumn boolean(String name) => declare(name, ColumnType.boolean); @@ -23,7 +27,9 @@ abstract class Table { //MigrationColumn dateTime(String name) => timeStamp(name, timezone: true); MigrationColumn timeStamp(String name, {bool timezone = false}) { - if (timezone != true) return declare(name, ColumnType.timeStamp); + if (!timezone) { + return declare(name, ColumnType.timeStamp); + } return declare(name, ColumnType.timeStampWithTimeZone); } diff --git a/packages/orm/angel_migration/pubspec.yaml b/packages/orm/angel_migration/pubspec.yaml index 67a6dad2..a2a381db 100755 --- a/packages/orm/angel_migration/pubspec.yaml +++ b/packages/orm/angel_migration/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_migration -version: 6.0.0 +version: 6.0.1 description: Database migration runtime for Angel3 ORM. Use this package to define schemas. homepage: https://angel3-framework.web.app/ repository: https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_migration @@ -8,7 +8,7 @@ environment: dependencies: angel3_orm: ^6.0.0 dev_dependencies: - lints: ^1.0.0 -# dependency_overrides: -# angel3_orm: -# path: ../angel_orm + lints: ^2.0.0 +dependency_overrides: + angel3_orm: + path: ../angel_orm diff --git a/packages/orm/angel_migration_runner/CHANGELOG.md b/packages/orm/angel_migration_runner/CHANGELOG.md index ed9c1855..11c2d4b4 100755 --- a/packages/orm/angel_migration_runner/CHANGELOG.md +++ b/packages/orm/angel_migration_runner/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 6.0.2 + +* Upgraded to `lints` 2.x.x + ## 6.0.1 * Added `MariaDbMigrationRunner` to support MariaDB migration with `mysql1` driver diff --git a/packages/orm/angel_migration_runner/pubspec.yaml b/packages/orm/angel_migration_runner/pubspec.yaml index 1f018cc5..0a5dfa71 100755 --- a/packages/orm/angel_migration_runner/pubspec.yaml +++ b/packages/orm/angel_migration_runner/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_migration_runner -version: 6.0.1 +version: 6.0.2 description: Command-line based database migration runner for Angel3's ORM. homepage: https://angel3-framework.web.app/ repository: https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_migration_runner @@ -15,7 +15,7 @@ dependencies: mysql1: ^0.19.0 logging: ^1.0.0 dev_dependencies: - lints: ^1.0.0 + lints: ^2.0.0 # dependency_overrides: # angel3_orm: # path: ../angel_orm diff --git a/packages/orm/angel_orm/lib/src/migration.dart b/packages/orm/angel_orm/lib/src/migration.dart index 0e48dea2..7a86e807 100644 --- a/packages/orm/angel_orm/lib/src/migration.dart +++ b/packages/orm/angel_orm/lib/src/migration.dart @@ -23,6 +23,15 @@ class Column { /// Specifies the length of a `VARCHAR`. final int length; + /// Specifies the precision of a `NUMERIC` or `DECIMAL`. + final int precision; + + /// Specifies the scale of a `NUMERIC` or `DECIMAL`. + final int scale; + + /// Specifies the timezone of a temporal field. + final String timezone; + /// Explicitly defines a SQL type for this column. final ColumnType type; @@ -35,7 +44,10 @@ class Column { const Column( {this.isNullable = true, this.length = 255, + this.precision = 17, + this.scale = 3, this.name = "", + this.timezone = "", this.type = ColumnType.varChar, this.indexType = IndexType.none, this.expression}); @@ -71,9 +83,16 @@ enum IndexType { class ColumnType { /// The name of this data type. final String name; - final bool hasSize; + final bool hasLength; + final bool hasPrecision; + final bool hasScale; + final bool hasTimezone; - const ColumnType(this.name, [this.hasSize = false]); + const ColumnType(this.name, + {this.hasLength = false, + this.hasPrecision = false, + this.hasScale = false, + this.hasTimezone = false}); static const ColumnType boolean = ColumnType('boolean'); @@ -87,13 +106,15 @@ class ColumnType { static const ColumnType smallInt = ColumnType('smallint'); static const ColumnType tinyInt = ColumnType('tinyint'); static const ColumnType bit = ColumnType('bit'); - static const ColumnType decimal = ColumnType('decimal', true); - static const ColumnType numeric = ColumnType('numeric', true); + static const ColumnType decimal = + ColumnType('decimal', hasPrecision: true, hasScale: true); + static const ColumnType numeric = + ColumnType('numeric', hasPrecision: true, hasScale: true); static const ColumnType money = ColumnType('money'); static const ColumnType smallMoney = ColumnType('smallmoney'); static const ColumnType float = ColumnType('float'); static const ColumnType real = ColumnType('real'); - static const ColumnType double = ColumnType('double'); + static const ColumnType double = ColumnType('double precision'); // Dates and times static const ColumnType dateTime = ColumnType('datetime'); @@ -102,35 +123,38 @@ class ColumnType { static const ColumnType time = ColumnType('time'); static const ColumnType timeStamp = ColumnType('timestamp'); static const ColumnType timeStampWithTimeZone = - ColumnType('timestamp with time zone'); + ColumnType('timestamptz', hasTimezone: true); // Strings - static const ColumnType char = ColumnType('char', true); - static const ColumnType varChar = ColumnType('varchar', true); + static const ColumnType char = ColumnType('char', hasLength: true); + static const ColumnType varChar = ColumnType('varchar', hasLength: true); static const ColumnType varCharMax = ColumnType('varchar(max)'); - static const ColumnType text = ColumnType('text', true); + static const ColumnType text = ColumnType('text', hasLength: true); // Unicode strings - static const ColumnType nChar = ColumnType('nchar', true); - static const ColumnType nVarChar = ColumnType('nvarchar', true); - static const ColumnType nVarCharMax = ColumnType('nvarchar(max)', true); - static const ColumnType nText = ColumnType('ntext', true); + static const ColumnType nChar = ColumnType('nchar', hasLength: true); + static const ColumnType nVarChar = ColumnType('nvarchar', hasLength: true); + static const ColumnType nVarCharMax = + ColumnType('nvarchar(max)', hasLength: true); + static const ColumnType nText = ColumnType('ntext', hasLength: true); // Binary - static const ColumnType binary = ColumnType('binary', true); - static const ColumnType varBinary = ColumnType('varbinary', true); - static const ColumnType varBinaryMax = ColumnType('varbinary(max)', true); - static const ColumnType image = ColumnType('image', true); + static const ColumnType binary = ColumnType('binary', hasLength: true); + static const ColumnType varBinary = ColumnType('varbinary', hasLength: true); + static const ColumnType varBinaryMax = + ColumnType('varbinary(max)', hasLength: true); + static const ColumnType image = ColumnType('image', hasLength: true); // JSON. - static const ColumnType json = ColumnType('json', true); - static const ColumnType jsonb = ColumnType('jsonb', true); + static const ColumnType json = ColumnType('json', hasLength: true); + static const ColumnType jsonb = ColumnType('jsonb', hasLength: true); // Misc. - static const ColumnType sqlVariant = ColumnType('sql_variant', true); + static const ColumnType sqlVariant = + ColumnType('sql_variant', hasLength: true); static const ColumnType uniqueIdentifier = - ColumnType('uniqueidentifier', true); - static const ColumnType xml = ColumnType('xml', true); - static const ColumnType cursor = ColumnType('cursor', true); - static const ColumnType table = ColumnType('table', true); + ColumnType('uniqueidentifier', hasLength: true); + static const ColumnType xml = ColumnType('xml', hasLength: true); + static const ColumnType cursor = ColumnType('cursor', hasLength: true); + static const ColumnType table = ColumnType('table', hasLength: true); } diff --git a/packages/orm/angel_orm/lib/src/query.dart b/packages/orm/angel_orm/lib/src/query.dart index b96f359e..fd07ce8b 100644 --- a/packages/orm/angel_orm/lib/src/query.dart +++ b/packages/orm/angel_orm/lib/src/query.dart @@ -377,7 +377,7 @@ abstract class Query extends QueryBase { var returningSql = ''; if (executor.dialect is PostgreSQLDialect) { var returning = fields.map(adornWithTableName).join(', '); - sql = 'WITH $tableName as ($insertion RETURNING $returning) ' + sql; + sql = 'WITH $tableName as ($insertion RETURNING $returning) $sql'; } else if (executor.dialect is MySQLDialect) { // Default to using 'id' as primary key in model if (fields.contains("id")) { @@ -422,7 +422,7 @@ abstract class Query extends QueryBase { var sql = compile({}); var returningSql = ''; if (executor.dialect is PostgreSQLDialect) { - sql = 'WITH $tableName as ($updateSql RETURNING $returning) ' + sql; + sql = 'WITH $tableName as ($updateSql RETURNING $returning) $sql'; } else if (executor.dialect is MySQLDialect) { returningSql = sql; sql = '$updateSql'; diff --git a/packages/orm/angel_orm_generator/lib/src/migration_generator.dart b/packages/orm/angel_orm_generator/lib/src/migration_generator.dart index a9a5d66c..b1f0cb79 100644 --- a/packages/orm/angel_orm_generator/lib/src/migration_generator.dart +++ b/packages/orm/angel_orm_generator/lib/src/migration_generator.dart @@ -135,7 +135,9 @@ class MigrationGenerator extends GeneratorForAnnotation { switch (col.type) { case ColumnType.varChar: methodName = 'varChar'; - named['length'] = literal(col.length); + if (col.type.hasLength) { + named['length'] = literal(col.length); + } break; case ColumnType.serial: methodName = 'serial'; @@ -148,9 +150,7 @@ class MigrationGenerator extends GeneratorForAnnotation { break; case ColumnType.numeric: methodName = 'numeric'; - break; - case ColumnType.double: - methodName = 'float'; + if (col.type.hasPrecision) {} break; case ColumnType.boolean: methodName = 'boolean'; diff --git a/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart b/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart index f9a12856..c9f972e8 100644 --- a/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart +++ b/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart @@ -342,10 +342,10 @@ ColumnType inferColumnType(DartType type) { return ColumnType.int; } if (const TypeChecker.fromRuntime(double).isAssignableFromType(type)) { - return ColumnType.double; + return ColumnType.float; } if (const TypeChecker.fromRuntime(num).isAssignableFromType(type)) { - return ColumnType.double; + return ColumnType.float; } if (const TypeChecker.fromRuntime(bool).isAssignableFromType(type)) { return ColumnType.boolean; @@ -426,7 +426,16 @@ class _ColumnType implements ColumnType { final String name; @override - final bool hasSize = false; + bool hasLength = false; + + @override + bool hasPrecision = false; + + @override + bool hasScale = false; + + @override + bool hasTimezone = false; //_ColumnType(this.name, [this.hasSize = false]); _ColumnType(this.name); diff --git a/packages/orm/angel_orm_generator/lib/src/orm_generator.dart b/packages/orm/angel_orm_generator/lib/src/orm_generator.dart index bf597ecf..8488c7f8 100644 --- a/packages/orm/angel_orm_generator/lib/src/orm_generator.dart +++ b/packages/orm/angel_orm_generator/lib/src/orm_generator.dart @@ -14,7 +14,6 @@ var floatTypes = [ ColumnType.float, ColumnType.numeric, ColumnType.real, - ColumnType.double, const ColumnType('double precision'), ]; @@ -498,7 +497,7 @@ class OrmGenerator extends GeneratorForAnnotation { // , b.write(foreignFields.isEmpty ? '' - : ', ' + foreignFields.join(', ')); + : ', ${foreignFields.join(', ')}'); // FROM users b.write(' FROM '); b.write(relationForeign.tableName); @@ -552,9 +551,8 @@ class OrmGenerator extends GeneratorForAnnotation { // There'll be a private `_field`, and then a getter, named `field`, // that returns the subquery object. - var foreignQueryType = refer(relationForeign - .buildContext.modelClassNameRecase.pascalCase + - 'Query'); + var foreignQueryType = refer( + '${relationForeign.buildContext.modelClassNameRecase.pascalCase}Query'); clazz ..fields.add(Field((b) => b diff --git a/packages/orm/angel_orm_generator/pubspec.yaml b/packages/orm/angel_orm_generator/pubspec.yaml index e417d41a..b9ac2e28 100644 --- a/packages/orm/angel_orm_generator/pubspec.yaml +++ b/packages/orm/angel_orm_generator/pubspec.yaml @@ -49,6 +49,6 @@ dependency_overrides: path: ../../serialize/angel_serialize_generator angel3_orm: path: ../angel_orm -# angel3_migration: -# path: ../angel_migration + angel3_migration: + path: ../angel_migration \ No newline at end of file diff --git a/packages/orm/angel_orm_postgres/CHANGELOG.md b/packages/orm/angel_orm_postgres/CHANGELOG.md index 55c462e6..fe6ac99c 100644 --- a/packages/orm/angel_orm_postgres/CHANGELOG.md +++ b/packages/orm/angel_orm_postgres/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 6.0.1 + +* Upgraded to `lints` 2.x.x + ## 6.0.0 * Updated to SDK 2.16.x diff --git a/packages/orm/angel_orm_postgres/pubspec.yaml b/packages/orm/angel_orm_postgres/pubspec.yaml index cce84d47..7766554a 100644 --- a/packages/orm/angel_orm_postgres/pubspec.yaml +++ b/packages/orm/angel_orm_postgres/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_orm_postgres -version: 6.0.0 +version: 6.0.1 description: PostgreSQL support for Angel3 ORM. Includes functionality for querying and transactions. homepage: https://angel3-framework.web.app/ repository: https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_orm_postgres @@ -15,7 +15,7 @@ dev_dependencies: belatuk_pretty_logging: ^4.0.0 angel3_orm_test: ^6.0.0 test: ^1.21.0 - lints: ^1.0.0 + lints: ^2.0.0 dependency_overrides: # angel3_serialize: # path: ../../serialize/angel_serialize @@ -25,5 +25,5 @@ dependency_overrides: path: ../angel_orm_test angel3_orm: path: ../angel_orm -# angel3_migration: -# path: ../angel_migration + angel3_migration: + path: ../angel_migration diff --git a/packages/orm/angel_orm_postgres/test/migrations/person_order.sql b/packages/orm/angel_orm_postgres/test/migrations/person_order.sql index 77220ff7..9634def1 100644 --- a/packages/orm/angel_orm_postgres/test/migrations/person_order.sql +++ b/packages/orm/angel_orm_postgres/test/migrations/person_order.sql @@ -2,7 +2,7 @@ CREATE TEMPORARY TABLE "person_orders" ( "id" serial PRIMARY KEY, "person_id" int not null, "name" varchar(255), - "price" int, + "price" float, "deleted" bool not null default false, "created_at" timestamp, "updated_at" timestamp diff --git a/packages/orm/angel_orm_test/lib/src/models/bike.g.dart b/packages/orm/angel_orm_test/lib/src/models/bike.g.dart index 5ade9210..52652e76 100644 --- a/packages/orm/angel_orm_test/lib/src/models/bike.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/bike.g.dart @@ -164,7 +164,7 @@ class BikeQueryWhere extends QueryWhere { class BikeQueryValues extends MapQueryValues { @override Map get casts { - return {'price': 'double'}; + return {'price': 'float'}; } String? get id { diff --git a/packages/orm/angel_orm_test/lib/src/models/boat.g.dart b/packages/orm/angel_orm_test/lib/src/models/boat.g.dart index 1f05b986..a15cdf85 100644 --- a/packages/orm/angel_orm_test/lib/src/models/boat.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/boat.g.dart @@ -164,7 +164,7 @@ class BoatQueryWhere extends QueryWhere { class BoatQueryValues extends MapQueryValues { @override Map get casts { - return {'price': 'double'}; + return {'price': 'float'}; } String? get id { diff --git a/packages/orm/angel_orm_test/lib/src/models/leg.g.dart b/packages/orm/angel_orm_test/lib/src/models/leg.g.dart index f930d54f..d20a0306 100644 --- a/packages/orm/angel_orm_test/lib/src/models/leg.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/leg.g.dart @@ -279,7 +279,7 @@ class FootQueryWhere extends QueryWhere { class FootQueryValues extends MapQueryValues { @override Map get casts { - return {'n_toes': 'double'}; + return {'n_toes': 'float'}; } String? get id { diff --git a/packages/orm/angel_orm_test/lib/src/models/person.dart b/packages/orm/angel_orm_test/lib/src/models/person.dart index 8ea4be24..56403bd5 100644 --- a/packages/orm/angel_orm_test/lib/src/models/person.dart +++ b/packages/orm/angel_orm_test/lib/src/models/person.dart @@ -22,5 +22,5 @@ class _PersonWithLastOrder { String? lastOrderName; @Column(expression: 'po.price') - int? lastOrderPrice; + double? lastOrderPrice; } diff --git a/packages/orm/angel_orm_test/lib/src/models/person.g.dart b/packages/orm/angel_orm_test/lib/src/models/person.g.dart index b18bc29b..1b7e2622 100644 --- a/packages/orm/angel_orm_test/lib/src/models/person.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/person.g.dart @@ -179,7 +179,7 @@ class PersonWithLastOrderQuery @override Map get casts { - return {}; + return {'last_order_price': 'char'}; } @override @@ -219,7 +219,7 @@ class PersonWithLastOrderQuery lastOrderName: fields.contains('last_order_name') ? (row[1] as String?) : null, lastOrderPrice: - fields.contains('last_order_price') ? (row[2] as int?) : null); + fields.contains('last_order_price') ? mapToDouble(row[2]) : null); return Optional.of(model); } @@ -244,7 +244,7 @@ class PersonWithLastOrderQueryWhere extends QueryWhere { class PersonWithLastOrderQueryValues extends MapQueryValues { @override Map get casts { - return {}; + return {'last_order_price': 'float'}; } String? get name { @@ -333,10 +333,10 @@ class PersonWithLastOrder extends _PersonWithLastOrder { String? lastOrderName; @override - int? lastOrderPrice; + double? lastOrderPrice; PersonWithLastOrder copyWith( - {String? name, String? lastOrderName, int? lastOrderPrice}) { + {String? name, String? lastOrderName, double? lastOrderPrice}) { return PersonWithLastOrder( name: name ?? this.name, lastOrderName: lastOrderName ?? this.lastOrderName, @@ -474,7 +474,7 @@ class PersonWithLastOrderSerializer extends Codec { return PersonWithLastOrder( name: map['name'] as String?, lastOrderName: map['last_order_name'] as String?, - lastOrderPrice: map['last_order_price'] as int?); + lastOrderPrice: map['last_order_price'] as double?); } static Map toMap(_PersonWithLastOrder? model) { diff --git a/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart b/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart index d7908428..6f832c88 100644 --- a/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart @@ -140,7 +140,7 @@ class PersonOrderQueryWhere extends QueryWhere { class PersonOrderQueryValues extends MapQueryValues { @override Map get casts { - return {'price': 'double'}; + return {'price': 'float'}; } String? get id { @@ -301,7 +301,7 @@ class OrderWithPersonInfoQueryWhere extends QueryWhere { class OrderWithPersonInfoQueryValues extends MapQueryValues { @override Map get casts { - return {'price': 'double'}; + return {'price': 'float'}; } String? get id { diff --git a/packages/orm/angel_orm_test/pubspec.yaml b/packages/orm/angel_orm_test/pubspec.yaml index 140beeed..7eb623b7 100644 --- a/packages/orm/angel_orm_test/pubspec.yaml +++ b/packages/orm/angel_orm_test/pubspec.yaml @@ -38,7 +38,7 @@ dependency_overrides: path: ../../serialize/angel_serialize_generator angel3_orm: path: ../angel_orm - # angel3_migration: - # path: ../angel_migration + angel3_migration: + path: ../angel_migration angel3_orm_generator: path: ../angel_orm_generator From 224d2be0265b61ebdec325b3ff54281710774d45 Mon Sep 17 00:00:00 2001 From: thomashii Date: Sat, 11 Jun 2022 14:39:29 +0800 Subject: [PATCH 03/13] Fixed issue 70 --- .../orm/angel_migration_runner/CHANGELOG.md | 1 + .../lib/src/mariadb/table.dart | 2 +- .../lib/src/mysql/table.dart | 2 +- .../lib/src/postgres/table.dart | 15 +++--- .../orm/angel_migration_runner/pubspec.yaml | 10 ++-- packages/orm/angel_orm/lib/src/migration.dart | 30 +++++------ .../lib/src/migration_generator.dart | 5 +- .../lib/src/orm_build_context.dart | 8 ++- .../orm/angel_orm_generator/mono_pkg.yaml | 0 .../angel_orm_test/lib/src/models/asset.dart | 3 ++ .../lib/src/models/asset.g.dart | 51 +++++++++++++++---- .../angel_orm_test/lib/src/models/bike.g.dart | 4 +- .../angel_orm_test/lib/src/models/boat.g.dart | 4 +- .../angel_orm_test/lib/src/models/leg.g.dart | 4 +- .../lib/src/models/person.g.dart | 2 +- .../lib/src/models/person_order.g.dart | 6 +-- packages/orm/angel_orm_test/mono_pkg.yaml | 0 17 files changed, 92 insertions(+), 55 deletions(-) delete mode 100644 packages/orm/angel_orm_generator/mono_pkg.yaml delete mode 100644 packages/orm/angel_orm_test/mono_pkg.yaml diff --git a/packages/orm/angel_migration_runner/CHANGELOG.md b/packages/orm/angel_migration_runner/CHANGELOG.md index 11c2d4b4..b611dd08 100755 --- a/packages/orm/angel_migration_runner/CHANGELOG.md +++ b/packages/orm/angel_migration_runner/CHANGELOG.md @@ -3,6 +3,7 @@ ## 6.0.2 * Upgraded to `lints` 2.x.x +* Fixed issue #70. Incorrectly generated SQL for `defaultsTo('Default Value')` ## 6.0.1 diff --git a/packages/orm/angel_migration_runner/lib/src/mariadb/table.dart b/packages/orm/angel_migration_runner/lib/src/mariadb/table.dart index 16e33500..08ed0b47 100644 --- a/packages/orm/angel_migration_runner/lib/src/mariadb/table.dart +++ b/packages/orm/angel_migration_runner/lib/src/mariadb/table.dart @@ -6,7 +6,7 @@ import 'package:charcode/ascii.dart'; abstract class MariaDbGenerator { static String columnType(MigrationColumn column) { var str = column.type.name; - if (column.type.hasSize) { + if (column.type.hasLength) { return '$str(${column.length})'; } else { return str; diff --git a/packages/orm/angel_migration_runner/lib/src/mysql/table.dart b/packages/orm/angel_migration_runner/lib/src/mysql/table.dart index 22b86ea2..32d93f57 100644 --- a/packages/orm/angel_migration_runner/lib/src/mysql/table.dart +++ b/packages/orm/angel_migration_runner/lib/src/mysql/table.dart @@ -6,7 +6,7 @@ import 'package:charcode/ascii.dart'; abstract class MySqlGenerator { static String columnType(MigrationColumn column) { var str = column.type.name; - if (column.type.hasSize) { + if (column.type.hasLength) { return '$str(${column.length})'; } else { return str; diff --git a/packages/orm/angel_migration_runner/lib/src/postgres/table.dart b/packages/orm/angel_migration_runner/lib/src/postgres/table.dart index dfbf76b3..4ca12528 100755 --- a/packages/orm/angel_migration_runner/lib/src/postgres/table.dart +++ b/packages/orm/angel_migration_runner/lib/src/postgres/table.dart @@ -6,7 +6,7 @@ import 'package:charcode/ascii.dart'; abstract class PostgresGenerator { static String columnType(MigrationColumn column) { var str = column.type.name; - if (column.type.hasSize) { + if (column.type.hasLength) { return '$str(${column.length})'; } else { return str; @@ -31,11 +31,10 @@ abstract class PostgresGenerator { b.writeCharCode(ch); } } - s = b.toString(); + s = '\'${b.toString()}\''; } else { s = value.toString(); } - buf.write(' DEFAULT $s'); } @@ -46,7 +45,7 @@ abstract class PostgresGenerator { } for (var ref in column.externalReferences) { - buf.write(' ' + compileReference(ref)); + buf.write(' ${compileReference(ref)}'); } return buf.toString(); @@ -55,7 +54,7 @@ abstract class PostgresGenerator { static String compileReference(MigrationColumnReference ref) { var buf = StringBuffer('REFERENCES "${ref.foreignTable}"("${ref.foreignKey}")'); - if (ref.behavior != null) buf.write(' ' + ref.behavior!); + if (ref.behavior != null) buf.write(' ${ref.behavior!}'); return buf.toString(); } } @@ -147,9 +146,9 @@ class PostgresAlterTable extends Table implements MutableTable { } @override - void changeColumnType(String name, ColumnType type, {int length = 256}) { - _stack.add('ALTER COLUMN "$name" TYPE ' + - PostgresGenerator.columnType(MigrationColumn(type, length: length))); + void changeColumnType(String name, ColumnType type, {int length = 255}) { + _stack.add( + 'ALTER COLUMN "$name" TYPE ${PostgresGenerator.columnType(MigrationColumn(type, length: length))}'); } @override diff --git a/packages/orm/angel_migration_runner/pubspec.yaml b/packages/orm/angel_migration_runner/pubspec.yaml index 0a5dfa71..e1f72d46 100755 --- a/packages/orm/angel_migration_runner/pubspec.yaml +++ b/packages/orm/angel_migration_runner/pubspec.yaml @@ -16,8 +16,8 @@ dependencies: logging: ^1.0.0 dev_dependencies: lints: ^2.0.0 -# dependency_overrides: -# angel3_orm: -# path: ../angel_orm -# angel3_migration: -# path: ../angel_migration +dependency_overrides: + angel3_orm: + path: ../angel_orm + angel3_migration: + path: ../angel_migration diff --git a/packages/orm/angel_orm/lib/src/migration.dart b/packages/orm/angel_orm/lib/src/migration.dart index 7a86e807..0b5533f7 100644 --- a/packages/orm/angel_orm/lib/src/migration.dart +++ b/packages/orm/angel_orm/lib/src/migration.dart @@ -129,32 +129,28 @@ class ColumnType { static const ColumnType char = ColumnType('char', hasLength: true); static const ColumnType varChar = ColumnType('varchar', hasLength: true); static const ColumnType varCharMax = ColumnType('varchar(max)'); - static const ColumnType text = ColumnType('text', hasLength: true); + static const ColumnType text = ColumnType('text'); // Unicode strings static const ColumnType nChar = ColumnType('nchar', hasLength: true); static const ColumnType nVarChar = ColumnType('nvarchar', hasLength: true); - static const ColumnType nVarCharMax = - ColumnType('nvarchar(max)', hasLength: true); + static const ColumnType nVarCharMax = ColumnType('nvarchar(max)'); static const ColumnType nText = ColumnType('ntext', hasLength: true); // Binary - static const ColumnType binary = ColumnType('binary', hasLength: true); - static const ColumnType varBinary = ColumnType('varbinary', hasLength: true); - static const ColumnType varBinaryMax = - ColumnType('varbinary(max)', hasLength: true); - static const ColumnType image = ColumnType('image', hasLength: true); + static const ColumnType binary = ColumnType('binary'); + static const ColumnType varBinary = ColumnType('varbinary'); + static const ColumnType varBinaryMax = ColumnType('varbinary(max)'); + static const ColumnType image = ColumnType('image'); // JSON. - static const ColumnType json = ColumnType('json', hasLength: true); - static const ColumnType jsonb = ColumnType('jsonb', hasLength: true); + static const ColumnType json = ColumnType('json'); + static const ColumnType jsonb = ColumnType('jsonb'); // Misc. - static const ColumnType sqlVariant = - ColumnType('sql_variant', hasLength: true); - static const ColumnType uniqueIdentifier = - ColumnType('uniqueidentifier', hasLength: true); - static const ColumnType xml = ColumnType('xml', hasLength: true); - static const ColumnType cursor = ColumnType('cursor', hasLength: true); - static const ColumnType table = ColumnType('table', hasLength: true); + static const ColumnType sqlVariant = ColumnType('sql_variant'); + static const ColumnType uniqueIdentifier = ColumnType('uniqueidentifier'); + static const ColumnType xml = ColumnType('xml'); + static const ColumnType cursor = ColumnType('cursor'); + static const ColumnType table = ColumnType('table'); } diff --git a/packages/orm/angel_orm_generator/lib/src/migration_generator.dart b/packages/orm/angel_orm_generator/lib/src/migration_generator.dart index b1f0cb79..86d1cdc8 100644 --- a/packages/orm/angel_orm_generator/lib/src/migration_generator.dart +++ b/packages/orm/angel_orm_generator/lib/src/migration_generator.dart @@ -148,6 +148,9 @@ class MigrationGenerator extends GeneratorForAnnotation { case ColumnType.float: methodName = 'float'; break; + case ColumnType.double: + methodName = 'double'; + break; case ColumnType.numeric: methodName = 'numeric'; if (col.type.hasPrecision) {} @@ -233,7 +236,7 @@ class MigrationGenerator extends GeneratorForAnnotation { cascade.add(refer('unique').call([])); } - if (col.isNullable != true) { + if (!col.isNullable) { cascade.add(refer('notNull').call([])); } diff --git a/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart b/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart index c9f972e8..67759e98 100644 --- a/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart +++ b/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart @@ -105,7 +105,9 @@ Future buildOrmContext( // Check for column annotation... var element = _findElement(field); var columnAnnotation = columnTypeChecker.firstAnnotationOf(element); - // print('${element.name} => $columnAnnotation'); + if (columnAnnotation != null) { + print('[ORM_BUILD_CONTEXT] ${element.name} => $columnAnnotation'); + } Column? column; if (columnAnnotation != null) { @@ -334,6 +336,7 @@ Future buildOrmContext( return ctx; } +// Detect and return the correct column type ColumnType inferColumnType(DartType type) { if (const TypeChecker.fromRuntime(String).isAssignableFromType(type)) { return ColumnType.varChar; @@ -342,7 +345,7 @@ ColumnType inferColumnType(DartType type) { return ColumnType.int; } if (const TypeChecker.fromRuntime(double).isAssignableFromType(type)) { - return ColumnType.float; + return ColumnType.double; } if (const TypeChecker.fromRuntime(num).isAssignableFromType(type)) { return ColumnType.float; @@ -401,6 +404,7 @@ Column reviveColumn(ConstantReader cr) { const TypeChecker relationshipTypeChecker = TypeChecker.fromRuntime(Relationship); +// ORM builder context class OrmBuildContext { final BuildContext buildContext; final Orm ormAnnotation; diff --git a/packages/orm/angel_orm_generator/mono_pkg.yaml b/packages/orm/angel_orm_generator/mono_pkg.yaml deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/orm/angel_orm_test/lib/src/models/asset.dart b/packages/orm/angel_orm_test/lib/src/models/asset.dart index 96896c85..2a3bc496 100644 --- a/packages/orm/angel_orm_test/lib/src/models/asset.dart +++ b/packages/orm/angel_orm_test/lib/src/models/asset.dart @@ -18,6 +18,9 @@ abstract class _Asset extends Model { String get name; + @Column(type: ColumnType.numeric, precision: 17, scale: 3) + double get price; + @hasMany List<_Item> get items; } diff --git a/packages/orm/angel_orm_test/lib/src/models/asset.g.dart b/packages/orm/angel_orm_test/lib/src/models/asset.g.dart index d17c1eef..ef882202 100644 --- a/packages/orm/angel_orm_test/lib/src/models/asset.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/asset.g.dart @@ -32,6 +32,7 @@ class AssetMigration extends Migration { table.timeStamp('updated_at'); table.varChar('description', length: 255); table.varChar('name', length: 255); + table.double('price'); }); } @@ -191,7 +192,7 @@ class AssetQuery extends Query { @override Map get casts { - return {}; + return {'price': 'char'}; } @override @@ -201,7 +202,14 @@ class AssetQuery extends Query { @override List get fields { - const _fields = ['id', 'created_at', 'updated_at', 'description', 'name']; + const _fields = [ + 'id', + 'created_at', + 'updated_at', + 'description', + 'name', + 'price' + ]; return _selectedFields.isEmpty ? _fields : _fields.where((field) => _selectedFields.contains(field)).toList(); @@ -231,9 +239,10 @@ class AssetQuery extends Query { createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, description: fields.contains('description') ? (row[3] as String) : '', - name: fields.contains('name') ? (row[4] as String) : ''); - if (row.length > 5) { - var modelOpt = ItemQuery().parseRow(row.skip(5).take(4).toList()); + name: fields.contains('name') ? (row[4] as String) : '', + price: fields.contains('price') ? mapToDouble(row[5]) : 0.0); + if (row.length > 6) { + var modelOpt = ItemQuery().parseRow(row.skip(6).take(4).toList()); modelOpt.ifPresent((m) { model = model.copyWith(items: [m]); }); @@ -311,7 +320,8 @@ class AssetQueryWhere extends QueryWhere { createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), description = StringSqlExpressionBuilder(query, 'description'), - name = StringSqlExpressionBuilder(query, 'name'); + name = StringSqlExpressionBuilder(query, 'name'), + price = NumericSqlExpressionBuilder(query, 'price'); final NumericSqlExpressionBuilder id; @@ -323,16 +333,18 @@ class AssetQueryWhere extends QueryWhere { final StringSqlExpressionBuilder name; + final NumericSqlExpressionBuilder price; + @override List get expressionBuilders { - return [id, createdAt, updatedAt, description, name]; + return [id, createdAt, updatedAt, description, name, price]; } } class AssetQueryValues extends MapQueryValues { @override Map get casts { - return {}; + return {'price': 'double precision'}; } String? get id { @@ -360,11 +372,17 @@ class AssetQueryValues extends MapQueryValues { } set name(String value) => values['name'] = value; + double get price { + return double.tryParse((values['price'] as String)) ?? 0.0; + } + + set price(double value) => values['price'] = value.toString(); void copyFrom(Asset model) { createdAt = model.createdAt; updatedAt = model.updatedAt; description = model.description; name = model.name; + price = model.price; } } @@ -435,6 +453,7 @@ class Asset extends _Asset { this.updatedAt, required this.description, required this.name, + required this.price, List<_Item> items = const []}) : items = List.unmodifiable(items); @@ -456,6 +475,9 @@ class Asset extends _Asset { @override String name; + @override + double price; + @override List<_Item> items; @@ -465,6 +487,7 @@ class Asset extends _Asset { DateTime? updatedAt, String? description, String? name, + double? price, List<_Item>? items}) { return Asset( id: id ?? this.id, @@ -472,6 +495,7 @@ class Asset extends _Asset { updatedAt: updatedAt ?? this.updatedAt, description: description ?? this.description, name: name ?? this.name, + price: price ?? this.price, items: items ?? this.items); } @@ -483,18 +507,20 @@ class Asset extends _Asset { other.updatedAt == updatedAt && other.description == description && other.name == name && + other.price == price && ListEquality<_Item>(DefaultEquality<_Item>()) .equals(other.items, items); } @override int get hashCode { - return hashObjects([id, createdAt, updatedAt, description, name, items]); + return hashObjects( + [id, createdAt, updatedAt, description, name, price, items]); } @override String toString() { - return 'Asset(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, description=$description, name=$name, items=$items)'; + return 'Asset(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, description=$description, name=$name, price=$price, items=$items)'; } Map toJson() { @@ -613,6 +639,7 @@ class AssetSerializer extends Codec { : null, description: map['description'] as String, name: map['name'] as String, + price: map['price'] as double, items: map['items'] is Iterable ? List.unmodifiable(((map['items'] as Iterable).whereType()) .map(ItemSerializer.fromMap)) @@ -629,6 +656,7 @@ class AssetSerializer extends Codec { 'updated_at': model.updatedAt?.toIso8601String(), 'description': model.description, 'name': model.name, + 'price': model.price, 'items': model.items.map((m) => ItemSerializer.toMap(m)).toList() }; } @@ -641,6 +669,7 @@ abstract class AssetFields { updatedAt, description, name, + price, items ]; @@ -654,5 +683,7 @@ abstract class AssetFields { static const String name = 'name'; + static const String price = 'price'; + static const String items = 'items'; } diff --git a/packages/orm/angel_orm_test/lib/src/models/bike.g.dart b/packages/orm/angel_orm_test/lib/src/models/bike.g.dart index 52652e76..9397418d 100644 --- a/packages/orm/angel_orm_test/lib/src/models/bike.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/bike.g.dart @@ -17,7 +17,7 @@ class BikeMigration extends Migration { table.varChar('description', length: 255); table.boolean('family_friendly'); table.timeStamp('recalled_at'); - table.float('price'); + table.double('price'); table.integer('width'); }); } @@ -164,7 +164,7 @@ class BikeQueryWhere extends QueryWhere { class BikeQueryValues extends MapQueryValues { @override Map get casts { - return {'price': 'float'}; + return {'price': 'double precision'}; } String? get id { diff --git a/packages/orm/angel_orm_test/lib/src/models/boat.g.dart b/packages/orm/angel_orm_test/lib/src/models/boat.g.dart index a15cdf85..4613a92b 100644 --- a/packages/orm/angel_orm_test/lib/src/models/boat.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/boat.g.dart @@ -17,7 +17,7 @@ class BoatMigration extends Migration { table.varChar('description', length: 255).defaultsTo('none'); table.boolean('family_friendly').defaultsTo(false); table.timeStamp('recalled_at'); - table.float('price').defaultsTo(0.0); + table.double('price').defaultsTo(0.0); table.integer('width').defaultsTo(0); }); } @@ -164,7 +164,7 @@ class BoatQueryWhere extends QueryWhere { class BoatQueryValues extends MapQueryValues { @override Map get casts { - return {'price': 'float'}; + return {'price': 'double precision'}; } String? get id { diff --git a/packages/orm/angel_orm_test/lib/src/models/leg.g.dart b/packages/orm/angel_orm_test/lib/src/models/leg.g.dart index d20a0306..336689eb 100644 --- a/packages/orm/angel_orm_test/lib/src/models/leg.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/leg.g.dart @@ -31,7 +31,7 @@ class FootMigration extends Migration { table.timeStamp('created_at'); table.timeStamp('updated_at'); table.integer('leg_id'); - table.float('n_toes'); + table.double('n_toes'); }); } @@ -279,7 +279,7 @@ class FootQueryWhere extends QueryWhere { class FootQueryValues extends MapQueryValues { @override Map get casts { - return {'n_toes': 'float'}; + return {'n_toes': 'double precision'}; } String? get id { diff --git a/packages/orm/angel_orm_test/lib/src/models/person.g.dart b/packages/orm/angel_orm_test/lib/src/models/person.g.dart index 1b7e2622..f76b4bee 100644 --- a/packages/orm/angel_orm_test/lib/src/models/person.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/person.g.dart @@ -244,7 +244,7 @@ class PersonWithLastOrderQueryWhere extends QueryWhere { class PersonWithLastOrderQueryValues extends MapQueryValues { @override Map get casts { - return {'last_order_price': 'float'}; + return {'last_order_price': 'double precision'}; } String? get name { diff --git a/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart b/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart index 6f832c88..04ce92cb 100644 --- a/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart @@ -15,7 +15,7 @@ class PersonOrderMigration extends Migration { table.timeStamp('updated_at'); table.integer('person_id'); table.varChar('name', length: 255); - table.float('price'); + table.double('price'); table.boolean('deleted'); }); } @@ -140,7 +140,7 @@ class PersonOrderQueryWhere extends QueryWhere { class PersonOrderQueryValues extends MapQueryValues { @override Map get casts { - return {'price': 'float'}; + return {'price': 'double precision'}; } String? get id { @@ -301,7 +301,7 @@ class OrderWithPersonInfoQueryWhere extends QueryWhere { class OrderWithPersonInfoQueryValues extends MapQueryValues { @override Map get casts { - return {'price': 'float'}; + return {'price': 'double precision'}; } String? get id { diff --git a/packages/orm/angel_orm_test/mono_pkg.yaml b/packages/orm/angel_orm_test/mono_pkg.yaml deleted file mode 100644 index e69de29b..00000000 From 6c51e7a23161449db124380363182f74f4bd01ce Mon Sep 17 00:00:00 2001 From: thomashii Date: Tue, 14 Jun 2022 11:19:24 +0800 Subject: [PATCH 04/13] Added default to Column --- .../orm/angel_migration/lib/src/column.dart | 9 +++++-- packages/orm/angel_orm/CHANGELOG.md | 1 + packages/orm/angel_orm/lib/src/migration.dart | 16 +++++++----- .../lib/src/migration_generator.dart | 25 ++++++++++++++++--- .../lib/src/orm_build_context.dart | 7 +++--- 5 files changed, 43 insertions(+), 15 deletions(-) diff --git a/packages/orm/angel_migration/lib/src/column.dart b/packages/orm/angel_migration/lib/src/column.dart index 41be1f13..8d92038f 100755 --- a/packages/orm/angel_migration/lib/src/column.dart +++ b/packages/orm/angel_migration/lib/src/column.dart @@ -12,6 +12,7 @@ class MigrationColumn extends Column { @override IndexType get indexType => _index; + @override dynamic get defaultValue => _defaultValue; List get externalReferences => @@ -21,8 +22,12 @@ class MigrationColumn extends Column { {bool isNullable = true, int length = 255, IndexType indexType = IndexType.standardIndex, - defaultValue}) - : super(type: type, length: length) { + dynamic defaultValue}) + : super( + type: type, + length: length, + isNullable: isNullable, + defaultValue: defaultValue) { _nullable = isNullable; _index = indexType; _defaultValue = defaultValue; diff --git a/packages/orm/angel_orm/CHANGELOG.md b/packages/orm/angel_orm/CHANGELOG.md index f7108264..7765498f 100644 --- a/packages/orm/angel_orm/CHANGELOG.md +++ b/packages/orm/angel_orm/CHANGELOG.md @@ -3,6 +3,7 @@ ## 6.0.2 * Fixed issue #68: Support for non-nullable type +* Added `defaultValue` to Column * Upgraded to `lints` 2.x.x ## 6.0.1 diff --git a/packages/orm/angel_orm/lib/src/migration.dart b/packages/orm/angel_orm/lib/src/migration.dart index 0b5533f7..44d8fc39 100644 --- a/packages/orm/angel_orm/lib/src/migration.dart +++ b/packages/orm/angel_orm/lib/src/migration.dart @@ -18,7 +18,7 @@ class Column { final bool isNullable; /// Specifies this column name. - final String name; + final String? name; /// Specifies the length of a `VARCHAR`. final int length; @@ -29,8 +29,8 @@ class Column { /// Specifies the scale of a `NUMERIC` or `DECIMAL`. final int scale; - /// Specifies the timezone of a temporal field. - final String timezone; + /// Specifies the timezone for temporal field. + final String? timezone; /// Explicitly defines a SQL type for this column. final ColumnType type; @@ -41,16 +41,20 @@ class Column { /// A custom SQL expression to execute, instead of a named column. final String? expression; + /// Specifies the default values. + final dynamic defaultValue; + const Column( {this.isNullable = true, this.length = 255, this.precision = 17, this.scale = 3, - this.name = "", - this.timezone = "", + this.name, + this.timezone, this.type = ColumnType.varChar, this.indexType = IndexType.none, - this.expression}); + this.expression, + this.defaultValue}); /// Returns `true` if [expression] is not `null`. bool get hasExpression => expression != null; diff --git a/packages/orm/angel_orm_generator/lib/src/migration_generator.dart b/packages/orm/angel_orm_generator/lib/src/migration_generator.dart index 86d1cdc8..57b7a755 100644 --- a/packages/orm/angel_orm_generator/lib/src/migration_generator.dart +++ b/packages/orm/angel_orm_generator/lib/src/migration_generator.dart @@ -1,4 +1,5 @@ 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:angel3_model/angel3_model.dart'; @@ -198,7 +199,20 @@ class MigrationGenerator extends GeneratorForAnnotation { var defaultValue = ctx.buildContext.defaults[name]; - if (defaultValue != null && !defaultValue.isNull) { + // Handle 'defaultValue' on Column annotation + if (col.defaultValue != null) { + var defaultCode = + dartObjectToString(col.defaultValue as DartObject); + + if (defaultCode != null) { + Expression defaultExpr = CodeExpression( + Code(defaultCode), + ); + cascade.add(refer('defaultsTo').call([defaultExpr])); + } + + // Handle 'defaultValue' on SerializableField annotation + } else if (defaultValue != null && !defaultValue.isNull) { var type = defaultValue.type; Expression? defaultExpr; @@ -219,9 +233,12 @@ class MigrationGenerator extends GeneratorForAnnotation { // Definitely an analyzer issue. } } else { - defaultExpr = CodeExpression( - Code(dartObjectToString(defaultValue)!), - ); + var defaultCode = dartObjectToString(defaultValue); + if (defaultCode != null) { + defaultExpr = CodeExpression( + Code(defaultCode), + ); + } } if (defaultExpr != null) { diff --git a/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart b/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart index 67759e98..f5457e4f 100644 --- a/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart +++ b/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart @@ -105,12 +105,10 @@ Future buildOrmContext( // Check for column annotation... var element = _findElement(field); var columnAnnotation = columnTypeChecker.firstAnnotationOf(element); - if (columnAnnotation != null) { - print('[ORM_BUILD_CONTEXT] ${element.name} => $columnAnnotation'); - } Column? column; if (columnAnnotation != null) { + // print('[ORM_BUILD_CONTEXT] ${element.name} => $columnAnnotation'); column = reviveColumn(ConstantReader(columnAnnotation)); } @@ -132,6 +130,7 @@ Future buildOrmContext( length: column.length, indexType: column.indexType, type: inferColumnType(field.type), + defaultValue: column.defaultValue, ); // Try to find a relationship @@ -321,6 +320,7 @@ Future buildOrmContext( length: column.length, type: column.type, indexType: column.indexType, + defaultValue: column.defaultValue, expression: ConstantReader(columnAnnotation).peek('expression')?.stringValue, ); @@ -396,6 +396,7 @@ Column reviveColumn(ConstantReader cr) { return Column( isNullable: cr.peek('isNullable')?.boolValue ?? false, length: cr.peek('length')?.intValue ?? 255, + defaultValue: cr.peek('defaultValue')?.objectValue, type: columnType, indexType: indexType, ); From a6681dbdabebb51b0f3617b97535d37604990a8a Mon Sep 17 00:00:00 2001 From: thomashii Date: Thu, 16 Jun 2022 10:14:17 +0800 Subject: [PATCH 05/13] Updated ORM --- packages/orm/angel_orm/CHANGELOG.md | 4 ++-- packages/orm/angel_orm/pubspec.yaml | 2 +- packages/orm/angel_orm_generator/CHANGELOG.md | 3 ++- packages/orm/angel_orm_generator/pubspec.yaml | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/orm/angel_orm/CHANGELOG.md b/packages/orm/angel_orm/CHANGELOG.md index 7765498f..3ddcfb7d 100644 --- a/packages/orm/angel_orm/CHANGELOG.md +++ b/packages/orm/angel_orm/CHANGELOG.md @@ -1,9 +1,9 @@ # Change Log -## 6.0.2 +## 6.1.0 * Fixed issue #68: Support for non-nullable type -* Added `defaultValue` to Column +* Added `defaultValue` to `@Column` annotation * Upgraded to `lints` 2.x.x ## 6.0.1 diff --git a/packages/orm/angel_orm/pubspec.yaml b/packages/orm/angel_orm/pubspec.yaml index e2abc462..f5bb64b4 100644 --- a/packages/orm/angel_orm/pubspec.yaml +++ b/packages/orm/angel_orm/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_orm -version: 6.0.2 +version: 6.1.0 description: Runtime support for Angel3 ORM. Includes base classes for queries. homepage: https://angel3-framework.web.app/ repository: https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_orm diff --git a/packages/orm/angel_orm_generator/CHANGELOG.md b/packages/orm/angel_orm_generator/CHANGELOG.md index 4c011eb0..4b7c5cd9 100644 --- a/packages/orm/angel_orm_generator/CHANGELOG.md +++ b/packages/orm/angel_orm_generator/CHANGELOG.md @@ -1,9 +1,10 @@ # Change Log -## 6.1.1 +## 6.2.0 * Fixed issue #68: Support for non-nullable type * Upgraded to `lints` 2.x.x +* Generate default value based on `defaultValue` in the `@Column` annotation ## 6.1.0 diff --git a/packages/orm/angel_orm_generator/pubspec.yaml b/packages/orm/angel_orm_generator/pubspec.yaml index b9ac2e28..879e6ee9 100644 --- a/packages/orm/angel_orm_generator/pubspec.yaml +++ b/packages/orm/angel_orm_generator/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_orm_generator -version: 6.1.1 +version: 6.2.0 description: Code generators for Angel3 ORM. Generates query builder classes. homepage: https://angel3-framework.web.app/ repository: https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_orm_generator From a5f4e4ff7a5c60e104a42fe64d475d5951342f58 Mon Sep 17 00:00:00 2001 From: thomashii Date: Sat, 18 Jun 2022 21:35:19 +0800 Subject: [PATCH 06/13] Fixed linter warnings --- .../orm/angel_migration_runner/lib/src/mariadb/table.dart | 8 ++++---- .../orm/angel_migration_runner/lib/src/mysql/table.dart | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/orm/angel_migration_runner/lib/src/mariadb/table.dart b/packages/orm/angel_migration_runner/lib/src/mariadb/table.dart index 08ed0b47..9161ea48 100644 --- a/packages/orm/angel_migration_runner/lib/src/mariadb/table.dart +++ b/packages/orm/angel_migration_runner/lib/src/mariadb/table.dart @@ -46,7 +46,7 @@ abstract class MariaDbGenerator { } for (var ref in column.externalReferences) { - buf.write(' ' + compileReference(ref)); + buf.write(' ${compileReference(ref)}'); } return buf.toString(); @@ -54,7 +54,7 @@ abstract class MariaDbGenerator { static String compileReference(MigrationColumnReference ref) { var buf = StringBuffer('REFERENCES ${ref.foreignTable}(${ref.foreignKey})'); - if (ref.behavior != null) buf.write(' ' + ref.behavior!); + if (ref.behavior != null) buf.write(' ${ref.behavior!}'); return buf.toString(); } } @@ -147,8 +147,8 @@ class MariaDbAlterTable extends Table implements MutableTable { @override void changeColumnType(String name, ColumnType type, {int length = 256}) { - _stack.add('ALTER COLUMN $name TYPE ' + - MariaDbGenerator.columnType(MigrationColumn(type, length: length))); + _stack.add( + 'ALTER COLUMN $name TYPE ${MariaDbGenerator.columnType(MigrationColumn(type, length: length))}'); } @override diff --git a/packages/orm/angel_migration_runner/lib/src/mysql/table.dart b/packages/orm/angel_migration_runner/lib/src/mysql/table.dart index 32d93f57..b244ee4e 100644 --- a/packages/orm/angel_migration_runner/lib/src/mysql/table.dart +++ b/packages/orm/angel_migration_runner/lib/src/mysql/table.dart @@ -46,7 +46,7 @@ abstract class MySqlGenerator { } for (var ref in column.externalReferences) { - buf.write(' ' + compileReference(ref)); + buf.write(' ${compileReference(ref)}'); } return buf.toString(); @@ -54,7 +54,7 @@ abstract class MySqlGenerator { static String compileReference(MigrationColumnReference ref) { var buf = StringBuffer('REFERENCES ${ref.foreignTable}(${ref.foreignKey})'); - if (ref.behavior != null) buf.write(' ' + ref.behavior!); + if (ref.behavior != null) buf.write(' ${ref.behavior!}'); return buf.toString(); } } @@ -147,8 +147,8 @@ class MysqlAlterTable extends Table implements MutableTable { @override void changeColumnType(String name, ColumnType type, {int length = 256}) { - _stack.add('ALTER COLUMN $name TYPE ' + - MySqlGenerator.columnType(MigrationColumn(type, length: length))); + _stack.add( + 'ALTER COLUMN $name TYPE ${MySqlGenerator.columnType(MigrationColumn(type, length: length))}'); } @override From f0a5e7c6fc61d744001b945b36859f05d0e0f7e8 Mon Sep 17 00:00:00 2001 From: "thomashii@dukefirehawk.com" Date: Mon, 11 Jul 2022 14:15:02 +0800 Subject: [PATCH 07/13] Added database connection retry --- .vscode/settings.json | 3 +- .../orm/angel_orm_sqlite/mono_pkg.yaml | 0 .../orm/angel_orm_sqlite/pubspec.yaml | 2 + docker/README.md | 30 ++++++++++++++ docker/docker-compose-pg.yml | 21 ++++++++++ .../orm/angel_migration_runner/pubspec.yaml | 4 +- packages/orm/angel_orm_mysql/pubspec.yaml | 4 +- packages/orm/angel_orm_postgres/CHANGELOG.md | 1 + .../lib/src/orm_postgres.dart | 40 ++++++++++++++++++- .../angel_orm_test/lib/src/models/boat.d.ts | 14 +++++++ .../angel_orm_test/lib/src/models/boat.dart | 12 +++--- .../angel_orm_test/lib/src/models/boat.g.dart | 20 +++++----- 12 files changed, 128 insertions(+), 23 deletions(-) delete mode 100644 archived_packages/orm/angel_orm_sqlite/mono_pkg.yaml create mode 100644 docker/README.md create mode 100644 docker/docker-compose-pg.yml create mode 100644 packages/orm/angel_orm_test/lib/src/models/boat.d.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 03145bf1..4e5534bc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,5 +13,6 @@ }, "editor.codeActionsOnSave": { "source.fixAll.markdownlint": true - } + }, + "cmake.configureOnOpen": false } \ No newline at end of file diff --git a/archived_packages/orm/angel_orm_sqlite/mono_pkg.yaml b/archived_packages/orm/angel_orm_sqlite/mono_pkg.yaml deleted file mode 100644 index e69de29b..00000000 diff --git a/archived_packages/orm/angel_orm_sqlite/pubspec.yaml b/archived_packages/orm/angel_orm_sqlite/pubspec.yaml index a38faa5d..6e2d9082 100644 --- a/archived_packages/orm/angel_orm_sqlite/pubspec.yaml +++ b/archived_packages/orm/angel_orm_sqlite/pubspec.yaml @@ -1,3 +1,5 @@ name: angel_orm_sqlite +environment: + sdk: ">=2.16.0 <3.0.0" dependencies: angel_orm: ^2.0.0-dev diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 00000000..52012f4e --- /dev/null +++ b/docker/README.md @@ -0,0 +1,30 @@ +# Working with Docker + +## Postgresql + +### Starting the container + + ```bash + docker-compose -f docker-compose-pg.yml up + ``` + +### Running psql + + ```bash + docker exec -it /bin/bash + psql --username postgres + ``` + +### Create database, user and access + + ```psql + postgres=# create database orm_test; + postgres=# create user test with encrypted password 'test123'; + postgres=# grant all privileges on database orm_test to test; + ``` + +## MariaDB + +## MySQL + +## Redis diff --git a/docker/docker-compose-pg.yml b/docker/docker-compose-pg.yml new file mode 100644 index 00000000..c79ef058 --- /dev/null +++ b/docker/docker-compose-pg.yml @@ -0,0 +1,21 @@ +version: "3.8" +services: + pgdb: + image: postgres:latest + restart: always + ports: + - "5432:5432" + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + volumes: + - "db:/var/lib/postgresql/data" + networks: + - webnet + +volumes: + db: + driver: local + +networks: + webnet: diff --git a/packages/orm/angel_migration_runner/pubspec.yaml b/packages/orm/angel_migration_runner/pubspec.yaml index e1f72d46..b0978a2d 100755 --- a/packages/orm/angel_migration_runner/pubspec.yaml +++ b/packages/orm/angel_migration_runner/pubspec.yaml @@ -11,8 +11,8 @@ dependencies: args: ^2.1.0 charcode: ^1.2.0 postgres: ^2.4.0 - mysql_client: ^0.0.15 - mysql1: ^0.19.0 + mysql_client: ^0.0.24 + mysql1: ^0.20.0 logging: ^1.0.0 dev_dependencies: lints: ^2.0.0 diff --git a/packages/orm/angel_orm_mysql/pubspec.yaml b/packages/orm/angel_orm_mysql/pubspec.yaml index 8f795214..126a65e6 100644 --- a/packages/orm/angel_orm_mysql/pubspec.yaml +++ b/packages/orm/angel_orm_mysql/pubspec.yaml @@ -8,8 +8,8 @@ environment: dependencies: angel3_orm: ^6.0.0 logging: ^1.0.0 - mysql1: ^0.19.0 - mysql_client: ^0.0.15 + mysql1: ^0.20.0 + mysql_client: ^0.0.24 optional: ^6.0.0 dev_dependencies: angel3_orm_generator: ^6.0.0 diff --git a/packages/orm/angel_orm_postgres/CHANGELOG.md b/packages/orm/angel_orm_postgres/CHANGELOG.md index fe6ac99c..a72a2874 100644 --- a/packages/orm/angel_orm_postgres/CHANGELOG.md +++ b/packages/orm/angel_orm_postgres/CHANGELOG.md @@ -3,6 +3,7 @@ ## 6.0.1 * Upgraded to `lints` 2.x.x +* Fixed #71. Create a new database connection and retry. ## 6.0.0 diff --git a/packages/orm/angel_orm_postgres/lib/src/orm_postgres.dart b/packages/orm/angel_orm_postgres/lib/src/orm_postgres.dart index 9dbb7dc3..947df50a 100644 --- a/packages/orm/angel_orm_postgres/lib/src/orm_postgres.dart +++ b/packages/orm/angel_orm_postgres/lib/src/orm_postgres.dart @@ -7,7 +7,7 @@ import 'package:postgres/postgres.dart'; /// A [QueryExecutor] that queries a PostgreSQL database. class PostgreSqlExecutor extends QueryExecutor { - final PostgreSQLExecutionContext _connection; + PostgreSQLExecutionContext _connection; /// An optional [Logger] to print information to. A default logger will be used /// if not set @@ -57,7 +57,43 @@ class PostgreSqlExecutor extends QueryExecutor { } }); - return _connection.query(query, substitutionValues: param); + return _connection + .query(query, substitutionValues: param) + .catchError((err) async { + logger.warning(err); + if (err is PostgreSQLException) { + // This is a hack to detect broken db connection + bool brokenConnection = + err.message?.contains("connection is not open") ?? false; + if (brokenConnection) { + if (_connection is PostgreSQLConnection) { + // Open a new db connection + var currentConnection = _connection as PostgreSQLConnection; + currentConnection.close(); + + logger.warning( + "A broken database connection is detected. Creating a new database connection."); + var conn = _createNewConnection(currentConnection); + await conn.open(); + _connection = conn; + + // Retry the query with the new db connection + return _connection.query(query, substitutionValues: param); + } + } + } + throw err; + }); + } + + // Create a new database connection from an existing connection + PostgreSQLConnection _createNewConnection(PostgreSQLConnection conn) { + return PostgreSQLConnection(conn.host, conn.port, conn.databaseName, + username: conn.username, + password: conn.password, + useSSL: conn.useSSL, + timeZone: conn.timeZone, + timeoutInSeconds: conn.timeoutInSeconds); } @override diff --git a/packages/orm/angel_orm_test/lib/src/models/boat.d.ts b/packages/orm/angel_orm_test/lib/src/models/boat.d.ts new file mode 100644 index 00000000..d2ab8fbf --- /dev/null +++ b/packages/orm/angel_orm_test/lib/src/models/boat.d.ts @@ -0,0 +1,14 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +declare module 'angel3_orm_test' { + interface Boat { + id?: string; + created_at?: any; + updated_at?: any; + make?: string; + description?: string; + family_friendly?: boolean; + recalled_at?: any; + price?: number; + width?: number; + } +} \ No newline at end of file diff --git a/packages/orm/angel_orm_test/lib/src/models/boat.dart b/packages/orm/angel_orm_test/lib/src/models/boat.dart index f98d8610..1cc5f19e 100644 --- a/packages/orm/angel_orm_test/lib/src/models/boat.dart +++ b/packages/orm/angel_orm_test/lib/src/models/boat.dart @@ -5,24 +5,24 @@ import 'package:optional/optional.dart'; part 'boat.g.dart'; -@serializable +@Serializable(serializers: Serializers.all) @orm abstract class _Boat extends Model { - @SerializableField(defaultValue: '') + @Column(defaultValue: '') String get make; - @SerializableField(defaultValue: 'none') + @Column(defaultValue: 'none') String get description; - @SerializableField(defaultValue: false) + @Column(defaultValue: false) bool get familyFriendly; //@SerializableField(defaultValue: '1970-01-01 00:00:00') DateTime get recalledAt; - @SerializableField(defaultValue: 0.0) + @Column(defaultValue: 0.0) double get price; - @SerializableField(defaultValue: 0) + @Column(defaultValue: 0) int get width; } diff --git a/packages/orm/angel_orm_test/lib/src/models/boat.g.dart b/packages/orm/angel_orm_test/lib/src/models/boat.g.dart index 4613a92b..62da26e3 100644 --- a/packages/orm/angel_orm_test/lib/src/models/boat.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/boat.g.dart @@ -234,12 +234,12 @@ class Boat extends _Boat { {this.id, this.createdAt, this.updatedAt, - this.make = '', - this.description = 'none', - this.familyFriendly = false, + required this.make, + required this.description, + required this.familyFriendly, required this.recalledAt, - this.price = 0.0, - this.width = 0}); + required this.price, + required this.width}); /// A unique identifier corresponding to this item. @override @@ -372,16 +372,16 @@ class BoatSerializer extends Codec { ? (map['updated_at'] as DateTime) : DateTime.parse(map['updated_at'].toString())) : null, - make: map['make'] as String? ?? '', - description: map['description'] as String? ?? 'none', - familyFriendly: map['family_friendly'] as bool? ?? false, + 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())) : DateTime.parse("1970-01-01 00:00:00"), - price: map['price'] as double? ?? 0.0, - width: map['width'] as int? ?? 0); + price: map['price'] as double, + width: map['width'] as int); } static Map toMap(_Boat? model) { From 793a8ac115858cfb0633d13561cc1920237123db Mon Sep 17 00:00:00 2001 From: "thomashii@dukefirehawk.com" Date: Sat, 16 Jul 2022 10:44:49 +0800 Subject: [PATCH 08/13] Updated DateTime to non UTC --- docker/docker-compose-mariadb.yml | 20 +++++++ docker/docker-compose-mysql.yml | 20 +++++++ docker/docker-compose-pg.yml | 3 +- docker/docker-compose-redis.yml | 21 ++++++++ .../lib/src/mariadb/schema.dart | 2 +- packages/orm/angel_orm/lib/src/query.dart | 2 +- .../orm/angel_orm/lib/src/query_values.dart | 4 +- packages/orm/angel_orm_mysql/README.md | 54 ++++++++++++++++--- .../orm/angel_orm_mysql/example/main.dart | 10 ++-- .../angel_orm_mysql/lib/src/orm_mariadb.dart | 7 +-- packages/orm/angel_orm_mysql/pubspec.yaml | 14 ++--- packages/orm/angel_orm_mysql/test/common.dart | 16 +++--- .../lib/src/standalone_test.dart | 8 +-- 13 files changed, 141 insertions(+), 40 deletions(-) create mode 100644 docker/docker-compose-mariadb.yml create mode 100644 docker/docker-compose-mysql.yml create mode 100644 docker/docker-compose-redis.yml diff --git a/docker/docker-compose-mariadb.yml b/docker/docker-compose-mariadb.yml new file mode 100644 index 00000000..91a71473 --- /dev/null +++ b/docker/docker-compose-mariadb.yml @@ -0,0 +1,20 @@ +version: "3.8" +services: + mariadb: + image: mariadb:latest + restart: "no" + ports: + - "3306:3306" + environment: + - MARIADB_ROOT_PASSWORD=Qwerty + volumes: + - "mariadb:/var/lib/mysql" + networks: + - webnet + +volumes: + mariadb: + driver: local + +networks: + webnet: diff --git a/docker/docker-compose-mysql.yml b/docker/docker-compose-mysql.yml new file mode 100644 index 00000000..14e64ef9 --- /dev/null +++ b/docker/docker-compose-mysql.yml @@ -0,0 +1,20 @@ +version: "3.8" +services: + mysql: + image: mysql:latest + restart: "no" + ports: + - "3306:3306" + environment: + - MYSQL_ROOT_PASSWORD=Qwerty + volumes: + - "mysql:/var/lib/mysql" + networks: + - webnet + +volumes: + mysql: + driver: local + +networks: + webnet: diff --git a/docker/docker-compose-pg.yml b/docker/docker-compose-pg.yml index c79ef058..f6c1b4e7 100644 --- a/docker/docker-compose-pg.yml +++ b/docker/docker-compose-pg.yml @@ -2,7 +2,7 @@ version: "3.8" services: pgdb: image: postgres:latest - restart: always + restart: "no" ports: - "5432:5432" environment: @@ -12,7 +12,6 @@ services: - "db:/var/lib/postgresql/data" networks: - webnet - volumes: db: driver: local diff --git a/docker/docker-compose-redis.yml b/docker/docker-compose-redis.yml new file mode 100644 index 00000000..b39a2d68 --- /dev/null +++ b/docker/docker-compose-redis.yml @@ -0,0 +1,21 @@ +version: "3.8" +services: + redis: + image: redis:latest + restart: "no" + ports: + - "5432:5432" + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + volumes: + - "redis:/data" + networks: + - webnet + +volumes: + redis: + driver: local + +networks: + webnet: diff --git a/packages/orm/angel_migration_runner/lib/src/mariadb/schema.dart b/packages/orm/angel_migration_runner/lib/src/mariadb/schema.dart index 9a753842..f9ed00e2 100644 --- a/packages/orm/angel_migration_runner/lib/src/mariadb/schema.dart +++ b/packages/orm/angel_migration_runner/lib/src/mariadb/schema.dart @@ -23,7 +23,7 @@ class MariaDbSchema extends Schema { _log.severe('Failed to run query: [ $sql ]', e); throw e; }); - affectedRows = result?.affectedRows ?? 0; + affectedRows = result.affectedRows ?? 0; }); return affectedRows; diff --git a/packages/orm/angel_orm/lib/src/query.dart b/packages/orm/angel_orm/lib/src/query.dart index fd07ce8b..cec7350d 100644 --- a/packages/orm/angel_orm/lib/src/query.dart +++ b/packages/orm/angel_orm/lib/src/query.dart @@ -371,7 +371,7 @@ abstract class Query extends QueryBase { var insertion = values?.compileInsert(this, tableName); if (insertion == '') { - throw StateError('No values have been specified for update.'); + throw StateError('No values have been specified for insertion.'); } else { var sql = compile({}); var returningSql = ''; diff --git a/packages/orm/angel_orm/lib/src/query_values.dart b/packages/orm/angel_orm/lib/src/query_values.dart index 09535211..0748dacb 100644 --- a/packages/orm/angel_orm/lib/src/query_values.dart +++ b/packages/orm/angel_orm/lib/src/query_values.dart @@ -16,7 +16,7 @@ abstract class QueryValues { String compileInsert(Query query, String tableName) { var data = Map.from(toMap()); - var now = DateTime.now().toUtc(); + var now = DateTime.now(); if (data.containsKey('created_at') && data['created_at'] == null) { data['created_at'] = now; } @@ -71,7 +71,7 @@ abstract class QueryValues { if (data.isEmpty) { return ''; } - var now = DateTime.now().toUtc(); + var now = DateTime.now(); if (data.containsKey('created_at') && data['created_at'] == null) { data.remove('created_at'); } diff --git a/packages/orm/angel_orm_mysql/README.md b/packages/orm/angel_orm_mysql/README.md index 038358cd..1a1776a7 100644 --- a/packages/orm/angel_orm_mysql/README.md +++ b/packages/orm/angel_orm_mysql/README.md @@ -7,8 +7,8 @@ This package contains the SQL Executor required by Angel3 ORM to work with MySQL and MariaDB respectively. In order to better support the differences in MySQL and MariaDb underlying protocols, two different drives have to be used. For MariaDb 10.2.x, `mysql1` driver provides the best results, while `mysql_client` driver handles MySQL 8.x.x without issues. -* MariaDbExecutor (beta) -* MySqlExecutor (beta) +* MariaDbExecutor +* MySqlExecutor ## Supported database version @@ -26,8 +26,8 @@ This package contains the SQL Executor required by Angel3 ORM to work with MySQL host: 'localhost', port: 3306, db: 'orm_test', - user: 'Test', - password: 'Test123*'); + user: 'test', + password: 'test123'); var connection = await MySqlConnection.connect(settings); var logger = Logger('orm_mariadb'); @@ -44,7 +44,7 @@ This package contains the SQL Executor required by Angel3 ORM to work with MySQL port: 3306, databaseName: "orm_test", userName: "test", - password: "Test123*", + password: "test123", secure: false); var logger = Logger('orm_mysql'); @@ -52,8 +52,48 @@ This package contains the SQL Executor required by Angel3 ORM to work with MySQL var executor = MySqlExecutor(connection, logger: logger); ``` +### Issues + +* Blob +* DateTime value not in UTC +* Transaction is broken + +## Creating a new database in MariaDB/MySQL + +1. Login to MariaDB/MySQL database console with the following command. + +```bash + mysql -u root -p +``` + +1. Run the following commands to create a new database, `orm_test` and grant both local and remote access to user, `test`. Replace `orm_test`, `test` and `test123` with your own database name, username and password respectively. + +```mysql + create database orm_test; + + create user 'test'@'localhost' identified by 'test123'; + grant all privileges on orm_test.* to 'test'@'localhost'; + + create user 'test'@'%' identified by 'test123'; + grant all privileges on orm_test.* to 'test'@'%'; +``` + ## Known limitation -* UTC time is not supported +### Using `mysql1` driver on MariabDb + +* Blob +* DateTime value not in UTC +* Transaction is broken + +### Using `mysql1` driver on MySQL + +* Blob is not supported + +### Using `mysql_client` driver on MariabDb + +* Blob is not supported + +### Using `mysql_client` driver on MySQL + * Blob is not supported - \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/example/main.dart b/packages/orm/angel_orm_mysql/example/main.dart index cf84baa7..a32806d7 100644 --- a/packages/orm/angel_orm_mysql/example/main.dart +++ b/packages/orm/angel_orm_mysql/example/main.dart @@ -13,8 +13,8 @@ part 'main.g.dart'; void main() async { //hierarchicalLoggingEnabled = true; - //await mariaDBExample(); - await mysqlExample(); + await mariaDBExample(); + //await mysqlExample(); exit(0); } @@ -28,8 +28,8 @@ Future mariaDBExample() async { host: 'localhost', port: 3306, db: 'orm_test', - user: 'Test', - password: 'Test123*'); + user: 'test', + password: 'test123'); var connection = await MySqlConnection.connect(settings); print("Connected to MariaDb"); @@ -61,7 +61,7 @@ Future mysqlExample() async { port: 3306, databaseName: "orm_test", userName: "test", - password: "Test123*", + password: "test123", secure: false); print("Connected to MySQL"); diff --git a/packages/orm/angel_orm_mysql/lib/src/orm_mariadb.dart b/packages/orm/angel_orm_mysql/lib/src/orm_mariadb.dart index 5675a6f0..8ecb4725 100644 --- a/packages/orm/angel_orm_mysql/lib/src/orm_mariadb.dart +++ b/packages/orm/angel_orm_mysql/lib/src/orm_mariadb.dart @@ -34,9 +34,9 @@ class MariaDbExecutor extends QueryExecutor { var params = substitutionValues.values.toList(); - //logger?.warning('Query: $query'); - //logger?.warning('Values: $params'); - //logger?.warning('Returning Query: $returningQuery'); + logger.warning('Query: $query'); + logger.warning('Values: $params'); + logger.warning('Returning Query: $returningQuery'); if (returningQuery.isNotEmpty) { // Handle insert, update and delete @@ -66,6 +66,7 @@ class MariaDbExecutor extends QueryExecutor { @override Future transaction(FutureOr Function(QueryExecutor) f) async { T? returnValue = await _connection.transaction((ctx) async { + // TODO: This is broken var conn = ctx as MySqlConnection; try { logger.fine('Entering transaction'); diff --git a/packages/orm/angel_orm_mysql/pubspec.yaml b/packages/orm/angel_orm_mysql/pubspec.yaml index 126a65e6..327b6d1b 100644 --- a/packages/orm/angel_orm_mysql/pubspec.yaml +++ b/packages/orm/angel_orm_mysql/pubspec.yaml @@ -17,18 +17,18 @@ dev_dependencies: build_runner: ^2.0.1 test: ^1.21.0 lints: ^1.0.0 -# dependency_overrides: +dependency_overrides: # angel3_serialize: # path: ../../serialize/angel_serialize # angel3_serialize_generator: # path: ../../serialize/angel_serialize_generator # angel3_model: # path: ../../model -# angel3_orm_test: -# path: ../angel_orm_test -# angel3_orm: -# path: ../angel_orm + angel3_orm_test: + path: ../angel_orm_test + angel3_orm: + path: ../angel_orm # angel3_orm_generator: # path: ../angel_orm_generator -# angel3_migration: -# path: ../angel_migration + angel3_migration: + path: ../angel_migration diff --git a/packages/orm/angel_orm_mysql/test/common.dart b/packages/orm/angel_orm_mysql/test/common.dart index 488cff55..58be1adb 100644 --- a/packages/orm/angel_orm_mysql/test/common.dart +++ b/packages/orm/angel_orm_mysql/test/common.dart @@ -10,14 +10,14 @@ List tmpTables = []; FutureOr Function() createTables(List schemas) { // For MySQL - return () => _connectToMySql(schemas); + //return () => _connectToMySql(schemas); // For MariaDB - // return () => _connectToMariaDb(tables); + return () => _connectToMariaDb(schemas); } // For MySQL -Future dropTables(QueryExecutor executor) async { +Future dropTables2(QueryExecutor executor) async { var sqlExecutor = (executor as MySqlExecutor); for (var tableName in tmpTables.reversed) { await sqlExecutor.rawConnection.execute('drop table $tableName;'); @@ -26,13 +26,13 @@ Future dropTables(QueryExecutor executor) async { } // For MariaDB -/* Future dropTables(QueryExecutor executor) { +Future dropTables(QueryExecutor executor) { var sqlExecutor = (executor as MariaDbExecutor); for (var tableName in tmpTables.reversed) { sqlExecutor.query(tableName, 'DROP TABLE $tableName', {}); } return sqlExecutor.close(); -} */ +} String extractTableName(String createQuery) { var start = createQuery.indexOf('EXISTS'); @@ -51,8 +51,8 @@ Future _connectToMariaDb(List schemas) async { host: 'localhost', port: 3306, db: 'orm_test', - user: 'Test', - password: 'Test123*'); + user: 'test', + password: 'test123'); var connection = await MySqlConnection.connect(settings); var logger = Logger('orm_mariadb'); @@ -87,7 +87,7 @@ Future _connectToMySql(List schemas) async { port: 3306, host: "localhost", userName: Platform.environment['MYSQL_USERNAME'] ?? 'test', - password: Platform.environment['MYSQL_PASSWORD'] ?? 'Test123*', + password: Platform.environment['MYSQL_PASSWORD'] ?? 'test123', secure: false); await connection.connect(timeoutMs: 10000); diff --git a/packages/orm/angel_orm_test/lib/src/standalone_test.dart b/packages/orm/angel_orm_test/lib/src/standalone_test.dart index 66097910..840f0fd3 100644 --- a/packages/orm/angel_orm_test/lib/src/standalone_test.dart +++ b/packages/orm/angel_orm_test/lib/src/standalone_test.dart @@ -3,7 +3,7 @@ import 'package:angel3_orm/angel3_orm.dart'; import 'package:test/test.dart'; import 'models/car.dart'; -final DateTime y2k = DateTime.utc(2000, 1, 1); +final DateTime y2k = DateTime(2000, 1, 1); void standaloneTests(FutureOr Function() createExecutor, {FutureOr Function(QueryExecutor)? close}) { @@ -173,9 +173,9 @@ void standaloneTests(FutureOr Function() createExecutor, }); test('insert', () async { - var recalledAt = DateTime.now().toUtc(); + var recalledAt = DateTime.now(); var query = CarQuery(); - var now = DateTime.now().toUtc(); + var now = DateTime.now(); query.values ..make = 'Honda' ..description = 'Hello' @@ -198,7 +198,7 @@ void standaloneTests(FutureOr Function() createExecutor, }); test('insert car', () async { - var recalledAt = DateTime.now().toUtc(); + var recalledAt = DateTime.now(); var beetle = Car( make: 'Beetle', description: 'Herbie', From 572a134c9c6cb1aff22034e23400a2591cfba629 Mon Sep 17 00:00:00 2001 From: "thomashii@dukefirehawk.com" Date: Sun, 24 Jul 2022 12:00:10 +0800 Subject: [PATCH 09/13] Fixed temporal mapping --- README.md | 9 +- .../performance => experiment/db}/AUTHORS.md | 0 {tool/performance => experiment/db}/LICENSE | 0 .../db}/analysis_options.yaml | 0 experiment/db/bin/mysql_sql_main.dart | 93 ++++++++++++++++ experiment/db/pubspec.yaml | 12 +++ experiment/logging/AUTHORS.md | 6 ++ experiment/logging/LICENSE | 29 +++++ experiment/logging/analysis_options.yaml | 1 + experiment/logging/bin/main.dart | 22 ++++ experiment/logging/pubspec.yaml | 11 ++ experiment/performance/AUTHORS.md | 6 ++ experiment/performance/LICENSE | 29 +++++ experiment/performance/analysis_options.yaml | 1 + .../performance/bin}/main.dart | 0 {tool => experiment}/performance/pubspec.yaml | 0 .../performance/tests/techempower.http | 0 packages/framework/lib/src/core/driver.dart | 13 ++- .../angel_migration_runner/lib/src/util.dart | 2 +- packages/orm/angel_orm/lib/src/query.dart | 9 +- packages/orm/angel_orm_mysql/README.md | 101 ++++++++++-------- .../angel_orm_mysql/lib/src/orm_mariadb.dart | 19 +++- .../angel_orm_mysql/lib/src/orm_mysql.dart | 5 +- packages/orm/angel_orm_mysql/test/common.dart | 15 +-- .../test/migrations/author.sql | 4 +- .../angel_orm_mysql/test/migrations/book.sql | 4 +- .../angel_orm_mysql/test/migrations/car.sql | 6 +- .../angel_orm_mysql/test/migrations/foot.sql | 4 +- .../angel_orm_mysql/test/migrations/fruit.sql | 4 +- .../test/migrations/has_car.sql | 4 +- .../test/migrations/has_map.sql | 4 +- .../angel_orm_mysql/test/migrations/leg.sql | 4 +- .../angel_orm_mysql/test/migrations/numba.sql | 4 +- .../angel_orm_mysql/test/migrations/role.sql | 4 +- .../angel_orm_mysql/test/migrations/song.sql | 4 +- .../angel_orm_mysql/test/migrations/tree.sql | 4 +- .../angel_orm_mysql/test/migrations/user.sql | 4 +- .../test/migrations/user_role.sql | 4 +- .../orm/angel_orm_mysql/test/orm_debug.dart | 2 +- packages/orm/angel_orm_test/README.md | 8 +- .../angel_orm_test/lib/src/models/boat.dart | 2 +- 41 files changed, 356 insertions(+), 97 deletions(-) rename {tool/performance => experiment/db}/AUTHORS.md (100%) rename {tool/performance => experiment/db}/LICENSE (100%) rename {tool/performance => experiment/db}/analysis_options.yaml (100%) create mode 100644 experiment/db/bin/mysql_sql_main.dart create mode 100644 experiment/db/pubspec.yaml create mode 100644 experiment/logging/AUTHORS.md create mode 100644 experiment/logging/LICENSE create mode 100644 experiment/logging/analysis_options.yaml create mode 100644 experiment/logging/bin/main.dart create mode 100644 experiment/logging/pubspec.yaml create mode 100644 experiment/performance/AUTHORS.md create mode 100644 experiment/performance/LICENSE create mode 100644 experiment/performance/analysis_options.yaml rename {tool/performance/techempower => experiment/performance/bin}/main.dart (100%) rename {tool => experiment}/performance/pubspec.yaml (100%) rename {tool => experiment}/performance/tests/techempower.http (100%) diff --git a/README.md b/README.md index 094a661d..9af7ffcc 100644 --- a/README.md +++ b/README.md @@ -63,8 +63,9 @@ For more details, checkout [Project Status](https://github.com/dukefirehawk/ange 1. Download and install [Dart](https://dart.dev/get-dart) 2. Clone one of the following starter projects: - * [Angel3 Basic Template](https://github.com/dukefirehawk/boilerplates/tree/angel3-basic) - * [Angel3 ORM Template](https://github.com/dukefirehawk/boilerplates/tree/angel3-orm) + * [Basic Template](https://github.com/dukefirehawk/boilerplates/tree/angel3-basic) + * [ORM for PostgreSQL Template](https://github.com/dukefirehawk/boilerplates/tree/angel3-orm) + * [ORM for MySQL Template](https://github.com/dukefirehawk/boilerplates/tree/angel3-orm-mysql) * [Angel3 Graphql Template](https://github.com/dukefirehawk/boilerplates/tree/angel3-graphql) 3. Run the project in development mode (*hot-reloaded* is enabled on file changes). @@ -123,12 +124,12 @@ Check out [Migrating to Angel3](https://angel3-docs.dukefirehawk.com/migration/a The performance benchmark can be found at -[TechEmpower Framework Benchmarks](https://tfb-status.techempower.com/) +[TechEmpower Framework Benchmarks Round 21](https://www.techempower.com/benchmarks/#section=data-r21&test=composite) The test cases are build using standard `Angel3 ORM` template. This result will be used for fine-tuning Angel3 framework. The following test cases will be progressively added in the upcoming update to benchmark. 1. Angel3 with MongoDB -2. Angel3 with MySQL ORM +2. Angel3 with ORM MySQL 3. Cached queries ## Examples and Documentation diff --git a/tool/performance/AUTHORS.md b/experiment/db/AUTHORS.md similarity index 100% rename from tool/performance/AUTHORS.md rename to experiment/db/AUTHORS.md diff --git a/tool/performance/LICENSE b/experiment/db/LICENSE similarity index 100% rename from tool/performance/LICENSE rename to experiment/db/LICENSE diff --git a/tool/performance/analysis_options.yaml b/experiment/db/analysis_options.yaml similarity index 100% rename from tool/performance/analysis_options.yaml rename to experiment/db/analysis_options.yaml diff --git a/experiment/db/bin/mysql_sql_main.dart b/experiment/db/bin/mysql_sql_main.dart new file mode 100644 index 00000000..e5ac0a30 --- /dev/null +++ b/experiment/db/bin/mysql_sql_main.dart @@ -0,0 +1,93 @@ +import 'dart:io'; + +import 'package:mysql_client/mysql_client.dart'; +import 'package:mysql1/mysql1.dart'; + +void main() async { + print("=== Start 'mysql1' driver test"); + await testMySQL1Driver().catchError((error, stackTrace) { + print(error); + }); + print("=== End test"); + print(" "); + + print("=== Start 'mysql_client' driver test"); + await testMySQLClientDriver().catchError((error, stackTrace) { + print(error); + }); + print("=== End test"); + print(" "); + + //sleep(Duration(seconds: 5)); + exit(0); +} + +Future testMySQLClientDriver() async { + var connection = await MySQLConnection.createConnection( + host: "localhost", + port: 3306, + databaseName: "orm_test", + userName: "test", + password: "test123", + secure: false); + await connection.connect(timeoutMs: 30000); + + print(">Test Select All"); + var result = await connection.execute("SELECT * from users"); + print("Total records: ${result.rows.length}"); + + print(">Test Insert"); + var params = { + "username": "test", + "password": "test123", + "email": "test@demo.com", + "updatedAt": DateTime.parse("1970-01-01 00:00:00") + }; + + result = await connection.execute( + "INSERT INTO users (username, password, email, updated_at) VALUES (:username, :password, :email, :updatedAt)", + params); + print("Last inserted ID: ${result.lastInsertID}"); + + print(">Test Select By ID"); + result = await connection.execute( + "SELECT * from users where id=:id", {"id": result.lastInsertID.toInt()}); + print("Read record: ${result.rows.first.assoc()}"); +} + +Future testMySQL1Driver() async { + var settings = ConnectionSettings( + host: 'localhost', + port: 3306, + db: 'orm_test', + user: 'test', + password: 'test123', + timeout: Duration(seconds: 60)); + var connection = await MySqlConnection.connect(settings); + + print(">Test Select All"); + var result = await connection.query("SELECT * from users"); + print("Total records: ${result.length}"); + + print(">Test Insert"); + var params = [ + "test", + "test123", + "test@demo.com", + DateTime.parse("1970-01-01 00:00:00").toUtc() + ]; + + // DateTime.parse("1970-01-01 00:00:01").toUtc() + result = await connection.query( + "INSERT INTO users (username, password, email, updated_at) VALUES (?, ?, ?, ?)", + params); + print("Last inserted ID: ${result.insertId}"); + + print(">Test Select By ID"); + result = await connection + .query("SELECT * from users where id=?", [result.insertId]); + print("Read record: ${result.first.values}"); + + var d = DateTime.parse("1970-01-01 00:00:00").toUtc(); + print("Local time: ${d.toLocal()}"); +} diff --git a/experiment/db/pubspec.yaml b/experiment/db/pubspec.yaml new file mode 100644 index 00000000..bfb3e131 --- /dev/null +++ b/experiment/db/pubspec.yaml @@ -0,0 +1,12 @@ +name: performance_tool +version: 1.0.0 +description: Angel3 performance testing tool +publish_to: none +environment: + sdk: '>=2.16.0 <3.0.0' +published_to: none +dependencies: + mysql1: ^0.20.0 + mysql_client: ^0.0.24 +dev_dependencies: + lints: ^2.0.0 \ No newline at end of file diff --git a/experiment/logging/AUTHORS.md b/experiment/logging/AUTHORS.md new file mode 100644 index 00000000..15258b53 --- /dev/null +++ b/experiment/logging/AUTHORS.md @@ -0,0 +1,6 @@ +Primary Authors +=============== + +* __[Thomas Hii](dukefirehawk.apps@gmail.com)__ + + The current main maintainer of the code base. diff --git a/experiment/logging/LICENSE b/experiment/logging/LICENSE new file mode 100644 index 00000000..df5e0635 --- /dev/null +++ b/experiment/logging/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, dukefirehawk.com +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/experiment/logging/analysis_options.yaml b/experiment/logging/analysis_options.yaml new file mode 100644 index 00000000..ea2c9e94 --- /dev/null +++ b/experiment/logging/analysis_options.yaml @@ -0,0 +1 @@ +include: package:lints/recommended.yaml \ No newline at end of file diff --git a/experiment/logging/bin/main.dart b/experiment/logging/bin/main.dart new file mode 100644 index 00000000..9c34ce7e --- /dev/null +++ b/experiment/logging/bin/main.dart @@ -0,0 +1,22 @@ +import 'dart:isolate'; + +Future runApp(var message) async { + var stopwatch = Stopwatch()..start(); + + // Do something + + print('Execution($message) Time: ${stopwatch.elapsed.inMilliseconds}ms'); + stopwatch.stop(); +} + +void main() async { + var concurrency = 6000; + + for (var i = 0; i < concurrency; i++) { + Isolate.spawn(runApp, 'Instance_$i'); + } + + await Future.delayed(const Duration(seconds: 10)); + + //print("Exit"); +} diff --git a/experiment/logging/pubspec.yaml b/experiment/logging/pubspec.yaml new file mode 100644 index 00000000..7b1205e4 --- /dev/null +++ b/experiment/logging/pubspec.yaml @@ -0,0 +1,11 @@ +name: performance_tool +version: 1.0.0 +description: Angel3 performance testing tool +publish_to: none +environment: + sdk: '>=2.16.0 <3.0.0' +published_to: none +dependencies: + http: ^0.13.4 +dev_dependencies: + lints: ^2.0.0 \ No newline at end of file diff --git a/experiment/performance/AUTHORS.md b/experiment/performance/AUTHORS.md new file mode 100644 index 00000000..15258b53 --- /dev/null +++ b/experiment/performance/AUTHORS.md @@ -0,0 +1,6 @@ +Primary Authors +=============== + +* __[Thomas Hii](dukefirehawk.apps@gmail.com)__ + + The current main maintainer of the code base. diff --git a/experiment/performance/LICENSE b/experiment/performance/LICENSE new file mode 100644 index 00000000..df5e0635 --- /dev/null +++ b/experiment/performance/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, dukefirehawk.com +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/experiment/performance/analysis_options.yaml b/experiment/performance/analysis_options.yaml new file mode 100644 index 00000000..ea2c9e94 --- /dev/null +++ b/experiment/performance/analysis_options.yaml @@ -0,0 +1 @@ +include: package:lints/recommended.yaml \ No newline at end of file diff --git a/tool/performance/techempower/main.dart b/experiment/performance/bin/main.dart similarity index 100% rename from tool/performance/techempower/main.dart rename to experiment/performance/bin/main.dart diff --git a/tool/performance/pubspec.yaml b/experiment/performance/pubspec.yaml similarity index 100% rename from tool/performance/pubspec.yaml rename to experiment/performance/pubspec.yaml diff --git a/tool/performance/tests/techempower.http b/experiment/performance/tests/techempower.http similarity index 100% rename from tool/performance/tests/techempower.http rename to experiment/performance/tests/techempower.http diff --git a/packages/framework/lib/src/core/driver.dart b/packages/framework/lib/src/core/driver.dart index 470532d2..74289c6e 100644 --- a/packages/framework/lib/src/core/driver.dart +++ b/packages/framework/lib/src/core/driver.dart @@ -291,15 +291,23 @@ abstract class Driver< Future sendResponse(Request request, Response response, RequestContext req, ResponseContext res, {bool ignoreFinalizers = false}) { + //app.logger.fine("Calling SendResponse"); Future _cleanup(_) { if (!app.environment.isProduction && req.container!.has()) { var sw = req.container!.make(); - app.logger.info( + app.logger.fine( "${res.statusCode} ${req.method} ${req.uri} (${sw.elapsedMilliseconds} ms)"); } return req.close(); } + // TODO: Debugging header + /* + for (var key in res.headers.keys) { + app.logger.fine("Response header key: $key"); + } + */ + if (!res.isBuffered) { //if (res.isOpen) { return res.close().then(_cleanup); @@ -307,6 +315,8 @@ abstract class Driver< //return Future.value(); } + //app.logger.fine("Calling finalizers"); + var finalizers = ignoreFinalizers == true ? Future.value() : Future.forEach(app.responseFinalizers, (dynamic f) => f(req, res)); @@ -315,6 +325,7 @@ abstract class Driver< //if (res.isOpen) res.close(); for (var key in res.headers.keys) { + app.logger.fine("Response header key: $key"); setHeader(response, key, res.headers[key] ?? ''); } diff --git a/packages/orm/angel_migration_runner/lib/src/util.dart b/packages/orm/angel_migration_runner/lib/src/util.dart index e54f499d..c7add83a 100755 --- a/packages/orm/angel_migration_runner/lib/src/util.dart +++ b/packages/orm/angel_migration_runner/lib/src/util.dart @@ -18,5 +18,5 @@ Future absoluteSourcePath(Type type) async { } } - return uri.toFilePath() + '#' + MirrorSystem.getName(mirror.simpleName); + return '${uri.toFilePath()}#${MirrorSystem.getName(mirror.simpleName)}'; } diff --git a/packages/orm/angel_orm/lib/src/query.dart b/packages/orm/angel_orm/lib/src/query.dart index cec7350d..e5bdb612 100644 --- a/packages/orm/angel_orm/lib/src/query.dart +++ b/packages/orm/angel_orm/lib/src/query.dart @@ -397,9 +397,14 @@ abstract class Query extends QueryBase { return executor .query(tableName, sql, substitutionValues, returningQuery: returningSql) - .then((it) { + .then((result) { // Return SQL execution results - return it.isEmpty ? Optional.empty() : deserialize(it.first); + //if (result.isNotEmpty) { + // for (var element in result.first) { + // _log.fine("value: $element"); + // } + //} + return result.isEmpty ? Optional.empty() : deserialize(result.first); }); } } diff --git a/packages/orm/angel_orm_mysql/README.md b/packages/orm/angel_orm_mysql/README.md index 1a1776a7..75211981 100644 --- a/packages/orm/angel_orm_mysql/README.md +++ b/packages/orm/angel_orm_mysql/README.md @@ -5,19 +5,48 @@ [![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion) [![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_orm_mysql/LICENSE) -This package contains the SQL Executor required by Angel3 ORM to work with MySQL and MariaDB respectively. In order to better support the differences in MySQL and MariaDb underlying protocols, two different drives have to be used. For MariaDb 10.2.x, `mysql1` driver provides the best results, while `mysql_client` driver handles MySQL 8.x.x without issues. +This package contains the SQL executor required by Angel3 ORM to work with MySQL and MariaDB respectively. In order to better support both MySQL and MariaDB, two different flavors of drives have been included; `mysql_client` and `mysql1`. They are implmented as `MySqlExecutor` and `MariaDbExecutor` respectively. -* MariaDbExecutor -* MySqlExecutor +## Supported databases -## Supported database version +* MariaDD 10.2.x or greater +* MySQL 8.x or greater -* MariaDb 10.2.x -* MySQL 8.x +**Note** MySQL below version 8.0 and MariaDB below version 10.2.0 are not supported as Angel3 ORM requires common table expressions (CTE) to work. -**Note** MySQL below version 8.0 and MariaDB below version 10.2 are not supported as Angel3 ORM requires common table expressions (CTE). +## MySqlExecutor -## Connecting to MariaDB database 10.2.x +This SQL executor is implemented using [`mysql_client`](https://pub.dev/packages?q=mysql_client) driver. It works with both `MySQL` 8.0+ and `MariaDB` 10.2+ database. + +### Connecting to MySQL or MariaDB + +```dart + import 'package:mysql_client/mysql_client.dart'; + + var connection = await MySQLConnection.createConnection( + host: "localhost", + port: 3306, + databaseName: "orm_test", + userName: "test", + password: "test123", + secure: true); + + var logger = Logger('orm_mysql'); + await connection.connect(timeoutMs: 10000); + var executor = MySqlExecutor(connection, logger: logger); +``` + +### Known Limitation for MySqlExecutor + +* `Blob` data type mapping is not support. +* `timestamp` data type mapping is not supported. Use `datetime` instead. +* UTC datetime is not supported. + +## MariaDBExecutor + +This SQL executor is implemented using [`mysql1`](https://pub.dev/packages?q=mysql1) driver. It only works with `MariaDB` 10.2+ database. Do not use this for `MySQL` 8.0+ database. + +### Connecting to MariaDB ```dart import 'package:mysql1/mysql1.dart'; @@ -34,31 +63,13 @@ This package contains the SQL Executor required by Angel3 ORM to work with MySQL var executor = MariaDbExecutor(connection, logger: logger); ``` -## Connecting to MySQL database 8.x +### Known Limitation for MariaDBExecutor -```dart - import 'package:mysql_client/mysql_client.dart'; +* `Blob` type mapping is not supported. +* `timestamp` mapping is not supported. Use `datetime` instead. +* Only UTC datetime is supported. None UTC datetime will be automatically converted into UTC datetime. - var connection = await MySQLConnection.createConnection( - host: "localhost", - port: 3306, - databaseName: "orm_test", - userName: "test", - password: "test123", - secure: false); - - var logger = Logger('orm_mysql'); - await connection.connect(timeoutMs: 10000); - var executor = MySqlExecutor(connection, logger: logger); -``` - -### Issues - -* Blob -* DateTime value not in UTC -* Transaction is broken - -## Creating a new database in MariaDB/MySQL +## Creating a new database in MariaDB or MySQL 1. Login to MariaDB/MySQL database console with the following command. @@ -71,29 +82,27 @@ This package contains the SQL Executor required by Angel3 ORM to work with MySQL ```mysql create database orm_test; + -- Granting localhost access only create user 'test'@'localhost' identified by 'test123'; grant all privileges on orm_test.* to 'test'@'localhost'; + -- Granting localhost and remote access create user 'test'@'%' identified by 'test123'; grant all privileges on orm_test.* to 'test'@'%'; ``` -## Known limitation +## Compatibility Matrix -### Using `mysql1` driver on MariabDb +### MariaDB 10.2+ -* Blob -* DateTime value not in UTC -* Transaction is broken +| | Create | Read | Update | Delete | +|-----------------|--------|--------|--------|--------| +| MySqlExecutor | Y | Y | Y | Y | +| MariaDBExecutor | Y | Y | Y | Y | -### Using `mysql1` driver on MySQL +### MySQL 8.0+ -* Blob is not supported - -### Using `mysql_client` driver on MariabDb - -* Blob is not supported - -### Using `mysql_client` driver on MySQL - -* Blob is not supported +| | Create | Read | Update | Delete | +|-----------------|--------|--------|--------|--------| +| MySqlExecutor | Y | Y | Y | Y | +| MariaDBExecutor | N | N | N | N | diff --git a/packages/orm/angel_orm_mysql/lib/src/orm_mariadb.dart b/packages/orm/angel_orm_mysql/lib/src/orm_mariadb.dart index 8ecb4725..ca440f75 100644 --- a/packages/orm/angel_orm_mysql/lib/src/orm_mariadb.dart +++ b/packages/orm/angel_orm_mysql/lib/src/orm_mariadb.dart @@ -9,6 +9,8 @@ class MariaDbExecutor extends QueryExecutor { final MySqlConnection _connection; + TransactionContext? _transactionContext; + MariaDbExecutor(this._connection, {Logger? logger}) { this.logger = logger ?? Logger('MariaDbExecutor'); } @@ -33,6 +35,15 @@ class MariaDbExecutor extends QueryExecutor { } var params = substitutionValues.values.toList(); + for (var i = 0; i < params.length; i++) { + var v = params[i]; + + if (v is DateTime) { + if (!v.isUtc) { + params[i] = v.toUtc(); + } + } + } logger.warning('Query: $query'); logger.warning('Values: $params'); @@ -66,12 +77,12 @@ class MariaDbExecutor extends QueryExecutor { @override Future transaction(FutureOr Function(QueryExecutor) f) async { T? returnValue = await _connection.transaction((ctx) async { - // TODO: This is broken - var conn = ctx as MySqlConnection; + // TODO: To be relooked at try { logger.fine('Entering transaction'); - var tx = MariaDbExecutor(conn, logger: logger); - return await f(tx); + //var tx = MariaDbExecutor(conn, logger: logger); + _transactionContext = ctx; + return await f(this); } catch (e) { logger.severe('Failed to run transaction', e); rethrow; diff --git a/packages/orm/angel_orm_mysql/lib/src/orm_mysql.dart b/packages/orm/angel_orm_mysql/lib/src/orm_mysql.dart index 773e5bc3..8e932702 100644 --- a/packages/orm/angel_orm_mysql/lib/src/orm_mysql.dart +++ b/packages/orm/angel_orm_mysql/lib/src/orm_mysql.dart @@ -131,7 +131,10 @@ class MySqlExecutor extends QueryExecutor { // Handle select return _connection.execute(query, substitutionValues).then((results) { - logger.warning("SELECT"); + var tmpData = results.rows; + for (var element in tmpData) { + logger.warning("[Result] : ${element.assoc()}"); + } return results.rows.map((r) => r.typedAssoc().values.toList()).toList(); }); diff --git a/packages/orm/angel_orm_mysql/test/common.dart b/packages/orm/angel_orm_mysql/test/common.dart index 58be1adb..27c05947 100644 --- a/packages/orm/angel_orm_mysql/test/common.dart +++ b/packages/orm/angel_orm_mysql/test/common.dart @@ -10,25 +10,28 @@ List tmpTables = []; FutureOr Function() createTables(List schemas) { // For MySQL - //return () => _connectToMySql(schemas); + return () => _connectToMySql(schemas); // For MariaDB - return () => _connectToMariaDb(schemas); + //return () => _connectToMariaDb(schemas); } // For MySQL -Future dropTables2(QueryExecutor executor) async { +Future dropTables(QueryExecutor executor) async { var sqlExecutor = (executor as MySqlExecutor); for (var tableName in tmpTables.reversed) { - await sqlExecutor.rawConnection.execute('drop table $tableName;'); + print('DROP TABLE $tableName'); + await sqlExecutor.rawConnection.execute('DROP TABLE $tableName;'); } + return sqlExecutor.close(); } // For MariaDB -Future dropTables(QueryExecutor executor) { +Future dropTables2(QueryExecutor executor) { var sqlExecutor = (executor as MariaDbExecutor); for (var tableName in tmpTables.reversed) { + print('DROP TABLE $tableName'); sqlExecutor.query(tableName, 'DROP TABLE $tableName', {}); } return sqlExecutor.close(); @@ -64,7 +67,7 @@ Future _connectToMariaDb(List schemas) async { var data = await File('test/migrations/$s.sql').readAsString(); var queries = data.split(";"); for (var q in queries) { - //print("Table: [$q]"); + print("Table: [$q]"); if (q.trim().isNotEmpty) { //await connection.execute(q); await connection.query(q); diff --git a/packages/orm/angel_orm_mysql/test/migrations/author.sql b/packages/orm/angel_orm_mysql/test/migrations/author.sql index b862b90f..1cc3830a 100644 --- a/packages/orm/angel_orm_mysql/test/migrations/author.sql +++ b/packages/orm/angel_orm_mysql/test/migrations/author.sql @@ -1,6 +1,6 @@ CREATE TABLE IF NOT EXISTS authors ( id serial PRIMARY KEY, name varchar(255) UNIQUE NOT NULL, - created_at timestamp, - updated_at timestamp + created_at datetime, + updated_at datetime ); \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/test/migrations/book.sql b/packages/orm/angel_orm_mysql/test/migrations/book.sql index f893c9ef..1199ac25 100644 --- a/packages/orm/angel_orm_mysql/test/migrations/book.sql +++ b/packages/orm/angel_orm_mysql/test/migrations/book.sql @@ -3,6 +3,6 @@ CREATE TABLE IF NOT EXISTS books ( author_id int NOT NULL, partner_author_id int, name varchar(255), - created_at timestamp, - updated_at timestamp + created_at datetime, + updated_at datetime ); \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/test/migrations/car.sql b/packages/orm/angel_orm_mysql/test/migrations/car.sql index 80058dfb..cb4b62ef 100644 --- a/packages/orm/angel_orm_mysql/test/migrations/car.sql +++ b/packages/orm/angel_orm_mysql/test/migrations/car.sql @@ -3,7 +3,7 @@ CREATE TABLE IF NOT EXISTS cars ( make varchar(255) NOT NULL, description TEXT NOT NULL, family_friendly BOOLEAN NOT NULL, - recalled_at timestamp, - created_at timestamp, - updated_at timestamp + recalled_at datetime, + created_at datetime, + updated_at datetime ); \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/test/migrations/foot.sql b/packages/orm/angel_orm_mysql/test/migrations/foot.sql index 54486289..308f1df2 100644 --- a/packages/orm/angel_orm_mysql/test/migrations/foot.sql +++ b/packages/orm/angel_orm_mysql/test/migrations/foot.sql @@ -2,6 +2,6 @@ CREATE TABLE IF NOT EXISTS feet ( id serial PRIMARY KEY, leg_id int NOT NULL, n_toes int NOT NULL, - created_at timestamp, - updated_at timestamp + created_at datetime, + updated_at datetime ); \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/test/migrations/fruit.sql b/packages/orm/angel_orm_mysql/test/migrations/fruit.sql index 901f03cb..584fdd7b 100644 --- a/packages/orm/angel_orm_mysql/test/migrations/fruit.sql +++ b/packages/orm/angel_orm_mysql/test/migrations/fruit.sql @@ -2,7 +2,7 @@ CREATE TABLE IF NOT EXISTS fruits ( id serial, tree_id int, common_name varchar(255), - created_at timestamp, - updated_at timestamp, + created_at datetime, + updated_at datetime, PRIMARY KEY(id) ); \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/test/migrations/has_car.sql b/packages/orm/angel_orm_mysql/test/migrations/has_car.sql index 24319fcd..82ff3644 100644 --- a/packages/orm/angel_orm_mysql/test/migrations/has_car.sql +++ b/packages/orm/angel_orm_mysql/test/migrations/has_car.sql @@ -1,6 +1,6 @@ CREATE TABLE IF NOT EXISTS has_cars ( id serial PRIMARY KEY, type int not null, - created_at timestamp, - updated_at timestamp + created_at datetime, + updated_at datetime ); \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/test/migrations/has_map.sql b/packages/orm/angel_orm_mysql/test/migrations/has_map.sql index b0861fbf..fea42a59 100644 --- a/packages/orm/angel_orm_mysql/test/migrations/has_map.sql +++ b/packages/orm/angel_orm_mysql/test/migrations/has_map.sql @@ -2,6 +2,6 @@ CREATE TABLE IF NOT EXISTS has_maps ( id serial PRIMARY KEY, value jsonb not null, list jsonb not null, - created_at timestamp, - updated_at timestamp + created_at datetime, + updated_at datetime ); \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/test/migrations/leg.sql b/packages/orm/angel_orm_mysql/test/migrations/leg.sql index 77308a3e..841a1131 100644 --- a/packages/orm/angel_orm_mysql/test/migrations/leg.sql +++ b/packages/orm/angel_orm_mysql/test/migrations/leg.sql @@ -1,6 +1,6 @@ CREATE TABLE IF NOT EXISTS legs ( id serial PRIMARY KEY, name varchar(255) NOT NULL, - created_at timestamp, - updated_at timestamp + created_at datetime, + updated_at datetime ); \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/test/migrations/numba.sql b/packages/orm/angel_orm_mysql/test/migrations/numba.sql index c7b23a35..e9448ec1 100644 --- a/packages/orm/angel_orm_mysql/test/migrations/numba.sql +++ b/packages/orm/angel_orm_mysql/test/migrations/numba.sql @@ -1,7 +1,7 @@ CREATE TABLE IF NOT EXISTS numbas ( i int NOT NULL UNIQUE, parent int, - created_at TIMESTAMP, - updated_at TIMESTAMP, + created_at datetime, + updated_at datetime, PRIMARY KEY(i) ); \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/test/migrations/role.sql b/packages/orm/angel_orm_mysql/test/migrations/role.sql index 3c9e3413..828093dd 100644 --- a/packages/orm/angel_orm_mysql/test/migrations/role.sql +++ b/packages/orm/angel_orm_mysql/test/migrations/role.sql @@ -1,6 +1,6 @@ CREATE TABLE IF NOT EXISTS roles ( id serial PRIMARY KEY, name varchar(255), - created_at timestamp, - updated_at timestamp + created_at datetime, + updated_at datetime ); \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/test/migrations/song.sql b/packages/orm/angel_orm_mysql/test/migrations/song.sql index 11435b01..be99cec9 100644 --- a/packages/orm/angel_orm_mysql/test/migrations/song.sql +++ b/packages/orm/angel_orm_mysql/test/migrations/song.sql @@ -2,7 +2,7 @@ CREATE TABLE IF NOT EXISTS songs ( id serial, weird_join_id int, title varchar(255), - created_at TIMESTAMP, - updated_at TIMESTAMP, + created_at datetime, + updated_at datetime, PRIMARY KEY(id) ); \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/test/migrations/tree.sql b/packages/orm/angel_orm_mysql/test/migrations/tree.sql index c9fc19cf..9be6c739 100644 --- a/packages/orm/angel_orm_mysql/test/migrations/tree.sql +++ b/packages/orm/angel_orm_mysql/test/migrations/tree.sql @@ -1,7 +1,7 @@ CREATE TABLE IF NOT EXISTS trees ( id serial, rings smallint UNIQUE, - created_at timestamp, - updated_at timestamp, + created_at datetime, + updated_at datetime, PRIMARY KEY(id) ); \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/test/migrations/user.sql b/packages/orm/angel_orm_mysql/test/migrations/user.sql index 3248b483..4ee57f71 100644 --- a/packages/orm/angel_orm_mysql/test/migrations/user.sql +++ b/packages/orm/angel_orm_mysql/test/migrations/user.sql @@ -3,6 +3,6 @@ CREATE TABLE IF NOT EXISTS users ( username varchar(255), password varchar(255), email varchar(255), - created_at timestamp, - updated_at timestamp + created_at datetime, + updated_at datetime ); \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/test/migrations/user_role.sql b/packages/orm/angel_orm_mysql/test/migrations/user_role.sql index 43a74d50..e32403d4 100644 --- a/packages/orm/angel_orm_mysql/test/migrations/user_role.sql +++ b/packages/orm/angel_orm_mysql/test/migrations/user_role.sql @@ -2,6 +2,6 @@ CREATE TABLE IF NOT EXISTS role_users ( id serial PRIMARY KEY, user_id int NOT NULL, role_id int NOT NULL, - created_at timestamp, - updated_at timestamp + created_at datetime, + updated_at datetime ); \ No newline at end of file diff --git a/packages/orm/angel_orm_mysql/test/orm_debug.dart b/packages/orm/angel_orm_mysql/test/orm_debug.dart index ed5c6e8e..4df4e5e0 100644 --- a/packages/orm/angel_orm_mysql/test/orm_debug.dart +++ b/packages/orm/angel_orm_mysql/test/orm_debug.dart @@ -14,7 +14,7 @@ void main() async { // if (rec.stackTrace != null) print(rec.stackTrace); //}); - belongsToTests(createTables(['author', 'book']), close: dropTables); + //belongsToTests(createTables(['author', 'book']), close: dropTables); //hasOneTests(my(['leg', 'foot']), close: closeMy); //standaloneTests(my(['car']), close: closeMy); diff --git a/packages/orm/angel_orm_test/README.md b/packages/orm/angel_orm_test/README.md index d923050f..e3fce218 100644 --- a/packages/orm/angel_orm_test/README.md +++ b/packages/orm/angel_orm_test/README.md @@ -5,4 +5,10 @@ [![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion) [![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_orm_test/LICENSE) -Common tests for Angel3 ORM. Reference implmentation of generated ORM files. +Common test cases for Angel3 ORM. Reference implmentation of generated ORM files. + +## Supported databases + +* MariaDb 10.2.x or greater +* MySQL 8.x or greater +* PostreSQL 10.x or greater diff --git a/packages/orm/angel_orm_test/lib/src/models/boat.dart b/packages/orm/angel_orm_test/lib/src/models/boat.dart index 1cc5f19e..b1ccf47c 100644 --- a/packages/orm/angel_orm_test/lib/src/models/boat.dart +++ b/packages/orm/angel_orm_test/lib/src/models/boat.dart @@ -17,7 +17,7 @@ abstract class _Boat extends Model { @Column(defaultValue: false) bool get familyFriendly; - //@SerializableField(defaultValue: '1970-01-01 00:00:00') + //@SerializableField(defaultValue: '1970-01-01 00:00:01') DateTime get recalledAt; @Column(defaultValue: 0.0) From aff68b2f07dac6855fab31afd27176f3d6866bb8 Mon Sep 17 00:00:00 2001 From: "thomashii@dukefirehawk.com" Date: Sun, 24 Jul 2022 13:10:23 +0800 Subject: [PATCH 10/13] Updated temporal mapping --- packages/orm/angel_migration/README.md | 16 +++++++++++++--- packages/orm/angel_migration/mono_pkg.yaml | 0 packages/orm/angel_migration_runner/CHANGELOG.md | 3 ++- packages/orm/angel_migration_runner/README.md | 10 ++++------ .../lib/src/mariadb/table.dart | 5 +++++ .../lib/src/mysql/table.dart | 4 ++++ packages/orm/angel_migration_runner/pubspec.yaml | 2 +- packages/orm/angel_orm_mysql/CHANGELOG.md | 6 ++++++ packages/orm/angel_orm_mysql/pubspec.yaml | 4 ++-- packages/orm/angel_orm_postgres/CHANGELOG.md | 4 ++-- packages/orm/angel_orm_postgres/pubspec.yaml | 2 +- 11 files changed, 40 insertions(+), 16 deletions(-) delete mode 100755 packages/orm/angel_migration/mono_pkg.yaml diff --git a/packages/orm/angel_migration/README.md b/packages/orm/angel_migration/README.md index a3e39612..36910bee 100755 --- a/packages/orm/angel_migration/README.md +++ b/packages/orm/angel_migration/README.md @@ -5,10 +5,20 @@ [![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion) [![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_migration/LICENSE) -A database migration framework built for Angel3 ORM. +A basic database migration framework built for Angel3 ORM. ## Supported database * PostgreSQL version 10 or later -* MariaDB 10.2.x -* MySQL 8.x +* MariaDB 10.2.x or later +* MySQL 8.x or later + +## Features + +* Create tables based on ORM models +* Drop tables based on ORM models +* Add new tables based ORM models + +## Limitation + +* Alter table/fields based on updated ORM models not supported diff --git a/packages/orm/angel_migration/mono_pkg.yaml b/packages/orm/angel_migration/mono_pkg.yaml deleted file mode 100755 index e69de29b..00000000 diff --git a/packages/orm/angel_migration_runner/CHANGELOG.md b/packages/orm/angel_migration_runner/CHANGELOG.md index b611dd08..79486d67 100755 --- a/packages/orm/angel_migration_runner/CHANGELOG.md +++ b/packages/orm/angel_migration_runner/CHANGELOG.md @@ -1,9 +1,10 @@ # Change Log -## 6.0.2 +## 6.1.0 * Upgraded to `lints` 2.x.x * Fixed issue #70. Incorrectly generated SQL for `defaultsTo('Default Value')` +* Mapped timestamp to datetime for MySQL and MariaDB ## 6.0.1 diff --git a/packages/orm/angel_migration_runner/README.md b/packages/orm/angel_migration_runner/README.md index 4ac16898..bfc02fe5 100755 --- a/packages/orm/angel_migration_runner/README.md +++ b/packages/orm/angel_migration_runner/README.md @@ -5,7 +5,7 @@ [![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion) [![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_migration_runner/LICENSE) -Command-line based database migration runner for Angel3 ORM. +Database migration runner for Angel3 ORM. Supported database: @@ -15,10 +15,8 @@ Supported database: ## Usage -* For PostgreSQL, use `PostgresMigrationRunner` to perform the database migration. +* Use `PostgresMigrationRunner` to perform the database migration for PostgreSQL. -* For MariaDB, use `MariaDbMigrationRunner` to perform the database migration. +* Use `MySqlMigrationRunner` to perform the database migration for MySQL and MariaDB. This is implemented with [`mysql_client`](https://pub.dev/packages?q=mysql_client) driver. -* For MySQL, use `MySqlMigrationRunner` to perform the database migration. - -**Important Notes** For MariaDB and MySQL, both migration runner are using different drivers. MariaDB is using `mysql1` driver while MySQL is using `mysql_client` driver. This is necessary as neither driver works correctly over both MariaDB and MySQL. Based on testing, `mysql1` driver works seamlessly with MariaDB 10.2.x while `mysql_client` works well with MySQL 8.x. +* Use `MariaDbMigrationRunner` to perform the database migration for MariaDB. [`mysql1`](https://pub.dev/packages?q=mysql1). diff --git a/packages/orm/angel_migration_runner/lib/src/mariadb/table.dart b/packages/orm/angel_migration_runner/lib/src/mariadb/table.dart index 9161ea48..c64b7607 100644 --- a/packages/orm/angel_migration_runner/lib/src/mariadb/table.dart +++ b/packages/orm/angel_migration_runner/lib/src/mariadb/table.dart @@ -6,6 +6,11 @@ import 'package:charcode/ascii.dart'; abstract class MariaDbGenerator { static String columnType(MigrationColumn column) { var str = column.type.name; + + // Map timestamp time to datetime + if (column.type == ColumnType.timeStamp) { + str = ColumnType.dateTime.name; + } if (column.type.hasLength) { return '$str(${column.length})'; } else { diff --git a/packages/orm/angel_migration_runner/lib/src/mysql/table.dart b/packages/orm/angel_migration_runner/lib/src/mysql/table.dart index b244ee4e..897dd47d 100644 --- a/packages/orm/angel_migration_runner/lib/src/mysql/table.dart +++ b/packages/orm/angel_migration_runner/lib/src/mysql/table.dart @@ -6,6 +6,10 @@ import 'package:charcode/ascii.dart'; abstract class MySqlGenerator { static String columnType(MigrationColumn column) { var str = column.type.name; + // Map timestamp time to datetime + if (column.type == ColumnType.timeStamp) { + str = ColumnType.dateTime.name; + } if (column.type.hasLength) { return '$str(${column.length})'; } else { diff --git a/packages/orm/angel_migration_runner/pubspec.yaml b/packages/orm/angel_migration_runner/pubspec.yaml index b0978a2d..ebfd6aa2 100755 --- a/packages/orm/angel_migration_runner/pubspec.yaml +++ b/packages/orm/angel_migration_runner/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_migration_runner -version: 6.0.2 +version: 6.1.0 description: Command-line based database migration runner for Angel3's ORM. homepage: https://angel3-framework.web.app/ repository: https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_migration_runner diff --git a/packages/orm/angel_orm_mysql/CHANGELOG.md b/packages/orm/angel_orm_mysql/CHANGELOG.md index f47ce61e..f0f8a757 100644 --- a/packages/orm/angel_orm_mysql/CHANGELOG.md +++ b/packages/orm/angel_orm_mysql/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 6.0.0 + +* Fixed temporal data type +* Fixed `MariaDbExcutor` transaction +* Updated to `lints` 2.0.0 + ## 6.0.0-beta.3 * Fixed transaction for `MariaDbExecutor` diff --git a/packages/orm/angel_orm_mysql/pubspec.yaml b/packages/orm/angel_orm_mysql/pubspec.yaml index 327b6d1b..7cff37b3 100644 --- a/packages/orm/angel_orm_mysql/pubspec.yaml +++ b/packages/orm/angel_orm_mysql/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_orm_mysql -version: 6.0.0-beta.3 +version: 6.0.0 description: MySQL support for Angel3 ORM. Includes functionality for querying and transactions. homepage: https://angel3-framework.web.app/ repository: https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_orm_mysql @@ -16,7 +16,7 @@ dev_dependencies: angel3_orm_test: ^6.0.0 build_runner: ^2.0.1 test: ^1.21.0 - lints: ^1.0.0 + lints: ^2.0.0 dependency_overrides: # angel3_serialize: # path: ../../serialize/angel_serialize diff --git a/packages/orm/angel_orm_postgres/CHANGELOG.md b/packages/orm/angel_orm_postgres/CHANGELOG.md index a72a2874..c2f3f058 100644 --- a/packages/orm/angel_orm_postgres/CHANGELOG.md +++ b/packages/orm/angel_orm_postgres/CHANGELOG.md @@ -1,9 +1,9 @@ # Change Log -## 6.0.1 +## 6.1.0 * Upgraded to `lints` 2.x.x -* Fixed #71. Create a new database connection and retry. +* Fixed #71. Restablish broken connection automatically. ## 6.0.0 diff --git a/packages/orm/angel_orm_postgres/pubspec.yaml b/packages/orm/angel_orm_postgres/pubspec.yaml index 7766554a..8e2959ae 100644 --- a/packages/orm/angel_orm_postgres/pubspec.yaml +++ b/packages/orm/angel_orm_postgres/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_orm_postgres -version: 6.0.1 +version: 6.1.0 description: PostgreSQL support for Angel3 ORM. Includes functionality for querying and transactions. homepage: https://angel3-framework.web.app/ repository: https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_orm_postgres From 98dfef8e33043723abd524a3eda94dd3f5a6961d Mon Sep 17 00:00:00 2001 From: "thomashii@dukefirehawk.com" Date: Wed, 27 Jul 2022 22:21:36 +0800 Subject: [PATCH 11/13] Fixed migration runner for MySQL --- .../orm/angel_migration_runner/CHANGELOG.md | 2 + packages/orm/angel_migration_runner/README.md | 18 ++++--- .../lib/src/mariadb/runner.dart | 48 +++++++++++------ .../lib/src/mariadb/schema.dart | 2 +- .../lib/src/mysql/runner.dart | 51 +++++++++++-------- 5 files changed, 79 insertions(+), 42 deletions(-) diff --git a/packages/orm/angel_migration_runner/CHANGELOG.md b/packages/orm/angel_migration_runner/CHANGELOG.md index 79486d67..4c1d8532 100755 --- a/packages/orm/angel_migration_runner/CHANGELOG.md +++ b/packages/orm/angel_migration_runner/CHANGELOG.md @@ -5,6 +5,8 @@ * Upgraded to `lints` 2.x.x * Fixed issue #70. Incorrectly generated SQL for `defaultsTo('Default Value')` * Mapped timestamp to datetime for MySQL and MariaDB +* Fixed `MariaDbMigrationRunner` to work with MariaDB +* Fixed `MySqlMigrationRunner` to work with MySQL and MariaDB ## 6.0.1 diff --git a/packages/orm/angel_migration_runner/README.md b/packages/orm/angel_migration_runner/README.md index bfc02fe5..d1e59ae1 100755 --- a/packages/orm/angel_migration_runner/README.md +++ b/packages/orm/angel_migration_runner/README.md @@ -9,14 +9,20 @@ Database migration runner for Angel3 ORM. Supported database: -* PostgreSQL version 10 or later -* MariaDB 10.2.x or later -* MySQL 8.x or later +* PostgreSQL 10.x or greater +* MariaDB 10.2.x or greater +* MySQL 8.x or greater ## Usage -* Use `PostgresMigrationRunner` to perform the database migration for PostgreSQL. +* Use `PostgresMigrationRunner` to perform database migration for PostgreSQL. -* Use `MySqlMigrationRunner` to perform the database migration for MySQL and MariaDB. This is implemented with [`mysql_client`](https://pub.dev/packages?q=mysql_client) driver. +* Use `MySqlMigrationRunner` to perform database migration for MySQL and MariaDB. This runner is using [`mysql_client`](https://pub.dev/packages?q=mysql_client) driver. -* Use `MariaDbMigrationRunner` to perform the database migration for MariaDB. [`mysql1`](https://pub.dev/packages?q=mysql1). +* Use `MariaDbMigrationRunner` to perform database migration for MariaDB. This runner is using[`mysql1`](https://pub.dev/packages?q=mysql1) driver. + +## Supported Operations + +* reset - Clear out all records in the `migrations` table and drop all the managed ORM tables. +* up - Generate all the managed ORM tables based on the ORM models. +* refresh - Run `reset` follow by `up` diff --git a/packages/orm/angel_migration_runner/lib/src/mariadb/runner.dart b/packages/orm/angel_migration_runner/lib/src/mariadb/runner.dart index 680d870c..1609a72f 100644 --- a/packages/orm/angel_migration_runner/lib/src/mariadb/runner.dart +++ b/packages/orm/angel_migration_runner/lib/src/mariadb/runner.dart @@ -45,7 +45,7 @@ class MariaDbMigrationRunner implements MigrationRunner { PRIMARY KEY(id) ); ''').then((result) { - _log.info('Check and create "migrations" table'); + _log.fine('Check and create "migrations" table'); }).catchError((e) { _log.severe('Failed to create "migrations" table.', e); }); @@ -54,18 +54,25 @@ class MariaDbMigrationRunner implements MigrationRunner { @override Future up() async { await _init(); - var r = await connection.query('SELECT path from migrations;'); - var existing = r.expand((x) => x).cast(); - var toRun = []; + var result = await connection.query('SELECT path from migrations;'); + var existing = []; + if (result.isNotEmpty) { + existing = result.expand((x) => x).cast().toList(); + } + + var toRun = []; migrations.forEach((k, v) { if (!existing.contains(k)) toRun.add(k); }); if (toRun.isNotEmpty) { - var r = await connection.query('SELECT MAX(batch) from migrations;'); - var rTmp = r.toList(); - var curBatch = int.tryParse(rTmp[0][0] ?? '0') as int; + var result = await connection.query('SELECT MAX(batch) from migrations;'); + var curBatch = 0; + if (result.isNotEmpty) { + var firstRow = result.toList(); + curBatch = int.tryParse(firstRow[0][0] ?? '0') as int; + } var batch = curBatch + 1; for (var k in toRun) { @@ -73,11 +80,10 @@ class MariaDbMigrationRunner implements MigrationRunner { var schema = MariaDbSchema(); migration.up(schema); _log.info('Added "$k" into "migrations" table.'); - try { await schema.run(connection).then((_) async { var result = await connection.query( - "INSERT INTO MIGRATIONS (batch, path) VALUES ($batch, '$k')"); + "INSERT INTO migrations (batch, path) VALUES ($batch, '$k')"); return result.affectedRows; }); @@ -94,13 +100,21 @@ class MariaDbMigrationRunner implements MigrationRunner { Future rollback() async { await _init(); - var r = await connection.query('SELECT MAX(batch) from migrations;'); - var rTmp = r.toList(); - var curBatch = int.tryParse(rTmp[0][0] ?? 0) as int; + var result = await connection.query('SELECT MAX(batch) from migrations;'); - r = await connection + var curBatch = 0; + if (result.isNotEmpty) { + var firstRow = result.toList(); + curBatch = int.tryParse(firstRow[0][0]) as int; + } + + result = await connection .query('SELECT path from migrations WHERE batch = $curBatch;'); - var existing = r.expand((x) => x).cast(); + var existing = []; + if (result.isNotEmpty) { + existing = result.expand((x) => x).cast().toList(); + } + var toRun = []; migrations.forEach((k, v) { @@ -128,7 +142,11 @@ class MariaDbMigrationRunner implements MigrationRunner { await _init(); var r = await connection .query('SELECT path from migrations ORDER BY batch DESC;'); - var existing = r.expand((x) => x).cast(); + var existing = []; + if (r.isNotEmpty) { + existing = r.expand((x) => x).cast().toList(); + } + var toRun = existing.where(migrations.containsKey).toList(); if (toRun.isNotEmpty) { diff --git a/packages/orm/angel_migration_runner/lib/src/mariadb/schema.dart b/packages/orm/angel_migration_runner/lib/src/mariadb/schema.dart index f9ed00e2..90a04d4f 100644 --- a/packages/orm/angel_migration_runner/lib/src/mariadb/schema.dart +++ b/packages/orm/angel_migration_runner/lib/src/mariadb/schema.dart @@ -42,7 +42,7 @@ class MariaDbSchema extends Schema { @override void drop(String tableName, {bool cascade = false}) { var c = cascade == true ? ' CASCADE' : ''; - _writeln('DROP TABLE "$tableName"$c;'); + _writeln('DROP TABLE $tableName$c;'); } @override diff --git a/packages/orm/angel_migration_runner/lib/src/mysql/runner.dart b/packages/orm/angel_migration_runner/lib/src/mysql/runner.dart index c06ca06c..a2cc93a2 100644 --- a/packages/orm/angel_migration_runner/lib/src/mysql/runner.dart +++ b/packages/orm/angel_migration_runner/lib/src/mysql/runner.dart @@ -54,8 +54,11 @@ class MySqlMigrationRunner implements MigrationRunner { @override Future up() async { await _init(); - var r = await connection.execute('SELECT path from migrations;'); - var existing = r.rows.cast(); //.expand((x) => x).cast(); + var result = await connection.execute('SELECT path from migrations;'); + var existing = []; + if (result.rows.isNotEmpty) { + existing = result.rows.first.assoc().values.cast().toList(); + } var toRun = []; migrations.forEach((k, v) { @@ -63,11 +66,14 @@ class MySqlMigrationRunner implements MigrationRunner { }); if (toRun.isNotEmpty) { - var r = await connection.execute('SELECT MAX(batch) from migrations;'); - var rTmp = r.rows.first; //r.toList(); - var curBatch = - int.tryParse(rTmp.colAt(0) ?? "0") ?? 0; //(rTmp[0][0] ?? 0) as int; - var batch = curBatch + 1; + var result = + await connection.execute('SELECT MAX(batch) from migrations;'); + var curBatch = 0; + if (result.rows.isNotEmpty) { + var firstRow = result.rows.first; + curBatch = int.tryParse(firstRow.colAt(0) ?? "0") ?? 0; + } + curBatch++; for (var k in toRun) { var migration = migrations[k]!; @@ -77,16 +83,13 @@ class MySqlMigrationRunner implements MigrationRunner { await schema.run(connection).then((_) async { var result = await connection .execute( - "INSERT INTO MIGRATIONS (batch, path) VALUES ($batch, '$k')") + "INSERT INTO migrations (batch, path) VALUES ($curBatch, '$k')") .catchError((e) { _log.severe('Failed to insert into "migrations" table.', e); }); return result.affectedRows.toInt(); }); - //return connection.execute( - // 'INSERT INTO MIGRATIONS (batch, path) VALUES ($batch, \'$k\');'); - } } else { _log.warning('Nothing to add into "migrations" table.'); @@ -97,14 +100,18 @@ class MySqlMigrationRunner implements MigrationRunner { Future rollback() async { await _init(); - var r = await connection.execute('SELECT MAX(batch) from migrations;'); - var rTmp = r.rows.first; //r.toList(); - var curBatch = - int.tryParse(rTmp.colAt(0) ?? "0") ?? 0; //(rTmp[0][0] ?? 0) as int; - - r = await connection + var result = await connection.execute('SELECT MAX(batch) from migrations;'); + var curBatch = 0; + if (result.rows.isNotEmpty) { + var firstRow = result.rows.first; + curBatch = int.tryParse(firstRow.colAt(0) ?? "0") ?? 0; + } + result = await connection .execute('SELECT path from migrations WHERE batch = $curBatch;'); - var existing = r.rows.cast(); //r.expand((x) => x).cast(); + var existing = []; + if (result.rows.isNotEmpty) { + existing = result.rows.first.assoc().values.cast().toList(); + } var toRun = []; migrations.forEach((k, v) { @@ -130,9 +137,13 @@ class MySqlMigrationRunner implements MigrationRunner { @override Future reset() async { await _init(); - var r = await connection + var result = await connection .execute('SELECT path from migrations ORDER BY batch DESC;'); - var existing = r.rows.cast(); //r.expand((x) => x).cast(); + var existing = []; + if (result.rows.isNotEmpty) { + var firstRow = result.rows.first; + existing = firstRow.assoc().values.cast().toList(); + } var toRun = existing.where(migrations.containsKey).toList(); if (toRun.isNotEmpty) { From 3db9c53fddc3d5c4a9fabe54f6d1424c401cc9b5 Mon Sep 17 00:00:00 2001 From: "thomashii@dukefirehawk.com" Date: Thu, 28 Jul 2022 01:03:31 +0800 Subject: [PATCH 12/13] Reverted lints to 1.x.x --- experiment/db/pubspec.yaml | 2 +- experiment/logging/pubspec.yaml | 2 +- packages/auth_twitter/pubspec.yaml | 2 +- packages/orm/angel_migration/CHANGELOG.md | 4 ++-- packages/orm/angel_migration/pubspec.yaml | 4 ++-- packages/orm/angel_migration_runner/CHANGELOG.md | 1 - packages/orm/angel_migration_runner/pubspec.yaml | 2 +- packages/orm/angel_orm/CHANGELOG.md | 1 - packages/orm/angel_orm/pubspec.yaml | 2 +- packages/orm/angel_orm_generator/CHANGELOG.md | 1 - packages/orm/angel_orm_generator/pubspec.yaml | 2 +- packages/orm/angel_orm_mysql/pubspec.yaml | 2 +- packages/orm/angel_orm_mysql/test/common.dart | 2 +- packages/orm/angel_orm_postgres/CHANGELOG.md | 1 - packages/orm/angel_orm_postgres/README.md | 2 +- packages/orm/angel_orm_postgres/pubspec.yaml | 2 +- packages/orm/angel_orm_test/CHANGELOG.md | 3 +-- packages/orm/angel_orm_test/pubspec.yaml | 4 ++-- packages/serialize/angel_serialize_generator/CHANGELOG.md | 1 - packages/serialize/angel_serialize_generator/pubspec.yaml | 2 +- 20 files changed, 18 insertions(+), 24 deletions(-) diff --git a/experiment/db/pubspec.yaml b/experiment/db/pubspec.yaml index bfb3e131..f19525c9 100644 --- a/experiment/db/pubspec.yaml +++ b/experiment/db/pubspec.yaml @@ -9,4 +9,4 @@ dependencies: mysql1: ^0.20.0 mysql_client: ^0.0.24 dev_dependencies: - lints: ^2.0.0 \ No newline at end of file + lints: ^1.0.0 \ No newline at end of file diff --git a/experiment/logging/pubspec.yaml b/experiment/logging/pubspec.yaml index 7b1205e4..0bfdd66a 100644 --- a/experiment/logging/pubspec.yaml +++ b/experiment/logging/pubspec.yaml @@ -8,4 +8,4 @@ published_to: none dependencies: http: ^0.13.4 dev_dependencies: - lints: ^2.0.0 \ No newline at end of file + lints: ^1.0.0 \ No newline at end of file diff --git a/packages/auth_twitter/pubspec.yaml b/packages/auth_twitter/pubspec.yaml index aab30e72..f677e6d0 100644 --- a/packages/auth_twitter/pubspec.yaml +++ b/packages/auth_twitter/pubspec.yaml @@ -15,4 +15,4 @@ dependencies: dart_twitter_api: ^0.5.6+1 dev_dependencies: logging: ^1.0.0 - lints: ^2.0.0 + lints: ^1.0.0 diff --git a/packages/orm/angel_migration/CHANGELOG.md b/packages/orm/angel_migration/CHANGELOG.md index bb59d67a..c87a8031 100755 --- a/packages/orm/angel_migration/CHANGELOG.md +++ b/packages/orm/angel_migration/CHANGELOG.md @@ -1,8 +1,8 @@ # Change Log -## 6.0.1 +## 6.1.0 -* Upgraded to `lints` 2.x.x +* Updated temporal fields ## 6.0.0 diff --git a/packages/orm/angel_migration/pubspec.yaml b/packages/orm/angel_migration/pubspec.yaml index a2a381db..8f6ab129 100755 --- a/packages/orm/angel_migration/pubspec.yaml +++ b/packages/orm/angel_migration/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_migration -version: 6.0.1 +version: 6.1.0 description: Database migration runtime for Angel3 ORM. Use this package to define schemas. homepage: https://angel3-framework.web.app/ repository: https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_migration @@ -8,7 +8,7 @@ environment: dependencies: angel3_orm: ^6.0.0 dev_dependencies: - lints: ^2.0.0 + lints: ^1.0.0 dependency_overrides: angel3_orm: path: ../angel_orm diff --git a/packages/orm/angel_migration_runner/CHANGELOG.md b/packages/orm/angel_migration_runner/CHANGELOG.md index 4c1d8532..313f1ba6 100755 --- a/packages/orm/angel_migration_runner/CHANGELOG.md +++ b/packages/orm/angel_migration_runner/CHANGELOG.md @@ -2,7 +2,6 @@ ## 6.1.0 -* Upgraded to `lints` 2.x.x * Fixed issue #70. Incorrectly generated SQL for `defaultsTo('Default Value')` * Mapped timestamp to datetime for MySQL and MariaDB * Fixed `MariaDbMigrationRunner` to work with MariaDB diff --git a/packages/orm/angel_migration_runner/pubspec.yaml b/packages/orm/angel_migration_runner/pubspec.yaml index ebfd6aa2..1aced63c 100755 --- a/packages/orm/angel_migration_runner/pubspec.yaml +++ b/packages/orm/angel_migration_runner/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: mysql1: ^0.20.0 logging: ^1.0.0 dev_dependencies: - lints: ^2.0.0 + lints: ^1.0.0 dependency_overrides: angel3_orm: path: ../angel_orm diff --git a/packages/orm/angel_orm/CHANGELOG.md b/packages/orm/angel_orm/CHANGELOG.md index 3ddcfb7d..f593bec1 100644 --- a/packages/orm/angel_orm/CHANGELOG.md +++ b/packages/orm/angel_orm/CHANGELOG.md @@ -4,7 +4,6 @@ * Fixed issue #68: Support for non-nullable type * Added `defaultValue` to `@Column` annotation -* Upgraded to `lints` 2.x.x ## 6.0.1 diff --git a/packages/orm/angel_orm/pubspec.yaml b/packages/orm/angel_orm/pubspec.yaml index f5bb64b4..b8c7fed2 100644 --- a/packages/orm/angel_orm/pubspec.yaml +++ b/packages/orm/angel_orm/pubspec.yaml @@ -18,7 +18,7 @@ dev_dependencies: angel3_serialize_generator: ^6.0.0 build_runner: ^2.1.1 test: ^1.17.4 - lints: ^2.0.0 + lints: ^1.0.0 # dependency_overrides: # angel3_serialize: # path: ../../serialize/angel_serialize diff --git a/packages/orm/angel_orm_generator/CHANGELOG.md b/packages/orm/angel_orm_generator/CHANGELOG.md index 4b7c5cd9..4b681411 100644 --- a/packages/orm/angel_orm_generator/CHANGELOG.md +++ b/packages/orm/angel_orm_generator/CHANGELOG.md @@ -3,7 +3,6 @@ ## 6.2.0 * Fixed issue #68: Support for non-nullable type -* Upgraded to `lints` 2.x.x * Generate default value based on `defaultValue` in the `@Column` annotation ## 6.1.0 diff --git a/packages/orm/angel_orm_generator/pubspec.yaml b/packages/orm/angel_orm_generator/pubspec.yaml index 879e6ee9..67a65ef9 100644 --- a/packages/orm/angel_orm_generator/pubspec.yaml +++ b/packages/orm/angel_orm_generator/pubspec.yaml @@ -29,7 +29,7 @@ dev_dependencies: build_runner: ^2.0.1 postgres: ^2.4.0 test: ^1.21.0 - lints: ^2.0.0 + lints: ^1.0.0 dependency_overrides: # angel3_container: # path: ../../container/angel_container diff --git a/packages/orm/angel_orm_mysql/pubspec.yaml b/packages/orm/angel_orm_mysql/pubspec.yaml index 7cff37b3..85d6f8bb 100644 --- a/packages/orm/angel_orm_mysql/pubspec.yaml +++ b/packages/orm/angel_orm_mysql/pubspec.yaml @@ -16,7 +16,7 @@ dev_dependencies: angel3_orm_test: ^6.0.0 build_runner: ^2.0.1 test: ^1.21.0 - lints: ^2.0.0 + lints: ^1.0.0 dependency_overrides: # angel3_serialize: # path: ../../serialize/angel_serialize diff --git a/packages/orm/angel_orm_mysql/test/common.dart b/packages/orm/angel_orm_mysql/test/common.dart index 27c05947..00c5230c 100644 --- a/packages/orm/angel_orm_mysql/test/common.dart +++ b/packages/orm/angel_orm_mysql/test/common.dart @@ -91,7 +91,7 @@ Future _connectToMySql(List schemas) async { host: "localhost", userName: Platform.environment['MYSQL_USERNAME'] ?? 'test', password: Platform.environment['MYSQL_PASSWORD'] ?? 'test123', - secure: false); + secure: true); await connection.connect(timeoutMs: 10000); diff --git a/packages/orm/angel_orm_postgres/CHANGELOG.md b/packages/orm/angel_orm_postgres/CHANGELOG.md index c2f3f058..55ee34a0 100644 --- a/packages/orm/angel_orm_postgres/CHANGELOG.md +++ b/packages/orm/angel_orm_postgres/CHANGELOG.md @@ -2,7 +2,6 @@ ## 6.1.0 -* Upgraded to `lints` 2.x.x * Fixed #71. Restablish broken connection automatically. ## 6.0.0 diff --git a/packages/orm/angel_orm_postgres/README.md b/packages/orm/angel_orm_postgres/README.md index 1c674180..bc5a6a79 100644 --- a/packages/orm/angel_orm_postgres/README.md +++ b/packages/orm/angel_orm_postgres/README.md @@ -9,6 +9,6 @@ PostgreSQL support for Angel3 ORM. ## Supported database -* PostgreSQL version 10 or later +* PostgreSQL version 10 or greater For documentation about the ORM, see [Developer Guide](https://angel3-docs.dukefirehawk.com/guides/orm) diff --git a/packages/orm/angel_orm_postgres/pubspec.yaml b/packages/orm/angel_orm_postgres/pubspec.yaml index 8e2959ae..5dd8d8aa 100644 --- a/packages/orm/angel_orm_postgres/pubspec.yaml +++ b/packages/orm/angel_orm_postgres/pubspec.yaml @@ -15,7 +15,7 @@ dev_dependencies: belatuk_pretty_logging: ^4.0.0 angel3_orm_test: ^6.0.0 test: ^1.21.0 - lints: ^2.0.0 + lints: ^1.0.0 dependency_overrides: # angel3_serialize: # path: ../../serialize/angel_serialize diff --git a/packages/orm/angel_orm_test/CHANGELOG.md b/packages/orm/angel_orm_test/CHANGELOG.md index f6493369..6f55ad2d 100644 --- a/packages/orm/angel_orm_test/CHANGELOG.md +++ b/packages/orm/angel_orm_test/CHANGELOG.md @@ -1,9 +1,8 @@ # Change Log -## 6.0.1 +## 6.1.0 * Added test cases for non nullable type -* Upgraded to `lints` 2.x.x ## 6.0.0 diff --git a/packages/orm/angel_orm_test/pubspec.yaml b/packages/orm/angel_orm_test/pubspec.yaml index 7eb623b7..95b8ca00 100644 --- a/packages/orm/angel_orm_test/pubspec.yaml +++ b/packages/orm/angel_orm_test/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_orm_test -version: 6.0.1 +version: 6.1.0 description: Common tests for Angel3 ORM. Reference implmentation of the generated ORM files. homepage: https://angel3-framework.web.app/ repository: https://github.com/dukefirehawk/angel/tree/master/packages/orm/angel_orm_test @@ -18,7 +18,7 @@ dev_dependencies: angel3_orm_generator: ^6.0.0 angel3_framework: ^6.0.0 build_runner: ^2.0.1 - lints: ^2.0.0 + lints: ^1.0.0 dependency_overrides: # angel3_container: # path: ../../container/angel_container diff --git a/packages/serialize/angel_serialize_generator/CHANGELOG.md b/packages/serialize/angel_serialize_generator/CHANGELOG.md index ff91d5e4..9ccba0a3 100644 --- a/packages/serialize/angel_serialize_generator/CHANGELOG.md +++ b/packages/serialize/angel_serialize_generator/CHANGELOG.md @@ -3,7 +3,6 @@ ## 6.1.1 * Fixed issue #68: Support for non-nullable type -* Upgraded to `lints` 2.x.x ## 6.1.0 diff --git a/packages/serialize/angel_serialize_generator/pubspec.yaml b/packages/serialize/angel_serialize_generator/pubspec.yaml index 1d7b5778..403f7816 100644 --- a/packages/serialize/angel_serialize_generator/pubspec.yaml +++ b/packages/serialize/angel_serialize_generator/pubspec.yaml @@ -22,7 +22,7 @@ dependencies: dev_dependencies: build_runner: ^2.0.1 collection: ^1.15.0 - lints: ^2.0.0 + lints: ^1.0.0 test: ^1.21.0 # dependency_overrides: # angel3_model: From c30609f955cde02f3cb7db17a11fef9b41a24d9c Mon Sep 17 00:00:00 2001 From: "thomashii@dukefirehawk.com" Date: Sat, 30 Jul 2022 23:08:38 +0800 Subject: [PATCH 13/13] Fixed postgreSQL failed test cases --- .../{mysql_sql_main.dart => mysql_main.dart} | 0 experiment/db/bin/pg_main.dart | 53 +++++++++++++++++++ experiment/db/pubspec.yaml | 2 + packages/orm/angel_orm/lib/src/util.dart | 10 ++++ .../lib/src/orm_generator.dart | 7 ++- .../orm/angel_orm_mysql/example/main.dart | 6 +-- packages/orm/angel_orm_postgres/pubspec.yaml | 10 ++-- .../lib/src/models/asset.g.dart | 16 ++++-- .../angel_orm_test/lib/src/models/bike.g.dart | 8 ++- .../angel_orm_test/lib/src/models/boat.g.dart | 8 ++- .../angel_orm_test/lib/src/models/book.g.dart | 16 ++++-- .../angel_orm_test/lib/src/models/car.g.dart | 13 +++-- .../lib/src/models/custom_expr.g.dart | 16 ++++-- .../lib/src/models/has_car.g.dart | 8 ++- .../angel_orm_test/lib/src/models/leg.g.dart | 16 ++++-- .../lib/src/models/order.g.dart | 21 +++++--- .../lib/src/models/person.g.dart | 8 ++- .../lib/src/models/person_order.g.dart | 16 ++++-- .../angel_orm_test/lib/src/models/tree.g.dart | 16 ++++-- .../lib/src/models/unorthodox.g.dart | 8 ++- .../angel_orm_test/lib/src/models/user.g.dart | 16 ++++-- 21 files changed, 216 insertions(+), 58 deletions(-) rename experiment/db/bin/{mysql_sql_main.dart => mysql_main.dart} (100%) create mode 100644 experiment/db/bin/pg_main.dart diff --git a/experiment/db/bin/mysql_sql_main.dart b/experiment/db/bin/mysql_main.dart similarity index 100% rename from experiment/db/bin/mysql_sql_main.dart rename to experiment/db/bin/mysql_main.dart diff --git a/experiment/db/bin/pg_main.dart b/experiment/db/bin/pg_main.dart new file mode 100644 index 00000000..7c6397f4 --- /dev/null +++ b/experiment/db/bin/pg_main.dart @@ -0,0 +1,53 @@ +import 'dart:io'; + +import 'package:postgres/postgres.dart'; + +void main() async { + /* + * Granting permission in postgres + * grant all privileges on database orm_test to test; + * grant all privileges on sequence users_id_seq to test; + */ + print("=== Start 'postgres' driver test"); + await testPgDriver().catchError((error, stackTrace) { + print(error); + }); + print("=== End test"); + print(" "); + + exit(0); +} + +Future testPgDriver() async { + var conn = PostgreSQLConnection('localhost', 5432, 'orm_test', + username: 'test', password: 'test123'); + await conn.open(); + + print(">Test Select All"); + var result = await conn.query("SELECT * from users"); + print("Total records: ${result.length}"); + for (var row in result) { + print(row[0]); + for (var element in row) { + print(element); + } + } + + print(">Test Insert"); + var params = { + "username": "test", + "password": "test123", + "email": "test@demo.com", + "updatedAt": DateTime.parse("1970-01-01 00:00:00") + }; + + result = await conn.query( + "INSERT INTO users (username, password, email, updated_at) VALUES (@username, @password, @email, @updatedAt)", + substitutionValues: params); + //print("Last inserted ID: ${result.}"); + + //print(">Test Select By ID"); + //result = await conn.query("SELECT * from users where id=@id", + // substitutionValues: {"id": result}); + //print("Read record: ${result.length}"); +} diff --git a/experiment/db/pubspec.yaml b/experiment/db/pubspec.yaml index f19525c9..0815302f 100644 --- a/experiment/db/pubspec.yaml +++ b/experiment/db/pubspec.yaml @@ -8,5 +8,7 @@ published_to: none dependencies: mysql1: ^0.20.0 mysql_client: ^0.0.24 + postgres: ^2.4.1 + postgres_pool: ^2.1.3 dev_dependencies: lints: ^1.0.0 \ No newline at end of file diff --git a/packages/orm/angel_orm/lib/src/util.dart b/packages/orm/angel_orm/lib/src/util.dart index 28604fef..eeab7c10 100644 --- a/packages/orm/angel_orm/lib/src/util.dart +++ b/packages/orm/angel_orm/lib/src/util.dart @@ -22,6 +22,8 @@ String mapToText(dynamic value) { return value; } +/// Helper method to convert dynamic value to DateTime. +/// If null return January 1st, 1970 at 00:00:00 UTC as default DateTime mapToDateTime(dynamic value) { if (value == null) { return defaultDate; @@ -32,6 +34,14 @@ DateTime mapToDateTime(dynamic value) { return value; } +/// Helper method to convert dynamic value to nullable DateTime +DateTime? mapToNullableDateTime(dynamic value) { + if (value is String) { + return DateTime.tryParse(value); + } + return value; +} + double mapToDouble(dynamic value) { if (value == null) { return 0.0; diff --git a/packages/orm/angel_orm_generator/lib/src/orm_generator.dart b/packages/orm/angel_orm_generator/lib/src/orm_generator.dart index 8488c7f8..7cbbbce9 100644 --- a/packages/orm/angel_orm_generator/lib/src/orm_generator.dart +++ b/packages/orm/angel_orm_generator/lib/src/orm_generator.dart @@ -274,9 +274,12 @@ class OrmGenerator extends GeneratorForAnnotation { // Generated Code: mapToBool(row[i]) expr = refer('mapToBool').call([expr]); } else if (fType.element?.displayName == 'DateTime') { - // print("fType: ${fType.element?.displayName}"); // Generated Code: mapToDateTime(row[i]) - expr = refer('mapToDateTime').call([expr]); + if (fType.nullabilitySuffix == NullabilitySuffix.question) { + expr = refer('mapToNullableDateTime').call([expr]); + } else { + expr = refer('mapToDateTime').call([expr]); + } } else { // Generated Code: (row[i] as type?) expr = expr.asA(type); diff --git a/packages/orm/angel_orm_mysql/example/main.dart b/packages/orm/angel_orm_mysql/example/main.dart index a32806d7..58f16e3e 100644 --- a/packages/orm/angel_orm_mysql/example/main.dart +++ b/packages/orm/angel_orm_mysql/example/main.dart @@ -13,8 +13,8 @@ part 'main.g.dart'; void main() async { //hierarchicalLoggingEnabled = true; - await mariaDBExample(); - //await mysqlExample(); + //await mariaDBExample(); + await mysqlExample(); exit(0); } @@ -62,7 +62,7 @@ Future mysqlExample() async { databaseName: "orm_test", userName: "test", password: "test123", - secure: false); + secure: true); print("Connected to MySQL"); var logger = Logger('orm_mysql'); diff --git a/packages/orm/angel_orm_postgres/pubspec.yaml b/packages/orm/angel_orm_postgres/pubspec.yaml index 5dd8d8aa..3abe1ae0 100644 --- a/packages/orm/angel_orm_postgres/pubspec.yaml +++ b/packages/orm/angel_orm_postgres/pubspec.yaml @@ -17,13 +17,13 @@ dev_dependencies: test: ^1.21.0 lints: ^1.0.0 dependency_overrides: -# angel3_serialize: -# path: ../../serialize/angel_serialize + angel3_serialize: + path: ../../serialize/angel_serialize # angel3_model: # path: ../../model - angel3_orm_test: + angel3_orm_test: path: ../angel_orm_test - angel3_orm: + angel3_orm: path: ../angel_orm - angel3_migration: + angel3_migration: path: ../angel_migration diff --git a/packages/orm/angel_orm_test/lib/src/models/asset.g.dart b/packages/orm/angel_orm_test/lib/src/models/asset.g.dart index ef882202..b6fb1813 100644 --- a/packages/orm/angel_orm_test/lib/src/models/asset.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/asset.g.dart @@ -99,8 +99,12 @@ class ItemQuery extends Query { } var model = Item( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, description: fields.contains('description') ? (row[3] as String) : ''); return Optional.of(model); } @@ -236,8 +240,12 @@ class AssetQuery extends Query { } var model = Asset( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, description: fields.contains('description') ? (row[3] as String) : '', name: fields.contains('name') ? (row[4] as String) : '', price: fields.contains('price') ? mapToDouble(row[5]) : 0.0); diff --git a/packages/orm/angel_orm_test/lib/src/models/bike.g.dart b/packages/orm/angel_orm_test/lib/src/models/bike.g.dart index 9397418d..db854073 100644 --- a/packages/orm/angel_orm_test/lib/src/models/bike.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/bike.g.dart @@ -95,8 +95,12 @@ class BikeQuery extends Query { } var model = Bike( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, make: fields.contains('make') ? (row[3] as String) : '', description: fields.contains('description') ? (row[4] as String) : '', familyFriendly: diff --git a/packages/orm/angel_orm_test/lib/src/models/boat.g.dart b/packages/orm/angel_orm_test/lib/src/models/boat.g.dart index 62da26e3..ba5405cf 100644 --- a/packages/orm/angel_orm_test/lib/src/models/boat.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/boat.g.dart @@ -95,8 +95,12 @@ class BoatQuery extends Query { } var model = Boat( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, make: fields.contains('make') ? (row[3] as String) : '', description: fields.contains('description') ? (row[4] as String) : '', familyFriendly: diff --git a/packages/orm/angel_orm_test/lib/src/models/book.g.dart b/packages/orm/angel_orm_test/lib/src/models/book.g.dart index 7d954e42..b893f00a 100644 --- a/packages/orm/angel_orm_test/lib/src/models/book.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/book.g.dart @@ -122,8 +122,12 @@ class BookQuery extends Query { } var model = Book( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, name: fields.contains('name') ? (row[5] as String?) : null); if (row.length > 6) { var modelOpt = AuthorQuery().parseRow(row.skip(6).take(4).toList()); @@ -285,8 +289,12 @@ class AuthorQuery extends Query { } var model = Author( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, name: fields.contains('name') ? (row[3] as String?) : null); return Optional.of(model); } diff --git a/packages/orm/angel_orm_test/lib/src/models/car.g.dart b/packages/orm/angel_orm_test/lib/src/models/car.g.dart index 80e7ffb9..60edc83f 100644 --- a/packages/orm/angel_orm_test/lib/src/models/car.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/car.g.dart @@ -91,15 +91,20 @@ class CarQuery extends Query { } var model = Car( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, make: fields.contains('make') ? (row[3] as String?) : null, description: fields.contains('description') ? (row[4] as String?) : null, familyFriendly: fields.contains('family_friendly') ? mapToBool(row[5]) : null, - recalledAt: - fields.contains('recalled_at') ? mapToDateTime(row[6]) : null); + recalledAt: fields.contains('recalled_at') + ? mapToNullableDateTime(row[6]) + : null); return Optional.of(model); } diff --git a/packages/orm/angel_orm_test/lib/src/models/custom_expr.g.dart b/packages/orm/angel_orm_test/lib/src/models/custom_expr.g.dart index 808af190..38134225 100644 --- a/packages/orm/angel_orm_test/lib/src/models/custom_expr.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/custom_expr.g.dart @@ -101,8 +101,12 @@ class NumbersQuery extends Query { } var model = Numbers( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, two: fields.contains('two') ? (row[3] as int?) : null); return Optional.of(model); } @@ -218,8 +222,12 @@ class AlphabetQuery extends Query { } var model = Alphabet( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, value: fields.contains('value') ? (row[3] as String?) : null); if (row.length > 5) { var modelOpt = NumbersQuery().parseRow(row.skip(5).take(4).toList()); diff --git a/packages/orm/angel_orm_test/lib/src/models/has_car.g.dart b/packages/orm/angel_orm_test/lib/src/models/has_car.g.dart index 2a40096d..65f70b26 100644 --- a/packages/orm/angel_orm_test/lib/src/models/has_car.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/has_car.g.dart @@ -81,8 +81,12 @@ class HasCarQuery extends Query { } var model = HasCar( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, type: fields.contains('type') ? row[3] == null ? null diff --git a/packages/orm/angel_orm_test/lib/src/models/leg.g.dart b/packages/orm/angel_orm_test/lib/src/models/leg.g.dart index 336689eb..d01cb636 100644 --- a/packages/orm/angel_orm_test/lib/src/models/leg.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/leg.g.dart @@ -110,8 +110,12 @@ class LegQuery extends Query { } var model = Leg( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, name: fields.contains('name') ? (row[3] as String?) : null); if (row.length > 4) { var modelOpt = FootQuery().parseRow(row.skip(4).take(5).toList()); @@ -239,8 +243,12 @@ class FootQuery extends Query { } var model = Foot( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, legId: fields.contains('leg_id') ? (row[3] as int?) : null, nToes: fields.contains('n_toes') ? mapToDouble(row[4]) : null); return Optional.of(model); diff --git a/packages/orm/angel_orm_test/lib/src/models/order.g.dart b/packages/orm/angel_orm_test/lib/src/models/order.g.dart index 5fd06694..cdf5f1a8 100644 --- a/packages/orm/angel_orm_test/lib/src/models/order.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/order.g.dart @@ -115,10 +115,16 @@ class OrderQuery extends Query { } var model = Order( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, employeeId: fields.contains('employee_id') ? (row[4] as int?) : null, - orderDate: fields.contains('order_date') ? mapToDateTime(row[5]) : null, + orderDate: fields.contains('order_date') + ? mapToNullableDateTime(row[5]) + : null, shipperId: fields.contains('shipper_id') ? (row[6] as int?) : null); if (row.length > 7) { var modelOpt = CustomerQuery().parseRow(row.skip(7).take(3).toList()); @@ -284,9 +290,12 @@ class CustomerQuery extends Query { } var model = Customer( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: - fields.contains('updated_at') ? mapToDateTime(row[2]) : null); + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null); return Optional.of(model); } diff --git a/packages/orm/angel_orm_test/lib/src/models/person.g.dart b/packages/orm/angel_orm_test/lib/src/models/person.g.dart index f76b4bee..55d2a424 100644 --- a/packages/orm/angel_orm_test/lib/src/models/person.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/person.g.dart @@ -82,8 +82,12 @@ class PersonQuery extends Query { } var model = Person( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, name: fields.contains('name') ? (row[3] as String?) : null, age: fields.contains('age') ? (row[4] as int?) : null); return Optional.of(model); diff --git a/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart b/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart index 04ce92cb..069b75a2 100644 --- a/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/person_order.g.dart @@ -92,8 +92,12 @@ class PersonOrderQuery extends Query { } var model = PersonOrder( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, personId: fields.contains('person_id') ? (row[3] as int?) : null, name: fields.contains('name') ? (row[4] as String?) : null, price: fields.contains('price') ? mapToDouble(row[5]) : null, @@ -255,8 +259,12 @@ class OrderWithPersonInfoQuery } var model = OrderWithPersonInfo( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, name: fields.contains('name') ? (row[3] as String?) : null, price: fields.contains('price') ? mapToDouble(row[4]) : null, deleted: fields.contains('deleted') ? mapToBool(row[5]) : null, diff --git a/packages/orm/angel_orm_test/lib/src/models/tree.g.dart b/packages/orm/angel_orm_test/lib/src/models/tree.g.dart index ea1b4063..1555e35e 100644 --- a/packages/orm/angel_orm_test/lib/src/models/tree.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/tree.g.dart @@ -110,8 +110,12 @@ class TreeQuery extends Query { } var model = Tree( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, rings: fields.contains('rings') ? (row[3] as int?) : null); if (row.length > 4) { var modelOpt = FruitQuery().parseRow(row.skip(4).take(5).toList()); @@ -299,8 +303,12 @@ class FruitQuery extends Query { } var model = Fruit( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, treeId: fields.contains('tree_id') ? (row[3] as int?) : null, commonName: fields.contains('common_name') ? (row[4] as String?) : null); diff --git a/packages/orm/angel_orm_test/lib/src/models/unorthodox.g.dart b/packages/orm/angel_orm_test/lib/src/models/unorthodox.g.dart index 91446563..cbdfa9bc 100644 --- a/packages/orm/angel_orm_test/lib/src/models/unorthodox.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/unorthodox.g.dart @@ -486,8 +486,12 @@ class SongQuery extends Query { } var model = Song( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, weirdJoinId: fields.contains('weird_join_id') ? (row[3] as int?) : null, title: fields.contains('title') ? (row[4] as String?) : null); return Optional.of(model); diff --git a/packages/orm/angel_orm_test/lib/src/models/user.g.dart b/packages/orm/angel_orm_test/lib/src/models/user.g.dart index 7e7a43bb..d9bc91a4 100644 --- a/packages/orm/angel_orm_test/lib/src/models/user.g.dart +++ b/packages/orm/angel_orm_test/lib/src/models/user.g.dart @@ -127,8 +127,12 @@ class UserQuery extends Query { } var model = User( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, username: fields.contains('username') ? (row[3] as String?) : null, password: fields.contains('password') ? (row[4] as String?) : null, email: fields.contains('email') ? (row[5] as String?) : null); @@ -487,8 +491,12 @@ class RoleQuery extends Query { } var model = Role( id: fields.contains('id') ? row[0].toString() : null, - createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, - updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, + createdAt: fields.contains('created_at') + ? mapToNullableDateTime(row[1]) + : null, + updatedAt: fields.contains('updated_at') + ? mapToNullableDateTime(row[2]) + : null, name: fields.contains('name') ? (row[3] as String?) : null); if (row.length > 4) { var modelOpt = UserQuery().parseRow(row.skip(4).take(6).toList());