source_gen error
This commit is contained in:
parent
421099ee94
commit
ba2afae0f4
10 changed files with 122 additions and 88 deletions
|
@ -1,3 +1,4 @@
|
||||||
export 'src/annotations.dart';
|
export 'src/annotations.dart';
|
||||||
export 'src/migration.dart';
|
export 'src/migration.dart';
|
||||||
|
export 'src/relations.dart';
|
||||||
export 'src/query.dart';
|
export 'src/query.dart';
|
|
@ -6,13 +6,14 @@ import 'package:path/path.dart' as p;
|
||||||
import 'package:recase/recase.dart';
|
import 'package:recase/recase.dart';
|
||||||
import '../../annotations.dart';
|
import '../../annotations.dart';
|
||||||
import '../../migration.dart';
|
import '../../migration.dart';
|
||||||
|
import '../../relations.dart';
|
||||||
import '../find_annotation.dart';
|
import '../find_annotation.dart';
|
||||||
import 'postgres_build_context.dart';
|
import 'postgres_build_context.dart';
|
||||||
|
|
||||||
// TODO: Should add id, createdAt, updatedAt...
|
// TODO: Should add id, createdAt, updatedAt...
|
||||||
PostgresBuildContext buildContext(ClassElement clazz, ORM annotation,
|
PostgresBuildContext buildContext(ClassElement clazz, ORM annotation,
|
||||||
BuildStep buildStep, bool autoSnakeCaseNames) {
|
BuildStep buildStep, bool autoSnakeCaseNames) {
|
||||||
var ctx = new PostgresBuildContext(annotation, clazz.fields,
|
var ctx = new PostgresBuildContext(annotation,
|
||||||
originalClassName: clazz.name,
|
originalClassName: clazz.name,
|
||||||
tableName: annotation.tableName?.isNotEmpty == true
|
tableName: annotation.tableName?.isNotEmpty == true
|
||||||
? annotation.tableName
|
? annotation.tableName
|
||||||
|
@ -21,6 +22,15 @@ PostgresBuildContext buildContext(ClassElement clazz, ORM annotation,
|
||||||
|
|
||||||
for (var field in clazz.fields) {
|
for (var field in clazz.fields) {
|
||||||
if (field.getter != null && field.setter != null) {
|
if (field.getter != null && field.setter != null) {
|
||||||
|
// Check for relationship. If so, skip.
|
||||||
|
Relationship relationship = findAnnotation<HasOne>(field, HasOne) ??
|
||||||
|
findAnnotation<HasMany>(field, HasMany) ??
|
||||||
|
findAnnotation<BelongsTo>(field, BelongsTo);
|
||||||
|
|
||||||
|
if (relationship != null) {
|
||||||
|
ctx.relationships[field.name] = relationship;
|
||||||
|
continue;
|
||||||
|
} else print('Hm: ${field.name}');
|
||||||
// Check for alias
|
// Check for alias
|
||||||
var alias = findAnnotation<Alias>(field, Alias);
|
var alias = findAnnotation<Alias>(field, Alias);
|
||||||
|
|
||||||
|
@ -63,6 +73,7 @@ PostgresBuildContext buildContext(ClassElement clazz, ORM annotation,
|
||||||
if (column == null)
|
if (column == null)
|
||||||
throw 'Cannot infer SQL column type for field "${field.name}" with type "${field.type.name}".';
|
throw 'Cannot infer SQL column type for field "${field.name}" with type "${field.type.name}".';
|
||||||
ctx.columnInfo[field.name] = column;
|
ctx.columnInfo[field.name] = column;
|
||||||
|
ctx.fields.add(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
import 'package:analyzer/dart/element/element.dart';
|
import 'package:analyzer/dart/element/element.dart';
|
||||||
import '../../annotations.dart';
|
import '../../annotations.dart';
|
||||||
import '../../migration.dart';
|
import '../../migration.dart';
|
||||||
|
import '../../relations.dart';
|
||||||
|
|
||||||
class PostgresBuildContext {
|
class PostgresBuildContext {
|
||||||
final Map<String, String> aliases = {};
|
final Map<String, String> aliases = {};
|
||||||
final Map<String, Column> columnInfo = {};
|
final Map<String, Column> columnInfo = {};
|
||||||
final Map<String, IndexType> indices = {};
|
final Map<String, IndexType> indices = {};
|
||||||
|
final Map<String, Relationship> relationships = {};
|
||||||
final String originalClassName, tableName, sourceFilename;
|
final String originalClassName, tableName, sourceFilename;
|
||||||
final ORM annotation;
|
final ORM annotation;
|
||||||
// Todo: We can use analyzer to copy straight from Model class
|
// Todo: We can use analyzer to copy straight from Model class
|
||||||
final List<FieldElement> fields;
|
final List<FieldElement> fields = [];
|
||||||
String primaryKeyName = 'id';
|
String primaryKeyName = 'id';
|
||||||
|
|
||||||
PostgresBuildContext(this.annotation, this.fields,
|
PostgresBuildContext(this.annotation,
|
||||||
{this.originalClassName, this.tableName, this.sourceFilename});
|
{this.originalClassName, this.tableName, this.sourceFilename});
|
||||||
|
|
||||||
String get modelClassName => originalClassName.startsWith('_')
|
String get modelClassName => originalClassName.startsWith('_')
|
||||||
|
|
52
lib/src/relations.dart
Normal file
52
lib/src/relations.dart
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
class Relationship {
|
||||||
|
final String localKey;
|
||||||
|
final String foreignKey;
|
||||||
|
final String foreignTable;
|
||||||
|
final bool cascadeOnDelete;
|
||||||
|
|
||||||
|
const Relationship._(
|
||||||
|
{this.localKey,
|
||||||
|
this.foreignKey,
|
||||||
|
this.foreignTable,
|
||||||
|
this.cascadeOnDelete});
|
||||||
|
}
|
||||||
|
|
||||||
|
class HasMany extends Relationship {
|
||||||
|
const HasMany(
|
||||||
|
{String localKey,
|
||||||
|
String foreignKey,
|
||||||
|
String foreignTable,
|
||||||
|
bool cascadeOnDelete: false})
|
||||||
|
: super._(
|
||||||
|
localKey: localKey,
|
||||||
|
foreignKey: foreignKey,
|
||||||
|
foreignTable: foreignTable,
|
||||||
|
cascadeOnDelete: cascadeOnDelete == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const HasMany hasMany = const HasMany();
|
||||||
|
|
||||||
|
class HasOne extends Relationship {
|
||||||
|
const HasOne(
|
||||||
|
{String localKey,
|
||||||
|
String foreignKey,
|
||||||
|
String foreignTable,
|
||||||
|
bool cascadeOnDelete: false})
|
||||||
|
: super._(
|
||||||
|
localKey: localKey,
|
||||||
|
foreignKey: foreignKey,
|
||||||
|
foreignTable: foreignTable,
|
||||||
|
cascadeOnDelete: cascadeOnDelete == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const HasOne hasOne = const HasOne();
|
||||||
|
|
||||||
|
class BelongsTo extends Relationship {
|
||||||
|
const BelongsTo({String localKey, String foreignKey, String foreignTable})
|
||||||
|
: super._(
|
||||||
|
localKey: localKey,
|
||||||
|
foreignKey: foreignKey,
|
||||||
|
foreignTable: foreignTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
const BelongsTo belongsTo = const BelongsTo();
|
|
@ -16,7 +16,7 @@ main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('insert', () async {
|
test('insert', () async {
|
||||||
var car = await CarQuery.insert(make: 'Mazda', familyFriendly: false);
|
var car = await CarQuery.insert(null, make: 'Mazda', familyFriendly: false);
|
||||||
print(car.toJson());
|
print(car.toJson());
|
||||||
}, skip: 'Insert not yet implemented');
|
}, skip: 'Insert not yet implemented');
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ library angel_orm.test.models.car;
|
||||||
import 'package:angel_framework/common.dart';
|
import 'package:angel_framework/common.dart';
|
||||||
import 'package:angel_orm/angel_orm.dart';
|
import 'package:angel_orm/angel_orm.dart';
|
||||||
import 'package:angel_serialize/angel_serialize.dart';
|
import 'package:angel_serialize/angel_serialize.dart';
|
||||||
|
import 'tire.dart';
|
||||||
part 'car.g.dart';
|
part 'car.g.dart';
|
||||||
|
|
||||||
@serializable
|
@serializable
|
||||||
|
@ -12,4 +13,6 @@ class _Car extends Model {
|
||||||
String description;
|
String description;
|
||||||
bool familyFriendly;
|
bool familyFriendly;
|
||||||
DateTime recalledAt;
|
DateTime recalledAt;
|
||||||
|
@hasMany
|
||||||
|
List<Tire> tires;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,15 @@ class Car extends _Car {
|
||||||
@override
|
@override
|
||||||
DateTime recalledAt;
|
DateTime recalledAt;
|
||||||
|
|
||||||
Car({this.make, this.description, this.familyFriendly, this.recalledAt});
|
@override
|
||||||
|
List tires;
|
||||||
|
|
||||||
|
Car(
|
||||||
|
{this.make,
|
||||||
|
this.description,
|
||||||
|
this.familyFriendly,
|
||||||
|
this.recalledAt,
|
||||||
|
this.tires});
|
||||||
|
|
||||||
factory Car.fromJson(Map data) {
|
factory Car.fromJson(Map data) {
|
||||||
return new Car(
|
return new Car(
|
||||||
|
@ -31,14 +39,16 @@ class Car extends _Car {
|
||||||
? data['recalledAt']
|
? data['recalledAt']
|
||||||
: (data['recalledAt'] is String
|
: (data['recalledAt'] is String
|
||||||
? DateTime.parse(data['recalledAt'])
|
? DateTime.parse(data['recalledAt'])
|
||||||
: null));
|
: null),
|
||||||
|
tires: data['tires']);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
'make': make,
|
'make': make,
|
||||||
'description': description,
|
'description': description,
|
||||||
'familyFriendly': familyFriendly,
|
'familyFriendly': familyFriendly,
|
||||||
'recalledAt': recalledAt == null ? null : recalledAt.toIso8601String()
|
'recalledAt': recalledAt == null ? null : recalledAt.toIso8601String(),
|
||||||
|
'tires': tires
|
||||||
};
|
};
|
||||||
|
|
||||||
static Car parse(Map map) => new Car.fromJson(map);
|
static Car parse(Map map) => new Car.fromJson(map);
|
||||||
|
|
|
@ -5,84 +5,6 @@
|
||||||
// Target: class _Car
|
// Target: class _Car
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
import 'dart:async';
|
// Error: type 'SuperConstructorInvocationImpl' is not a subtype of type 'ConstructorFieldInitializer' in type cast where
|
||||||
import 'package:angel_orm/angel_orm.dart';
|
// SuperConstructorInvocationImpl is from package:analyzer/src/dart/ast/ast.dart
|
||||||
import 'package:postgres/postgres.dart';
|
// ConstructorFieldInitializer is from package:analyzer/dart/ast/ast.dart
|
||||||
import 'car.dart';
|
|
||||||
|
|
||||||
class CarQuery {
|
|
||||||
final List<String> _and = [];
|
|
||||||
|
|
||||||
final List<String> _or = [];
|
|
||||||
|
|
||||||
final List<String> _not = [];
|
|
||||||
|
|
||||||
final CarQueryWhere where = new CarQueryWhere();
|
|
||||||
|
|
||||||
void and(CarQuery other) {
|
|
||||||
var compiled = other.where.toWhereClause();
|
|
||||||
if (compiled != null) {
|
|
||||||
_and.add(compiled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void or(CarQuery other) {
|
|
||||||
var compiled = other.where.toWhereClause();
|
|
||||||
if (compiled != null) {
|
|
||||||
_or.add(compiled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void not(CarQuery other) {
|
|
||||||
var compiled = other.where.toWhereClause();
|
|
||||||
if (compiled != null) {
|
|
||||||
_not.add(compiled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<Car> get() {}
|
|
||||||
|
|
||||||
Future<Car> getOne() {}
|
|
||||||
|
|
||||||
Future<Car> update() {}
|
|
||||||
|
|
||||||
Future<Car> delete() {}
|
|
||||||
|
|
||||||
static Future<Car> insert(PostgreSQLConnection connection,
|
|
||||||
{String make,
|
|
||||||
String description,
|
|
||||||
bool familyFriendly,
|
|
||||||
DateTime recalledAt}) {}
|
|
||||||
|
|
||||||
static Stream<Car> getAll() => new CarQuery().get();
|
|
||||||
}
|
|
||||||
|
|
||||||
class CarQueryWhere {
|
|
||||||
final StringSqlExpressionBuilder make = new StringSqlExpressionBuilder();
|
|
||||||
|
|
||||||
final StringSqlExpressionBuilder description =
|
|
||||||
new StringSqlExpressionBuilder();
|
|
||||||
|
|
||||||
final BooleanSqlExpressionBuilder familyFriendly =
|
|
||||||
new BooleanSqlExpressionBuilder();
|
|
||||||
|
|
||||||
final DateTimeSqlExpressionBuilder recalledAt =
|
|
||||||
new DateTimeSqlExpressionBuilder('recalled_at');
|
|
||||||
|
|
||||||
String toWhereClause() {
|
|
||||||
final List<String> expressions = [];
|
|
||||||
if (make.hasValue) {
|
|
||||||
expressions.add('`make` ' + make.compile());
|
|
||||||
}
|
|
||||||
if (description.hasValue) {
|
|
||||||
expressions.add('`description` ' + description.compile());
|
|
||||||
}
|
|
||||||
if (familyFriendly.hasValue) {
|
|
||||||
expressions.add('`family_friendly` ' + familyFriendly.compile());
|
|
||||||
}
|
|
||||||
if (recalledAt.hasValue) {
|
|
||||||
expressions.add(recalledAt.compile());
|
|
||||||
}
|
|
||||||
return expressions.isEmpty ? null : ('WHERE ' + expressions.join(' AND '));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
10
test/models/tire.dart
Normal file
10
test/models/tire.dart
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
library angel_test.test.models.tire;
|
||||||
|
|
||||||
|
import 'package:angel_framework/common.dart';
|
||||||
|
import 'package:angel_serialize/angel_serialize.dart';
|
||||||
|
part 'tire.g.dart';
|
||||||
|
|
||||||
|
@serializable
|
||||||
|
class _Tire extends Model {
|
||||||
|
int size;
|
||||||
|
}
|
23
test/models/tire.g.dart
Normal file
23
test/models/tire.g.dart
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of angel_test.test.models.tire;
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// Generator: JsonModelGenerator
|
||||||
|
// Target: class _Tire
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class Tire extends _Tire {
|
||||||
|
@override
|
||||||
|
int size;
|
||||||
|
|
||||||
|
Tire({this.size});
|
||||||
|
|
||||||
|
factory Tire.fromJson(Map data) {
|
||||||
|
return new Tire(size: data['size']);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {'size': size};
|
||||||
|
|
||||||
|
static Tire parse(Map map) => new Tire.fromJson(map);
|
||||||
|
}
|
Loading…
Reference in a new issue