blob: af6df1554a860a014ea52c73bda078ca4352ad59 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070019import android.annotation.IntDef;
20import android.annotation.IntRange;
Makoto Onuki17aa1b72015-12-16 14:02:01 -080021import android.annotation.NonNull;
22import android.annotation.Nullable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.content.ContentValues;
24import android.database.Cursor;
Vasu Nori062fc7ce2010-03-31 16:13:05 -070025import android.database.DatabaseErrorHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.database.DatabaseUtils;
Vasu Nori062fc7ce2010-03-31 16:13:05 -070027import android.database.DefaultDatabaseErrorHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.database.SQLException;
Vasu Noric3849202010-03-09 10:47:25 -080029import android.database.sqlite.SQLiteDebug.DbStats;
Jeff Browna7771df2012-05-07 20:06:46 -070030import android.os.CancellationSignal;
Jeff Browne5360fb2011-10-31 17:48:13 -070031import android.os.Looper;
Jeff Browna7771df2012-05-07 20:06:46 -070032import android.os.OperationCanceledException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.util.EventLog;
Dmitri Plotnikov90142c92009-09-15 10:52:17 -070035import android.util.Log;
Vasu Noric3849202010-03-09 10:47:25 -080036import android.util.Pair;
Jeff Browne5360fb2011-10-31 17:48:13 -070037import android.util.Printer;
38
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070039import com.android.internal.util.Preconditions;
40
Jeff Browne5360fb2011-10-31 17:48:13 -070041import dalvik.system.CloseGuard;
42
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import java.io.File;
Jeff Brown79087e42012-03-01 19:52:44 -080044import java.io.FileFilter;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070045import java.lang.annotation.Retention;
46import java.lang.annotation.RetentionPolicy;
Vasu Noric3849202010-03-09 10:47:25 -080047import java.util.ArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import java.util.HashMap;
Jesse Wilson9b5a9352011-02-10 11:19:09 -080049import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import java.util.Locale;
51import java.util.Map;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import java.util.WeakHashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053
54/**
55 * Exposes methods to manage a SQLite database.
Jeff Browne5360fb2011-10-31 17:48:13 -070056 *
57 * <p>
58 * SQLiteDatabase has methods to create, delete, execute SQL commands, and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059 * perform other common database management tasks.
Jeff Browne5360fb2011-10-31 17:48:13 -070060 * </p><p>
61 * See the Notepad sample application in the SDK for an example of creating
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062 * and managing a database.
Jeff Browne5360fb2011-10-31 17:48:13 -070063 * </p><p>
64 * Database names must be unique within an application, not across all applications.
65 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066 *
67 * <h3>Localized Collation - ORDER BY</h3>
Jeff Browne5360fb2011-10-31 17:48:13 -070068 * <p>
69 * In addition to SQLite's default <code>BINARY</code> collator, Android supplies
70 * two more, <code>LOCALIZED</code>, which changes with the system's current locale,
71 * and <code>UNICODE</code>, which is the Unicode Collation Algorithm and not tailored
72 * to the current locale.
73 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074 */
Jeff Brownbaefdfa2012-03-05 10:33:13 -080075public final class SQLiteDatabase extends SQLiteClosable {
Vasu Norifb16cbd2010-07-25 16:38:48 -070076 private static final String TAG = "SQLiteDatabase";
Jeff Browne5360fb2011-10-31 17:48:13 -070077
Jeff Hamilton082c2af2009-09-29 11:49:51 -070078 private static final int EVENT_DB_CORRUPT = 75004;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079
Jeff Browne5360fb2011-10-31 17:48:13 -070080 // Stores reference to all databases opened in the current process.
81 // (The referent Object is not used at this time.)
82 // INVARIANT: Guarded by sActiveDatabases.
83 private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases =
84 new WeakHashMap<SQLiteDatabase, Object>();
85
86 // Thread-local for database sessions that belong to this database.
87 // Each thread has its own database session.
88 // INVARIANT: Immutable.
89 private final ThreadLocal<SQLiteSession> mThreadSession = new ThreadLocal<SQLiteSession>() {
90 @Override
91 protected SQLiteSession initialValue() {
92 return createSession();
93 }
94 };
95
96 // The optional factory to use when creating new Cursors. May be null.
97 // INVARIANT: Immutable.
98 private final CursorFactory mCursorFactory;
99
100 // Error handler to be used when SQLite returns corruption errors.
101 // INVARIANT: Immutable.
102 private final DatabaseErrorHandler mErrorHandler;
103
104 // Shared database state lock.
105 // This lock guards all of the shared state of the database, such as its
106 // configuration, whether it is open or closed, and so on. This lock should
107 // be held for as little time as possible.
108 //
109 // The lock MUST NOT be held while attempting to acquire database connections or
110 // while executing SQL statements on behalf of the client as it can lead to deadlock.
111 //
112 // It is ok to hold the lock while reconfiguring the connection pool or dumping
113 // statistics because those operations are non-reentrant and do not try to acquire
114 // connections that might be held by other threads.
115 //
116 // Basic rule: grab the lock, access or modify global state, release the lock, then
117 // do the required SQL work.
118 private final Object mLock = new Object();
119
120 // Warns if the database is finalized without being closed properly.
121 // INVARIANT: Guarded by mLock.
122 private final CloseGuard mCloseGuardLocked = CloseGuard.get();
123
124 // The database configuration.
125 // INVARIANT: Guarded by mLock.
126 private final SQLiteDatabaseConfiguration mConfigurationLocked;
127
128 // The connection pool for the database, null when closed.
129 // The pool itself is thread-safe, but the reference to it can only be acquired
130 // when the lock is held.
131 // INVARIANT: Guarded by mLock.
132 private SQLiteConnectionPool mConnectionPoolLocked;
133
134 // True if the database has attached databases.
135 // INVARIANT: Guarded by mLock.
136 private boolean mHasAttachedDbsLocked;
137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700139 * When a constraint violation occurs, an immediate ROLLBACK occurs,
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800140 * thus ending the current transaction, and the command aborts with a
141 * return code of SQLITE_CONSTRAINT. If no transaction is active
142 * (other than the implied transaction that is created on every command)
Jeff Browne5360fb2011-10-31 17:48:13 -0700143 * then this algorithm works the same as ABORT.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800144 */
145 public static final int CONFLICT_ROLLBACK = 1;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700146
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800147 /**
148 * When a constraint violation occurs,no ROLLBACK is executed
149 * so changes from prior commands within the same transaction
150 * are preserved. This is the default behavior.
151 */
152 public static final int CONFLICT_ABORT = 2;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700153
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800154 /**
155 * When a constraint violation occurs, the command aborts with a return
156 * code SQLITE_CONSTRAINT. But any changes to the database that
157 * the command made prior to encountering the constraint violation
158 * are preserved and are not backed out.
159 */
160 public static final int CONFLICT_FAIL = 3;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700161
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800162 /**
163 * When a constraint violation occurs, the one row that contains
164 * the constraint violation is not inserted or changed.
165 * But the command continues executing normally. Other rows before and
166 * after the row that contained the constraint violation continue to be
167 * inserted or updated normally. No error is returned.
168 */
169 public static final int CONFLICT_IGNORE = 4;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700170
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800171 /**
172 * When a UNIQUE constraint violation occurs, the pre-existing rows that
173 * are causing the constraint violation are removed prior to inserting
174 * or updating the current row. Thus the insert or update always occurs.
175 * The command continues executing normally. No error is returned.
176 * If a NOT NULL constraint violation occurs, the NULL value is replaced
177 * by the default value for that column. If the column has no default
178 * value, then the ABORT algorithm is used. If a CHECK constraint
179 * violation occurs then the IGNORE algorithm is used. When this conflict
180 * resolution strategy deletes rows in order to satisfy a constraint,
181 * it does not invoke delete triggers on those rows.
Jeff Browne5360fb2011-10-31 17:48:13 -0700182 * This behavior might change in a future release.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800183 */
184 public static final int CONFLICT_REPLACE = 5;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700185
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800186 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700187 * Use the following when no conflict action is specified.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800188 */
189 public static final int CONFLICT_NONE = 0;
Jeff Browne5360fb2011-10-31 17:48:13 -0700190
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800191 private static final String[] CONFLICT_VALUES = new String[]
192 {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 /**
195 * Maximum Length Of A LIKE Or GLOB Pattern
196 * The pattern matching algorithm used in the default LIKE and GLOB implementation
197 * of SQLite can exhibit O(N^2) performance (where N is the number of characters in
198 * the pattern) for certain pathological cases. To avoid denial-of-service attacks
199 * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes.
200 * The default value of this limit is 50000. A modern workstation can evaluate
201 * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly.
202 * The denial of service problem only comes into play when the pattern length gets
203 * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns
204 * are at most a few dozen bytes in length, paranoid application developers may
205 * want to reduce this parameter to something in the range of a few hundred
206 * if they know that external users are able to generate arbitrary patterns.
207 */
208 public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000;
209
210 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700211 * Open flag: Flag for {@link #openDatabase} to open the database for reading and writing.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 * If the disk is full, this may fail even before you actually write anything.
213 *
214 * {@more} Note that the value of this flag is 0, so it is the default.
215 */
216 public static final int OPEN_READWRITE = 0x00000000; // update native code if changing
217
218 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700219 * Open flag: Flag for {@link #openDatabase} to open the database for reading only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 * This is the only reliable way to open a database if the disk may be full.
221 */
222 public static final int OPEN_READONLY = 0x00000001; // update native code if changing
223
224 private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing
225
226 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700227 * Open flag: Flag for {@link #openDatabase} to open the database without support for
228 * localized collators.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 *
230 * {@more} This causes the collator <code>LOCALIZED</code> not to be created.
231 * You must be consistent when using this flag to use the setting the database was
232 * created with. If this is set, {@link #setLocale} will do nothing.
233 */
234 public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing
235
236 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700237 * Open flag: Flag for {@link #openDatabase} to create the database file if it does not
238 * already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 */
240 public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing
241
242 /**
Jeff Brown47847f32012-03-22 19:13:11 -0700243 * Open flag: Flag for {@link #openDatabase} to open the database file with
244 * write-ahead logging enabled by default. Using this flag is more efficient
245 * than calling {@link #enableWriteAheadLogging}.
246 *
247 * Write-ahead logging cannot be used with read-only databases so the value of
248 * this flag is ignored if the database is opened read-only.
249 *
250 * @see #enableWriteAheadLogging
251 */
252 public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;
253
254 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700255 * Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}.
Vasu Norib729dcc2010-09-14 11:35:49 -0700256 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700257 * Each prepared-statement is between 1K - 6K, depending on the complexity of the
258 * SQL statement & schema. A large SQL cache may use a significant amount of memory.
Vasu Norie495d1f2010-01-06 16:34:19 -0800259 */
Vasu Nori90a367262010-04-12 12:49:09 -0700260 public static final int MAX_SQL_CACHE_SIZE = 100;
Vasu Norib729dcc2010-09-14 11:35:49 -0700261
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700262 private SQLiteDatabase(final String path, final int openFlags,
263 CursorFactory cursorFactory, DatabaseErrorHandler errorHandler,
264 int lookasideSlotSize, int lookasideSlotCount) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700265 mCursorFactory = cursorFactory;
266 mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler();
267 mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700268 mConfigurationLocked.lookasideSlotSize = lookasideSlotSize;
269 mConfigurationLocked.lookasideSlotCount = lookasideSlotCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700271
Jeff Browne5360fb2011-10-31 17:48:13 -0700272 @Override
273 protected void finalize() throws Throwable {
274 try {
275 dispose(true);
276 } finally {
277 super.finalize();
278 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700279 }
280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 @Override
282 protected void onAllReferencesReleased() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700283 dispose(false);
284 }
285
286 private void dispose(boolean finalized) {
287 final SQLiteConnectionPool pool;
288 synchronized (mLock) {
289 if (mCloseGuardLocked != null) {
290 if (finalized) {
291 mCloseGuardLocked.warnIfOpen();
292 }
293 mCloseGuardLocked.close();
294 }
295
296 pool = mConnectionPoolLocked;
297 mConnectionPoolLocked = null;
298 }
299
300 if (!finalized) {
301 synchronized (sActiveDatabases) {
302 sActiveDatabases.remove(this);
303 }
304
305 if (pool != null) {
306 pool.close();
307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 }
309 }
310
311 /**
312 * Attempts to release memory that SQLite holds but does not require to
313 * operate properly. Typically this memory will come from the page cache.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700314 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 * @return the number of bytes actually released
316 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700317 public static int releaseMemory() {
318 return SQLiteGlobal.releaseMemory();
319 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320
321 /**
322 * Control whether or not the SQLiteDatabase is made thread-safe by using locks
323 * around critical sections. This is pretty expensive, so if you know that your
324 * DB will only be used by a single thread then you should set this to false.
325 * The default is true.
326 * @param lockingEnabled set to true to enable locks, false otherwise
Jeff Browne5360fb2011-10-31 17:48:13 -0700327 *
328 * @deprecated This method now does nothing. Do not use.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700330 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331 public void setLockingEnabled(boolean lockingEnabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800332 }
333
334 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700335 * Gets a label to use when describing the database in log messages.
336 * @return The label.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700338 String getLabel() {
339 synchronized (mLock) {
340 return mConfigurationLocked.label;
341 }
342 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800343
Jeff Browne5360fb2011-10-31 17:48:13 -0700344 /**
345 * Sends a corruption message to the database error handler.
346 */
347 void onCorruption() {
348 EventLog.writeEvent(EVENT_DB_CORRUPT, getLabel());
Vasu Noriccd95442010-05-28 17:04:16 -0700349 mErrorHandler.onCorruption(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 }
351
352 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700353 * Gets the {@link SQLiteSession} that belongs to this thread for this database.
354 * Once a thread has obtained a session, it will continue to obtain the same
355 * session even after the database has been closed (although the session will not
356 * be usable). However, a thread that does not already have a session cannot
357 * obtain one after the database has been closed.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700358 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700359 * The idea is that threads that have active connections to the database may still
360 * have work to complete even after the call to {@link #close}. Active database
361 * connections are not actually disposed until they are released by the threads
362 * that own them.
363 *
364 * @return The session, never null.
365 *
366 * @throws IllegalStateException if the thread does not yet have a session and
367 * the database is not open.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700369 SQLiteSession getThreadSession() {
370 return mThreadSession.get(); // initialValue() throws if database closed
Vasu Nori6d970252010-10-05 10:48:49 -0700371 }
Vasu Nori16057fa2011-03-18 11:40:37 -0700372
Jeff Browne5360fb2011-10-31 17:48:13 -0700373 SQLiteSession createSession() {
374 final SQLiteConnectionPool pool;
375 synchronized (mLock) {
376 throwIfNotOpenLocked();
377 pool = mConnectionPoolLocked;
Vasu Nori6d970252010-10-05 10:48:49 -0700378 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700379 return new SQLiteSession(pool);
Vasu Norid4608a32011-02-03 16:24:06 -0800380 }
381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700383 * Gets default connection flags that are appropriate for this thread, taking into
384 * account whether the thread is acting on behalf of the UI.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700386 * @param readOnly True if the connection should be read-only.
387 * @return The connection flags.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700389 int getThreadDefaultConnectionFlags(boolean readOnly) {
390 int flags = readOnly ? SQLiteConnectionPool.CONNECTION_FLAG_READ_ONLY :
391 SQLiteConnectionPool.CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY;
392 if (isMainThread()) {
393 flags |= SQLiteConnectionPool.CONNECTION_FLAG_INTERACTIVE;
394 }
395 return flags;
Vasu Nori16057fa2011-03-18 11:40:37 -0700396 }
397
Jeff Browne5360fb2011-10-31 17:48:13 -0700398 private static boolean isMainThread() {
399 // FIXME: There should be a better way to do this.
400 // Would also be nice to have something that would work across Binder calls.
401 Looper looper = Looper.myLooper();
402 return looper != null && looper == Looper.getMainLooper();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 }
404
405 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700406 * Begins a transaction in EXCLUSIVE mode.
407 * <p>
408 * Transactions can be nested.
409 * When the outer transaction is ended all of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 * the work done in that transaction and all of the nested transactions will be committed or
411 * rolled back. The changes will be rolled back if any transaction is ended without being
412 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700413 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 * <p>Here is the standard idiom for transactions:
415 *
416 * <pre>
417 * db.beginTransaction();
418 * try {
419 * ...
420 * db.setTransactionSuccessful();
421 * } finally {
422 * db.endTransaction();
423 * }
424 * </pre>
425 */
426 public void beginTransaction() {
Vasu Nori6c354da2010-04-26 23:33:39 -0700427 beginTransaction(null /* transactionStatusCallback */, true);
428 }
429
430 /**
431 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
432 * the outer transaction is ended all of the work done in that transaction
433 * and all of the nested transactions will be committed or rolled back. The
434 * changes will be rolled back if any transaction is ended without being
435 * marked as clean (by calling setTransactionSuccessful). Otherwise they
436 * will be committed.
437 * <p>
438 * Here is the standard idiom for transactions:
439 *
440 * <pre>
441 * db.beginTransactionNonExclusive();
442 * try {
443 * ...
444 * db.setTransactionSuccessful();
445 * } finally {
446 * db.endTransaction();
447 * }
448 * </pre>
449 */
450 public void beginTransactionNonExclusive() {
451 beginTransaction(null /* transactionStatusCallback */, false);
Fred Quintanac4516a72009-09-03 12:14:06 -0700452 }
453
454 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700455 * Begins a transaction in EXCLUSIVE mode.
456 * <p>
457 * Transactions can be nested.
458 * When the outer transaction is ended all of
Fred Quintanac4516a72009-09-03 12:14:06 -0700459 * the work done in that transaction and all of the nested transactions will be committed or
460 * rolled back. The changes will be rolled back if any transaction is ended without being
461 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700462 * </p>
Fred Quintanac4516a72009-09-03 12:14:06 -0700463 * <p>Here is the standard idiom for transactions:
464 *
465 * <pre>
466 * db.beginTransactionWithListener(listener);
467 * try {
468 * ...
469 * db.setTransactionSuccessful();
470 * } finally {
471 * db.endTransaction();
472 * }
473 * </pre>
Vasu Noriccd95442010-05-28 17:04:16 -0700474 *
Fred Quintanac4516a72009-09-03 12:14:06 -0700475 * @param transactionListener listener that should be notified when the transaction begins,
476 * commits, or is rolled back, either explicitly or by a call to
477 * {@link #yieldIfContendedSafely}.
478 */
479 public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
Vasu Nori6c354da2010-04-26 23:33:39 -0700480 beginTransaction(transactionListener, true);
481 }
482
483 /**
484 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
485 * the outer transaction is ended all of the work done in that transaction
486 * and all of the nested transactions will be committed or rolled back. The
487 * changes will be rolled back if any transaction is ended without being
488 * marked as clean (by calling setTransactionSuccessful). Otherwise they
489 * will be committed.
490 * <p>
491 * Here is the standard idiom for transactions:
492 *
493 * <pre>
494 * db.beginTransactionWithListenerNonExclusive(listener);
495 * try {
496 * ...
497 * db.setTransactionSuccessful();
498 * } finally {
499 * db.endTransaction();
500 * }
501 * </pre>
502 *
503 * @param transactionListener listener that should be notified when the
504 * transaction begins, commits, or is rolled back, either
505 * explicitly or by a call to {@link #yieldIfContendedSafely}.
506 */
507 public void beginTransactionWithListenerNonExclusive(
508 SQLiteTransactionListener transactionListener) {
509 beginTransaction(transactionListener, false);
510 }
511
512 private void beginTransaction(SQLiteTransactionListener transactionListener,
513 boolean exclusive) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800514 acquireReference();
515 try {
516 getThreadSession().beginTransaction(
517 exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
518 SQLiteSession.TRANSACTION_MODE_IMMEDIATE,
519 transactionListener,
520 getThreadDefaultConnectionFlags(false /*readOnly*/), null);
521 } finally {
522 releaseReference();
523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 }
525
526 /**
527 * End a transaction. See beginTransaction for notes about how to use this and when transactions
528 * are committed and rolled back.
529 */
530 public void endTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800531 acquireReference();
532 try {
533 getThreadSession().endTransaction(null);
534 } finally {
535 releaseReference();
536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 }
538
539 /**
540 * Marks the current transaction as successful. Do not do any more database work between
541 * calling this and calling endTransaction. Do as little non-database work as possible in that
542 * situation too. If any errors are encountered between this and endTransaction the transaction
543 * will still be committed.
544 *
545 * @throws IllegalStateException if the current thread is not in a transaction or the
546 * transaction is already marked as successful.
547 */
548 public void setTransactionSuccessful() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800549 acquireReference();
550 try {
551 getThreadSession().setTransactionSuccessful();
552 } finally {
553 releaseReference();
554 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 }
556
557 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700558 * Returns true if the current thread has a transaction pending.
559 *
560 * @return True if the current thread is in a transaction.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561 */
562 public boolean inTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800563 acquireReference();
564 try {
565 return getThreadSession().hasTransaction();
566 } finally {
567 releaseReference();
568 }
Vasu Norice38b982010-07-22 13:57:13 -0700569 }
570
571 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700572 * Returns true if the current thread is holding an active connection to the database.
Vasu Norice38b982010-07-22 13:57:13 -0700573 * <p>
Jeff Browne5360fb2011-10-31 17:48:13 -0700574 * The name of this method comes from a time when having an active connection
575 * to the database meant that the thread was holding an actual lock on the
576 * database. Nowadays, there is no longer a true "database lock" although threads
577 * may block if they cannot acquire a database connection to perform a
578 * particular operation.
579 * </p>
Vasu Norice38b982010-07-22 13:57:13 -0700580 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700581 * @return True if the current thread is holding an active connection to the database.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 */
583 public boolean isDbLockedByCurrentThread() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800584 acquireReference();
585 try {
586 return getThreadSession().hasConnection();
587 } finally {
588 releaseReference();
589 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 }
591
592 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700593 * Always returns false.
594 * <p>
595 * There is no longer the concept of a database lock, so this method always returns false.
596 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700598 * @return False.
599 * @deprecated Always returns false. Do not use this method.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700601 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 public boolean isDbLockedByOtherThreads() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700603 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 }
605
606 /**
607 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
608 * successful so far. Do not call setTransactionSuccessful before calling this. When this
609 * returns a new transaction will have been created but not marked as successful.
610 * @return true if the transaction was yielded
611 * @deprecated if the db is locked more than once (becuase of nested transactions) then the lock
612 * will not be yielded. Use yieldIfContendedSafely instead.
613 */
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700614 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615 public boolean yieldIfContended() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700616 return yieldIfContendedHelper(false /* do not check yielding */,
617 -1 /* sleepAfterYieldDelay */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 }
619
620 /**
621 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
622 * successful so far. Do not call setTransactionSuccessful before calling this. When this
623 * returns a new transaction will have been created but not marked as successful. This assumes
624 * that there are no nested transactions (beginTransaction has only been called once) and will
Fred Quintana5c7aede2009-08-27 21:41:27 -0700625 * throw an exception if that is not the case.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 * @return true if the transaction was yielded
627 */
628 public boolean yieldIfContendedSafely() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700629 return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630 }
631
Fred Quintana5c7aede2009-08-27 21:41:27 -0700632 /**
633 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
634 * successful so far. Do not call setTransactionSuccessful before calling this. When this
635 * returns a new transaction will have been created but not marked as successful. This assumes
636 * that there are no nested transactions (beginTransaction has only been called once) and will
637 * throw an exception if that is not the case.
638 * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if
639 * the lock was actually yielded. This will allow other background threads to make some
640 * more progress than they would if we started the transaction immediately.
641 * @return true if the transaction was yielded
642 */
643 public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
644 return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay);
645 }
646
Jeff Browne5360fb2011-10-31 17:48:13 -0700647 private boolean yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800648 acquireReference();
649 try {
650 return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null);
651 } finally {
652 releaseReference();
653 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654 }
655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800656 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700657 * Deprecated.
Vasu Nori95675132010-07-21 16:24:40 -0700658 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 */
Vasu Nori95675132010-07-21 16:24:40 -0700660 @Deprecated
661 public Map<String, String> getSyncedTables() {
662 return new HashMap<String, String>(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663 }
664
665 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666 * Open the database according to the flags {@link #OPEN_READWRITE}
667 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
668 *
669 * <p>Sets the locale of the database to the the system's current locale.
670 * Call {@link #setLocale} if you would like something else.</p>
671 *
672 * @param path to database file to open and/or create
673 * @param factory an optional factory class that is called to instantiate a
674 * cursor when query is called, or null for default
675 * @param flags to control database access mode
676 * @return the newly opened database
677 * @throws SQLiteException if the database cannot be opened
678 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700679 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
680 @DatabaseOpenFlags int flags) {
Jeff Brown47847f32012-03-22 19:13:11 -0700681 return openDatabase(path, factory, flags, null);
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700682 }
683
684 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700685 * Open the database according to the specified {@link OpenParams parameters}
686 *
687 * @param path to database file to open and/or create
688 * @param openParams configuration parameters that are used for opening {@link SQLiteDatabase}
689 * @return the newly opened database
690 * @throws SQLiteException if the database cannot be opened
691 */
692 public static SQLiteDatabase openDatabase(@NonNull String path,
693 @NonNull OpenParams openParams) {
694 Preconditions.checkArgument(openParams != null, "OpenParams cannot be null");
695 SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags,
696 openParams.mCursorFactory, openParams.mErrorHandler,
697 openParams.mLookasideSlotSize, openParams.mLookasideSlotCount);
698 db.open();
699 return db;
700 }
701
702 /**
Vasu Nori74f170f2010-06-01 18:06:18 -0700703 * Open the database according to the flags {@link #OPEN_READWRITE}
704 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
705 *
706 * <p>Sets the locale of the database to the the system's current locale.
707 * Call {@link #setLocale} if you would like something else.</p>
708 *
709 * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be
710 * used to handle corruption when sqlite reports database corruption.</p>
711 *
712 * @param path to database file to open and/or create
713 * @param factory an optional factory class that is called to instantiate a
714 * cursor when query is called, or null for default
715 * @param flags to control database access mode
716 * @param errorHandler the {@link DatabaseErrorHandler} obj to be used to handle corruption
717 * when sqlite reports database corruption
718 * @return the newly opened database
719 * @throws SQLiteException if the database cannot be opened
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700720 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700721 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
722 @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler) {
723 SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1);
Jeff Browne5360fb2011-10-31 17:48:13 -0700724 db.open();
725 return db;
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700726 }
727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 /**
729 * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
730 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700731 public static SQLiteDatabase openOrCreateDatabase(@NonNull File file,
732 @Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 return openOrCreateDatabase(file.getPath(), factory);
734 }
735
736 /**
737 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
738 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700739 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
740 @Nullable CursorFactory factory) {
Jeff Brown47847f32012-03-22 19:13:11 -0700741 return openDatabase(path, factory, CREATE_IF_NECESSARY, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800742 }
743
744 /**
Vasu Nori6c354da2010-04-26 23:33:39 -0700745 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler).
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700746 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700747 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
748 @Nullable CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler) {
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700749 return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler);
750 }
751
Jeff Brown559d0642012-02-29 10:19:12 -0800752 /**
Jeff Brown79087e42012-03-01 19:52:44 -0800753 * Deletes a database including its journal file and other auxiliary files
754 * that may have been created by the database engine.
755 *
756 * @param file The database file path.
757 * @return True if the database was successfully deleted.
758 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700759 public static boolean deleteDatabase(@NonNull File file) {
Jeff Brown79087e42012-03-01 19:52:44 -0800760 if (file == null) {
761 throw new IllegalArgumentException("file must not be null");
762 }
763
764 boolean deleted = false;
765 deleted |= file.delete();
766 deleted |= new File(file.getPath() + "-journal").delete();
767 deleted |= new File(file.getPath() + "-shm").delete();
768 deleted |= new File(file.getPath() + "-wal").delete();
769
770 File dir = file.getParentFile();
771 if (dir != null) {
772 final String prefix = file.getName() + "-mj";
Jeff Brownfce58902014-01-24 13:20:57 -0800773 File[] files = dir.listFiles(new FileFilter() {
Jeff Brown79087e42012-03-01 19:52:44 -0800774 @Override
775 public boolean accept(File candidate) {
776 return candidate.getName().startsWith(prefix);
777 }
Jeff Brownfce58902014-01-24 13:20:57 -0800778 });
779 if (files != null) {
780 for (File masterJournal : files) {
781 deleted |= masterJournal.delete();
782 }
Jeff Brown79087e42012-03-01 19:52:44 -0800783 }
784 }
785 return deleted;
786 }
787
788 /**
Jeff Brown559d0642012-02-29 10:19:12 -0800789 * Reopens the database in read-write mode.
790 * If the database is already read-write, does nothing.
791 *
792 * @throws SQLiteException if the database could not be reopened as requested, in which
793 * case it remains open in read only mode.
794 * @throws IllegalStateException if the database is not open.
795 *
796 * @see #isReadOnly()
797 * @hide
798 */
799 public void reopenReadWrite() {
800 synchronized (mLock) {
801 throwIfNotOpenLocked();
802
803 if (!isReadOnlyLocked()) {
804 return; // nothing to do
805 }
806
807 // Reopen the database in read-write mode.
808 final int oldOpenFlags = mConfigurationLocked.openFlags;
809 mConfigurationLocked.openFlags = (mConfigurationLocked.openFlags & ~OPEN_READ_MASK)
810 | OPEN_READWRITE;
811 try {
812 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
813 } catch (RuntimeException ex) {
814 mConfigurationLocked.openFlags = oldOpenFlags;
815 throw ex;
816 }
817 }
818 }
819
Jeff Browne5360fb2011-10-31 17:48:13 -0700820 private void open() {
821 try {
822 try {
823 openInner();
824 } catch (SQLiteDatabaseCorruptException ex) {
825 onCorruption();
826 openInner();
827 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700828 } catch (SQLiteException ex) {
829 Log.e(TAG, "Failed to open database '" + getLabel() + "'.", ex);
830 close();
831 throw ex;
832 }
833 }
834
835 private void openInner() {
836 synchronized (mLock) {
837 assert mConnectionPoolLocked == null;
838 mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked);
839 mCloseGuardLocked.open("close");
840 }
841
842 synchronized (sActiveDatabases) {
843 sActiveDatabases.put(this, null);
844 }
845 }
846
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700847 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 * Create a memory backed SQLite database. Its contents will be destroyed
849 * when the database is closed.
850 *
851 * <p>Sets the locale of the database to the the system's current locale.
852 * Call {@link #setLocale} if you would like something else.</p>
853 *
854 * @param factory an optional factory class that is called to instantiate a
855 * cursor when query is called
856 * @return a SQLiteDatabase object, or null if the database can't be created
857 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700858 @NonNull
859 public static SQLiteDatabase create(@Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 // This is a magic string with special meaning for SQLite.
Jeff Browne5360fb2011-10-31 17:48:13 -0700861 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
862 factory, CREATE_IF_NECESSARY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 }
864
865 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700866 * Create a memory backed SQLite database. Its contents will be destroyed
867 * when the database is closed.
868 *
869 * <p>Sets the locale of the database to the the system's current locale.
870 * Call {@link #setLocale} if you would like something else.</p>
871 * @param openParams configuration parameters that are used for opening SQLiteDatabase
872 * @return a SQLiteDatabase object, or null if the database can't be created
873 */
874 @NonNull
875 public static SQLiteDatabase createInMemory(@NonNull OpenParams openParams) {
876 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
877 openParams.toBuilder().addOpenFlags(CREATE_IF_NECESSARY).build());
878 }
879
880 /**
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400881 * Registers a CustomFunction callback as a function that can be called from
Jeff Browne5360fb2011-10-31 17:48:13 -0700882 * SQLite database triggers.
883 *
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400884 * @param name the name of the sqlite3 function
885 * @param numArgs the number of arguments for the function
886 * @param function callback to call when the function is executed
887 * @hide
888 */
889 public void addCustomFunction(String name, int numArgs, CustomFunction function) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700890 // Create wrapper (also validates arguments).
891 SQLiteCustomFunction wrapper = new SQLiteCustomFunction(name, numArgs, function);
892
893 synchronized (mLock) {
894 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -0700895
Jeff Browne5360fb2011-10-31 17:48:13 -0700896 mConfigurationLocked.customFunctions.add(wrapper);
Jeff Browne67ca422012-03-21 17:24:05 -0700897 try {
898 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
899 } catch (RuntimeException ex) {
900 mConfigurationLocked.customFunctions.remove(wrapper);
901 throw ex;
902 }
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400903 }
904 }
905
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400906 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 * Gets the database version.
908 *
909 * @return the database version
910 */
911 public int getVersion() {
Vasu Noriccd95442010-05-28 17:04:16 -0700912 return ((Long) DatabaseUtils.longForQuery(this, "PRAGMA user_version;", null)).intValue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 }
914
915 /**
916 * Sets the database version.
917 *
918 * @param version the new database version
919 */
920 public void setVersion(int version) {
921 execSQL("PRAGMA user_version = " + version);
922 }
923
924 /**
925 * Returns the maximum size the database may grow to.
926 *
927 * @return the new maximum database size
928 */
929 public long getMaximumSize() {
Vasu Noriccd95442010-05-28 17:04:16 -0700930 long pageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count;", null);
931 return pageCount * getPageSize();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932 }
933
934 /**
935 * Sets the maximum size the database will grow to. The maximum size cannot
936 * be set below the current size.
937 *
938 * @param numBytes the maximum database size, in bytes
939 * @return the new maximum database size
940 */
941 public long setMaximumSize(long numBytes) {
Vasu Noriccd95442010-05-28 17:04:16 -0700942 long pageSize = getPageSize();
943 long numPages = numBytes / pageSize;
944 // If numBytes isn't a multiple of pageSize, bump up a page
945 if ((numBytes % pageSize) != 0) {
946 numPages++;
Vasu Norif3cf8a42010-03-23 11:41:44 -0700947 }
Vasu Noriccd95442010-05-28 17:04:16 -0700948 long newPageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count = " + numPages,
949 null);
950 return newPageCount * pageSize;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800951 }
952
953 /**
954 * Returns the current database page size, in bytes.
955 *
956 * @return the database page size, in bytes
957 */
958 public long getPageSize() {
Vasu Noriccd95442010-05-28 17:04:16 -0700959 return DatabaseUtils.longForQuery(this, "PRAGMA page_size;", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 }
961
962 /**
963 * Sets the database page size. The page size must be a power of two. This
964 * method does not work if any data has been written to the database file,
965 * and must be called right after the database has been created.
966 *
967 * @param numBytes the database page size, in bytes
968 */
969 public void setPageSize(long numBytes) {
970 execSQL("PRAGMA page_size = " + numBytes);
971 }
972
973 /**
974 * Mark this table as syncable. When an update occurs in this table the
975 * _sync_dirty field will be set to ensure proper syncing operation.
976 *
977 * @param table the table to mark as syncable
978 * @param deletedTable The deleted table that corresponds to the
979 * syncable table
Vasu Nori95675132010-07-21 16:24:40 -0700980 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 */
Vasu Nori95675132010-07-21 16:24:40 -0700982 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 public void markTableSyncable(String table, String deletedTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 }
985
986 /**
987 * Mark this table as syncable, with the _sync_dirty residing in another
988 * table. When an update occurs in this table the _sync_dirty field of the
989 * row in updateTable with the _id in foreignKey will be set to
990 * ensure proper syncing operation.
991 *
992 * @param table an update on this table will trigger a sync time removal
993 * @param foreignKey this is the column in table whose value is an _id in
994 * updateTable
995 * @param updateTable this is the table that will have its _sync_dirty
Vasu Nori95675132010-07-21 16:24:40 -0700996 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 */
Vasu Nori95675132010-07-21 16:24:40 -0700998 @Deprecated
999 public void markTableSyncable(String table, String foreignKey, String updateTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 }
1001
1002 /**
1003 * Finds the name of the first table, which is editable.
1004 *
1005 * @param tables a list of tables
1006 * @return the first table listed
1007 */
1008 public static String findEditTable(String tables) {
1009 if (!TextUtils.isEmpty(tables)) {
1010 // find the first word terminated by either a space or a comma
1011 int spacepos = tables.indexOf(' ');
1012 int commapos = tables.indexOf(',');
1013
1014 if (spacepos > 0 && (spacepos < commapos || commapos < 0)) {
1015 return tables.substring(0, spacepos);
1016 } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) {
1017 return tables.substring(0, commapos);
1018 }
1019 return tables;
1020 } else {
1021 throw new IllegalStateException("Invalid tables");
1022 }
1023 }
1024
1025 /**
1026 * Compiles an SQL statement into a reusable pre-compiled statement object.
1027 * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the
1028 * statement and fill in those values with {@link SQLiteProgram#bindString}
1029 * and {@link SQLiteProgram#bindLong} each time you want to run the
1030 * statement. Statements may not return result sets larger than 1x1.
Vasu Nori2827d6d2010-07-04 00:26:18 -07001031 *<p>
1032 * No two threads should be using the same {@link SQLiteStatement} at the same time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 *
1034 * @param sql The raw SQL statement, may contain ? for unknown values to be
1035 * bound later.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001036 * @return A pre-compiled {@link SQLiteStatement} object. Note that
1037 * {@link SQLiteStatement}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 */
1039 public SQLiteStatement compileStatement(String sql) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001040 acquireReference();
1041 try {
1042 return new SQLiteStatement(this, sql, null);
1043 } finally {
1044 releaseReference();
1045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001046 }
1047
1048 /**
1049 * Query the given URL, returning a {@link Cursor} over the result set.
1050 *
1051 * @param distinct true if you want each row to be unique, false otherwise.
1052 * @param table The table name to compile the query against.
1053 * @param columns A list of which columns to return. Passing null will
1054 * return all columns, which is discouraged to prevent reading
1055 * data from storage that isn't going to be used.
1056 * @param selection A filter declaring which rows to return, formatted as an
1057 * SQL WHERE clause (excluding the WHERE itself). Passing null
1058 * will return all rows for the given table.
1059 * @param selectionArgs You may include ?s in selection, which will be
1060 * replaced by the values from selectionArgs, in order that they
1061 * appear in the selection. The values will be bound as Strings.
1062 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1063 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1064 * will cause the rows to not be grouped.
1065 * @param having A filter declare which row groups to include in the cursor,
1066 * if row grouping is being used, formatted as an SQL HAVING
1067 * clause (excluding the HAVING itself). Passing null will cause
1068 * all row groups to be included, and is required when row
1069 * grouping is not being used.
1070 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1071 * (excluding the ORDER BY itself). Passing null will use the
1072 * default sort order, which may be unordered.
1073 * @param limit Limits the number of rows returned by the query,
1074 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001075 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1076 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 * @see Cursor
1078 */
1079 public Cursor query(boolean distinct, String table, String[] columns,
1080 String selection, String[] selectionArgs, String groupBy,
1081 String having, String orderBy, String limit) {
1082 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown75ea64f2012-01-25 19:37:13 -08001083 groupBy, having, orderBy, limit, null);
1084 }
1085
1086 /**
1087 * Query the given URL, returning a {@link Cursor} over the result set.
1088 *
1089 * @param distinct true if you want each row to be unique, false otherwise.
1090 * @param table The table name to compile the query against.
1091 * @param columns A list of which columns to return. Passing null will
1092 * return all columns, which is discouraged to prevent reading
1093 * data from storage that isn't going to be used.
1094 * @param selection A filter declaring which rows to return, formatted as an
1095 * SQL WHERE clause (excluding the WHERE itself). Passing null
1096 * will return all rows for the given table.
1097 * @param selectionArgs You may include ?s in selection, which will be
1098 * replaced by the values from selectionArgs, in order that they
1099 * appear in the selection. The values will be bound as Strings.
1100 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1101 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1102 * will cause the rows to not be grouped.
1103 * @param having A filter declare which row groups to include in the cursor,
1104 * if row grouping is being used, formatted as an SQL HAVING
1105 * clause (excluding the HAVING itself). Passing null will cause
1106 * all row groups to be included, and is required when row
1107 * grouping is not being used.
1108 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1109 * (excluding the ORDER BY itself). Passing null will use the
1110 * default sort order, which may be unordered.
1111 * @param limit Limits the number of rows returned by the query,
1112 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001113 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001114 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1115 * when the query is executed.
1116 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1117 * {@link Cursor}s are not synchronized, see the documentation for more details.
1118 * @see Cursor
1119 */
1120 public Cursor query(boolean distinct, String table, String[] columns,
1121 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001122 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001123 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001124 groupBy, having, orderBy, limit, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001125 }
1126
1127 /**
1128 * Query the given URL, returning a {@link Cursor} over the result set.
1129 *
1130 * @param cursorFactory the cursor factory to use, or null for the default factory
1131 * @param distinct true if you want each row to be unique, false otherwise.
1132 * @param table The table name to compile the query against.
1133 * @param columns A list of which columns to return. Passing null will
1134 * return all columns, which is discouraged to prevent reading
1135 * data from storage that isn't going to be used.
1136 * @param selection A filter declaring which rows to return, formatted as an
1137 * SQL WHERE clause (excluding the WHERE itself). Passing null
1138 * will return all rows for the given table.
1139 * @param selectionArgs You may include ?s in selection, which will be
1140 * replaced by the values from selectionArgs, in order that they
1141 * appear in the selection. The values will be bound as Strings.
1142 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1143 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1144 * will cause the rows to not be grouped.
1145 * @param having A filter declare which row groups to include in the cursor,
1146 * if row grouping is being used, formatted as an SQL HAVING
1147 * clause (excluding the HAVING itself). Passing null will cause
1148 * all row groups to be included, and is required when row
1149 * grouping is not being used.
1150 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1151 * (excluding the ORDER BY itself). Passing null will use the
1152 * default sort order, which may be unordered.
1153 * @param limit Limits the number of rows returned by the query,
1154 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001155 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1156 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 * @see Cursor
1158 */
1159 public Cursor queryWithFactory(CursorFactory cursorFactory,
1160 boolean distinct, String table, String[] columns,
1161 String selection, String[] selectionArgs, String groupBy,
1162 String having, String orderBy, String limit) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001163 return queryWithFactory(cursorFactory, distinct, table, columns, selection,
1164 selectionArgs, groupBy, having, orderBy, limit, null);
1165 }
1166
1167 /**
1168 * Query the given URL, returning a {@link Cursor} over the result set.
1169 *
1170 * @param cursorFactory the cursor factory to use, or null for the default factory
1171 * @param distinct true if you want each row to be unique, false otherwise.
1172 * @param table The table name to compile the query against.
1173 * @param columns A list of which columns to return. Passing null will
1174 * return all columns, which is discouraged to prevent reading
1175 * data from storage that isn't going to be used.
1176 * @param selection A filter declaring which rows to return, formatted as an
1177 * SQL WHERE clause (excluding the WHERE itself). Passing null
1178 * will return all rows for the given table.
1179 * @param selectionArgs You may include ?s in selection, which will be
1180 * replaced by the values from selectionArgs, in order that they
1181 * appear in the selection. The values will be bound as Strings.
1182 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1183 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1184 * will cause the rows to not be grouped.
1185 * @param having A filter declare which row groups to include in the cursor,
1186 * if row grouping is being used, formatted as an SQL HAVING
1187 * clause (excluding the HAVING itself). Passing null will cause
1188 * all row groups to be included, and is required when row
1189 * grouping is not being used.
1190 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1191 * (excluding the ORDER BY itself). Passing null will use the
1192 * default sort order, which may be unordered.
1193 * @param limit Limits the number of rows returned by the query,
1194 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001195 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001196 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1197 * when the query is executed.
1198 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1199 * {@link Cursor}s are not synchronized, see the documentation for more details.
1200 * @see Cursor
1201 */
1202 public Cursor queryWithFactory(CursorFactory cursorFactory,
1203 boolean distinct, String table, String[] columns,
1204 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001205 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001206 acquireReference();
1207 try {
1208 String sql = SQLiteQueryBuilder.buildQueryString(
1209 distinct, table, columns, selection, groupBy, having, orderBy, limit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001210
Jeff Brown03bd3022012-03-06 13:48:56 -08001211 return rawQueryWithFactory(cursorFactory, sql, selectionArgs,
1212 findEditTable(table), cancellationSignal);
1213 } finally {
1214 releaseReference();
1215 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001216 }
1217
1218 /**
1219 * Query the given table, returning a {@link Cursor} over the result set.
1220 *
1221 * @param table The table name to compile the query against.
1222 * @param columns A list of which columns to return. Passing null will
1223 * return all columns, which is discouraged to prevent reading
1224 * data from storage that isn't going to be used.
1225 * @param selection A filter declaring which rows to return, formatted as an
1226 * SQL WHERE clause (excluding the WHERE itself). Passing null
1227 * will return all rows for the given table.
1228 * @param selectionArgs You may include ?s in selection, which will be
1229 * replaced by the values from selectionArgs, in order that they
1230 * appear in the selection. The values will be bound as Strings.
1231 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1232 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1233 * will cause the rows to not be grouped.
1234 * @param having A filter declare which row groups to include in the cursor,
1235 * if row grouping is being used, formatted as an SQL HAVING
1236 * clause (excluding the HAVING itself). Passing null will cause
1237 * all row groups to be included, and is required when row
1238 * grouping is not being used.
1239 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1240 * (excluding the ORDER BY itself). Passing null will use the
1241 * default sort order, which may be unordered.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001242 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1243 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001244 * @see Cursor
1245 */
1246 public Cursor query(String table, String[] columns, String selection,
1247 String[] selectionArgs, String groupBy, String having,
1248 String orderBy) {
1249
1250 return query(false, table, columns, selection, selectionArgs, groupBy,
1251 having, orderBy, null /* limit */);
1252 }
1253
1254 /**
1255 * Query the given table, returning a {@link Cursor} over the result set.
1256 *
1257 * @param table The table name to compile the query against.
1258 * @param columns A list of which columns to return. Passing null will
1259 * return all columns, which is discouraged to prevent reading
1260 * data from storage that isn't going to be used.
1261 * @param selection A filter declaring which rows to return, formatted as an
1262 * SQL WHERE clause (excluding the WHERE itself). Passing null
1263 * will return all rows for the given table.
1264 * @param selectionArgs You may include ?s in selection, which will be
1265 * replaced by the values from selectionArgs, in order that they
1266 * appear in the selection. The values will be bound as Strings.
1267 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1268 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1269 * will cause the rows to not be grouped.
1270 * @param having A filter declare which row groups to include in the cursor,
1271 * if row grouping is being used, formatted as an SQL HAVING
1272 * clause (excluding the HAVING itself). Passing null will cause
1273 * all row groups to be included, and is required when row
1274 * grouping is not being used.
1275 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1276 * (excluding the ORDER BY itself). Passing null will use the
1277 * default sort order, which may be unordered.
1278 * @param limit Limits the number of rows returned by the query,
1279 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001280 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1281 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001282 * @see Cursor
1283 */
1284 public Cursor query(String table, String[] columns, String selection,
1285 String[] selectionArgs, String groupBy, String having,
1286 String orderBy, String limit) {
1287
1288 return query(false, table, columns, selection, selectionArgs, groupBy,
1289 having, orderBy, limit);
1290 }
1291
1292 /**
1293 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1294 *
1295 * @param sql the SQL query. The SQL string must not be ; terminated
1296 * @param selectionArgs You may include ?s in where clause in the query,
1297 * which will be replaced by the values from selectionArgs. The
1298 * values will be bound as Strings.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001299 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1300 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001301 */
1302 public Cursor rawQuery(String sql, String[] selectionArgs) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001303 return rawQueryWithFactory(null, sql, selectionArgs, null, null);
1304 }
1305
1306 /**
1307 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1308 *
1309 * @param sql the SQL query. The SQL string must not be ; terminated
1310 * @param selectionArgs You may include ?s in where clause in the query,
1311 * which will be replaced by the values from selectionArgs. The
1312 * values will be bound as Strings.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001313 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001314 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1315 * when the query is executed.
1316 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1317 * {@link Cursor}s are not synchronized, see the documentation for more details.
1318 */
1319 public Cursor rawQuery(String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001320 CancellationSignal cancellationSignal) {
1321 return rawQueryWithFactory(null, sql, selectionArgs, null, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001322 }
1323
1324 /**
1325 * Runs the provided SQL and returns a cursor over the result set.
1326 *
1327 * @param cursorFactory the cursor factory to use, or null for the default factory
1328 * @param sql the SQL query. The SQL string must not be ; terminated
1329 * @param selectionArgs You may include ?s in where clause in the query,
1330 * which will be replaced by the values from selectionArgs. The
1331 * values will be bound as Strings.
1332 * @param editTable the name of the first table, which is editable
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001333 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1334 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335 */
1336 public Cursor rawQueryWithFactory(
1337 CursorFactory cursorFactory, String sql, String[] selectionArgs,
1338 String editTable) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001339 return rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable, null);
1340 }
1341
1342 /**
1343 * Runs the provided SQL and returns a cursor over the result set.
1344 *
1345 * @param cursorFactory the cursor factory to use, or null for the default factory
1346 * @param sql the SQL query. The SQL string must not be ; terminated
1347 * @param selectionArgs You may include ?s in where clause in the query,
1348 * which will be replaced by the values from selectionArgs. The
1349 * values will be bound as Strings.
1350 * @param editTable the name of the first table, which is editable
Jeff Brown4c1241d2012-02-02 17:05:00 -08001351 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001352 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1353 * when the query is executed.
1354 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1355 * {@link Cursor}s are not synchronized, see the documentation for more details.
1356 */
1357 public Cursor rawQueryWithFactory(
1358 CursorFactory cursorFactory, String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001359 String editTable, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001360 acquireReference();
1361 try {
1362 SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
1363 cancellationSignal);
1364 return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
1365 selectionArgs);
1366 } finally {
1367 releaseReference();
1368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 }
1370
1371 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 * Convenience method for inserting a row into the database.
1373 *
1374 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001375 * @param nullColumnHack optional; may be <code>null</code>.
1376 * SQL doesn't allow inserting a completely empty row without
1377 * naming at least one column name. If your provided <code>values</code> is
1378 * empty, no column names are known and an empty row can't be inserted.
1379 * If not set to null, the <code>nullColumnHack</code> parameter
1380 * provides the name of nullable column name to explicitly insert a NULL into
1381 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 * @param values this map contains the initial column values for the
1383 * row. The keys should be the column names and the values the
1384 * column values
1385 * @return the row ID of the newly inserted row, or -1 if an error occurred
1386 */
1387 public long insert(String table, String nullColumnHack, ContentValues values) {
1388 try {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001389 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 } catch (SQLException e) {
1391 Log.e(TAG, "Error inserting " + values, e);
1392 return -1;
1393 }
1394 }
1395
1396 /**
1397 * Convenience method for inserting a row into the database.
1398 *
1399 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001400 * @param nullColumnHack optional; may be <code>null</code>.
1401 * SQL doesn't allow inserting a completely empty row without
1402 * naming at least one column name. If your provided <code>values</code> is
1403 * empty, no column names are known and an empty row can't be inserted.
1404 * If not set to null, the <code>nullColumnHack</code> parameter
1405 * provides the name of nullable column name to explicitly insert a NULL into
1406 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407 * @param values this map contains the initial column values for the
1408 * row. The keys should be the column names and the values the
1409 * column values
1410 * @throws SQLException
1411 * @return the row ID of the newly inserted row, or -1 if an error occurred
1412 */
1413 public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
1414 throws SQLException {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001415 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001416 }
1417
1418 /**
1419 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001420 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 *
1422 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001423 * @param nullColumnHack optional; may be <code>null</code>.
1424 * SQL doesn't allow inserting a completely empty row without
1425 * naming at least one column name. If your provided <code>initialValues</code> is
1426 * empty, no column names are known and an empty row can't be inserted.
1427 * If not set to null, the <code>nullColumnHack</code> parameter
1428 * provides the name of nullable column name to explicitly insert a NULL into
1429 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001431 * the row. The keys should be the column names and the values the column values.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432 * @return the row ID of the newly inserted row, or -1 if an error occurred
1433 */
1434 public long replace(String table, String nullColumnHack, ContentValues initialValues) {
1435 try {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001436 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001437 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438 } catch (SQLException e) {
1439 Log.e(TAG, "Error inserting " + initialValues, e);
1440 return -1;
1441 }
1442 }
1443
1444 /**
1445 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001446 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 *
1448 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001449 * @param nullColumnHack optional; may be <code>null</code>.
1450 * SQL doesn't allow inserting a completely empty row without
1451 * naming at least one column name. If your provided <code>initialValues</code> is
1452 * empty, no column names are known and an empty row can't be inserted.
1453 * If not set to null, the <code>nullColumnHack</code> parameter
1454 * provides the name of nullable column name to explicitly insert a NULL into
1455 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001457 * the row. The keys should be the column names and the values the column values.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 * @throws SQLException
1459 * @return the row ID of the newly inserted row, or -1 if an error occurred
1460 */
1461 public long replaceOrThrow(String table, String nullColumnHack,
1462 ContentValues initialValues) throws SQLException {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001463 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001464 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465 }
1466
1467 /**
1468 * General method for inserting a row into the database.
1469 *
1470 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001471 * @param nullColumnHack optional; may be <code>null</code>.
1472 * SQL doesn't allow inserting a completely empty row without
1473 * naming at least one column name. If your provided <code>initialValues</code> is
1474 * empty, no column names are known and an empty row can't be inserted.
1475 * If not set to null, the <code>nullColumnHack</code> parameter
1476 * provides the name of nullable column name to explicitly insert a NULL into
1477 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 * @param initialValues this map contains the initial column values for the
1479 * row. The keys should be the column names and the values the
1480 * column values
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001481 * @param conflictAlgorithm for insert conflict resolver
Steve Pomeroyc240b602013-03-14 00:42:10 -04001482 * @return the row ID of the newly inserted row OR <code>-1</code> if either the
1483 * input parameter <code>conflictAlgorithm</code> = {@link #CONFLICT_IGNORE}
1484 * or an error occurred.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 */
1486 public long insertWithOnConflict(String table, String nullColumnHack,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001487 ContentValues initialValues, int conflictAlgorithm) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001488 acquireReference();
1489 try {
1490 StringBuilder sql = new StringBuilder();
1491 sql.append("INSERT");
1492 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1493 sql.append(" INTO ");
1494 sql.append(table);
1495 sql.append('(');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496
Jeff Brown03bd3022012-03-06 13:48:56 -08001497 Object[] bindArgs = null;
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001498 int size = (initialValues != null && !initialValues.isEmpty())
Jeff Brown03bd3022012-03-06 13:48:56 -08001499 ? initialValues.size() : 0;
1500 if (size > 0) {
1501 bindArgs = new Object[size];
1502 int i = 0;
1503 for (String colName : initialValues.keySet()) {
1504 sql.append((i > 0) ? "," : "");
1505 sql.append(colName);
1506 bindArgs[i++] = initialValues.get(colName);
1507 }
1508 sql.append(')');
1509 sql.append(" VALUES (");
1510 for (i = 0; i < size; i++) {
1511 sql.append((i > 0) ? ",?" : "?");
1512 }
1513 } else {
1514 sql.append(nullColumnHack + ") VALUES (NULL");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 sql.append(')');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517
Jeff Brown03bd3022012-03-06 13:48:56 -08001518 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1519 try {
1520 return statement.executeInsert();
1521 } finally {
1522 statement.close();
1523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001525 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 }
1527 }
1528
1529 /**
1530 * Convenience method for deleting rows in the database.
1531 *
1532 * @param table the table to delete from
1533 * @param whereClause the optional WHERE clause to apply when deleting.
1534 * Passing null will delete all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001535 * @param whereArgs You may include ?s in the where clause, which
1536 * will be replaced by the values from whereArgs. The values
1537 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 * @return the number of rows affected if a whereClause is passed in, 0
1539 * otherwise. To remove all rows and get a count pass "1" as the
1540 * whereClause.
1541 */
1542 public int delete(String table, String whereClause, String[] whereArgs) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001543 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001544 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001545 SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table +
1546 (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
1547 try {
1548 return statement.executeUpdateDelete();
1549 } finally {
1550 statement.close();
1551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001553 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 }
1555 }
1556
1557 /**
1558 * Convenience method for updating rows in the database.
1559 *
1560 * @param table the table to update in
1561 * @param values a map from column names to new column values. null is a
1562 * valid value that will be translated to NULL.
1563 * @param whereClause the optional WHERE clause to apply when updating.
1564 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001565 * @param whereArgs You may include ?s in the where clause, which
1566 * will be replaced by the values from whereArgs. The values
1567 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 * @return the number of rows affected
1569 */
1570 public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001571 return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 /**
1575 * Convenience method for updating rows in the database.
1576 *
1577 * @param table the table to update in
1578 * @param values a map from column names to new column values. null is a
1579 * valid value that will be translated to NULL.
1580 * @param whereClause the optional WHERE clause to apply when updating.
1581 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001582 * @param whereArgs You may include ?s in the where clause, which
1583 * will be replaced by the values from whereArgs. The values
1584 * will be bound as Strings.
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001585 * @param conflictAlgorithm for update conflict resolver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 * @return the number of rows affected
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 */
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001588 public int updateWithOnConflict(String table, ContentValues values,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001589 String whereClause, String[] whereArgs, int conflictAlgorithm) {
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001590 if (values == null || values.isEmpty()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 throw new IllegalArgumentException("Empty values");
1592 }
1593
Jeff Brown03bd3022012-03-06 13:48:56 -08001594 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001596 StringBuilder sql = new StringBuilder(120);
1597 sql.append("UPDATE ");
1598 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1599 sql.append(table);
1600 sql.append(" SET ");
1601
1602 // move all bind args to one array
1603 int setValuesSize = values.size();
1604 int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
1605 Object[] bindArgs = new Object[bindArgsSize];
1606 int i = 0;
1607 for (String colName : values.keySet()) {
1608 sql.append((i > 0) ? "," : "");
1609 sql.append(colName);
1610 bindArgs[i++] = values.get(colName);
1611 sql.append("=?");
1612 }
1613 if (whereArgs != null) {
1614 for (i = setValuesSize; i < bindArgsSize; i++) {
1615 bindArgs[i] = whereArgs[i - setValuesSize];
1616 }
1617 }
1618 if (!TextUtils.isEmpty(whereClause)) {
1619 sql.append(" WHERE ");
1620 sql.append(whereClause);
1621 }
1622
1623 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1624 try {
1625 return statement.executeUpdateDelete();
1626 } finally {
1627 statement.close();
1628 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001630 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 }
1632 }
1633
1634 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001635 * Execute a single SQL statement that is NOT a SELECT
1636 * or any other SQL statement that returns data.
1637 * <p>
Vasu Norice38b982010-07-22 13:57:13 -07001638 * It has no means to return any data (such as the number of affected rows).
Vasu Noriccd95442010-05-28 17:04:16 -07001639 * Instead, you're encouraged to use {@link #insert(String, String, ContentValues)},
1640 * {@link #update(String, ContentValues, String, String[])}, et al, when possible.
1641 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001642 * <p>
1643 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1644 * automatically managed by this class. So, do not set journal_mode
1645 * using "PRAGMA journal_mode'<value>" statement if your app is using
1646 * {@link #enableWriteAheadLogging()}
1647 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 *
Vasu Noriccd95442010-05-28 17:04:16 -07001649 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1650 * not supported.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001651 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001653 public void execSQL(String sql) throws SQLException {
Vasu Nori16057fa2011-03-18 11:40:37 -07001654 executeSql(sql, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655 }
1656
1657 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001658 * Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE.
1659 * <p>
1660 * For INSERT statements, use any of the following instead.
1661 * <ul>
1662 * <li>{@link #insert(String, String, ContentValues)}</li>
1663 * <li>{@link #insertOrThrow(String, String, ContentValues)}</li>
1664 * <li>{@link #insertWithOnConflict(String, String, ContentValues, int)}</li>
1665 * </ul>
1666 * <p>
1667 * For UPDATE statements, use any of the following instead.
1668 * <ul>
1669 * <li>{@link #update(String, ContentValues, String, String[])}</li>
1670 * <li>{@link #updateWithOnConflict(String, ContentValues, String, String[], int)}</li>
1671 * </ul>
1672 * <p>
1673 * For DELETE statements, use any of the following instead.
1674 * <ul>
1675 * <li>{@link #delete(String, String, String[])}</li>
1676 * </ul>
1677 * <p>
1678 * For example, the following are good candidates for using this method:
1679 * <ul>
1680 * <li>ALTER TABLE</li>
1681 * <li>CREATE or DROP table / trigger / view / index / virtual table</li>
1682 * <li>REINDEX</li>
1683 * <li>RELEASE</li>
1684 * <li>SAVEPOINT</li>
1685 * <li>PRAGMA that returns no data</li>
1686 * </ul>
1687 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001688 * <p>
1689 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1690 * automatically managed by this class. So, do not set journal_mode
1691 * using "PRAGMA journal_mode'<value>" statement if your app is using
1692 * {@link #enableWriteAheadLogging()}
1693 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694 *
Vasu Noriccd95442010-05-28 17:04:16 -07001695 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1696 * not supported.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 * @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001698 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001700 public void execSQL(String sql, Object[] bindArgs) throws SQLException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 if (bindArgs == null) {
1702 throw new IllegalArgumentException("Empty bindArgs");
1703 }
Vasu Norib83cb7c2010-09-14 13:36:01 -07001704 executeSql(sql, bindArgs);
Vasu Norice38b982010-07-22 13:57:13 -07001705 }
1706
Vasu Nori54025902010-09-14 12:14:26 -07001707 private int executeSql(String sql, Object[] bindArgs) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001708 acquireReference();
1709 try {
1710 if (DatabaseUtils.getSqlStatementType(sql) == DatabaseUtils.STATEMENT_ATTACH) {
1711 boolean disableWal = false;
1712 synchronized (mLock) {
1713 if (!mHasAttachedDbsLocked) {
1714 mHasAttachedDbsLocked = true;
1715 disableWal = true;
Fyodor Kupolovfd9c4a52017-07-13 15:36:57 -07001716 mConnectionPoolLocked.disableIdleConnectionHandler();
Jeff Brown03bd3022012-03-06 13:48:56 -08001717 }
1718 }
1719 if (disableWal) {
1720 disableWriteAheadLogging();
Jeff Browne5360fb2011-10-31 17:48:13 -07001721 }
1722 }
Jeff Browne5360fb2011-10-31 17:48:13 -07001723
Jeff Brown03bd3022012-03-06 13:48:56 -08001724 SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs);
1725 try {
1726 return statement.executeUpdateDelete();
1727 } finally {
1728 statement.close();
1729 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001730 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001731 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001732 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 }
1734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735 /**
Makoto Onuki17aa1b72015-12-16 14:02:01 -08001736 * Verifies that a SQL SELECT statement is valid by compiling it.
1737 * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
1738 *
1739 * @param sql SQL to be validated
1740 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
1741 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1742 * when the query is executed.
1743 * @throws SQLiteException if {@code sql} is invalid
1744 */
1745 public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal) {
1746 getThreadSession().prepare(sql,
1747 getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null);
1748 }
1749
1750 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001751 * Returns true if the database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001752 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001753 * @return True if database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001754 */
1755 public boolean isReadOnly() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001756 synchronized (mLock) {
1757 return isReadOnlyLocked();
1758 }
1759 }
1760
1761 private boolean isReadOnlyLocked() {
1762 return (mConfigurationLocked.openFlags & OPEN_READ_MASK) == OPEN_READONLY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 }
1764
1765 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001766 * Returns true if the database is in-memory db.
1767 *
1768 * @return True if the database is in-memory.
1769 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 */
Jeff Browne5360fb2011-10-31 17:48:13 -07001771 public boolean isInMemoryDatabase() {
1772 synchronized (mLock) {
1773 return mConfigurationLocked.isInMemoryDb();
1774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001775 }
1776
Jeff Browne5360fb2011-10-31 17:48:13 -07001777 /**
1778 * Returns true if the database is currently open.
1779 *
1780 * @return True if the database is currently open (has not been closed).
1781 */
1782 public boolean isOpen() {
1783 synchronized (mLock) {
1784 return mConnectionPoolLocked != null;
1785 }
1786 }
1787
1788 /**
1789 * Returns true if the new version code is greater than the current database version.
1790 *
1791 * @param newVersion The new version code.
Mark Lu1e202082016-08-30 17:41:25 -07001792 * @return True if the new version code is greater than the current database version.
Jeff Browne5360fb2011-10-31 17:48:13 -07001793 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 public boolean needUpgrade(int newVersion) {
1795 return newVersion > getVersion();
1796 }
1797
1798 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001799 * Gets the path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001800 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001801 * @return The path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 */
1803 public final String getPath() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001804 synchronized (mLock) {
1805 return mConfigurationLocked.path;
Christopher Tatead9e8b12011-10-05 17:49:26 -07001806 }
Brad Fitzpatrick722802e2010-03-23 22:22:16 -07001807 }
1808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 /**
1810 * Sets the locale for this database. Does nothing if this database has
Jeff Brown1d9f7422012-03-15 14:32:32 -07001811 * the {@link #NO_LOCALIZED_COLLATORS} flag set or was opened read only.
Jeff Browne5360fb2011-10-31 17:48:13 -07001812 *
1813 * @param locale The new locale.
1814 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 * @throws SQLException if the locale could not be set. The most common reason
1816 * for this is that there is no collator available for the locale you requested.
1817 * In this case the database remains unchanged.
1818 */
1819 public void setLocale(Locale locale) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001820 if (locale == null) {
1821 throw new IllegalArgumentException("locale must not be null.");
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001822 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001823
Jeff Browne5360fb2011-10-31 17:48:13 -07001824 synchronized (mLock) {
1825 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001826
1827 final Locale oldLocale = mConfigurationLocked.locale;
Jeff Browne5360fb2011-10-31 17:48:13 -07001828 mConfigurationLocked.locale = locale;
Jeff Browne67ca422012-03-21 17:24:05 -07001829 try {
1830 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1831 } catch (RuntimeException ex) {
1832 mConfigurationLocked.locale = oldLocale;
1833 throw ex;
1834 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001835 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001836 }
1837
Vasu Norie495d1f2010-01-06 16:34:19 -08001838 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001839 * Sets the maximum size of the prepared-statement cache for this database.
Vasu Norie495d1f2010-01-06 16:34:19 -08001840 * (size of the cache = number of compiled-sql-statements stored in the cache).
Vasu Noriccd95442010-05-28 17:04:16 -07001841 *<p>
Vasu Norib729dcc2010-09-14 11:35:49 -07001842 * Maximum cache size can ONLY be increased from its current size (default = 10).
Vasu Noriccd95442010-05-28 17:04:16 -07001843 * If this method is called with smaller size than the current maximum value,
1844 * then IllegalStateException is thrown.
Vasu Norib729dcc2010-09-14 11:35:49 -07001845 *<p>
1846 * This method is thread-safe.
Vasu Norie495d1f2010-01-06 16:34:19 -08001847 *
Vasu Nori90a367262010-04-12 12:49:09 -07001848 * @param cacheSize the size of the cache. can be (0 to {@link #MAX_SQL_CACHE_SIZE})
Jeff Browne5360fb2011-10-31 17:48:13 -07001849 * @throws IllegalStateException if input cacheSize > {@link #MAX_SQL_CACHE_SIZE}.
Vasu Norie495d1f2010-01-06 16:34:19 -08001850 */
Vasu Nori54025902010-09-14 12:14:26 -07001851 public void setMaxSqlCacheSize(int cacheSize) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001852 if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) {
1853 throw new IllegalStateException(
1854 "expected value between 0 and " + MAX_SQL_CACHE_SIZE);
Vasu Nori587423a2010-09-27 18:18:34 -07001855 }
Vasu Nori587423a2010-09-27 18:18:34 -07001856
Jeff Browne5360fb2011-10-31 17:48:13 -07001857 synchronized (mLock) {
1858 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001859
1860 final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize;
Jeff Browne5360fb2011-10-31 17:48:13 -07001861 mConfigurationLocked.maxSqlCacheSize = cacheSize;
Jeff Browne67ca422012-03-21 17:24:05 -07001862 try {
1863 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1864 } catch (RuntimeException ex) {
1865 mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize;
1866 throw ex;
1867 }
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001868 }
1869 }
1870
Vasu Nori6c354da2010-04-26 23:33:39 -07001871 /**
Jeff Brown96496ad2012-03-23 14:38:06 -07001872 * Sets whether foreign key constraints are enabled for the database.
1873 * <p>
1874 * By default, foreign key constraints are not enforced by the database.
1875 * This method allows an application to enable foreign key constraints.
1876 * It must be called each time the database is opened to ensure that foreign
1877 * key constraints are enabled for the session.
1878 * </p><p>
1879 * A good time to call this method is right after calling {@link #openOrCreateDatabase}
1880 * or in the {@link SQLiteOpenHelper#onConfigure} callback.
1881 * </p><p>
1882 * When foreign key constraints are disabled, the database does not check whether
1883 * changes to the database will violate foreign key constraints. Likewise, when
1884 * foreign key constraints are disabled, the database will not execute cascade
1885 * delete or update triggers. As a result, it is possible for the database
1886 * state to become inconsistent. To perform a database integrity check,
1887 * call {@link #isDatabaseIntegrityOk}.
1888 * </p><p>
1889 * This method must not be called while a transaction is in progress.
1890 * </p><p>
1891 * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a>
1892 * for more details about foreign key constraint support.
1893 * </p>
1894 *
1895 * @param enable True to enable foreign key constraints, false to disable them.
1896 *
1897 * @throws IllegalStateException if the are transactions is in progress
1898 * when this method is called.
1899 */
1900 public void setForeignKeyConstraintsEnabled(boolean enable) {
1901 synchronized (mLock) {
1902 throwIfNotOpenLocked();
1903
1904 if (mConfigurationLocked.foreignKeyConstraintsEnabled == enable) {
1905 return;
1906 }
1907
1908 mConfigurationLocked.foreignKeyConstraintsEnabled = enable;
1909 try {
1910 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1911 } catch (RuntimeException ex) {
1912 mConfigurationLocked.foreignKeyConstraintsEnabled = !enable;
1913 throw ex;
1914 }
1915 }
1916 }
1917
1918 /**
Jeff Brown47847f32012-03-22 19:13:11 -07001919 * This method enables parallel execution of queries from multiple threads on the
1920 * same database. It does this by opening multiple connections to the database
1921 * and using a different database connection for each query. The database
1922 * journal mode is also changed to enable writes to proceed concurrently with reads.
Vasu Nori6c354da2010-04-26 23:33:39 -07001923 * <p>
Jeff Brown47847f32012-03-22 19:13:11 -07001924 * When write-ahead logging is not enabled (the default), it is not possible for
1925 * reads and writes to occur on the database at the same time. Before modifying the
1926 * database, the writer implicitly acquires an exclusive lock on the database which
1927 * prevents readers from accessing the database until the write is completed.
1928 * </p><p>
1929 * In contrast, when write-ahead logging is enabled (by calling this method), write
1930 * operations occur in a separate log file which allows reads to proceed concurrently.
1931 * While a write is in progress, readers on other threads will perceive the state
1932 * of the database as it was before the write began. When the write completes, readers
1933 * on other threads will then perceive the new state of the database.
1934 * </p><p>
1935 * It is a good idea to enable write-ahead logging whenever a database will be
1936 * concurrently accessed and modified by multiple threads at the same time.
1937 * However, write-ahead logging uses significantly more memory than ordinary
1938 * journaling because there are multiple connections to the same database.
1939 * So if a database will only be used by a single thread, or if optimizing
1940 * concurrency is not very important, then write-ahead logging should be disabled.
1941 * </p><p>
1942 * After calling this method, execution of queries in parallel is enabled as long as
1943 * the database remains open. To disable execution of queries in parallel, either
1944 * call {@link #disableWriteAheadLogging} or close the database and reopen it.
1945 * </p><p>
1946 * The maximum number of connections used to execute queries in parallel is
Vasu Nori6c354da2010-04-26 23:33:39 -07001947 * dependent upon the device memory and possibly other properties.
Jeff Brown47847f32012-03-22 19:13:11 -07001948 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07001949 * If a query is part of a transaction, then it is executed on the same database handle the
1950 * transaction was begun.
Jeff Brown47847f32012-03-22 19:13:11 -07001951 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07001952 * Writers should use {@link #beginTransactionNonExclusive()} or
1953 * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
Jeff Brown47847f32012-03-22 19:13:11 -07001954 * to start a transaction. Non-exclusive mode allows database file to be in readable
1955 * by other threads executing queries.
1956 * </p><p>
1957 * If the database has any attached databases, then execution of queries in parallel is NOT
1958 * possible. Likewise, write-ahead logging is not supported for read-only databases
1959 * or memory databases. In such cases, {@link #enableWriteAheadLogging} returns false.
1960 * </p><p>
1961 * The best way to enable write-ahead logging is to pass the
1962 * {@link #ENABLE_WRITE_AHEAD_LOGGING} flag to {@link #openDatabase}. This is
1963 * more efficient than calling {@link #enableWriteAheadLogging}.
1964 * <code><pre>
1965 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
1966 * SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
1967 * myDatabaseErrorHandler);
1968 * db.enableWriteAheadLogging();
1969 * </pre></code>
1970 * </p><p>
1971 * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging}
1972 * after opening the database.
1973 * <code><pre>
1974 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
1975 * SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
1976 * db.enableWriteAheadLogging();
1977 * </pre></code>
1978 * </p><p>
1979 * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for
1980 * more details about how write-ahead logging works.
Vasu Nori6c354da2010-04-26 23:33:39 -07001981 * </p>
1982 *
Jeff Brown47847f32012-03-22 19:13:11 -07001983 * @return True if write-ahead logging is enabled.
Jeff Browne67ca422012-03-21 17:24:05 -07001984 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07001985 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07001986 * time this method is called. WAL mode can only be changed when there are no
1987 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07001988 *
1989 * @see #ENABLE_WRITE_AHEAD_LOGGING
1990 * @see #disableWriteAheadLogging
Vasu Nori6c354da2010-04-26 23:33:39 -07001991 */
Vasu Noriffe06122010-09-27 12:32:57 -07001992 public boolean enableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001993 synchronized (mLock) {
1994 throwIfNotOpenLocked();
1995
Jeff Brown47847f32012-03-22 19:13:11 -07001996 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08001997 return true;
1998 }
Jeff Browne5360fb2011-10-31 17:48:13 -07001999
2000 if (isReadOnlyLocked()) {
2001 // WAL doesn't make sense for readonly-databases.
2002 // TODO: True, but connection pooling does still make sense...
2003 return false;
2004 }
2005
2006 if (mConfigurationLocked.isInMemoryDb()) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002007 Log.i(TAG, "can't enable WAL for memory databases.");
2008 return false;
2009 }
2010
2011 // make sure this database has NO attached databases because sqlite's write-ahead-logging
2012 // doesn't work for databases with attached databases
Jeff Browne5360fb2011-10-31 17:48:13 -07002013 if (mHasAttachedDbsLocked) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002014 if (Log.isLoggable(TAG, Log.DEBUG)) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002015 Log.d(TAG, "this database: " + mConfigurationLocked.label
2016 + " has attached databases. can't enable WAL.");
Paul Westbrookdae6d372011-02-17 10:59:56 -08002017 }
2018 return false;
2019 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002020
Jeff Brown47847f32012-03-22 19:13:11 -07002021 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002022 try {
2023 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2024 } catch (RuntimeException ex) {
Jeff Brown47847f32012-03-22 19:13:11 -07002025 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002026 throw ex;
2027 }
Paul Westbrookdae6d372011-02-17 10:59:56 -08002028 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002029 return true;
Vasu Nori6c354da2010-04-26 23:33:39 -07002030 }
2031
Vasu Nori2827d6d2010-07-04 00:26:18 -07002032 /**
Vasu Nori7b04c412010-07-20 10:31:21 -07002033 * This method disables the features enabled by {@link #enableWriteAheadLogging()}.
Jeff Browne67ca422012-03-21 17:24:05 -07002034 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002035 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002036 * time this method is called. WAL mode can only be changed when there are no
2037 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002038 *
2039 * @see #enableWriteAheadLogging
Vasu Nori2827d6d2010-07-04 00:26:18 -07002040 */
Vasu Nori7b04c412010-07-20 10:31:21 -07002041 public void disableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002042 synchronized (mLock) {
2043 throwIfNotOpenLocked();
2044
Jeff Brown47847f32012-03-22 19:13:11 -07002045 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002046 return;
Paul Westbrookdae6d372011-02-17 10:59:56 -08002047 }
Vasu Nori8d111032010-06-22 18:34:21 -07002048
Jeff Brown47847f32012-03-22 19:13:11 -07002049 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002050 try {
2051 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2052 } catch (RuntimeException ex) {
Jeff Brown47847f32012-03-22 19:13:11 -07002053 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002054 throw ex;
2055 }
Vasu Nori65a88832010-07-16 15:14:08 -07002056 }
Vasu Nori6c354da2010-04-26 23:33:39 -07002057 }
2058
Vasu Norif3cf8a42010-03-23 11:41:44 -07002059 /**
Jeff Brown47847f32012-03-22 19:13:11 -07002060 * Returns true if write-ahead logging has been enabled for this database.
2061 *
2062 * @return True if write-ahead logging has been enabled for this database.
2063 *
2064 * @see #enableWriteAheadLogging
2065 * @see #ENABLE_WRITE_AHEAD_LOGGING
2066 */
2067 public boolean isWriteAheadLoggingEnabled() {
2068 synchronized (mLock) {
2069 throwIfNotOpenLocked();
2070
2071 return (mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2072 }
2073 }
2074
2075 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002076 * Collect statistics about all open databases in the current process.
2077 * Used by bug report.
Vasu Norif3cf8a42010-03-23 11:41:44 -07002078 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002079 static ArrayList<DbStats> getDbStats() {
Vasu Noric3849202010-03-09 10:47:25 -08002080 ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002081 for (SQLiteDatabase db : getActiveDatabases()) {
2082 db.collectDbStats(dbStatsList);
Vasu Nori24675612010-09-27 14:54:19 -07002083 }
Vasu Noric3849202010-03-09 10:47:25 -08002084 return dbStatsList;
2085 }
2086
Jeff Browne5360fb2011-10-31 17:48:13 -07002087 private void collectDbStats(ArrayList<DbStats> dbStatsList) {
2088 synchronized (mLock) {
2089 if (mConnectionPoolLocked != null) {
2090 mConnectionPoolLocked.collectDbStats(dbStatsList);
2091 }
2092 }
2093 }
2094
2095 private static ArrayList<SQLiteDatabase> getActiveDatabases() {
2096 ArrayList<SQLiteDatabase> databases = new ArrayList<SQLiteDatabase>();
2097 synchronized (sActiveDatabases) {
2098 databases.addAll(sActiveDatabases.keySet());
2099 }
2100 return databases;
2101 }
2102
2103 /**
2104 * Dump detailed information about all open databases in the current process.
2105 * Used by bug report.
2106 */
Jeff Browna9be4152012-01-18 15:29:57 -08002107 static void dumpAll(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002108 for (SQLiteDatabase db : getActiveDatabases()) {
Jeff Browna9be4152012-01-18 15:29:57 -08002109 db.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002110 }
2111 }
2112
Jeff Browna9be4152012-01-18 15:29:57 -08002113 private void dump(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002114 synchronized (mLock) {
2115 if (mConnectionPoolLocked != null) {
2116 printer.println("");
Jeff Browna9be4152012-01-18 15:29:57 -08002117 mConnectionPoolLocked.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002118 }
2119 }
2120 }
2121
Vasu Noric3849202010-03-09 10:47:25 -08002122 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002123 * Returns list of full pathnames of all attached databases including the main database
2124 * by executing 'pragma database_list' on the database.
2125 *
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002126 * @return ArrayList of pairs of (database name, database file path) or null if the database
2127 * is not open.
Vasu Noric3849202010-03-09 10:47:25 -08002128 */
Vasu Noria017eda2011-01-27 10:52:55 -08002129 public List<Pair<String, String>> getAttachedDbs() {
Vasu Noric3849202010-03-09 10:47:25 -08002130 ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002131 synchronized (mLock) {
2132 if (mConnectionPoolLocked == null) {
2133 return null; // not open
2134 }
2135
2136 if (!mHasAttachedDbsLocked) {
2137 // No attached databases.
2138 // There is a small window where attached databases exist but this flag is not
2139 // set yet. This can occur when this thread is in a race condition with another
2140 // thread that is executing the SQL statement: "attach database <blah> as <foo>"
2141 // If this thread is NOT ok with such a race condition (and thus possibly not
2142 // receivethe entire list of attached databases), then the caller should ensure
2143 // that no thread is executing any SQL statements while a thread is calling this
2144 // method. Typically, this method is called when 'adb bugreport' is done or the
2145 // caller wants to collect stats on the database and all its attached databases.
2146 attachedDbs.add(new Pair<String, String>("main", mConfigurationLocked.path));
2147 return attachedDbs;
2148 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002149
2150 acquireReference();
Vasu Nori24675612010-09-27 14:54:19 -07002151 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002152
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002153 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002154 // has attached databases. query sqlite to get the list of attached databases.
2155 Cursor c = null;
2156 try {
2157 c = rawQuery("pragma database_list;", null);
2158 while (c.moveToNext()) {
2159 // sqlite returns a row for each database in the returned list of databases.
2160 // in each row,
2161 // 1st column is the database name such as main, or the database
2162 // name specified on the "ATTACH" command
2163 // 2nd column is the database file path.
2164 attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2)));
2165 }
2166 } finally {
2167 if (c != null) {
2168 c.close();
2169 }
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002170 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002171 return attachedDbs;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002172 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08002173 releaseReference();
Vasu Noric3849202010-03-09 10:47:25 -08002174 }
Vasu Noric3849202010-03-09 10:47:25 -08002175 }
2176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002178 * Runs 'pragma integrity_check' on the given database (and all the attached databases)
2179 * and returns true if the given database (and all its attached databases) pass integrity_check,
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002180 * false otherwise.
Vasu Noriccd95442010-05-28 17:04:16 -07002181 *<p>
2182 * If the result is false, then this method logs the errors reported by the integrity_check
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002183 * command execution.
Vasu Noriccd95442010-05-28 17:04:16 -07002184 *<p>
2185 * Note that 'pragma integrity_check' on a database can take a long time.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002186 *
2187 * @return true if the given database (and all its attached databases) pass integrity_check,
Vasu Noriccd95442010-05-28 17:04:16 -07002188 * false otherwise.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002189 */
2190 public boolean isDatabaseIntegrityOk() {
Jeff Brown03bd3022012-03-06 13:48:56 -08002191 acquireReference();
Vasu Noribfe1dc22010-08-25 16:29:02 -07002192 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002193 List<Pair<String, String>> attachedDbs = null;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002194 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002195 attachedDbs = getAttachedDbs();
2196 if (attachedDbs == null) {
2197 throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " +
2198 "be retrieved. probably because the database is closed");
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002199 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002200 } catch (SQLiteException e) {
2201 // can't get attachedDb list. do integrity check on the main database
2202 attachedDbs = new ArrayList<Pair<String, String>>();
2203 attachedDbs.add(new Pair<String, String>("main", getPath()));
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002204 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002205
2206 for (int i = 0; i < attachedDbs.size(); i++) {
2207 Pair<String, String> p = attachedDbs.get(i);
2208 SQLiteStatement prog = null;
2209 try {
2210 prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);");
2211 String rslt = prog.simpleQueryForString();
2212 if (!rslt.equalsIgnoreCase("ok")) {
2213 // integrity_checker failed on main or attached databases
2214 Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt);
2215 return false;
2216 }
2217 } finally {
2218 if (prog != null) prog.close();
2219 }
2220 }
2221 } finally {
2222 releaseReference();
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002223 }
Vasu Noribfe1dc22010-08-25 16:29:02 -07002224 return true;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002225 }
2226
Jeff Browne5360fb2011-10-31 17:48:13 -07002227 @Override
2228 public String toString() {
2229 return "SQLiteDatabase: " + getPath();
2230 }
2231
Jeff Browne5360fb2011-10-31 17:48:13 -07002232 private void throwIfNotOpenLocked() {
2233 if (mConnectionPoolLocked == null) {
2234 throw new IllegalStateException("The database '" + mConfigurationLocked.label
2235 + "' is not open.");
2236 }
2237 }
Vasu Nori3ef94e22010-02-05 14:49:04 -08002238
2239 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002240 * Used to allow returning sub-classes of {@link Cursor} when calling query.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002241 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002242 public interface CursorFactory {
2243 /**
2244 * See {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}.
2245 */
2246 public Cursor newCursor(SQLiteDatabase db,
2247 SQLiteCursorDriver masterQuery, String editTable,
2248 SQLiteQuery query);
2249 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250
2251 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002252 * A callback interface for a custom sqlite3 function.
2253 * This can be used to create a function that can be called from
2254 * sqlite3 database triggers.
2255 * @hide
Vasu Noric3849202010-03-09 10:47:25 -08002256 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002257 public interface CustomFunction {
2258 public void callback(String[] args);
2259 }
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002260
2261 /**
2262 * Wrapper for configuration parameters that are used for opening {@link SQLiteDatabase}
2263 */
2264 public static final class OpenParams {
2265 private final int mOpenFlags;
2266 private final CursorFactory mCursorFactory;
2267 private final DatabaseErrorHandler mErrorHandler;
2268 private final int mLookasideSlotSize;
2269 private final int mLookasideSlotCount;
2270
2271 private OpenParams(int openFlags, CursorFactory cursorFactory,
2272 DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount) {
2273 mOpenFlags = openFlags;
2274 mCursorFactory = cursorFactory;
2275 mErrorHandler = errorHandler;
2276 mLookasideSlotSize = lookasideSlotSize;
2277 mLookasideSlotCount = lookasideSlotCount;
2278 }
2279
2280 /**
2281 * Returns size in bytes of each lookaside slot or -1 if not set.
2282 *
2283 * @see Builder#setLookasideConfig(int, int)
2284 */
2285 @IntRange(from = -1)
2286 public int getLookasideSlotSize() {
2287 return mLookasideSlotSize;
2288 }
2289
2290 /**
2291 * Returns total number of lookaside memory slots per database connection or -1 if not
2292 * set.
2293 *
2294 * @see Builder#setLookasideConfig(int, int)
2295 */
2296 @IntRange(from = -1)
2297 public int getLookasideSlotCount() {
2298 return mLookasideSlotCount;
2299 }
2300
2301 /**
2302 * Returns flags to control database access mode
2303 *
2304 * @see Builder#setOpenFlags(int)
2305 */
2306 @DatabaseOpenFlags
2307 public int getOpenFlags() {
2308 return mOpenFlags;
2309 }
2310
2311 /**
2312 * Returns an optional factory class that is called to instantiate a cursor when query
2313 * is called
2314 *
2315 * @see Builder#setCursorFactory(CursorFactory)
2316 */
2317 @Nullable
2318 public CursorFactory getCursorFactory() {
2319 return mCursorFactory;
2320 }
2321
2322 /**
2323 * Returns handler for database corruption errors
2324 *
2325 * @see Builder#setErrorHandler(DatabaseErrorHandler)
2326 */
2327 @Nullable
2328 public DatabaseErrorHandler getErrorHandler() {
2329 return mErrorHandler;
2330 }
2331
2332 /**
2333 * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with
2334 * {@code this} parameters.
2335 * @hide
2336 */
2337 @NonNull
2338 public Builder toBuilder() {
2339 return new Builder(this);
2340 }
2341
2342 /**
2343 * Builder for {@link OpenParams}.
2344 */
2345 public static final class Builder {
2346 private int mLookasideSlotSize = -1;
2347 private int mLookasideSlotCount = -1;
2348 private int mOpenFlags;
2349 private CursorFactory mCursorFactory;
2350 private DatabaseErrorHandler mErrorHandler;
2351
2352 public Builder() {
2353 }
2354
2355 public Builder(OpenParams params) {
2356 mLookasideSlotSize = params.mLookasideSlotSize;
2357 mLookasideSlotCount = params.mLookasideSlotCount;
2358 mOpenFlags = params.mOpenFlags;
2359 mCursorFactory = params.mCursorFactory;
2360 mErrorHandler = params.mErrorHandler;
2361 }
2362
2363 /**
2364 * Configures
2365 * <a href="https://sqlite.org/malloc.html#lookaside">lookaside memory allocator</a>
2366 *
2367 * <p>SQLite default settings will be used, if this method isn't called.
2368 * Use {@code setLookasideConfig(0,0)} to disable lookaside
2369 *
Fyodor Kupolov05a0f0f2017-06-30 19:00:00 -07002370 * <p><strong>Note:</strong> Provided slotSize/slotCount configuration is just a
2371 * recommendation. The system may choose different values depending on a device, e.g.
2372 * lookaside allocations can be disabled on low-RAM devices
2373 *
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002374 * @param slotSize The size in bytes of each lookaside slot.
2375 * @param slotCount The total number of lookaside memory slots per database connection.
2376 */
2377 public Builder setLookasideConfig(@IntRange(from = 0) final int slotSize,
2378 @IntRange(from = 0) final int slotCount) {
2379 Preconditions.checkArgument(slotSize >= 0,
2380 "lookasideSlotCount cannot be negative");
2381 Preconditions.checkArgument(slotCount >= 0,
2382 "lookasideSlotSize cannot be negative");
2383 Preconditions.checkArgument(
2384 (slotSize > 0 && slotCount > 0) || (slotCount == 0 && slotSize == 0),
2385 "Invalid configuration: " + slotSize + ", " + slotCount);
2386
2387 mLookasideSlotSize = slotSize;
2388 mLookasideSlotCount = slotCount;
2389 return this;
2390 }
2391
2392 /**
2393 * Returns true if {@link #ENABLE_WRITE_AHEAD_LOGGING} flag is set
2394 * @hide
2395 */
2396 public boolean isWriteAheadLoggingEnabled() {
2397 return (mOpenFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2398 }
2399
2400 /**
2401 * Sets flags to control database access mode
2402 * @param openFlags The new flags to set
2403 * @see #OPEN_READWRITE
2404 * @see #OPEN_READONLY
2405 * @see #CREATE_IF_NECESSARY
2406 * @see #NO_LOCALIZED_COLLATORS
2407 * @see #ENABLE_WRITE_AHEAD_LOGGING
2408 * @return same builder instance for chaining multiple calls into a single statement
2409 */
2410 @NonNull
2411 public Builder setOpenFlags(@DatabaseOpenFlags int openFlags) {
2412 mOpenFlags = openFlags;
2413 return this;
2414 }
2415
2416 /**
2417 * Adds flags to control database access mode
2418 *
2419 * @param openFlags The new flags to add
2420 * @return same builder instance for chaining multiple calls into a single statement
2421 */
2422 @NonNull
2423 public Builder addOpenFlags(@DatabaseOpenFlags int openFlags) {
2424 mOpenFlags |= openFlags;
2425 return this;
2426 }
2427
2428 /**
2429 * Removes database access mode flags
2430 *
2431 * @param openFlags Flags to remove
2432 * @return same builder instance for chaining multiple calls into a single statement
2433 */
2434 @NonNull
2435 public Builder removeOpenFlags(@DatabaseOpenFlags int openFlags) {
2436 mOpenFlags &= ~openFlags;
2437 return this;
2438 }
2439
2440 /**
2441 * Sets {@link #ENABLE_WRITE_AHEAD_LOGGING} flag if {@code enabled} is {@code true},
2442 * unsets otherwise
2443 * @hide
2444 */
2445 public void setWriteAheadLoggingEnabled(boolean enabled) {
2446 if (enabled) {
2447 addOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2448 } else {
2449 removeOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2450 }
2451 }
2452
2453 /**
2454 * Set an optional factory class that is called to instantiate a cursor when query
2455 * is called.
2456 *
2457 * @param cursorFactory instance
2458 * @return same builder instance for chaining multiple calls into a single statement
2459 */
2460 @NonNull
2461 public Builder setCursorFactory(@Nullable CursorFactory cursorFactory) {
2462 mCursorFactory = cursorFactory;
2463 return this;
2464 }
2465
2466
2467 /**
2468 * Sets {@link DatabaseErrorHandler} object to handle db corruption errors
2469 */
2470 @NonNull
2471 public Builder setErrorHandler(@Nullable DatabaseErrorHandler errorHandler) {
2472 mErrorHandler = errorHandler;
2473 return this;
2474 }
2475
2476 /**
2477 * Creates an instance of {@link OpenParams} with the options that were previously set
2478 * on this builder
2479 */
2480 @NonNull
2481 public OpenParams build() {
2482 return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize,
2483 mLookasideSlotCount);
2484 }
2485 }
2486 }
2487
2488 /** @hide */
2489 @IntDef(flag = true, prefix = {"OPEN_", "CREATE_", "NO_", "ENABLE_"}, value = {
2490 OPEN_READWRITE,
2491 OPEN_READONLY,
2492 CREATE_IF_NECESSARY,
2493 NO_LOCALIZED_COLLATORS,
2494 ENABLE_WRITE_AHEAD_LOGGING
2495 })
2496 @Retention(RetentionPolicy.SOURCE)
2497 public @interface DatabaseOpenFlags {}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002498}