From fc16c7078a8d4f7ae5031d9ede64c499c5444abf Mon Sep 17 00:00:00 2001 From: Dharanish Date: Sat, 13 Jul 2024 15:09:17 +0200 Subject: [PATCH] Fix database issues --- .../core/models/sqlite/SQLiteEntryList.kt | 8 --- .../core/models/sqlite/SQLiteHabitList.kt | 34 +++++++++- .../src/jvmMain/resources/migrations/26.sql | 63 +++++++++++++------ .../core/commands/EditHabitCommandTest.kt | 2 +- .../core/models/sqlite/SQLiteHabitListTest.kt | 6 +- .../core/reminders/ReminderSchedulerTest.kt | 2 +- .../habits/list/HabitCardListCacheTest.kt | 4 +- 7 files changed, 83 insertions(+), 36 deletions(-) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/SQLiteEntryList.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/SQLiteEntryList.kt index 128accd13..62b7cb9d4 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/SQLiteEntryList.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/SQLiteEntryList.kt @@ -81,12 +81,4 @@ class SQLiteEntryList(database: Database) : EntryList() { override fun recomputeFrom(originalEntries: EntryList, frequency: Frequency, isNumerical: Boolean) { throw UnsupportedOperationException() } - - override fun clear() { - super.clear() - repository.execSQL( - "delete from repetitions where habit = ?", - habitId.toString() - ) - } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.kt index a70f41147..edb78636f 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.kt @@ -39,13 +39,23 @@ class SQLiteHabitList @Inject constructor(private val modelFactory: ModelFactory loaded = true list.groupId = this.groupId list.removeAll() - val records = repository.findAll("order by position") + val records = repository.findAll("order by group_id, position") + var shouldRebuildOrder = false + var currentGroup: Long? = null + var expectedPosition = 0 for (rec in records) { + if (currentGroup != rec.groupId) { + currentGroup = rec.groupId + expectedPosition = 0 + } + if (rec.position != expectedPosition) shouldRebuildOrder = true val h = modelFactory.buildHabit() rec.copyTo(h) (h.originalEntries as SQLiteEntryList).habitId = h.id if (h.groupId == list.groupId) list.add(h) + expectedPosition++ } + if (shouldRebuildOrder) rebuildOrder() } @Synchronized @@ -61,6 +71,26 @@ class SQLiteHabitList @Inject constructor(private val modelFactory: ModelFactory observable.notifyListeners() } + @Synchronized + private fun rebuildOrder() { + val records = repository.findAll("order by group_id, position") + repository.executeAsTransaction { + var currentGroup: Long? = null + var expectedPosition = 0 + for (r in records) { + if (currentGroup != r.groupId) { + currentGroup = r.groupId + expectedPosition = 0 + } + if (r.position != expectedPosition) { + r.position = expectedPosition + repository.save(r) + } + expectedPosition++ + } + } + } + @Synchronized override fun add(position: Int, habit: Habit) { loadRecords() @@ -137,6 +167,7 @@ class SQLiteHabitList @Inject constructor(private val modelFactory: ModelFactory h.originalEntries.clear() repository.remove(record) } + rebuildOrder() observable.notifyListeners() } @@ -189,6 +220,7 @@ class SQLiteHabitList @Inject constructor(private val modelFactory: ModelFactory @Synchronized override fun repair() { loadRecords() + rebuildOrder() observable.notifyListeners() } diff --git a/uhabits-core/src/jvmMain/resources/migrations/26.sql b/uhabits-core/src/jvmMain/resources/migrations/26.sql index 4548aa4b9..ec3d1c028 100644 --- a/uhabits-core/src/jvmMain/resources/migrations/26.sql +++ b/uhabits-core/src/jvmMain/resources/migrations/26.sql @@ -5,7 +5,22 @@ create table SharedIds ( insert into SharedIds (name, next_id) values ('habitandgroup', (select coalesce(max(id),0) from Habits) + 1 ); -alter table Habits rename to HabitsOld; +create table HabitGroups ( + id integer primary key, + archived integer, + color integer, + description text not null default "", + highlight integer, + name text, + position integer, + reminder_days integer not null default 127, + reminder_hour integer, + reminder_min integer, + question text not null default "", + uuid text +); + +alter table Habits rename to Habits_old; create table Habits ( id integer primary key, @@ -25,29 +40,37 @@ create table Habits ( target_value real not null default 0, unit text not null default "", question text, - uuid text + uuid text, + group_id integer, + group_uuid text, + foreign key(group_id) + references HabitGroups(id) + on update cascade + on delete cascade ); insert into Habits (id, archived, color, description, freq_den, freq_num, highlight, name, position, reminder_min, reminder_days, type, target_type, target_value, unit, question, uuid) select id, archived, color, description, freq_den, freq_num, highlight, name, position, reminder_min, reminder_days, type, target_type, target_value, unit, question, uuid -from HabitsOld; +from Habits_old; -drop table HabitsOld; +PRAGMA foreign_keys = OFF; +begin transaction; -create table HabitGroups ( - id integer primary key, - archived integer, - color integer, - description text not null default "", - highlight integer, - name text, - position integer, - reminder_days integer not null default 127, - reminder_hour integer, - reminder_min integer, - question text not null default "", - uuid text -); + alter table Repetitions rename to Repetitions_old; + create table Repetitions ( + id integer primary key autoincrement, + habit integer, + timestamp integer, + value integer not null, + notes text, + foreign key (habit) + references Habits(id) + on update cascade + on delete cascade + ); + insert into Repetitions select * from Repetitions_old; + drop table Repetitions_old; + drop table Habits_old; -alter table Habits add column group_uuid text references habitgroups(uuid); -alter table Habits add column group_id integer references habitgroups(id); \ No newline at end of file +commit; +PRAGMA foreign_keys = ON; \ No newline at end of file diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/commands/EditHabitCommandTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/commands/EditHabitCommandTest.kt index d17ab7e86..72f4a0d06 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/commands/EditHabitCommandTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/commands/EditHabitCommandTest.kt @@ -52,7 +52,7 @@ class EditHabitCommandTest : BaseUnitTest() { @Test fun testExecute() { - command = EditHabitCommand(habitList, habit.uuid!!, modified) + command = EditHabitCommand(habitList, habit.id!!, modified) val originalScore = habit.scores[today].value assertThat(habit.name, equalTo("original")) command.run() diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitListTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitListTest.kt index f08d14f42..12d7581d3 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitListTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitListTest.kt @@ -35,7 +35,6 @@ import org.junit.Assert.assertThrows import org.junit.Test import org.mockito.kotlin.mock import org.mockito.kotlin.verify -import java.util.ArrayList import kotlin.test.assertNull class SQLiteHabitListTest : BaseUnitTest() { @@ -49,6 +48,7 @@ class SQLiteHabitListTest : BaseUnitTest() { override fun setUp() { super.setUp() val db: Database = buildMemoryDatabase() + db.execute("PRAGMA foreign_keys = ON;") modelFactory = SQLModelFactory(db) habitList = SQLiteHabitList(modelFactory) fixtures = HabitFixtures(modelFactory, habitList) @@ -98,8 +98,8 @@ class SQLiteHabitListTest : BaseUnitTest() { habit.name = "Hello world with id" habit.id = 12300L habitList.add(habit) - assertThat(habit.id, equalTo(12300L)) - val record = repository.find(12300L) + assertThat(habit.id, equalTo(11L)) + val record = repository.find(11L) assertThat(record!!.name, equalTo(habit.name)) } diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.kt index 8772ce4d3..9aaf427d2 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.kt @@ -56,7 +56,7 @@ class ReminderSchedulerTest : BaseUnitTest() { habit = fixtures.createEmptyHabit() habit.id = habitId reminderScheduler = - ReminderScheduler(commandRunner, habitList, sys, widgetPreferences) + ReminderScheduler(commandRunner, habitList, habitGroupList, sys, widgetPreferences) setFixedTimeZone(TimeZone.getTimeZone("GMT-4")) } diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCacheTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCacheTest.kt index 264a64c6c..37d3574f3 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCacheTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCacheTest.kt @@ -82,8 +82,8 @@ class HabitCardListCacheTest : BaseUnitTest() { val h = habitList.getByPosition(3) val score = h.scores[today].value assertThat(cache.getHabitByPosition(3), equalTo(h)) - assertThat(cache.getScore(h.uuid!!), equalTo(score)) - val actualCheckmarks = cache.getCheckmarks(h.uuid!!) + assertThat(cache.getScore(h.id!!), equalTo(score)) + val actualCheckmarks = cache.getCheckmarks(h.id!!) val expectedCheckmarks = h .computedEntries