Fixed issue 70

This commit is contained in:
thomashii 2022-06-11 14:39:29 +08:00
parent da5b87043d
commit 224d2be026
17 changed files with 92 additions and 55 deletions

View file

@ -3,6 +3,7 @@
## 6.0.2 ## 6.0.2
* Upgraded to `lints` 2.x.x * Upgraded to `lints` 2.x.x
* Fixed issue #70. Incorrectly generated SQL for `defaultsTo('Default Value')`
## 6.0.1 ## 6.0.1

View file

@ -6,7 +6,7 @@ import 'package:charcode/ascii.dart';
abstract class MariaDbGenerator { abstract class MariaDbGenerator {
static String columnType(MigrationColumn column) { static String columnType(MigrationColumn column) {
var str = column.type.name; var str = column.type.name;
if (column.type.hasSize) { if (column.type.hasLength) {
return '$str(${column.length})'; return '$str(${column.length})';
} else { } else {
return str; return str;

View file

@ -6,7 +6,7 @@ import 'package:charcode/ascii.dart';
abstract class MySqlGenerator { abstract class MySqlGenerator {
static String columnType(MigrationColumn column) { static String columnType(MigrationColumn column) {
var str = column.type.name; var str = column.type.name;
if (column.type.hasSize) { if (column.type.hasLength) {
return '$str(${column.length})'; return '$str(${column.length})';
} else { } else {
return str; return str;

View file

@ -6,7 +6,7 @@ import 'package:charcode/ascii.dart';
abstract class PostgresGenerator { abstract class PostgresGenerator {
static String columnType(MigrationColumn column) { static String columnType(MigrationColumn column) {
var str = column.type.name; var str = column.type.name;
if (column.type.hasSize) { if (column.type.hasLength) {
return '$str(${column.length})'; return '$str(${column.length})';
} else { } else {
return str; return str;
@ -31,11 +31,10 @@ abstract class PostgresGenerator {
b.writeCharCode(ch); b.writeCharCode(ch);
} }
} }
s = b.toString(); s = '\'${b.toString()}\'';
} else { } else {
s = value.toString(); s = value.toString();
} }
buf.write(' DEFAULT $s'); buf.write(' DEFAULT $s');
} }
@ -46,7 +45,7 @@ abstract class PostgresGenerator {
} }
for (var ref in column.externalReferences) { for (var ref in column.externalReferences) {
buf.write(' ' + compileReference(ref)); buf.write(' ${compileReference(ref)}');
} }
return buf.toString(); return buf.toString();
@ -55,7 +54,7 @@ abstract class PostgresGenerator {
static String compileReference(MigrationColumnReference ref) { static String compileReference(MigrationColumnReference ref) {
var buf = var buf =
StringBuffer('REFERENCES "${ref.foreignTable}"("${ref.foreignKey}")'); 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(); return buf.toString();
} }
} }
@ -147,9 +146,9 @@ class PostgresAlterTable extends Table implements MutableTable {
} }
@override @override
void changeColumnType(String name, ColumnType type, {int length = 256}) { void changeColumnType(String name, ColumnType type, {int length = 255}) {
_stack.add('ALTER COLUMN "$name" TYPE ' + _stack.add(
PostgresGenerator.columnType(MigrationColumn(type, length: length))); 'ALTER COLUMN "$name" TYPE ${PostgresGenerator.columnType(MigrationColumn(type, length: length))}');
} }
@override @override

View file

@ -16,8 +16,8 @@ dependencies:
logging: ^1.0.0 logging: ^1.0.0
dev_dependencies: dev_dependencies:
lints: ^2.0.0 lints: ^2.0.0
# dependency_overrides: dependency_overrides:
# angel3_orm: angel3_orm:
# path: ../angel_orm path: ../angel_orm
# angel3_migration: angel3_migration:
# path: ../angel_migration path: ../angel_migration

View file

@ -129,32 +129,28 @@ class ColumnType {
static const ColumnType char = ColumnType('char', hasLength: true); static const ColumnType char = ColumnType('char', hasLength: true);
static const ColumnType varChar = ColumnType('varchar', hasLength: true); static const ColumnType varChar = ColumnType('varchar', hasLength: true);
static const ColumnType varCharMax = ColumnType('varchar(max)'); static const ColumnType varCharMax = ColumnType('varchar(max)');
static const ColumnType text = ColumnType('text', hasLength: true); static const ColumnType text = ColumnType('text');
// Unicode strings // Unicode strings
static const ColumnType nChar = ColumnType('nchar', hasLength: true); static const ColumnType nChar = ColumnType('nchar', hasLength: true);
static const ColumnType nVarChar = ColumnType('nvarchar', hasLength: true); static const ColumnType nVarChar = ColumnType('nvarchar', hasLength: true);
static const ColumnType nVarCharMax = static const ColumnType nVarCharMax = ColumnType('nvarchar(max)');
ColumnType('nvarchar(max)', hasLength: true);
static const ColumnType nText = ColumnType('ntext', hasLength: true); static const ColumnType nText = ColumnType('ntext', hasLength: true);
// Binary // Binary
static const ColumnType binary = ColumnType('binary', hasLength: true); static const ColumnType binary = ColumnType('binary');
static const ColumnType varBinary = ColumnType('varbinary', hasLength: true); static const ColumnType varBinary = ColumnType('varbinary');
static const ColumnType varBinaryMax = static const ColumnType varBinaryMax = ColumnType('varbinary(max)');
ColumnType('varbinary(max)', hasLength: true); static const ColumnType image = ColumnType('image');
static const ColumnType image = ColumnType('image', hasLength: true);
// JSON. // JSON.
static const ColumnType json = ColumnType('json', hasLength: true); static const ColumnType json = ColumnType('json');
static const ColumnType jsonb = ColumnType('jsonb', hasLength: true); static const ColumnType jsonb = ColumnType('jsonb');
// Misc. // Misc.
static const ColumnType sqlVariant = static const ColumnType sqlVariant = ColumnType('sql_variant');
ColumnType('sql_variant', hasLength: true); static const ColumnType uniqueIdentifier = ColumnType('uniqueidentifier');
static const ColumnType uniqueIdentifier = static const ColumnType xml = ColumnType('xml');
ColumnType('uniqueidentifier', hasLength: true); static const ColumnType cursor = ColumnType('cursor');
static const ColumnType xml = ColumnType('xml', hasLength: true); static const ColumnType table = ColumnType('table');
static const ColumnType cursor = ColumnType('cursor', hasLength: true);
static const ColumnType table = ColumnType('table', hasLength: true);
} }

View file

@ -148,6 +148,9 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
case ColumnType.float: case ColumnType.float:
methodName = 'float'; methodName = 'float';
break; break;
case ColumnType.double:
methodName = 'double';
break;
case ColumnType.numeric: case ColumnType.numeric:
methodName = 'numeric'; methodName = 'numeric';
if (col.type.hasPrecision) {} if (col.type.hasPrecision) {}
@ -233,7 +236,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
cascade.add(refer('unique').call([])); cascade.add(refer('unique').call([]));
} }
if (col.isNullable != true) { if (!col.isNullable) {
cascade.add(refer('notNull').call([])); cascade.add(refer('notNull').call([]));
} }

View file

@ -105,7 +105,9 @@ Future<OrmBuildContext?> buildOrmContext(
// Check for column annotation... // Check for column annotation...
var element = _findElement(field); var element = _findElement(field);
var columnAnnotation = columnTypeChecker.firstAnnotationOf(element); var columnAnnotation = columnTypeChecker.firstAnnotationOf(element);
// print('${element.name} => $columnAnnotation'); if (columnAnnotation != null) {
print('[ORM_BUILD_CONTEXT] ${element.name} => $columnAnnotation');
}
Column? column; Column? column;
if (columnAnnotation != null) { if (columnAnnotation != null) {
@ -334,6 +336,7 @@ Future<OrmBuildContext?> buildOrmContext(
return ctx; return ctx;
} }
// Detect and return the correct column type
ColumnType inferColumnType(DartType type) { ColumnType inferColumnType(DartType type) {
if (const TypeChecker.fromRuntime(String).isAssignableFromType(type)) { if (const TypeChecker.fromRuntime(String).isAssignableFromType(type)) {
return ColumnType.varChar; return ColumnType.varChar;
@ -342,7 +345,7 @@ ColumnType inferColumnType(DartType type) {
return ColumnType.int; return ColumnType.int;
} }
if (const TypeChecker.fromRuntime(double).isAssignableFromType(type)) { if (const TypeChecker.fromRuntime(double).isAssignableFromType(type)) {
return ColumnType.float; return ColumnType.double;
} }
if (const TypeChecker.fromRuntime(num).isAssignableFromType(type)) { if (const TypeChecker.fromRuntime(num).isAssignableFromType(type)) {
return ColumnType.float; return ColumnType.float;
@ -401,6 +404,7 @@ Column reviveColumn(ConstantReader cr) {
const TypeChecker relationshipTypeChecker = const TypeChecker relationshipTypeChecker =
TypeChecker.fromRuntime(Relationship); TypeChecker.fromRuntime(Relationship);
// ORM builder context
class OrmBuildContext { class OrmBuildContext {
final BuildContext buildContext; final BuildContext buildContext;
final Orm ormAnnotation; final Orm ormAnnotation;

View file

@ -18,6 +18,9 @@ abstract class _Asset extends Model {
String get name; String get name;
@Column(type: ColumnType.numeric, precision: 17, scale: 3)
double get price;
@hasMany @hasMany
List<_Item> get items; List<_Item> get items;
} }

View file

@ -32,6 +32,7 @@ class AssetMigration extends Migration {
table.timeStamp('updated_at'); table.timeStamp('updated_at');
table.varChar('description', length: 255); table.varChar('description', length: 255);
table.varChar('name', length: 255); table.varChar('name', length: 255);
table.double('price');
}); });
} }
@ -191,7 +192,7 @@ class AssetQuery extends Query<Asset, AssetQueryWhere> {
@override @override
Map<String, String> get casts { Map<String, String> get casts {
return {}; return {'price': 'char'};
} }
@override @override
@ -201,7 +202,14 @@ class AssetQuery extends Query<Asset, AssetQueryWhere> {
@override @override
List<String> get fields { List<String> get fields {
const _fields = ['id', 'created_at', 'updated_at', 'description', 'name']; const _fields = [
'id',
'created_at',
'updated_at',
'description',
'name',
'price'
];
return _selectedFields.isEmpty return _selectedFields.isEmpty
? _fields ? _fields
: _fields.where((field) => _selectedFields.contains(field)).toList(); : _fields.where((field) => _selectedFields.contains(field)).toList();
@ -231,9 +239,10 @@ class AssetQuery extends Query<Asset, AssetQueryWhere> {
createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null, createdAt: fields.contains('created_at') ? mapToDateTime(row[1]) : null,
updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null, updatedAt: fields.contains('updated_at') ? mapToDateTime(row[2]) : null,
description: fields.contains('description') ? (row[3] as String) : '', description: fields.contains('description') ? (row[3] as String) : '',
name: fields.contains('name') ? (row[4] as String) : ''); name: fields.contains('name') ? (row[4] as String) : '',
if (row.length > 5) { price: fields.contains('price') ? mapToDouble(row[5]) : 0.0);
var modelOpt = ItemQuery().parseRow(row.skip(5).take(4).toList()); if (row.length > 6) {
var modelOpt = ItemQuery().parseRow(row.skip(6).take(4).toList());
modelOpt.ifPresent((m) { modelOpt.ifPresent((m) {
model = model.copyWith(items: [m]); model = model.copyWith(items: [m]);
}); });
@ -311,7 +320,8 @@ class AssetQueryWhere extends QueryWhere {
createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'),
updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'), updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'),
description = StringSqlExpressionBuilder(query, 'description'), description = StringSqlExpressionBuilder(query, 'description'),
name = StringSqlExpressionBuilder(query, 'name'); name = StringSqlExpressionBuilder(query, 'name'),
price = NumericSqlExpressionBuilder<double>(query, 'price');
final NumericSqlExpressionBuilder<int> id; final NumericSqlExpressionBuilder<int> id;
@ -323,16 +333,18 @@ class AssetQueryWhere extends QueryWhere {
final StringSqlExpressionBuilder name; final StringSqlExpressionBuilder name;
final NumericSqlExpressionBuilder<double> price;
@override @override
List<SqlExpressionBuilder> get expressionBuilders { List<SqlExpressionBuilder> get expressionBuilders {
return [id, createdAt, updatedAt, description, name]; return [id, createdAt, updatedAt, description, name, price];
} }
} }
class AssetQueryValues extends MapQueryValues { class AssetQueryValues extends MapQueryValues {
@override @override
Map<String, String> get casts { Map<String, String> get casts {
return {}; return {'price': 'double precision'};
} }
String? get id { String? get id {
@ -360,11 +372,17 @@ class AssetQueryValues extends MapQueryValues {
} }
set name(String value) => values['name'] = value; 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) { void copyFrom(Asset model) {
createdAt = model.createdAt; createdAt = model.createdAt;
updatedAt = model.updatedAt; updatedAt = model.updatedAt;
description = model.description; description = model.description;
name = model.name; name = model.name;
price = model.price;
} }
} }
@ -435,6 +453,7 @@ class Asset extends _Asset {
this.updatedAt, this.updatedAt,
required this.description, required this.description,
required this.name, required this.name,
required this.price,
List<_Item> items = const []}) List<_Item> items = const []})
: items = List.unmodifiable(items); : items = List.unmodifiable(items);
@ -456,6 +475,9 @@ class Asset extends _Asset {
@override @override
String name; String name;
@override
double price;
@override @override
List<_Item> items; List<_Item> items;
@ -465,6 +487,7 @@ class Asset extends _Asset {
DateTime? updatedAt, DateTime? updatedAt,
String? description, String? description,
String? name, String? name,
double? price,
List<_Item>? items}) { List<_Item>? items}) {
return Asset( return Asset(
id: id ?? this.id, id: id ?? this.id,
@ -472,6 +495,7 @@ class Asset extends _Asset {
updatedAt: updatedAt ?? this.updatedAt, updatedAt: updatedAt ?? this.updatedAt,
description: description ?? this.description, description: description ?? this.description,
name: name ?? this.name, name: name ?? this.name,
price: price ?? this.price,
items: items ?? this.items); items: items ?? this.items);
} }
@ -483,18 +507,20 @@ class Asset extends _Asset {
other.updatedAt == updatedAt && other.updatedAt == updatedAt &&
other.description == description && other.description == description &&
other.name == name && other.name == name &&
other.price == price &&
ListEquality<_Item>(DefaultEquality<_Item>()) ListEquality<_Item>(DefaultEquality<_Item>())
.equals(other.items, items); .equals(other.items, items);
} }
@override @override
int get hashCode { int get hashCode {
return hashObjects([id, createdAt, updatedAt, description, name, items]); return hashObjects(
[id, createdAt, updatedAt, description, name, price, items]);
} }
@override @override
String toString() { 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<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -613,6 +639,7 @@ class AssetSerializer extends Codec<Asset, Map> {
: null, : null,
description: map['description'] as String, description: map['description'] as String,
name: map['name'] as String, name: map['name'] as String,
price: map['price'] as double,
items: map['items'] is Iterable items: map['items'] is Iterable
? List.unmodifiable(((map['items'] as Iterable).whereType<Map>()) ? List.unmodifiable(((map['items'] as Iterable).whereType<Map>())
.map(ItemSerializer.fromMap)) .map(ItemSerializer.fromMap))
@ -629,6 +656,7 @@ class AssetSerializer extends Codec<Asset, Map> {
'updated_at': model.updatedAt?.toIso8601String(), 'updated_at': model.updatedAt?.toIso8601String(),
'description': model.description, 'description': model.description,
'name': model.name, 'name': model.name,
'price': model.price,
'items': model.items.map((m) => ItemSerializer.toMap(m)).toList() 'items': model.items.map((m) => ItemSerializer.toMap(m)).toList()
}; };
} }
@ -641,6 +669,7 @@ abstract class AssetFields {
updatedAt, updatedAt,
description, description,
name, name,
price,
items items
]; ];
@ -654,5 +683,7 @@ abstract class AssetFields {
static const String name = 'name'; static const String name = 'name';
static const String price = 'price';
static const String items = 'items'; static const String items = 'items';
} }

View file

@ -17,7 +17,7 @@ class BikeMigration extends Migration {
table.varChar('description', length: 255); table.varChar('description', length: 255);
table.boolean('family_friendly'); table.boolean('family_friendly');
table.timeStamp('recalled_at'); table.timeStamp('recalled_at');
table.float('price'); table.double('price');
table.integer('width'); table.integer('width');
}); });
} }
@ -164,7 +164,7 @@ class BikeQueryWhere extends QueryWhere {
class BikeQueryValues extends MapQueryValues { class BikeQueryValues extends MapQueryValues {
@override @override
Map<String, String> get casts { Map<String, String> get casts {
return {'price': 'float'}; return {'price': 'double precision'};
} }
String? get id { String? get id {

View file

@ -17,7 +17,7 @@ class BoatMigration extends Migration {
table.varChar('description', length: 255).defaultsTo('none'); table.varChar('description', length: 255).defaultsTo('none');
table.boolean('family_friendly').defaultsTo(false); table.boolean('family_friendly').defaultsTo(false);
table.timeStamp('recalled_at'); table.timeStamp('recalled_at');
table.float('price').defaultsTo(0.0); table.double('price').defaultsTo(0.0);
table.integer('width').defaultsTo(0); table.integer('width').defaultsTo(0);
}); });
} }
@ -164,7 +164,7 @@ class BoatQueryWhere extends QueryWhere {
class BoatQueryValues extends MapQueryValues { class BoatQueryValues extends MapQueryValues {
@override @override
Map<String, String> get casts { Map<String, String> get casts {
return {'price': 'float'}; return {'price': 'double precision'};
} }
String? get id { String? get id {

View file

@ -31,7 +31,7 @@ class FootMigration extends Migration {
table.timeStamp('created_at'); table.timeStamp('created_at');
table.timeStamp('updated_at'); table.timeStamp('updated_at');
table.integer('leg_id'); table.integer('leg_id');
table.float('n_toes'); table.double('n_toes');
}); });
} }
@ -279,7 +279,7 @@ class FootQueryWhere extends QueryWhere {
class FootQueryValues extends MapQueryValues { class FootQueryValues extends MapQueryValues {
@override @override
Map<String, String> get casts { Map<String, String> get casts {
return {'n_toes': 'float'}; return {'n_toes': 'double precision'};
} }
String? get id { String? get id {

View file

@ -244,7 +244,7 @@ class PersonWithLastOrderQueryWhere extends QueryWhere {
class PersonWithLastOrderQueryValues extends MapQueryValues { class PersonWithLastOrderQueryValues extends MapQueryValues {
@override @override
Map<String, String> get casts { Map<String, String> get casts {
return {'last_order_price': 'float'}; return {'last_order_price': 'double precision'};
} }
String? get name { String? get name {

View file

@ -15,7 +15,7 @@ class PersonOrderMigration extends Migration {
table.timeStamp('updated_at'); table.timeStamp('updated_at');
table.integer('person_id'); table.integer('person_id');
table.varChar('name', length: 255); table.varChar('name', length: 255);
table.float('price'); table.double('price');
table.boolean('deleted'); table.boolean('deleted');
}); });
} }
@ -140,7 +140,7 @@ class PersonOrderQueryWhere extends QueryWhere {
class PersonOrderQueryValues extends MapQueryValues { class PersonOrderQueryValues extends MapQueryValues {
@override @override
Map<String, String> get casts { Map<String, String> get casts {
return {'price': 'float'}; return {'price': 'double precision'};
} }
String? get id { String? get id {
@ -301,7 +301,7 @@ class OrderWithPersonInfoQueryWhere extends QueryWhere {
class OrderWithPersonInfoQueryValues extends MapQueryValues { class OrderWithPersonInfoQueryValues extends MapQueryValues {
@override @override
Map<String, String> get casts { Map<String, String> get casts {
return {'price': 'float'}; return {'price': 'double precision'};
} }
String? get id { String? get id {