Improve recursive query performance

gtask_related_email
Alex Baker 5 years ago
parent 3fac672f1e
commit 83642e25d7

File diff suppressed because it is too large Load Diff

@ -58,7 +58,7 @@ import org.tasks.notifications.NotificationDao;
CaldavAccount.class,
GoogleTaskAccount.class
},
version = 65)
version = 66)
public abstract class Database extends RoomDatabase {
public static final String NAME = "database";

@ -5,11 +5,19 @@ import static com.todoroo.astrid.helper.UUIDHelper.newUUID;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.Index;
import androidx.room.PrimaryKey;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.Table;
@Entity(tableName = "caldav_tasks")
@Entity(
tableName = "caldav_tasks",
indices = {
@Index(name = "cd_task", value = "cd_task"),
@Index(
name = "cd_calendar_parent",
value = {"cd_calendar", "cd_parent"})
})
public class CaldavTask {
public static final String KEY = "caldav";

@ -7,16 +7,22 @@ import android.os.Parcelable;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.Index;
import androidx.room.PrimaryKey;
import com.todoroo.andlib.data.Property.LongProperty;
import com.todoroo.andlib.data.Property.StringProperty;
import com.todoroo.andlib.data.Table;
import java.io.Serializable;
@Entity(tableName = TABLE_NAME)
@Entity(tableName = TABLE_NAME, indices = @Index(name = "geo_task", value = "task"))
public class Geofence implements Serializable, Parcelable {
public static final String TABLE_NAME = "geofences";
public static final Table TABLE = new Table(TABLE_NAME);
public static final LongProperty TASK = new LongProperty(TABLE, "task");
public static final StringProperty PLACE = new StringProperty(TABLE, "place");
public static final Parcelable.Creator<Geofence> CREATOR =
new Parcelable.Creator<Geofence>() {
@Override

@ -3,11 +3,19 @@ package org.tasks.data;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.Index;
import androidx.room.PrimaryKey;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.Table;
@Entity(tableName = "google_tasks")
@Entity(
tableName = "google_tasks",
indices = {
@Index(name = "gt_task", value = "gt_task"),
@Index(
name = "gt_list_parent",
value = {"gt_list_id", "gt_parent"})
})
public class GoogleTask {
public static final String KEY = "gtasks"; // $NON-NLS-1$

@ -10,9 +10,11 @@ import android.os.Parcelable;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.Index;
import androidx.room.PrimaryKey;
import com.google.common.base.Strings;
import com.mapbox.api.geocoding.v5.models.CarmenFeature;
import com.todoroo.andlib.data.Property.StringProperty;
import com.todoroo.andlib.data.Table;
import com.todoroo.astrid.helper.UUIDHelper;
import java.io.Serializable;
@ -21,12 +23,14 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.tasks.location.MapPosition;
@Entity(tableName = TABLE_NAME)
@Entity(tableName = TABLE_NAME, indices = @Index(name = "place_uid", value = "uid", unique = true))
public class Place implements Serializable, Parcelable {
public static final String TABLE_NAME = "places";
public static final Table TABLE = new Table(TABLE_NAME);
public static final StringProperty UID = new StringProperty(TABLE, "uid");
public static final Parcelable.Creator<Place> CREATOR =
new Parcelable.Creator<Place>() {
@Override

@ -4,18 +4,19 @@ import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.Index;
import androidx.room.PrimaryKey;
import com.todoroo.andlib.data.Property.StringProperty;
import com.todoroo.andlib.data.Table;
import com.todoroo.astrid.data.Task;
import org.tasks.backup.XmlReader;
@Entity(tableName = "tags")
@Entity(tableName = "tags", indices = @Index(name = "tag_task", value = "task"))
public class Tag {
public static final String KEY = "tags-tag"; // $NON-NLS-1$
@Deprecated public static final Table TABLE = new Table("tags");
public static final Table TABLE = new Table("tags");
public static final StringProperty TASK_UID = new StringProperty(TABLE, "task_uid");
public static final StringProperty NAME = new StringProperty(TABLE, "name");

@ -315,6 +315,20 @@ public class Migrations {
}
};
private static final Migration MIGRATION_65_66 =
new Migration(65, 66) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("CREATE UNIQUE INDEX `place_uid` ON `places` (`uid`)");
database.execSQL("CREATE INDEX `geo_task` ON `geofences` (`task`)");
database.execSQL("CREATE INDEX `tag_task` ON `tags` (`task`)");
database.execSQL("CREATE INDEX `gt_list_parent` ON `google_tasks` (`gt_list_id`, `gt_parent`)");
database.execSQL("CREATE INDEX `gt_task` ON `google_tasks` (`gt_task`)");
database.execSQL("CREATE INDEX `cd_calendar_parent` ON `caldav_tasks` (`cd_calendar`, `cd_parent`)");
database.execSQL("CREATE INDEX `cd_task` ON `caldav_tasks` (`cd_task`)");
}
};
public static final Migration[] MIGRATIONS =
new Migration[] {
MIGRATION_35_36,
@ -337,7 +351,8 @@ public class Migrations {
MIGRATION_61_62,
MIGRATION_62_63,
MIGRATION_63_64,
MIGRATION_64_65
MIGRATION_64_65,
MIGRATION_65_66
};
private static Migration NOOP(int from, int to) {

@ -33,6 +33,7 @@ import com.todoroo.astrid.api.TagFilter;
import com.todoroo.astrid.core.SortHelper;
import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
import com.todoroo.astrid.data.Task;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
@ -41,9 +42,11 @@ import io.reactivex.schedulers.Schedulers;
import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
import org.tasks.data.CaldavCalendar;
import org.tasks.data.CaldavTask;
import org.tasks.data.Geofence;
import org.tasks.data.GoogleTask;
import org.tasks.data.GoogleTaskList;
import org.tasks.data.Place;
import org.tasks.data.Tag;
import org.tasks.data.TaskContainer;
@ -72,7 +75,7 @@ public class TaskListViewModel extends ViewModel implements Observer<PagedList<T
.as("tags");
private static final StringProperty TAGS_RECURSIVE =
new StringProperty(null, "(SELECT group_concat(distinct(tag_uid))\n" +
"FROM tags WHERE tags.task = recursive_tasks.task\n" +
"FROM tags WHERE tags.task = tasks._id\n" +
"GROUP BY tags.task)")
.as("tags");
@ -133,8 +136,8 @@ public class TaskListViewModel extends ViewModel implements Observer<PagedList<T
String joins =
Join.left(GoogleTask.TABLE.as(GTASK_METADATA_JOIN), gtaskJoinCriterion).toString()
+ Join.left(CaldavTask.TABLE.as(CALDAV_METADATA_JOIN), caldavJoinCriterion)
+ Join.left(Geofence.TABLE, field(Geofence.TABLE_NAME + ".task").eq(Task.ID))
+ Join.left(Place.TABLE, field(Place.TABLE_NAME + ".uid").eq(field("geofences.place")));
+ Join.left(Geofence.TABLE, Geofence.TASK.eq(Task.ID))
+ Join.left(Place.TABLE, Place.UID.eq(Geofence.PLACE));
if (atLeastLollipop()
&& (filter instanceof CaldavFilter
@ -150,31 +153,59 @@ public class TaskListViewModel extends ViewModel implements Observer<PagedList<T
fields.add(TAGS_RECURSIVE);
fields.add(INDENT);
String joinedQuery = Join.left(Task.TABLE, Task.ID.eq(RECURSIVE_TASK)) + joins;
String joinedQuery = Join.inner(Task.TABLE, Task.ID.eq(RECURSIVE_TASK)) + joins;
String parentQuery;
QueryTemplate subtaskQuery = new QueryTemplate();
if (filter instanceof CaldavFilter) {
Criterion criterion = CaldavFilter.getCriterion(((CaldavFilter) filter).getCalendar());
CaldavCalendar calendar = ((CaldavFilter) filter).getCalendar();
parentQuery =
new QueryTemplate()
.join(Join.left(CaldavTask.TABLE, Task.ID.eq(CaldavTask.TASK)))
.where(Criterion.and(criterion, CaldavTask.PARENT.eq(0)))
.join(
Join.inner(
CaldavTask.TABLE,
Criterion.and(
CaldavTask.CALENDAR.eq(calendar.getUuid()),
CaldavTask.PARENT.eq(0),
CaldavTask.TASK.eq(Task.ID),
CaldavTask.DELETED.eq(0))))
.where(TaskCriteria.activeAndVisible())
.toString();
subtaskQuery
.join(Join.inner(RECURSIVE, RECURSIVE_TASK.eq(CaldavTask.PARENT)))
.join(Join.left(CaldavTask.TABLE, Task.ID.eq(CaldavTask.TASK)))
.where(criterion);
.join(Join.inner(RECURSIVE, CaldavTask.PARENT.eq(RECURSIVE_TASK)))
.join(
Join.inner(
CaldavTask.TABLE,
Criterion.and(
CaldavTask.CALENDAR.eq(calendar.getUuid()),
CaldavTask.PARENT.gt(0),
CaldavTask.TASK.eq(Task.ID),
CaldavTask.DELETED.eq(0))))
.where(TaskCriteria.activeAndVisible());
} else {
Criterion criterion = GtasksFilter.getCriterion(((GtasksFilter) filter).getList());
GoogleTaskList list = ((GtasksFilter) filter).getList();
parentQuery =
new QueryTemplate()
.join(Join.left(GoogleTask.TABLE, Task.ID.eq(GoogleTask.TASK)))
.where(Criterion.and(criterion, GoogleTask.PARENT.eq(0)))
.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, RECURSIVE_TASK.eq(GoogleTask.PARENT)))
.join(Join.left(GoogleTask.TABLE, Task.ID.eq(GoogleTask.TASK)))
.where(criterion);
.join(Join.inner(RECURSIVE, GoogleTask.PARENT.eq(RECURSIVE_TASK)))
.join(
Join.inner(
GoogleTask.TABLE,
Criterion.and(
GoogleTask.LIST.eq(list.getRemoteId()),
GoogleTask.PARENT.gt(0),
GoogleTask.TASK.eq(Task.ID),
GoogleTask.DELETED.eq(0))))
.where(TaskCriteria.activeAndVisible());
}
String sortSelect = SortHelper.orderSelectForSortTypeRecursive(preferences.getSortMode());

Loading…
Cancel
Save