diff --git a/drift/lib/src/dsl/columns.dart b/drift/lib/src/dsl/columns.dart index 000e948e..f85c51d2 100644 --- a/drift/lib/src/dsl/columns.dart +++ b/drift/lib/src/dsl/columns.dart @@ -409,3 +409,34 @@ class JsonKey { /// generated json. See the documentation for [JsonKey] for details. const JsonKey(this.key); } + +/// Annotation to use on reference columns inside of a [Table] to define the name +/// of the filters and orderings for the reverse relation. +/// +/// Example: +/// ```dart +/// class TodoEntries extends Table { +/// IntColumn get id => integer().autoIncrement()(); +/// TextColumn get body => text()(); +/// @ReferenceName("categories") +/// IntColumn get category => integer().nullable().references(Categories, #id)(); +/// } +/// class Categories extends Table { +/// IntColumn get id => integer().autoIncrement()(); +/// } +/// /// Filter all Categories which contain a TodoEntries with a body of "Todo" +/// categories.filter((f) => f.categories((f) => f.body("Todo"))) +/// +/// ``` +/// When these aren't specified, drift will use the referenced tables name followed by `Refs`. +/// If a reference name clashes with other fields on the table, the generator will show a warning, +/// and filters and orderings wont be generated +class ReferenceName { + /// The name that this reference will use when generating filters and ordering in the reverse direction + /// for [ReferenceName] for details. + final String name; + + /// Annotation to use on reference columns inside of a [Table] to define the name + /// of the filters and orderings for the reverse relation. + const ReferenceName(this.name); +} diff --git a/drift_dev/lib/src/analysis/resolver/dart/column.dart b/drift_dev/lib/src/analysis/resolver/dart/column.dart index ef9b9e4a..68e74608 100644 --- a/drift_dev/lib/src/analysis/resolver/dart/column.dart +++ b/drift_dev/lib/src/analysis/resolver/dart/column.dart @@ -472,6 +472,7 @@ class ColumnParser { documentationComment: docString, constraints: foundConstraints, customConstraints: foundCustomConstraint, + referenceName: _readJsonKey(element), ), referencesColumnInSameTable: referencesColumnInSameTable, ); @@ -507,6 +508,22 @@ class ColumnParser { return object.computeConstantValue()!.getField('key')!.toStringValue(); } + String? _readReferenceName(Element getter) { + final annotations = getter.metadata; + final object = annotations.firstWhereOrNull((e) { + final value = e.computeConstantValue(); + final valueType = value?.type; + + return valueType is InterfaceType && + isFromDrift(valueType) && + valueType.element.name == 'ReferenceName'; + }); + + if (object == null) return null; + + return object.computeConstantValue()!.getField('name')!.toStringValue(); + } + Future> _driftConstraintsFromCustomConstraints({ required bool isNullable, String? customConstraints, diff --git a/drift_dev/lib/src/analysis/results/column.dart b/drift_dev/lib/src/analysis/results/column.dart index bbd150aa..14f23d35 100644 --- a/drift_dev/lib/src/analysis/results/column.dart +++ b/drift_dev/lib/src/analysis/results/column.dart @@ -69,6 +69,10 @@ class DriftColumn implements HasType { /// set. final AnnotatedDartCode? clientDefaultCode; + /// If this column references another column, this column will contain the name + /// that the filters and orderings should use to denote the reverse direction + final String? referenceName; + @override final AppliedTypeConverter? typeConverter; @@ -92,6 +96,7 @@ class DriftColumn implements HasType { this.documentationComment, this.constraints = const [], this.customConstraints, + this.referenceName, bool foreignConverter = false, }) { if (typeConverter != null && !foreignConverter) { diff --git a/drift_dev/lib/src/writer/manager.dart b/drift_dev/lib/src/writer/manager.dart index 8d294937..222aa760 100644 --- a/drift_dev/lib/src/writer/manager.dart +++ b/drift_dev/lib/src/writer/manager.dart @@ -396,9 +396,11 @@ class _TableNames { // If we are referencing the current table, add a back ref if (referencedTableNames.table.entityInfoName == table.entityInfoName) { + final backRefName = referencedCol.referenceName ?? + "${otherTableNames.table.dbGetterName}Refs"; backRefFilters.add(_ReferencedFilter( referencedColumnNames.fieldGetter, - "${otherTableNames.table.dbGetterName}Refs", + backRefName, otherTableNames, referencedColumnNames)); }