package com.fsck.k9.local; import android.app.Application; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.text.TextUtils; import android.util.Log; import com.fsck.k9.Account; import com.fsck.k9.K9; import com.fsck.k9.Preferences; import com.fsck.k9.helper.UrlEncodingHelper; import com.fsck.k9.helper.Utility; import com.fsck.k9.mail.Flag; import com.fsck.k9.mail.Folder; import com.fsck.k9.mail.MessageRetrievalListener; import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.Store; import com.fsck.k9.mail.store.RemoteStore; import com.fsck.k9.local.StorageManager.StorageProvider; import com.fsck.k9.mail.store.StoreConfig; import com.fsck.k9.local.LockableDatabase.DbCallback; import com.fsck.k9.local.LockableDatabase.WrappedException; import com.fsck.k9.provider.EmailProvider; import com.fsck.k9.provider.EmailProvider.MessageColumns; import com.fsck.k9.search.LocalSearch; import com.fsck.k9.search.SearchSpecification.Attribute; import com.fsck.k9.search.SearchSpecification.Searchfield; import com.fsck.k9.search.SqlQueryBuilder; import java.io.File; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** *
* Implements a SQLite database backed local store for Messages. **/ public class LocalStore extends Store implements Serializable { private static final long serialVersionUID = -5142141896809423072L; static final String[] EMPTY_STRING_ARRAY = new String[0]; static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; /** * Lock objects indexed by account UUID. * * @see #getInstance(Account, Application) */ private static ConcurrentMap
* At the time of this writing (2012-12-06) SQLite only supports around 1000 arguments. That's * why we have to split SQL statements with a large set of arguments into multiple SQL * statements each working on a subset of the arguments. *
* * @param selectionCallback * Supplies the argument set and the code to query/update the database. * @param batchSize * The maximum size of the selection set in each SQL statement. * * @throws MessagingException */ public void doBatchSetSelection(final BatchSetSelection selectionCallback, final int batchSize) throws MessagingException { final List
* The goal of this method is to be fast. Currently this means using as few SQL UPDATE
* statements as possible.
*
* @param messageIds
* A list of primary keys in the "messages" table.
* @param flag
* The flag to change. This must be a flag with a separate column in the database.
* @param newState
* {@code true}, if the flag should be set. {@code false}, otherwise.
*
* @throws MessagingException
*/
public void setFlag(final List
* The goal of this method is to be fast. Currently this means using as few SQL UPDATE
* statements as possible.
*
* @param threadRootIds
* A list of root thread IDs.
* @param flag
* The flag to change. This must be a flag with a separate column in the database.
* @param newState
* {@code true}, if the flag should be set. {@code false}, otherwise.
*
* @throws MessagingException
*/
public void setFlagForThreads(final List