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