SQLiteDatabase.java revision 119c106f8d0dc884b239c5d88b0fd43002b3e32d
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.database.sqlite;
18
19import com.google.android.collect.Maps;
20
21import android.app.ActivityThread;
22import android.content.ContentValues;
23import android.database.Cursor;
24import android.database.DatabaseErrorHandler;
25import android.database.DatabaseUtils;
26import android.database.DefaultDatabaseErrorHandler;
27import android.database.SQLException;
28import android.database.sqlite.SQLiteDebug.DbStats;
29import android.os.Debug;
30import android.os.SystemClock;
31import android.os.SystemProperties;
32import android.text.TextUtils;
33import android.util.Config;
34import android.util.EventLog;
35import android.util.Log;
36import android.util.Pair;
37
38import java.io.File;
39import java.lang.ref.WeakReference;
40import java.text.SimpleDateFormat;
41import java.util.ArrayList;
42import java.util.HashMap;
43import java.util.HashSet;
44import java.util.Iterator;
45import java.util.Locale;
46import java.util.Map;
47import java.util.Random;
48import java.util.Set;
49import java.util.WeakHashMap;
50import java.util.concurrent.locks.ReentrantLock;
51import java.util.regex.Pattern;
52
53/**
54 * Exposes methods to manage a SQLite database.
55 * <p>SQLiteDatabase has methods to create, delete, execute SQL commands, and
56 * perform other common database management tasks.
57 * <p>See the Notepad sample application in the SDK for an example of creating
58 * and managing a database.
59 * <p> Database names must be unique within an application, not across all
60 * applications.
61 *
62 * <h3>Localized Collation - ORDER BY</h3>
63 * <p>In addition to SQLite's default <code>BINARY</code> collator, Android supplies
64 * two more, <code>LOCALIZED</code>, which changes with the system's current locale
65 * if you wire it up correctly (XXX a link needed!), and <code>UNICODE</code>, which
66 * is the Unicode Collation Algorithm and not tailored to the current locale.
67 */
68public class SQLiteDatabase extends SQLiteClosable {
69    private static final String TAG = "Database";
70    private static final int EVENT_DB_OPERATION = 52000;
71    private static final int EVENT_DB_CORRUPT = 75004;
72
73    /**
74     * Algorithms used in ON CONFLICT clause
75     * http://www.sqlite.org/lang_conflict.html
76     */
77    /**
78     *  When a constraint violation occurs, an immediate ROLLBACK occurs,
79     * thus ending the current transaction, and the command aborts with a
80     * return code of SQLITE_CONSTRAINT. If no transaction is active
81     * (other than the implied transaction that is created on every command)
82     *  then this algorithm works the same as ABORT.
83     */
84    public static final int CONFLICT_ROLLBACK = 1;
85
86    /**
87     * When a constraint violation occurs,no ROLLBACK is executed
88     * so changes from prior commands within the same transaction
89     * are preserved. This is the default behavior.
90     */
91    public static final int CONFLICT_ABORT = 2;
92
93    /**
94     * When a constraint violation occurs, the command aborts with a return
95     * code SQLITE_CONSTRAINT. But any changes to the database that
96     * the command made prior to encountering the constraint violation
97     * are preserved and are not backed out.
98     */
99    public static final int CONFLICT_FAIL = 3;
100
101    /**
102     * When a constraint violation occurs, the one row that contains
103     * the constraint violation is not inserted or changed.
104     * But the command continues executing normally. Other rows before and
105     * after the row that contained the constraint violation continue to be
106     * inserted or updated normally. No error is returned.
107     */
108    public static final int CONFLICT_IGNORE = 4;
109
110    /**
111     * When a UNIQUE constraint violation occurs, the pre-existing rows that
112     * are causing the constraint violation are removed prior to inserting
113     * or updating the current row. Thus the insert or update always occurs.
114     * The command continues executing normally. No error is returned.
115     * If a NOT NULL constraint violation occurs, the NULL value is replaced
116     * by the default value for that column. If the column has no default
117     * value, then the ABORT algorithm is used. If a CHECK constraint
118     * violation occurs then the IGNORE algorithm is used. When this conflict
119     * resolution strategy deletes rows in order to satisfy a constraint,
120     * it does not invoke delete triggers on those rows.
121     *  This behavior might change in a future release.
122     */
123    public static final int CONFLICT_REPLACE = 5;
124
125    /**
126     * use the following when no conflict action is specified.
127     */
128    public static final int CONFLICT_NONE = 0;
129    private static final String[] CONFLICT_VALUES = new String[]
130            {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
131
132    /**
133     * Maximum Length Of A LIKE Or GLOB Pattern
134     * The pattern matching algorithm used in the default LIKE and GLOB implementation
135     * of SQLite can exhibit O(N^2) performance (where N is the number of characters in
136     * the pattern) for certain pathological cases. To avoid denial-of-service attacks
137     * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes.
138     * The default value of this limit is 50000. A modern workstation can evaluate
139     * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly.
140     * The denial of service problem only comes into play when the pattern length gets
141     * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns
142     * are at most a few dozen bytes in length, paranoid application developers may
143     * want to reduce this parameter to something in the range of a few hundred
144     * if they know that external users are able to generate arbitrary patterns.
145     */
146    public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000;
147
148    /**
149     * Flag for {@link #openDatabase} to open the database for reading and writing.
150     * If the disk is full, this may fail even before you actually write anything.
151     *
152     * {@more} Note that the value of this flag is 0, so it is the default.
153     */
154    public static final int OPEN_READWRITE = 0x00000000;          // update native code if changing
155
156    /**
157     * Flag for {@link #openDatabase} to open the database for reading only.
158     * This is the only reliable way to open a database if the disk may be full.
159     */
160    public static final int OPEN_READONLY = 0x00000001;           // update native code if changing
161
162    private static final int OPEN_READ_MASK = 0x00000001;         // update native code if changing
163
164    /**
165     * Flag for {@link #openDatabase} to open the database without support for localized collators.
166     *
167     * {@more} This causes the collator <code>LOCALIZED</code> not to be created.
168     * You must be consistent when using this flag to use the setting the database was
169     * created with.  If this is set, {@link #setLocale} will do nothing.
170     */
171    public static final int NO_LOCALIZED_COLLATORS = 0x00000010;  // update native code if changing
172
173    /**
174     * Flag for {@link #openDatabase} to create the database file if it does not already exist.
175     */
176    public static final int CREATE_IF_NECESSARY = 0x10000000;     // update native code if changing
177
178    /**
179     * Indicates whether the most-recently started transaction has been marked as successful.
180     */
181    private boolean mInnerTransactionIsSuccessful;
182
183    /**
184     * Valid during the life of a transaction, and indicates whether the entire transaction (the
185     * outer one and all of the inner ones) so far has been successful.
186     */
187    private boolean mTransactionIsSuccessful;
188
189    /**
190     * Valid during the life of a transaction.
191     */
192    private SQLiteTransactionListener mTransactionListener;
193
194    /** Synchronize on this when accessing the database */
195    private final ReentrantLock mLock = new ReentrantLock(true);
196
197    private long mLockAcquiredWallTime = 0L;
198    private long mLockAcquiredThreadTime = 0L;
199
200    // limit the frequency of complaints about each database to one within 20 sec
201    // unless run command adb shell setprop log.tag.Database VERBOSE
202    private static final int LOCK_WARNING_WINDOW_IN_MS = 20000;
203    /** If the lock is held this long then a warning will be printed when it is released. */
204    private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS = 300;
205    private static final int LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS = 100;
206    private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT = 2000;
207
208    private static final int SLEEP_AFTER_YIELD_QUANTUM = 1000;
209
210    // The pattern we remove from database filenames before
211    // potentially logging them.
212    private static final Pattern EMAIL_IN_DB_PATTERN = Pattern.compile("[\\w\\.\\-]+@[\\w\\.\\-]+");
213
214    private long mLastLockMessageTime = 0L;
215
216    // Things related to query logging/sampling for debugging
217    // slow/frequent queries during development.  Always log queries
218    // which take (by default) 500ms+; shorter queries are sampled
219    // accordingly.  Commit statements, which are typically slow, are
220    // logged together with the most recently executed SQL statement,
221    // for disambiguation.  The 500ms value is configurable via a
222    // SystemProperty, but developers actively debugging database I/O
223    // should probably use the regular log tunable,
224    // LOG_SLOW_QUERIES_PROPERTY, defined below.
225    private static int sQueryLogTimeInMillis = 0;  // lazily initialized
226    private static final int QUERY_LOG_SQL_LENGTH = 64;
227    private static final String COMMIT_SQL = "COMMIT;";
228    private final Random mRandom = new Random();
229    private String mLastSqlStatement = null;
230
231    // String prefix for slow database query EventLog records that show
232    // lock acquistions of the database.
233    /* package */ static final String GET_LOCK_LOG_PREFIX = "GETLOCK:";
234
235    /** Used by native code, do not rename */
236    /* package */ int mNativeHandle = 0;
237
238    /** Used to make temp table names unique */
239    /* package */ int mTempTableSequence = 0;
240
241    /** The path for the database file */
242    private String mPath;
243
244    /** The anonymized path for the database file for logging purposes */
245    private String mPathForLogs = null;  // lazily populated
246
247    /** The flags passed to open/create */
248    private int mFlags;
249
250    /** The optional factory to use when creating new Cursors */
251    private CursorFactory mFactory;
252
253    private WeakHashMap<SQLiteClosable, Object> mPrograms;
254
255    /**
256     * for each instance of this class, a cache is maintained to store
257     * the compiled query statement ids returned by sqlite database.
258     *     key = sql statement with "?" for bind args
259     *     value = {@link SQLiteCompiledSql}
260     * If an application opens the database and keeps it open during its entire life, then
261     * there will not be an overhead of compilation of sql statements by sqlite.
262     *
263     * why is this cache NOT static? because sqlite attaches compiledsql statements to the
264     * struct created when {@link SQLiteDatabase#openDatabase(String, CursorFactory, int)} is
265     * invoked.
266     *
267     * this cache has an upper limit of mMaxSqlCacheSize (settable by calling the method
268     * (@link setMaxCacheSize(int)}). its default is 0 - i.e., no caching by default because
269     * most of the apps don't use "?" syntax in their sql, caching is not useful for them.
270     */
271    /* package */ Map<String, SQLiteCompiledSql> mCompiledQueries = Maps.newHashMap();
272    /**
273     * absolute max value that can set by {@link #setMaxSqlCacheSize(int)}
274     * size of each prepared-statement is between 1K - 6K, depending on the complexity of the
275     * sql statement & schema.
276     */
277    public static final int MAX_SQL_CACHE_SIZE = 100;
278
279    // default statement-cache size per database connection ( = instance of this class)
280    private int mMaxSqlCacheSize = 25;
281
282    private int mCacheFullWarnings;
283    private static final int MAX_WARNINGS_ON_CACHESIZE_CONDITION = 1;
284
285    /** maintain stats about number of cache hits and misses */
286    private int mNumCacheHits;
287    private int mNumCacheMisses;
288
289    /** the following 2 members maintain the time when a database is opened and closed */
290    private String mTimeOpened = null;
291    private String mTimeClosed = null;
292
293    /** Used to find out where this object was created in case it never got closed. */
294    private Throwable mStackTrace = null;
295
296    // System property that enables logging of slow queries. Specify the threshold in ms.
297    private static final String LOG_SLOW_QUERIES_PROPERTY = "db.log.slow_query_threshold";
298    private final int mSlowQueryThreshold;
299
300    /** {@link DatabaseErrorHandler} to be used when SQLite returns any of the following errors
301     *    Corruption
302     * */
303    private DatabaseErrorHandler errorHandler;
304
305    /**
306     * @param closable
307     */
308    void addSQLiteClosable(SQLiteClosable closable) {
309        lock();
310        try {
311            mPrograms.put(closable, null);
312        } finally {
313            unlock();
314        }
315    }
316
317    void removeSQLiteClosable(SQLiteClosable closable) {
318        lock();
319        try {
320            mPrograms.remove(closable);
321        } finally {
322            unlock();
323        }
324    }
325
326    @Override
327    protected void onAllReferencesReleased() {
328        if (isOpen()) {
329            if (SQLiteDebug.DEBUG_SQL_CACHE) {
330                mTimeClosed = getTime();
331            }
332            dbclose();
333        }
334    }
335
336    /**
337     * Attempts to release memory that SQLite holds but does not require to
338     * operate properly. Typically this memory will come from the page cache.
339     *
340     * @return the number of bytes actually released
341     */
342    static public native int releaseMemory();
343
344    /**
345     * Control whether or not the SQLiteDatabase is made thread-safe by using locks
346     * around critical sections. This is pretty expensive, so if you know that your
347     * DB will only be used by a single thread then you should set this to false.
348     * The default is true.
349     * @param lockingEnabled set to true to enable locks, false otherwise
350     */
351    public void setLockingEnabled(boolean lockingEnabled) {
352        mLockingEnabled = lockingEnabled;
353    }
354
355    /**
356     * If set then the SQLiteDatabase is made thread-safe by using locks
357     * around critical sections
358     */
359    private boolean mLockingEnabled = true;
360
361    /* package */ void onCorruption() {
362        EventLog.writeEvent(EVENT_DB_CORRUPT, mPath);
363        errorHandler.onCorruption(this);
364    }
365
366    /**
367     * Locks the database for exclusive access. The database lock must be held when
368     * touch the native sqlite3* object since it is single threaded and uses
369     * a polling lock contention algorithm. The lock is recursive, and may be acquired
370     * multiple times by the same thread. This is a no-op if mLockingEnabled is false.
371     *
372     * @see #unlock()
373     */
374    /* package */ void lock() {
375        if (!mLockingEnabled) return;
376        mLock.lock();
377        if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) {
378            if (mLock.getHoldCount() == 1) {
379                // Use elapsed real-time since the CPU may sleep when waiting for IO
380                mLockAcquiredWallTime = SystemClock.elapsedRealtime();
381                mLockAcquiredThreadTime = Debug.threadCpuTimeNanos();
382            }
383        }
384    }
385
386    /**
387     * Locks the database for exclusive access. The database lock must be held when
388     * touch the native sqlite3* object since it is single threaded and uses
389     * a polling lock contention algorithm. The lock is recursive, and may be acquired
390     * multiple times by the same thread.
391     *
392     * @see #unlockForced()
393     */
394    private void lockForced() {
395        mLock.lock();
396        if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) {
397            if (mLock.getHoldCount() == 1) {
398                // Use elapsed real-time since the CPU may sleep when waiting for IO
399                mLockAcquiredWallTime = SystemClock.elapsedRealtime();
400                mLockAcquiredThreadTime = Debug.threadCpuTimeNanos();
401            }
402        }
403    }
404
405    /**
406     * Releases the database lock. This is a no-op if mLockingEnabled is false.
407     *
408     * @see #unlock()
409     */
410    /* package */ void unlock() {
411        if (!mLockingEnabled) return;
412        if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) {
413            if (mLock.getHoldCount() == 1) {
414                checkLockHoldTime();
415            }
416        }
417        mLock.unlock();
418    }
419
420    /**
421     * Releases the database lock.
422     *
423     * @see #unlockForced()
424     */
425    private void unlockForced() {
426        if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) {
427            if (mLock.getHoldCount() == 1) {
428                checkLockHoldTime();
429            }
430        }
431        mLock.unlock();
432    }
433
434    private void checkLockHoldTime() {
435        // Use elapsed real-time since the CPU may sleep when waiting for IO
436        long elapsedTime = SystemClock.elapsedRealtime();
437        long lockedTime = elapsedTime - mLockAcquiredWallTime;
438        if (lockedTime < LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT &&
439                !Log.isLoggable(TAG, Log.VERBOSE) &&
440                (elapsedTime - mLastLockMessageTime) < LOCK_WARNING_WINDOW_IN_MS) {
441            return;
442        }
443        if (lockedTime > LOCK_ACQUIRED_WARNING_TIME_IN_MS) {
444            int threadTime = (int)
445                    ((Debug.threadCpuTimeNanos() - mLockAcquiredThreadTime) / 1000000);
446            if (threadTime > LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS ||
447                    lockedTime > LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT) {
448                mLastLockMessageTime = elapsedTime;
449                String msg = "lock held on " + mPath + " for " + lockedTime + "ms. Thread time was "
450                        + threadTime + "ms";
451                if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING_STACK_TRACE) {
452                    Log.d(TAG, msg, new Exception());
453                } else {
454                    Log.d(TAG, msg);
455                }
456            }
457        }
458    }
459
460    /**
461     * Begins a transaction. Transactions can be nested. When the outer transaction is ended all of
462     * the work done in that transaction and all of the nested transactions will be committed or
463     * rolled back. The changes will be rolled back if any transaction is ended without being
464     * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
465     *
466     * <p>Here is the standard idiom for transactions:
467     *
468     * <pre>
469     *   db.beginTransaction();
470     *   try {
471     *     ...
472     *     db.setTransactionSuccessful();
473     *   } finally {
474     *     db.endTransaction();
475     *   }
476     * </pre>
477     */
478    public void beginTransaction() {
479        beginTransactionWithListener(null /* transactionStatusCallback */);
480    }
481
482    /**
483     * Begins a transaction. Transactions can be nested. When the outer transaction is ended all of
484     * the work done in that transaction and all of the nested transactions will be committed or
485     * rolled back. The changes will be rolled back if any transaction is ended without being
486     * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
487     *
488     * <p>Here is the standard idiom for transactions:
489     *
490     * <pre>
491     *   db.beginTransactionWithListener(listener);
492     *   try {
493     *     ...
494     *     db.setTransactionSuccessful();
495     *   } finally {
496     *     db.endTransaction();
497     *   }
498     * </pre>
499     * @param transactionListener listener that should be notified when the transaction begins,
500     * commits, or is rolled back, either explicitly or by a call to
501     * {@link #yieldIfContendedSafely}.
502     */
503    public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
504        lockForced();
505        if (!isOpen()) {
506            throw new IllegalStateException("database not open");
507        }
508        boolean ok = false;
509        try {
510            // If this thread already had the lock then get out
511            if (mLock.getHoldCount() > 1) {
512                if (mInnerTransactionIsSuccessful) {
513                    String msg = "Cannot call beginTransaction between "
514                            + "calling setTransactionSuccessful and endTransaction";
515                    IllegalStateException e = new IllegalStateException(msg);
516                    Log.e(TAG, "beginTransaction() failed", e);
517                    throw e;
518                }
519                ok = true;
520                return;
521            }
522
523            // This thread didn't already have the lock, so begin a database
524            // transaction now.
525            execSQL("BEGIN EXCLUSIVE;");
526            mTransactionListener = transactionListener;
527            mTransactionIsSuccessful = true;
528            mInnerTransactionIsSuccessful = false;
529            if (transactionListener != null) {
530                try {
531                    transactionListener.onBegin();
532                } catch (RuntimeException e) {
533                    execSQL("ROLLBACK;");
534                    throw e;
535                }
536            }
537            ok = true;
538        } finally {
539            if (!ok) {
540                // beginTransaction is called before the try block so we must release the lock in
541                // the case of failure.
542                unlockForced();
543            }
544        }
545    }
546
547    /**
548     * End a transaction. See beginTransaction for notes about how to use this and when transactions
549     * are committed and rolled back.
550     */
551    public void endTransaction() {
552        if (!isOpen()) {
553            throw new IllegalStateException("database not open");
554        }
555        if (!mLock.isHeldByCurrentThread()) {
556            throw new IllegalStateException("no transaction pending");
557        }
558        try {
559            if (mInnerTransactionIsSuccessful) {
560                mInnerTransactionIsSuccessful = false;
561            } else {
562                mTransactionIsSuccessful = false;
563            }
564            if (mLock.getHoldCount() != 1) {
565                return;
566            }
567            RuntimeException savedException = null;
568            if (mTransactionListener != null) {
569                try {
570                    if (mTransactionIsSuccessful) {
571                        mTransactionListener.onCommit();
572                    } else {
573                        mTransactionListener.onRollback();
574                    }
575                } catch (RuntimeException e) {
576                    savedException = e;
577                    mTransactionIsSuccessful = false;
578                }
579            }
580            if (mTransactionIsSuccessful) {
581                execSQL(COMMIT_SQL);
582            } else {
583                try {
584                    execSQL("ROLLBACK;");
585                    if (savedException != null) {
586                        throw savedException;
587                    }
588                } catch (SQLException e) {
589                    if (Config.LOGD) {
590                        Log.d(TAG, "exception during rollback, maybe the DB previously "
591                                + "performed an auto-rollback");
592                    }
593                }
594            }
595        } finally {
596            mTransactionListener = null;
597            unlockForced();
598            if (Config.LOGV) {
599                Log.v(TAG, "unlocked " + Thread.currentThread()
600                        + ", holdCount is " + mLock.getHoldCount());
601            }
602        }
603    }
604
605    /**
606     * Marks the current transaction as successful. Do not do any more database work between
607     * calling this and calling endTransaction. Do as little non-database work as possible in that
608     * situation too. If any errors are encountered between this and endTransaction the transaction
609     * will still be committed.
610     *
611     * @throws IllegalStateException if the current thread is not in a transaction or the
612     * transaction is already marked as successful.
613     */
614    public void setTransactionSuccessful() {
615        if (!isOpen()) {
616            throw new IllegalStateException("database not open");
617        }
618        if (!mLock.isHeldByCurrentThread()) {
619            throw new IllegalStateException("no transaction pending");
620        }
621        if (mInnerTransactionIsSuccessful) {
622            throw new IllegalStateException(
623                    "setTransactionSuccessful may only be called once per call to beginTransaction");
624        }
625        mInnerTransactionIsSuccessful = true;
626    }
627
628    /**
629     * return true if there is a transaction pending
630     */
631    public boolean inTransaction() {
632        return mLock.getHoldCount() > 0;
633    }
634
635    /**
636     * Checks if the database lock is held by this thread.
637     *
638     * @return true, if this thread is holding the database lock.
639     */
640    public boolean isDbLockedByCurrentThread() {
641        return mLock.isHeldByCurrentThread();
642    }
643
644    /**
645     * Checks if the database is locked by another thread. This is
646     * just an estimate, since this status can change at any time,
647     * including after the call is made but before the result has
648     * been acted upon.
649     *
650     * @return true, if the database is locked by another thread
651     */
652    public boolean isDbLockedByOtherThreads() {
653        return !mLock.isHeldByCurrentThread() && mLock.isLocked();
654    }
655
656    /**
657     * Temporarily end the transaction to let other threads run. The transaction is assumed to be
658     * successful so far. Do not call setTransactionSuccessful before calling this. When this
659     * returns a new transaction will have been created but not marked as successful.
660     * @return true if the transaction was yielded
661     * @deprecated if the db is locked more than once (becuase of nested transactions) then the lock
662     *   will not be yielded. Use yieldIfContendedSafely instead.
663     */
664    @Deprecated
665    public boolean yieldIfContended() {
666        return yieldIfContendedHelper(false /* do not check yielding */,
667                -1 /* sleepAfterYieldDelay */);
668    }
669
670    /**
671     * Temporarily end the transaction to let other threads run. The transaction is assumed to be
672     * successful so far. Do not call setTransactionSuccessful before calling this. When this
673     * returns a new transaction will have been created but not marked as successful. This assumes
674     * that there are no nested transactions (beginTransaction has only been called once) and will
675     * throw an exception if that is not the case.
676     * @return true if the transaction was yielded
677     */
678    public boolean yieldIfContendedSafely() {
679        return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/);
680    }
681
682    /**
683     * Temporarily end the transaction to let other threads run. The transaction is assumed to be
684     * successful so far. Do not call setTransactionSuccessful before calling this. When this
685     * returns a new transaction will have been created but not marked as successful. This assumes
686     * that there are no nested transactions (beginTransaction has only been called once) and will
687     * throw an exception if that is not the case.
688     * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if
689     *   the lock was actually yielded. This will allow other background threads to make some
690     *   more progress than they would if we started the transaction immediately.
691     * @return true if the transaction was yielded
692     */
693    public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
694        return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay);
695    }
696
697    private boolean yieldIfContendedHelper(boolean checkFullyYielded, long sleepAfterYieldDelay) {
698        if (mLock.getQueueLength() == 0) {
699            // Reset the lock acquire time since we know that the thread was willing to yield
700            // the lock at this time.
701            mLockAcquiredWallTime = SystemClock.elapsedRealtime();
702            mLockAcquiredThreadTime = Debug.threadCpuTimeNanos();
703            return false;
704        }
705        setTransactionSuccessful();
706        SQLiteTransactionListener transactionListener = mTransactionListener;
707        endTransaction();
708        if (checkFullyYielded) {
709            if (this.isDbLockedByCurrentThread()) {
710                throw new IllegalStateException(
711                        "Db locked more than once. yielfIfContended cannot yield");
712            }
713        }
714        if (sleepAfterYieldDelay > 0) {
715            // Sleep for up to sleepAfterYieldDelay milliseconds, waking up periodically to
716            // check if anyone is using the database.  If the database is not contended,
717            // retake the lock and return.
718            long remainingDelay = sleepAfterYieldDelay;
719            while (remainingDelay > 0) {
720                try {
721                    Thread.sleep(remainingDelay < SLEEP_AFTER_YIELD_QUANTUM ?
722                            remainingDelay : SLEEP_AFTER_YIELD_QUANTUM);
723                } catch (InterruptedException e) {
724                    Thread.interrupted();
725                }
726                remainingDelay -= SLEEP_AFTER_YIELD_QUANTUM;
727                if (mLock.getQueueLength() == 0) {
728                    break;
729                }
730            }
731        }
732        beginTransactionWithListener(transactionListener);
733        return true;
734    }
735
736    /** Maps table names to info about what to which _sync_time column to set
737     * to NULL on an update. This is used to support syncing. */
738    private final Map<String, SyncUpdateInfo> mSyncUpdateInfo =
739            new HashMap<String, SyncUpdateInfo>();
740
741    public Map<String, String> getSyncedTables() {
742        synchronized(mSyncUpdateInfo) {
743            HashMap<String, String> tables = new HashMap<String, String>();
744            for (String table : mSyncUpdateInfo.keySet()) {
745                SyncUpdateInfo info = mSyncUpdateInfo.get(table);
746                if (info.deletedTable != null) {
747                    tables.put(table, info.deletedTable);
748                }
749            }
750            return tables;
751        }
752    }
753
754    /**
755     * Internal class used to keep track what needs to be marked as changed
756     * when an update occurs. This is used for syncing, so the sync engine
757     * knows what data has been updated locally.
758     */
759    static private class SyncUpdateInfo {
760        /**
761         * Creates the SyncUpdateInfo class.
762         *
763         * @param masterTable The table to set _sync_time to NULL in
764         * @param deletedTable The deleted table that corresponds to the
765         *          master table
766         * @param foreignKey The key that refers to the primary key in table
767         */
768        SyncUpdateInfo(String masterTable, String deletedTable,
769                String foreignKey) {
770            this.masterTable = masterTable;
771            this.deletedTable = deletedTable;
772            this.foreignKey = foreignKey;
773        }
774
775        /** The table containing the _sync_time column */
776        String masterTable;
777
778        /** The deleted table that corresponds to the master table */
779        String deletedTable;
780
781        /** The key in the local table the row in table. It may be _id, if table
782         * is the local table. */
783        String foreignKey;
784    }
785
786    /**
787     * Used to allow returning sub-classes of {@link Cursor} when calling query.
788     */
789    public interface CursorFactory {
790        /**
791         * See
792         * {@link SQLiteCursor#SQLiteCursor(SQLiteDatabase, SQLiteCursorDriver,
793         * String, SQLiteQuery)}.
794         */
795        public Cursor newCursor(SQLiteDatabase db,
796                SQLiteCursorDriver masterQuery, String editTable,
797                SQLiteQuery query);
798    }
799
800    /**
801     * Open the database according to the flags {@link #OPEN_READWRITE}
802     * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
803     *
804     * <p>Sets the locale of the database to the  the system's current locale.
805     * Call {@link #setLocale} if you would like something else.</p>
806     *
807     * @param path to database file to open and/or create
808     * @param factory an optional factory class that is called to instantiate a
809     *            cursor when query is called, or null for default
810     * @param flags to control database access mode
811     * @return the newly opened database
812     * @throws SQLiteException if the database cannot be opened
813     */
814    public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags) {
815        return openDatabase(path, factory, flags, new DefaultDatabaseErrorHandler());
816    }
817
818    /**
819     * same as {@link #openDatabase(String, CursorFactory, int)} except for an additional param
820     * errorHandler.
821     * @param errorHandler the {@link DatabaseErrorHandler} obj to be used when database
822     * corruption is detected on the database.
823     */
824    public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags,
825            DatabaseErrorHandler errorHandler) {
826        SQLiteDatabase sqliteDatabase = new SQLiteDatabase(path, factory, flags);
827
828        // set the ErrorHandler to be used when SQLite reports exceptions
829        sqliteDatabase.errorHandler = errorHandler;
830
831        try {
832            // Open the database.
833            sqliteDatabase.openDatabase(path, flags);
834            if (SQLiteDebug.DEBUG_SQL_STATEMENTS) {
835                sqliteDatabase.enableSqlTracing(path);
836            }
837            if (SQLiteDebug.DEBUG_SQL_TIME) {
838                sqliteDatabase.enableSqlProfiling(path);
839            }
840        } catch (SQLiteDatabaseCorruptException e) {
841            // Database is not even openable.
842            errorHandler.onCorruption(sqliteDatabase);
843            sqliteDatabase = new SQLiteDatabase(path, factory, flags);
844        }
845        ActiveDatabases.getInstance().mActiveDatabases.add(
846                new WeakReference<SQLiteDatabase>(sqliteDatabase));
847        return sqliteDatabase;
848    }
849
850    private void openDatabase(String path, int flags) {
851        // Open the database.
852        dbopen(path, flags);
853        try {
854            setLocale(Locale.getDefault());
855        } catch (RuntimeException e) {
856            Log.e(TAG, "Failed to setLocale(). closing the database", e);
857            dbclose();
858            throw e;
859        }
860    }
861
862    /**
863     * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
864     */
865    public static SQLiteDatabase openOrCreateDatabase(File file, CursorFactory factory) {
866        return openOrCreateDatabase(file.getPath(), factory);
867    }
868
869    /**
870     * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
871     */
872    public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory) {
873        return openDatabase(path, factory, CREATE_IF_NECESSARY);
874    }
875
876    /**
877     * same as {@link #openOrCreateDatabase(String, CursorFactory)} except for an additional param
878     * errorHandler.
879     * @param errorHandler the {@link DatabaseErrorHandler} obj to be used when database
880     * corruption is detected on the database.
881     */
882    public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory,
883            DatabaseErrorHandler errorHandler) {
884        return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler);
885    }
886
887    /**
888     * Create a memory backed SQLite database.  Its contents will be destroyed
889     * when the database is closed.
890     *
891     * <p>Sets the locale of the database to the  the system's current locale.
892     * Call {@link #setLocale} if you would like something else.</p>
893     *
894     * @param factory an optional factory class that is called to instantiate a
895     *            cursor when query is called
896     * @return a SQLiteDatabase object, or null if the database can't be created
897     */
898    public static SQLiteDatabase create(CursorFactory factory) {
899        // This is a magic string with special meaning for SQLite.
900        return openDatabase(":memory:", factory, CREATE_IF_NECESSARY);
901    }
902
903    /**
904     * Close the database.
905     */
906    public void close() {
907        if (!isOpen()) {
908            return; // already closed
909        }
910        lock();
911        try {
912            closeClosable();
913            // close this database instance - regardless of its reference count value
914            onAllReferencesReleased();
915        } finally {
916            unlock();
917        }
918    }
919
920    private void closeClosable() {
921        /* deallocate all compiled sql statement objects from mCompiledQueries cache.
922         * this should be done before de-referencing all {@link SQLiteClosable} objects
923         * from this database object because calling
924         * {@link SQLiteClosable#onAllReferencesReleasedFromContainer()} could cause the database
925         * to be closed. sqlite doesn't let a database close if there are
926         * any unfinalized statements - such as the compiled-sql objects in mCompiledQueries.
927         */
928        deallocCachedSqlStatements();
929
930        Iterator<Map.Entry<SQLiteClosable, Object>> iter = mPrograms.entrySet().iterator();
931        while (iter.hasNext()) {
932            Map.Entry<SQLiteClosable, Object> entry = iter.next();
933            SQLiteClosable program = entry.getKey();
934            if (program != null) {
935                program.onAllReferencesReleasedFromContainer();
936            }
937        }
938    }
939
940    /**
941     * Native call to close the database.
942     */
943    private native void dbclose();
944
945    /**
946     * Gets the database version.
947     *
948     * @return the database version
949     */
950    public int getVersion() {
951        SQLiteStatement prog = null;
952        lock();
953        if (!isOpen()) {
954            throw new IllegalStateException("database not open");
955        }
956        try {
957            prog = new SQLiteStatement(this, "PRAGMA user_version;");
958            long version = prog.simpleQueryForLong();
959            return (int) version;
960        } finally {
961            if (prog != null) prog.close();
962            unlock();
963        }
964    }
965
966    /**
967     * Sets the database version.
968     *
969     * @param version the new database version
970     */
971    public void setVersion(int version) {
972        execSQL("PRAGMA user_version = " + version);
973    }
974
975    /**
976     * Returns the maximum size the database may grow to.
977     *
978     * @return the new maximum database size
979     */
980    public long getMaximumSize() {
981        SQLiteStatement prog = null;
982        lock();
983        if (!isOpen()) {
984            throw new IllegalStateException("database not open");
985        }
986        try {
987            prog = new SQLiteStatement(this,
988                    "PRAGMA max_page_count;");
989            long pageCount = prog.simpleQueryForLong();
990            return pageCount * getPageSize();
991        } finally {
992            if (prog != null) prog.close();
993            unlock();
994        }
995    }
996
997    /**
998     * Sets the maximum size the database will grow to. The maximum size cannot
999     * be set below the current size.
1000     *
1001     * @param numBytes the maximum database size, in bytes
1002     * @return the new maximum database size
1003     */
1004    public long setMaximumSize(long numBytes) {
1005        SQLiteStatement prog = null;
1006        lock();
1007        if (!isOpen()) {
1008            throw new IllegalStateException("database not open");
1009        }
1010        try {
1011            long pageSize = getPageSize();
1012            long numPages = numBytes / pageSize;
1013            // If numBytes isn't a multiple of pageSize, bump up a page
1014            if ((numBytes % pageSize) != 0) {
1015                numPages++;
1016            }
1017            prog = new SQLiteStatement(this,
1018                    "PRAGMA max_page_count = " + numPages);
1019            long newPageCount = prog.simpleQueryForLong();
1020            return newPageCount * pageSize;
1021        } finally {
1022            if (prog != null) prog.close();
1023            unlock();
1024        }
1025    }
1026
1027    /**
1028     * Returns the current database page size, in bytes.
1029     *
1030     * @return the database page size, in bytes
1031     */
1032    public long getPageSize() {
1033        SQLiteStatement prog = null;
1034        lock();
1035        if (!isOpen()) {
1036            throw new IllegalStateException("database not open");
1037        }
1038        try {
1039            prog = new SQLiteStatement(this,
1040                    "PRAGMA page_size;");
1041            long size = prog.simpleQueryForLong();
1042            return size;
1043        } finally {
1044            if (prog != null) prog.close();
1045            unlock();
1046        }
1047    }
1048
1049    /**
1050     * Sets the database page size. The page size must be a power of two. This
1051     * method does not work if any data has been written to the database file,
1052     * and must be called right after the database has been created.
1053     *
1054     * @param numBytes the database page size, in bytes
1055     */
1056    public void setPageSize(long numBytes) {
1057        execSQL("PRAGMA page_size = " + numBytes);
1058    }
1059
1060    /**
1061     * Mark this table as syncable. When an update occurs in this table the
1062     * _sync_dirty field will be set to ensure proper syncing operation.
1063     *
1064     * @param table the table to mark as syncable
1065     * @param deletedTable The deleted table that corresponds to the
1066     *          syncable table
1067     */
1068    public void markTableSyncable(String table, String deletedTable) {
1069        markTableSyncable(table, "_id", table, deletedTable);
1070    }
1071
1072    /**
1073     * Mark this table as syncable, with the _sync_dirty residing in another
1074     * table. When an update occurs in this table the _sync_dirty field of the
1075     * row in updateTable with the _id in foreignKey will be set to
1076     * ensure proper syncing operation.
1077     *
1078     * @param table an update on this table will trigger a sync time removal
1079     * @param foreignKey this is the column in table whose value is an _id in
1080     *          updateTable
1081     * @param updateTable this is the table that will have its _sync_dirty
1082     */
1083    public void markTableSyncable(String table, String foreignKey,
1084            String updateTable) {
1085        markTableSyncable(table, foreignKey, updateTable, null);
1086    }
1087
1088    /**
1089     * Mark this table as syncable, with the _sync_dirty residing in another
1090     * table. When an update occurs in this table the _sync_dirty field of the
1091     * row in updateTable with the _id in foreignKey will be set to
1092     * ensure proper syncing operation.
1093     *
1094     * @param table an update on this table will trigger a sync time removal
1095     * @param foreignKey this is the column in table whose value is an _id in
1096     *          updateTable
1097     * @param updateTable this is the table that will have its _sync_dirty
1098     * @param deletedTable The deleted table that corresponds to the
1099     *          updateTable
1100     */
1101    private void markTableSyncable(String table, String foreignKey,
1102            String updateTable, String deletedTable) {
1103        lock();
1104        try {
1105            native_execSQL("SELECT _sync_dirty FROM " + updateTable
1106                    + " LIMIT 0");
1107            native_execSQL("SELECT " + foreignKey + " FROM " + table
1108                    + " LIMIT 0");
1109        } finally {
1110            unlock();
1111        }
1112
1113        SyncUpdateInfo info = new SyncUpdateInfo(updateTable, deletedTable,
1114                foreignKey);
1115        synchronized (mSyncUpdateInfo) {
1116            mSyncUpdateInfo.put(table, info);
1117        }
1118    }
1119
1120    /**
1121     * Call for each row that is updated in a cursor.
1122     *
1123     * @param table the table the row is in
1124     * @param rowId the row ID of the updated row
1125     */
1126    /* package */ void rowUpdated(String table, long rowId) {
1127        SyncUpdateInfo info;
1128        synchronized (mSyncUpdateInfo) {
1129            info = mSyncUpdateInfo.get(table);
1130        }
1131        if (info != null) {
1132            execSQL("UPDATE " + info.masterTable
1133                    + " SET _sync_dirty=1 WHERE _id=(SELECT " + info.foreignKey
1134                    + " FROM " + table + " WHERE _id=" + rowId + ")");
1135        }
1136    }
1137
1138    /**
1139     * Finds the name of the first table, which is editable.
1140     *
1141     * @param tables a list of tables
1142     * @return the first table listed
1143     */
1144    public static String findEditTable(String tables) {
1145        if (!TextUtils.isEmpty(tables)) {
1146            // find the first word terminated by either a space or a comma
1147            int spacepos = tables.indexOf(' ');
1148            int commapos = tables.indexOf(',');
1149
1150            if (spacepos > 0 && (spacepos < commapos || commapos < 0)) {
1151                return tables.substring(0, spacepos);
1152            } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) {
1153                return tables.substring(0, commapos);
1154            }
1155            return tables;
1156        } else {
1157            throw new IllegalStateException("Invalid tables");
1158        }
1159    }
1160
1161    /**
1162     * Compiles an SQL statement into a reusable pre-compiled statement object.
1163     * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the
1164     * statement and fill in those values with {@link SQLiteProgram#bindString}
1165     * and {@link SQLiteProgram#bindLong} each time you want to run the
1166     * statement. Statements may not return result sets larger than 1x1.
1167     *
1168     * @param sql The raw SQL statement, may contain ? for unknown values to be
1169     *            bound later.
1170     * @return a pre-compiled statement object.
1171     */
1172    public SQLiteStatement compileStatement(String sql) throws SQLException {
1173        lock();
1174        if (!isOpen()) {
1175            throw new IllegalStateException("database not open");
1176        }
1177        try {
1178            return new SQLiteStatement(this, sql);
1179        } finally {
1180            unlock();
1181        }
1182    }
1183
1184    /**
1185     * Query the given URL, returning a {@link Cursor} over the result set.
1186     *
1187     * @param distinct true if you want each row to be unique, false otherwise.
1188     * @param table The table name to compile the query against.
1189     * @param columns A list of which columns to return. Passing null will
1190     *            return all columns, which is discouraged to prevent reading
1191     *            data from storage that isn't going to be used.
1192     * @param selection A filter declaring which rows to return, formatted as an
1193     *            SQL WHERE clause (excluding the WHERE itself). Passing null
1194     *            will return all rows for the given table.
1195     * @param selectionArgs You may include ?s in selection, which will be
1196     *         replaced by the values from selectionArgs, in order that they
1197     *         appear in the selection. The values will be bound as Strings.
1198     * @param groupBy A filter declaring how to group rows, formatted as an SQL
1199     *            GROUP BY clause (excluding the GROUP BY itself). Passing null
1200     *            will cause the rows to not be grouped.
1201     * @param having A filter declare which row groups to include in the cursor,
1202     *            if row grouping is being used, formatted as an SQL HAVING
1203     *            clause (excluding the HAVING itself). Passing null will cause
1204     *            all row groups to be included, and is required when row
1205     *            grouping is not being used.
1206     * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1207     *            (excluding the ORDER BY itself). Passing null will use the
1208     *            default sort order, which may be unordered.
1209     * @param limit Limits the number of rows returned by the query,
1210     *            formatted as LIMIT clause. Passing null denotes no LIMIT clause.
1211     * @return A Cursor object, which is positioned before the first entry
1212     * @see Cursor
1213     */
1214    public Cursor query(boolean distinct, String table, String[] columns,
1215            String selection, String[] selectionArgs, String groupBy,
1216            String having, String orderBy, String limit) {
1217        return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
1218                groupBy, having, orderBy, limit);
1219    }
1220
1221    /**
1222     * Query the given URL, returning a {@link Cursor} over the result set.
1223     *
1224     * @param cursorFactory the cursor factory to use, or null for the default factory
1225     * @param distinct true if you want each row to be unique, false otherwise.
1226     * @param table The table name to compile the query against.
1227     * @param columns A list of which columns to return. Passing null will
1228     *            return all columns, which is discouraged to prevent reading
1229     *            data from storage that isn't going to be used.
1230     * @param selection A filter declaring which rows to return, formatted as an
1231     *            SQL WHERE clause (excluding the WHERE itself). Passing null
1232     *            will return all rows for the given table.
1233     * @param selectionArgs You may include ?s in selection, which will be
1234     *         replaced by the values from selectionArgs, in order that they
1235     *         appear in the selection. The values will be bound as Strings.
1236     * @param groupBy A filter declaring how to group rows, formatted as an SQL
1237     *            GROUP BY clause (excluding the GROUP BY itself). Passing null
1238     *            will cause the rows to not be grouped.
1239     * @param having A filter declare which row groups to include in the cursor,
1240     *            if row grouping is being used, formatted as an SQL HAVING
1241     *            clause (excluding the HAVING itself). Passing null will cause
1242     *            all row groups to be included, and is required when row
1243     *            grouping is not being used.
1244     * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1245     *            (excluding the ORDER BY itself). Passing null will use the
1246     *            default sort order, which may be unordered.
1247     * @param limit Limits the number of rows returned by the query,
1248     *            formatted as LIMIT clause. Passing null denotes no LIMIT clause.
1249     * @return A Cursor object, which is positioned before the first entry
1250     * @see Cursor
1251     */
1252    public Cursor queryWithFactory(CursorFactory cursorFactory,
1253            boolean distinct, String table, String[] columns,
1254            String selection, String[] selectionArgs, String groupBy,
1255            String having, String orderBy, String limit) {
1256        if (!isOpen()) {
1257            throw new IllegalStateException("database not open");
1258        }
1259        String sql = SQLiteQueryBuilder.buildQueryString(
1260                distinct, table, columns, selection, groupBy, having, orderBy, limit);
1261
1262        return rawQueryWithFactory(
1263                cursorFactory, sql, selectionArgs, findEditTable(table));
1264    }
1265
1266    /**
1267     * Query the given table, returning a {@link Cursor} over the result set.
1268     *
1269     * @param table The table name to compile the query against.
1270     * @param columns A list of which columns to return. Passing null will
1271     *            return all columns, which is discouraged to prevent reading
1272     *            data from storage that isn't going to be used.
1273     * @param selection A filter declaring which rows to return, formatted as an
1274     *            SQL WHERE clause (excluding the WHERE itself). Passing null
1275     *            will return all rows for the given table.
1276     * @param selectionArgs You may include ?s in selection, which will be
1277     *         replaced by the values from selectionArgs, in order that they
1278     *         appear in the selection. The values will be bound as Strings.
1279     * @param groupBy A filter declaring how to group rows, formatted as an SQL
1280     *            GROUP BY clause (excluding the GROUP BY itself). Passing null
1281     *            will cause the rows to not be grouped.
1282     * @param having A filter declare which row groups to include in the cursor,
1283     *            if row grouping is being used, formatted as an SQL HAVING
1284     *            clause (excluding the HAVING itself). Passing null will cause
1285     *            all row groups to be included, and is required when row
1286     *            grouping is not being used.
1287     * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1288     *            (excluding the ORDER BY itself). Passing null will use the
1289     *            default sort order, which may be unordered.
1290     * @return A {@link Cursor} object, which is positioned before the first entry
1291     * @see Cursor
1292     */
1293    public Cursor query(String table, String[] columns, String selection,
1294            String[] selectionArgs, String groupBy, String having,
1295            String orderBy) {
1296
1297        return query(false, table, columns, selection, selectionArgs, groupBy,
1298                having, orderBy, null /* limit */);
1299    }
1300
1301    /**
1302     * Query the given table, returning a {@link Cursor} over the result set.
1303     *
1304     * @param table The table name to compile the query against.
1305     * @param columns A list of which columns to return. Passing null will
1306     *            return all columns, which is discouraged to prevent reading
1307     *            data from storage that isn't going to be used.
1308     * @param selection A filter declaring which rows to return, formatted as an
1309     *            SQL WHERE clause (excluding the WHERE itself). Passing null
1310     *            will return all rows for the given table.
1311     * @param selectionArgs You may include ?s in selection, which will be
1312     *         replaced by the values from selectionArgs, in order that they
1313     *         appear in the selection. The values will be bound as Strings.
1314     * @param groupBy A filter declaring how to group rows, formatted as an SQL
1315     *            GROUP BY clause (excluding the GROUP BY itself). Passing null
1316     *            will cause the rows to not be grouped.
1317     * @param having A filter declare which row groups to include in the cursor,
1318     *            if row grouping is being used, formatted as an SQL HAVING
1319     *            clause (excluding the HAVING itself). Passing null will cause
1320     *            all row groups to be included, and is required when row
1321     *            grouping is not being used.
1322     * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1323     *            (excluding the ORDER BY itself). Passing null will use the
1324     *            default sort order, which may be unordered.
1325     * @param limit Limits the number of rows returned by the query,
1326     *            formatted as LIMIT clause. Passing null denotes no LIMIT clause.
1327     * @return A {@link Cursor} object, which is positioned before the first entry
1328     * @see Cursor
1329     */
1330    public Cursor query(String table, String[] columns, String selection,
1331            String[] selectionArgs, String groupBy, String having,
1332            String orderBy, String limit) {
1333
1334        return query(false, table, columns, selection, selectionArgs, groupBy,
1335                having, orderBy, limit);
1336    }
1337
1338    /**
1339     * Runs the provided SQL and returns a {@link Cursor} over the result set.
1340     *
1341     * @param sql the SQL query. The SQL string must not be ; terminated
1342     * @param selectionArgs You may include ?s in where clause in the query,
1343     *     which will be replaced by the values from selectionArgs. The
1344     *     values will be bound as Strings.
1345     * @return A {@link Cursor} object, which is positioned before the first entry
1346     */
1347    public Cursor rawQuery(String sql, String[] selectionArgs) {
1348        return rawQueryWithFactory(null, sql, selectionArgs, null);
1349    }
1350
1351    /**
1352     * Runs the provided SQL and returns a cursor over the result set.
1353     *
1354     * @param cursorFactory the cursor factory to use, or null for the default factory
1355     * @param sql the SQL query. The SQL string must not be ; terminated
1356     * @param selectionArgs You may include ?s in where clause in the query,
1357     *     which will be replaced by the values from selectionArgs. The
1358     *     values will be bound as Strings.
1359     * @param editTable the name of the first table, which is editable
1360     * @return A {@link Cursor} object, which is positioned before the first entry
1361     */
1362    public Cursor rawQueryWithFactory(
1363            CursorFactory cursorFactory, String sql, String[] selectionArgs,
1364            String editTable) {
1365        if (!isOpen()) {
1366            throw new IllegalStateException("database not open");
1367        }
1368        long timeStart = 0;
1369
1370        if (Config.LOGV || mSlowQueryThreshold != -1) {
1371            timeStart = System.currentTimeMillis();
1372        }
1373
1374        SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable);
1375
1376        Cursor cursor = null;
1377        int count = 0;
1378        try {
1379            cursor = driver.query(
1380                    cursorFactory != null ? cursorFactory : mFactory,
1381                    selectionArgs);
1382
1383            // Force query execution
1384            if (cursor != null) {
1385                count = cursor.getCount();
1386            }
1387        } finally {
1388            if (Config.LOGV || mSlowQueryThreshold != -1) {
1389
1390                long duration = System.currentTimeMillis() - timeStart;
1391
1392                if (Config.LOGV || duration >= mSlowQueryThreshold) {
1393                    Log.v(SQLiteCursor.TAG,
1394                          "query (" + duration + " ms): " + driver.toString() + ", args are "
1395                                  + (selectionArgs != null
1396                                  ? TextUtils.join(",", selectionArgs)
1397                                  : "<null>") + ", count is " + count);
1398                }
1399            }
1400        }
1401        return cursor;
1402    }
1403
1404    /**
1405     * Runs the provided SQL and returns a cursor over the result set.
1406     * The cursor will read an initial set of rows and the return to the caller.
1407     * It will continue to read in batches and send data changed notifications
1408     * when the later batches are ready.
1409     * @param sql the SQL query. The SQL string must not be ; terminated
1410     * @param selectionArgs You may include ?s in where clause in the query,
1411     *     which will be replaced by the values from selectionArgs. The
1412     *     values will be bound as Strings.
1413     * @param initialRead set the initial count of items to read from the cursor
1414     * @param maxRead set the count of items to read on each iteration after the first
1415     * @return A {@link Cursor} object, which is positioned before the first entry
1416     *
1417     * This work is incomplete and not fully tested or reviewed, so currently
1418     * hidden.
1419     * @hide
1420     */
1421    public Cursor rawQuery(String sql, String[] selectionArgs,
1422            int initialRead, int maxRead) {
1423        SQLiteCursor c = (SQLiteCursor)rawQueryWithFactory(
1424                null, sql, selectionArgs, null);
1425        c.setLoadStyle(initialRead, maxRead);
1426        return c;
1427    }
1428
1429    /**
1430     * Convenience method for inserting a row into the database.
1431     *
1432     * @param table the table to insert the row into
1433     * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
1434     *            so if initialValues is empty this column will explicitly be
1435     *            assigned a NULL value
1436     * @param values this map contains the initial column values for the
1437     *            row. The keys should be the column names and the values the
1438     *            column values
1439     * @return the row ID of the newly inserted row, or -1 if an error occurred
1440     */
1441    public long insert(String table, String nullColumnHack, ContentValues values) {
1442        try {
1443            return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
1444        } catch (SQLException e) {
1445            Log.e(TAG, "Error inserting " + values, e);
1446            return -1;
1447        }
1448    }
1449
1450    /**
1451     * Convenience method for inserting a row into the database.
1452     *
1453     * @param table the table to insert the row into
1454     * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
1455     *            so if initialValues is empty this column will explicitly be
1456     *            assigned a NULL value
1457     * @param values this map contains the initial column values for the
1458     *            row. The keys should be the column names and the values the
1459     *            column values
1460     * @throws SQLException
1461     * @return the row ID of the newly inserted row, or -1 if an error occurred
1462     */
1463    public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
1464            throws SQLException {
1465        return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
1466    }
1467
1468    /**
1469     * Convenience method for replacing a row in the database.
1470     *
1471     * @param table the table in which to replace the row
1472     * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
1473     *            so if initialValues is empty this row will explicitly be
1474     *            assigned a NULL value
1475     * @param initialValues this map contains the initial column values for
1476     *   the row. The key
1477     * @return the row ID of the newly inserted row, or -1 if an error occurred
1478     */
1479    public long replace(String table, String nullColumnHack, ContentValues initialValues) {
1480        try {
1481            return insertWithOnConflict(table, nullColumnHack, initialValues,
1482                    CONFLICT_REPLACE);
1483        } catch (SQLException e) {
1484            Log.e(TAG, "Error inserting " + initialValues, e);
1485            return -1;
1486        }
1487    }
1488
1489    /**
1490     * Convenience method for replacing a row in the database.
1491     *
1492     * @param table the table in which to replace the row
1493     * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
1494     *            so if initialValues is empty this row will explicitly be
1495     *            assigned a NULL value
1496     * @param initialValues this map contains the initial column values for
1497     *   the row. The key
1498     * @throws SQLException
1499     * @return the row ID of the newly inserted row, or -1 if an error occurred
1500     */
1501    public long replaceOrThrow(String table, String nullColumnHack,
1502            ContentValues initialValues) throws SQLException {
1503        return insertWithOnConflict(table, nullColumnHack, initialValues,
1504                CONFLICT_REPLACE);
1505    }
1506
1507    /**
1508     * General method for inserting a row into the database.
1509     *
1510     * @param table the table to insert the row into
1511     * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
1512     *            so if initialValues is empty this column will explicitly be
1513     *            assigned a NULL value
1514     * @param initialValues this map contains the initial column values for the
1515     *            row. The keys should be the column names and the values the
1516     *            column values
1517     * @param conflictAlgorithm for insert conflict resolver
1518     * @return the row ID of the newly inserted row
1519     * OR the primary key of the existing row if the input param 'conflictAlgorithm' =
1520     * {@link #CONFLICT_IGNORE}
1521     * OR -1 if any error
1522     */
1523    public long insertWithOnConflict(String table, String nullColumnHack,
1524            ContentValues initialValues, int conflictAlgorithm) {
1525        if (!isOpen()) {
1526            throw new IllegalStateException("database not open");
1527        }
1528
1529        // Measurements show most sql lengths <= 152
1530        StringBuilder sql = new StringBuilder(152);
1531        sql.append("INSERT");
1532        sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1533        sql.append(" INTO ");
1534        sql.append(table);
1535        // Measurements show most values lengths < 40
1536        StringBuilder values = new StringBuilder(40);
1537
1538        Set<Map.Entry<String, Object>> entrySet = null;
1539        if (initialValues != null && initialValues.size() > 0) {
1540            entrySet = initialValues.valueSet();
1541            Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator();
1542            sql.append('(');
1543
1544            boolean needSeparator = false;
1545            while (entriesIter.hasNext()) {
1546                if (needSeparator) {
1547                    sql.append(", ");
1548                    values.append(", ");
1549                }
1550                needSeparator = true;
1551                Map.Entry<String, Object> entry = entriesIter.next();
1552                sql.append(entry.getKey());
1553                values.append('?');
1554            }
1555
1556            sql.append(')');
1557        } else {
1558            sql.append("(" + nullColumnHack + ") ");
1559            values.append("NULL");
1560        }
1561
1562        sql.append(" VALUES(");
1563        sql.append(values);
1564        sql.append(");");
1565
1566        lock();
1567        SQLiteStatement statement = null;
1568        try {
1569            statement = compileStatement(sql.toString());
1570
1571            // Bind the values
1572            if (entrySet != null) {
1573                int size = entrySet.size();
1574                Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator();
1575                for (int i = 0; i < size; i++) {
1576                    Map.Entry<String, Object> entry = entriesIter.next();
1577                    DatabaseUtils.bindObjectToProgram(statement, i + 1, entry.getValue());
1578                }
1579            }
1580
1581            // Run the program and then cleanup
1582            statement.execute();
1583
1584            long insertedRowId = lastInsertRow();
1585            if (insertedRowId == -1) {
1586                Log.e(TAG, "Error inserting " + initialValues + " using " + sql);
1587            } else {
1588                if (Config.LOGD && Log.isLoggable(TAG, Log.VERBOSE)) {
1589                    Log.v(TAG, "Inserting row " + insertedRowId + " from "
1590                            + initialValues + " using " + sql);
1591                }
1592            }
1593            return insertedRowId;
1594        } catch (SQLiteDatabaseCorruptException e) {
1595            onCorruption();
1596            throw e;
1597        } finally {
1598            if (statement != null) {
1599                statement.close();
1600            }
1601            unlock();
1602        }
1603    }
1604
1605    /**
1606     * Convenience method for deleting rows in the database.
1607     *
1608     * @param table the table to delete from
1609     * @param whereClause the optional WHERE clause to apply when deleting.
1610     *            Passing null will delete all rows.
1611     * @return the number of rows affected if a whereClause is passed in, 0
1612     *         otherwise. To remove all rows and get a count pass "1" as the
1613     *         whereClause.
1614     */
1615    public int delete(String table, String whereClause, String[] whereArgs) {
1616        lock();
1617        if (!isOpen()) {
1618            throw new IllegalStateException("database not open");
1619        }
1620        SQLiteStatement statement = null;
1621        try {
1622            statement = compileStatement("DELETE FROM " + table
1623                    + (!TextUtils.isEmpty(whereClause)
1624                    ? " WHERE " + whereClause : ""));
1625            if (whereArgs != null) {
1626                int numArgs = whereArgs.length;
1627                for (int i = 0; i < numArgs; i++) {
1628                    DatabaseUtils.bindObjectToProgram(statement, i + 1, whereArgs[i]);
1629                }
1630            }
1631            statement.execute();
1632            return lastChangeCount();
1633        } catch (SQLiteDatabaseCorruptException e) {
1634            onCorruption();
1635            throw e;
1636        } finally {
1637            if (statement != null) {
1638                statement.close();
1639            }
1640            unlock();
1641        }
1642    }
1643
1644    /**
1645     * Convenience method for updating rows in the database.
1646     *
1647     * @param table the table to update in
1648     * @param values a map from column names to new column values. null is a
1649     *            valid value that will be translated to NULL.
1650     * @param whereClause the optional WHERE clause to apply when updating.
1651     *            Passing null will update all rows.
1652     * @return the number of rows affected
1653     */
1654    public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
1655        return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE);
1656    }
1657
1658    /**
1659     * Convenience method for updating rows in the database.
1660     *
1661     * @param table the table to update in
1662     * @param values a map from column names to new column values. null is a
1663     *            valid value that will be translated to NULL.
1664     * @param whereClause the optional WHERE clause to apply when updating.
1665     *            Passing null will update all rows.
1666     * @param conflictAlgorithm for update conflict resolver
1667     * @return the number of rows affected
1668     */
1669    public int updateWithOnConflict(String table, ContentValues values,
1670            String whereClause, String[] whereArgs, int conflictAlgorithm) {
1671        if (values == null || values.size() == 0) {
1672            throw new IllegalArgumentException("Empty values");
1673        }
1674
1675        StringBuilder sql = new StringBuilder(120);
1676        sql.append("UPDATE ");
1677        sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1678        sql.append(table);
1679        sql.append(" SET ");
1680
1681        Set<Map.Entry<String, Object>> entrySet = values.valueSet();
1682        Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator();
1683
1684        while (entriesIter.hasNext()) {
1685            Map.Entry<String, Object> entry = entriesIter.next();
1686            sql.append(entry.getKey());
1687            sql.append("=?");
1688            if (entriesIter.hasNext()) {
1689                sql.append(", ");
1690            }
1691        }
1692
1693        if (!TextUtils.isEmpty(whereClause)) {
1694            sql.append(" WHERE ");
1695            sql.append(whereClause);
1696        }
1697
1698        lock();
1699        if (!isOpen()) {
1700            throw new IllegalStateException("database not open");
1701        }
1702        SQLiteStatement statement = null;
1703        try {
1704            statement = compileStatement(sql.toString());
1705
1706            // Bind the values
1707            int size = entrySet.size();
1708            entriesIter = entrySet.iterator();
1709            int bindArg = 1;
1710            for (int i = 0; i < size; i++) {
1711                Map.Entry<String, Object> entry = entriesIter.next();
1712                DatabaseUtils.bindObjectToProgram(statement, bindArg, entry.getValue());
1713                bindArg++;
1714            }
1715
1716            if (whereArgs != null) {
1717                size = whereArgs.length;
1718                for (int i = 0; i < size; i++) {
1719                    statement.bindString(bindArg, whereArgs[i]);
1720                    bindArg++;
1721                }
1722            }
1723
1724            // Run the program and then cleanup
1725            statement.execute();
1726            int numChangedRows = lastChangeCount();
1727            if (Config.LOGD && Log.isLoggable(TAG, Log.VERBOSE)) {
1728                Log.v(TAG, "Updated " + numChangedRows + " using " + values + " and " + sql);
1729            }
1730            return numChangedRows;
1731        } catch (SQLiteDatabaseCorruptException e) {
1732            onCorruption();
1733            throw e;
1734        } catch (SQLException e) {
1735            Log.e(TAG, "Error updating " + values + " using " + sql);
1736            throw e;
1737        } finally {
1738            if (statement != null) {
1739                statement.close();
1740            }
1741            unlock();
1742        }
1743    }
1744
1745    /**
1746     * Execute a single SQL statement that is not a query. For example, CREATE
1747     * TABLE, DELETE, INSERT, etc. Multiple statements separated by ;s are not
1748     * supported. it takes a write lock
1749     *
1750     * @throws SQLException If the SQL string is invalid for some reason
1751     */
1752    public void execSQL(String sql) throws SQLException {
1753        long timeStart = SystemClock.uptimeMillis();
1754        lock();
1755        if (!isOpen()) {
1756            throw new IllegalStateException("database not open");
1757        }
1758        logTimeStat(mLastSqlStatement, timeStart, GET_LOCK_LOG_PREFIX);
1759        try {
1760            native_execSQL(sql);
1761        } catch (SQLiteDatabaseCorruptException e) {
1762            onCorruption();
1763            throw e;
1764        } finally {
1765            unlock();
1766        }
1767
1768        // Log commit statements along with the most recently executed
1769        // SQL statement for disambiguation.  Note that instance
1770        // equality to COMMIT_SQL is safe here.
1771        if (sql == COMMIT_SQL) {
1772            logTimeStat(mLastSqlStatement, timeStart, COMMIT_SQL);
1773        } else {
1774            logTimeStat(sql, timeStart, null);
1775        }
1776    }
1777
1778    /**
1779     * Execute a single SQL statement that is not a query. For example, CREATE
1780     * TABLE, DELETE, INSERT, etc. Multiple statements separated by ;s are not
1781     * supported. it takes a write lock,
1782     *
1783     * @param sql
1784     * @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
1785     * @throws SQLException If the SQL string is invalid for some reason
1786     */
1787    public void execSQL(String sql, Object[] bindArgs) throws SQLException {
1788        if (bindArgs == null) {
1789            throw new IllegalArgumentException("Empty bindArgs");
1790        }
1791        long timeStart = SystemClock.uptimeMillis();
1792        lock();
1793        if (!isOpen()) {
1794            throw new IllegalStateException("database not open");
1795        }
1796        SQLiteStatement statement = null;
1797        try {
1798            statement = compileStatement(sql);
1799            if (bindArgs != null) {
1800                int numArgs = bindArgs.length;
1801                for (int i = 0; i < numArgs; i++) {
1802                    DatabaseUtils.bindObjectToProgram(statement, i + 1, bindArgs[i]);
1803                }
1804            }
1805            statement.execute();
1806        } catch (SQLiteDatabaseCorruptException e) {
1807            onCorruption();
1808            throw e;
1809        } finally {
1810            if (statement != null) {
1811                statement.close();
1812            }
1813            unlock();
1814        }
1815        logTimeStat(sql, timeStart);
1816    }
1817
1818    @Override
1819    protected void finalize() {
1820        if (isOpen()) {
1821            Log.e(TAG, "close() was never explicitly called on database '" +
1822                    mPath + "' ", mStackTrace);
1823            closeClosable();
1824            onAllReferencesReleased();
1825        }
1826    }
1827
1828    /**
1829     * Private constructor. See {@link #create} and {@link #openDatabase}.
1830     *
1831     * @param path The full path to the database
1832     * @param factory The factory to use when creating cursors, may be NULL.
1833     * @param flags 0 or {@link #NO_LOCALIZED_COLLATORS}.  If the database file already
1834     *              exists, mFlags will be updated appropriately.
1835     */
1836    private SQLiteDatabase(String path, CursorFactory factory, int flags) {
1837        if (path == null) {
1838            throw new IllegalArgumentException("path should not be null");
1839        }
1840        mFlags = flags;
1841        mPath = path;
1842        mSlowQueryThreshold = SystemProperties.getInt(LOG_SLOW_QUERIES_PROPERTY, -1);
1843        mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
1844        mFactory = factory;
1845        if (SQLiteDebug.DEBUG_SQL_CACHE) {
1846            mTimeOpened = getTime();
1847        }
1848        mPrograms = new WeakHashMap<SQLiteClosable,Object>();
1849    }
1850
1851    private String getTime() {
1852        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS ").format(System.currentTimeMillis());
1853    }
1854
1855    /**
1856     * return whether the DB is opened as read only.
1857     * @return true if DB is opened as read only
1858     */
1859    public boolean isReadOnly() {
1860        return (mFlags & OPEN_READ_MASK) == OPEN_READONLY;
1861    }
1862
1863    /**
1864     * @return true if the DB is currently open (has not been closed)
1865     */
1866    public boolean isOpen() {
1867        return mNativeHandle != 0;
1868    }
1869
1870    public boolean needUpgrade(int newVersion) {
1871        return newVersion > getVersion();
1872    }
1873
1874    /**
1875     * Getter for the path to the database file.
1876     *
1877     * @return the path to our database file.
1878     */
1879    public final String getPath() {
1880        return mPath;
1881    }
1882
1883    /* package */ void logTimeStat(String sql, long beginMillis) {
1884        logTimeStat(sql, beginMillis, null);
1885    }
1886
1887    /* package */ void logTimeStat(String sql, long beginMillis, String prefix) {
1888        // Keep track of the last statement executed here, as this is
1889        // the common funnel through which all methods of hitting
1890        // libsqlite eventually flow.
1891        mLastSqlStatement = sql;
1892
1893        // Sample fast queries in proportion to the time taken.
1894        // Quantize the % first, so the logged sampling probability
1895        // exactly equals the actual sampling rate for this query.
1896
1897        int samplePercent;
1898        long durationMillis = SystemClock.uptimeMillis() - beginMillis;
1899        if (durationMillis == 0 && prefix == GET_LOCK_LOG_PREFIX) {
1900            // The common case is locks being uncontended.  Don't log those,
1901            // even at 1%, which is our default below.
1902            return;
1903        }
1904        if (sQueryLogTimeInMillis == 0) {
1905            sQueryLogTimeInMillis = SystemProperties.getInt("db.db_operation.threshold_ms", 500);
1906        }
1907        if (durationMillis >= sQueryLogTimeInMillis) {
1908            samplePercent = 100;
1909        } else {;
1910            samplePercent = (int) (100 * durationMillis / sQueryLogTimeInMillis) + 1;
1911            if (mRandom.nextInt(100) >= samplePercent) return;
1912        }
1913
1914        // Note: the prefix will be "COMMIT;" or "GETLOCK:" when non-null.  We wait to do
1915        // it here so we avoid allocating in the common case.
1916        if (prefix != null) {
1917            sql = prefix + sql;
1918        }
1919
1920        if (sql.length() > QUERY_LOG_SQL_LENGTH) sql = sql.substring(0, QUERY_LOG_SQL_LENGTH);
1921
1922        // ActivityThread.currentPackageName() only returns non-null if the
1923        // current thread is an application main thread.  This parameter tells
1924        // us whether an event loop is blocked, and if so, which app it is.
1925        //
1926        // Sadly, there's no fast way to determine app name if this is *not* a
1927        // main thread, or when we are invoked via Binder (e.g. ContentProvider).
1928        // Hopefully the full path to the database will be informative enough.
1929
1930        String blockingPackage = ActivityThread.currentPackageName();
1931        if (blockingPackage == null) blockingPackage = "";
1932
1933        EventLog.writeEvent(
1934            EVENT_DB_OPERATION,
1935            getPathForLogs(),
1936            sql,
1937            durationMillis,
1938            blockingPackage,
1939            samplePercent);
1940    }
1941
1942    /**
1943     * Removes email addresses from database filenames before they're
1944     * logged to the EventLog where otherwise apps could potentially
1945     * read them.
1946     */
1947    private String getPathForLogs() {
1948        if (mPathForLogs != null) {
1949            return mPathForLogs;
1950        }
1951        if (mPath == null) {
1952            return null;
1953        }
1954        if (mPath.indexOf('@') == -1) {
1955            mPathForLogs = mPath;
1956        } else {
1957            mPathForLogs = EMAIL_IN_DB_PATTERN.matcher(mPath).replaceAll("XX@YY");
1958        }
1959        return mPathForLogs;
1960    }
1961
1962    /**
1963     * Sets the locale for this database.  Does nothing if this database has
1964     * the NO_LOCALIZED_COLLATORS flag set or was opened read only.
1965     * @throws SQLException if the locale could not be set.  The most common reason
1966     * for this is that there is no collator available for the locale you requested.
1967     * In this case the database remains unchanged.
1968     */
1969    public void setLocale(Locale locale) {
1970        lock();
1971        try {
1972            native_setLocale(locale.toString(), mFlags);
1973        } finally {
1974            unlock();
1975        }
1976    }
1977
1978    /*
1979     * ============================================================================
1980     *
1981     *       The following methods deal with compiled-sql cache
1982     * ============================================================================
1983     */
1984    /**
1985     * adds the given sql and its compiled-statement-id-returned-by-sqlite to the
1986     * cache of compiledQueries attached to 'this'.
1987     *
1988     * if there is already a {@link SQLiteCompiledSql} in compiledQueries for the given sql,
1989     * the new {@link SQLiteCompiledSql} object is NOT inserted into the cache (i.e.,the current
1990     * mapping is NOT replaced with the new mapping).
1991     */
1992    /* package */ void addToCompiledQueries(String sql, SQLiteCompiledSql compiledStatement) {
1993        SQLiteCompiledSql compiledSql = null;
1994        synchronized(mCompiledQueries) {
1995            // don't insert the new mapping if a mapping already exists
1996            compiledSql = mCompiledQueries.get(sql);
1997            if (compiledSql != null) {
1998                return;
1999            }
2000            // add this <sql, compiledStatement> to the cache
2001            if (mCompiledQueries.size() == mMaxSqlCacheSize) {
2002                /*
2003                 * cache size of {@link #mMaxSqlCacheSize} is not enough for this app.
2004                 * log a warning MAX_WARNINGS_ON_CACHESIZE_CONDITION times
2005                 * chances are it is NOT using ? for bindargs - so caching is useless.
2006                 * TODO: either let the callers set max cchesize for their app, or intelligently
2007                 * figure out what should be cached for a given app.
2008                 */
2009                if (++mCacheFullWarnings == MAX_WARNINGS_ON_CACHESIZE_CONDITION) {
2010                    Log.w(TAG, "Reached MAX size for compiled-sql statement cache for database " +
2011                            getPath() + "; i.e., NO space for this sql statement in cache: " +
2012                            sql + ". Please change your sql statements to use '?' for " +
2013                            "bindargs, instead of using actual values");
2014                }
2015                // don't add this entry to cache
2016            } else {
2017                // cache is NOT full. add this to cache.
2018                mCompiledQueries.put(sql, compiledStatement);
2019                if (SQLiteDebug.DEBUG_SQL_CACHE) {
2020                    Log.v(TAG, "|adding_sql_to_cache|" + getPath() + "|" +
2021                            mCompiledQueries.size() + "|" + sql);
2022                }
2023            }
2024        }
2025        return;
2026    }
2027
2028
2029    private void deallocCachedSqlStatements() {
2030        synchronized (mCompiledQueries) {
2031            for (SQLiteCompiledSql compiledSql : mCompiledQueries.values()) {
2032                compiledSql.releaseSqlStatement();
2033            }
2034            mCompiledQueries.clear();
2035        }
2036    }
2037
2038    /**
2039     * from the compiledQueries cache, returns the compiled-statement-id for the given sql.
2040     * returns null, if not found in the cache.
2041     */
2042    /* package */ SQLiteCompiledSql getCompiledStatementForSql(String sql) {
2043        SQLiteCompiledSql compiledStatement = null;
2044        boolean cacheHit;
2045        synchronized(mCompiledQueries) {
2046            cacheHit = (compiledStatement = mCompiledQueries.get(sql)) != null;
2047        }
2048        if (cacheHit) {
2049            mNumCacheHits++;
2050        } else {
2051            mNumCacheMisses++;
2052        }
2053
2054        if (SQLiteDebug.DEBUG_SQL_CACHE) {
2055            Log.v(TAG, "|cache_stats|" +
2056                    getPath() + "|" + mCompiledQueries.size() +
2057                    "|" + mNumCacheHits + "|" + mNumCacheMisses +
2058                    "|" + cacheHit + "|" + mTimeOpened + "|" + mTimeClosed + "|" + sql);
2059        }
2060        return compiledStatement;
2061    }
2062
2063    /**
2064     * returns true if the given sql is cached in compiled-sql cache.
2065     * @hide
2066     */
2067    public boolean isInCompiledSqlCache(String sql) {
2068        synchronized(mCompiledQueries) {
2069            return mCompiledQueries.containsKey(sql);
2070        }
2071    }
2072
2073    /**
2074     * purges the given sql from the compiled-sql cache.
2075     * @hide
2076     */
2077    public void purgeFromCompiledSqlCache(String sql) {
2078        synchronized(mCompiledQueries) {
2079            mCompiledQueries.remove(sql);
2080        }
2081    }
2082
2083    /**
2084     * remove everything from the compiled sql cache
2085     * @hide
2086     */
2087    public void resetCompiledSqlCache() {
2088        synchronized(mCompiledQueries) {
2089            mCompiledQueries.clear();
2090        }
2091    }
2092
2093    /**
2094     * return the current maxCacheSqlCacheSize
2095     * @hide
2096     */
2097    public synchronized int getMaxSqlCacheSize() {
2098        return mMaxSqlCacheSize;
2099    }
2100
2101    /**
2102     * set the max size of the prepared-statement cache for this database.
2103     * (size of the cache = number of compiled-sql-statements stored in the cache).
2104     *
2105     * max cache size can ONLY be increased from its current size (default = 10).
2106     * if this method is called with smaller size than the current value of mMaxSqlCacheSize,
2107     * then IllegalStateException is thrown
2108     *
2109     * synchronized because we don't want t threads to change cache size at the same time.
2110     * @param cacheSize the size of the cache. can be (0 to {@link #MAX_SQL_CACHE_SIZE})
2111     * @throws IllegalStateException if input cacheSize > {@link #MAX_SQL_CACHE_SIZE} or
2112     * > the value set with previous setMaxSqlCacheSize() call.
2113     */
2114    public synchronized void setMaxSqlCacheSize(int cacheSize) {
2115        if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) {
2116            throw new IllegalStateException("expected value between 0 and " + MAX_SQL_CACHE_SIZE);
2117        } else if (cacheSize < mMaxSqlCacheSize) {
2118            throw new IllegalStateException("cannot set cacheSize to a value less than the value " +
2119                    "set with previous setMaxSqlCacheSize() call.");
2120        }
2121        mMaxSqlCacheSize = cacheSize;
2122    }
2123
2124    static class ActiveDatabases {
2125        private static final ActiveDatabases activeDatabases = new ActiveDatabases();
2126        private HashSet<WeakReference<SQLiteDatabase>> mActiveDatabases =
2127            new HashSet<WeakReference<SQLiteDatabase>>();
2128        private ActiveDatabases() {} // disable instantiation of this class
2129        static ActiveDatabases getInstance() {return activeDatabases;}
2130    }
2131
2132    /**
2133     * this method is used to collect data about ALL open databases in the current process.
2134     * bugreport is a user of this data.
2135     */
2136    /* package */ static ArrayList<DbStats> getDbStats() {
2137        ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
2138        for (WeakReference<SQLiteDatabase> w : ActiveDatabases.getInstance().mActiveDatabases) {
2139            SQLiteDatabase db = w.get();
2140            if (db == null || !db.isOpen()) {
2141                continue;
2142            }
2143            // get SQLITE_DBSTATUS_LOOKASIDE_USED for the db
2144            int lookasideUsed = db.native_getDbLookaside();
2145
2146            // get the lastnode of the dbname
2147            String path = db.getPath();
2148            int indx = path.lastIndexOf("/");
2149            String lastnode = path.substring((indx != -1) ? ++indx : 0);
2150
2151            // get list of attached dbs and for each db, get its size and pagesize
2152            ArrayList<Pair<String, String>> attachedDbs = db.getAttachedDbs();
2153            if (attachedDbs == null) {
2154                continue;
2155            }
2156            for (int i = 0; i < attachedDbs.size(); i++) {
2157                Pair<String, String> p = attachedDbs.get(i);
2158                long pageCount = getPragmaVal(db, p.first + ".page_count;");
2159
2160                // first entry in the attached db list is always the main database
2161                // don't worry about prefixing the dbname with "main"
2162                String dbName;
2163                if (i == 0) {
2164                    dbName = lastnode;
2165                } else {
2166                    // lookaside is only relevant for the main db
2167                    lookasideUsed = 0;
2168                    dbName = "  (attached) " + p.first;
2169                    // if the attached db has a path, attach the lastnode from the path to above
2170                    if (p.second.trim().length() > 0) {
2171                        int idx = p.second.lastIndexOf("/");
2172                        dbName += " : " + p.second.substring((idx != -1) ? ++idx : 0);
2173                    }
2174                }
2175                if (pageCount > 0) {
2176                    dbStatsList.add(new DbStats(dbName, pageCount, db.getPageSize(),
2177                            lookasideUsed, db.mNumCacheHits, db.mNumCacheMisses,
2178                            db.mCompiledQueries.size()));
2179                }
2180            }
2181        }
2182        return dbStatsList;
2183    }
2184
2185    /**
2186     * get the specified pragma value from sqlite for the specified database.
2187     * only handles pragma's that return int/long.
2188     * NO JAVA locks are held in this method.
2189     * TODO: use this to do all pragma's in this class
2190     */
2191    private static long getPragmaVal(SQLiteDatabase db, String pragma) {
2192        if (!db.isOpen()) {
2193            return 0;
2194        }
2195        SQLiteStatement prog = null;
2196        try {
2197            prog = new SQLiteStatement(db, "PRAGMA " + pragma);
2198            long val = prog.simpleQueryForLong();
2199            return val;
2200        } finally {
2201            if (prog != null) prog.close();
2202        }
2203    }
2204
2205    /**
2206     * returns list of full pathnames of all attached databases including the main database
2207     * @return ArrayList of pairs of (database name, database file path) or null if the database
2208     * is not open.
2209     */
2210    public ArrayList<Pair<String, String>> getAttachedDbs() {
2211        if (!isOpen()) {
2212            return null;
2213        }
2214        ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>();
2215        Cursor c = null;
2216        try {
2217            c = rawQuery("pragma database_list;", null);
2218            while (c.moveToNext()) {
2219                // sqlite returns a row for each database in the returned list of databases.
2220                //   in each row,
2221                //       1st column is the database name such as main, or the database
2222                //                              name specified on the "ATTACH" command
2223                //       2nd column is the database file path.
2224                attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2)));
2225            }
2226        } finally {
2227            if (c != null) {
2228                c.close();
2229            }
2230        }
2231        return attachedDbs;
2232    }
2233
2234    /**
2235     * run pragma integrity_check on the given database (and all the attached databases)
2236     * and return true if the given database (and all its attached databases) pass integrity_check,
2237     * false otherwise.
2238     *
2239     * if the result is false, then this method logs the errors reported by the integrity_check
2240     * command execution.
2241     *
2242     * @return true if the given database (and all its attached databases) pass integrity_check,
2243     * false otherwise
2244     */
2245    public boolean isDatabaseIntegrityOk() {
2246        if (!isOpen()) {
2247            throw new IllegalStateException("database: " + getPath() + " is NOT open");
2248        }
2249        ArrayList<Pair<String, String>> attachedDbs = getAttachedDbs();
2250        if (attachedDbs == null) {
2251            throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " +
2252                    "be retrieved. probably because the database is closed");
2253        }
2254        boolean isDatabaseCorrupt = false;
2255        for (int i = 0; i < attachedDbs.size(); i++) {
2256            Pair<String, String> p = attachedDbs.get(i);
2257            SQLiteStatement prog = null;
2258            try {
2259                prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);");
2260                String rslt = prog.simpleQueryForString();
2261                if (!rslt.equalsIgnoreCase("ok")) {
2262                    // integrity_checker failed on main or attached databases
2263                    isDatabaseCorrupt = true;
2264                    Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt);
2265                }
2266            } finally {
2267                if (prog != null) prog.close();
2268            }
2269        }
2270        return isDatabaseCorrupt;
2271    }
2272
2273    /**
2274     * Native call to open the database.
2275     *
2276     * @param path The full path to the database
2277     */
2278    private native void dbopen(String path, int flags);
2279
2280    /**
2281     * Native call to setup tracing of all sql statements
2282     *
2283     * @param path the full path to the database
2284     */
2285    private native void enableSqlTracing(String path);
2286
2287    /**
2288     * Native call to setup profiling of all sql statements.
2289     * currently, sqlite's profiling = printing of execution-time
2290     * (wall-clock time) of each of the sql statements, as they
2291     * are executed.
2292     *
2293     * @param path the full path to the database
2294     */
2295    private native void enableSqlProfiling(String path);
2296
2297    /**
2298     * Native call to execute a raw SQL statement. {@link #lock} must be held
2299     * when calling this method.
2300     *
2301     * @param sql The raw SQL string
2302     * @throws SQLException
2303     */
2304    /* package */ native void native_execSQL(String sql) throws SQLException;
2305
2306    /**
2307     * Native call to set the locale.  {@link #lock} must be held when calling
2308     * this method.
2309     * @throws SQLException
2310     */
2311    /* package */ native void native_setLocale(String loc, int flags);
2312
2313    /**
2314     * Returns the row ID of the last row inserted into the database.
2315     *
2316     * @return the row ID of the last row inserted into the database.
2317     */
2318    /* package */ native long lastInsertRow();
2319
2320    /**
2321     * Returns the number of changes made in the last statement executed.
2322     *
2323     * @return the number of changes made in the last statement executed.
2324     */
2325    /* package */ native int lastChangeCount();
2326
2327    /**
2328     * return the SQLITE_DBSTATUS_LOOKASIDE_USED documented here
2329     * http://www.sqlite.org/c3ref/c_dbstatus_lookaside_used.html
2330     * @return int value of SQLITE_DBSTATUS_LOOKASIDE_USED
2331     */
2332    private native int native_getDbLookaside();
2333}
2334