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