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