update for new serializer
This commit is contained in:
parent
47606e1d51
commit
5ed22259c3
12 changed files with 270 additions and 47 deletions
|
@ -14,6 +14,7 @@ class Orm {
|
||||||
const Orm({this.tableName, this.generateMigrations: true});
|
const Orm({this.tableName, this.generateMigrations: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@deprecated
|
||||||
class Join {
|
class Join {
|
||||||
final Type against;
|
final Type against;
|
||||||
final String foreignKey;
|
final String foreignKey;
|
||||||
|
|
|
@ -399,3 +399,39 @@ class DateTimeSqlExpressionBuilder extends SqlExpressionBuilder<DateTime> {
|
||||||
return parts.isEmpty ? null : parts.join(' AND ');
|
return parts.isEmpty ? null : parts.join(' AND ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MapSqlExpressionBuilder<K, V, Key extends SqlExpressionBuilder<K>,
|
||||||
|
Value extends SqlExpressionBuilder<V>> extends SqlExpressionBuilder {
|
||||||
|
final Key key;
|
||||||
|
final Value value;
|
||||||
|
bool _hasValue = false;
|
||||||
|
String _raw;
|
||||||
|
|
||||||
|
MapSqlExpressionBuilder(Query query, String columnName, this.key, this.value)
|
||||||
|
: super(query, columnName);
|
||||||
|
|
||||||
|
UnsupportedError _unsupported() =>
|
||||||
|
UnsupportedError('JSON/JSONB does not support this operation.');
|
||||||
|
|
||||||
|
@override
|
||||||
|
String compile() {
|
||||||
|
var parts = <String>[_raw, key.compile(), value.compile()];
|
||||||
|
parts.removeWhere((s) => s == null);
|
||||||
|
return parts.isEmpty ? null : parts.join(' && ');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get hasValue => key.hasValue || value.hasValue || _hasValue;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void isBetween(lower, upper) => throw _unsupported();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void isIn(Iterable values) => throw _unsupported();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void isNotBetween(lower, upper) => throw _unsupported();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void isNotIn(Iterable values) => throw _unsupported();
|
||||||
|
}
|
||||||
|
|
|
@ -111,6 +111,10 @@ class ColumnType {
|
||||||
static const ColumnType varBinaryMax = const ColumnType('varbinary(max)');
|
static const ColumnType varBinaryMax = const ColumnType('varbinary(max)');
|
||||||
static const ColumnType image = const ColumnType('image');
|
static const ColumnType image = const ColumnType('image');
|
||||||
|
|
||||||
|
// JSON.
|
||||||
|
static const ColumnType json = const ColumnType('json');
|
||||||
|
static const ColumnType jsonb = const ColumnType('jsonb');
|
||||||
|
|
||||||
// Misc.
|
// Misc.
|
||||||
static const ColumnType sqlVariant = const ColumnType('sql_variant');
|
static const ColumnType sqlVariant = const ColumnType('sql_variant');
|
||||||
static const ColumnType uniqueIdentifier =
|
static const ColumnType uniqueIdentifier =
|
||||||
|
|
|
@ -26,12 +26,14 @@ targets:
|
||||||
- test/models/customer.dart
|
- test/models/customer.dart
|
||||||
- test/models/foot.dart
|
- test/models/foot.dart
|
||||||
- test/models/fruit.dart
|
- test/models/fruit.dart
|
||||||
|
- test/models/has_map.dart
|
||||||
- test/models/role.dart
|
- test/models/role.dart
|
||||||
$default:
|
$default:
|
||||||
dependencies:
|
dependencies:
|
||||||
- :_standalone
|
- :_standalone
|
||||||
sources:
|
sources:
|
||||||
- test/models/book.dart
|
- test/models/book.dart
|
||||||
|
# - test/models/has_car.dart
|
||||||
- test/models/leg.dart
|
- test/models/leg.dart
|
||||||
- test/models/order.dart
|
- test/models/order.dart
|
||||||
- test/models/tree.dart
|
- test/models/tree.dart
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:analyzer/dart/element/element.dart';
|
import 'package:analyzer/dart/element/element.dart';
|
||||||
|
import 'package:angel_model/angel_model.dart';
|
||||||
import 'package:angel_orm/angel_orm.dart';
|
import 'package:angel_orm/angel_orm.dart';
|
||||||
import 'package:angel_serialize_generator/angel_serialize_generator.dart';
|
import 'package:angel_serialize_generator/angel_serialize_generator.dart';
|
||||||
import 'package:build/build.dart';
|
import 'package:build/build.dart';
|
||||||
|
@ -11,8 +12,7 @@ import 'orm_build_context.dart';
|
||||||
Builder migrationBuilder(BuilderOptions options) {
|
Builder migrationBuilder(BuilderOptions options) {
|
||||||
return new SharedPartBuilder([
|
return new SharedPartBuilder([
|
||||||
new MigrationGenerator(
|
new MigrationGenerator(
|
||||||
autoSnakeCaseNames: options.config['auto_snake_case_names'] != false,
|
autoSnakeCaseNames: options.config['auto_snake_case_names'] != false)
|
||||||
autoIdAndDateFields: options.config['auto_id_and_date_fields'] != false)
|
|
||||||
], 'angel_migration');
|
], 'angel_migration');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,11 +25,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
/// If `true` (default), then field names will automatically be (de)serialized as snake_case.
|
/// If `true` (default), then field names will automatically be (de)serialized as snake_case.
|
||||||
final bool autoSnakeCaseNames;
|
final bool autoSnakeCaseNames;
|
||||||
|
|
||||||
/// If `true` (default), then the schema will automatically add id, created_at and updated_at fields.
|
const MigrationGenerator({this.autoSnakeCaseNames: true});
|
||||||
final bool autoIdAndDateFields;
|
|
||||||
|
|
||||||
const MigrationGenerator(
|
|
||||||
{this.autoSnakeCaseNames: true, this.autoIdAndDateFields: true});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> generateForAnnotatedElement(
|
Future<String> generateForAnnotatedElement(
|
||||||
|
@ -45,13 +41,8 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
}
|
}
|
||||||
|
|
||||||
var resolver = await buildStep.resolver;
|
var resolver = await buildStep.resolver;
|
||||||
var ctx = await buildOrmContext(
|
var ctx = await buildOrmContext(element as ClassElement, annotation,
|
||||||
element as ClassElement,
|
buildStep, resolver, autoSnakeCaseNames != false);
|
||||||
annotation,
|
|
||||||
buildStep,
|
|
||||||
resolver,
|
|
||||||
autoSnakeCaseNames != false,
|
|
||||||
autoIdAndDateFields != false);
|
|
||||||
var lib = generateMigrationLibrary(
|
var lib = generateMigrationLibrary(
|
||||||
ctx, element as ClassElement, resolver, buildStep);
|
ctx, element as ClassElement, resolver, buildStep);
|
||||||
if (lib == null) return null;
|
if (lib == null) return null;
|
||||||
|
@ -73,6 +64,8 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
|
|
||||||
Method buildUpMigration(OrmBuildContext ctx, LibraryBuilder lib) {
|
Method buildUpMigration(OrmBuildContext ctx, LibraryBuilder lib) {
|
||||||
return new Method((meth) {
|
return new Method((meth) {
|
||||||
|
var autoIdAndDateFields = const TypeChecker.fromRuntime(Model)
|
||||||
|
.isAssignableFromType(ctx.buildContext.clazz.type);
|
||||||
meth
|
meth
|
||||||
..name = 'up'
|
..name = 'up'
|
||||||
..annotations.add(refer('override'))
|
..annotations.add(refer('override'))
|
||||||
|
|
|
@ -27,7 +27,6 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
BuildStep buildStep,
|
BuildStep buildStep,
|
||||||
Resolver resolver,
|
Resolver resolver,
|
||||||
bool autoSnakeCaseNames,
|
bool autoSnakeCaseNames,
|
||||||
bool autoIdAndDateFields,
|
|
||||||
{bool heedExclude: true}) async {
|
{bool heedExclude: true}) async {
|
||||||
// Check for @generatedSerializable
|
// Check for @generatedSerializable
|
||||||
// ignore: unused_local_variable
|
// ignore: unused_local_variable
|
||||||
|
@ -44,8 +43,8 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
if (_cache.containsKey(id)) {
|
if (_cache.containsKey(id)) {
|
||||||
return _cache[id];
|
return _cache[id];
|
||||||
}
|
}
|
||||||
var buildCtx = await buildContext(clazz, annotation, buildStep, resolver,
|
var buildCtx = await buildContext(
|
||||||
autoSnakeCaseNames, autoIdAndDateFields,
|
clazz, annotation, buildStep, resolver, autoSnakeCaseNames,
|
||||||
heedExclude: heedExclude);
|
heedExclude: heedExclude);
|
||||||
var ormAnnotation = reviveORMAnnotation(annotation);
|
var ormAnnotation = reviveORMAnnotation(annotation);
|
||||||
var ctx = new OrmBuildContext(
|
var ctx = new OrmBuildContext(
|
||||||
|
@ -66,7 +65,10 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
column = reviveColumn(new ConstantReader(columnAnnotation));
|
column = reviveColumn(new ConstantReader(columnAnnotation));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (column == null && field.name == 'id' && autoIdAndDateFields == true) {
|
if (column == null &&
|
||||||
|
field.name == 'id' &&
|
||||||
|
const TypeChecker.fromRuntime(Model)
|
||||||
|
.isAssignableFromType(buildCtx.clazz.type)) {
|
||||||
// This is only for PostgreSQL, so implementations without a `serial` type
|
// This is only for PostgreSQL, so implementations without a `serial` type
|
||||||
// must handle it accordingly, of course.
|
// must handle it accordingly, of course.
|
||||||
column = const Column(type: ColumnType.serial);
|
column = const Column(type: ColumnType.serial);
|
||||||
|
@ -76,7 +78,7 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
// Guess what kind of column this is...
|
// Guess what kind of column this is...
|
||||||
column = new Column(
|
column = new Column(
|
||||||
type: inferColumnType(
|
type: inferColumnType(
|
||||||
field.type,
|
buildCtx.resolveSerializedFieldType(field.name),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -133,8 +135,7 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
.firstAnnotationOf(modelType.element)),
|
.firstAnnotationOf(modelType.element)),
|
||||||
buildStep,
|
buildStep,
|
||||||
resolver,
|
resolver,
|
||||||
autoSnakeCaseNames,
|
autoSnakeCaseNames);
|
||||||
autoIdAndDateFields);
|
|
||||||
|
|
||||||
var ormAnn = const TypeChecker.fromRuntime(Orm)
|
var ormAnn = const TypeChecker.fromRuntime(Orm)
|
||||||
.firstAnnotationOf(modelType.element);
|
.firstAnnotationOf(modelType.element);
|
||||||
|
@ -176,7 +177,9 @@ Future<OrmBuildContext> buildOrmContext(
|
||||||
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)) {
|
||||||
if (field.name != 'id' || !autoIdAndDateFields) {
|
if (field.name != 'id' ||
|
||||||
|
!const TypeChecker.fromRuntime(Model)
|
||||||
|
.isAssignableFromType(ctx.buildContext.clazz.type)) {
|
||||||
var rf = new RelationFieldImpl(name,
|
var rf = new RelationFieldImpl(name,
|
||||||
field.type.element.context.typeProvider.intType, field.name);
|
field.type.element.context.typeProvider.intType, field.name);
|
||||||
ctx.effectiveFields.add(rf);
|
ctx.effectiveFields.add(rf);
|
||||||
|
@ -212,6 +215,8 @@ ColumnType inferColumnType(DartType type) {
|
||||||
return ColumnType.boolean;
|
return ColumnType.boolean;
|
||||||
if (const TypeChecker.fromRuntime(DateTime).isAssignableFromType(type))
|
if (const TypeChecker.fromRuntime(DateTime).isAssignableFromType(type))
|
||||||
return ColumnType.timeStamp;
|
return ColumnType.timeStamp;
|
||||||
|
if (const TypeChecker.fromRuntime(Map).isAssignableFromType(type))
|
||||||
|
return ColumnType.jsonb;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:analyzer/dart/element/element.dart';
|
import 'package:analyzer/dart/element/element.dart';
|
||||||
|
import 'package:analyzer/dart/element/type.dart';
|
||||||
|
import 'package:angel_model/angel_model.dart';
|
||||||
import 'package:angel_orm/angel_orm.dart';
|
import 'package:angel_orm/angel_orm.dart';
|
||||||
import 'package:angel_serialize_generator/angel_serialize_generator.dart';
|
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';
|
||||||
|
@ -12,8 +14,7 @@ import 'orm_build_context.dart';
|
||||||
Builder ormBuilder(BuilderOptions options) {
|
Builder ormBuilder(BuilderOptions options) {
|
||||||
return new SharedPartBuilder([
|
return new SharedPartBuilder([
|
||||||
new OrmGenerator(
|
new OrmGenerator(
|
||||||
autoSnakeCaseNames: options.config['auto_snake_case_names'] != false,
|
autoSnakeCaseNames: options.config['auto_snake_case_names'] != false)
|
||||||
autoIdAndDateFields: options.config['auto_id_and_date_fields'] != false)
|
|
||||||
], 'angel_orm');
|
], 'angel_orm');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,16 +27,15 @@ 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;
|
||||||
final bool autoIdAndDateFields;
|
|
||||||
|
|
||||||
OrmGenerator({this.autoSnakeCaseNames, this.autoIdAndDateFields});
|
OrmGenerator({this.autoSnakeCaseNames});
|
||||||
|
|
||||||
@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) {
|
||||||
var ctx = await buildOrmContext(element, annotation, buildStep,
|
var ctx = await buildOrmContext(element, annotation, buildStep,
|
||||||
buildStep.resolver, autoSnakeCaseNames, autoIdAndDateFields);
|
buildStep.resolver, autoSnakeCaseNames);
|
||||||
var lib = buildOrmLibrary(buildStep.inputId, ctx);
|
var lib = buildOrmLibrary(buildStep.inputId, ctx);
|
||||||
return lib.accept(new DartEmitter()).toString();
|
return lib.accept(new DartEmitter()).toString();
|
||||||
} else {
|
} else {
|
||||||
|
@ -146,10 +146,10 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
|
|
||||||
for (var field in ctx.effectiveFields) {
|
for (var field in ctx.effectiveFields) {
|
||||||
Reference type = convertTypeReference(field.type);
|
Reference type = convertTypeReference(field.type);
|
||||||
if (isSpecialId(field)) type = refer('int');
|
if (isSpecialId(ctx, field)) type = refer('int');
|
||||||
|
|
||||||
var expr = (refer('row').index(literalNum(i++)));
|
var expr = (refer('row').index(literalNum(i++)));
|
||||||
if (isSpecialId(field))
|
if (isSpecialId(ctx, field))
|
||||||
expr = expr.property('toString').call([]);
|
expr = expr.property('toString').call([]);
|
||||||
else if (field is RelationFieldImpl)
|
else if (field is RelationFieldImpl)
|
||||||
continue;
|
continue;
|
||||||
|
@ -229,7 +229,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
relation.type == RelationshipType.hasMany) {
|
relation.type == RelationshipType.hasMany) {
|
||||||
var foreign = ctx.relationTypes[relation];
|
var foreign = ctx.relationTypes[relation];
|
||||||
var additionalFields = foreign.effectiveFields
|
var additionalFields = foreign.effectiveFields
|
||||||
.where((f) => f.name != 'id' || !isSpecialId(f))
|
.where((f) => f.name != 'id' || !isSpecialId(ctx, f))
|
||||||
.map((f) => literalString(
|
.map((f) => literalString(
|
||||||
foreign.buildContext.resolveFieldName(f.name)));
|
foreign.buildContext.resolveFieldName(f.name)));
|
||||||
var joinArgs = [relation.localKey, relation.foreignKey]
|
var joinArgs = [relation.localKey, relation.foreignKey]
|
||||||
|
@ -284,7 +284,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
|
|
||||||
// Just call getOne() again
|
// Just call getOne() again
|
||||||
if (ctx.effectiveFields.any((f) =>
|
if (ctx.effectiveFields.any((f) =>
|
||||||
isSpecialId(f) ||
|
isSpecialId(ctx, f) ||
|
||||||
(ctx.columns[f.name]?.indexType ==
|
(ctx.columns[f.name]?.indexType ==
|
||||||
IndexType.primaryKey))) {
|
IndexType.primaryKey))) {
|
||||||
b.addExpression(refer('where')
|
b.addExpression(refer('where')
|
||||||
|
@ -370,7 +370,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
'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.';
|
||||||
});
|
});
|
||||||
|
|
||||||
var queryValue = (isSpecialId(localField))
|
var queryValue = (isSpecialId(ctx, localField))
|
||||||
? 'int.parse(model.id)'
|
? 'int.parse(model.id)'
|
||||||
: 'model.${localField.name}';
|
: 'model.${localField.name}';
|
||||||
var cascadeText =
|
var cascadeText =
|
||||||
|
@ -445,10 +445,12 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSpecialId(FieldElement field) {
|
bool isSpecialId(OrmBuildContext ctx, FieldElement field) {
|
||||||
return field is ShimFieldImpl &&
|
return field is ShimFieldImpl &&
|
||||||
field is! RelationFieldImpl &&
|
field is! RelationFieldImpl &&
|
||||||
(field.name == 'id' && autoIdAndDateFields);
|
(field.name == 'id' &&
|
||||||
|
const TypeChecker.fromRuntime(Model)
|
||||||
|
.isAssignableFromType(ctx.buildContext.clazz.type));
|
||||||
}
|
}
|
||||||
|
|
||||||
Class buildWhereClass(OrmBuildContext ctx) {
|
Class buildWhereClass(OrmBuildContext ctx) {
|
||||||
|
@ -475,23 +477,31 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
// Add builders for each field
|
// Add builders for each field
|
||||||
for (var field in ctx.effectiveFields) {
|
for (var field in ctx.effectiveFields) {
|
||||||
var name = field.name;
|
var name = field.name;
|
||||||
|
DartType type;
|
||||||
Reference builderType;
|
Reference builderType;
|
||||||
|
|
||||||
if (const TypeChecker.fromRuntime(int).isExactlyType(field.type) ||
|
try {
|
||||||
const TypeChecker.fromRuntime(double).isExactlyType(field.type) ||
|
type = ctx.buildContext.resolveSerializedFieldType(field.name);
|
||||||
isSpecialId(field)) {
|
} on StateError {
|
||||||
|
type = field.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const TypeChecker.fromRuntime(int).isExactlyType(type) ||
|
||||||
|
const TypeChecker.fromRuntime(double).isExactlyType(type) ||
|
||||||
|
isSpecialId(ctx, field)) {
|
||||||
builderType = new TypeReference((b) => b
|
builderType = new TypeReference((b) => b
|
||||||
..symbol = 'NumericSqlExpressionBuilder'
|
..symbol = 'NumericSqlExpressionBuilder'
|
||||||
..types.add(refer(isSpecialId(field) ? 'int' : field.type.name)));
|
..types.add(refer(isSpecialId(ctx, field) ? 'int' : type.name)));
|
||||||
} else if (const TypeChecker.fromRuntime(String)
|
} else if (const TypeChecker.fromRuntime(String).isExactlyType(type)) {
|
||||||
.isExactlyType(field.type)) {
|
|
||||||
builderType = refer('StringSqlExpressionBuilder');
|
builderType = refer('StringSqlExpressionBuilder');
|
||||||
} else if (const TypeChecker.fromRuntime(bool)
|
} else if (const TypeChecker.fromRuntime(bool).isExactlyType(type)) {
|
||||||
.isExactlyType(field.type)) {
|
|
||||||
builderType = refer('BooleanSqlExpressionBuilder');
|
builderType = refer('BooleanSqlExpressionBuilder');
|
||||||
} else if (const TypeChecker.fromRuntime(DateTime)
|
} else if (const TypeChecker.fromRuntime(DateTime)
|
||||||
.isExactlyType(field.type)) {
|
.isExactlyType(type)) {
|
||||||
builderType = refer('DateTimeSqlExpressionBuilder');
|
builderType = refer('DateTimeSqlExpressionBuilder');
|
||||||
|
} else if (const TypeChecker.fromRuntime(Map)
|
||||||
|
.isAssignableFromType(type)) {
|
||||||
|
builderType = refer('MapSqlExpressionBuilder');
|
||||||
} 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)
|
||||||
|
@ -545,7 +555,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
// Each field generates a getter for setter
|
// Each field generates a getter for setter
|
||||||
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);
|
||||||
var type = isSpecialId(field)
|
var type = isSpecialId(ctx, field)
|
||||||
? refer('int')
|
? refer('int')
|
||||||
: convertTypeReference(field.type);
|
: convertTypeReference(field.type);
|
||||||
|
|
||||||
|
@ -584,7 +594,8 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
var args = <String, Expression>{};
|
var args = <String, Expression>{};
|
||||||
|
|
||||||
for (var field in ctx.effectiveFields) {
|
for (var field in ctx.effectiveFields) {
|
||||||
if (isSpecialId(field) || field is RelationFieldImpl) continue;
|
if (isSpecialId(ctx, field) || field is RelationFieldImpl)
|
||||||
|
continue;
|
||||||
args[ctx.buildContext.resolveFieldName(field.name)] =
|
args[ctx.buildContext.resolveFieldName(field.name)] =
|
||||||
refer('model').property(field.name);
|
refer('model').property(field.name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/// Tests for @hasOne...
|
/// Tests for @hasOne...
|
||||||
library angel_orm_generator.test.has_one_test;
|
library angel_orm_generator.test.has_one_test;
|
||||||
|
|
||||||
import 'package:angel_orm/angel_orm.dart';
|
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
import 'models/foot.dart';
|
import 'models/foot.dart';
|
||||||
import 'models/leg.dart';
|
import 'models/leg.dart';
|
||||||
|
|
|
@ -10,6 +10,6 @@ part 'author.g.dart';
|
||||||
@orm
|
@orm
|
||||||
abstract class _Author extends Model {
|
abstract class _Author extends Model {
|
||||||
@Column(length: 255, indexType: IndexType.unique)
|
@Column(length: 255, indexType: IndexType.unique)
|
||||||
@DefaultValue('Tobe Osakwe')
|
@SerializableField(defaultValue: 'Tobe Osakwe')
|
||||||
String get name;
|
String get name;
|
||||||
}
|
}
|
||||||
|
|
12
angel_orm_generator/test/models/has_car.dart
Normal file
12
angel_orm_generator/test/models/has_car.dart
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import 'package:angel_migration/angel_migration.dart';
|
||||||
|
import 'package:angel_model/angel_model.dart';
|
||||||
|
import 'package:angel_orm/angel_orm.dart';
|
||||||
|
import 'package:angel_serialize/angel_serialize.dart';
|
||||||
|
import 'car.dart';
|
||||||
|
// part 'has_car.g.dart';
|
||||||
|
|
||||||
|
@orm
|
||||||
|
@serializable
|
||||||
|
abstract class _PackageJson extends Model {
|
||||||
|
Car get car;
|
||||||
|
}
|
12
angel_orm_generator/test/models/has_map.dart
Normal file
12
angel_orm_generator/test/models/has_map.dart
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import 'package:angel_migration/angel_migration.dart';
|
||||||
|
import 'package:angel_model/angel_model.dart';
|
||||||
|
import 'package:angel_orm/angel_orm.dart';
|
||||||
|
import 'package:angel_serialize/angel_serialize.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
part 'has_map.g.dart';
|
||||||
|
|
||||||
|
@orm
|
||||||
|
@serializable
|
||||||
|
abstract class _HasMap {
|
||||||
|
Map get value;
|
||||||
|
}
|
148
angel_orm_generator/test/models/has_map.g.dart
Normal file
148
angel_orm_generator/test/models/has_map.g.dart
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'has_map.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// MigrationGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class HasMapMigration extends Migration {
|
||||||
|
@override
|
||||||
|
up(Schema schema) {
|
||||||
|
schema.create('has_maps', (table) {
|
||||||
|
table.declare('value', new ColumnType('jsonb'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
down(Schema schema) {
|
||||||
|
schema.drop('has_maps');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// OrmGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class HasMapQuery extends Query<HasMap, HasMapQueryWhere> {
|
||||||
|
HasMapQuery() {
|
||||||
|
_where = new HasMapQueryWhere(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
final HasMapQueryValues values = new HasMapQueryValues();
|
||||||
|
|
||||||
|
HasMapQueryWhere _where;
|
||||||
|
|
||||||
|
@override
|
||||||
|
get tableName {
|
||||||
|
return 'has_maps';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
get fields {
|
||||||
|
return const ['value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
HasMapQueryWhere get where {
|
||||||
|
return _where;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
HasMapQueryWhere newWhereClause() {
|
||||||
|
return new HasMapQueryWhere(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HasMap parseRow(List row) {
|
||||||
|
if (row.every((x) => x == null)) return null;
|
||||||
|
var model = new HasMap(value: (row[0] as Map<dynamic, dynamic>));
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
deserialize(List row) {
|
||||||
|
return parseRow(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HasMapQueryWhere extends QueryWhere {
|
||||||
|
HasMapQueryWhere(HasMapQuery query)
|
||||||
|
: value = new MapSqlExpressionBuilder(query, 'value');
|
||||||
|
|
||||||
|
final MapSqlExpressionBuilder value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
get expressionBuilders {
|
||||||
|
return [value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HasMapQueryValues extends MapQueryValues {
|
||||||
|
Map<dynamic, dynamic> get value {
|
||||||
|
return (values['value'] as Map<dynamic, dynamic>);
|
||||||
|
}
|
||||||
|
|
||||||
|
set value(Map<dynamic, dynamic> value) => values['value'] = value;
|
||||||
|
void copyFrom(HasMap model) {
|
||||||
|
values.addAll({'value': model.value});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonModelGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
@generatedSerializable
|
||||||
|
class HasMap implements _HasMap {
|
||||||
|
const HasMap({Map<dynamic, dynamic> this.value});
|
||||||
|
|
||||||
|
@override
|
||||||
|
final Map<dynamic, dynamic> value;
|
||||||
|
|
||||||
|
HasMap copyWith({Map<dynamic, dynamic> value}) {
|
||||||
|
return new HasMap(value: value ?? this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator ==(other) {
|
||||||
|
return other is _HasMap &&
|
||||||
|
const MapEquality<dynamic, dynamic>(
|
||||||
|
keys: const DefaultEquality(), values: const DefaultEquality())
|
||||||
|
.equals(other.value, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return hashObjects([value]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return HasMapSerializer.toMap(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// SerializerGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
abstract class HasMapSerializer {
|
||||||
|
static HasMap fromMap(Map map) {
|
||||||
|
return new HasMap(
|
||||||
|
value: map['value'] is Map
|
||||||
|
? (map['value'] as Map).cast<dynamic, dynamic>()
|
||||||
|
: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, dynamic> toMap(_HasMap model) {
|
||||||
|
if (model == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {'value': model.value};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class HasMapFields {
|
||||||
|
static const List<String> allFields = const <String>[value];
|
||||||
|
|
||||||
|
static const String value = 'value';
|
||||||
|
}
|
Loading…
Reference in a new issue