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