drift icon indicating copy to clipboard operation
drift copied to clipboard

Manager references around custom row classes throws an error when calling prefetchedData

Open AhmedLSayed9 opened this issue 1 year ago • 3 comments

Related to #3335

Simply, try running the following sample:

import 'package:drift/drift.dart';
import 'package:drift/native.dart';

part 'main.g.dart';

class AnotherTable extends Table {
  IntColumn get id => integer().autoIncrement()();
}

@UseRowClass(Item)
class Items extends Table {
  IntColumn get id => integer().autoIncrement()();
  IntColumn get anotherTable => integer().references(AnotherTable, #id)();
}

class Item {
  Item({required this.id});

  final int id;
}

@DriftDatabase(tables: [AnotherTable, Items])
class Database extends _$Database {
  Database(super.e);

  @override
  int get schemaVersion => 1;

  @override
  MigrationStrategy get migration => MigrationStrategy();
}

Future<void> main() async {
  final db = Database(NativeDatabase.memory());

  await db.into(db.anotherTable).insert(AnotherTableCompanion.insert(id: const Value(1)));

  await db.into(db.items).insert(ItemsCompanion.insert(id: const Value(1), anotherTable: 1));

  final another = await db.managers.anotherTable
      .withReferences((prefetch) => prefetch(itemsRefs: true))
      .getSingle();

  final item = another.$2.itemsRefs.prefetchedData?.first;
  print(item);
}

The following error will be thrown:

NoSuchMethodError: Class 'Item' has no instance getter 'anotherTable'.
Receiver: Instance of 'Item'
Tried calling: anotherTable

AhmedLSayed9 avatar Jan 27 '25 21:01 AhmedLSayed9

I've "improved" this in 5767b8c68ca471186e36eec55402c740ec84fb6d to add the relevant type arguments so that this is no longer a dynamic invocation. That makes this runtime error a compile-time error - still not great, but it also improves performance when it works.

Refactoring this a bit harder than the forward relations, I'll have to think about this some more.

simolus3 avatar Jan 28 '25 18:01 simolus3

@AhmedLSayed9

IntColumn get anotherTable => integer().references(AnotherTable, #id)();

Can we define foreign key constraints on drift ?

  • NO ACTION
  • RESTRICT
  • CASCADE
  • SET NULL
  • SET DEFAULT

Seems like the foreign key constraints are only possible in migrations, correct?

cassioseffrin avatar Mar 25 '25 18:03 cassioseffrin

You can use the onUpdate and onDelete parameters on references:

  IntColumn get anotherTable => integer().references(AnotherTable, #id, onUpdate: KeyAction.cascade)();

Also, the best way to ask these questions is to open new discussions or issues. Please don't comment on unrelated issues or tag random users.

simolus3 avatar Mar 26 '25 06:03 simolus3