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

Commit f78a4f03 authored by Marco Nelissen's avatar Marco Nelissen Committed by elektroschmock
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 dcf4128e
Loading
Loading
Loading
Loading
+29 −11
Original line number Diff line number Diff line
@@ -1447,24 +1447,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);