Migrated angel_orm_generator
This commit is contained in:
parent
d2af68779e
commit
af36c3b339
8 changed files with 214 additions and 209 deletions
|
@ -31,8 +31,8 @@
|
||||||
* Created basic-sdk-2.12.x_nnbd template (1/1 test passed) <= Milestone 1
|
* Created basic-sdk-2.12.x_nnbd template (1/1 test passed) <= Milestone 1
|
||||||
* Migrated angel_serialize to 4.0.0 (0/0 test passed)
|
* Migrated angel_serialize to 4.0.0 (0/0 test passed)
|
||||||
* Migrated angel_serialize_generator to 4.0.0 (33/33 tests passed)
|
* Migrated angel_serialize_generator to 4.0.0 (33/33 tests passed)
|
||||||
* Updated angel_orm to 3.0.0 (0/0 tests passed)
|
* Migrated angel_orm to 3.0.0 (0/0 tests passed)
|
||||||
* Updated angel_migration to 3.0.0 (0/0 tests passed)
|
* Migrated angel_migration to 3.0.0 (0/0 tests passed)
|
||||||
* Added inflection2 and migrated to 1.0.0 (28/32 tests passed)
|
* Added inflection2 and migrated to 1.0.0 (28/32 tests passed)
|
||||||
* Updated angel_orm_generator to 3.0.0 (in progress)
|
* Updated angel_orm_generator to 3.0.0 (in progress)
|
||||||
* Updated angel_migration_runner to 3.0.0 (in progress)
|
* Updated angel_migration_runner to 3.0.0 (in progress)
|
||||||
|
|
|
@ -8,12 +8,12 @@ part 'main.g.dart';
|
||||||
|
|
||||||
main() async {
|
main() async {
|
||||||
var query = EmployeeQuery()
|
var query = EmployeeQuery()
|
||||||
..where.firstName.equals('Rich')
|
..where!.firstName.equals('Rich')
|
||||||
..where.lastName.equals('Person')
|
..where!.lastName.equals('Person')
|
||||||
..orWhere((w) => w.salary.greaterThanOrEqualTo(75000))
|
..orWhere((w) => w!.salary.greaterThanOrEqualTo(75000))
|
||||||
..join('companies', 'company_id', 'id');
|
..join('companies', 'company_id', 'id');
|
||||||
|
|
||||||
var richPerson = await query.getOne(_FakeExecutor());
|
var richPerson = await (query.getOne(_FakeExecutor()) as FutureOr<Employee>);
|
||||||
print(richPerson.toJson());
|
print(richPerson.toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ class _FakeExecutor extends QueryExecutor {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<List>> query(
|
Future<List<List>> query(
|
||||||
String tableName, String query, Map<String, dynamic> substitutionValues,
|
String tableName, String? query, Map<String, dynamic> substitutionValues,
|
||||||
[returningFields]) async {
|
[returningFields]) async {
|
||||||
var now = DateTime.now();
|
var now = DateTime.now();
|
||||||
print(
|
print(
|
||||||
|
@ -41,12 +41,12 @@ class _FakeExecutor extends QueryExecutor {
|
||||||
@orm
|
@orm
|
||||||
@serializable
|
@serializable
|
||||||
abstract class _Employee extends Model {
|
abstract class _Employee extends Model {
|
||||||
String get firstName;
|
String? get firstName;
|
||||||
|
|
||||||
String get lastName;
|
String? get lastName;
|
||||||
|
|
||||||
@Column(indexType: IndexType.unique)
|
@Column(indexType: IndexType.unique)
|
||||||
String uniqueId;
|
String? uniqueId;
|
||||||
|
|
||||||
double get salary;
|
double? get salary;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,9 @@ part of 'main.dart';
|
||||||
|
|
||||||
class EmployeeMigration extends Migration {
|
class EmployeeMigration extends Migration {
|
||||||
@override
|
@override
|
||||||
up(Schema schema) {
|
void up(Schema schema) {
|
||||||
schema.create('employees', (table) {
|
schema.create('employees', (table) {
|
||||||
table.serial('id')..primaryKey();
|
table.serial('id').primaryKey();
|
||||||
table.timeStamp('created_at');
|
table.timeStamp('created_at');
|
||||||
table.timeStamp('updated_at');
|
table.timeStamp('updated_at');
|
||||||
table.varChar('unique_id');
|
table.varChar('unique_id');
|
||||||
|
@ -21,7 +21,7 @@ class EmployeeMigration extends Migration {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
down(Schema schema) {
|
void down(Schema schema) {
|
||||||
schema.drop('employees');
|
schema.drop('employees');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,8 @@ class EmployeeMigration extends Migration {
|
||||||
// OrmGenerator
|
// OrmGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
class EmployeeQuery extends Query<Employee, EmployeeQueryWhere> {
|
class EmployeeQuery extends Query<Employee?, EmployeeQueryWhere?> {
|
||||||
EmployeeQuery({Set<String> trampoline}) {
|
EmployeeQuery({Set<String>? trampoline}) {
|
||||||
trampoline ??= Set();
|
trampoline ??= Set();
|
||||||
trampoline.add(tableName);
|
trampoline.add(tableName);
|
||||||
_where = EmployeeQueryWhere(this);
|
_where = EmployeeQueryWhere(this);
|
||||||
|
@ -40,7 +40,7 @@ class EmployeeQuery extends Query<Employee, EmployeeQueryWhere> {
|
||||||
@override
|
@override
|
||||||
final EmployeeQueryValues values = EmployeeQueryValues();
|
final EmployeeQueryValues values = EmployeeQueryValues();
|
||||||
|
|
||||||
EmployeeQueryWhere _where;
|
EmployeeQueryWhere? _where;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
get casts {
|
get casts {
|
||||||
|
@ -66,7 +66,7 @@ class EmployeeQuery extends Query<Employee, EmployeeQueryWhere> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
EmployeeQueryWhere get where {
|
EmployeeQueryWhere? get where {
|
||||||
return _where;
|
return _where;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,15 +75,15 @@ class EmployeeQuery extends Query<Employee, EmployeeQueryWhere> {
|
||||||
return EmployeeQueryWhere(this);
|
return EmployeeQueryWhere(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Employee parseRow(List row) {
|
static Employee? parseRow(List row) {
|
||||||
if (row.every((x) => x == null)) return null;
|
if (row.every((x) => x == null)) return null;
|
||||||
var model = Employee(
|
var model = Employee(
|
||||||
id: (row[0] as String),
|
id: (row[0] as String?),
|
||||||
createdAt: (row[1] as DateTime),
|
createdAt: (row[1] as DateTime?),
|
||||||
updatedAt: (row[2] as DateTime),
|
updatedAt: (row[2] as DateTime?),
|
||||||
uniqueId: (row[3] as String),
|
uniqueId: (row[3] as String?),
|
||||||
firstName: (row[4] as String),
|
firstName: (row[4] as String?),
|
||||||
lastName: (row[5] as String),
|
lastName: (row[5] as String?),
|
||||||
salary: double.tryParse(row[6].toString()));
|
salary: double.tryParse(row[6].toString()));
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
@ -130,41 +130,41 @@ class EmployeeQueryValues extends MapQueryValues {
|
||||||
return {'salary': 'decimal'};
|
return {'salary': 'decimal'};
|
||||||
}
|
}
|
||||||
|
|
||||||
String get id {
|
String? get id {
|
||||||
return (values['id'] as String);
|
return (values['id'] as String?);
|
||||||
}
|
}
|
||||||
|
|
||||||
set id(String value) => values['id'] = value;
|
set id(String? value) => values['id'] = value;
|
||||||
DateTime get createdAt {
|
DateTime? get createdAt {
|
||||||
return (values['created_at'] as DateTime);
|
return (values['created_at'] as DateTime?);
|
||||||
}
|
}
|
||||||
|
|
||||||
set createdAt(DateTime value) => values['created_at'] = value;
|
set createdAt(DateTime? value) => values['created_at'] = value;
|
||||||
DateTime get updatedAt {
|
DateTime? get updatedAt {
|
||||||
return (values['updated_at'] as DateTime);
|
return (values['updated_at'] as DateTime?);
|
||||||
}
|
}
|
||||||
|
|
||||||
set updatedAt(DateTime value) => values['updated_at'] = value;
|
set updatedAt(DateTime? value) => values['updated_at'] = value;
|
||||||
String get uniqueId {
|
String? get uniqueId {
|
||||||
return (values['unique_id'] as String);
|
return (values['unique_id'] as String?);
|
||||||
}
|
}
|
||||||
|
|
||||||
set uniqueId(String value) => values['unique_id'] = value;
|
set uniqueId(String? value) => values['unique_id'] = value;
|
||||||
String get firstName {
|
String? get firstName {
|
||||||
return (values['first_name'] as String);
|
return (values['first_name'] as String?);
|
||||||
}
|
}
|
||||||
|
|
||||||
set firstName(String value) => values['first_name'] = value;
|
set firstName(String? value) => values['first_name'] = value;
|
||||||
String get lastName {
|
String? get lastName {
|
||||||
return (values['last_name'] as String);
|
return (values['last_name'] as String?);
|
||||||
}
|
}
|
||||||
|
|
||||||
set lastName(String value) => values['last_name'] = value;
|
set lastName(String? value) => values['last_name'] = value;
|
||||||
double get salary {
|
double? get salary {
|
||||||
return double.tryParse((values['salary'] as String));
|
return double.tryParse((values['salary'] as String));
|
||||||
}
|
}
|
||||||
|
|
||||||
set salary(double value) => values['salary'] = value.toString();
|
set salary(double? value) => values['salary'] = value.toString();
|
||||||
void copyFrom(Employee model) {
|
void copyFrom(Employee model) {
|
||||||
id = model.id;
|
id = model.id;
|
||||||
createdAt = model.createdAt;
|
createdAt = model.createdAt;
|
||||||
|
@ -193,36 +193,36 @@ class Employee extends _Employee {
|
||||||
|
|
||||||
/// A unique identifier corresponding to this item.
|
/// A unique identifier corresponding to this item.
|
||||||
@override
|
@override
|
||||||
String id;
|
String? id;
|
||||||
|
|
||||||
/// The time at which this item was created.
|
/// The time at which this item was created.
|
||||||
@override
|
@override
|
||||||
DateTime createdAt;
|
DateTime? createdAt;
|
||||||
|
|
||||||
/// The last time at which this item was updated.
|
/// The last time at which this item was updated.
|
||||||
@override
|
@override
|
||||||
DateTime updatedAt;
|
DateTime? updatedAt;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String uniqueId;
|
String? uniqueId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final String firstName;
|
final String? firstName;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final String lastName;
|
final String? lastName;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final double salary;
|
final double? salary;
|
||||||
|
|
||||||
Employee copyWith(
|
Employee copyWith(
|
||||||
{String id,
|
{String? id,
|
||||||
DateTime createdAt,
|
DateTime? createdAt,
|
||||||
DateTime updatedAt,
|
DateTime? updatedAt,
|
||||||
String uniqueId,
|
String? uniqueId,
|
||||||
String firstName,
|
String? firstName,
|
||||||
String lastName,
|
String? lastName,
|
||||||
double salary}) {
|
double? salary}) {
|
||||||
return Employee(
|
return Employee(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
createdAt: createdAt ?? this.createdAt,
|
createdAt: createdAt ?? this.createdAt,
|
||||||
|
@ -284,32 +284,29 @@ class EmployeeSerializer extends Codec<Employee, Map> {
|
||||||
const EmployeeSerializer();
|
const EmployeeSerializer();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
get encoder => const EmployeeEncoder();
|
EmployeeEncoder get encoder => const EmployeeEncoder();
|
||||||
@override
|
@override
|
||||||
get decoder => const EmployeeDecoder();
|
EmployeeDecoder get decoder => const EmployeeDecoder();
|
||||||
static Employee fromMap(Map map) {
|
static Employee fromMap(Map map) {
|
||||||
return Employee(
|
return Employee(
|
||||||
id: map['id'] as String,
|
id: map['id'] as String?,
|
||||||
createdAt: map['created_at'] != null
|
createdAt: map['created_at'] != null
|
||||||
? (map['created_at'] is DateTime
|
? (map['created_at'] is DateTime
|
||||||
? (map['created_at'] as DateTime)
|
? (map['created_at'] as DateTime?)
|
||||||
: DateTime.parse(map['created_at'].toString()))
|
: DateTime.parse(map['created_at'].toString()))
|
||||||
: null,
|
: null,
|
||||||
updatedAt: map['updated_at'] != null
|
updatedAt: map['updated_at'] != null
|
||||||
? (map['updated_at'] is DateTime
|
? (map['updated_at'] is DateTime
|
||||||
? (map['updated_at'] as DateTime)
|
? (map['updated_at'] as DateTime?)
|
||||||
: DateTime.parse(map['updated_at'].toString()))
|
: DateTime.parse(map['updated_at'].toString()))
|
||||||
: null,
|
: null,
|
||||||
uniqueId: map['unique_id'] as String,
|
uniqueId: map['unique_id'] as String?,
|
||||||
firstName: map['first_name'] as String,
|
firstName: map['first_name'] as String?,
|
||||||
lastName: map['last_name'] as String,
|
lastName: map['last_name'] as String?,
|
||||||
salary: map['salary'] as double);
|
salary: map['salary'] as double?);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Map<String, dynamic> toMap(_Employee model) {
|
static Map<String, dynamic> toMap(_Employee model) {
|
||||||
if (model == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
'id': model.id,
|
'id': model.id,
|
||||||
'created_at': model.createdAt?.toIso8601String(),
|
'created_at': model.createdAt?.toIso8601String(),
|
||||||
|
|
|
@ -29,7 +29,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
const MigrationGenerator({this.autoSnakeCaseNames = true});
|
const MigrationGenerator({this.autoSnakeCaseNames = true});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> generateForAnnotatedElement(
|
Future<String?> generateForAnnotatedElement(
|
||||||
Element element, ConstantReader annotation, BuildStep buildStep) async {
|
Element element, ConstantReader annotation, BuildStep buildStep) async {
|
||||||
if (element is! ClassElement) {
|
if (element is! ClassElement) {
|
||||||
throw 'Only classes can be annotated with @ORM().';
|
throw 'Only classes can be annotated with @ORM().';
|
||||||
|
@ -43,20 +43,19 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
}
|
}
|
||||||
|
|
||||||
var resolver = await buildStep.resolver;
|
var resolver = await buildStep.resolver;
|
||||||
var ctx = await buildOrmContext({}, element as ClassElement, annotation,
|
var ctx = await buildOrmContext({}, element, annotation, buildStep,
|
||||||
buildStep, resolver, autoSnakeCaseNames != false);
|
resolver, autoSnakeCaseNames != false);
|
||||||
var lib = generateMigrationLibrary(
|
var lib = generateMigrationLibrary(ctx, element, resolver, buildStep);
|
||||||
ctx, element as ClassElement, resolver, buildStep);
|
|
||||||
if (lib == null) return null;
|
if (lib == null) return null;
|
||||||
return DartFormatter().format(lib.accept(DartEmitter()).toString());
|
return DartFormatter().format(lib.accept(DartEmitter()).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
Library generateMigrationLibrary(OrmBuildContext ctx, ClassElement element,
|
Library generateMigrationLibrary(OrmBuildContext? ctx, ClassElement element,
|
||||||
Resolver resolver, BuildStep buildStep) {
|
Resolver resolver, BuildStep buildStep) {
|
||||||
return Library((lib) {
|
return Library((lib) {
|
||||||
lib.body.add(Class((clazz) {
|
lib.body.add(Class((clazz) {
|
||||||
clazz
|
clazz
|
||||||
..name = '${ctx.buildContext.modelClassName}Migration'
|
..name = '${ctx!.buildContext.modelClassName}Migration'
|
||||||
..extend = refer('Migration')
|
..extend = refer('Migration')
|
||||||
..methods
|
..methods
|
||||||
.addAll([buildUpMigration(ctx, lib), buildDownMigration(ctx)]);
|
.addAll([buildUpMigration(ctx, lib), buildDownMigration(ctx)]);
|
||||||
|
@ -64,10 +63,10 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Method buildUpMigration(OrmBuildContext ctx, LibraryBuilder lib) {
|
Method buildUpMigration(OrmBuildContext? ctx, LibraryBuilder lib) {
|
||||||
return Method((meth) {
|
return Method((meth) {
|
||||||
var autoIdAndDateFields = const TypeChecker.fromRuntime(Model)
|
var autoIdAndDateFields = const TypeChecker.fromRuntime(Model)
|
||||||
.isAssignableFromType(ctx.buildContext.clazz.thisType);
|
.isAssignableFromType(ctx!.buildContext.clazz.thisType);
|
||||||
meth
|
meth
|
||||||
..name = 'up'
|
..name = 'up'
|
||||||
..annotations.add(refer('override'))
|
..annotations.add(refer('override'))
|
||||||
|
@ -80,7 +79,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
..body = Block((closureBody) {
|
..body = Block((closureBody) {
|
||||||
var table = refer('table');
|
var table = refer('table');
|
||||||
|
|
||||||
List<String> dup = [];
|
List<String?> dup = [];
|
||||||
ctx.columns.forEach((name, col) {
|
ctx.columns.forEach((name, col) {
|
||||||
// Skip custom-expression columns.
|
// Skip custom-expression columns.
|
||||||
if (col.hasExpression) return;
|
if (col.hasExpression) return;
|
||||||
|
@ -103,7 +102,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
(autoIdAndDateFields != false && name == 'id'))) {
|
(autoIdAndDateFields != false && name == 'id'))) {
|
||||||
// Check for relationships that might duplicate
|
// Check for relationships that might duplicate
|
||||||
for (var rName in ctx.relations.keys) {
|
for (var rName in ctx.relations.keys) {
|
||||||
var relationship = ctx.relations[rName];
|
var relationship = ctx.relations[rName]!;
|
||||||
if (relationship.localKey == key) return;
|
if (relationship.localKey == key) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,7 +110,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
dup.add(key);
|
dup.add(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
String methodName;
|
String? methodName;
|
||||||
List<Expression> positional = [literal(key)];
|
List<Expression> positional = [literal(key)];
|
||||||
Map<String, Expression> named = {};
|
Map<String, Expression> named = {};
|
||||||
|
|
||||||
|
@ -159,13 +158,13 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
if (col.length == null) {
|
if (col.length == null) {
|
||||||
methodName = 'declare';
|
methodName = 'declare';
|
||||||
provColumn = columnTypeType.newInstance([
|
provColumn = columnTypeType.newInstance([
|
||||||
literal(col.type.name),
|
literal(col.type!.name),
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
methodName = 'declareColumn';
|
methodName = 'declareColumn';
|
||||||
provColumn = colType.newInstance([], {
|
provColumn = colType.newInstance([], {
|
||||||
'type': columnTypeType.newInstance([
|
'type': columnTypeType.newInstance([
|
||||||
literal(col.type.name),
|
literal(col.type!.name),
|
||||||
]),
|
]),
|
||||||
'length': literal(col.length),
|
'length': literal(col.length),
|
||||||
});
|
});
|
||||||
|
@ -183,10 +182,10 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
|
|
||||||
if (defaultValue != null && !defaultValue.isNull) {
|
if (defaultValue != null && !defaultValue.isNull) {
|
||||||
var type = defaultValue.type;
|
var type = defaultValue.type;
|
||||||
Expression defaultExpr;
|
Expression? defaultExpr;
|
||||||
|
|
||||||
if (const TypeChecker.fromRuntime(RawSql)
|
if (const TypeChecker.fromRuntime(RawSql)
|
||||||
.isAssignableFromType(defaultValue.type)) {
|
.isAssignableFromType(defaultValue.type!)) {
|
||||||
var value =
|
var value =
|
||||||
ConstantReader(defaultValue).read('value').stringValue;
|
ConstantReader(defaultValue).read('value').stringValue;
|
||||||
defaultExpr =
|
defaultExpr =
|
||||||
|
@ -195,7 +194,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
// Default to enum index.
|
// Default to enum index.
|
||||||
try {
|
try {
|
||||||
var index =
|
var index =
|
||||||
ConstantReader(defaultValue).read('index')?.intValue;
|
ConstantReader(defaultValue).read('index').intValue;
|
||||||
if (index != null) defaultExpr = literalNum(index);
|
if (index != null) defaultExpr = literalNum(index);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
// Extremely weird error occurs here: `Not an instance of int`.
|
// Extremely weird error occurs here: `Not an instance of int`.
|
||||||
|
@ -203,7 +202,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
defaultExpr = CodeExpression(
|
defaultExpr = CodeExpression(
|
||||||
Code(dartObjectToString(defaultValue)),
|
Code(dartObjectToString(defaultValue)!),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +249,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
var columnTypeType = refer('ColumnType');
|
var columnTypeType = refer('ColumnType');
|
||||||
var key = relationship.localKey;
|
var key = relationship.localKey;
|
||||||
var keyType = relationship
|
var keyType = relationship
|
||||||
.foreign.columns[relationship.foreignKey].type.name;
|
.foreign!.columns[relationship.foreignKey!]!.type!.name;
|
||||||
|
|
||||||
var field = table.property('declare').call([
|
var field = table.property('declare').call([
|
||||||
literal(key),
|
literal(key),
|
||||||
|
@ -284,7 +283,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Method buildDownMigration(OrmBuildContext ctx) {
|
Method buildDownMigration(OrmBuildContext? ctx) {
|
||||||
return Method((b) {
|
return Method((b) {
|
||||||
b
|
b
|
||||||
..name = 'down'
|
..name = 'down'
|
||||||
|
@ -293,7 +292,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
..body = Block((b) {
|
..body = Block((b) {
|
||||||
var named = <String, Expression>{};
|
var named = <String, Expression>{};
|
||||||
|
|
||||||
if (ctx.relations.values.any((r) =>
|
if (ctx!.relations.values.any((r) =>
|
||||||
r.type == RelationshipType.hasOne ||
|
r.type == RelationshipType.hasOne ||
|
||||||
r.type == RelationshipType.hasMany ||
|
r.type == RelationshipType.hasMany ||
|
||||||
r.isManyToMany)) {
|
r.isManyToMany)) {
|
||||||
|
@ -302,7 +301,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
|
|
||||||
b.addExpression(_schema
|
b.addExpression(_schema
|
||||||
.property('drop')
|
.property('drop')
|
||||||
.call([literalString(ctx.tableName)], named));
|
.call([literalString(ctx.tableName!)], named));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import 'package:angel_serialize_generator/angel_serialize_generator.dart';
|
||||||
import 'package:angel_serialize_generator/build_context.dart';
|
import 'package:angel_serialize_generator/build_context.dart';
|
||||||
import 'package:angel_serialize_generator/context.dart';
|
import 'package:angel_serialize_generator/context.dart';
|
||||||
import 'package:build/build.dart';
|
import 'package:build/build.dart';
|
||||||
|
import 'package:collection/collection.dart' show IterableExtension;
|
||||||
import 'package:inflection2/inflection2.dart';
|
import 'package:inflection2/inflection2.dart';
|
||||||
import 'package:recase/recase.dart';
|
import 'package:recase/recase.dart';
|
||||||
import 'package:source_gen/source_gen.dart';
|
import 'package:source_gen/source_gen.dart';
|
||||||
|
@ -19,21 +20,21 @@ import 'readers.dart';
|
||||||
bool isHasRelation(Relationship r) =>
|
bool isHasRelation(Relationship r) =>
|
||||||
r.type == RelationshipType.hasOne || r.type == RelationshipType.hasMany;
|
r.type == RelationshipType.hasOne || r.type == RelationshipType.hasMany;
|
||||||
|
|
||||||
bool isSpecialId(OrmBuildContext ctx, FieldElement field) {
|
bool isSpecialId(OrmBuildContext? ctx, FieldElement field) {
|
||||||
return
|
return
|
||||||
// field is ShimFieldImpl &&
|
// field is ShimFieldImpl &&
|
||||||
field is! RelationFieldImpl &&
|
field is! RelationFieldImpl &&
|
||||||
(field.name == 'id' &&
|
(field.name == 'id' &&
|
||||||
const TypeChecker.fromRuntime(Model)
|
const TypeChecker.fromRuntime(Model)
|
||||||
.isAssignableFromType(ctx.buildContext.clazz.thisType));
|
.isAssignableFromType(ctx!.buildContext.clazz.thisType));
|
||||||
}
|
}
|
||||||
|
|
||||||
Element _findElement(FieldElement field) {
|
Element _findElement(FieldElement field) {
|
||||||
return (field.setter == null ? field.getter : field) ?? field;
|
return (field.setter == null ? field.getter : field) ?? field;
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldElement findPrimaryFieldInList(
|
FieldElement? findPrimaryFieldInList(
|
||||||
OrmBuildContext ctx, Iterable<FieldElement> fields) {
|
OrmBuildContext? ctx, Iterable<FieldElement> fields) {
|
||||||
for (var field_ in fields) {
|
for (var field_ in fields) {
|
||||||
var field = field_ is RelationFieldImpl ? field_.originalField : field_;
|
var field = field_ is RelationFieldImpl ? field_.originalField : field_;
|
||||||
var element = _findElement(field);
|
var element = _findElement(field);
|
||||||
|
@ -51,39 +52,38 @@ FieldElement findPrimaryFieldInList(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var specialId =
|
var specialId = fields.firstWhereOrNull((f) => isSpecialId(ctx, f));
|
||||||
fields.firstWhere((f) => isSpecialId(ctx, f), orElse: () => null);
|
|
||||||
// print(
|
// print(
|
||||||
// 'Special ID on ${ctx.buildContext.originalClassName} => ${specialId?.name}');
|
// 'Special ID on ${ctx.buildContext.originalClassName} => ${specialId?.name}');
|
||||||
return specialId;
|
return specialId;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<OrmBuildContext> buildOrmContext(
|
Future<OrmBuildContext?> buildOrmContext(
|
||||||
Map<String, OrmBuildContext> cache,
|
Map<String, OrmBuildContext> cache,
|
||||||
ClassElement clazz,
|
ClassElement clazz,
|
||||||
ConstantReader annotation,
|
ConstantReader annotation,
|
||||||
BuildStep buildStep,
|
BuildStep buildStep,
|
||||||
Resolver resolver,
|
Resolver resolver,
|
||||||
bool autoSnakeCaseNames,
|
bool? autoSnakeCaseNames,
|
||||||
{bool heedExclude = true}) async {
|
{bool heedExclude = true}) async {
|
||||||
// Check for @generatedSerializable
|
// Check for @generatedSerializable
|
||||||
// ignore: unused_local_variable
|
// ignore: unused_local_variable
|
||||||
DartObject generatedSerializable;
|
DartObject? generatedSerializable;
|
||||||
|
|
||||||
while ((generatedSerializable =
|
while ((generatedSerializable =
|
||||||
const TypeChecker.fromRuntime(GeneratedSerializable)
|
const TypeChecker.fromRuntime(GeneratedSerializable)
|
||||||
.firstAnnotationOf(clazz)) !=
|
.firstAnnotationOf(clazz)) !=
|
||||||
null) {
|
null) {
|
||||||
clazz = clazz.supertype.element;
|
clazz = clazz.supertype!.element;
|
||||||
}
|
}
|
||||||
|
|
||||||
var id = clazz.location.components.join('-');
|
var id = clazz.location!.components.join('-');
|
||||||
if (cache.containsKey(id)) {
|
if (cache.containsKey(id)) {
|
||||||
return cache[id];
|
return cache[id];
|
||||||
}
|
}
|
||||||
var buildCtx = await buildContext(
|
var buildCtx = await (buildContext(
|
||||||
clazz, annotation, buildStep, resolver, autoSnakeCaseNames,
|
clazz, annotation, buildStep, resolver, autoSnakeCaseNames!,
|
||||||
heedExclude: heedExclude);
|
heedExclude: heedExclude) as FutureOr<BuildContext>);
|
||||||
var ormAnnotation = reviveORMAnnotation(annotation);
|
var ormAnnotation = reviveORMAnnotation(annotation);
|
||||||
// print(
|
// print(
|
||||||
// 'tableName (${annotation.objectValue.type.name}) => ${ormAnnotation.tableName} from ${clazz.name} (${annotation.revive().namedArguments})');
|
// 'tableName (${annotation.objectValue.type.name}) => ${ormAnnotation.tableName} from ${clazz.name} (${annotation.revive().namedArguments})');
|
||||||
|
@ -98,7 +98,7 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
// Read all fields
|
// Read all fields
|
||||||
for (var field in buildCtx.fields) {
|
for (var field in buildCtx.fields) {
|
||||||
// Check for column annotation...
|
// Check for column annotation...
|
||||||
Column column;
|
Column? column;
|
||||||
var element = _findElement(field);
|
var element = _findElement(field);
|
||||||
var columnAnnotation = columnTypeChecker.firstAnnotationOf(element);
|
var columnAnnotation = columnTypeChecker.firstAnnotationOf(element);
|
||||||
// print('${element.name} => $columnAnnotation');
|
// print('${element.name} => $columnAnnotation');
|
||||||
|
@ -134,7 +134,7 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
|
|
||||||
// Try to find a relationship
|
// Try to find a relationship
|
||||||
var el = _findElement(field);
|
var el = _findElement(field);
|
||||||
el ??= field;
|
//el ??= field;
|
||||||
var ann = relationshipTypeChecker.firstAnnotationOf(el);
|
var ann = relationshipTypeChecker.firstAnnotationOf(el);
|
||||||
|
|
||||||
if (ann != null) {
|
if (ann != null) {
|
||||||
|
@ -146,7 +146,7 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
var foreignTable = cr.peek('foreignTable')?.stringValue;
|
var foreignTable = cr.peek('foreignTable')?.stringValue;
|
||||||
var cascadeOnDelete = cr.peek('cascadeOnDelete')?.boolValue == true;
|
var cascadeOnDelete = cr.peek('cascadeOnDelete')?.boolValue == true;
|
||||||
var through = cr.peek('through')?.typeValue;
|
var through = cr.peek('through')?.typeValue;
|
||||||
OrmBuildContext foreign, throughContext;
|
OrmBuildContext? foreign, throughContext;
|
||||||
|
|
||||||
if (foreignTable == null) {
|
if (foreignTable == null) {
|
||||||
// if (!isModelClass(field.type) &&
|
// if (!isModelClass(field.type) &&
|
||||||
|
@ -166,7 +166,7 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
const TypeChecker.fromRuntime(List)
|
const TypeChecker.fromRuntime(List)
|
||||||
.isAssignableFromType(refType) &&
|
.isAssignableFromType(refType) &&
|
||||||
refType.typeArguments.length == 1) {
|
refType.typeArguments.length == 1) {
|
||||||
refType = (refType as InterfaceType).typeArguments[0];
|
refType = refType.typeArguments[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
var modelType = firstModelAncestor(refType) ?? refType;
|
var modelType = firstModelAncestor(refType) ?? refType;
|
||||||
|
@ -175,7 +175,7 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
cache,
|
cache,
|
||||||
modelType.element as ClassElement,
|
modelType.element as ClassElement,
|
||||||
ConstantReader(const TypeChecker.fromRuntime(Orm)
|
ConstantReader(const TypeChecker.fromRuntime(Orm)
|
||||||
.firstAnnotationOf(modelType.element)),
|
.firstAnnotationOf(modelType.element!)),
|
||||||
buildStep,
|
buildStep,
|
||||||
resolver,
|
resolver,
|
||||||
autoSnakeCaseNames);
|
autoSnakeCaseNames);
|
||||||
|
@ -186,14 +186,14 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
cache,
|
cache,
|
||||||
through.element,
|
through.element,
|
||||||
ConstantReader(const TypeChecker.fromRuntime(Serializable)
|
ConstantReader(const TypeChecker.fromRuntime(Serializable)
|
||||||
.firstAnnotationOf(modelType.element)),
|
.firstAnnotationOf(modelType.element!)),
|
||||||
buildStep,
|
buildStep,
|
||||||
resolver,
|
resolver,
|
||||||
autoSnakeCaseNames);
|
autoSnakeCaseNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
var ormAnn = const TypeChecker.fromRuntime(Orm)
|
var ormAnn = const TypeChecker.fromRuntime(Orm)
|
||||||
.firstAnnotationOf(modelType.element);
|
.firstAnnotationOf(modelType.element!);
|
||||||
|
|
||||||
if (ormAnn != null) {
|
if (ormAnn != null) {
|
||||||
foreignTable =
|
foreignTable =
|
||||||
|
@ -201,7 +201,7 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
}
|
}
|
||||||
|
|
||||||
foreignTable ??=
|
foreignTable ??=
|
||||||
pluralize(foreign.buildContext.modelClassNameRecase.snakeCase);
|
pluralize(foreign!.buildContext.modelClassNameRecase.snakeCase);
|
||||||
} on StackOverflowError {
|
} on StackOverflowError {
|
||||||
throw UnsupportedError(
|
throw UnsupportedError(
|
||||||
'There is an infinite cycle between ${clazz.name} and ${field.type.name}. This triggered a stack overflow.');
|
'There is an infinite cycle between ${clazz.name} and ${field.type.name}. This triggered a stack overflow.');
|
||||||
|
@ -233,7 +233,7 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
foreignKey ??= '${rc.snakeCase}_$localKey';
|
foreignKey ??= '${rc.snakeCase}_$localKey';
|
||||||
} else if (type == RelationshipType.belongsTo) {
|
} else if (type == RelationshipType.belongsTo) {
|
||||||
foreignKey ??=
|
foreignKey ??=
|
||||||
ctx.buildContext.resolveFieldName(keyName(foreign, 'foreign key'));
|
ctx.buildContext.resolveFieldName(keyName(foreign!, 'foreign key'));
|
||||||
localKey ??= '${rcc.snakeCase}_$foreignKey';
|
localKey ??= '${rcc.snakeCase}_$foreignKey';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,7 +271,7 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
// 'foreignKey=$foreignKey, localKey=$localKey');
|
// 'foreignKey=$foreignKey, localKey=$localKey');
|
||||||
|
|
||||||
if (relation.type == RelationshipType.belongsTo) {
|
if (relation.type == RelationshipType.belongsTo) {
|
||||||
var name = ReCase(relation.localKey).camelCase;
|
var name = ReCase(relation.localKey!).camelCase;
|
||||||
ctx.buildContext.aliases[name] = relation.localKey;
|
ctx.buildContext.aliases[name] = relation.localKey;
|
||||||
|
|
||||||
if (!ctx.effectiveFields.any((f) => f.name == field.name)) {
|
if (!ctx.effectiveFields.any((f) => f.name == field.name)) {
|
||||||
|
@ -290,7 +290,7 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
|
|
||||||
ctx.relations[field.name] = relation;
|
ctx.relations[field.name] = relation;
|
||||||
} else {
|
} else {
|
||||||
if (column?.type == null) {
|
if (column.type == null) {
|
||||||
throw 'Cannot infer SQL column type for field "${ctx.buildContext.originalClassName}.${field.name}" with type "${field.type.displayName}".';
|
throw 'Cannot infer SQL column type for field "${ctx.buildContext.originalClassName}.${field.name}" with type "${field.type.displayName}".';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +315,7 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -345,18 +345,18 @@ ColumnType inferColumnType(DartType type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Column reviveColumn(ConstantReader cr) {
|
Column reviveColumn(ConstantReader cr) {
|
||||||
ColumnType columnType;
|
ColumnType? columnType;
|
||||||
|
|
||||||
var indexTypeObj = cr.peek('indexType')?.objectValue;
|
var indexTypeObj = cr.peek('indexType')?.objectValue;
|
||||||
indexTypeObj ??= cr.revive().namedArguments['indexType'];
|
indexTypeObj ??= cr.revive().namedArguments['indexType'];
|
||||||
|
|
||||||
var columnObj =
|
var columnObj =
|
||||||
cr.peek('type')?.objectValue?.getField('name')?.toStringValue();
|
cr.peek('type')?.objectValue.getField('name')?.toStringValue();
|
||||||
var indexType = IndexType.values[
|
var indexType = IndexType.values[
|
||||||
indexTypeObj?.getField('index')?.toIntValue() ?? IndexType.none.index];
|
indexTypeObj?.getField('index')?.toIntValue() ?? IndexType.none.index];
|
||||||
|
|
||||||
if (const TypeChecker.fromRuntime(PrimaryKey)
|
if (const TypeChecker.fromRuntime(PrimaryKey)
|
||||||
.isAssignableFromType(cr.objectValue.type)) {
|
.isAssignableFromType(cr.objectValue.type!)) {
|
||||||
indexType = IndexType.primaryKey;
|
indexType = IndexType.primaryKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,7 +365,7 @@ Column reviveColumn(ConstantReader cr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
isNullable: cr.peek('isNullable')?.boolValue,
|
isNullable: cr.peek('isNullable')?.boolValue ?? false,
|
||||||
length: cr.peek('length')?.intValue,
|
length: cr.peek('length')?.intValue,
|
||||||
type: columnType,
|
type: columnType,
|
||||||
indexType: indexType,
|
indexType: indexType,
|
||||||
|
@ -378,7 +378,7 @@ const TypeChecker relationshipTypeChecker =
|
||||||
class OrmBuildContext {
|
class OrmBuildContext {
|
||||||
final BuildContext buildContext;
|
final BuildContext buildContext;
|
||||||
final Orm ormAnnotation;
|
final Orm ormAnnotation;
|
||||||
final String tableName;
|
final String? tableName;
|
||||||
|
|
||||||
final Map<String, Column> columns = {};
|
final Map<String, Column> columns = {};
|
||||||
final List<FieldElement> effectiveFields = [];
|
final List<FieldElement> effectiveFields = [];
|
||||||
|
@ -411,13 +411,13 @@ class RelationFieldImpl extends ShimFieldImpl {
|
||||||
|
|
||||||
String get originalFieldName => originalField.name;
|
String get originalFieldName => originalField.name;
|
||||||
|
|
||||||
PropertyAccessorElement get getter => originalField.getter;
|
PropertyAccessorElement? get getter => originalField.getter;
|
||||||
}
|
}
|
||||||
|
|
||||||
InterfaceType firstModelAncestor(DartType type) {
|
InterfaceType? firstModelAncestor(DartType? type) {
|
||||||
if (type is InterfaceType) {
|
if (type is InterfaceType) {
|
||||||
if (type.superclass != null &&
|
if (type.superclass != null &&
|
||||||
const TypeChecker.fromRuntime(Model).isExactlyType(type.superclass)) {
|
const TypeChecker.fromRuntime(Model).isExactlyType(type.superclass!)) {
|
||||||
return type;
|
return type;
|
||||||
} else {
|
} else {
|
||||||
return type.superclass == null
|
return type.superclass == null
|
||||||
|
|
|
@ -31,7 +31,7 @@ TypeReference futureOf(String type) {
|
||||||
|
|
||||||
/// Builder that generates `.orm.g.dart`, with an abstract `FooOrm` class.
|
/// Builder that generates `.orm.g.dart`, with an abstract `FooOrm` class.
|
||||||
class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
final bool autoSnakeCaseNames;
|
final bool? autoSnakeCaseNames;
|
||||||
|
|
||||||
OrmGenerator({this.autoSnakeCaseNames});
|
OrmGenerator({this.autoSnakeCaseNames});
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Library buildOrmLibrary(AssetId inputId, OrmBuildContext ctx) {
|
Library buildOrmLibrary(AssetId inputId, OrmBuildContext? ctx) {
|
||||||
return Library((lib) {
|
return Library((lib) {
|
||||||
// Create `FooQuery` class
|
// Create `FooQuery` class
|
||||||
// Create `FooQueryWhere` class
|
// Create `FooQueryWhere` class
|
||||||
|
@ -58,9 +58,9 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Class buildQueryClass(OrmBuildContext ctx) {
|
Class buildQueryClass(OrmBuildContext? ctx) {
|
||||||
return Class((clazz) {
|
return Class((clazz) {
|
||||||
var rc = ctx.buildContext.modelClassNameRecase;
|
var rc = ctx!.buildContext.modelClassNameRecase;
|
||||||
var queryWhereType = refer('${rc.pascalCase}QueryWhere');
|
var queryWhereType = refer('${rc.pascalCase}QueryWhere');
|
||||||
clazz
|
clazz
|
||||||
..name = '${rc.pascalCase}Query'
|
..name = '${rc.pascalCase}Query'
|
||||||
|
@ -80,7 +80,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
..annotations.add(refer('override'))
|
..annotations.add(refer('override'))
|
||||||
..type = MethodType.getter
|
..type = MethodType.getter
|
||||||
..body = Block((b) {
|
..body = Block((b) {
|
||||||
var args = <String, Expression>{};
|
var args = <String?, Expression>{};
|
||||||
|
|
||||||
for (var field in ctx.effectiveFields) {
|
for (var field in ctx.effectiveFields) {
|
||||||
var name = ctx.buildContext.resolveFieldName(field.name);
|
var name = ctx.buildContext.resolveFieldName(field.name);
|
||||||
|
@ -113,7 +113,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
..annotations.add(refer('override'))
|
..annotations.add(refer('override'))
|
||||||
..type = MethodType.getter
|
..type = MethodType.getter
|
||||||
..body = Block((b) {
|
..body = Block((b) {
|
||||||
b.addExpression(literalString(ctx.tableName).returned);
|
b.addExpression(literalString(ctx.tableName!).returned);
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
..body = Block((b) {
|
..body = Block((b) {
|
||||||
var names = ctx.effectiveFields
|
var names = ctx.effectiveFields
|
||||||
.map((f) =>
|
.map((f) =>
|
||||||
literalString(ctx.buildContext.resolveFieldName(f.name)))
|
literalString(ctx.buildContext.resolveFieldName(f.name)!))
|
||||||
.toList();
|
.toList();
|
||||||
b.addExpression(literalConstList(names).returned);
|
b.addExpression(literalConstList(names).returned);
|
||||||
});
|
});
|
||||||
|
@ -168,7 +168,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
..name = 'row'
|
..name = 'row'
|
||||||
..type = refer('List')))
|
..type = refer('List')))
|
||||||
..body = Block((b) {
|
..body = Block((b) {
|
||||||
int i = 0;
|
var i = 0;
|
||||||
var args = <String, Expression>{};
|
var args = <String, Expression>{};
|
||||||
|
|
||||||
for (var field in ctx.effectiveFields) {
|
for (var field in ctx.effectiveFields) {
|
||||||
|
@ -211,12 +211,12 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
RelationshipType.belongsTo,
|
RelationshipType.belongsTo,
|
||||||
RelationshipType.hasMany
|
RelationshipType.hasMany
|
||||||
].contains(relation.type)) return;
|
].contains(relation.type)) return;
|
||||||
var foreign = relation.foreign;
|
var foreign = relation.foreign!;
|
||||||
var skipToList = refer('row')
|
var skipToList = refer('row')
|
||||||
.property('skip')
|
.property('skip')
|
||||||
.call([literalNum(i)])
|
.call([literalNum(i)])
|
||||||
.property('take')
|
.property('take')
|
||||||
.call([literalNum(relation.foreign.effectiveFields.length)])
|
.call([literalNum(relation.foreign!.effectiveFields.length)])
|
||||||
.property('toList')
|
.property('toList')
|
||||||
.call([]);
|
.call([]);
|
||||||
var parsed = refer(
|
var parsed = refer(
|
||||||
|
@ -236,7 +236,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
var blockStr = block.accept(DartEmitter());
|
var blockStr = block.accept(DartEmitter());
|
||||||
var ifStr = 'if (row.length > $i) { $blockStr }';
|
var ifStr = 'if (row.length > $i) { $blockStr }';
|
||||||
b.statements.add(Code(ifStr));
|
b.statements.add(Code(ifStr));
|
||||||
i += relation.foreign.effectiveFields.length;
|
i += relation.foreign!.effectiveFields.length;
|
||||||
});
|
});
|
||||||
|
|
||||||
b.addExpression(refer('model').returned);
|
b.addExpression(refer('model').returned);
|
||||||
|
@ -277,10 +277,10 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
|
|
||||||
// Add any manual SQL expressions.
|
// Add any manual SQL expressions.
|
||||||
ctx.columns.forEach((name, col) {
|
ctx.columns.forEach((name, col) {
|
||||||
if (col != null && col.hasExpression) {
|
if (col.hasExpression) {
|
||||||
var lhs = refer('expressions').index(
|
var lhs = refer('expressions').index(
|
||||||
literalString(ctx.buildContext.resolveFieldName(name)));
|
literalString(ctx.buildContext.resolveFieldName(name)!));
|
||||||
var rhs = literalString(col.expression);
|
var rhs = literalString(col.expression!);
|
||||||
b.addExpression(lhs.assign(rhs));
|
b.addExpression(lhs.assign(rhs));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -301,13 +301,15 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
|
|
||||||
// If this is a many-to-many, add the fields from the other object.
|
// If this is a many-to-many, add the fields from the other object.
|
||||||
|
|
||||||
var additionalStrs = relation.foreign.effectiveFields.map((f) =>
|
var additionalStrs = relation.foreign!.effectiveFields.map(
|
||||||
relation.foreign.buildContext.resolveFieldName(f.name));
|
(f) => relation.foreign!.buildContext
|
||||||
var additionalFields = additionalStrs.map(literalString);
|
.resolveFieldName(f.name));
|
||||||
|
var additionalFields = additionalStrs
|
||||||
|
.map(literalString as Expression Function(String?));
|
||||||
|
|
||||||
var joinArgs = [relation.localKey, relation.foreignKey]
|
var joinArgs = [relation.localKey, relation.foreignKey]
|
||||||
.map(literalString)
|
.map(literalString as Function(String?))
|
||||||
.toList();
|
.toList() as List<Expression>;
|
||||||
|
|
||||||
// In the case of a many-to-many, we don't generate a subquery field,
|
// In the case of a many-to-many, we don't generate a subquery field,
|
||||||
// as it easily leads to stack overflows.
|
// as it easily leads to stack overflows.
|
||||||
|
@ -318,10 +320,10 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
// FROM users
|
// FROM users
|
||||||
// LEFT JOIN role_users ON role_users.user_id=users.id)
|
// LEFT JOIN role_users ON role_users.user_id=users.id)
|
||||||
var foreignFields = additionalStrs
|
var foreignFields = additionalStrs
|
||||||
.map((f) => '${relation.foreign.tableName}.$f');
|
.map((f) => '${relation.foreign!.tableName}.$f');
|
||||||
var b = StringBuffer('(SELECT ');
|
var b = StringBuffer('(SELECT ');
|
||||||
// role_users.role_id
|
// role_users.role_id
|
||||||
b.write('${relation.throughContext.tableName}');
|
b.write('${relation.throughContext!.tableName}');
|
||||||
b.write('.${relation.foreignKey}');
|
b.write('.${relation.foreignKey}');
|
||||||
// , <user_fields>
|
// , <user_fields>
|
||||||
b.write(foreignFields.isEmpty
|
b.write(foreignFields.isEmpty
|
||||||
|
@ -329,39 +331,39 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
: ', ' + foreignFields.join(', '));
|
: ', ' + foreignFields.join(', '));
|
||||||
// FROM users
|
// FROM users
|
||||||
b.write(' FROM ');
|
b.write(' FROM ');
|
||||||
b.write(relation.foreign.tableName);
|
b.write(relation.foreign!.tableName);
|
||||||
// LEFT JOIN role_users
|
// LEFT JOIN role_users
|
||||||
b.write(' LEFT JOIN ${relation.throughContext.tableName}');
|
b.write(' LEFT JOIN ${relation.throughContext!.tableName}');
|
||||||
// Figure out which field on the "through" table points to users (foreign).
|
// Figure out which field on the "through" table points to users (foreign).
|
||||||
var throughRelation =
|
var throughRelation =
|
||||||
relation.throughContext.relations.values.firstWhere((e) {
|
relation.throughContext!.relations.values.firstWhere((e) {
|
||||||
return e.foreignTable == relation.foreign.tableName;
|
return e.foreignTable == relation.foreign!.tableName;
|
||||||
}, orElse: () {
|
}, orElse: () {
|
||||||
// _Role has a many-to-many to _User through _RoleUser, but
|
// _Role has a many-to-many to _User through _RoleUser, but
|
||||||
// _RoleUser has no relation pointing to _User.
|
// _RoleUser has no relation pointing to _User.
|
||||||
var b = StringBuffer();
|
var b = StringBuffer();
|
||||||
b.write(ctx.buildContext.modelClassName);
|
b.write(ctx.buildContext.modelClassName);
|
||||||
b.write('has a many-to-many relationship to ');
|
b.write('has a many-to-many relationship to ');
|
||||||
b.write(relation.foreign.buildContext.modelClassName);
|
b.write(relation.foreign!.buildContext.modelClassName);
|
||||||
b.write(' through ');
|
b.write(' through ');
|
||||||
b.write(
|
b.write(
|
||||||
relation.throughContext.buildContext.modelClassName);
|
relation.throughContext!.buildContext.modelClassName);
|
||||||
b.write(', but ');
|
b.write(', but ');
|
||||||
b.write(
|
b.write(
|
||||||
relation.throughContext.buildContext.modelClassName);
|
relation.throughContext!.buildContext.modelClassName);
|
||||||
b.write('has no relation pointing to ');
|
b.write('has no relation pointing to ');
|
||||||
b.write(relation.foreign.buildContext.modelClassName);
|
b.write(relation.foreign!.buildContext.modelClassName);
|
||||||
b.write('.');
|
b.write('.');
|
||||||
throw b.toString();
|
throw b.toString();
|
||||||
});
|
});
|
||||||
|
|
||||||
// ON role_users.user_id=users.id)
|
// ON role_users.user_id=users.id)
|
||||||
b.write(' ON ');
|
b.write(' ON ');
|
||||||
b.write('${relation.throughContext.tableName}');
|
b.write('${relation.throughContext!.tableName}');
|
||||||
b.write('.');
|
b.write('.');
|
||||||
b.write(throughRelation.localKey);
|
b.write(throughRelation.localKey);
|
||||||
b.write('=');
|
b.write('=');
|
||||||
b.write(relation.foreign.tableName);
|
b.write(relation.foreign!.tableName);
|
||||||
b.write('.');
|
b.write('.');
|
||||||
b.write(throughRelation.foreignKey);
|
b.write(throughRelation.foreignKey);
|
||||||
b.write(')');
|
b.write(')');
|
||||||
|
@ -377,7 +379,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
// There'll be a private `_field`, and then a getter, named `field`,
|
// There'll be a private `_field`, and then a getter, named `field`,
|
||||||
// that returns the subquery object.
|
// that returns the subquery object.
|
||||||
var foreignQueryType = refer(
|
var foreignQueryType = refer(
|
||||||
foreign.buildContext.modelClassNameRecase.pascalCase +
|
foreign!.buildContext.modelClassNameRecase.pascalCase +
|
||||||
'Query');
|
'Query');
|
||||||
clazz
|
clazz
|
||||||
..fields.add(Field((b) => b
|
..fields.add(Field((b) => b
|
||||||
|
@ -415,7 +417,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
|
|
||||||
if (manyToMany.isNotEmpty) {
|
if (manyToMany.isNotEmpty) {
|
||||||
var outExprs = manyToMany.map<Expression>((e) {
|
var outExprs = manyToMany.map<Expression>((e) {
|
||||||
var foreignTableName = e.value.throughContext.tableName;
|
var foreignTableName = e.value.throughContext!.tableName;
|
||||||
return CodeExpression(Code('''
|
return CodeExpression(Code('''
|
||||||
(!(
|
(!(
|
||||||
trampoline.contains('${ctx.tableName}')
|
trampoline.contains('${ctx.tableName}')
|
||||||
|
@ -495,9 +497,9 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Class buildWhereClass(OrmBuildContext ctx) {
|
Class buildWhereClass(OrmBuildContext? ctx) {
|
||||||
return Class((clazz) {
|
return Class((clazz) {
|
||||||
var rc = ctx.buildContext.modelClassNameRecase;
|
var rc = ctx!.buildContext.modelClassNameRecase;
|
||||||
clazz
|
clazz
|
||||||
..name = '${rc.pascalCase}QueryWhere'
|
..name = '${rc.pascalCase}QueryWhere'
|
||||||
..extend = refer('QueryWhere');
|
..extend = refer('QueryWhere');
|
||||||
|
@ -519,7 +521,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
|
|
||||||
// Add builders for each field
|
// Add builders for each field
|
||||||
for (var field in ctx.effectiveNormalFields) {
|
for (var field in ctx.effectiveNormalFields) {
|
||||||
var name = field.name;
|
String? name = field.name;
|
||||||
var args = <Expression>[];
|
var args = <Expression>[];
|
||||||
DartType type;
|
DartType type;
|
||||||
Reference builderType;
|
Reference builderType;
|
||||||
|
@ -535,7 +537,9 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
isSpecialId(ctx, field)) {
|
isSpecialId(ctx, field)) {
|
||||||
builderType = TypeReference((b) => b
|
builderType = TypeReference((b) => b
|
||||||
..symbol = 'NumericSqlExpressionBuilder'
|
..symbol = 'NumericSqlExpressionBuilder'
|
||||||
..types.add(refer(isSpecialId(ctx, field) ? 'int' : type.name)));
|
..types.add(refer(isSpecialId(ctx, field)
|
||||||
|
? 'int'
|
||||||
|
: type.getDisplayString(withNullability: true))));
|
||||||
} else if (type is InterfaceType && type.element.isEnum) {
|
} else if (type is InterfaceType && type.element.isEnum) {
|
||||||
builderType = TypeReference((b) => b
|
builderType = TypeReference((b) => b
|
||||||
..symbol = 'EnumSqlExpressionBuilder'
|
..symbol = 'EnumSqlExpressionBuilder'
|
||||||
|
@ -555,7 +559,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
.isAssignableFromType(type)) {
|
.isAssignableFromType(type)) {
|
||||||
builderType = refer('ListSqlExpressionBuilder');
|
builderType = refer('ListSqlExpressionBuilder');
|
||||||
} else if (ctx.relations.containsKey(field.name)) {
|
} else if (ctx.relations.containsKey(field.name)) {
|
||||||
var relation = ctx.relations[field.name];
|
var relation = ctx.relations[field.name]!;
|
||||||
if (relation.type != RelationshipType.belongsTo) {
|
if (relation.type != RelationshipType.belongsTo) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
@ -566,7 +570,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw UnsupportedError(
|
throw UnsupportedError(
|
||||||
'Cannot generate ORM code for field of type ${field.type.name}.');
|
'Cannot generate ORM code for field of type ${field.type.getDisplayString(withNullability: false)}.');
|
||||||
}
|
}
|
||||||
|
|
||||||
clazz.fields.add(Field((b) {
|
clazz.fields.add(Field((b) {
|
||||||
|
@ -579,7 +583,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
refer(field.name)
|
refer(field.name)
|
||||||
.assign(builderType.newInstance([
|
.assign(builderType.newInstance([
|
||||||
refer('query'),
|
refer('query'),
|
||||||
literalString(ctx.buildContext.resolveFieldName(field.name))
|
literalString(ctx.buildContext.resolveFieldName(field.name)!)
|
||||||
].followedBy(args)))
|
].followedBy(args)))
|
||||||
.code,
|
.code,
|
||||||
);
|
);
|
||||||
|
@ -597,9 +601,9 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Class buildValuesClass(OrmBuildContext ctx) {
|
Class buildValuesClass(OrmBuildContext? ctx) {
|
||||||
return Class((clazz) {
|
return Class((clazz) {
|
||||||
var rc = ctx.buildContext.modelClassNameRecase;
|
var rc = ctx!.buildContext.modelClassNameRecase;
|
||||||
clazz
|
clazz
|
||||||
..name = '${rc.pascalCase}QueryValues'
|
..name = '${rc.pascalCase}QueryValues'
|
||||||
..extend = refer('MapQueryValues');
|
..extend = refer('MapQueryValues');
|
||||||
|
@ -611,7 +615,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
..annotations.add(refer('override'))
|
..annotations.add(refer('override'))
|
||||||
..type = MethodType.getter
|
..type = MethodType.getter
|
||||||
..body = Block((b) {
|
..body = Block((b) {
|
||||||
var args = <String, Expression>{};
|
var args = <String?, Expression>{};
|
||||||
|
|
||||||
for (var field in ctx.effectiveFields) {
|
for (var field in ctx.effectiveFields) {
|
||||||
var fType = field.type;
|
var fType = field.type;
|
||||||
|
@ -637,7 +641,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
var type = convertTypeReference(field.type);
|
var type = convertTypeReference(field.type);
|
||||||
|
|
||||||
clazz.methods.add(Method((b) {
|
clazz.methods.add(Method((b) {
|
||||||
var value = refer('values').index(literalString(name));
|
var value = refer('values').index(literalString(name!));
|
||||||
|
|
||||||
if (fType is InterfaceType && fType.element.isEnum) {
|
if (fType is InterfaceType && fType.element.isEnum) {
|
||||||
var asInt = value.asA(refer('int'));
|
var asInt = value.asA(refer('int'));
|
||||||
|
@ -682,7 +686,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
..name = 'value'
|
..name = 'value'
|
||||||
..type = type))
|
..type = type))
|
||||||
..body =
|
..body =
|
||||||
refer('values').index(literalString(name)).assign(value).code;
|
refer('values').index(literalString(name!)).assign(value).code;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -709,7 +713,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
var prop = refer('model').property(original);
|
var prop = refer('model').property(original);
|
||||||
// Add only if present
|
// Add only if present
|
||||||
var target = refer('values').index(literalString(
|
var target = refer('values').index(literalString(
|
||||||
ctx.buildContext.resolveFieldName(field.name)));
|
ctx.buildContext.resolveFieldName(field.name)!));
|
||||||
var foreign = field.relationship.throughContext ??
|
var foreign = field.relationship.throughContext ??
|
||||||
field.relationship.foreign;
|
field.relationship.foreign;
|
||||||
var foreignField = field.relationship.findForeignField(ctx);
|
var foreignField = field.relationship.findForeignField(ctx);
|
||||||
|
|
|
@ -20,21 +20,21 @@ class ColumnReader {
|
||||||
|
|
||||||
bool get isNullable => reader.peek('isNullable')?.boolValue ?? true;
|
bool get isNullable => reader.peek('isNullable')?.boolValue ?? true;
|
||||||
|
|
||||||
int get length => reader.peek('length')?.intValue;
|
int? get length => reader.peek('length')?.intValue;
|
||||||
|
|
||||||
DartObject get defaultValue => reader.peek('defaultValue')?.objectValue;
|
DartObject? get defaultValue => reader.peek('defaultValue')?.objectValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
class RelationshipReader {
|
class RelationshipReader {
|
||||||
final int type;
|
final int type;
|
||||||
final String localKey;
|
final String? localKey;
|
||||||
final String foreignKey;
|
final String? foreignKey;
|
||||||
final String foreignTable;
|
final String? foreignTable;
|
||||||
final bool cascadeOnDelete;
|
final bool? cascadeOnDelete;
|
||||||
final DartType through;
|
final DartType? through;
|
||||||
final OrmBuildContext foreign;
|
final OrmBuildContext? foreign;
|
||||||
final OrmBuildContext throughContext;
|
final OrmBuildContext? throughContext;
|
||||||
final JoinType joinType;
|
final JoinType? joinType;
|
||||||
|
|
||||||
const RelationshipReader(this.type,
|
const RelationshipReader(this.type,
|
||||||
{this.localKey,
|
{this.localKey,
|
||||||
|
@ -72,16 +72,16 @@ class RelationshipReader {
|
||||||
orElse: () {
|
orElse: () {
|
||||||
throw '${ctx.buildContext.clazz.name} has no field that maps to the name "$localKey", '
|
throw '${ctx.buildContext.clazz.name} has no field that maps to the name "$localKey", '
|
||||||
'but it has a @HasMany() relation that expects such a field.';
|
'but it has a @HasMany() relation that expects such a field.';
|
||||||
});
|
} as FieldElement Function()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldElement findForeignField(OrmBuildContext ctx) {
|
FieldElement findForeignField(OrmBuildContext? ctx) {
|
||||||
var foreign = throughContext ?? this.foreign;
|
var foreign = throughContext ?? this.foreign!;
|
||||||
return foreign.effectiveFields.firstWhere(
|
return foreign.effectiveFields.firstWhere(
|
||||||
(f) => foreign.buildContext.resolveFieldName(f.name) == foreignKey,
|
(f) => foreign.buildContext.resolveFieldName(f.name) == foreignKey,
|
||||||
orElse: () {
|
orElse: () {
|
||||||
throw '${foreign.buildContext.clazz.name} has no field that maps to the name "$foreignKey", '
|
throw '${foreign.buildContext.clazz.name} has no field that maps to the name "$foreignKey", '
|
||||||
'but ${ctx.buildContext.clazz.name} has a @HasMany() relation that expects such a field.';
|
'but ${ctx!.buildContext.clazz.name} has a @HasMany() relation that expects such a field.';
|
||||||
});
|
} as FieldElement Function()?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,54 +4,59 @@ description: Code generators for Angel's ORM. Generates query builder classes.
|
||||||
homepage: https://github.com/dukefirehawk/angel
|
homepage: https://github.com/dukefirehawk/angel
|
||||||
publish_to: none
|
publish_to: none
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.10.0 <3.0.0'
|
sdk: '>=2.12.0 <3.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
analyzer: ">=0.35.0 <2.0.0"
|
analyzer: ^1.5.0
|
||||||
angel_model:
|
angel_model:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/dukefirehawk/angel.git
|
url: https://github.com/dukefirehawk/angel.git
|
||||||
ref: sdk-2.12.x
|
ref: sdk-2.12.x_nnbd
|
||||||
path: packages/model
|
path: packages/model
|
||||||
angel_serialize:
|
angel_serialize:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/dukefirehawk/angel.git
|
url: https://github.com/dukefirehawk/angel.git
|
||||||
ref: sdk-2.12.x
|
ref: sdk-2.12.x_nnbd
|
||||||
path: packages/serialize/angel_serialize
|
path: packages/serialize/angel_serialize
|
||||||
angel_orm:
|
angel_orm:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/dukefirehawk/angel.git
|
url: https://github.com/dukefirehawk/angel.git
|
||||||
ref: sdk-2.12.x
|
ref: sdk-2.12.x_nnbd
|
||||||
path: packages/orm/angel_orm
|
path: packages/orm/angel_orm
|
||||||
angel_serialize_generator:
|
angel_serialize_generator:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/dukefirehawk/angel.git
|
url: https://github.com/dukefirehawk/angel.git
|
||||||
ref: sdk-2.12.x
|
ref: sdk-2.12.x_nnbd
|
||||||
path: packages/serialize/angel_serialize_generator
|
path: packages/serialize/angel_serialize_generator
|
||||||
build: ^1.0.0
|
inflection2:
|
||||||
build_config: ^0.4.0
|
git:
|
||||||
code_builder: ^3.0.0
|
url: https://github.com/dukefirehawk/angel.git
|
||||||
dart_style: ^1.0.0
|
ref: sdk-2.12.x_nnbd
|
||||||
inflection2: ^0.4.2
|
path: packages/inflection2
|
||||||
meta: ^1.0.0
|
build: ^2.0.1
|
||||||
path: ^1.0.0
|
build_config: ^1.0.0
|
||||||
recase: ^3.0.1
|
code_builder: ^4.0.0
|
||||||
source_gen: ^0.9.0
|
dart_style: ^2.0.1
|
||||||
|
meta: ^1.3.0
|
||||||
|
path: ^1.8.0
|
||||||
|
recase: ^4.0.0
|
||||||
|
source_gen: ^1.0.0
|
||||||
|
collection: ^1.15.0-nullsafety.4
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
angel_framework:
|
angel_framework:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/dukefirehawk/angel.git
|
url: https://github.com/dukefirehawk/angel.git
|
||||||
ref: sdk-2.12.x
|
ref: sdk-2.12.x_nnbd
|
||||||
path: packages/framework
|
path: packages/framework
|
||||||
angel_migration:
|
angel_migration:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/dukefirehawk/angel.git
|
url: https://github.com/dukefirehawk/angel.git
|
||||||
ref: sdk-2.12.x
|
ref: sdk-2.12.x_nnbd
|
||||||
path: packages/orm/angel_migration
|
path: packages/orm/angel_migration
|
||||||
#angel_test: ^1.0.0
|
#angel_test: ^1.0.0
|
||||||
build_runner: ^1.11.5
|
build_runner: ^2.0.1
|
||||||
collection: ^1.0.0
|
collection: ^1.15.0
|
||||||
pedantic: ^1.11.0
|
pedantic: ^1.11.0
|
||||||
postgres: ^2.2.0
|
postgres: ^2.3.2
|
||||||
# git:
|
# git:
|
||||||
# url: https://github.com/dukefirehawk/postgresql-dart
|
# url: https://github.com/dukefirehawk/postgresql-dart
|
||||||
test: ^1.16.5
|
test: ^1.17.3
|
||||||
|
|
Loading…
Reference in a new issue