ORM gen updates
This commit is contained in:
parent
e95c4d8c6b
commit
432bac7512
30 changed files with 639 additions and 595 deletions
|
@ -3,14 +3,10 @@ builders:
|
|||
import: "package:angel_orm_generator/angel_orm_generator.dart"
|
||||
builder_factories:
|
||||
- ormBuilder
|
||||
#- mongoDBOrmBuilder
|
||||
- postgreSqlOrmBuilder
|
||||
auto_apply: root_package
|
||||
build_to: source
|
||||
build_extensions:
|
||||
.dart:
|
||||
- ".orm.g.dart"
|
||||
- ".mongodb.orm.g.dart"
|
||||
- ".mysql.orm.g.dart"
|
||||
- ".rethinkdb.orm.g.dart"
|
||||
- ".postgresql.orm.g.dart"
|
||||
- ".angel_orm.g.part"
|
||||
applies_builders:
|
||||
["source_gen|combining_builder", "source_gen|part_cleanup"]
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
//export 'src/mongodb_orm_generator.dart';
|
||||
export 'src/orm_build_context.dart';
|
||||
export 'src/orm_generator.dart';
|
||||
export 'src/postgresql_orm_generator.dart';
|
||||
export 'src/readers.dart';
|
|
@ -1,45 +0,0 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:angel_orm/angel_orm.dart';
|
||||
import 'package:build/build.dart';
|
||||
import 'package:code_builder/code_builder.dart' hide LibraryBuilder;
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:source_gen/source_gen.dart';
|
||||
|
||||
import 'orm_build_context.dart';
|
||||
|
||||
Builder mongoDBOrmBuilder(_) {
|
||||
return new LibraryBuilder(new MongoDBOrmGenerator(),
|
||||
generatedExtension: '.mongodb.orm.g.dart');
|
||||
}
|
||||
|
||||
/// Builder that generates `.orm.g.dart`, with an abstract `FooOrm` class.
|
||||
class MongoDBOrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||
final bool autoSnakeCaseNames;
|
||||
final bool autoIdAndDateFields;
|
||||
|
||||
MongoDBOrmGenerator({this.autoSnakeCaseNames, this.autoIdAndDateFields});
|
||||
|
||||
@override
|
||||
Future<String> generateForAnnotatedElement(
|
||||
Element element, ConstantReader annotation, BuildStep buildStep) async {
|
||||
if (element is ClassElement) {
|
||||
var ctx = await buildOrmContext(element, annotation, buildStep,
|
||||
buildStep.resolver, autoSnakeCaseNames, autoIdAndDateFields);
|
||||
var lib = buildOrmLibrary(buildStep.inputId, ctx);
|
||||
return lib.accept(new DartEmitter()).toString();
|
||||
} else {
|
||||
throw 'The @Orm() annotation can only be applied to classes.';
|
||||
}
|
||||
}
|
||||
|
||||
Library buildOrmLibrary(AssetId inputId, OrmBuildContext ctx) {
|
||||
return new Library((lib) {
|
||||
// Add part of
|
||||
var libFile =
|
||||
p.setExtension(p.basename(inputId.uri.path), '.orm.g.dart');
|
||||
lib.body.add(new Code("part of '$libFile';"));
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,18 +1,19 @@
|
|||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:angel_orm/angel_orm.dart';
|
||||
import 'package:angel_serialize_generator/angel_serialize_generator.dart';
|
||||
import 'package:build/build.dart';
|
||||
import 'package:code_builder/code_builder.dart' hide LibraryBuilder;
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:recase/recase.dart';
|
||||
import 'package:source_gen/source_gen.dart';
|
||||
|
||||
import 'orm_build_context.dart';
|
||||
|
||||
Builder ormBuilder(_) {
|
||||
return new LibraryBuilder(new OrmGenerator(),
|
||||
generatedExtension: '.orm.g.dart');
|
||||
Builder ormBuilder(BuilderOptions options) {
|
||||
return new SharedPartBuilder([
|
||||
new OrmGenerator(
|
||||
autoSnakeCaseNames: options.config['auto_snake_case_names'] != false,
|
||||
autoIdAndDateFields: options.config['auto_id_and_date_fields'] != false)
|
||||
], 'angel_orm');
|
||||
}
|
||||
|
||||
TypeReference futureOf(String type) {
|
||||
|
@ -34,156 +35,151 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
|||
if (element is ClassElement) {
|
||||
var ctx = await buildOrmContext(element, annotation, buildStep,
|
||||
buildStep.resolver, autoSnakeCaseNames, autoIdAndDateFields);
|
||||
var lib = buildOrmBaseLibrary(buildStep.inputId, ctx);
|
||||
var lib = buildOrmLibrary(buildStep.inputId, ctx);
|
||||
return lib.accept(new DartEmitter()).toString();
|
||||
} else {
|
||||
throw 'The @Orm() annotation can only be applied to classes.';
|
||||
}
|
||||
}
|
||||
|
||||
Library buildOrmBaseLibrary(AssetId inputId, OrmBuildContext ctx) {
|
||||
Library buildOrmLibrary(AssetId inputId, OrmBuildContext ctx) {
|
||||
return new Library((lib) {
|
||||
// Necessary imports
|
||||
var imports = new SplayTreeSet<String>.from(
|
||||
['dart:async', p.basename(inputId.uri.path)]);
|
||||
// Create `FooQuery` class
|
||||
// Create `FooQueryWhere` class
|
||||
lib.body.add(buildQueryClass(ctx));
|
||||
lib.body.add(buildWhereClass(ctx));
|
||||
});
|
||||
}
|
||||
|
||||
switch (ctx.ormAnnotation.type) {
|
||||
// case OrmType.mongoDB:
|
||||
// imports.add('package:mongo_dart/mongo_dart.dart');
|
||||
// break;
|
||||
case OrmType.postgreSql:
|
||||
imports.add('package:postgres/postgres.dart');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Class buildQueryClass(OrmBuildContext ctx) {
|
||||
// TODO: Handle relations
|
||||
|
||||
lib.directives.addAll(imports.map((url) => new Directive.import(url)));
|
||||
|
||||
// Add the corresponding `part`
|
||||
String dbExtension;
|
||||
|
||||
switch (ctx.ormAnnotation.type) {
|
||||
// case OrmType.mongoDB:
|
||||
// dbExtension = 'mongodb';
|
||||
// break;
|
||||
case OrmType.rethinkDB:
|
||||
dbExtension = 'rethinkdb';
|
||||
break;
|
||||
case OrmType.mySql:
|
||||
dbExtension = 'mysql';
|
||||
break;
|
||||
case OrmType.postgreSql:
|
||||
dbExtension = 'postgresql';
|
||||
break;
|
||||
default:
|
||||
throw 'Unsupported ORM type: ${ctx.ormAnnotation.type}';
|
||||
}
|
||||
|
||||
var dbFile = p.setExtension(
|
||||
p.basename(inputId.uri.path), '.$dbExtension.orm.g.dart');
|
||||
|
||||
lib.body.add(new Code("part '$dbFile';"));
|
||||
|
||||
// Create `FooOrm` abstract class
|
||||
return new Class((clazz) {
|
||||
var rc = ctx.buildContext.modelClassNameRecase;
|
||||
var queryWhereType = refer('${rc.pascalCase}QueryWhere');
|
||||
clazz
|
||||
..name = '${rc.pascalCase}Query'
|
||||
..extend = new TypeReference((b) {
|
||||
b
|
||||
..symbol = 'Query'
|
||||
..types.addAll([
|
||||
ctx.buildContext.modelClassType,
|
||||
queryWhereType,
|
||||
]);
|
||||
});
|
||||
|
||||
lib.body.add(new Class((clazz) {
|
||||
clazz
|
||||
..name = '${rc.pascalCase}Orm'
|
||||
..abstract = true;
|
||||
|
||||
// Add factory constructors.
|
||||
switch (ctx.ormAnnotation.type) {
|
||||
case OrmType.postgreSql:
|
||||
clazz.constructors.add(new Constructor((b) {
|
||||
b
|
||||
..name = 'postgreSql'
|
||||
..factory = true
|
||||
..redirect = refer('PostgreSql${rc.pascalCase}Orm')
|
||||
..requiredParameters.add(new Parameter((b) {
|
||||
b
|
||||
..name = 'connection'
|
||||
..type = refer('PostgreSQLConnection');
|
||||
}));
|
||||
}));
|
||||
dbExtension = 'postgresql';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Next, add method stubs.
|
||||
// * getAll
|
||||
// * getById
|
||||
// * deleteById
|
||||
// * updateX()
|
||||
// * createX()
|
||||
// * query()
|
||||
|
||||
// getAll
|
||||
clazz.methods.add(new Method((m) {
|
||||
m
|
||||
..name = 'getAll'
|
||||
..returns = new TypeReference((b) => b
|
||||
..symbol = 'Future'
|
||||
..types.add(new TypeReference((b) => b
|
||||
..symbol = 'List'
|
||||
..types.add(ctx.buildContext.modelClassType))));
|
||||
}));
|
||||
|
||||
// getById
|
||||
clazz.methods.add(new Method((m) {
|
||||
m
|
||||
..name = 'getById'
|
||||
..returns = futureOf(ctx.buildContext.modelClassName)
|
||||
..requiredParameters.add(new Parameter((b) => b
|
||||
..name = 'id'
|
||||
..type = refer('String')));
|
||||
}));
|
||||
|
||||
// deleteById
|
||||
clazz.methods.add(new Method((m) {
|
||||
m
|
||||
..name = 'deleteById'
|
||||
..returns = futureOf(ctx.buildContext.modelClassName)
|
||||
..requiredParameters.add(new Parameter((b) => b
|
||||
..name = 'id'
|
||||
..type = refer('String')));
|
||||
}));
|
||||
|
||||
// createX()
|
||||
clazz.methods.add(new Method((m) {
|
||||
m
|
||||
..name = 'create${ctx.buildContext.modelClassName}'
|
||||
..returns = futureOf(ctx.buildContext.modelClassName)
|
||||
..requiredParameters.add(new Parameter((b) => b
|
||||
..name = 'model'
|
||||
..type = ctx.buildContext.modelClassType));
|
||||
}));
|
||||
|
||||
// updateX()
|
||||
clazz.methods.add(new Method((m) {
|
||||
m
|
||||
..name = 'update${ctx.buildContext.modelClassName}'
|
||||
..returns = futureOf(ctx.buildContext.modelClassName)
|
||||
..requiredParameters.add(new Parameter((b) => b
|
||||
..name = 'model'
|
||||
..type = ctx.buildContext.modelClassType));
|
||||
}));
|
||||
|
||||
// query()
|
||||
clazz.methods.add(new Method((m) {
|
||||
m
|
||||
..name = 'query'
|
||||
..returns = refer('${rc.pascalCase}Query');
|
||||
}));
|
||||
// Add tableName
|
||||
clazz.methods.add(new Method((m) {
|
||||
m
|
||||
..name = 'tableName'
|
||||
..annotations.add(refer('override'))
|
||||
..type = MethodType.getter
|
||||
..body = new Block((b) {
|
||||
b.addExpression(literalString(ctx.tableName).returned);
|
||||
});
|
||||
}));
|
||||
|
||||
// Create `FooQuery` class
|
||||
lib.body.add(new Class((clazz) {
|
||||
clazz..name = '${rc.pascalCase}Query';
|
||||
// Add fields getter
|
||||
clazz.methods.add(new Method((m) {
|
||||
m
|
||||
..name = 'fields'
|
||||
..annotations.add(refer('override'))
|
||||
..type = MethodType.getter
|
||||
..body = new Block((b) {
|
||||
var names = ctx.buildContext.fields
|
||||
.map((f) => literalString(f.name))
|
||||
.toList();
|
||||
b.addExpression(literalConstList(names).returned);
|
||||
});
|
||||
}));
|
||||
|
||||
// Add where member
|
||||
clazz.fields.add(new Field((b) {
|
||||
b
|
||||
..annotations.add(refer('override'))
|
||||
..name = 'where'
|
||||
..modifier = FieldModifier.final$
|
||||
..type = queryWhereType
|
||||
..assignment = queryWhereType.newInstance([]).code;
|
||||
}));
|
||||
|
||||
// Add deserialize()
|
||||
clazz.methods.add(new Method((m) {
|
||||
m
|
||||
..name = 'deserialize'
|
||||
..annotations.add(refer('override'))
|
||||
..requiredParameters.add(new Parameter((b) => b
|
||||
..name = 'row'
|
||||
..type = refer('List')))
|
||||
..body = new Block((b) {
|
||||
int i = 0;
|
||||
var args = <String, Expression>{};
|
||||
|
||||
for (var field in ctx.buildContext.fields) {
|
||||
var type = convertTypeReference(field.type);
|
||||
args[field.name] = (refer('row').index(literalNum(i))).asA(type);
|
||||
}
|
||||
|
||||
b.addExpression(
|
||||
ctx.buildContext.modelClassType.newInstance([], args).returned);
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
Class buildWhereClass(OrmBuildContext ctx) {
|
||||
return new Class((clazz) {
|
||||
var rc = ctx.buildContext.modelClassNameRecase;
|
||||
clazz
|
||||
..name = '${rc.pascalCase}QueryWhere'
|
||||
..extend = refer('QueryWhere');
|
||||
|
||||
// Build expressionBuilders getter
|
||||
clazz.methods.add(new Method((m) {
|
||||
m
|
||||
..name = 'expressionBuilders'
|
||||
..annotations.add(refer('override'))
|
||||
..type = MethodType.getter
|
||||
..body = new Block((b) {
|
||||
var references = ctx.buildContext.fields.map((f) => refer(f.name));
|
||||
b.addExpression(literalList(references).returned);
|
||||
});
|
||||
}));
|
||||
|
||||
// Add builders for each field
|
||||
for (var field in ctx.buildContext.fields) {
|
||||
// TODO: Handle fields with relations
|
||||
Reference builderType;
|
||||
|
||||
if (const TypeChecker.fromRuntime(String).isExactlyType(field.type)) {
|
||||
builderType = refer('StringSqlExpressionBuilder');
|
||||
} else if (const TypeChecker.fromRuntime(bool)
|
||||
.isExactlyType(field.type)) {
|
||||
builderType = refer('BooleanSqlExpressionBuilder');
|
||||
} else if (const TypeChecker.fromRuntime(DateTime)
|
||||
.isExactlyType(field.type)) {
|
||||
builderType = refer('DateTimeSqlExpressionBuilder');
|
||||
} else if (const TypeChecker.fromRuntime(int)
|
||||
.isExactlyType(field.type) ||
|
||||
const TypeChecker.fromRuntime(double).isExactlyType(field.type)) {
|
||||
builderType = new TypeReference((b) => b
|
||||
..symbol = 'NumericSqlExpressionBuilder'
|
||||
..types.add(refer(field.type.name)));
|
||||
} else {
|
||||
throw new UnsupportedError(
|
||||
'Cannot generate ORM code for field of type ${field.type.name}.');
|
||||
}
|
||||
|
||||
clazz.fields.add(new Field((b) {
|
||||
b
|
||||
..name = field.name
|
||||
..modifier = FieldModifier.final$
|
||||
..type = builderType
|
||||
..assignment = builderType.newInstance([
|
||||
literalString(ctx.buildContext.resolveFieldName(field.name))
|
||||
]).code;
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,348 +0,0 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:angel_orm/angel_orm.dart';
|
||||
import 'package:angel_serialize_generator/angel_serialize_generator.dart';
|
||||
import 'package:angel_serialize_generator/build_context.dart';
|
||||
import 'package:build/build.dart';
|
||||
import 'package:code_builder/code_builder.dart' hide LibraryBuilder;
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:source_gen/source_gen.dart';
|
||||
|
||||
import 'orm_build_context.dart';
|
||||
|
||||
Builder postgreSqlOrmBuilder(_) {
|
||||
return new LibraryBuilder(new PostgreSqlOrmGenerator(),
|
||||
generatedExtension: '.postgresql.orm.g.dart');
|
||||
}
|
||||
|
||||
/// Builder that generates `.orm.g.dart`, with an abstract `FooOrm` class.
|
||||
class PostgreSqlOrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||
final bool autoSnakeCaseNames;
|
||||
final bool autoIdAndDateFields;
|
||||
|
||||
PostgreSqlOrmGenerator({this.autoSnakeCaseNames, this.autoIdAndDateFields});
|
||||
|
||||
@override
|
||||
Future<String> generateForAnnotatedElement(
|
||||
Element element, ConstantReader annotation, BuildStep buildStep) async {
|
||||
if (element is ClassElement) {
|
||||
var ctx = await buildOrmContext(element, annotation, buildStep,
|
||||
buildStep.resolver, autoSnakeCaseNames, autoIdAndDateFields);
|
||||
var lib = buildOrmLibrary(buildStep.inputId, ctx);
|
||||
return lib.accept(new DartEmitter()).toString();
|
||||
} else {
|
||||
throw 'The @Orm() annotation can only be applied to classes.';
|
||||
}
|
||||
}
|
||||
|
||||
Library buildOrmLibrary(AssetId inputId, OrmBuildContext ctx) {
|
||||
return new Library((lib) {
|
||||
// Add part of
|
||||
var libFile = p.setExtension(p.basename(inputId.uri.path), '.orm.g.dart');
|
||||
lib.body.add(new Code("part of '$libFile';"));
|
||||
|
||||
// Add _PostgresqlFooOrmImpl
|
||||
lib.body.add(buildOrmClass(ctx));
|
||||
});
|
||||
}
|
||||
|
||||
Class buildOrmClass(OrmBuildContext ctx) {
|
||||
return new Class((clazz) {
|
||||
var rc = ctx.buildContext.modelClassNameRecase;
|
||||
clazz
|
||||
..name = 'PostgreSql${rc.pascalCase}Orm'
|
||||
..implements.add(refer('${rc.pascalCase}Orm'))
|
||||
|
||||
// final PostgreSQLConnection connection;
|
||||
..fields.add(new Field((b) {
|
||||
b
|
||||
..modifier = FieldModifier.final$
|
||||
..name = 'connection'
|
||||
..type = refer('PostgreSQLConnection');
|
||||
}))
|
||||
|
||||
// _PostgresqlFooOrmImpl(this.connection);
|
||||
..constructors.add(new Constructor((b) {
|
||||
b
|
||||
..requiredParameters.add(new Parameter((b) => b
|
||||
..name = 'connection'
|
||||
..toThis = true));
|
||||
}))
|
||||
..methods.add(buildParseRowMethod(ctx))
|
||||
..methods.add(buildGetById(ctx))
|
||||
..methods.add(buildDeleteById(ctx))
|
||||
..methods.add(buildGetAll(ctx))
|
||||
..methods.add(buildCreate(ctx))
|
||||
..methods.add(buildUpdate(ctx))
|
||||
..methods.add(buildQuery(ctx));
|
||||
});
|
||||
}
|
||||
|
||||
Method buildQuery(OrmBuildContext ctx) {
|
||||
return new Method((m) {
|
||||
m
|
||||
..name = 'query'
|
||||
..returns = refer('${ctx.buildContext.modelClassName}Query')
|
||||
..body = new Block((b) => b.addExpression(literalNull.returned));
|
||||
});
|
||||
}
|
||||
|
||||
Method buildParseRowMethod(OrmBuildContext ctx) {
|
||||
return new Method((m) {
|
||||
m
|
||||
..name = 'parseRow'
|
||||
..static = true
|
||||
..returns = ctx.buildContext.modelClassType
|
||||
..requiredParameters.add(new Parameter((b) => b
|
||||
..name = 'row'
|
||||
..type = refer('List')))
|
||||
..body = new Block((b) {
|
||||
var args = <String, Expression>{};
|
||||
|
||||
for (int i = 0; i < ctx.buildContext.fields.length; i++) {
|
||||
var field = ctx.buildContext.fields[i];
|
||||
args[field.name] = refer('row')
|
||||
.index(literalNum(i))
|
||||
.asA(convertTypeReference(field.type));
|
||||
}
|
||||
|
||||
var returnValue =
|
||||
ctx.buildContext.modelClassType.newInstance([], args);
|
||||
b.addExpression(returnValue.returned);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
String buildFieldString(OrmBuildContext ctx) {
|
||||
var queryString = new StringBuffer();
|
||||
int i = 0;
|
||||
|
||||
for (var field in ctx.buildContext.fields) {
|
||||
if (i++ > 0) queryString.write(',');
|
||||
queryString.write(' ' + ctx.buildContext.resolveFieldName(field.name));
|
||||
}
|
||||
return queryString.toString();
|
||||
}
|
||||
|
||||
String buildQuotedFieldString(OrmBuildContext ctx) {
|
||||
var queryString = new StringBuffer();
|
||||
int i = 0;
|
||||
|
||||
for (var field in ctx.buildContext.fields) {
|
||||
if (i++ > 0) queryString.write(',');
|
||||
queryString
|
||||
.write(' "' + ctx.buildContext.resolveFieldName(field.name) + '"');
|
||||
}
|
||||
return queryString.toString();
|
||||
}
|
||||
|
||||
String buildInsertionValueString(OrmBuildContext ctx) {
|
||||
var buf = new StringBuffer('(');
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (var field in ctx.buildContext.fields) {
|
||||
if (i++ > 0) buf.write(',');
|
||||
if (dateTimeTypeChecker.isAssignableFromType(field.type))
|
||||
buf.write(
|
||||
'CAST (@${field.name} AS ${ctx.columns[field.name].type.name})');
|
||||
else
|
||||
buf.write('@${field.name}');
|
||||
}
|
||||
|
||||
return buf.toString() + ')';
|
||||
}
|
||||
|
||||
Expression buildSubstitutionValues(OrmBuildContext ctx) {
|
||||
var values = <Expression, Expression>{};
|
||||
|
||||
for (var field in ctx.buildContext.fields) {
|
||||
values[literalString(field.name)] = refer('model').property(field.name);
|
||||
}
|
||||
|
||||
return literalMap(values);
|
||||
}
|
||||
|
||||
void applyQuery(
|
||||
BlockBuilder b, String queryString, Expression substitutionValues) {
|
||||
b.statements.add(refer('connection')
|
||||
.property('query')
|
||||
.call(
|
||||
[literalString(queryString)],
|
||||
substitutionValues == null
|
||||
? {}
|
||||
: {'substitutionValues': substitutionValues})
|
||||
.awaited
|
||||
.assignVar('r')
|
||||
.statement);
|
||||
}
|
||||
|
||||
void applyQueryAndReturnOne(
|
||||
BlockBuilder b, String queryString, Expression substitutionValues) {
|
||||
applyQuery(b, queryString, substitutionValues);
|
||||
b.addExpression(
|
||||
(refer('parseRow').call([refer('r').property('first')])).returned);
|
||||
}
|
||||
|
||||
void applyQueryAndReturnList(
|
||||
BlockBuilder b, String queryString, Expression substitutionValues) {
|
||||
applyQuery(b, queryString, substitutionValues);
|
||||
b.statements.add(new Code('return r.map(parseRow).toList();'));
|
||||
}
|
||||
|
||||
Method buildGetById(OrmBuildContext ctx) {
|
||||
/*
|
||||
@override
|
||||
Future<Author> getById(id) async {
|
||||
var r = await connection.query('');
|
||||
return parseRow(r.first);
|
||||
}
|
||||
*/
|
||||
return new Method((m) {
|
||||
m
|
||||
..name = 'getById'
|
||||
..annotations.add(refer('override'))
|
||||
..modifier = MethodModifier.async
|
||||
..requiredParameters.add(new Parameter((b) => b
|
||||
..name = 'id'
|
||||
..type = refer('String')))
|
||||
..returns = new TypeReference((b) => b
|
||||
..symbol = 'Future'
|
||||
..types.add(ctx.buildContext.modelClassType))
|
||||
..body = new Block((b) {
|
||||
var fields = buildFieldString(ctx);
|
||||
var queryString =
|
||||
'SELECT $fields FROM "${ctx.tableName}" WHERE id = @id LIMIT 1;';
|
||||
applyQueryAndReturnOne(
|
||||
b,
|
||||
queryString,
|
||||
literalMap({
|
||||
'id': refer('int').property('parse').call([refer('id')])
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Method buildDeleteById(OrmBuildContext ctx) {
|
||||
/*
|
||||
@override
|
||||
Future<Author> getById(id) async {
|
||||
var r = await connection.query('');
|
||||
return parseRow(r.first);
|
||||
}
|
||||
*/
|
||||
return new Method((m) {
|
||||
m
|
||||
..name = 'deleteById'
|
||||
..annotations.add(refer('override'))
|
||||
..modifier = MethodModifier.async
|
||||
..requiredParameters.add(new Parameter((b) => b
|
||||
..name = 'id'
|
||||
..type = refer('String')))
|
||||
..returns = new TypeReference((b) => b
|
||||
..symbol = 'Future'
|
||||
..types.add(ctx.buildContext.modelClassType))
|
||||
..body = new Block((b) {
|
||||
var fields = buildQuotedFieldString(ctx);
|
||||
var queryString =
|
||||
'DELETE FROM "${ctx.tableName}" WHERE id = @id RETURNING $fields;';
|
||||
applyQueryAndReturnOne(
|
||||
b,
|
||||
queryString,
|
||||
literalMap({
|
||||
'id': refer('int').property('parse').call([refer('id')])
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Method buildGetAll(OrmBuildContext ctx) {
|
||||
/*
|
||||
@override
|
||||
Future<List<Author>> getAll() async {
|
||||
var r = await connection
|
||||
.query('SELECT id, name, created_at, updated_at FROM "authors";');
|
||||
return r.map(parseRow).toList();
|
||||
}
|
||||
*/
|
||||
return new Method((method) {
|
||||
method
|
||||
..name = 'getAll'
|
||||
..modifier = MethodModifier.async
|
||||
..returns = refer('Future<List<${ctx.buildContext.modelClassName}>>')
|
||||
..annotations.add(refer('override'))
|
||||
..body = new Block((block) {
|
||||
var fields = buildFieldString(ctx);
|
||||
var queryString = 'SELECT $fields FROM "${ctx.tableName}";';
|
||||
applyQueryAndReturnList(block, queryString, null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Method buildCreate(OrmBuildContext ctx) {
|
||||
/*
|
||||
@override
|
||||
Future<Author> createAuthor(Author model) async {
|
||||
// ...
|
||||
}
|
||||
*/
|
||||
return new Method((method) {
|
||||
method
|
||||
..name = 'create${ctx.buildContext.modelClassName}'
|
||||
..modifier = MethodModifier.async
|
||||
..annotations.add(refer('override'))
|
||||
..returns = refer('Future<${ctx.buildContext.modelClassName}>')
|
||||
..requiredParameters.add(new Parameter((b) => b
|
||||
..name = 'model'
|
||||
..type = ctx.buildContext.modelClassType))
|
||||
..body = new Block((block) {
|
||||
if (ctx.buildContext.autoIdAndDateFields != false) {
|
||||
// If we are auto-managing created+updated at, do so now
|
||||
block.statements.add(new Code(
|
||||
'model = model.copyWith(createdAt: new DateTime.now(), updatedAt: new DateTime.now());'));
|
||||
}
|
||||
|
||||
var fields = buildQuotedFieldString(ctx);
|
||||
var fieldSet = buildInsertionValueString(ctx);
|
||||
var queryString =
|
||||
'INSERT INTO "${ctx.tableName}" ($fields) VALUES $fieldSet RETURNING $fields;';
|
||||
applyQueryAndReturnOne(
|
||||
block, queryString, buildSubstitutionValues(ctx));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Method buildUpdate(OrmBuildContext ctx) {
|
||||
/*
|
||||
@override
|
||||
Future<Author> updateAuthor(Author model) async {
|
||||
// ...
|
||||
}
|
||||
*/
|
||||
return new Method((method) {
|
||||
method
|
||||
..name = 'update${ctx.buildContext.modelClassName}'
|
||||
..modifier = MethodModifier.async
|
||||
..annotations.add(refer('override'))
|
||||
..returns = refer('Future<${ctx.buildContext.modelClassName}>')
|
||||
..requiredParameters.add(new Parameter((b) => b
|
||||
..name = 'model'
|
||||
..type = ctx.buildContext.modelClassType))
|
||||
..body = new Block((block) {
|
||||
if (ctx.buildContext.autoIdAndDateFields != false) {
|
||||
// If we are auto-managing created+updated at, do so now
|
||||
block.statements.add(new Code(
|
||||
'model = model.copyWith(updatedAt: new DateTime.now());'));
|
||||
}
|
||||
|
||||
var fields = buildQuotedFieldString(ctx);
|
||||
var fieldSet = buildInsertionValueString(ctx);
|
||||
var queryString =
|
||||
'UPDATE "${ctx.tableName}" SET ($fields) = $fieldSet RETURNING $fields;';
|
||||
applyQueryAndReturnOne(
|
||||
block, queryString, buildSubstitutionValues(ctx));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -5,10 +5,7 @@ import 'package:source_gen/source_gen.dart';
|
|||
const TypeChecker columnTypeChecker = const TypeChecker.fromRuntime(Column);
|
||||
|
||||
Orm reviveORMAnnotation(ConstantReader reader) {
|
||||
return Orm(
|
||||
OrmType.values[reader.read('type').objectValue.getField('index').toIntValue()],
|
||||
tableName: reader.peek('tableName')?.stringValue,
|
||||
);
|
||||
return Orm(tableName: reader.peek('tableName')?.stringValue);
|
||||
}
|
||||
|
||||
class ColumnReader {
|
||||
|
|
|
@ -8,7 +8,7 @@ environment:
|
|||
dependencies:
|
||||
angel_orm: ^2.0.0-dev
|
||||
angel_serialize_generator: ^2.0.0
|
||||
build: ^0.12.0
|
||||
build: ">=0.12.0 <2.0.0"
|
||||
build_config: ^0.3.0
|
||||
code_builder: ^3.0.0
|
||||
inflection:
|
||||
|
@ -23,6 +23,6 @@ dev_dependencies:
|
|||
angel_framework: ^2.0.0-alpha
|
||||
#angel_migration: ^1.0.0-alpha
|
||||
#angel_test: ^1.0.0
|
||||
build_runner: ^0.10.0
|
||||
build_runner: ^1.0.0
|
||||
postgres: ^1.0.0
|
||||
test: ^1.0.0
|
||||
|
|
|
@ -9,7 +9,7 @@ part 'author.g.dart';
|
|||
part 'author.serializer.g.dart';
|
||||
|
||||
@serializable
|
||||
@postgreSqlOrm
|
||||
@orm
|
||||
class _Author extends Model {
|
||||
@Column(length: 255, indexType: IndexType.unique, defaultValue: 'Tobe Osakwe')
|
||||
String name;
|
||||
|
|
|
@ -2,6 +2,52 @@
|
|||
|
||||
part of angel_orm.generator.models.author;
|
||||
|
||||
// **************************************************************************
|
||||
// OrmGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class AuthorQuery extends Query<Author, AuthorQueryWhere> {
|
||||
@override
|
||||
final AuthorQueryWhere where = new AuthorQueryWhere();
|
||||
|
||||
@override
|
||||
get tableName {
|
||||
return 'authors';
|
||||
}
|
||||
|
||||
@override
|
||||
get fields {
|
||||
return const ['id', 'name', 'createdAt', 'updatedAt'];
|
||||
}
|
||||
|
||||
@override
|
||||
deserialize(List row) {
|
||||
return new Author(
|
||||
id: (row[0] as String),
|
||||
name: (row[0] as String),
|
||||
createdAt: (row[0] as DateTime),
|
||||
updatedAt: (row[0] as DateTime));
|
||||
}
|
||||
}
|
||||
|
||||
class AuthorQueryWhere extends QueryWhere {
|
||||
final StringSqlExpressionBuilder id = new StringSqlExpressionBuilder('id');
|
||||
|
||||
final StringSqlExpressionBuilder name =
|
||||
new StringSqlExpressionBuilder('name');
|
||||
|
||||
final DateTimeSqlExpressionBuilder createdAt =
|
||||
new DateTimeSqlExpressionBuilder('created_at');
|
||||
|
||||
final DateTimeSqlExpressionBuilder updatedAt =
|
||||
new DateTimeSqlExpressionBuilder('updated_at');
|
||||
|
||||
@override
|
||||
get expressionBuilders {
|
||||
return [id, name, createdAt, updatedAt];
|
||||
}
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonModelGenerator
|
||||
// **************************************************************************
|
||||
|
@ -39,6 +85,11 @@ class Author extends _Author {
|
|||
other.updatedAt == updatedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return hashObjects([id, name, createdAt, updatedAt]);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return AuthorSerializer.toMap(this);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ part 'book.g.dart';
|
|||
part 'book.serializer.g.dart';
|
||||
|
||||
@serializable
|
||||
@postgreSqlOrm
|
||||
@orm
|
||||
class _Book extends Model {
|
||||
@belongsTo
|
||||
Author author;
|
||||
|
|
|
@ -67,6 +67,12 @@ class Book extends _Book {
|
|||
other.updatedAt == updatedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return hashObjects(
|
||||
[id, author, partnerAuthor, authorId, name, createdAt, updatedAt]);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return BookSerializer.toMap(this);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ part 'car.g.dart';
|
|||
part 'car.serializer.g.dart';
|
||||
|
||||
@serializable
|
||||
@postgreSqlOrm
|
||||
@orm
|
||||
class _Car extends Model {
|
||||
String make;
|
||||
String description;
|
||||
|
|
|
@ -2,6 +2,80 @@
|
|||
|
||||
part of angel_orm.generator.models.car;
|
||||
|
||||
// **************************************************************************
|
||||
// OrmGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class CarQuery extends Query<Car, CarQueryWhere> {
|
||||
@override
|
||||
final CarQueryWhere where = new CarQueryWhere();
|
||||
|
||||
@override
|
||||
get tableName {
|
||||
return 'cars';
|
||||
}
|
||||
|
||||
@override
|
||||
get fields {
|
||||
return const [
|
||||
'id',
|
||||
'make',
|
||||
'description',
|
||||
'familyFriendly',
|
||||
'recalledAt',
|
||||
'createdAt',
|
||||
'updatedAt'
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
deserialize(List row) {
|
||||
return new Car(
|
||||
id: (row[0] as String),
|
||||
make: (row[0] as String),
|
||||
description: (row[0] as String),
|
||||
familyFriendly: (row[0] as bool),
|
||||
recalledAt: (row[0] as DateTime),
|
||||
createdAt: (row[0] as DateTime),
|
||||
updatedAt: (row[0] as DateTime));
|
||||
}
|
||||
}
|
||||
|
||||
class CarQueryWhere extends QueryWhere {
|
||||
final StringSqlExpressionBuilder id = new StringSqlExpressionBuilder('id');
|
||||
|
||||
final StringSqlExpressionBuilder make =
|
||||
new StringSqlExpressionBuilder('make');
|
||||
|
||||
final StringSqlExpressionBuilder description =
|
||||
new StringSqlExpressionBuilder('description');
|
||||
|
||||
final BooleanSqlExpressionBuilder familyFriendly =
|
||||
new BooleanSqlExpressionBuilder('family_friendly');
|
||||
|
||||
final DateTimeSqlExpressionBuilder recalledAt =
|
||||
new DateTimeSqlExpressionBuilder('recalled_at');
|
||||
|
||||
final DateTimeSqlExpressionBuilder createdAt =
|
||||
new DateTimeSqlExpressionBuilder('created_at');
|
||||
|
||||
final DateTimeSqlExpressionBuilder updatedAt =
|
||||
new DateTimeSqlExpressionBuilder('updated_at');
|
||||
|
||||
@override
|
||||
get expressionBuilders {
|
||||
return [
|
||||
id,
|
||||
make,
|
||||
description,
|
||||
familyFriendly,
|
||||
recalledAt,
|
||||
createdAt,
|
||||
updatedAt
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonModelGenerator
|
||||
// **************************************************************************
|
||||
|
@ -67,6 +141,19 @@ class Car extends _Car {
|
|||
other.updatedAt == updatedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return hashObjects([
|
||||
id,
|
||||
make,
|
||||
description,
|
||||
familyFriendly,
|
||||
recalledAt,
|
||||
createdAt,
|
||||
updatedAt
|
||||
]);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return CarSerializer.toMap(this);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import 'package:angel_serialize/angel_serialize.dart';
|
|||
part 'customer.g.dart';
|
||||
part 'customer.serializer.g.dart';
|
||||
|
||||
@postgreSqlOrm
|
||||
@orm
|
||||
@serializable
|
||||
class _Customer extends Model {
|
||||
}
|
|
@ -2,6 +2,48 @@
|
|||
|
||||
part of angel_orm_generator.test.models.customer;
|
||||
|
||||
// **************************************************************************
|
||||
// OrmGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class CustomerQuery extends Query<Customer, CustomerQueryWhere> {
|
||||
@override
|
||||
final CustomerQueryWhere where = new CustomerQueryWhere();
|
||||
|
||||
@override
|
||||
get tableName {
|
||||
return 'customers';
|
||||
}
|
||||
|
||||
@override
|
||||
get fields {
|
||||
return const ['id', 'createdAt', 'updatedAt'];
|
||||
}
|
||||
|
||||
@override
|
||||
deserialize(List row) {
|
||||
return new Customer(
|
||||
id: (row[0] as String),
|
||||
createdAt: (row[0] as DateTime),
|
||||
updatedAt: (row[0] as DateTime));
|
||||
}
|
||||
}
|
||||
|
||||
class CustomerQueryWhere extends QueryWhere {
|
||||
final StringSqlExpressionBuilder id = new StringSqlExpressionBuilder('id');
|
||||
|
||||
final DateTimeSqlExpressionBuilder createdAt =
|
||||
new DateTimeSqlExpressionBuilder('created_at');
|
||||
|
||||
final DateTimeSqlExpressionBuilder updatedAt =
|
||||
new DateTimeSqlExpressionBuilder('updated_at');
|
||||
|
||||
@override
|
||||
get expressionBuilders {
|
||||
return [id, createdAt, updatedAt];
|
||||
}
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonModelGenerator
|
||||
// **************************************************************************
|
||||
|
@ -33,6 +75,11 @@ class Customer extends _Customer {
|
|||
other.updatedAt == updatedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return hashObjects([id, createdAt, updatedAt]);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return CustomerSerializer.toMap(this);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ part 'foot.g.dart';
|
|||
part 'foot.serializer.g.dart';
|
||||
|
||||
@serializable
|
||||
@postgreSqlOrm
|
||||
@orm
|
||||
class _Foot extends Model {
|
||||
int legId, nToes;
|
||||
}
|
|
@ -2,6 +2,56 @@
|
|||
|
||||
part of angel_orm_generator.test.models.foot;
|
||||
|
||||
// **************************************************************************
|
||||
// OrmGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class FootQuery extends Query<Foot, FootQueryWhere> {
|
||||
@override
|
||||
final FootQueryWhere where = new FootQueryWhere();
|
||||
|
||||
@override
|
||||
get tableName {
|
||||
return 'foots';
|
||||
}
|
||||
|
||||
@override
|
||||
get fields {
|
||||
return const ['id', 'legId', 'nToes', 'createdAt', 'updatedAt'];
|
||||
}
|
||||
|
||||
@override
|
||||
deserialize(List row) {
|
||||
return new Foot(
|
||||
id: (row[0] as String),
|
||||
legId: (row[0] as int),
|
||||
nToes: (row[0] as int),
|
||||
createdAt: (row[0] as DateTime),
|
||||
updatedAt: (row[0] as DateTime));
|
||||
}
|
||||
}
|
||||
|
||||
class FootQueryWhere extends QueryWhere {
|
||||
final StringSqlExpressionBuilder id = new StringSqlExpressionBuilder('id');
|
||||
|
||||
final NumericSqlExpressionBuilder<int> legId =
|
||||
new NumericSqlExpressionBuilder<int>('leg_id');
|
||||
|
||||
final NumericSqlExpressionBuilder<int> nToes =
|
||||
new NumericSqlExpressionBuilder<int>('n_toes');
|
||||
|
||||
final DateTimeSqlExpressionBuilder createdAt =
|
||||
new DateTimeSqlExpressionBuilder('created_at');
|
||||
|
||||
final DateTimeSqlExpressionBuilder updatedAt =
|
||||
new DateTimeSqlExpressionBuilder('updated_at');
|
||||
|
||||
@override
|
||||
get expressionBuilders {
|
||||
return [id, legId, nToes, createdAt, updatedAt];
|
||||
}
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonModelGenerator
|
||||
// **************************************************************************
|
||||
|
@ -48,6 +98,11 @@ class Foot extends _Foot {
|
|||
other.updatedAt == updatedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return hashObjects([id, legId, nToes, createdAt, updatedAt]);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return FootSerializer.toMap(this);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ part 'fruit.g.dart';
|
|||
part 'fruit.serializer.g.dart';
|
||||
|
||||
@serializable
|
||||
@postgreSqlOrm
|
||||
@orm
|
||||
class _Fruit extends Model {
|
||||
int treeId;
|
||||
String commonName;
|
||||
|
|
|
@ -2,6 +2,56 @@
|
|||
|
||||
part of angel_orm_generator.test.models.fruit;
|
||||
|
||||
// **************************************************************************
|
||||
// OrmGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class FruitQuery extends Query<Fruit, FruitQueryWhere> {
|
||||
@override
|
||||
final FruitQueryWhere where = new FruitQueryWhere();
|
||||
|
||||
@override
|
||||
get tableName {
|
||||
return 'fruits';
|
||||
}
|
||||
|
||||
@override
|
||||
get fields {
|
||||
return const ['id', 'treeId', 'commonName', 'createdAt', 'updatedAt'];
|
||||
}
|
||||
|
||||
@override
|
||||
deserialize(List row) {
|
||||
return new Fruit(
|
||||
id: (row[0] as String),
|
||||
treeId: (row[0] as int),
|
||||
commonName: (row[0] as String),
|
||||
createdAt: (row[0] as DateTime),
|
||||
updatedAt: (row[0] as DateTime));
|
||||
}
|
||||
}
|
||||
|
||||
class FruitQueryWhere extends QueryWhere {
|
||||
final StringSqlExpressionBuilder id = new StringSqlExpressionBuilder('id');
|
||||
|
||||
final NumericSqlExpressionBuilder<int> treeId =
|
||||
new NumericSqlExpressionBuilder<int>('tree_id');
|
||||
|
||||
final StringSqlExpressionBuilder commonName =
|
||||
new StringSqlExpressionBuilder('common_name');
|
||||
|
||||
final DateTimeSqlExpressionBuilder createdAt =
|
||||
new DateTimeSqlExpressionBuilder('created_at');
|
||||
|
||||
final DateTimeSqlExpressionBuilder updatedAt =
|
||||
new DateTimeSqlExpressionBuilder('updated_at');
|
||||
|
||||
@override
|
||||
get expressionBuilders {
|
||||
return [id, treeId, commonName, createdAt, updatedAt];
|
||||
}
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonModelGenerator
|
||||
// **************************************************************************
|
||||
|
@ -49,6 +99,11 @@ class Fruit extends _Fruit {
|
|||
other.updatedAt == updatedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return hashObjects([id, treeId, commonName, createdAt, updatedAt]);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return FruitSerializer.toMap(this);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ part 'leg.g.dart';
|
|||
part 'leg.serializer.g.dart';
|
||||
|
||||
@serializable
|
||||
@postgreSqlOrm
|
||||
@orm
|
||||
class _Leg extends Model {
|
||||
@hasOne
|
||||
Foot foot;
|
||||
|
|
|
@ -48,6 +48,11 @@ class Leg extends _Leg {
|
|||
other.updatedAt == updatedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return hashObjects([id, foot, name, createdAt, updatedAt]);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return LegSerializer.toMap(this);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import 'customer.dart';
|
|||
part 'order.g.dart';
|
||||
part 'order.serializer.g.dart';
|
||||
|
||||
@postgreSqlOrm
|
||||
@orm
|
||||
@serializable
|
||||
class _Order extends Model {
|
||||
@Join(Customer, CustomerFields.id)
|
||||
|
|
|
@ -2,6 +2,80 @@
|
|||
|
||||
part of angel_orm_generator.test.models.order;
|
||||
|
||||
// **************************************************************************
|
||||
// OrmGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class OrderQuery extends Query<Order, OrderQueryWhere> {
|
||||
@override
|
||||
final OrderQueryWhere where = new OrderQueryWhere();
|
||||
|
||||
@override
|
||||
get tableName {
|
||||
return 'orders';
|
||||
}
|
||||
|
||||
@override
|
||||
get fields {
|
||||
return const [
|
||||
'id',
|
||||
'customerId',
|
||||
'employeeId',
|
||||
'orderDate',
|
||||
'shipperId',
|
||||
'createdAt',
|
||||
'updatedAt'
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
deserialize(List row) {
|
||||
return new Order(
|
||||
id: (row[0] as String),
|
||||
customerId: (row[0] as int),
|
||||
employeeId: (row[0] as int),
|
||||
orderDate: (row[0] as DateTime),
|
||||
shipperId: (row[0] as int),
|
||||
createdAt: (row[0] as DateTime),
|
||||
updatedAt: (row[0] as DateTime));
|
||||
}
|
||||
}
|
||||
|
||||
class OrderQueryWhere extends QueryWhere {
|
||||
final StringSqlExpressionBuilder id = new StringSqlExpressionBuilder('id');
|
||||
|
||||
final NumericSqlExpressionBuilder<int> customerId =
|
||||
new NumericSqlExpressionBuilder<int>('customer_id');
|
||||
|
||||
final NumericSqlExpressionBuilder<int> employeeId =
|
||||
new NumericSqlExpressionBuilder<int>('employee_id');
|
||||
|
||||
final DateTimeSqlExpressionBuilder orderDate =
|
||||
new DateTimeSqlExpressionBuilder('order_date');
|
||||
|
||||
final NumericSqlExpressionBuilder<int> shipperId =
|
||||
new NumericSqlExpressionBuilder<int>('shipper_id');
|
||||
|
||||
final DateTimeSqlExpressionBuilder createdAt =
|
||||
new DateTimeSqlExpressionBuilder('created_at');
|
||||
|
||||
final DateTimeSqlExpressionBuilder updatedAt =
|
||||
new DateTimeSqlExpressionBuilder('updated_at');
|
||||
|
||||
@override
|
||||
get expressionBuilders {
|
||||
return [
|
||||
id,
|
||||
customerId,
|
||||
employeeId,
|
||||
orderDate,
|
||||
shipperId,
|
||||
createdAt,
|
||||
updatedAt
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonModelGenerator
|
||||
// **************************************************************************
|
||||
|
@ -67,6 +141,19 @@ class Order extends _Order {
|
|||
other.updatedAt == updatedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return hashObjects([
|
||||
id,
|
||||
customerId,
|
||||
employeeId,
|
||||
orderDate,
|
||||
shipperId,
|
||||
createdAt,
|
||||
updatedAt
|
||||
]);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return OrderSerializer.toMap(this);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ part 'role.g.dart';
|
|||
part 'role.serializer.g.dart';
|
||||
|
||||
@serializable
|
||||
@postgreSqlOrm
|
||||
@orm
|
||||
class _Role extends Model {
|
||||
String name;
|
||||
}
|
|
@ -2,6 +2,52 @@
|
|||
|
||||
part of angel_orm_generator.test.models.role;
|
||||
|
||||
// **************************************************************************
|
||||
// OrmGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class RoleQuery extends Query<Role, RoleQueryWhere> {
|
||||
@override
|
||||
final RoleQueryWhere where = new RoleQueryWhere();
|
||||
|
||||
@override
|
||||
get tableName {
|
||||
return 'roles';
|
||||
}
|
||||
|
||||
@override
|
||||
get fields {
|
||||
return const ['id', 'name', 'createdAt', 'updatedAt'];
|
||||
}
|
||||
|
||||
@override
|
||||
deserialize(List row) {
|
||||
return new Role(
|
||||
id: (row[0] as String),
|
||||
name: (row[0] as String),
|
||||
createdAt: (row[0] as DateTime),
|
||||
updatedAt: (row[0] as DateTime));
|
||||
}
|
||||
}
|
||||
|
||||
class RoleQueryWhere extends QueryWhere {
|
||||
final StringSqlExpressionBuilder id = new StringSqlExpressionBuilder('id');
|
||||
|
||||
final StringSqlExpressionBuilder name =
|
||||
new StringSqlExpressionBuilder('name');
|
||||
|
||||
final DateTimeSqlExpressionBuilder createdAt =
|
||||
new DateTimeSqlExpressionBuilder('created_at');
|
||||
|
||||
final DateTimeSqlExpressionBuilder updatedAt =
|
||||
new DateTimeSqlExpressionBuilder('updated_at');
|
||||
|
||||
@override
|
||||
get expressionBuilders {
|
||||
return [id, name, createdAt, updatedAt];
|
||||
}
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonModelGenerator
|
||||
// **************************************************************************
|
||||
|
@ -39,6 +85,11 @@ class Role extends _Role {
|
|||
other.updatedAt == updatedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return hashObjects([id, name, createdAt, updatedAt]);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return RoleSerializer.toMap(this);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ part 'tree.g.dart';
|
|||
part 'tree.serializer.g.dart';
|
||||
|
||||
@serializable
|
||||
@postgreSqlOrm
|
||||
@orm
|
||||
class _Tree extends Model {
|
||||
@Column(indexType: IndexType.unique, type: ColumnType.smallInt)
|
||||
int rings;
|
||||
|
|
|
@ -55,6 +55,11 @@ class Tree extends _Tree {
|
|||
other.updatedAt == updatedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return hashObjects([id, rings, fruits, createdAt, updatedAt]);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return TreeSerializer.toMap(this);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ part 'user.g.dart';
|
|||
part 'user.serializer.g.dart';
|
||||
|
||||
@serializable
|
||||
@postgreSqlOrm
|
||||
@orm
|
||||
class _User extends Model {
|
||||
String username, password, email;
|
||||
|
||||
|
|
|
@ -69,6 +69,12 @@ class User extends _User {
|
|||
other.updatedAt == updatedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return hashObjects(
|
||||
[id, username, password, email, roles, createdAt, updatedAt]);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return UserSerializer.toMap(this);
|
||||
}
|
||||
|
|
|
@ -5,18 +5,17 @@ import 'package:angel_orm/angel_orm.dart';
|
|||
import 'package:postgres/postgres.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'models/car.dart';
|
||||
import 'models/car.orm.g.dart';
|
||||
import 'common.dart';
|
||||
|
||||
final DateTime MILENNIUM = new DateTime.utc(2000, 1, 1);
|
||||
final DateTime y2k = new DateTime.utc(2000, 1, 1);
|
||||
|
||||
main() {
|
||||
test('to where', () {
|
||||
var query = new CarQuery();
|
||||
query.where
|
||||
..familyFriendly.equals(true)
|
||||
..recalledAt.lessThanOrEqualTo(MILENNIUM, includeTime: false);
|
||||
var whereClause = query.where.toWhereClause();
|
||||
..recalledAt.lessThanOrEqualTo(y2k, includeTime: false);
|
||||
var whereClause = query.where.compile(tableName: 'cars');
|
||||
print('Where clause: $whereClause');
|
||||
expect(whereClause,
|
||||
'WHERE cars.family_friendly = TRUE AND cars.recalled_at <= \'2000-01-01\'');
|
||||
|
@ -28,23 +27,20 @@ main() {
|
|||
'Mazda',
|
||||
'CX9',
|
||||
true,
|
||||
dateYmdHms.format(MILENNIUM),
|
||||
dateYmdHms.format(MILENNIUM),
|
||||
dateYmdHms.format(MILENNIUM)
|
||||
dateYmdHms.format(y2k),
|
||||
dateYmdHms.format(y2k),
|
||||
dateYmdHms.format(y2k)
|
||||
];
|
||||
print(row);
|
||||
var car = PostgreSqlCarOrm.parseRow(row);
|
||||
var car = new CarQuery().deserialize(row);
|
||||
print(car.toJson());
|
||||
expect(car.id, '0');
|
||||
expect(car.make, 'Mazda');
|
||||
expect(car.description, 'CX9');
|
||||
expect(car.familyFriendly, true);
|
||||
expect(MILENNIUM.toIso8601String(),
|
||||
startsWith(car.recalledAt.toIso8601String()));
|
||||
expect(MILENNIUM.toIso8601String(),
|
||||
startsWith(car.createdAt.toIso8601String()));
|
||||
expect(MILENNIUM.toIso8601String(),
|
||||
startsWith(car.updatedAt.toIso8601String()));
|
||||
expect(y2k.toIso8601String(), startsWith(car.recalledAt.toIso8601String()));
|
||||
expect(y2k.toIso8601String(), startsWith(car.createdAt.toIso8601String()));
|
||||
expect(y2k.toIso8601String(), startsWith(car.updatedAt.toIso8601String()));
|
||||
});
|
||||
|
||||
group('queries', () {
|
||||
|
@ -56,7 +52,7 @@ main() {
|
|||
|
||||
group('selects', () {
|
||||
test('select all', () async {
|
||||
var cars = await CarQuery.getAll(connection).toList();
|
||||
var cars = await CarQuery.getAll(connection);
|
||||
expect(cars, []);
|
||||
});
|
||||
|
||||
|
@ -72,12 +68,12 @@ main() {
|
|||
|
||||
test('where clause is applied', () async {
|
||||
var query = new CarQuery()..where.familyFriendly.equals(true);
|
||||
var cars = await query.get(connection).toList();
|
||||
var cars = await query.get(connection);
|
||||
expect(cars, isEmpty);
|
||||
|
||||
var sportsCars = new CarQuery()..where.familyFriendly.notEquals(true);
|
||||
cars = await sportsCars.get(connection).toList();
|
||||
print(cars.map((c) => c.toJson()).toList());
|
||||
cars = await sportsCars.get(connection);
|
||||
print(cars.map((c) => c.toJson()));
|
||||
|
||||
var car = cars.first;
|
||||
expect(car.make, ferrari.make);
|
||||
|
@ -93,27 +89,26 @@ main() {
|
|||
query1
|
||||
..union(query2)
|
||||
..unionAll(query3);
|
||||
print(query1.toSql());
|
||||
print(query1.compile());
|
||||
|
||||
var cars = await query1.get(connection).toList();
|
||||
var cars = await query1.get(connection);
|
||||
expect(cars, hasLength(1));
|
||||
});
|
||||
|
||||
test('or clause', () async {
|
||||
var query = new CarQuery()
|
||||
..where.make.like('Fer%')
|
||||
..or(new CarQueryWhere()
|
||||
..familyFriendly.equals(true)
|
||||
..make.equals('Honda'));
|
||||
print(query.toSql());
|
||||
var cars = await query.get(connection).toList();
|
||||
..orWhere((where) =>
|
||||
where..familyFriendly.equals(true)..make.equals('Honda'));
|
||||
print(query.compile());
|
||||
var cars = await query.get(connection);
|
||||
expect(cars, hasLength(1));
|
||||
});
|
||||
|
||||
test('limit obeyed', () async {
|
||||
var query = new CarQuery()..limit = 0;
|
||||
print(query.toSql());
|
||||
var cars = await query.get(connection).toList();
|
||||
var query = new CarQuery()..limit(0);
|
||||
print(query.compile());
|
||||
var cars = await query.get(connection);
|
||||
expect(cars, isEmpty);
|
||||
});
|
||||
|
||||
|
@ -126,28 +121,28 @@ main() {
|
|||
var car = await CarQuery.deleteOne(int.parse(ferrari.id), connection);
|
||||
expect(car.toJson(), ferrari.toJson());
|
||||
|
||||
var cars = await CarQuery.getAll(connection).toList();
|
||||
var cars = await CarQuery.getAll(connection);
|
||||
expect(cars, isEmpty);
|
||||
});
|
||||
|
||||
test('delete stream', () async {
|
||||
var query = new CarQuery()..where.make.equals('Ferrari');
|
||||
query.or(new CarQueryWhere()..familyFriendly.equals(true));
|
||||
print(query.toSql('DELETE FROM "cars"'));
|
||||
var cars = await query.delete(connection).toList();
|
||||
print(query.compile('DELETE FROM "cars"'));
|
||||
var cars = await query.delete(connection);
|
||||
expect(cars, hasLength(1));
|
||||
expect(cars.first.toJson(), ferrari.toJson());
|
||||
});
|
||||
|
||||
test('update', () async {
|
||||
var query = new CarQuery()..where.id.equals(int.parse(ferrari.id));
|
||||
var cars = await query.update(connection, make: 'Hyundai').toList();
|
||||
var cars = await query.update(connection, make: 'Hyundai');
|
||||
expect(cars, hasLength(1));
|
||||
expect(cars.first.make, 'Hyundai');
|
||||
});
|
||||
|
||||
test('update car', () async {
|
||||
var cloned = ferrari.clone()..make = 'Angel';
|
||||
var cloned = ferrari.copyWith(make: 'Angel');
|
||||
var car = await CarQuery.updateCar(connection, cloned);
|
||||
print(car.toJson());
|
||||
expect(car.toJson(), cloned.toJson());
|
||||
|
@ -166,8 +161,7 @@ main() {
|
|||
expect(car.make, 'Honda');
|
||||
expect(car.description, 'Hello');
|
||||
expect(car.familyFriendly, isTrue);
|
||||
expect(
|
||||
dateYmdHms.format(car.recalledAt), dateYmdHms.format(recalledAt));
|
||||
expect(dateYmdHms.format(car.recalledAt), dateYmdHms.format(recalledAt));
|
||||
expect(car.createdAt, allOf(isNotNull, equals(car.updatedAt)));
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue