Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8ab2dc2f authored by Marco Nelissen's avatar Marco Nelissen
Browse files

Improve scan time for some cases

When the path being matched has a sqlite wildcard character in it, a "like"
match will be quite slow. Unfortunately this is fairly common, since "_"
is a wildcard character. However, because in most cases the case of the path
in the database will match the case on disk, an "=" match will work, so it
is worthwhile to try an "=" match first, before trying a "like".

If there are no wildcard characters, the "like" will be as fast as the "=",
because of the case-insensitive index on the _data column, so there is no
need to try "=" first in that case.

b/6751354

Change-Id: I1cd4efbd56a37886cb44a86acb73eb9a3c9f303d
parent b1758cf8
Loading
Loading
Loading
Loading
+29 −11
Original line number Diff line number Diff line
@@ -1463,24 +1463,42 @@ public class MediaScanner
    }

    FileEntry makeEntryFor(String path) {
        String key = path;
        String where;
        String[] selectionArgs;
        if (mCaseInsensitivePaths) {
            // the 'like' makes it use the index, the 'lower()' makes it correct
            // when the path contains sqlite wildcard characters
            where = "_data LIKE ?1 AND lower(_data)=lower(?1)";

        Cursor c = null;
        try {
            boolean hasWildCards = path.contains("_") || path.contains("%");

            if (hasWildCards || !mCaseInsensitivePaths) {
                // if there are wildcard characters in the path, the "like" match
                // will be slow, and it's worth trying an "=" comparison
                // first, since in most cases the case will match.
                // Also, we shouldn't do a "like" match on case-sensitive filesystems
                where = Files.FileColumns.DATA + "=?";
                selectionArgs = new String[] { path };
            } else {
            where = Files.FileColumns.DATA + "=?";
                // if there are no wildcard characters in the path, then the "like"
                // match will be just as fast as the "=" case, because of the index
                where = "_data LIKE ?1 AND lower(_data)=lower(?1)";
                selectionArgs = new String[] { path };
            }

        Cursor c = null;
        try {
            c = mMediaProvider.query(mFilesUri, FILES_PRESCAN_PROJECTION,
                    where, selectionArgs, null, null);
            if (c.moveToNext()) {
            if (!c.moveToFirst() && hasWildCards && mCaseInsensitivePaths) {
                // Try again with case-insensitive match. This will be slower, especially
                // if the path contains wildcard characters.
                // The 'like' makes it use the index, the 'lower()' makes it correct
                // when the path contains sqlite wildcard characters,
                where = "_data LIKE ?1 AND lower(_data)=lower(?1)";
                selectionArgs = new String[] { path };
                c.close();
                c = mMediaProvider.query(mFilesUri, FILES_PRESCAN_PROJECTION,
                        where, selectionArgs, null, null);
                // TODO update the path in the db with the correct case so the fast
                // path works next time?
            }
            if (c.moveToFirst()) {
                long rowId = c.getLong(FILES_PRESCAN_ID_COLUMN_INDEX);
                int format = c.getInt(FILES_PRESCAN_FORMAT_COLUMN_INDEX);
                long lastModified = c.getLong(FILES_PRESCAN_DATE_MODIFIED_COLUMN_INDEX);