diff --git a/app/test/use_case/face_recognition_person/sync_face_recognition_person_test.dart b/app/test/use_case/face_recognition_person/sync_face_recognition_person_test.dart index f9bbcebd..d01de770 100644 --- a/app/test/use_case/face_recognition_person/sync_face_recognition_person_test.dart +++ b/app/test/use_case/face_recognition_person/sync_face_recognition_person_test.dart @@ -1,167 +1,169 @@ -// import 'package:drift/drift.dart' as sql; -// import 'package:nc_photos/di_container.dart'; -// import 'package:nc_photos/entity/face_recognition_person.dart'; -// import 'package:nc_photos/entity/face_recognition_person/data_source.dart'; -// import 'package:nc_photos/entity/face_recognition_person/repo.dart'; -// import 'package:np_db_sqlite/np_db_sqlite_compat.dart' as compat; -// import 'package:nc_photos/entity/sqlite/type_converter.dart'; -// import 'package:nc_photos/use_case/face_recognition_person/sync_face_recognition_person.dart'; -// import 'package:test/test.dart'; -// import 'package:tuple/tuple.dart'; +import 'package:drift/drift.dart' as sql; +import 'package:nc_photos/db/entity_converter.dart'; +import 'package:nc_photos/di_container.dart'; +import 'package:nc_photos/entity/face_recognition_person.dart'; +import 'package:nc_photos/entity/face_recognition_person/data_source.dart'; +import 'package:nc_photos/entity/face_recognition_person/repo.dart'; +import 'package:nc_photos/use_case/face_recognition_person/sync_face_recognition_person.dart'; +import 'package:np_db/np_db.dart'; +import 'package:np_db_sqlite/np_db_sqlite_compat.dart' as compat; +import 'package:test/test.dart'; +import 'package:tuple/tuple.dart'; -// import '../../mock_type.dart'; -// import '../../test_util.dart' as util; +import '../../mock_type.dart'; +import '../../test_util.dart' as util; -// void main() { -// group("SyncFaceRecognitionPerson", () { -// test("new", _new); -// test("remove", _remove); -// test("update", _update); -// }); -// } +void main() { + group("SyncFaceRecognitionPerson", () { + test("new", _new); + test("remove", _remove); + test("update", _update); + }); +} -// /// Sync with remote where there are new persons -// /// -// /// Remote: [test1, test2, test3] -// /// Local: [test1] -// /// Expect: [test1, test2, test3] -// Future _new() async { -// final account = util.buildAccount(); -// final c = DiContainer.late(); -// c.sqliteDb = util.buildTestDb(); -// addTearDown(() => c.sqliteDb.close()); -// c.faceRecognitionPersonRepoRemote = MockFaceRecognitionPersonMemoryRepo({ -// account.id: [ -// const FaceRecognitionPerson(name: "test1", thumbFaceId: 1, count: 1), -// const FaceRecognitionPerson(name: "test2", thumbFaceId: 2, count: 10), -// const FaceRecognitionPerson(name: "test3", thumbFaceId: 3, count: 100), -// ], -// }); -// c.faceRecognitionPersonRepoLocal = BasicFaceRecognitionPersonRepo( -// FaceRecognitionPersonSqliteDbDataSource(c.sqliteDb)); -// await c.sqliteDb.transaction(() async { -// await c.sqliteDb.insertAccounts([account.toDb()]); -// await c.sqliteDb.batch((batch) { -// batch.insert( -// c.sqliteDb.faceRecognitionPersons, -// sql.FaceRecognitionPersonsCompanion.insert( -// account: 1, name: "test1", thumbFaceId: 1, count: 1), -// ); -// }); -// }); +/// Sync with remote where there are new persons +/// +/// Remote: [test1, test2, test3] +/// Local: [test1] +/// Expect: [test1, test2, test3] +Future _new() async { + final account = util.buildAccount(); + final c = DiContainer.late(); + c.npDb = util.buildTestDb(); + addTearDown(() => c.sqliteDb.close()); + c.faceRecognitionPersonRepoRemote = MockFaceRecognitionPersonMemoryRepo({ + account.id: [ + const FaceRecognitionPerson(name: "test1", thumbFaceId: 1, count: 1), + const FaceRecognitionPerson(name: "test2", thumbFaceId: 2, count: 10), + const FaceRecognitionPerson(name: "test3", thumbFaceId: 3, count: 100), + ], + }); + c.faceRecognitionPersonRepoLocal = BasicFaceRecognitionPersonRepo( + FaceRecognitionPersonSqliteDbDataSource(c.npDb)); + await c.sqliteDb.transaction(() async { + await c.sqliteDb.insertAccounts([account.toDb()]); + await c.sqliteDb.batch((batch) { + batch.insert( + c.sqliteDb.faceRecognitionPersons, + compat.FaceRecognitionPersonsCompanion.insert( + account: 1, name: "test1", thumbFaceId: 1, count: 1), + ); + }); + }); -// await SyncFaceRecognitionPerson(c)(account); -// expect( -// await _listSqliteDbPersons(c.sqliteDb), -// { -// account.userId.toCaseInsensitiveString(): { -// const FaceRecognitionPerson(name: "test1", thumbFaceId: 1, count: 1), -// const FaceRecognitionPerson(name: "test2", thumbFaceId: 2, count: 10), -// const FaceRecognitionPerson(name: "test3", thumbFaceId: 3, count: 100), -// }, -// }, -// ); -// } + await SyncFaceRecognitionPerson(c)(account); + expect( + await _listSqliteDbPersons(c.sqliteDb), + { + account.userId.toCaseInsensitiveString(): { + const DbFaceRecognitionPerson(name: "test1", thumbFaceId: 1, count: 1), + const DbFaceRecognitionPerson(name: "test2", thumbFaceId: 2, count: 10), + const DbFaceRecognitionPerson( + name: "test3", thumbFaceId: 3, count: 100), + }, + }, + ); +} -// /// Sync with remote where there are removed persons -// /// -// /// Remote: [test1] -// /// Local: [test1, test2, test3] -// /// Expect: [test1] -// Future _remove() async { -// final account = util.buildAccount(); -// final c = DiContainer.late(); -// c.sqliteDb = util.buildTestDb(); -// addTearDown(() => c.sqliteDb.close()); -// c.faceRecognitionPersonRepoRemote = MockFaceRecognitionPersonMemoryRepo({ -// account.id: [ -// const FaceRecognitionPerson(name: "test1", thumbFaceId: 1, count: 1), -// ], -// }); -// c.faceRecognitionPersonRepoLocal = BasicFaceRecognitionPersonRepo( -// FaceRecognitionPersonSqliteDbDataSource(c.sqliteDb)); -// await c.sqliteDb.transaction(() async { -// await c.sqliteDb.insertAccounts([account.toDb()]); -// await c.sqliteDb.batch((batch) { -// batch.insertAll(c.sqliteDb.faceRecognitionPersons, [ -// sql.FaceRecognitionPersonsCompanion.insert( -// account: 1, name: "test1", thumbFaceId: 1, count: 1), -// sql.FaceRecognitionPersonsCompanion.insert( -// account: 1, name: "test2", thumbFaceId: 2, count: 10), -// sql.FaceRecognitionPersonsCompanion.insert( -// account: 1, name: "test3", thumbFaceId: 3, count: 100), -// ]); -// }); -// }); +/// Sync with remote where there are removed persons +/// +/// Remote: [test1] +/// Local: [test1, test2, test3] +/// Expect: [test1] +Future _remove() async { + final account = util.buildAccount(); + final c = DiContainer.late(); + c.npDb = util.buildTestDb(); + addTearDown(() => c.sqliteDb.close()); + c.faceRecognitionPersonRepoRemote = MockFaceRecognitionPersonMemoryRepo({ + account.id: [ + const FaceRecognitionPerson(name: "test1", thumbFaceId: 1, count: 1), + ], + }); + c.faceRecognitionPersonRepoLocal = BasicFaceRecognitionPersonRepo( + FaceRecognitionPersonSqliteDbDataSource(c.npDb)); + await c.sqliteDb.transaction(() async { + await c.sqliteDb.insertAccounts([account.toDb()]); + await c.sqliteDb.batch((batch) { + batch.insertAll(c.sqliteDb.faceRecognitionPersons, [ + compat.FaceRecognitionPersonsCompanion.insert( + account: 1, name: "test1", thumbFaceId: 1, count: 1), + compat.FaceRecognitionPersonsCompanion.insert( + account: 1, name: "test2", thumbFaceId: 2, count: 10), + compat.FaceRecognitionPersonsCompanion.insert( + account: 1, name: "test3", thumbFaceId: 3, count: 100), + ]); + }); + }); -// await SyncFaceRecognitionPerson(c)(account); -// expect( -// await _listSqliteDbPersons(c.sqliteDb), -// { -// account.userId.toCaseInsensitiveString(): { -// const FaceRecognitionPerson(name: "test1", thumbFaceId: 1, count: 1), -// }, -// }, -// ); -// } + await SyncFaceRecognitionPerson(c)(account); + expect( + await _listSqliteDbPersons(c.sqliteDb), + { + account.userId.toCaseInsensitiveString(): { + const DbFaceRecognitionPerson(name: "test1", thumbFaceId: 1, count: 1), + }, + }, + ); +} -// /// Sync with remote where there are updated persons (i.e, same name, different -// /// properties) -// /// -// /// Remote: [test1, test2 (face: 3)] -// /// Local: [test1, test2 (face: 2)] -// /// Expect: [test1, test2 (face: 3)] -// Future _update() async { -// final account = util.buildAccount(); -// final c = DiContainer.late(); -// c.sqliteDb = util.buildTestDb(); -// addTearDown(() => c.sqliteDb.close()); -// c.faceRecognitionPersonRepoRemote = MockFaceRecognitionPersonMemoryRepo({ -// account.id: [ -// const FaceRecognitionPerson(name: "test1", thumbFaceId: 1, count: 1), -// const FaceRecognitionPerson(name: "test2", thumbFaceId: 3, count: 10), -// ], -// }); -// c.faceRecognitionPersonRepoLocal = BasicFaceRecognitionPersonRepo( -// FaceRecognitionPersonSqliteDbDataSource(c.sqliteDb)); -// await c.sqliteDb.transaction(() async { -// await c.sqliteDb.insertAccounts([account.toDb()]); -// await c.sqliteDb.batch((batch) { -// batch.insertAll(c.sqliteDb.faceRecognitionPersons, [ -// sql.FaceRecognitionPersonsCompanion.insert( -// account: 1, name: "test1", thumbFaceId: 1, count: 1), -// sql.FaceRecognitionPersonsCompanion.insert( -// account: 1, name: "test2", thumbFaceId: 2, count: 10), -// ]); -// }); -// }); +/// Sync with remote where there are updated persons (i.e, same name, different +/// properties) +/// +/// Remote: [test1, test2 (face: 3)] +/// Local: [test1, test2 (face: 2)] +/// Expect: [test1, test2 (face: 3)] +Future _update() async { + final account = util.buildAccount(); + final c = DiContainer.late(); + c.npDb = util.buildTestDb(); + addTearDown(() => c.sqliteDb.close()); + c.faceRecognitionPersonRepoRemote = MockFaceRecognitionPersonMemoryRepo({ + account.id: [ + const FaceRecognitionPerson(name: "test1", thumbFaceId: 1, count: 1), + const FaceRecognitionPerson(name: "test2", thumbFaceId: 3, count: 10), + ], + }); + c.faceRecognitionPersonRepoLocal = BasicFaceRecognitionPersonRepo( + FaceRecognitionPersonSqliteDbDataSource(c.npDb)); + await c.sqliteDb.transaction(() async { + await c.sqliteDb.insertAccounts([account.toDb()]); + await c.sqliteDb.batch((batch) { + batch.insertAll(c.sqliteDb.faceRecognitionPersons, [ + compat.FaceRecognitionPersonsCompanion.insert( + account: 1, name: "test1", thumbFaceId: 1, count: 1), + compat.FaceRecognitionPersonsCompanion.insert( + account: 1, name: "test2", thumbFaceId: 2, count: 10), + ]); + }); + }); -// await SyncFaceRecognitionPerson(c)(account); -// expect( -// await _listSqliteDbPersons(c.sqliteDb), -// { -// account.userId.toCaseInsensitiveString(): { -// const FaceRecognitionPerson(name: "test1", thumbFaceId: 1, count: 1), -// const FaceRecognitionPerson(name: "test2", thumbFaceId: 3, count: 10), -// }, -// }, -// ); -// } + await SyncFaceRecognitionPerson(c)(account); + expect( + await _listSqliteDbPersons(c.sqliteDb), + { + account.userId.toCaseInsensitiveString(): { + const DbFaceRecognitionPerson(name: "test1", thumbFaceId: 1, count: 1), + const DbFaceRecognitionPerson(name: "test2", thumbFaceId: 3, count: 10), + }, + }, + ); +} -// Future>> _listSqliteDbPersons( -// sql.SqliteDb db) async { -// final query = db.select(db.faceRecognitionPersons).join([ -// sql.innerJoin(db.accounts, -// db.accounts.rowId.equalsExp(db.faceRecognitionPersons.account)), -// ]); -// final result = await query -// .map((r) => Tuple2( -// r.readTable(db.accounts), r.readTable(db.faceRecognitionPersons))) -// .get(); -// final product = >{}; -// for (final r in result) { -// (product[r.item1.userId] ??= {}) -// .add(SqliteFaceRecognitionPersonConverter.fromSql(r.item2)); -// } -// return product; -// } +Future>> _listSqliteDbPersons( + compat.SqliteDb db) async { + final query = db.select(db.faceRecognitionPersons).join([ + sql.innerJoin(db.accounts, + db.accounts.rowId.equalsExp(db.faceRecognitionPersons.account)), + ]); + final result = await query + .map((r) => Tuple2( + r.readTable(db.accounts), r.readTable(db.faceRecognitionPersons))) + .get(); + final product = >{}; + for (final r in result) { + (product[r.item1.userId] ??= {}) + .add(compat.FaceRecognitionPersonConverter.fromSql(r.item2)); + } + return product; +} diff --git a/app/test/use_case/sync_tag_test.dart b/app/test/use_case/sync_tag_test.dart index 3326ebd5..4c504a1f 100644 --- a/app/test/use_case/sync_tag_test.dart +++ b/app/test/use_case/sync_tag_test.dart @@ -1,152 +1,185 @@ -// import 'package:drift/drift.dart' as sql; -// import 'package:nc_photos/account.dart'; -// import 'package:nc_photos/di_container.dart'; -// import 'package:np_db_sqlite/np_db_sqlite_compat.dart' as compat; -// import 'package:nc_photos/entity/sqlite/type_converter.dart'; -// import 'package:nc_photos/entity/tag.dart'; -// import 'package:nc_photos/entity/tag/data_source.dart'; -// import 'package:nc_photos/use_case/sync_tag.dart'; -// import 'package:test/test.dart'; -// import 'package:tuple/tuple.dart'; +import 'package:drift/drift.dart' as sql; +import 'package:nc_photos/account.dart'; +import 'package:nc_photos/db/entity_converter.dart'; +import 'package:nc_photos/di_container.dart'; +import 'package:nc_photos/entity/tag.dart'; +import 'package:nc_photos/entity/tag/data_source.dart'; +import 'package:nc_photos/use_case/sync_tag.dart'; +import 'package:np_db/np_db.dart'; +import 'package:np_db_sqlite/np_db_sqlite_compat.dart' as compat; +import 'package:test/test.dart'; +import 'package:tuple/tuple.dart'; -// import '../mock_type.dart'; -// import '../test_util.dart' as util; +import '../mock_type.dart'; +import '../test_util.dart' as util; -// void main() { -// group("SyncTag", () { -// test("new", _new); -// test("remove", _remove); -// test("update", _update); -// }); -// } +void main() { + group("SyncTag", () { + test("new", _new); + test("remove", _remove); + test("update", _update); + }); +} -// /// Sync with remote where there are new tags -// /// -// /// Remote: [tag0, tag1, tag2] -// /// Local: [tag0] -// /// Expect: [tag0, tag1, tag2] -// Future _new() async { -// final account = util.buildAccount(); -// final c = DiContainer.late(); -// c.sqliteDb = util.buildTestDb(); -// addTearDown(() => c.sqliteDb.close()); -// c.tagRepoRemote = MockTagMemoryRepo({ -// account.url: [ -// const Tag(id: 10, displayName: "tag0"), -// const Tag(id: 11, displayName: "tag1"), -// const Tag(id: 12, displayName: "tag2"), -// ], -// }); -// c.tagRepoLocal = TagRepo(TagSqliteDbDataSource(c.sqliteDb)); -// await c.sqliteDb.transaction(() async { -// await c.sqliteDb.insertAccounts([account.toDb()]); -// await c.sqliteDb.batch((batch) { -// batch.insert(c.sqliteDb.tags, -// sql.TagsCompanion.insert(server: 1, tagId: 10, displayName: "tag0")); -// }); -// }); +/// Sync with remote where there are new tags +/// +/// Remote: [tag0, tag1, tag2] +/// Local: [tag0] +/// Expect: [tag0, tag1, tag2] +Future _new() async { + final account = util.buildAccount(); + final c = DiContainer.late(); + c.npDb = util.buildTestDb(); + addTearDown(() => c.sqliteDb.close()); + c.tagRepoRemote = MockTagMemoryRepo({ + account.url: [ + const Tag(id: 10, displayName: "tag0"), + const Tag(id: 11, displayName: "tag1"), + const Tag(id: 12, displayName: "tag2"), + ], + }); + c.tagRepoLocal = TagRepo(TagSqliteDbDataSource(c.npDb)); + await c.sqliteDb.transaction(() async { + await c.sqliteDb.insertAccounts([account.toDb()]); + await c.sqliteDb.batch((batch) { + batch.insert( + c.sqliteDb.tags, + compat.TagsCompanion.insert(server: 1, tagId: 10, displayName: "tag0"), + ); + }); + }); -// await SyncTag(c)(account); -// expect( -// await _listSqliteDbTags(c.sqliteDb), -// { -// account.url: { -// const Tag(id: 10, displayName: "tag0"), -// const Tag(id: 11, displayName: "tag1"), -// const Tag(id: 12, displayName: "tag2"), -// }, -// }, -// ); -// } + await SyncTag(c)(account); + expect( + await _listSqliteDbTags(c.sqliteDb), + { + account.url: { + const DbTag( + id: 10, + displayName: "tag0", + userVisible: null, + userAssignable: null, + ), + const DbTag( + id: 11, + displayName: "tag1", + userVisible: null, + userAssignable: null, + ), + const DbTag( + id: 12, + displayName: "tag2", + userVisible: null, + userAssignable: null, + ), + }, + }, + ); +} -// /// Sync with remote where there are removed tags -// /// -// /// Remote: [tag0] -// /// Local: [tag0, tag1, tag2] -// /// Expect: [tag0] -// Future _remove() async { -// final account = util.buildAccount(); -// final c = DiContainer.late(); -// c.sqliteDb = util.buildTestDb(); -// addTearDown(() => c.sqliteDb.close()); -// c.tagRepoRemote = MockTagMemoryRepo({ -// account.url: [ -// const Tag(id: 10, displayName: "tag0"), -// ], -// }); -// c.tagRepoLocal = TagRepo(TagSqliteDbDataSource(c.sqliteDb)); -// await c.sqliteDb.transaction(() async { -// await c.sqliteDb.insertAccounts([account.toDb()]); -// await c.sqliteDb.batch((batch) { -// batch.insertAll(c.sqliteDb.tags, [ -// sql.TagsCompanion.insert(server: 1, tagId: 10, displayName: "tag0"), -// sql.TagsCompanion.insert(server: 1, tagId: 11, displayName: "tag1"), -// sql.TagsCompanion.insert(server: 1, tagId: 12, displayName: "tag2"), -// ]); -// }); -// }); +/// Sync with remote where there are removed tags +/// +/// Remote: [tag0] +/// Local: [tag0, tag1, tag2] +/// Expect: [tag0] +Future _remove() async { + final account = util.buildAccount(); + final c = DiContainer.late(); + c.npDb = util.buildTestDb(); + addTearDown(() => c.sqliteDb.close()); + c.tagRepoRemote = MockTagMemoryRepo({ + account.url: [ + const Tag(id: 10, displayName: "tag0"), + ], + }); + c.tagRepoLocal = TagRepo(TagSqliteDbDataSource(c.npDb)); + await c.sqliteDb.transaction(() async { + await c.sqliteDb.insertAccounts([account.toDb()]); + await c.sqliteDb.batch((batch) { + batch.insertAll(c.sqliteDb.tags, [ + compat.TagsCompanion.insert(server: 1, tagId: 10, displayName: "tag0"), + compat.TagsCompanion.insert(server: 1, tagId: 11, displayName: "tag1"), + compat.TagsCompanion.insert(server: 1, tagId: 12, displayName: "tag2"), + ]); + }); + }); -// await SyncTag(c)(account); -// expect( -// await _listSqliteDbTags(c.sqliteDb), -// { -// account.url: { -// const Tag(id: 10, displayName: "tag0"), -// }, -// }, -// ); -// } + await SyncTag(c)(account); + expect( + await _listSqliteDbTags(c.sqliteDb), + { + account.url: { + const DbTag( + id: 10, + displayName: "tag0", + userVisible: null, + userAssignable: null, + ), + }, + }, + ); +} -// /// Sync with remote where there are updated tags (i.e, same id, different -// /// properties) -// /// -// /// Remote: [tag0, new tag1] -// /// Local: [tag0, tag1] -// /// Expect: [tag0, new tag1] -// Future _update() async { -// final account = util.buildAccount(); -// final c = DiContainer.late(); -// c.sqliteDb = util.buildTestDb(); -// addTearDown(() => c.sqliteDb.close()); -// c.tagRepoRemote = MockTagMemoryRepo({ -// account.url: [ -// const Tag(id: 10, displayName: "tag0"), -// const Tag(id: 11, displayName: "new tag1"), -// ], -// }); -// c.tagRepoLocal = TagRepo(TagSqliteDbDataSource(c.sqliteDb)); -// await c.sqliteDb.transaction(() async { -// await c.sqliteDb.insertAccounts([account.toDb()]); -// await c.sqliteDb.batch((batch) { -// batch.insertAll(c.sqliteDb.tags, [ -// sql.TagsCompanion.insert(server: 1, tagId: 10, displayName: "tag0"), -// sql.TagsCompanion.insert(server: 1, tagId: 11, displayName: "tag1"), -// ]); -// }); -// }); +/// Sync with remote where there are updated tags (i.e, same id, different +/// properties) +/// +/// Remote: [tag0, new tag1] +/// Local: [tag0, tag1] +/// Expect: [tag0, new tag1] +Future _update() async { + final account = util.buildAccount(); + final c = DiContainer.late(); + c.npDb = util.buildTestDb(); + addTearDown(() => c.sqliteDb.close()); + c.tagRepoRemote = MockTagMemoryRepo({ + account.url: [ + const Tag(id: 10, displayName: "tag0"), + const Tag(id: 11, displayName: "new tag1"), + ], + }); + c.tagRepoLocal = TagRepo(TagSqliteDbDataSource(c.npDb)); + await c.sqliteDb.transaction(() async { + await c.sqliteDb.insertAccounts([account.toDb()]); + await c.sqliteDb.batch((batch) { + batch.insertAll(c.sqliteDb.tags, [ + compat.TagsCompanion.insert(server: 1, tagId: 10, displayName: "tag0"), + compat.TagsCompanion.insert(server: 1, tagId: 11, displayName: "tag1"), + ]); + }); + }); -// await SyncTag(c)(account); -// expect( -// await _listSqliteDbTags(c.sqliteDb), -// { -// account.url: { -// const Tag(id: 10, displayName: "tag0"), -// const Tag(id: 11, displayName: "new tag1"), -// }, -// }, -// ); -// } + await SyncTag(c)(account); + expect( + await _listSqliteDbTags(c.sqliteDb), + { + account.url: { + const DbTag( + id: 10, + displayName: "tag0", + userVisible: null, + userAssignable: null, + ), + const DbTag( + id: 11, + displayName: "new tag1", + userVisible: null, + userAssignable: null, + ), + }, + }, + ); +} -// Future>> _listSqliteDbTags(sql.SqliteDb db) async { -// final query = db.select(db.tags).join([ -// sql.innerJoin(db.servers, db.servers.rowId.equalsExp(db.tags.server)), -// ]); -// final result = await query -// .map((r) => Tuple2(r.readTable(db.servers), r.readTable(db.tags))) -// .get(); -// final product = >{}; -// for (final r in result) { -// (product[r.item1.address] ??= {}).add(SqliteTagConverter.fromSql(r.item2)); -// } -// return product; -// } +Future>> _listSqliteDbTags(compat.SqliteDb db) async { + final query = db.select(db.tags).join([ + sql.innerJoin(db.servers, db.servers.rowId.equalsExp(db.tags.server)), + ]); + final result = await query + .map((r) => Tuple2(r.readTable(db.servers), r.readTable(db.tags))) + .get(); + final product = >{}; + for (final r in result) { + (product[r.item1.address] ??= {}).add(compat.TagConverter.fromSql(r.item2)); + } + return product; +} diff --git a/np_db_sqlite/lib/np_db_sqlite_compat.dart b/np_db_sqlite/lib/np_db_sqlite_compat.dart index 121ee21e..f601f023 100644 --- a/np_db_sqlite/lib/np_db_sqlite_compat.dart +++ b/np_db_sqlite/lib/np_db_sqlite_compat.dart @@ -1,4 +1,5 @@ library np_db_sqlite; +export 'src/converter.dart'; export 'src/database.dart'; export 'src/database_extension.dart';