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