diff --git a/drift_schemas/my_database/drift_schema_v4.json b/drift_schemas/my_database/drift_schema_v4.json new file mode 100644 index 00000000..89441439 --- /dev/null +++ b/drift_schemas/my_database/drift_schema_v4.json @@ -0,0 +1 @@ +{"_meta":{"description":"This file contains a serialized version of schema entities for drift.","version":"1.2.0"},"options":{"store_date_time_values_as_text":false},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"fhir_resource","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"source_id","getter_name":"sourceId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"resource_type","getter_name":"resourceType","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"resource_id","getter_name":"resourceId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"title","getter_name":"title","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"date","getter_name":"date","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"resource_raw","getter_name":"resourceRaw","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"encounter_id","getter_name":"encounterId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"subject_id","getter_name":"subjectId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["id"]}},{"id":1,"references":[],"type":"table","data":{"name":"sources","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"logo","getter_name":"logo","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"label_source","getter_name":"labelSource","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["id"]}},{"id":2,"references":[0],"type":"table","data":{"name":"record_attachments","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"resource_id","getter_name":"resourceId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES fhir_resource (id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES fhir_resource (id)"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"file_path","getter_name":"filePath","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"timestamp","getter_name":"timestamp","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":3,"references":[0],"type":"table","data":{"name":"record_notes","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"resource_id","getter_name":"resourceId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES fhir_resource (id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES fhir_resource (id)"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"content","getter_name":"content","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"timestamp","getter_name":"timestamp","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":4,"references":[0],"type":"index","data":{"on":0,"name":"resourceType","sql":null,"unique":false,"columns":["resource_type"]}},{"id":5,"references":[0],"type":"index","data":{"on":0,"name":"resourceId","sql":null,"unique":false,"columns":["resource_id"]}}]} \ No newline at end of file diff --git a/drift_schemas/my_database/drift_schema_v5.json b/drift_schemas/my_database/drift_schema_v5.json new file mode 100644 index 00000000..89441439 --- /dev/null +++ b/drift_schemas/my_database/drift_schema_v5.json @@ -0,0 +1 @@ +{"_meta":{"description":"This file contains a serialized version of schema entities for drift.","version":"1.2.0"},"options":{"store_date_time_values_as_text":false},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"fhir_resource","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"source_id","getter_name":"sourceId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"resource_type","getter_name":"resourceType","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"resource_id","getter_name":"resourceId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"title","getter_name":"title","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"date","getter_name":"date","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"resource_raw","getter_name":"resourceRaw","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"encounter_id","getter_name":"encounterId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"subject_id","getter_name":"subjectId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["id"]}},{"id":1,"references":[],"type":"table","data":{"name":"sources","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"logo","getter_name":"logo","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"label_source","getter_name":"labelSource","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["id"]}},{"id":2,"references":[0],"type":"table","data":{"name":"record_attachments","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"resource_id","getter_name":"resourceId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES fhir_resource (id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES fhir_resource (id)"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"file_path","getter_name":"filePath","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"timestamp","getter_name":"timestamp","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":3,"references":[0],"type":"table","data":{"name":"record_notes","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"resource_id","getter_name":"resourceId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES fhir_resource (id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES fhir_resource (id)"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"content","getter_name":"content","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"timestamp","getter_name":"timestamp","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":4,"references":[0],"type":"index","data":{"on":0,"name":"resourceType","sql":null,"unique":false,"columns":["resource_type"]}},{"id":5,"references":[0],"type":"index","data":{"on":0,"name":"resourceId","sql":null,"unique":false,"columns":["resource_id"]}}]} \ No newline at end of file diff --git a/lib/core/data/local/app_database.dart b/lib/core/data/local/app_database.dart index 000e7f0e..35794f69 100644 --- a/lib/core/data/local/app_database.dart +++ b/lib/core/data/local/app_database.dart @@ -17,7 +17,7 @@ class AppDatabase extends _$AppDatabase { AppDatabase([QueryExecutor? e]) : super(e ?? _openConnection()); @override - int get schemaVersion => 4; + int get schemaVersion => 5; @override MigrationStrategy get migration => MigrationStrategy( @@ -37,6 +37,9 @@ class AppDatabase extends _$AppDatabase { from3To4: (m, schema) async { await m.addColumn(schema.sources, schema.sources.labelSource); }, + from4To5: (m, schema) async { + await m.addColumn(schema.fhirResource, schema.fhirResource.updatedAt); + }, ), ); diff --git a/lib/core/data/local/app_database.steps.dart b/lib/core/data/local/app_database.steps.dart index 3cbdc519..af1141f1 100644 --- a/lib/core/data/local/app_database.steps.dart +++ b/lib/core/data/local/app_database.steps.dart @@ -255,6 +255,22 @@ final class Schema3 extends i0.VersionedSchema { 'resourceId', 'CREATE INDEX resourceId ON fhir_resource (resource_id)'); } +class Shape3 extends i0.VersionedTable { + Shape3({required super.source, required super.alias}) : super.aliased(); + i1.GeneratedColumn get id => + columnsByName['id']! as i1.GeneratedColumn; + i1.GeneratedColumn get resourceId => + columnsByName['resource_id']! as i1.GeneratedColumn; + i1.GeneratedColumn get content => + columnsByName['content']! as i1.GeneratedColumn; + i1.GeneratedColumn get timestamp => + columnsByName['timestamp']! as i1.GeneratedColumn; +} + +i1.GeneratedColumn _column_15(String aliasedName) => + i1.GeneratedColumn('content', aliasedName, false, + type: i1.DriftSqlType.string); + final class Schema4 extends i0.VersionedSchema { Schema4({required super.database}) : super(version: 4); @override @@ -266,7 +282,7 @@ final class Schema4 extends i0.VersionedSchema { resourceType, resourceId, ]; - late final Shape0 fhirResource = Shape0( + late final Shape4 fhirResource = Shape4( source: i0.VersionedTable( entityName: 'fhir_resource', withoutRowId: false, @@ -284,11 +300,12 @@ final class Schema4 extends i0.VersionedSchema { _column_6, _column_7, _column_8, + _column_16, ], attachedDatabase: database, ), alias: null); - late final Shape4 sources = Shape4( + late final Shape5 sources = Shape5( source: i0.VersionedTable( entityName: 'sources', withoutRowId: false, @@ -300,7 +317,7 @@ final class Schema4 extends i0.VersionedSchema { _column_0, _column_9, _column_10, - _column_16, + _column_17, ], attachedDatabase: database, ), @@ -341,28 +358,36 @@ final class Schema4 extends i0.VersionedSchema { 'resourceId', 'CREATE INDEX resourceId ON fhir_resource (resource_id)'); } -class Shape3 extends i0.VersionedTable { - Shape3({required super.source, required super.alias}) : super.aliased(); - i1.GeneratedColumn get id => - columnsByName['id']! as i1.GeneratedColumn; +class Shape4 extends i0.VersionedTable { + Shape4({required super.source, required super.alias}) : super.aliased(); + i1.GeneratedColumn get id => + columnsByName['id']! as i1.GeneratedColumn; + i1.GeneratedColumn get sourceId => + columnsByName['source_id']! as i1.GeneratedColumn; + i1.GeneratedColumn get resourceType => + columnsByName['resource_type']! as i1.GeneratedColumn; i1.GeneratedColumn get resourceId => columnsByName['resource_id']! as i1.GeneratedColumn; - i1.GeneratedColumn get content => - columnsByName['content']! as i1.GeneratedColumn; - i1.GeneratedColumn get timestamp => - columnsByName['timestamp']! as i1.GeneratedColumn; + i1.GeneratedColumn get title => + columnsByName['title']! as i1.GeneratedColumn; + i1.GeneratedColumn get date => + columnsByName['date']! as i1.GeneratedColumn; + i1.GeneratedColumn get resourceRaw => + columnsByName['resource_raw']! as i1.GeneratedColumn; + i1.GeneratedColumn get encounterId => + columnsByName['encounter_id']! as i1.GeneratedColumn; + i1.GeneratedColumn get subjectId => + columnsByName['subject_id']! as i1.GeneratedColumn; + i1.GeneratedColumn get updatedAt => + columnsByName['updated_at']! as i1.GeneratedColumn; } -i1.GeneratedColumn _column_15(String aliasedName) => - i1.GeneratedColumn('content', aliasedName, false, - type: i1.DriftSqlType.string); - -i1.GeneratedColumn _column_16(String aliasedName) => - i1.GeneratedColumn('label_source', aliasedName, true, - type: i1.DriftSqlType.string); +i1.GeneratedColumn _column_16(String aliasedName) => + i1.GeneratedColumn('updated_at', aliasedName, true, + type: i1.DriftSqlType.dateTime); -class Shape4 extends i0.VersionedTable { - Shape4({required super.source, required super.alias}) : super.aliased(); +class Shape5 extends i0.VersionedTable { + Shape5({required super.source, required super.alias}) : super.aliased(); i1.GeneratedColumn get id => columnsByName['id']! as i1.GeneratedColumn; i1.GeneratedColumn get name => @@ -373,10 +398,102 @@ class Shape4 extends i0.VersionedTable { columnsByName['label_source']! as i1.GeneratedColumn; } +i1.GeneratedColumn _column_17(String aliasedName) => + i1.GeneratedColumn('label_source', aliasedName, true, + type: i1.DriftSqlType.string); + +final class Schema5 extends i0.VersionedSchema { + Schema5({required super.database}) : super(version: 5); + @override + late final List entities = [ + fhirResource, + sources, + recordAttachments, + recordNotes, + resourceType, + resourceId, + ]; + late final Shape4 fhirResource = Shape4( + source: i0.VersionedTable( + entityName: 'fhir_resource', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(id)', + ], + columns: [ + _column_0, + _column_1, + _column_2, + _column_3, + _column_4, + _column_5, + _column_6, + _column_7, + _column_8, + _column_16, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape5 sources = Shape5( + source: i0.VersionedTable( + entityName: 'sources', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(id)', + ], + columns: [ + _column_0, + _column_9, + _column_10, + _column_17, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape2 recordAttachments = Shape2( + source: i0.VersionedTable( + entityName: 'record_attachments', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_11, + _column_12, + _column_13, + _column_14, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape3 recordNotes = Shape3( + source: i0.VersionedTable( + entityName: 'record_notes', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_11, + _column_12, + _column_15, + _column_14, + ], + attachedDatabase: database, + ), + alias: null); + final i1.Index resourceType = i1.Index('resourceType', + 'CREATE INDEX resourceType ON fhir_resource (resource_type)'); + final i1.Index resourceId = i1.Index( + 'resourceId', 'CREATE INDEX resourceId ON fhir_resource (resource_id)'); +} + i0.MigrationStepWithVersion migrationSteps({ required Future Function(i1.Migrator m, Schema2 schema) from1To2, required Future Function(i1.Migrator m, Schema3 schema) from2To3, required Future Function(i1.Migrator m, Schema4 schema) from3To4, + required Future Function(i1.Migrator m, Schema5 schema) from4To5, }) { return (currentVersion, database) async { switch (currentVersion) { @@ -395,6 +512,11 @@ i0.MigrationStepWithVersion migrationSteps({ final migrator = i1.Migrator(database, schema); await from3To4(migrator, schema); return 4; + case 4: + final schema = Schema5(database: database); + final migrator = i1.Migrator(database, schema); + await from4To5(migrator, schema); + return 5; default: throw ArgumentError.value('Unknown migration from $currentVersion'); } @@ -405,10 +527,12 @@ i1.OnUpgrade stepByStep({ required Future Function(i1.Migrator m, Schema2 schema) from1To2, required Future Function(i1.Migrator m, Schema3 schema) from2To3, required Future Function(i1.Migrator m, Schema4 schema) from3To4, + required Future Function(i1.Migrator m, Schema5 schema) from4To5, }) => i0.VersionedSchema.stepByStepHelper( step: migrationSteps( from1To2: from1To2, from2To3: from2To3, from3To4: from3To4, + from4To5: from4To5, )); diff --git a/lib/features/sync/data/data_source/local/sync_local_data_source.dart b/lib/features/sync/data/data_source/local/sync_local_data_source.dart index fb268da7..ae63309d 100644 --- a/lib/features/sync/data/data_source/local/sync_local_data_source.dart +++ b/lib/features/sync/data/data_source/local/sync_local_data_source.dart @@ -18,6 +18,7 @@ abstract class SyncLocalDataSource { Future deleteAllSources(); Future markResourcesAsDeleted(List deletions); Future updateSourceLabel(String sourceId, String newLabel); + Future> getAllFhirResources(); } @Injectable(as: SyncLocalDataSource) @@ -40,6 +41,7 @@ class SyncLocalDataSourceImpl implements SyncLocalDataSource { resourceRaw: jsonEncode(e.resourceRaw), encounterId: Value(e.encounterId), subjectId: Value(e.subjectId), + updatedAt: Value(e.updatedAt), ); }).toList(); await _appDatabase.batch((batch) { @@ -56,6 +58,26 @@ class SyncLocalDataSourceImpl implements SyncLocalDataSource { return _appDatabase.delete(_appDatabase.fhirResource).go(); } + @override + Future> getAllFhirResources() async { + final query = _appDatabase.select(_appDatabase.fhirResource); + final results = await query.get(); + return results.map((row) { + return FhirResourceDto( + id: row.id, + resourceType: row.resourceType, + resourceId: row.resourceId, + sourceId: row.sourceId, + title: row.title, + date: row.date, + resourceRaw: jsonDecode(row.resourceRaw), + encounterId: row.encounterId, + subjectId: row.subjectId, + updatedAt: row.updatedAt, + ); + }).toList(); + } + @override Future getLastSyncTimestamp() { return Future.value(_sharedPreferences.getString('lastSyncTimestamp')); diff --git a/lib/features/sync/data/data_source/local/tables/fhir_resource_table.dart b/lib/features/sync/data/data_source/local/tables/fhir_resource_table.dart index b31bcdc6..d201e4b9 100644 --- a/lib/features/sync/data/data_source/local/tables/fhir_resource_table.dart +++ b/lib/features/sync/data/data_source/local/tables/fhir_resource_table.dart @@ -13,6 +13,7 @@ class FhirResource extends Table { TextColumn get resourceRaw => text()(); TextColumn get encounterId => text().nullable()(); TextColumn get subjectId => text().nullable()(); + DateTimeColumn get updatedAt => dateTime().nullable()(); @override Set get primaryKey => {id}; diff --git a/lib/features/sync/data/dto/fhir_resource_dto.dart b/lib/features/sync/data/dto/fhir_resource_dto.dart index 761c39b2..1db25415 100644 --- a/lib/features/sync/data/dto/fhir_resource_dto.dart +++ b/lib/features/sync/data/dto/fhir_resource_dto.dart @@ -24,6 +24,7 @@ class FhirResourceDto with _$FhirResourceDto { @JsonKey(name: "deleted_at", fromJson: dateTimeFromJson) DateTime? deletedAt, @JsonKey(name: "change_type") String? changeType, + @JsonKey(name: "updated_at", fromJson: dateTimeFromJson) final DateTime? updatedAt, }) = _FhirResourceDto; factory FhirResourceDto.fromJson(Map json) => diff --git a/lib/features/sync/data/repository/sync_repository_impl.dart b/lib/features/sync/data/repository/sync_repository_impl.dart index cfa5a7e5..60ca5b6d 100644 --- a/lib/features/sync/data/repository/sync_repository_impl.dart +++ b/lib/features/sync/data/repository/sync_repository_impl.dart @@ -27,13 +27,76 @@ class SyncRepositoryImpl implements SyncRepository { @override Future syncResources({required String endpoint}) async { - List resources = + final List incomingResources = await _remoteDataSource.getResources(endpoint: endpoint); + final List currentResources = + await _localDataSource.getAllFhirResources(); + + // Build a map for quick lookup + final Map currentResourcesMap = { + for (var resource in currentResources) + if (resource.resourceId != null) resource.resourceId!: resource + }; + + // Fallback subject = first subject found in any local resource + final Map? fallbackSubject = currentResources + .map((res) => res.resourceRaw?['subject'] as Map?) + .firstWhere((subject) => subject != null, orElse: () => null); + + final List resourcesToUpsert = []; + + final processedIncoming = incomingResources + .map((res) => + res.populateEncounterIdFromRaw().populateSubjectIdFromRaw()) + .toList(); + + for (final incomingResource in processedIncoming) { + if (incomingResource.resourceId == null) continue; + + final resourceId = incomingResource.resourceId!; + + if (currentResourcesMap.containsKey(resourceId)) { + // Record exists, so check if it has been updated + final localResource = currentResourcesMap[resourceId]!; + + // Compare the 'lastUpdated' timestamp. + // We only update if the incoming date is newer than the local one. + final incomingDate = incomingResource.updatedAt; + final localDate = localResource.updatedAt; + + if (incomingDate != null && + (localDate == null || incomingDate.isAfter(localDate))) { + // The incoming record is newer, so add it for an update. + resourcesToUpsert.add(incomingResource); + } + // If the incoming record is not newer, we do nothing, skipping the unnecessary write. + } else { + // Record does not exist locally, so it's new. + // New resource + var newResource = incomingResource; + + // If subject is missing, attach fallback subject + if ((newResource.resourceRaw?['subject'] == null) && + fallbackSubject != null) { + + final newRaw = + Map.from(newResource.resourceRaw ?? {}); + newRaw['subject'] = Map.from(fallbackSubject); + + newResource = newResource.copyWith( + resourceRaw: newRaw, + subjectId: fallbackSubject['reference'] as String?, + ); + } + + resourcesToUpsert.add(newResource); + } + } + + if (resourcesToUpsert.isNotEmpty) { + await _localDataSource.cacheFhirResources(resourcesToUpsert); + } - await _localDataSource.cacheFhirResources(resources - .map((resource) => - resource.populateEncounterIdFromRaw().populateSubjectIdFromRaw()) - .toList()); await _localDataSource .setLastSyncTimestamp(DateTime.now().toIso8601String()); } diff --git a/test/drift/my_database/generated/schema.dart b/test/drift/my_database/generated/schema.dart index 209e70d7..c42542af 100644 --- a/test/drift/my_database/generated/schema.dart +++ b/test/drift/my_database/generated/schema.dart @@ -6,6 +6,8 @@ import 'package:drift/internal/migrations.dart'; import 'schema_v1.dart' as v1; import 'schema_v2.dart' as v2; import 'schema_v3.dart' as v3; +import 'schema_v4.dart' as v4; +import 'schema_v5.dart' as v5; class GeneratedHelper implements SchemaInstantiationHelper { @override @@ -17,10 +19,14 @@ class GeneratedHelper implements SchemaInstantiationHelper { return v2.DatabaseAtV2(db); case 3: return v3.DatabaseAtV3(db); + case 4: + return v4.DatabaseAtV4(db); + case 5: + return v5.DatabaseAtV5(db); default: throw MissingSchemaException(version, versions); } } - static const versions = const [1, 2, 3]; + static const versions = const [1, 2, 3, 4, 5]; } diff --git a/test/drift/my_database/generated/schema_v4.dart b/test/drift/my_database/generated/schema_v4.dart new file mode 100644 index 00000000..6929cee5 --- /dev/null +++ b/test/drift/my_database/generated/schema_v4.dart @@ -0,0 +1,1148 @@ +// dart format width=80 +// GENERATED CODE, DO NOT EDIT BY HAND. +// ignore_for_file: type=lint +import 'package:drift/drift.dart'; + +class FhirResource extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + FhirResource(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn sourceId = GeneratedColumn( + 'source_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn resourceType = GeneratedColumn( + 'resource_type', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn resourceId = GeneratedColumn( + 'resource_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn title = GeneratedColumn( + 'title', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn date = GeneratedColumn( + 'date', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn resourceRaw = GeneratedColumn( + 'resource_raw', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn encounterId = GeneratedColumn( + 'encounter_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn subjectId = GeneratedColumn( + 'subject_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + @override + List get $columns => [ + id, + sourceId, + resourceType, + resourceId, + title, + date, + resourceRaw, + encounterId, + subjectId, + updatedAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'fhir_resource'; + @override + Set get $primaryKey => {id}; + @override + FhirResourceData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return FhirResourceData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}id'])!, + sourceId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}source_id']), + resourceType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}resource_type']), + resourceId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}resource_id']), + title: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}title']), + date: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}date']), + resourceRaw: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}resource_raw'])!, + encounterId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}encounter_id']), + subjectId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}subject_id']), + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at']), + ); + } + + @override + FhirResource createAlias(String alias) { + return FhirResource(attachedDatabase, alias); + } +} + +class FhirResourceData extends DataClass + implements Insertable { + final String id; + final String? sourceId; + final String? resourceType; + final String? resourceId; + final String? title; + final DateTime? date; + final String resourceRaw; + final String? encounterId; + final String? subjectId; + final DateTime? updatedAt; + const FhirResourceData( + {required this.id, + this.sourceId, + this.resourceType, + this.resourceId, + this.title, + this.date, + required this.resourceRaw, + this.encounterId, + this.subjectId, + this.updatedAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + if (!nullToAbsent || sourceId != null) { + map['source_id'] = Variable(sourceId); + } + if (!nullToAbsent || resourceType != null) { + map['resource_type'] = Variable(resourceType); + } + if (!nullToAbsent || resourceId != null) { + map['resource_id'] = Variable(resourceId); + } + if (!nullToAbsent || title != null) { + map['title'] = Variable(title); + } + if (!nullToAbsent || date != null) { + map['date'] = Variable(date); + } + map['resource_raw'] = Variable(resourceRaw); + if (!nullToAbsent || encounterId != null) { + map['encounter_id'] = Variable(encounterId); + } + if (!nullToAbsent || subjectId != null) { + map['subject_id'] = Variable(subjectId); + } + if (!nullToAbsent || updatedAt != null) { + map['updated_at'] = Variable(updatedAt); + } + return map; + } + + FhirResourceCompanion toCompanion(bool nullToAbsent) { + return FhirResourceCompanion( + id: Value(id), + sourceId: sourceId == null && nullToAbsent + ? const Value.absent() + : Value(sourceId), + resourceType: resourceType == null && nullToAbsent + ? const Value.absent() + : Value(resourceType), + resourceId: resourceId == null && nullToAbsent + ? const Value.absent() + : Value(resourceId), + title: + title == null && nullToAbsent ? const Value.absent() : Value(title), + date: date == null && nullToAbsent ? const Value.absent() : Value(date), + resourceRaw: Value(resourceRaw), + encounterId: encounterId == null && nullToAbsent + ? const Value.absent() + : Value(encounterId), + subjectId: subjectId == null && nullToAbsent + ? const Value.absent() + : Value(subjectId), + updatedAt: updatedAt == null && nullToAbsent + ? const Value.absent() + : Value(updatedAt), + ); + } + + factory FhirResourceData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return FhirResourceData( + id: serializer.fromJson(json['id']), + sourceId: serializer.fromJson(json['sourceId']), + resourceType: serializer.fromJson(json['resourceType']), + resourceId: serializer.fromJson(json['resourceId']), + title: serializer.fromJson(json['title']), + date: serializer.fromJson(json['date']), + resourceRaw: serializer.fromJson(json['resourceRaw']), + encounterId: serializer.fromJson(json['encounterId']), + subjectId: serializer.fromJson(json['subjectId']), + updatedAt: serializer.fromJson(json['updatedAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'sourceId': serializer.toJson(sourceId), + 'resourceType': serializer.toJson(resourceType), + 'resourceId': serializer.toJson(resourceId), + 'title': serializer.toJson(title), + 'date': serializer.toJson(date), + 'resourceRaw': serializer.toJson(resourceRaw), + 'encounterId': serializer.toJson(encounterId), + 'subjectId': serializer.toJson(subjectId), + 'updatedAt': serializer.toJson(updatedAt), + }; + } + + FhirResourceData copyWith( + {String? id, + Value sourceId = const Value.absent(), + Value resourceType = const Value.absent(), + Value resourceId = const Value.absent(), + Value title = const Value.absent(), + Value date = const Value.absent(), + String? resourceRaw, + Value encounterId = const Value.absent(), + Value subjectId = const Value.absent(), + Value updatedAt = const Value.absent()}) => + FhirResourceData( + id: id ?? this.id, + sourceId: sourceId.present ? sourceId.value : this.sourceId, + resourceType: + resourceType.present ? resourceType.value : this.resourceType, + resourceId: resourceId.present ? resourceId.value : this.resourceId, + title: title.present ? title.value : this.title, + date: date.present ? date.value : this.date, + resourceRaw: resourceRaw ?? this.resourceRaw, + encounterId: encounterId.present ? encounterId.value : this.encounterId, + subjectId: subjectId.present ? subjectId.value : this.subjectId, + updatedAt: updatedAt.present ? updatedAt.value : this.updatedAt, + ); + FhirResourceData copyWithCompanion(FhirResourceCompanion data) { + return FhirResourceData( + id: data.id.present ? data.id.value : this.id, + sourceId: data.sourceId.present ? data.sourceId.value : this.sourceId, + resourceType: data.resourceType.present + ? data.resourceType.value + : this.resourceType, + resourceId: + data.resourceId.present ? data.resourceId.value : this.resourceId, + title: data.title.present ? data.title.value : this.title, + date: data.date.present ? data.date.value : this.date, + resourceRaw: + data.resourceRaw.present ? data.resourceRaw.value : this.resourceRaw, + encounterId: + data.encounterId.present ? data.encounterId.value : this.encounterId, + subjectId: data.subjectId.present ? data.subjectId.value : this.subjectId, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ); + } + + @override + String toString() { + return (StringBuffer('FhirResourceData(') + ..write('id: $id, ') + ..write('sourceId: $sourceId, ') + ..write('resourceType: $resourceType, ') + ..write('resourceId: $resourceId, ') + ..write('title: $title, ') + ..write('date: $date, ') + ..write('resourceRaw: $resourceRaw, ') + ..write('encounterId: $encounterId, ') + ..write('subjectId: $subjectId, ') + ..write('updatedAt: $updatedAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, sourceId, resourceType, resourceId, title, + date, resourceRaw, encounterId, subjectId, updatedAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is FhirResourceData && + other.id == this.id && + other.sourceId == this.sourceId && + other.resourceType == this.resourceType && + other.resourceId == this.resourceId && + other.title == this.title && + other.date == this.date && + other.resourceRaw == this.resourceRaw && + other.encounterId == this.encounterId && + other.subjectId == this.subjectId && + other.updatedAt == this.updatedAt); +} + +class FhirResourceCompanion extends UpdateCompanion { + final Value id; + final Value sourceId; + final Value resourceType; + final Value resourceId; + final Value title; + final Value date; + final Value resourceRaw; + final Value encounterId; + final Value subjectId; + final Value updatedAt; + final Value rowid; + const FhirResourceCompanion({ + this.id = const Value.absent(), + this.sourceId = const Value.absent(), + this.resourceType = const Value.absent(), + this.resourceId = const Value.absent(), + this.title = const Value.absent(), + this.date = const Value.absent(), + this.resourceRaw = const Value.absent(), + this.encounterId = const Value.absent(), + this.subjectId = const Value.absent(), + this.updatedAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + FhirResourceCompanion.insert({ + required String id, + this.sourceId = const Value.absent(), + this.resourceType = const Value.absent(), + this.resourceId = const Value.absent(), + this.title = const Value.absent(), + this.date = const Value.absent(), + required String resourceRaw, + this.encounterId = const Value.absent(), + this.subjectId = const Value.absent(), + this.updatedAt = const Value.absent(), + this.rowid = const Value.absent(), + }) : id = Value(id), + resourceRaw = Value(resourceRaw); + static Insertable custom({ + Expression? id, + Expression? sourceId, + Expression? resourceType, + Expression? resourceId, + Expression? title, + Expression? date, + Expression? resourceRaw, + Expression? encounterId, + Expression? subjectId, + Expression? updatedAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (sourceId != null) 'source_id': sourceId, + if (resourceType != null) 'resource_type': resourceType, + if (resourceId != null) 'resource_id': resourceId, + if (title != null) 'title': title, + if (date != null) 'date': date, + if (resourceRaw != null) 'resource_raw': resourceRaw, + if (encounterId != null) 'encounter_id': encounterId, + if (subjectId != null) 'subject_id': subjectId, + if (updatedAt != null) 'updated_at': updatedAt, + if (rowid != null) 'rowid': rowid, + }); + } + + FhirResourceCompanion copyWith( + {Value? id, + Value? sourceId, + Value? resourceType, + Value? resourceId, + Value? title, + Value? date, + Value? resourceRaw, + Value? encounterId, + Value? subjectId, + Value? updatedAt, + Value? rowid}) { + return FhirResourceCompanion( + id: id ?? this.id, + sourceId: sourceId ?? this.sourceId, + resourceType: resourceType ?? this.resourceType, + resourceId: resourceId ?? this.resourceId, + title: title ?? this.title, + date: date ?? this.date, + resourceRaw: resourceRaw ?? this.resourceRaw, + encounterId: encounterId ?? this.encounterId, + subjectId: subjectId ?? this.subjectId, + updatedAt: updatedAt ?? this.updatedAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (sourceId.present) { + map['source_id'] = Variable(sourceId.value); + } + if (resourceType.present) { + map['resource_type'] = Variable(resourceType.value); + } + if (resourceId.present) { + map['resource_id'] = Variable(resourceId.value); + } + if (title.present) { + map['title'] = Variable(title.value); + } + if (date.present) { + map['date'] = Variable(date.value); + } + if (resourceRaw.present) { + map['resource_raw'] = Variable(resourceRaw.value); + } + if (encounterId.present) { + map['encounter_id'] = Variable(encounterId.value); + } + if (subjectId.present) { + map['subject_id'] = Variable(subjectId.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('FhirResourceCompanion(') + ..write('id: $id, ') + ..write('sourceId: $sourceId, ') + ..write('resourceType: $resourceType, ') + ..write('resourceId: $resourceId, ') + ..write('title: $title, ') + ..write('date: $date, ') + ..write('resourceRaw: $resourceRaw, ') + ..write('encounterId: $encounterId, ') + ..write('subjectId: $subjectId, ') + ..write('updatedAt: $updatedAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class Sources extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Sources(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn logo = GeneratedColumn( + 'logo', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn labelSource = GeneratedColumn( + 'label_source', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + @override + List get $columns => [id, name, logo, labelSource]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'sources'; + @override + Set get $primaryKey => {id}; + @override + SourcesData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SourcesData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}id'])!, + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name']), + logo: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}logo']), + labelSource: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}label_source']), + ); + } + + @override + Sources createAlias(String alias) { + return Sources(attachedDatabase, alias); + } +} + +class SourcesData extends DataClass implements Insertable { + final String id; + final String? name; + final String? logo; + final String? labelSource; + const SourcesData({required this.id, this.name, this.logo, this.labelSource}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + if (!nullToAbsent || name != null) { + map['name'] = Variable(name); + } + if (!nullToAbsent || logo != null) { + map['logo'] = Variable(logo); + } + if (!nullToAbsent || labelSource != null) { + map['label_source'] = Variable(labelSource); + } + return map; + } + + SourcesCompanion toCompanion(bool nullToAbsent) { + return SourcesCompanion( + id: Value(id), + name: name == null && nullToAbsent ? const Value.absent() : Value(name), + logo: logo == null && nullToAbsent ? const Value.absent() : Value(logo), + labelSource: labelSource == null && nullToAbsent + ? const Value.absent() + : Value(labelSource), + ); + } + + factory SourcesData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SourcesData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + logo: serializer.fromJson(json['logo']), + labelSource: serializer.fromJson(json['labelSource']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'logo': serializer.toJson(logo), + 'labelSource': serializer.toJson(labelSource), + }; + } + + SourcesData copyWith( + {String? id, + Value name = const Value.absent(), + Value logo = const Value.absent(), + Value labelSource = const Value.absent()}) => + SourcesData( + id: id ?? this.id, + name: name.present ? name.value : this.name, + logo: logo.present ? logo.value : this.logo, + labelSource: labelSource.present ? labelSource.value : this.labelSource, + ); + SourcesData copyWithCompanion(SourcesCompanion data) { + return SourcesData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + logo: data.logo.present ? data.logo.value : this.logo, + labelSource: + data.labelSource.present ? data.labelSource.value : this.labelSource, + ); + } + + @override + String toString() { + return (StringBuffer('SourcesData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('logo: $logo, ') + ..write('labelSource: $labelSource') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, name, logo, labelSource); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SourcesData && + other.id == this.id && + other.name == this.name && + other.logo == this.logo && + other.labelSource == this.labelSource); +} + +class SourcesCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value logo; + final Value labelSource; + final Value rowid; + const SourcesCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.logo = const Value.absent(), + this.labelSource = const Value.absent(), + this.rowid = const Value.absent(), + }); + SourcesCompanion.insert({ + required String id, + this.name = const Value.absent(), + this.logo = const Value.absent(), + this.labelSource = const Value.absent(), + this.rowid = const Value.absent(), + }) : id = Value(id); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? logo, + Expression? labelSource, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (logo != null) 'logo': logo, + if (labelSource != null) 'label_source': labelSource, + if (rowid != null) 'rowid': rowid, + }); + } + + SourcesCompanion copyWith( + {Value? id, + Value? name, + Value? logo, + Value? labelSource, + Value? rowid}) { + return SourcesCompanion( + id: id ?? this.id, + name: name ?? this.name, + logo: logo ?? this.logo, + labelSource: labelSource ?? this.labelSource, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (logo.present) { + map['logo'] = Variable(logo.value); + } + if (labelSource.present) { + map['label_source'] = Variable(labelSource.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SourcesCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('logo: $logo, ') + ..write('labelSource: $labelSource, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class RecordAttachments extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RecordAttachments(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn resourceId = GeneratedColumn( + 'resource_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('REFERENCES fhir_resource (id)')); + late final GeneratedColumn filePath = GeneratedColumn( + 'file_path', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn timestamp = GeneratedColumn( + 'timestamp', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + @override + List get $columns => [id, resourceId, filePath, timestamp]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'record_attachments'; + @override + Set get $primaryKey => {id}; + @override + RecordAttachmentsData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RecordAttachmentsData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + resourceId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}resource_id'])!, + filePath: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}file_path'])!, + timestamp: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}timestamp'])!, + ); + } + + @override + RecordAttachments createAlias(String alias) { + return RecordAttachments(attachedDatabase, alias); + } +} + +class RecordAttachmentsData extends DataClass + implements Insertable { + final int id; + final String resourceId; + final String filePath; + final DateTime timestamp; + const RecordAttachmentsData( + {required this.id, + required this.resourceId, + required this.filePath, + required this.timestamp}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['resource_id'] = Variable(resourceId); + map['file_path'] = Variable(filePath); + map['timestamp'] = Variable(timestamp); + return map; + } + + RecordAttachmentsCompanion toCompanion(bool nullToAbsent) { + return RecordAttachmentsCompanion( + id: Value(id), + resourceId: Value(resourceId), + filePath: Value(filePath), + timestamp: Value(timestamp), + ); + } + + factory RecordAttachmentsData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RecordAttachmentsData( + id: serializer.fromJson(json['id']), + resourceId: serializer.fromJson(json['resourceId']), + filePath: serializer.fromJson(json['filePath']), + timestamp: serializer.fromJson(json['timestamp']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'resourceId': serializer.toJson(resourceId), + 'filePath': serializer.toJson(filePath), + 'timestamp': serializer.toJson(timestamp), + }; + } + + RecordAttachmentsData copyWith( + {int? id, + String? resourceId, + String? filePath, + DateTime? timestamp}) => + RecordAttachmentsData( + id: id ?? this.id, + resourceId: resourceId ?? this.resourceId, + filePath: filePath ?? this.filePath, + timestamp: timestamp ?? this.timestamp, + ); + RecordAttachmentsData copyWithCompanion(RecordAttachmentsCompanion data) { + return RecordAttachmentsData( + id: data.id.present ? data.id.value : this.id, + resourceId: + data.resourceId.present ? data.resourceId.value : this.resourceId, + filePath: data.filePath.present ? data.filePath.value : this.filePath, + timestamp: data.timestamp.present ? data.timestamp.value : this.timestamp, + ); + } + + @override + String toString() { + return (StringBuffer('RecordAttachmentsData(') + ..write('id: $id, ') + ..write('resourceId: $resourceId, ') + ..write('filePath: $filePath, ') + ..write('timestamp: $timestamp') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, resourceId, filePath, timestamp); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RecordAttachmentsData && + other.id == this.id && + other.resourceId == this.resourceId && + other.filePath == this.filePath && + other.timestamp == this.timestamp); +} + +class RecordAttachmentsCompanion + extends UpdateCompanion { + final Value id; + final Value resourceId; + final Value filePath; + final Value timestamp; + const RecordAttachmentsCompanion({ + this.id = const Value.absent(), + this.resourceId = const Value.absent(), + this.filePath = const Value.absent(), + this.timestamp = const Value.absent(), + }); + RecordAttachmentsCompanion.insert({ + this.id = const Value.absent(), + required String resourceId, + required String filePath, + required DateTime timestamp, + }) : resourceId = Value(resourceId), + filePath = Value(filePath), + timestamp = Value(timestamp); + static Insertable custom({ + Expression? id, + Expression? resourceId, + Expression? filePath, + Expression? timestamp, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (resourceId != null) 'resource_id': resourceId, + if (filePath != null) 'file_path': filePath, + if (timestamp != null) 'timestamp': timestamp, + }); + } + + RecordAttachmentsCompanion copyWith( + {Value? id, + Value? resourceId, + Value? filePath, + Value? timestamp}) { + return RecordAttachmentsCompanion( + id: id ?? this.id, + resourceId: resourceId ?? this.resourceId, + filePath: filePath ?? this.filePath, + timestamp: timestamp ?? this.timestamp, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (resourceId.present) { + map['resource_id'] = Variable(resourceId.value); + } + if (filePath.present) { + map['file_path'] = Variable(filePath.value); + } + if (timestamp.present) { + map['timestamp'] = Variable(timestamp.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RecordAttachmentsCompanion(') + ..write('id: $id, ') + ..write('resourceId: $resourceId, ') + ..write('filePath: $filePath, ') + ..write('timestamp: $timestamp') + ..write(')')) + .toString(); + } +} + +class RecordNotes extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RecordNotes(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn resourceId = GeneratedColumn( + 'resource_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('REFERENCES fhir_resource (id)')); + late final GeneratedColumn content = GeneratedColumn( + 'content', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn timestamp = GeneratedColumn( + 'timestamp', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + @override + List get $columns => [id, resourceId, content, timestamp]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'record_notes'; + @override + Set get $primaryKey => {id}; + @override + RecordNotesData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RecordNotesData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + resourceId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}resource_id'])!, + content: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}content'])!, + timestamp: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}timestamp'])!, + ); + } + + @override + RecordNotes createAlias(String alias) { + return RecordNotes(attachedDatabase, alias); + } +} + +class RecordNotesData extends DataClass implements Insertable { + final int id; + final String resourceId; + final String content; + final DateTime timestamp; + const RecordNotesData( + {required this.id, + required this.resourceId, + required this.content, + required this.timestamp}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['resource_id'] = Variable(resourceId); + map['content'] = Variable(content); + map['timestamp'] = Variable(timestamp); + return map; + } + + RecordNotesCompanion toCompanion(bool nullToAbsent) { + return RecordNotesCompanion( + id: Value(id), + resourceId: Value(resourceId), + content: Value(content), + timestamp: Value(timestamp), + ); + } + + factory RecordNotesData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RecordNotesData( + id: serializer.fromJson(json['id']), + resourceId: serializer.fromJson(json['resourceId']), + content: serializer.fromJson(json['content']), + timestamp: serializer.fromJson(json['timestamp']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'resourceId': serializer.toJson(resourceId), + 'content': serializer.toJson(content), + 'timestamp': serializer.toJson(timestamp), + }; + } + + RecordNotesData copyWith( + {int? id, + String? resourceId, + String? content, + DateTime? timestamp}) => + RecordNotesData( + id: id ?? this.id, + resourceId: resourceId ?? this.resourceId, + content: content ?? this.content, + timestamp: timestamp ?? this.timestamp, + ); + RecordNotesData copyWithCompanion(RecordNotesCompanion data) { + return RecordNotesData( + id: data.id.present ? data.id.value : this.id, + resourceId: + data.resourceId.present ? data.resourceId.value : this.resourceId, + content: data.content.present ? data.content.value : this.content, + timestamp: data.timestamp.present ? data.timestamp.value : this.timestamp, + ); + } + + @override + String toString() { + return (StringBuffer('RecordNotesData(') + ..write('id: $id, ') + ..write('resourceId: $resourceId, ') + ..write('content: $content, ') + ..write('timestamp: $timestamp') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, resourceId, content, timestamp); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RecordNotesData && + other.id == this.id && + other.resourceId == this.resourceId && + other.content == this.content && + other.timestamp == this.timestamp); +} + +class RecordNotesCompanion extends UpdateCompanion { + final Value id; + final Value resourceId; + final Value content; + final Value timestamp; + const RecordNotesCompanion({ + this.id = const Value.absent(), + this.resourceId = const Value.absent(), + this.content = const Value.absent(), + this.timestamp = const Value.absent(), + }); + RecordNotesCompanion.insert({ + this.id = const Value.absent(), + required String resourceId, + required String content, + required DateTime timestamp, + }) : resourceId = Value(resourceId), + content = Value(content), + timestamp = Value(timestamp); + static Insertable custom({ + Expression? id, + Expression? resourceId, + Expression? content, + Expression? timestamp, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (resourceId != null) 'resource_id': resourceId, + if (content != null) 'content': content, + if (timestamp != null) 'timestamp': timestamp, + }); + } + + RecordNotesCompanion copyWith( + {Value? id, + Value? resourceId, + Value? content, + Value? timestamp}) { + return RecordNotesCompanion( + id: id ?? this.id, + resourceId: resourceId ?? this.resourceId, + content: content ?? this.content, + timestamp: timestamp ?? this.timestamp, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (resourceId.present) { + map['resource_id'] = Variable(resourceId.value); + } + if (content.present) { + map['content'] = Variable(content.value); + } + if (timestamp.present) { + map['timestamp'] = Variable(timestamp.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RecordNotesCompanion(') + ..write('id: $id, ') + ..write('resourceId: $resourceId, ') + ..write('content: $content, ') + ..write('timestamp: $timestamp') + ..write(')')) + .toString(); + } +} + +class DatabaseAtV4 extends GeneratedDatabase { + DatabaseAtV4(QueryExecutor e) : super(e); + late final FhirResource fhirResource = FhirResource(this); + late final Sources sources = Sources(this); + late final RecordAttachments recordAttachments = RecordAttachments(this); + late final RecordNotes recordNotes = RecordNotes(this); + late final Index resourceType = Index('resourceType', + 'CREATE INDEX resourceType ON fhir_resource (resource_type)'); + late final Index resourceId = Index( + 'resourceId', 'CREATE INDEX resourceId ON fhir_resource (resource_id)'); + @override + Iterable> get allTables => + allSchemaEntities.whereType>(); + @override + List get allSchemaEntities => [ + fhirResource, + sources, + recordAttachments, + recordNotes, + resourceType, + resourceId + ]; + @override + int get schemaVersion => 4; +} diff --git a/test/drift/my_database/generated/schema_v5.dart b/test/drift/my_database/generated/schema_v5.dart new file mode 100644 index 00000000..c32310df --- /dev/null +++ b/test/drift/my_database/generated/schema_v5.dart @@ -0,0 +1,1148 @@ +// dart format width=80 +// GENERATED CODE, DO NOT EDIT BY HAND. +// ignore_for_file: type=lint +import 'package:drift/drift.dart'; + +class FhirResource extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + FhirResource(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn sourceId = GeneratedColumn( + 'source_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn resourceType = GeneratedColumn( + 'resource_type', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn resourceId = GeneratedColumn( + 'resource_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn title = GeneratedColumn( + 'title', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn date = GeneratedColumn( + 'date', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn resourceRaw = GeneratedColumn( + 'resource_raw', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn encounterId = GeneratedColumn( + 'encounter_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn subjectId = GeneratedColumn( + 'subject_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + @override + List get $columns => [ + id, + sourceId, + resourceType, + resourceId, + title, + date, + resourceRaw, + encounterId, + subjectId, + updatedAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'fhir_resource'; + @override + Set get $primaryKey => {id}; + @override + FhirResourceData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return FhirResourceData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}id'])!, + sourceId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}source_id']), + resourceType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}resource_type']), + resourceId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}resource_id']), + title: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}title']), + date: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}date']), + resourceRaw: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}resource_raw'])!, + encounterId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}encounter_id']), + subjectId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}subject_id']), + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at']), + ); + } + + @override + FhirResource createAlias(String alias) { + return FhirResource(attachedDatabase, alias); + } +} + +class FhirResourceData extends DataClass + implements Insertable { + final String id; + final String? sourceId; + final String? resourceType; + final String? resourceId; + final String? title; + final DateTime? date; + final String resourceRaw; + final String? encounterId; + final String? subjectId; + final DateTime? updatedAt; + const FhirResourceData( + {required this.id, + this.sourceId, + this.resourceType, + this.resourceId, + this.title, + this.date, + required this.resourceRaw, + this.encounterId, + this.subjectId, + this.updatedAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + if (!nullToAbsent || sourceId != null) { + map['source_id'] = Variable(sourceId); + } + if (!nullToAbsent || resourceType != null) { + map['resource_type'] = Variable(resourceType); + } + if (!nullToAbsent || resourceId != null) { + map['resource_id'] = Variable(resourceId); + } + if (!nullToAbsent || title != null) { + map['title'] = Variable(title); + } + if (!nullToAbsent || date != null) { + map['date'] = Variable(date); + } + map['resource_raw'] = Variable(resourceRaw); + if (!nullToAbsent || encounterId != null) { + map['encounter_id'] = Variable(encounterId); + } + if (!nullToAbsent || subjectId != null) { + map['subject_id'] = Variable(subjectId); + } + if (!nullToAbsent || updatedAt != null) { + map['updated_at'] = Variable(updatedAt); + } + return map; + } + + FhirResourceCompanion toCompanion(bool nullToAbsent) { + return FhirResourceCompanion( + id: Value(id), + sourceId: sourceId == null && nullToAbsent + ? const Value.absent() + : Value(sourceId), + resourceType: resourceType == null && nullToAbsent + ? const Value.absent() + : Value(resourceType), + resourceId: resourceId == null && nullToAbsent + ? const Value.absent() + : Value(resourceId), + title: + title == null && nullToAbsent ? const Value.absent() : Value(title), + date: date == null && nullToAbsent ? const Value.absent() : Value(date), + resourceRaw: Value(resourceRaw), + encounterId: encounterId == null && nullToAbsent + ? const Value.absent() + : Value(encounterId), + subjectId: subjectId == null && nullToAbsent + ? const Value.absent() + : Value(subjectId), + updatedAt: updatedAt == null && nullToAbsent + ? const Value.absent() + : Value(updatedAt), + ); + } + + factory FhirResourceData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return FhirResourceData( + id: serializer.fromJson(json['id']), + sourceId: serializer.fromJson(json['sourceId']), + resourceType: serializer.fromJson(json['resourceType']), + resourceId: serializer.fromJson(json['resourceId']), + title: serializer.fromJson(json['title']), + date: serializer.fromJson(json['date']), + resourceRaw: serializer.fromJson(json['resourceRaw']), + encounterId: serializer.fromJson(json['encounterId']), + subjectId: serializer.fromJson(json['subjectId']), + updatedAt: serializer.fromJson(json['updatedAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'sourceId': serializer.toJson(sourceId), + 'resourceType': serializer.toJson(resourceType), + 'resourceId': serializer.toJson(resourceId), + 'title': serializer.toJson(title), + 'date': serializer.toJson(date), + 'resourceRaw': serializer.toJson(resourceRaw), + 'encounterId': serializer.toJson(encounterId), + 'subjectId': serializer.toJson(subjectId), + 'updatedAt': serializer.toJson(updatedAt), + }; + } + + FhirResourceData copyWith( + {String? id, + Value sourceId = const Value.absent(), + Value resourceType = const Value.absent(), + Value resourceId = const Value.absent(), + Value title = const Value.absent(), + Value date = const Value.absent(), + String? resourceRaw, + Value encounterId = const Value.absent(), + Value subjectId = const Value.absent(), + Value updatedAt = const Value.absent()}) => + FhirResourceData( + id: id ?? this.id, + sourceId: sourceId.present ? sourceId.value : this.sourceId, + resourceType: + resourceType.present ? resourceType.value : this.resourceType, + resourceId: resourceId.present ? resourceId.value : this.resourceId, + title: title.present ? title.value : this.title, + date: date.present ? date.value : this.date, + resourceRaw: resourceRaw ?? this.resourceRaw, + encounterId: encounterId.present ? encounterId.value : this.encounterId, + subjectId: subjectId.present ? subjectId.value : this.subjectId, + updatedAt: updatedAt.present ? updatedAt.value : this.updatedAt, + ); + FhirResourceData copyWithCompanion(FhirResourceCompanion data) { + return FhirResourceData( + id: data.id.present ? data.id.value : this.id, + sourceId: data.sourceId.present ? data.sourceId.value : this.sourceId, + resourceType: data.resourceType.present + ? data.resourceType.value + : this.resourceType, + resourceId: + data.resourceId.present ? data.resourceId.value : this.resourceId, + title: data.title.present ? data.title.value : this.title, + date: data.date.present ? data.date.value : this.date, + resourceRaw: + data.resourceRaw.present ? data.resourceRaw.value : this.resourceRaw, + encounterId: + data.encounterId.present ? data.encounterId.value : this.encounterId, + subjectId: data.subjectId.present ? data.subjectId.value : this.subjectId, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ); + } + + @override + String toString() { + return (StringBuffer('FhirResourceData(') + ..write('id: $id, ') + ..write('sourceId: $sourceId, ') + ..write('resourceType: $resourceType, ') + ..write('resourceId: $resourceId, ') + ..write('title: $title, ') + ..write('date: $date, ') + ..write('resourceRaw: $resourceRaw, ') + ..write('encounterId: $encounterId, ') + ..write('subjectId: $subjectId, ') + ..write('updatedAt: $updatedAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, sourceId, resourceType, resourceId, title, + date, resourceRaw, encounterId, subjectId, updatedAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is FhirResourceData && + other.id == this.id && + other.sourceId == this.sourceId && + other.resourceType == this.resourceType && + other.resourceId == this.resourceId && + other.title == this.title && + other.date == this.date && + other.resourceRaw == this.resourceRaw && + other.encounterId == this.encounterId && + other.subjectId == this.subjectId && + other.updatedAt == this.updatedAt); +} + +class FhirResourceCompanion extends UpdateCompanion { + final Value id; + final Value sourceId; + final Value resourceType; + final Value resourceId; + final Value title; + final Value date; + final Value resourceRaw; + final Value encounterId; + final Value subjectId; + final Value updatedAt; + final Value rowid; + const FhirResourceCompanion({ + this.id = const Value.absent(), + this.sourceId = const Value.absent(), + this.resourceType = const Value.absent(), + this.resourceId = const Value.absent(), + this.title = const Value.absent(), + this.date = const Value.absent(), + this.resourceRaw = const Value.absent(), + this.encounterId = const Value.absent(), + this.subjectId = const Value.absent(), + this.updatedAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + FhirResourceCompanion.insert({ + required String id, + this.sourceId = const Value.absent(), + this.resourceType = const Value.absent(), + this.resourceId = const Value.absent(), + this.title = const Value.absent(), + this.date = const Value.absent(), + required String resourceRaw, + this.encounterId = const Value.absent(), + this.subjectId = const Value.absent(), + this.updatedAt = const Value.absent(), + this.rowid = const Value.absent(), + }) : id = Value(id), + resourceRaw = Value(resourceRaw); + static Insertable custom({ + Expression? id, + Expression? sourceId, + Expression? resourceType, + Expression? resourceId, + Expression? title, + Expression? date, + Expression? resourceRaw, + Expression? encounterId, + Expression? subjectId, + Expression? updatedAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (sourceId != null) 'source_id': sourceId, + if (resourceType != null) 'resource_type': resourceType, + if (resourceId != null) 'resource_id': resourceId, + if (title != null) 'title': title, + if (date != null) 'date': date, + if (resourceRaw != null) 'resource_raw': resourceRaw, + if (encounterId != null) 'encounter_id': encounterId, + if (subjectId != null) 'subject_id': subjectId, + if (updatedAt != null) 'updated_at': updatedAt, + if (rowid != null) 'rowid': rowid, + }); + } + + FhirResourceCompanion copyWith( + {Value? id, + Value? sourceId, + Value? resourceType, + Value? resourceId, + Value? title, + Value? date, + Value? resourceRaw, + Value? encounterId, + Value? subjectId, + Value? updatedAt, + Value? rowid}) { + return FhirResourceCompanion( + id: id ?? this.id, + sourceId: sourceId ?? this.sourceId, + resourceType: resourceType ?? this.resourceType, + resourceId: resourceId ?? this.resourceId, + title: title ?? this.title, + date: date ?? this.date, + resourceRaw: resourceRaw ?? this.resourceRaw, + encounterId: encounterId ?? this.encounterId, + subjectId: subjectId ?? this.subjectId, + updatedAt: updatedAt ?? this.updatedAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (sourceId.present) { + map['source_id'] = Variable(sourceId.value); + } + if (resourceType.present) { + map['resource_type'] = Variable(resourceType.value); + } + if (resourceId.present) { + map['resource_id'] = Variable(resourceId.value); + } + if (title.present) { + map['title'] = Variable(title.value); + } + if (date.present) { + map['date'] = Variable(date.value); + } + if (resourceRaw.present) { + map['resource_raw'] = Variable(resourceRaw.value); + } + if (encounterId.present) { + map['encounter_id'] = Variable(encounterId.value); + } + if (subjectId.present) { + map['subject_id'] = Variable(subjectId.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('FhirResourceCompanion(') + ..write('id: $id, ') + ..write('sourceId: $sourceId, ') + ..write('resourceType: $resourceType, ') + ..write('resourceId: $resourceId, ') + ..write('title: $title, ') + ..write('date: $date, ') + ..write('resourceRaw: $resourceRaw, ') + ..write('encounterId: $encounterId, ') + ..write('subjectId: $subjectId, ') + ..write('updatedAt: $updatedAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class Sources extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Sources(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn logo = GeneratedColumn( + 'logo', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn labelSource = GeneratedColumn( + 'label_source', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + @override + List get $columns => [id, name, logo, labelSource]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'sources'; + @override + Set get $primaryKey => {id}; + @override + SourcesData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SourcesData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}id'])!, + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name']), + logo: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}logo']), + labelSource: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}label_source']), + ); + } + + @override + Sources createAlias(String alias) { + return Sources(attachedDatabase, alias); + } +} + +class SourcesData extends DataClass implements Insertable { + final String id; + final String? name; + final String? logo; + final String? labelSource; + const SourcesData({required this.id, this.name, this.logo, this.labelSource}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + if (!nullToAbsent || name != null) { + map['name'] = Variable(name); + } + if (!nullToAbsent || logo != null) { + map['logo'] = Variable(logo); + } + if (!nullToAbsent || labelSource != null) { + map['label_source'] = Variable(labelSource); + } + return map; + } + + SourcesCompanion toCompanion(bool nullToAbsent) { + return SourcesCompanion( + id: Value(id), + name: name == null && nullToAbsent ? const Value.absent() : Value(name), + logo: logo == null && nullToAbsent ? const Value.absent() : Value(logo), + labelSource: labelSource == null && nullToAbsent + ? const Value.absent() + : Value(labelSource), + ); + } + + factory SourcesData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SourcesData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + logo: serializer.fromJson(json['logo']), + labelSource: serializer.fromJson(json['labelSource']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'logo': serializer.toJson(logo), + 'labelSource': serializer.toJson(labelSource), + }; + } + + SourcesData copyWith( + {String? id, + Value name = const Value.absent(), + Value logo = const Value.absent(), + Value labelSource = const Value.absent()}) => + SourcesData( + id: id ?? this.id, + name: name.present ? name.value : this.name, + logo: logo.present ? logo.value : this.logo, + labelSource: labelSource.present ? labelSource.value : this.labelSource, + ); + SourcesData copyWithCompanion(SourcesCompanion data) { + return SourcesData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + logo: data.logo.present ? data.logo.value : this.logo, + labelSource: + data.labelSource.present ? data.labelSource.value : this.labelSource, + ); + } + + @override + String toString() { + return (StringBuffer('SourcesData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('logo: $logo, ') + ..write('labelSource: $labelSource') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, name, logo, labelSource); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SourcesData && + other.id == this.id && + other.name == this.name && + other.logo == this.logo && + other.labelSource == this.labelSource); +} + +class SourcesCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value logo; + final Value labelSource; + final Value rowid; + const SourcesCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.logo = const Value.absent(), + this.labelSource = const Value.absent(), + this.rowid = const Value.absent(), + }); + SourcesCompanion.insert({ + required String id, + this.name = const Value.absent(), + this.logo = const Value.absent(), + this.labelSource = const Value.absent(), + this.rowid = const Value.absent(), + }) : id = Value(id); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? logo, + Expression? labelSource, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (logo != null) 'logo': logo, + if (labelSource != null) 'label_source': labelSource, + if (rowid != null) 'rowid': rowid, + }); + } + + SourcesCompanion copyWith( + {Value? id, + Value? name, + Value? logo, + Value? labelSource, + Value? rowid}) { + return SourcesCompanion( + id: id ?? this.id, + name: name ?? this.name, + logo: logo ?? this.logo, + labelSource: labelSource ?? this.labelSource, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (logo.present) { + map['logo'] = Variable(logo.value); + } + if (labelSource.present) { + map['label_source'] = Variable(labelSource.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SourcesCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('logo: $logo, ') + ..write('labelSource: $labelSource, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class RecordAttachments extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RecordAttachments(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn resourceId = GeneratedColumn( + 'resource_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('REFERENCES fhir_resource (id)')); + late final GeneratedColumn filePath = GeneratedColumn( + 'file_path', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn timestamp = GeneratedColumn( + 'timestamp', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + @override + List get $columns => [id, resourceId, filePath, timestamp]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'record_attachments'; + @override + Set get $primaryKey => {id}; + @override + RecordAttachmentsData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RecordAttachmentsData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + resourceId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}resource_id'])!, + filePath: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}file_path'])!, + timestamp: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}timestamp'])!, + ); + } + + @override + RecordAttachments createAlias(String alias) { + return RecordAttachments(attachedDatabase, alias); + } +} + +class RecordAttachmentsData extends DataClass + implements Insertable { + final int id; + final String resourceId; + final String filePath; + final DateTime timestamp; + const RecordAttachmentsData( + {required this.id, + required this.resourceId, + required this.filePath, + required this.timestamp}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['resource_id'] = Variable(resourceId); + map['file_path'] = Variable(filePath); + map['timestamp'] = Variable(timestamp); + return map; + } + + RecordAttachmentsCompanion toCompanion(bool nullToAbsent) { + return RecordAttachmentsCompanion( + id: Value(id), + resourceId: Value(resourceId), + filePath: Value(filePath), + timestamp: Value(timestamp), + ); + } + + factory RecordAttachmentsData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RecordAttachmentsData( + id: serializer.fromJson(json['id']), + resourceId: serializer.fromJson(json['resourceId']), + filePath: serializer.fromJson(json['filePath']), + timestamp: serializer.fromJson(json['timestamp']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'resourceId': serializer.toJson(resourceId), + 'filePath': serializer.toJson(filePath), + 'timestamp': serializer.toJson(timestamp), + }; + } + + RecordAttachmentsData copyWith( + {int? id, + String? resourceId, + String? filePath, + DateTime? timestamp}) => + RecordAttachmentsData( + id: id ?? this.id, + resourceId: resourceId ?? this.resourceId, + filePath: filePath ?? this.filePath, + timestamp: timestamp ?? this.timestamp, + ); + RecordAttachmentsData copyWithCompanion(RecordAttachmentsCompanion data) { + return RecordAttachmentsData( + id: data.id.present ? data.id.value : this.id, + resourceId: + data.resourceId.present ? data.resourceId.value : this.resourceId, + filePath: data.filePath.present ? data.filePath.value : this.filePath, + timestamp: data.timestamp.present ? data.timestamp.value : this.timestamp, + ); + } + + @override + String toString() { + return (StringBuffer('RecordAttachmentsData(') + ..write('id: $id, ') + ..write('resourceId: $resourceId, ') + ..write('filePath: $filePath, ') + ..write('timestamp: $timestamp') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, resourceId, filePath, timestamp); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RecordAttachmentsData && + other.id == this.id && + other.resourceId == this.resourceId && + other.filePath == this.filePath && + other.timestamp == this.timestamp); +} + +class RecordAttachmentsCompanion + extends UpdateCompanion { + final Value id; + final Value resourceId; + final Value filePath; + final Value timestamp; + const RecordAttachmentsCompanion({ + this.id = const Value.absent(), + this.resourceId = const Value.absent(), + this.filePath = const Value.absent(), + this.timestamp = const Value.absent(), + }); + RecordAttachmentsCompanion.insert({ + this.id = const Value.absent(), + required String resourceId, + required String filePath, + required DateTime timestamp, + }) : resourceId = Value(resourceId), + filePath = Value(filePath), + timestamp = Value(timestamp); + static Insertable custom({ + Expression? id, + Expression? resourceId, + Expression? filePath, + Expression? timestamp, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (resourceId != null) 'resource_id': resourceId, + if (filePath != null) 'file_path': filePath, + if (timestamp != null) 'timestamp': timestamp, + }); + } + + RecordAttachmentsCompanion copyWith( + {Value? id, + Value? resourceId, + Value? filePath, + Value? timestamp}) { + return RecordAttachmentsCompanion( + id: id ?? this.id, + resourceId: resourceId ?? this.resourceId, + filePath: filePath ?? this.filePath, + timestamp: timestamp ?? this.timestamp, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (resourceId.present) { + map['resource_id'] = Variable(resourceId.value); + } + if (filePath.present) { + map['file_path'] = Variable(filePath.value); + } + if (timestamp.present) { + map['timestamp'] = Variable(timestamp.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RecordAttachmentsCompanion(') + ..write('id: $id, ') + ..write('resourceId: $resourceId, ') + ..write('filePath: $filePath, ') + ..write('timestamp: $timestamp') + ..write(')')) + .toString(); + } +} + +class RecordNotes extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RecordNotes(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn resourceId = GeneratedColumn( + 'resource_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('REFERENCES fhir_resource (id)')); + late final GeneratedColumn content = GeneratedColumn( + 'content', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn timestamp = GeneratedColumn( + 'timestamp', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + @override + List get $columns => [id, resourceId, content, timestamp]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'record_notes'; + @override + Set get $primaryKey => {id}; + @override + RecordNotesData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RecordNotesData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + resourceId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}resource_id'])!, + content: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}content'])!, + timestamp: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}timestamp'])!, + ); + } + + @override + RecordNotes createAlias(String alias) { + return RecordNotes(attachedDatabase, alias); + } +} + +class RecordNotesData extends DataClass implements Insertable { + final int id; + final String resourceId; + final String content; + final DateTime timestamp; + const RecordNotesData( + {required this.id, + required this.resourceId, + required this.content, + required this.timestamp}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['resource_id'] = Variable(resourceId); + map['content'] = Variable(content); + map['timestamp'] = Variable(timestamp); + return map; + } + + RecordNotesCompanion toCompanion(bool nullToAbsent) { + return RecordNotesCompanion( + id: Value(id), + resourceId: Value(resourceId), + content: Value(content), + timestamp: Value(timestamp), + ); + } + + factory RecordNotesData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RecordNotesData( + id: serializer.fromJson(json['id']), + resourceId: serializer.fromJson(json['resourceId']), + content: serializer.fromJson(json['content']), + timestamp: serializer.fromJson(json['timestamp']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'resourceId': serializer.toJson(resourceId), + 'content': serializer.toJson(content), + 'timestamp': serializer.toJson(timestamp), + }; + } + + RecordNotesData copyWith( + {int? id, + String? resourceId, + String? content, + DateTime? timestamp}) => + RecordNotesData( + id: id ?? this.id, + resourceId: resourceId ?? this.resourceId, + content: content ?? this.content, + timestamp: timestamp ?? this.timestamp, + ); + RecordNotesData copyWithCompanion(RecordNotesCompanion data) { + return RecordNotesData( + id: data.id.present ? data.id.value : this.id, + resourceId: + data.resourceId.present ? data.resourceId.value : this.resourceId, + content: data.content.present ? data.content.value : this.content, + timestamp: data.timestamp.present ? data.timestamp.value : this.timestamp, + ); + } + + @override + String toString() { + return (StringBuffer('RecordNotesData(') + ..write('id: $id, ') + ..write('resourceId: $resourceId, ') + ..write('content: $content, ') + ..write('timestamp: $timestamp') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, resourceId, content, timestamp); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RecordNotesData && + other.id == this.id && + other.resourceId == this.resourceId && + other.content == this.content && + other.timestamp == this.timestamp); +} + +class RecordNotesCompanion extends UpdateCompanion { + final Value id; + final Value resourceId; + final Value content; + final Value timestamp; + const RecordNotesCompanion({ + this.id = const Value.absent(), + this.resourceId = const Value.absent(), + this.content = const Value.absent(), + this.timestamp = const Value.absent(), + }); + RecordNotesCompanion.insert({ + this.id = const Value.absent(), + required String resourceId, + required String content, + required DateTime timestamp, + }) : resourceId = Value(resourceId), + content = Value(content), + timestamp = Value(timestamp); + static Insertable custom({ + Expression? id, + Expression? resourceId, + Expression? content, + Expression? timestamp, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (resourceId != null) 'resource_id': resourceId, + if (content != null) 'content': content, + if (timestamp != null) 'timestamp': timestamp, + }); + } + + RecordNotesCompanion copyWith( + {Value? id, + Value? resourceId, + Value? content, + Value? timestamp}) { + return RecordNotesCompanion( + id: id ?? this.id, + resourceId: resourceId ?? this.resourceId, + content: content ?? this.content, + timestamp: timestamp ?? this.timestamp, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (resourceId.present) { + map['resource_id'] = Variable(resourceId.value); + } + if (content.present) { + map['content'] = Variable(content.value); + } + if (timestamp.present) { + map['timestamp'] = Variable(timestamp.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RecordNotesCompanion(') + ..write('id: $id, ') + ..write('resourceId: $resourceId, ') + ..write('content: $content, ') + ..write('timestamp: $timestamp') + ..write(')')) + .toString(); + } +} + +class DatabaseAtV5 extends GeneratedDatabase { + DatabaseAtV5(QueryExecutor e) : super(e); + late final FhirResource fhirResource = FhirResource(this); + late final Sources sources = Sources(this); + late final RecordAttachments recordAttachments = RecordAttachments(this); + late final RecordNotes recordNotes = RecordNotes(this); + late final Index resourceType = Index('resourceType', + 'CREATE INDEX resourceType ON fhir_resource (resource_type)'); + late final Index resourceId = Index( + 'resourceId', 'CREATE INDEX resourceId ON fhir_resource (resource_id)'); + @override + Iterable> get allTables => + allSchemaEntities.whereType>(); + @override + List get allSchemaEntities => [ + fhirResource, + sources, + recordAttachments, + recordNotes, + resourceType, + resourceId + ]; + @override + int get schemaVersion => 5; +}