diff --git a/drift/test/generated/todos.g.dart b/drift/test/generated/todos.g.dart index 3872c361..096ca4b9 100644 --- a/drift/test/generated/todos.g.dart +++ b/drift/test/generated/todos.g.dart @@ -1846,9 +1846,9 @@ class AllTodosWithCategoryResult extends CustomResultSet { mixin _$SomeDaoMixin on DatabaseAccessor { $UsersTable get users => attachedDatabase.users; - $SharedTodosTable get sharedTodos => attachedDatabase.sharedTodos; $CategoriesTable get categories => attachedDatabase.categories; $TodosTableTable get todosTable => attachedDatabase.todosTable; + $SharedTodosTable get sharedTodos => attachedDatabase.sharedTodos; $TodoWithCategoryViewView get todoWithCategoryView => attachedDatabase.todoWithCategoryView; Selectable todosForUser({required int user}) { diff --git a/drift_dev/CHANGELOG.md b/drift_dev/CHANGELOG.md index a947e4b5..c9116efb 100644 --- a/drift_dev/CHANGELOG.md +++ b/drift_dev/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.8.3-dev + +- Allow Dart-defined tables to reference imported tables through SQL + [#2433](https://github.com/simolus3/drift/issues/2433). + ## 2.8.2 - Fix generated to write qualified column references for Dart components in diff --git a/drift_dev/lib/src/analysis/driver/cache.dart b/drift_dev/lib/src/analysis/driver/cache.dart index 70781ec5..9d160c26 100644 --- a/drift_dev/lib/src/analysis/driver/cache.dart +++ b/drift_dev/lib/src/analysis/driver/cache.dart @@ -63,8 +63,12 @@ class DriftAnalysisCache { yield found; for (final imported in found.imports ?? const []) { - if (seenUris.add(imported)) { - pending.add(knownFiles[imported]!); + // We might not have a known file for all imports of a Dart file, since + // not all imports are drift-related there. + final knownImport = knownFiles[imported]; + + if (seenUris.add(imported) && knownImport != null) { + pending.add(knownImport); } } } diff --git a/drift_dev/lib/src/analysis/driver/driver.dart b/drift_dev/lib/src/analysis/driver/driver.dart index 5b8058f4..e0ea0c7c 100644 --- a/drift_dev/lib/src/analysis/driver/driver.dart +++ b/drift_dev/lib/src/analysis/driver/driver.dart @@ -184,6 +184,10 @@ class DriftAnalysisDriver { ); } } + } else if (state is DiscoveredDartLibrary) { + for (final import in state.importDependencies) { + await prepareFileForAnalysis(import); + } } } diff --git a/drift_dev/lib/src/analysis/driver/state.dart b/drift_dev/lib/src/analysis/driver/state.dart index 861d8d68..b0cb5ae5 100644 --- a/drift_dev/lib/src/analysis/driver/state.dart +++ b/drift_dev/lib/src/analysis/driver/state.dart @@ -129,10 +129,17 @@ class DriftFileImport { class DiscoveredDartLibrary extends DiscoveredFileState { final LibraryElement library; + @override + final List importDependencies; + @override bool get isValidImport => true; - DiscoveredDartLibrary(this.library, super.locallyDefinedElements); + DiscoveredDartLibrary( + this.library, + super.locallyDefinedElements, + this.importDependencies, + ); } class NotADartLibrary extends DiscoveredFileState { diff --git a/drift_dev/lib/src/analysis/resolver/dart/table.dart b/drift_dev/lib/src/analysis/resolver/dart/table.dart index f01c22f1..4d08b5ac 100644 --- a/drift_dev/lib/src/analysis/resolver/dart/table.dart +++ b/drift_dev/lib/src/analysis/resolver/dart/table.dart @@ -46,6 +46,9 @@ class DartTableResolver extends LocalElementResolver { } } + final tableConstraints = + await _readCustomConstraints(references, columns, element); + final table = DriftTable( discovered.ownId, DriftDeclaration.dartElement(element), @@ -60,7 +63,7 @@ class DartTableResolver extends LocalElementResolver { for (final uniqueKey in uniqueKeys ?? const >[]) UniqueColumns(uniqueKey), ], - overrideTableConstraints: await _readCustomConstraints(columns, element), + overrideTableConstraints: tableConstraints, withoutRowId: await _overrideWithoutRowId(element) ?? false, ); @@ -272,7 +275,7 @@ class DartTableResolver extends LocalElementResolver { return ColumnParser(this).parse(declaration, element); } - Future> _readCustomConstraints( + Future> _readCustomConstraints(Set references, List localColumns, ClassElement element) async { final customConstraints = element.lookUpGetter('customConstraints', element.library); @@ -343,6 +346,7 @@ class DartTableResolver extends LocalElementResolver { (msg) => DriftAnalysisError.inDartAst(element, source, msg)); if (table != null) { + references.add(table); final missingColumns = clause.columnNames .map((e) => e.columnName) .where((e) => !table.columnBySqlName.containsKey(e)); diff --git a/drift_dev/lib/src/analysis/resolver/discover.dart b/drift_dev/lib/src/analysis/resolver/discover.dart index 3819dc6d..c7537ea0 100644 --- a/drift_dev/lib/src/analysis/resolver/discover.dart +++ b/drift_dev/lib/src/analysis/resolver/discover.dart @@ -77,8 +77,11 @@ class DiscoverStep { await finder.find(); _file.errorsDuringDiscovery.addAll(finder.errors); - _file.discovery = - DiscoveredDartLibrary(library, _checkForDuplicates(finder.found)); + _file.discovery = DiscoveredDartLibrary( + library, + _checkForDuplicates(finder.found), + finder.imports, + ); break; case '.drift': case '.moor': @@ -153,6 +156,8 @@ class _FindDartElements extends RecursiveElementVisitor { final DiscoverStep _discoverStep; final LibraryElement _library; + final List imports = []; + final TypeChecker _isTable, _isView, _isTableInfo, _isDatabase, _isDao; final List> _pendingWork = []; @@ -231,6 +236,18 @@ class _FindDartElements extends RecursiveElementVisitor { super.visitClassElement(element); } + @override + void visitLibraryImportElement(LibraryImportElement element) { + final imported = element.importedLibrary; + + if (imported != null && !imported.isInSdk) { + _pendingWork.add(Future(() async { + final uri = await _discoverStep._driver.backend.uriOfDart(imported); + imports.add(uri); + })); + } + } + String _defaultNameForTableOrView(ClassElement definingElement) { return _discoverStep._driver.options.caseFromDartToSql .apply(definingElement.name); diff --git a/drift_dev/test/analysis/resolver/dart/table_test.dart b/drift_dev/test/analysis/resolver/dart/table_test.dart index b81dd61a..974a06d7 100644 --- a/drift_dev/test/analysis/resolver/dart/table_test.dart +++ b/drift_dev/test/analysis/resolver/dart/table_test.dart @@ -364,6 +364,48 @@ class WithConstraints extends Table { ]); }); + test('can resolve references from import', () async { + final backend = TestBackend.inTest({ + 'a|lib/topic.dart': ''' +import 'package:drift/drift.dart'; + +import 'language.dart'; + +class Topics extends Table { + IntColumn get id => integer()(); + TextColumn get langCode => text()(); +} + +''', + 'a|lib/video.dart': ''' +import 'package:drift/drift.dart'; + +import 'topic.dart'; + +class Videos extends Table { + IntColumn get id => integer()(); + + IntColumn get topicId => integer()(); + TextColumn get topicLang => text()(); + + @override + List get customConstraints => [ + 'FOREIGN KEY (topic_id, topic_lang) REFERENCES topics (id, lang_code)', + ]; +} +''', + }); + + final state = await backend.analyze('package:a/video.dart'); + backend.expectNoErrors(); + + final table = state.analyzedElements.single as DriftTable; + expect( + table.references, + contains(isA() + .having((e) => e.schemaName, 'schemaName', 'topics'))); + }); + test('supports autoIncrement on int64 columns', () async { final backend = TestBackend.inTest({ 'a|lib/a.dart': '''