Use RoomRawQuery

pull/3302/head
Alex Baker 10 months ago
parent 803a005dd8
commit 70dd8932a9

@ -1,176 +1,6 @@
package org.tasks.data package org.tasks.data
import androidx.room.util.getColumnIndex
import androidx.room.util.getColumnIndexOrThrow
import androidx.sqlite.SQLiteStatement import androidx.sqlite.SQLiteStatement
import org.tasks.data.entity.CaldavTask
import org.tasks.data.entity.Geofence
import org.tasks.data.entity.Place
import org.tasks.data.entity.Task
/*
room kmp doesn't support raw query yet 😢
https://issuetracker.google.com/issues/330586815
*/
fun SQLiteStatement.getTasks(): List<TaskContainer> {
val result = mutableListOf<TaskContainer>()
val _cursorIndexOfAccountType: Int = getColumnIndex(this, "accountType")
val _cursorIndexOfParentComplete: Int = getColumnIndex(this, "parentComplete")
val _cursorIndexOfTagsString: Int = getColumnIndex(this, "tags")
val _cursorIndexOfChildren: Int = getColumnIndex(this, "children")
val _cursorIndexOfSortGroup: Int = getColumnIndex(this, "sortGroup")
val _cursorIndexOfPrimarySort: Int = getColumnIndex(this, "primarySort")
val _cursorIndexOfSecondarySort: Int = getColumnIndex(this, "secondarySort")
val _cursorIndexOfIndent: Int = getColumnIndex(this, "indent")
val _cursorIndexOfId: Int = getColumnIndexOrThrow(this, "_id")
val _cursorIndexOfTitle: Int = getColumnIndexOrThrow(this, "title")
val _cursorIndexOfPriority: Int = getColumnIndexOrThrow(this, "importance")
val _cursorIndexOfDueDate: Int = getColumnIndexOrThrow(this, "dueDate")
val _cursorIndexOfHideUntil: Int = getColumnIndexOrThrow(this, "hideUntil")
val _cursorIndexOfCreationDate: Int = getColumnIndexOrThrow(this, "created")
val _cursorIndexOfModificationDate: Int = getColumnIndexOrThrow(this, "modified")
val _cursorIndexOfCompletionDate: Int = getColumnIndexOrThrow(this, "completed")
val _cursorIndexOfDeletionDate: Int = getColumnIndexOrThrow(this, "deleted")
val _cursorIndexOfNotes: Int = getColumnIndexOrThrow(this, "notes")
val _cursorIndexOfEstimatedSeconds: Int = getColumnIndexOrThrow(this, "estimatedSeconds")
val _cursorIndexOfElapsedSeconds: Int = getColumnIndexOrThrow(this, "elapsedSeconds")
val _cursorIndexOfTimerStart: Int = getColumnIndexOrThrow(this, "timerStart")
val _cursorIndexOfRingFlags: Int = getColumnIndexOrThrow(this, "notificationFlags")
val _cursorIndexOfReminderLast: Int = getColumnIndexOrThrow(this, "lastNotified")
val _cursorIndexOfRecurrence: Int = getColumnIndexOrThrow(this, "recurrence")
val _cursorIndexOfRepeatFrom: Int = getColumnIndexOrThrow(this, "repeat_from")
val _cursorIndexOfCalendarURI: Int = getColumnIndexOrThrow(this, "calendarUri")
val _cursorIndexOfRemoteId: Int = getColumnIndexOrThrow(this, "remoteId")
val _cursorIndexOfIsCollapsed: Int = getColumnIndexOrThrow(this, "collapsed")
val _cursorIndexOfParent: Int = getColumnIndexOrThrow(this, "parent")
val _cursorIndexOfOrder: Int = getColumnIndexOrThrow(this, "order")
val _cursorIndexOfReadOnly: Int = getColumnIndexOrThrow(this, "read_only")
val _cursorIndexOfId_1: Int = getColumnIndex(this, "cd_id")
val _cursorIndexOfTask: Int = getColumnIndex(this, "cd_task")
val _cursorIndexOfCalendar: Int = getColumnIndex(this, "cd_calendar")
val _cursorIndexOfRemoteId_1: Int = getColumnIndex(this, "cd_remote_id")
val _cursorIndexOfObj: Int = getColumnIndex(this, "cd_object")
val _cursorIndexOfEtag: Int = getColumnIndex(this, "cd_etag")
val _cursorIndexOfLastSync: Int = getColumnIndex(this, "cd_last_sync")
val _cursorIndexOfDeleted: Int = getColumnIndex(this, "cd_deleted")
val _cursorIndexOfRemoteParent: Int = getColumnIndex(this, "cd_remote_parent")
val _cursorIndexOfIsMoved: Int = getColumnIndex(this, "gt_moved")
val _cursorIndexOfRemoteOrder: Int = getColumnIndex(this, "gt_remote_order")
val _cursorIndexOfId_2: Int = getColumnIndex(this, "geofence_id")
val _cursorIndexOfTask_1: Int = getColumnIndex(this, "task")
val _cursorIndexOfPlace: Int = getColumnIndex(this, "place")
val _cursorIndexOfIsArrival: Int = getColumnIndex(this, "arrival")
val _cursorIndexOfIsDeparture: Int = getColumnIndex(this, "departure")
val _cursorIndexOfId_3: Int = getColumnIndex(this, "place_id")
val _cursorIndexOfUid: Int = getColumnIndex(this, "uid")
val _cursorIndexOfName: Int = getColumnIndex(this, "name")
val _cursorIndexOfAddress: Int = getColumnIndex(this, "address")
val _cursorIndexOfPhone: Int = getColumnIndex(this, "phone")
val _cursorIndexOfUrl: Int = getColumnIndex(this, "url")
val _cursorIndexOfLatitude: Int = getColumnIndex(this, "latitude")
val _cursorIndexOfLongitude: Int = getColumnIndex(this, "longitude")
val _cursorIndexOfColor: Int = getColumnIndex(this, "place_color")
val _cursorIndexOfIcon: Int = getColumnIndex(this, "place_icon")
val _cursorIndexOfOrder_1: Int = getColumnIndex(this, "place_order")
val _cursorIndexOfRadius: Int = getColumnIndex(this, "radius")
while (step()) {
val task = Task(
id = getLong(_cursorIndexOfId),
title = getTextOrNull(_cursorIndexOfTitle),
priority = getInt(_cursorIndexOfPriority),
dueDate = getLong(_cursorIndexOfDueDate),
hideUntil = getLong(_cursorIndexOfHideUntil),
creationDate = getLong(_cursorIndexOfCreationDate),
modificationDate = getLong(_cursorIndexOfModificationDate),
completionDate = getLong(_cursorIndexOfCompletionDate),
deletionDate = getLong(_cursorIndexOfDeletionDate),
notes = getTextOrNull(_cursorIndexOfNotes),
estimatedSeconds = getInt(_cursorIndexOfEstimatedSeconds),
elapsedSeconds = getInt(_cursorIndexOfElapsedSeconds),
timerStart = getLong(_cursorIndexOfTimerStart),
ringFlags = getInt(_cursorIndexOfRingFlags),
reminderLast = getLong(_cursorIndexOfReminderLast),
recurrence = getTextOrNull(_cursorIndexOfRecurrence),
repeatFrom = getInt(_cursorIndexOfRepeatFrom),
calendarURI = getTextOrNull(_cursorIndexOfCalendarURI),
remoteId = getTextOrNull(_cursorIndexOfRemoteId),
isCollapsed = getBoolean(_cursorIndexOfIsCollapsed),
parent = getLong(_cursorIndexOfParent),
order = getLongOrNull(_cursorIndexOfOrder),
readOnly = getBoolean(_cursorIndexOfReadOnly),
)
val caldavTask = getLongOrNull(_cursorIndexOfId_1)?.takeIf { it > 0 }?.let {
CaldavTask(
id = it,
task = getLong(_cursorIndexOfTask),
calendar = getTextOrNull(_cursorIndexOfCalendar),
remoteId = getTextOrNull(_cursorIndexOfRemoteId_1),
obj = getTextOrNull(_cursorIndexOfObj),
etag = getTextOrNull(_cursorIndexOfEtag),
lastSync = getLong(_cursorIndexOfLastSync),
deleted = getLong(_cursorIndexOfDeleted),
remoteParent = getTextOrNull(_cursorIndexOfRemoteParent),
isMoved = getBoolean(_cursorIndexOfIsMoved),
remoteOrder = getLong(_cursorIndexOfRemoteOrder),
)
}
val accountType = getIntOrNull(_cursorIndexOfAccountType) ?: 0
val geofence = getLongOrNull(_cursorIndexOfId_2)?.takeIf { it > 0 }?.let {
Geofence(
id = it,
task = getLong(_cursorIndexOfTask_1),
place = getTextOrNull(_cursorIndexOfPlace),
isArrival = getBoolean(_cursorIndexOfIsArrival),
isDeparture = getBoolean(_cursorIndexOfIsDeparture),
)
}
val place = getLongOrNull(_cursorIndexOfId_3)?.takeIf { it > 0 }?.let {
Place(
id = it,
uid = getTextOrNull(_cursorIndexOfUid),
name = getTextOrNull(_cursorIndexOfName),
address = getTextOrNull(_cursorIndexOfAddress),
phone = getTextOrNull(_cursorIndexOfPhone),
url = getTextOrNull(_cursorIndexOfUrl),
latitude = getDouble(_cursorIndexOfLatitude),
longitude = getDouble(_cursorIndexOfLongitude),
color = getInt(_cursorIndexOfColor),
icon = getTextOrNull(_cursorIndexOfIcon),
order = getInt(_cursorIndexOfOrder_1),
radius = getInt(_cursorIndexOfRadius),
)
}
result.add(
TaskContainer(
task = task,
caldavTask = caldavTask,
accountType = accountType,
location = if (geofence != null && place != null) {
Location(geofence, place)
} else {
null
},
tagsString = getTextOrNull(_cursorIndexOfTagsString),
indent = getIntOrNull(_cursorIndexOfIndent) ?: 0,
sortGroup = getLongOrNull(_cursorIndexOfSortGroup),
children = getIntOrNull(_cursorIndexOfChildren) ?: 0,
primarySort = getLongOrNull(_cursorIndexOfPrimarySort) ?: 0,
secondarySort = getLongOrNull(_cursorIndexOfSecondarySort) ?: 0,
parentComplete = getBooleanOrNull(_cursorIndexOfParentComplete) ?: false,
)
)
}
return result
}
fun SQLiteStatement.getTextOrNull(index: Int): String? = fun SQLiteStatement.getTextOrNull(index: Int): String? =
if (index == -1 || isNull(index)) null else this.getText(index) if (index == -1 || isNull(index)) null else this.getText(index)
private fun SQLiteStatement.getLongOrNull(index: Int): Long? =
if (index == -1 || isNull(index)) null else this.getLong(index)
private fun SQLiteStatement.getIntOrNull(index: Int): Int? =
if (index == -1 || isNull(index)) null else this.getInt(index)
private fun SQLiteStatement.getBooleanOrNull(index: Int): Boolean? =
if (index == -1 || isNull(index)) null else this.getBoolean(index)

@ -3,6 +3,8 @@ package org.tasks.data.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import androidx.room.RawQuery
import androidx.room.RoomRawQuery
import androidx.room.Update import androidx.room.Update
import androidx.room.execSQL import androidx.room.execSQL
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
@ -14,8 +16,6 @@ import org.tasks.data.db.SuspendDbUtils.chunkedMap
import org.tasks.data.db.SuspendDbUtils.eachChunk import org.tasks.data.db.SuspendDbUtils.eachChunk
import org.tasks.data.entity.Alarm import org.tasks.data.entity.Alarm
import org.tasks.data.entity.Task import org.tasks.data.entity.Task
import org.tasks.data.getTasks
import org.tasks.data.rawQuery
import org.tasks.data.sql.Criterion import org.tasks.data.sql.Criterion
import org.tasks.data.sql.Functions import org.tasks.data.sql.Functions
import org.tasks.data.withTransaction import org.tasks.data.withTransaction
@ -118,18 +118,22 @@ FROM (
for (i in 0 until last) { for (i in 0 until last) {
execSQL(queries[i]) execSQL(queries[i])
} }
val result = usePrepared(queries[last]) { it.getTasks() } val result = fetchTasks(queries[last])
Logger.v("TaskDao") { Logger.v("TaskDao") {
"${DateTimeUtils2.currentTimeMillis() - start}ms: ${queries.joinToString(";\n")}" "${DateTimeUtils2.currentTimeMillis() - start}ms: ${queries.joinToString(";\n")}"
} }
result result
} }
suspend fun fetchTasks(query: String): List<TaskContainer> = suspend fun fetchTasks(query: String): List<TaskContainer> = fetchRaw(RoomRawQuery(query))
database.rawQuery(query) { it.getTasks() }
suspend fun countRaw(query: String): Int = @RawQuery
database.rawQuery(query) { if (it.step()) it.getInt(0) else 0 } internal abstract suspend fun fetchRaw(query: RoomRawQuery): List<TaskContainer>
suspend fun countRaw(query: String): Int = countRaw(RoomRawQuery(query))
@RawQuery
internal abstract suspend fun countRaw(query: RoomRawQuery): Int
suspend fun touch(ids: List<Long>, now: Long = DateTimeUtils2.currentTimeMillis()) = suspend fun touch(ids: List<Long>, now: Long = DateTimeUtils2.currentTimeMillis()) =
ids.eachChunk { internalTouch(it, now) } ids.eachChunk { internalTouch(it, now) }

Loading…
Cancel
Save