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