From 13e60d72d207205b186ad1a73437eb9e2bc0b9d1 Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Wed, 20 May 2020 13:40:12 -0500 Subject: [PATCH] Convert task list queries to Kotlin --- .../java/com/todoroo/astrid/dao/TaskDao.kt | 2 +- .../java/org/tasks/data/TaskListQuery.java | 263 ------------------ .../main/java/org/tasks/data/TaskListQuery.kt | 51 ++++ .../tasks/data/TaskListQueryNonRecursive.kt | 41 +++ .../org/tasks/data/TaskListQueryRecursive.kt | 139 +++++++++ 5 files changed, 232 insertions(+), 264 deletions(-) delete mode 100644 app/src/main/java/org/tasks/data/TaskListQuery.java create mode 100644 app/src/main/java/org/tasks/data/TaskListQuery.kt create mode 100644 app/src/main/java/org/tasks/data/TaskListQueryNonRecursive.kt create mode 100644 app/src/main/java/org/tasks/data/TaskListQueryRecursive.kt diff --git a/app/src/main/java/com/todoroo/astrid/dao/TaskDao.kt b/app/src/main/java/com/todoroo/astrid/dao/TaskDao.kt index 25439ef86..86662002d 100644 --- a/app/src/main/java/com/todoroo/astrid/dao/TaskDao.kt +++ b/app/src/main/java/com/todoroo/astrid/dao/TaskDao.kt @@ -125,7 +125,7 @@ abstract class TaskDao(private val database: Database) { db.execSQL(queries[i]) } val result = fetchTasks(SimpleSQLiteQuery(queries[last])) - Timber.v("%sms: %s", DateUtilities.now() - start, queries.joinToString(";")) + Timber.v("%sms: %s", DateUtilities.now() - start, queries.joinToString(";\n")) return result } diff --git a/app/src/main/java/org/tasks/data/TaskListQuery.java b/app/src/main/java/org/tasks/data/TaskListQuery.java deleted file mode 100644 index 0a664bc42..000000000 --- a/app/src/main/java/org/tasks/data/TaskListQuery.java +++ /dev/null @@ -1,263 +0,0 @@ -package org.tasks.data; - -import static com.google.common.collect.Lists.newArrayList; -import static com.todoroo.andlib.sql.Field.field; -import static com.todoroo.astrid.activity.TaskListFragment.CALDAV_METADATA_JOIN; -import static com.todoroo.astrid.activity.TaskListFragment.GTASK_METADATA_JOIN; -import static com.todoroo.astrid.activity.TaskListFragment.TAGS_METADATA_JOIN; - -import com.google.common.collect.ImmutableList; -import com.todoroo.andlib.data.Property.StringProperty; -import com.todoroo.andlib.data.Table; -import com.todoroo.andlib.sql.Criterion; -import com.todoroo.andlib.sql.Field; -import com.todoroo.andlib.sql.Join; -import com.todoroo.andlib.sql.Query; -import com.todoroo.andlib.sql.QueryTemplate; -import com.todoroo.astrid.api.CaldavFilter; -import com.todoroo.astrid.api.Filter; -import com.todoroo.astrid.api.GtasksFilter; -import com.todoroo.astrid.api.PermaSql; -import com.todoroo.astrid.core.SortHelper; -import com.todoroo.astrid.dao.TaskDao.TaskCriteria; -import com.todoroo.astrid.data.Task; -import java.util.ArrayList; -import java.util.List; -import org.tasks.preferences.Preferences; - -public class TaskListQuery { - - private static final Criterion JOIN_GTASK = - Criterion.and( - Task.ID.eq(field(GTASK_METADATA_JOIN + ".gt_task")), - field(GTASK_METADATA_JOIN + ".gt_deleted").eq(0)); - private static final Criterion JOIN_CALDAV = - Criterion.and( - Task.ID.eq(field(CALDAV_METADATA_JOIN + ".cd_task")), - field(CALDAV_METADATA_JOIN + ".cd_deleted").eq(0)); - private static final Criterion JOIN_TAGS = Task.ID.eq(field(TAGS_METADATA_JOIN + ".task")); - private static final String JOINS = - Join.left(GoogleTask.TABLE.as(GTASK_METADATA_JOIN), JOIN_GTASK).toString() - + Join.left(CaldavTask.TABLE.as(CALDAV_METADATA_JOIN), JOIN_CALDAV) - + Join.left(Geofence.TABLE, Geofence.TASK.eq(Task.ID)) - + Join.left(Place.TABLE, Place.UID.eq(Geofence.PLACE)); - - private static final Table RECURSIVE = new Table("recursive_tasks"); - private static final Field RECURSIVE_TASK = field(RECURSIVE + ".task"); - private static final Field TASKS = field("tasks.*"); - private static final Field GTASK = field(GTASK_METADATA_JOIN + ".*"); - private static final Field GEOFENCE = field("geofences.*"); - private static final Field PLACE = field("places.*"); - private static final Field CALDAV = field(CALDAV_METADATA_JOIN + ".*"); - private static final Field CHILDREN = field("children"); - private static final Field PRIMARY_SORT = field("primary_sort").as("primarySort"); - private static final Field SECONDARY_SORT = field("secondary_sort").as("secondarySort"); - private static final Field INDENT = field("indent"); - private static final Field TAG_QUERY = - field( - "(" - + Query.select(field("group_concat(distinct(tag_uid))")) - .from(Tag.TABLE) - .where(Task.ID.eq(Tag.TASK)) - .toString() - + " GROUP BY " - + Tag.TASK - + ")") - .as("tags"); - private static final StringProperty TAGS = - new StringProperty(null, "group_concat(distinct(" + TAGS_METADATA_JOIN + ".tag_uid)" + ")") - .as("tags"); - private static final List FIELDS = ImmutableList.of(TASKS, GTASK, CALDAV, GEOFENCE, PLACE); - - public static List getQuery( - Preferences preferences, com.todoroo.astrid.api.Filter filter, SubtaskInfo subtasks) { - - if (filter.supportsManualSort() && preferences.isManualSort()) { - return filter instanceof GtasksFilter || filter instanceof CaldavFilter - ? getRecursiveQuery(filter, preferences, subtasks) - : getNonRecursiveQuery(filter, preferences); - } - - if (filter.supportSubtasks() && subtasks.usesSubtasks() && preferences.showSubtasks()) { - return getRecursiveQuery(filter, preferences, subtasks); - } else { - return getNonRecursiveQuery(filter, preferences); - } - } - - private static List getRecursiveQuery( - com.todoroo.astrid.api.Filter filter, - Preferences preferences, - SubtaskInfo subtasks) { - List fields = new ArrayList<>(FIELDS); - fields.add(TAG_QUERY); - fields.add(INDENT); - fields.add(CHILDREN); - fields.add(PRIMARY_SORT); - fields.add(SECONDARY_SORT); - - String joinedQuery = - Join.inner(RECURSIVE, Task.ID.eq(RECURSIVE_TASK)) - + " LEFT JOIN (SELECT parent, count(distinct recursive_tasks.task) AS children FROM recursive_tasks GROUP BY parent) AS recursive_children ON recursive_children.parent = tasks._id " - + JOINS; - String where = " WHERE recursive_tasks.hidden = 0"; - String parentQuery; - QueryTemplate subtaskQuery = new QueryTemplate(); - if (filter instanceof CaldavFilter) { - CaldavCalendar calendar = ((CaldavFilter) filter).getCalendar(); - parentQuery = - new QueryTemplate() - .join( - Join.inner( - CaldavTask.TABLE, - Criterion.and( - CaldavTask.CALENDAR.eq(calendar.getUuid()), - CaldavTask.TASK.eq(Task.ID), - CaldavTask.DELETED.eq(0)))) - .where(Criterion.and(TaskCriteria.activeAndVisible(), Task.PARENT.eq(0))) - .toString(); - subtaskQuery - .join(Join.inner(RECURSIVE, Task.PARENT.eq(RECURSIVE_TASK))) - .join( - Join.inner(CaldavTask.TABLE, - Criterion.and(CaldavTask.TASK.eq(Task.ID), CaldavTask.DELETED.eq(0)))) - .where(TaskCriteria.activeAndVisible()); - } else if (filter instanceof GtasksFilter) { - GoogleTaskList list = ((GtasksFilter) filter).getList(); - parentQuery = - new QueryTemplate() - .join( - Join.inner( - GoogleTask.TABLE, - Criterion.and( - GoogleTask.LIST.eq(list.getRemoteId()), - GoogleTask.PARENT.eq(0), - GoogleTask.TASK.eq(Task.ID), - GoogleTask.DELETED.eq(0)))) - .where(TaskCriteria.activeAndVisible()) - .toString(); - subtaskQuery - .join(Join.inner(RECURSIVE, GoogleTask.PARENT.eq(RECURSIVE_TASK))) - .join( - Join.inner( - GoogleTask.TABLE, - Criterion.and(GoogleTask.TASK.eq(Task.ID), GoogleTask.DELETED.eq(0)))) - .where(TaskCriteria.activeAndVisible()); - } else { - parentQuery = PermaSql.replacePlaceholdersForQuery(filter.getSqlQuery()); - if (subtasks.hasGoogleSubtasks && subtasks.hasSubtasks) { - addGoogleAndCaldavSubtasks(subtaskQuery); - } else if (subtasks.hasGoogleSubtasks) { - addGoogleSubtasks(subtaskQuery); - } else { - addCaldavSubtasks(subtaskQuery); - } - subtaskQuery.where(TaskCriteria.activeAndVisible()); - joinedQuery += - " LEFT JOIN (SELECT task, max(indent) AS max_indent FROM recursive_tasks GROUP BY task) AS recursive_indents ON recursive_indents.task = tasks._id "; - where += " AND indent = max_indent "; - } - joinedQuery += where; - - boolean manualSort = preferences.isManualSort(); - boolean manualGtasks = manualSort && filter instanceof GtasksFilter; - boolean manualCaldav = manualSort && filter instanceof CaldavFilter; - int sortMode; - String sortField; - if (manualGtasks) { - sortMode = SortHelper.SORT_GTASKS; - sortField = "google_tasks.gt_order"; - } else if (manualCaldav) { - sortMode = SortHelper.SORT_CALDAV; - sortField = SortHelper.CALDAV_ORDER_COLUMN; - } else { - sortMode = preferences.getSortMode(); - sortField = "NULL"; - } - boolean reverseSort = preferences.isReverseSort() && sortMode != SortHelper.SORT_GTASKS; - String sortSelect = SortHelper.orderSelectForSortTypeRecursive(sortMode); - String withClause = - "CREATE TEMPORARY TABLE `recursive_tasks` AS\n" - + "WITH RECURSIVE recursive_tasks (task, parent, collapsed, hidden, indent, title, sortField, primary_sort, secondary_sort) AS (\n" - + " SELECT tasks._id, 0 as parent, tasks.collapsed as collapsed, 0 as hidden, 0 AS sort_indent, UPPER(tasks.title) AS sort_title, " - + sortSelect - + ", " + sortField + " as primary_sort, NULL as secondarySort" - + " FROM tasks\n" - + parentQuery - + "\nUNION ALL SELECT tasks._id, recursive_tasks.task as parent, tasks.collapsed as collapsed, CASE WHEN recursive_tasks.collapsed > 0 OR recursive_tasks.hidden > 0 THEN 1 ELSE 0 END as hidden, recursive_tasks.indent+1 AS sort_indent, UPPER(tasks.title) AS sort_title, " - + sortSelect - + ", recursive_tasks.primary_sort as primary_sort, " + sortField + " as secondary_sort" - + " FROM tasks\n" - + subtaskQuery - + "\nORDER BY sort_indent DESC, " - + SortHelper.orderForSortTypeRecursive(sortMode, reverseSort) - + ") SELECT * FROM recursive_tasks"; - - return newArrayList( - "DROP TABLE IF EXISTS `temp`.`recursive_tasks`", - SortHelper.adjustQueryForFlags(preferences, withClause), - "CREATE INDEX `r_tasks` ON `recursive_tasks` (`task`)", - "CREATE INDEX `r_parents` ON `recursive_tasks` (`parent`)", - Query.select(fields.toArray(new Field[0])) - .withQueryTemplate(PermaSql.replacePlaceholdersForQuery(joinedQuery)) - .from(Task.TABLE) - .toString()); - } - - private static List getNonRecursiveQuery(Filter filter, Preferences preferences) { - List fields = new ArrayList<>(FIELDS); - fields.add(TAGS); - - // TODO: For now, we'll modify the query to join and include the things like tag data here. - // Eventually, we might consider restructuring things so that this query is constructed - // elsewhere. - - String joinedQuery = - Join.left(Tag.TABLE.as(TAGS_METADATA_JOIN), JOIN_TAGS).toString() - + JOINS - + filter.getSqlQuery(); - - String query = - SortHelper.adjustQueryForFlagsAndSort(preferences, joinedQuery, preferences.getSortMode()); - - String groupedQuery = - query.contains("ORDER BY") - ? query.replace("ORDER BY", "GROUP BY " + Task.ID + " ORDER BY") - : query + " GROUP BY " + Task.ID; - - return newArrayList( - Query.select(fields.toArray(new Field[0])) - .withQueryTemplate(PermaSql.replacePlaceholdersForQuery(groupedQuery)) - .from(Task.TABLE) - .toString()); - } - - private static void addGoogleSubtasks(QueryTemplate subtaskQuery) { - subtaskQuery - .join(Join.inner(RECURSIVE, GoogleTask.PARENT.eq(RECURSIVE_TASK))) - .join( - Join.inner( - GoogleTask.TABLE, - Criterion.and(GoogleTask.TASK.eq(Task.ID), GoogleTask.DELETED.eq(0)))); - } - - private static void addCaldavSubtasks(QueryTemplate subtaskQuery) { - subtaskQuery.join(Join.inner(RECURSIVE, Task.PARENT.eq(RECURSIVE_TASK))); - } - - private static void addGoogleAndCaldavSubtasks(QueryTemplate subtaskQuery) { - subtaskQuery - .join( - Join.inner( - RECURSIVE, - Criterion.or(GoogleTask.PARENT.eq(RECURSIVE_TASK), Task.PARENT.eq(RECURSIVE_TASK)))) - .join( - Join.left( - GoogleTask.TABLE, - Criterion.and(GoogleTask.TASK.eq(Task.ID), GoogleTask.DELETED.eq(0)))) - .join( - Join.left( - CaldavTask.TABLE, - Criterion.and(CaldavTask.TASK.eq(Task.ID), CaldavTask.DELETED.eq(0)))); - } -} diff --git a/app/src/main/java/org/tasks/data/TaskListQuery.kt b/app/src/main/java/org/tasks/data/TaskListQuery.kt new file mode 100644 index 000000000..790fd98d2 --- /dev/null +++ b/app/src/main/java/org/tasks/data/TaskListQuery.kt @@ -0,0 +1,51 @@ +package org.tasks.data + +import com.todoroo.andlib.sql.Criterion +import com.todoroo.andlib.sql.Field.field +import com.todoroo.andlib.sql.Join +import com.todoroo.astrid.activity.TaskListFragment +import com.todoroo.astrid.api.CaldavFilter +import com.todoroo.astrid.api.Filter +import com.todoroo.astrid.api.GtasksFilter +import com.todoroo.astrid.data.Task +import okhttp3.internal.immutableListOf +import org.tasks.data.TaskListQueryNonRecursive.getNonRecursiveQuery +import org.tasks.data.TaskListQueryRecursive.getRecursiveQuery +import org.tasks.preferences.Preferences + +object TaskListQuery { + private val JOIN_GTASK = Criterion.and( + Task.ID.eq(field("${TaskListFragment.GTASK_METADATA_JOIN}.gt_task")), + field("${TaskListFragment.GTASK_METADATA_JOIN}.gt_deleted").eq(0)) + private val JOIN_CALDAV = Criterion.and( + Task.ID.eq(field("${TaskListFragment.CALDAV_METADATA_JOIN}.cd_task")), + field("${TaskListFragment.CALDAV_METADATA_JOIN}.cd_deleted").eq(0)) + val JOINS = """ + ${Join.left(GoogleTask.TABLE.`as`(TaskListFragment.GTASK_METADATA_JOIN), JOIN_GTASK)} + ${Join.left(CaldavTask.TABLE.`as`(TaskListFragment.CALDAV_METADATA_JOIN), JOIN_CALDAV)} + ${Join.left(Geofence.TABLE, Geofence.TASK.eq(Task.ID))} + ${Join.left(Place.TABLE, Place.UID.eq(Geofence.PLACE))} + """.trimIndent() + val FIELDS = immutableListOf( + field("tasks.*"), + field("${TaskListFragment.GTASK_METADATA_JOIN}.*"), + field("${TaskListFragment.CALDAV_METADATA_JOIN}.*"), + field("geofences.*"), + field("places.*")) + + @JvmStatic + fun getQuery(preferences: Preferences, filter: Filter, subtasks: SubtaskInfo): List { + if (filter.supportsManualSort() && preferences.isManualSort) { + return if (filter is GtasksFilter || filter is CaldavFilter) { + getRecursiveQuery(filter, preferences, subtasks) + } else { + getNonRecursiveQuery(filter, preferences) + } + } + return if (filter.supportSubtasks() && subtasks.usesSubtasks() && preferences.showSubtasks()) { + getRecursiveQuery(filter, preferences, subtasks) + } else { + getNonRecursiveQuery(filter, preferences) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/data/TaskListQueryNonRecursive.kt b/app/src/main/java/org/tasks/data/TaskListQueryNonRecursive.kt new file mode 100644 index 000000000..7960776c1 --- /dev/null +++ b/app/src/main/java/org/tasks/data/TaskListQueryNonRecursive.kt @@ -0,0 +1,41 @@ +package org.tasks.data + +import com.todoroo.andlib.data.Property.StringProperty +import com.todoroo.andlib.sql.Field +import com.todoroo.andlib.sql.Join +import com.todoroo.andlib.sql.Query +import com.todoroo.astrid.activity.TaskListFragment +import com.todoroo.astrid.api.Filter +import com.todoroo.astrid.api.PermaSql +import com.todoroo.astrid.core.SortHelper +import com.todoroo.astrid.data.Task +import org.tasks.preferences.Preferences + +internal object TaskListQueryNonRecursive { + private val JOIN_TAGS = Task.ID.eq(Field.field("${TaskListFragment.TAGS_METADATA_JOIN}.task")) + private val JOINS = """ + ${Join.left(Tag.TABLE.`as`(TaskListFragment.TAGS_METADATA_JOIN), JOIN_TAGS)} + ${TaskListQuery.JOINS} + """.trimIndent() + private val TAGS = + StringProperty( + null, + "group_concat(distinct(${TaskListFragment.TAGS_METADATA_JOIN}.tag_uid))") + .`as`("tags") + private val FIELDS = TaskListQuery.FIELDS.plus(TAGS).toTypedArray() + + fun getNonRecursiveQuery(filter: Filter, preferences: Preferences): List { + val joinedQuery = JOINS + filter.getSqlQuery() + val query = SortHelper.adjustQueryForFlagsAndSort(preferences, joinedQuery, preferences.sortMode) + val groupedQuery = if (query.contains("ORDER BY")) { + query.replace("ORDER BY", "GROUP BY ${Task.ID} ORDER BY") + } else { + "$query GROUP BY ${Task.ID}" + } + return listOf( + Query.select(*FIELDS) + .withQueryTemplate(PermaSql.replacePlaceholdersForQuery(groupedQuery)) + .from(Task.TABLE) + .toString()) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/data/TaskListQueryRecursive.kt b/app/src/main/java/org/tasks/data/TaskListQueryRecursive.kt new file mode 100644 index 000000000..dae392c6d --- /dev/null +++ b/app/src/main/java/org/tasks/data/TaskListQueryRecursive.kt @@ -0,0 +1,139 @@ +package org.tasks.data + +import com.todoroo.andlib.data.Table +import com.todoroo.andlib.sql.Criterion +import com.todoroo.andlib.sql.Field.field +import com.todoroo.andlib.sql.Join +import com.todoroo.andlib.sql.Query +import com.todoroo.andlib.sql.QueryTemplate +import com.todoroo.astrid.api.CaldavFilter +import com.todoroo.astrid.api.Filter +import com.todoroo.astrid.api.GtasksFilter +import com.todoroo.astrid.api.PermaSql +import com.todoroo.astrid.core.SortHelper +import com.todoroo.astrid.dao.TaskDao.TaskCriteria.activeAndVisible +import com.todoroo.astrid.data.Task +import org.tasks.preferences.Preferences + +internal object TaskListQueryRecursive { + private val RECURSIVE = Table("recursive_tasks") + private val RECURSIVE_TASK = field("$RECURSIVE.task") + private val FIELDS = + TaskListQuery.FIELDS.plus(listOf( + field("(${Query.select(field("group_concat(distinct(tag_uid))")).from(Tag.TABLE).where(Task.ID.eq(Tag.TASK))} GROUP BY ${Tag.TASK})").`as`("tags"), + field("indent"), + field("children"), + field("primary_sort").`as`("primarySort"), + field("secondary_sort").`as`("secondarySort"))).toTypedArray() + private val JOINS = """ + ${Join.inner(RECURSIVE, Task.ID.eq(RECURSIVE_TASK))} + LEFT JOIN (SELECT parent, count(distinct recursive_tasks.task) AS children FROM recursive_tasks GROUP BY parent) AS recursive_children ON recursive_children.parent = tasks._id + ${TaskListQuery.JOINS} + """.trimIndent() + private val GOOGLE_SUBTASKS = + QueryTemplate() + .join(Join.inner(RECURSIVE, GoogleTask.PARENT.eq(RECURSIVE_TASK))) + .join(Join.inner(GoogleTask.TABLE, Criterion.and(GoogleTask.TASK.eq(Task.ID), GoogleTask.DELETED.eq(0)))) + .where(activeAndVisible()) + private val CALDAV_SUBTASKS = + QueryTemplate() + .join(Join.inner(RECURSIVE, Task.PARENT.eq(RECURSIVE_TASK))) + .join(Join.inner(CaldavTask.TABLE, Criterion.and(CaldavTask.TASK.eq(Task.ID), CaldavTask.DELETED.eq(0)))) + .where(activeAndVisible()) + private val GOOGLE_AND_CALDAV_SUBTASKS = + QueryTemplate() + .join(Join.inner(RECURSIVE, Criterion.or(GoogleTask.PARENT.eq(RECURSIVE_TASK), Task.PARENT.eq(RECURSIVE_TASK)))) + .join(Join.left(GoogleTask.TABLE, Criterion.and(GoogleTask.TASK.eq(Task.ID), GoogleTask.DELETED.eq(0)))) + .join(Join.left(CaldavTask.TABLE, Criterion.and(CaldavTask.TASK.eq(Task.ID), CaldavTask.DELETED.eq(0)))) + .where(activeAndVisible()) + + fun getRecursiveQuery(filter: Filter, preferences: Preferences, subtasks: SubtaskInfo): List { + var joinedQuery = JOINS + var where = " WHERE recursive_tasks.hidden = 0" + val parentQuery: String + val subtaskQuery: QueryTemplate + when (filter) { + is CaldavFilter -> { + parentQuery = newCaldavQuery(filter) + subtaskQuery = CALDAV_SUBTASKS + } + is GtasksFilter -> { + parentQuery = newGoogleTaskQuery(filter) + subtaskQuery = GOOGLE_SUBTASKS + } + else -> { + parentQuery = PermaSql.replacePlaceholdersForQuery(filter.getSqlQuery()) + subtaskQuery = when { + subtasks.hasGoogleSubtasks && subtasks.hasSubtasks -> GOOGLE_AND_CALDAV_SUBTASKS + subtasks.hasGoogleSubtasks -> GOOGLE_SUBTASKS + else -> CALDAV_SUBTASKS + } + joinedQuery += " LEFT JOIN (SELECT task, max(indent) AS max_indent FROM recursive_tasks GROUP BY task) AS recursive_indents ON recursive_indents.task = tasks._id " + where += " AND indent = max_indent " + } + } + joinedQuery += where + val manualSort = preferences.isManualSort + val sortMode: Int + val sortField: String + when { + manualSort && filter is GtasksFilter -> { + sortMode = SortHelper.SORT_GTASKS + sortField = "google_tasks.gt_order" + } + manualSort && filter is CaldavFilter -> { + sortMode = SortHelper.SORT_CALDAV + sortField = SortHelper.CALDAV_ORDER_COLUMN + } + else -> { + sortMode = preferences.sortMode + sortField = "NULL" + } + } + val reverseSort = preferences.isReverseSort && sortMode != SortHelper.SORT_GTASKS && sortMode != SortHelper.SORT_CALDAV + val sortSelect = SortHelper.orderSelectForSortTypeRecursive(sortMode) + val withClause =""" + CREATE TEMPORARY TABLE `recursive_tasks` AS + WITH RECURSIVE recursive_tasks (task, parent, collapsed, hidden, indent, title, sortField, primary_sort, secondary_sort) AS ( + SELECT tasks._id, 0 as parent, tasks.collapsed as collapsed, 0 as hidden, 0 AS sort_indent, UPPER(tasks.title) AS sort_title, $sortSelect, $sortField as primary_sort, NULL as secondarySort FROM tasks + $parentQuery + UNION ALL SELECT tasks._id, recursive_tasks.task as parent, tasks.collapsed as collapsed, CASE WHEN recursive_tasks.collapsed > 0 OR recursive_tasks.hidden > 0 THEN 1 ELSE 0 END as hidden, recursive_tasks.indent+1 AS sort_indent, UPPER(tasks.title) AS sort_title, $sortSelect, recursive_tasks.primary_sort as primary_sort, $sortField as secondary_sort FROM tasks + $subtaskQuery + ORDER BY sort_indent DESC, ${SortHelper.orderForSortTypeRecursive(sortMode, reverseSort)} + ) SELECT * FROM recursive_tasks + """.trimIndent() + + return listOf( + "DROP TABLE IF EXISTS `temp`.`recursive_tasks`", + SortHelper.adjustQueryForFlags(preferences, withClause), + "CREATE INDEX `r_tasks` ON `recursive_tasks` (`task`)", + "CREATE INDEX `r_parents` ON `recursive_tasks` (`parent`)", + Query.select(*FIELDS) + .withQueryTemplate(PermaSql.replacePlaceholdersForQuery(joinedQuery)) + .from(Task.TABLE) + .toString()) + } + + private fun newCaldavQuery(filter: CaldavFilter) = + QueryTemplate() + .join(Join.inner( + CaldavTask.TABLE, + Criterion.and( + CaldavTask.CALENDAR.eq(filter.uuid), + CaldavTask.TASK.eq(Task.ID), + CaldavTask.DELETED.eq(0)))) + .where(Criterion.and(activeAndVisible(), Task.PARENT.eq(0))) + .toString() + + private fun newGoogleTaskQuery(filter: GtasksFilter) = + QueryTemplate() + .join(Join.inner( + GoogleTask.TABLE, + Criterion.and( + GoogleTask.LIST.eq(filter.remoteId), + GoogleTask.PARENT.eq(0), + GoogleTask.TASK.eq(Task.ID), + GoogleTask.DELETED.eq(0)))) + .where(activeAndVisible()) + .toString() +} \ No newline at end of file