Detect join type from enum

This commit is contained in:
Tobe O 2019-10-09 12:06:40 -04:00
parent 69106dd0e7
commit 0ae331d38c
7 changed files with 44 additions and 13 deletions

View file

@ -8,6 +8,7 @@ ORM queries to reference their joined subqueries.
* Removed deprecated `Join`, `toSql`, `sanitizeExpression`, `isAscii`.
* Always put `ORDER BY` before `LIMIT`.
* `and`, `or`, `not` in `QueryWhere` include parentheses.
* Add `joinType` to `Relationship` class.
# 2.0.2
* Place `LIMIT` and `OFFSET` after `ORDER BY`.

View file

@ -29,7 +29,7 @@ class HasMany extends Relationship {
String foreignKey,
String foreignTable,
bool cascadeOnDelete = false,
JoinType joinType = JoinType.left})
JoinType joinType})
: super(RelationshipType.hasMany,
localKey: localKey,
foreignKey: foreignKey,
@ -46,7 +46,7 @@ class HasOne extends Relationship {
String foreignKey,
String foreignTable,
bool cascadeOnDelete = false,
JoinType joinType = JoinType.left})
JoinType joinType})
: super(RelationshipType.hasOne,
localKey: localKey,
foreignKey: foreignKey,
@ -62,7 +62,7 @@ class BelongsTo extends Relationship {
{String localKey,
String foreignKey,
String foreignTable,
JoinType joinType = JoinType.left})
JoinType joinType})
: super(RelationshipType.belongsTo,
localKey: localKey,
foreignKey: foreignKey,
@ -80,7 +80,7 @@ class ManyToMany extends Relationship {
String foreignKey,
String foreignTable,
bool cascadeOnDelete = false,
JoinType joinType = JoinType.left})
JoinType joinType})
: super(
RelationshipType.hasMany, // Many-to-Many is actually just a hasMany
localKey: localKey,

View file

@ -1,3 +1,8 @@
# 2.1.0
* Relationships have always generated subqueries; now these subqueries are
available as `Query` objects on generated classes.
* Support explicitly-defined join types for relations.
# 2.0.5
* Remove `ShimFieldImpl` check, which broke relations.
* Fix bug where primary key type would not be emitted in migrations.

View file

@ -3,6 +3,7 @@ import 'dart:async';
import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/constant/value.dart';
import 'package:angel_model/angel_model.dart';
import 'package:angel_orm/angel_orm.dart';
import 'package:angel_serialize/angel_serialize.dart';
@ -240,9 +241,17 @@ Future<OrmBuildContext> buildOrmContext(
var joinType = JoinType.left;
var joinTypeRdr = cr.peek('joinType')?.objectValue;
if (joinTypeRdr != null) {
var idx = joinTypeRdr.getField('index')?.toIntValue();
if (idx != null) {
joinType = JoinType.values[idx];
// Unfortunately, the analyzer library provides little to nothing
// in the way of reading enums from source, so here's a hack.
var joinTypeType = (joinTypeRdr.type as InterfaceType);
var enumFields =
joinTypeType.element.fields.where((f) => f.isEnumConstant).toList();
for (int i = 0; i < enumFields.length; i++) {
if (enumFields[i].constantValue == joinTypeRdr) {
joinType = JoinType.values[i];
break;
}
}
}
@ -255,7 +264,7 @@ Future<OrmBuildContext> buildOrmContext(
through: through,
foreign: foreign,
throughContext: throughContext,
joinType: joinType ?? JoinType.left,
joinType: joinType,
);
// print('Relation on ${buildCtx.originalClassName}.${field.name} => '

View file

@ -327,7 +327,8 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
joinArgs.insert(
0, refer('_$fieldName').assign(queryInstantiation));
b.addExpression(refer('leftJoin').call(joinArgs, {
var joinType = relation.joinTypeString;
b.addExpression(refer(joinType).call(joinArgs, {
'additionalFields':
literalConstList(additionalFields.toList()),
'trampoline': refer('trampoline'),

View file

@ -44,12 +44,27 @@ class RelationshipReader {
this.through,
this.foreign,
this.throughContext,
this.joinType = JoinType.left});
this.joinType});
bool get isManyToMany =>
type == RelationshipType.hasMany && throughContext != null;
String get joinTypeString => joinType.toString().replaceAll('JoinType.', '');
String get joinTypeString {
switch (joinType ?? JoinType.left) {
case JoinType.inner:
return 'join';
case JoinType.left:
return 'leftJoin';
case JoinType.right:
return 'rightJoin';
case JoinType.full:
return 'fullOuterJoin';
case JoinType.self:
return 'selfJoin';
default:
return 'join';
}
}
FieldElement findLocalField(OrmBuildContext ctx) {
return ctx.effectiveFields.firstWhere(

View file

@ -55,11 +55,11 @@ class BookQuery extends Query<Book, BookQueryWhere> {
trampoline ??= Set();
trampoline.add(tableName);
_where = BookQueryWhere(this);
leftJoin(_author = AuthorQuery(trampoline: trampoline, parent: this),
join(_author = AuthorQuery(trampoline: trampoline, parent: this),
'author_id', 'id',
additionalFields: const ['id', 'created_at', 'updated_at', 'name'],
trampoline: trampoline);
leftJoin(_partnerAuthor = AuthorQuery(trampoline: trampoline, parent: this),
join(_partnerAuthor = AuthorQuery(trampoline: trampoline, parent: this),
'partner_author_id', 'id',
additionalFields: const ['id', 'created_at', 'updated_at', 'name'],
trampoline: trampoline);