Commit 0ee3c8f
Changed files (10)
health_data_store
lib
health_data_store/lib/src/repositories/blood_pressure_repository_impl.dart
@@ -33,21 +33,29 @@ class BloodPressureRepositoryImpl extends BloodPressureRepository {
final entryID = await DBHelper.getEntryID(
txn,
timeSec,
- ['Systolic', 'Diastolic', 'Pulse'],
);
if (record.sys != null) {
+ await txn.delete('Systolic', where: 'entryID = ?',
+ whereArgs: [entryID],
+ );
await txn.insert('Systolic', {
'entryID': entryID,
'sys': record.sys!.kPa,
});
}
if (record.dia != null) {
+ await txn.delete('Diastolic', where: 'entryID = ?',
+ whereArgs: [entryID],
+ );
await txn.insert('Diastolic', {
'entryID': entryID,
'dia': record.dia!.kPa,
});
}
if (record.pul != null) {
+ await txn.delete('Pulse', where: 'entryID = ?',
+ whereArgs: [entryID],
+ );
await txn.insert('Pulse', {
'entryID': entryID,
'pul': record.pul,
health_data_store/lib/src/repositories/medicine_intake_repository_impl.dart
@@ -30,8 +30,8 @@ class MedicineIntakeRepositoryImpl extends MedicineIntakeRepository {
final medIDRes = await txn.query('Medicine',
columns: ['medID'],
where: 'designation = ? '
- 'AND color ' +((intake.medicine.color != null) ? '= ?' : 'IS NULL')
- + ' AND defaultDose ' +((intake.medicine.dosis != null) ? '= ?':'IS '
+ 'AND color ' + ((intake.medicine.color != null) ? '= ?' : 'IS NULL')
+ + ' AND defaultDose ' + ((intake.medicine.dosis != null) ? '= ?':'IS '
'NULL'),
whereArgs: [
intake.medicine.designation,
@@ -46,10 +46,8 @@ class MedicineIntakeRepositoryImpl extends MedicineIntakeRepository {
final medID = medIDRes.first['medID'];
// obtain free entry id
- final id = await DBHelper.getEntryID(
- txn, intake.time.secondsSinceEpoch,
- ['Intake'],
- );
+ final id = await DBHelper.getEntryID(txn, intake.time.secondsSinceEpoch);
+ await txn.delete('Intake', where: 'entryID = ?', whereArgs: [id]);
// store to db
await txn.insert('Intake', {
health_data_store/lib/src/repositories/note_repository_impl.dart
@@ -27,9 +27,9 @@ class NoteRepositoryImpl extends NoteRepository {
return;
}
await _db.transaction((txn) async {
- final id = await DBHelper.getEntryID(
- txn, note.time.secondsSinceEpoch,
- ['Notes'],
+ final id = await DBHelper.getEntryID(txn, note.time.secondsSinceEpoch);
+ await txn.delete('Notes', where: 'entryID = ?',
+ whereArgs: [id],
);
await txn.insert('Notes', {
'entryID': id,
health_data_store/lib/src/repositories/repository.dart
@@ -12,6 +12,10 @@ import 'package:health_data_store/src/types/date_range.dart';
/// to avoid exposing the constructor to the public api.
abstract class Repository<T> {
/// Adds a new value to the repository.
+ ///
+ /// If there is an existing value of that type at the same time it gets
+ /// overridden. This is to ensure no duplicate entries are inserted and only
+ /// the most up to date value is used.
Future<void> add(T value);
/// Attempts to remove a value from the repository.
health_data_store/lib/src/database_helper.dart
@@ -7,19 +7,16 @@ class DBHelper {
/// Get a entryID from the `Timestamps` table of a database.
///
- /// Ensures that the associated timestamp matches [timestampUnixS] and that
- /// it is used in no table with a name in [blockedTables]. Creates a entry
- /// when necessary
+ /// Ensures that the associated timestamp matches [timestampUnixS]. Creates a
+ /// new id when necessary.
static Future<int> getEntryID(
Transaction txn,
int timestampUnixS,
- List<String> blockedTables,
) async {
- var query = 'SELECT entryID FROM Timestamps WHERE timestampUnixS = ?';
- for (final t in blockedTables) {
- query += 'AND entryID NOT IN (SELECT entryID FROM $t)';
- }
- final existing = await txn.rawQuery(query, [timestampUnixS]);
+ final existing = await txn.rawQuery(
+ 'SELECT entryID FROM Timestamps WHERE timestampUnixS = ?',
+ [timestampUnixS],
+ );
int entryID;
if (existing.isEmpty) {
final result = await txn.query('Timestamps',
health_data_store/lib/src/database_manager.dart
@@ -105,10 +105,12 @@ class DatabaseManager {
/// - medicines that are marked as deleted and have no referencing intakes
/// - timestamp entries that have no
Future<void> performCleanup() => _db.transaction((txn) async {
+ // Remove medicines marked deleted with no remaining entries
await txn.rawDelete('DELETE FROM Medicine '
'WHERE removed = 1 '
'AND medID NOT IN (SELECT medID FROM Intake);',
);
+ // Remove unused entry ids
await txn.rawDelete('DELETE FROM Timestamps '
'WHERE entryID NOT IN (SELECT entryID FROM Intake)'
'AND entryID NOT IN (SELECT entryID FROM Systolic) '
health_data_store/test/src/repositories/blood_pressure_repository_test.dart
@@ -103,7 +103,7 @@ void main() {
));
expect(values3, isEmpty);
});
- test('should remove correct record when multiple are at same time', () async {
+ test('overrides when inserting multiple records are at same time', () async {
final db = await mockDBManager();
addTearDown(db.close);
final repo = BloodPressureRepositoryImpl(db.db);
@@ -111,8 +111,6 @@ void main() {
final r2 = mockRecord(time: 10000, sys: 678, dia: 457, pul: 458);
await repo.add(r1);
await repo.add(r2);
-
- await repo.remove(r1);
final values2 = await repo.get(DateRange(
start: DateTime.fromMillisecondsSinceEpoch(0),
end: DateTime.fromMillisecondsSinceEpoch(80000),
health_data_store/test/src/repositories/medicine_intake_repository_test.dart
@@ -82,19 +82,18 @@ void main() {
));
expect(values2, isEmpty);
});
- test('should remove correct intake when multiple are at same time', () async {
+ test('overrides when inserting multiple intakes are at same time', () async {
final db = await mockDBManager();
addTearDown(db.close);
final repo = MedicineIntakeRepositoryImpl(db.db);
final medRepo = MedicineRepositoryImpl(db.db);
final med = mockMedicine();
await medRepo.add(med);
- final i1 = mockIntake(med, time: 10000);
+ final i1 = mockIntake(med, time: 10000, dosis: 123);
final i2 = mockIntake(med, time: 10000, dosis: 458);
await repo.add(i1);
await repo.add(i2);
- await repo.remove(i1);
final values2 = await repo.get(DateRange(
start: DateTime.fromMillisecondsSinceEpoch(0),
end: DateTime.fromMillisecondsSinceEpoch(80000),
health_data_store/test/src/repositories/note_repository_test.dart
@@ -78,7 +78,6 @@ void main() {
));
expect(values, isEmpty);
});
-
test('should emit stream events on changes', () async {
final db = await mockDBManager();
addTearDown(db.close);
health_data_store/test/src/database_helper_test.dart
@@ -14,9 +14,9 @@ void main() {
));
addTearDown(db.close);
await db.db.transaction((txn) async {
- final entry1 = await DBHelper.getEntryID(txn, 123, []);
+ final entry1 = await DBHelper.getEntryID(txn, 123);
expect(entry1, 1);
- final entry2 = await DBHelper.getEntryID(txn, 124, []);
+ final entry2 = await DBHelper.getEntryID(txn, 124);
expect(entry2, 2);
});
});
@@ -26,38 +26,10 @@ void main() {
));
addTearDown(db.close);
await db.db.transaction((txn) async {
- final entry1 = await DBHelper.getEntryID(txn, 123, []);
+ final entry1 = await DBHelper.getEntryID(txn, 123);
expect(entry1, 1);
- final entry1Again = await DBHelper.getEntryID(txn, 123, []);
+ final entry1Again = await DBHelper.getEntryID(txn, 123);
expect(entry1Again, 1);
});
});
- test('should find existing entryID with constraints', () async {
- final db = await DatabaseManager.load(await openDatabase(
- inMemoryDatabasePath,
- ));
- addTearDown(db.close);
- await db.db.transaction((txn) async {
- final entry1 = await DBHelper.getEntryID(txn, 123, []);
- expect(entry1, 1);
- final entry1Again = await DBHelper.getEntryID(txn, 123, ['Systolic']);
- expect(entry1Again, 1);
- });
- });
- test('should find respect constraints when finding entryID', () async {
- final db = await DatabaseManager.load(await openDatabase(
- inMemoryDatabasePath,
- ));
- addTearDown(db.close);
- await db.db.transaction((txn) async {
- final entry1 = await DBHelper.getEntryID(txn, 123, []);
- expect(entry1, 1);
- await txn.insert('Systolic', {
- 'entryID': entry1,
- 'sys': 1,
- });
- final anotherEntry = await DBHelper.getEntryID(txn, 123, ['Systolic']);
- expect(anotherEntry, 2);
- });
- });
}