blob: c1c0812e129ebd2349d1b85d71c67a9cea54fdd4 [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;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070023import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.ContentValues;
25import android.database.Cursor;
Vasu Nori062fc7ce2010-03-31 16:13:05 -070026import android.database.DatabaseErrorHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.database.DatabaseUtils;
Vasu Nori062fc7ce2010-03-31 16:13:05 -070028import android.database.DefaultDatabaseErrorHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.database.SQLException;
Vasu Noric3849202010-03-09 10:47:25 -080030import android.database.sqlite.SQLiteDebug.DbStats;
Jeff Browna7771df2012-05-07 20:06:46 -070031import android.os.CancellationSignal;
Jeff Browne5360fb2011-10-31 17:48:13 -070032import android.os.Looper;
Jeff Browna7771df2012-05-07 20:06:46 -070033import android.os.OperationCanceledException;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070034import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.util.EventLog;
Dmitri Plotnikov90142c92009-09-15 10:52:17 -070037import android.util.Log;
Vasu Noric3849202010-03-09 10:47:25 -080038import android.util.Pair;
Jeff Browne5360fb2011-10-31 17:48:13 -070039import android.util.Printer;
40
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070041import com.android.internal.util.Preconditions;
42
Jeff Browne5360fb2011-10-31 17:48:13 -070043import dalvik.system.CloseGuard;
44
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import java.io.File;
Jeff Brown79087e42012-03-01 19:52:44 -080046import java.io.FileFilter;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070047import java.lang.annotation.Retention;
48import java.lang.annotation.RetentionPolicy;
Vasu Noric3849202010-03-09 10:47:25 -080049import java.util.ArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import java.util.HashMap;
Jesse Wilson9b5a9352011-02-10 11:19:09 -080051import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import java.util.Locale;
53import java.util.Map;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import java.util.WeakHashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055
56/**
57 * Exposes methods to manage a SQLite database.
Jeff Browne5360fb2011-10-31 17:48:13 -070058 *
59 * <p>
60 * SQLiteDatabase has methods to create, delete, execute SQL commands, and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 * perform other common database management tasks.
Jeff Browne5360fb2011-10-31 17:48:13 -070062 * </p><p>
63 * See the Notepad sample application in the SDK for an example of creating
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 * and managing a database.
Jeff Browne5360fb2011-10-31 17:48:13 -070065 * </p><p>
66 * Database names must be unique within an application, not across all applications.
67 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 *
69 * <h3>Localized Collation - ORDER BY</h3>
Jeff Browne5360fb2011-10-31 17:48:13 -070070 * <p>
71 * In addition to SQLite's default <code>BINARY</code> collator, Android supplies
72 * two more, <code>LOCALIZED</code>, which changes with the system's current locale,
73 * and <code>UNICODE</code>, which is the Unicode Collation Algorithm and not tailored
74 * to the current locale.
75 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 */
Jeff Brownbaefdfa2012-03-05 10:33:13 -080077public final class SQLiteDatabase extends SQLiteClosable {
Vasu Norifb16cbd2010-07-25 16:38:48 -070078 private static final String TAG = "SQLiteDatabase";
Jeff Browne5360fb2011-10-31 17:48:13 -070079
Jeff Hamilton082c2af2009-09-29 11:49:51 -070080 private static final int EVENT_DB_CORRUPT = 75004;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081
Fyodor Kupolov535672992017-08-30 18:16:31 -070082 // By default idle connections are not closed
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070083 private static final boolean DEBUG_CLOSE_IDLE_CONNECTIONS = SystemProperties
Fyodor Kupolov535672992017-08-30 18:16:31 -070084 .getBoolean("persist.debug.sqlite.close_idle_connections", false);
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070085
Jeff Browne5360fb2011-10-31 17:48:13 -070086 // Stores reference to all databases opened in the current process.
87 // (The referent Object is not used at this time.)
88 // INVARIANT: Guarded by sActiveDatabases.
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070089 private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases = new WeakHashMap<>();
Jeff Browne5360fb2011-10-31 17:48:13 -070090
91 // Thread-local for database sessions that belong to this database.
92 // Each thread has its own database session.
93 // INVARIANT: Immutable.
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070094 private final ThreadLocal<SQLiteSession> mThreadSession = ThreadLocal
95 .withInitial(this::createSession);
Jeff Browne5360fb2011-10-31 17:48:13 -070096
97 // The optional factory to use when creating new Cursors. May be null.
98 // INVARIANT: Immutable.
99 private final CursorFactory mCursorFactory;
100
101 // Error handler to be used when SQLite returns corruption errors.
102 // INVARIANT: Immutable.
103 private final DatabaseErrorHandler mErrorHandler;
104
105 // Shared database state lock.
106 // This lock guards all of the shared state of the database, such as its
107 // configuration, whether it is open or closed, and so on. This lock should
108 // be held for as little time as possible.
109 //
110 // The lock MUST NOT be held while attempting to acquire database connections or
111 // while executing SQL statements on behalf of the client as it can lead to deadlock.
112 //
113 // It is ok to hold the lock while reconfiguring the connection pool or dumping
114 // statistics because those operations are non-reentrant and do not try to acquire
115 // connections that might be held by other threads.
116 //
117 // Basic rule: grab the lock, access or modify global state, release the lock, then
118 // do the required SQL work.
119 private final Object mLock = new Object();
120
121 // Warns if the database is finalized without being closed properly.
122 // INVARIANT: Guarded by mLock.
123 private final CloseGuard mCloseGuardLocked = CloseGuard.get();
124
125 // The database configuration.
126 // INVARIANT: Guarded by mLock.
127 private final SQLiteDatabaseConfiguration mConfigurationLocked;
128
129 // The connection pool for the database, null when closed.
130 // The pool itself is thread-safe, but the reference to it can only be acquired
131 // when the lock is held.
132 // INVARIANT: Guarded by mLock.
133 private SQLiteConnectionPool mConnectionPoolLocked;
134
135 // True if the database has attached databases.
136 // INVARIANT: Guarded by mLock.
137 private boolean mHasAttachedDbsLocked;
138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700140 * When a constraint violation occurs, an immediate ROLLBACK occurs,
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800141 * thus ending the current transaction, and the command aborts with a
142 * return code of SQLITE_CONSTRAINT. If no transaction is active
143 * (other than the implied transaction that is created on every command)
Jeff Browne5360fb2011-10-31 17:48:13 -0700144 * then this algorithm works the same as ABORT.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800145 */
146 public static final int CONFLICT_ROLLBACK = 1;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700147
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800148 /**
149 * When a constraint violation occurs,no ROLLBACK is executed
150 * so changes from prior commands within the same transaction
151 * are preserved. This is the default behavior.
152 */
153 public static final int CONFLICT_ABORT = 2;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700154
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800155 /**
156 * When a constraint violation occurs, the command aborts with a return
157 * code SQLITE_CONSTRAINT. But any changes to the database that
158 * the command made prior to encountering the constraint violation
159 * are preserved and are not backed out.
160 */
161 public static final int CONFLICT_FAIL = 3;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700162
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800163 /**
164 * When a constraint violation occurs, the one row that contains
165 * the constraint violation is not inserted or changed.
166 * But the command continues executing normally. Other rows before and
167 * after the row that contained the constraint violation continue to be
168 * inserted or updated normally. No error is returned.
169 */
170 public static final int CONFLICT_IGNORE = 4;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700171
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800172 /**
173 * When a UNIQUE constraint violation occurs, the pre-existing rows that
174 * are causing the constraint violation are removed prior to inserting
175 * or updating the current row. Thus the insert or update always occurs.
176 * The command continues executing normally. No error is returned.
177 * If a NOT NULL constraint violation occurs, the NULL value is replaced
178 * by the default value for that column. If the column has no default
179 * value, then the ABORT algorithm is used. If a CHECK constraint
180 * violation occurs then the IGNORE algorithm is used. When this conflict
181 * resolution strategy deletes rows in order to satisfy a constraint,
182 * it does not invoke delete triggers on those rows.
Jeff Browne5360fb2011-10-31 17:48:13 -0700183 * This behavior might change in a future release.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800184 */
185 public static final int CONFLICT_REPLACE = 5;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700186
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800187 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700188 * Use the following when no conflict action is specified.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800189 */
190 public static final int CONFLICT_NONE = 0;
Jeff Browne5360fb2011-10-31 17:48:13 -0700191
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800192 private static final String[] CONFLICT_VALUES = new String[]
193 {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 /**
196 * Maximum Length Of A LIKE Or GLOB Pattern
197 * The pattern matching algorithm used in the default LIKE and GLOB implementation
198 * of SQLite can exhibit O(N^2) performance (where N is the number of characters in
199 * the pattern) for certain pathological cases. To avoid denial-of-service attacks
200 * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes.
201 * The default value of this limit is 50000. A modern workstation can evaluate
202 * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly.
203 * The denial of service problem only comes into play when the pattern length gets
204 * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns
205 * are at most a few dozen bytes in length, paranoid application developers may
206 * want to reduce this parameter to something in the range of a few hundred
207 * if they know that external users are able to generate arbitrary patterns.
208 */
209 public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000;
210
211 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700212 * Open flag: Flag for {@link #openDatabase} to open the database for reading and writing.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 * If the disk is full, this may fail even before you actually write anything.
214 *
215 * {@more} Note that the value of this flag is 0, so it is the default.
216 */
217 public static final int OPEN_READWRITE = 0x00000000; // update native code if changing
218
219 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700220 * Open flag: Flag for {@link #openDatabase} to open the database for reading only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 * This is the only reliable way to open a database if the disk may be full.
222 */
223 public static final int OPEN_READONLY = 0x00000001; // update native code if changing
224
225 private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing
226
227 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700228 * Open flag: Flag for {@link #openDatabase} to open the database without support for
229 * localized collators.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 *
231 * {@more} This causes the collator <code>LOCALIZED</code> not to be created.
232 * You must be consistent when using this flag to use the setting the database was
233 * created with. If this is set, {@link #setLocale} will do nothing.
234 */
235 public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing
236
237 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700238 * Open flag: Flag for {@link #openDatabase} to create the database file if it does not
239 * already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 */
241 public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing
242
243 /**
Jeff Brown47847f32012-03-22 19:13:11 -0700244 * Open flag: Flag for {@link #openDatabase} to open the database file with
245 * write-ahead logging enabled by default. Using this flag is more efficient
246 * than calling {@link #enableWriteAheadLogging}.
247 *
248 * Write-ahead logging cannot be used with read-only databases so the value of
249 * this flag is ignored if the database is opened read-only.
250 *
251 * @see #enableWriteAheadLogging
252 */
253 public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;
254
255 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700256 * Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}.
Vasu Norib729dcc2010-09-14 11:35:49 -0700257 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700258 * Each prepared-statement is between 1K - 6K, depending on the complexity of the
259 * SQL statement & schema. A large SQL cache may use a significant amount of memory.
Vasu Norie495d1f2010-01-06 16:34:19 -0800260 */
Vasu Nori90a367262010-04-12 12:49:09 -0700261 public static final int MAX_SQL_CACHE_SIZE = 100;
Vasu Norib729dcc2010-09-14 11:35:49 -0700262
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700263 private SQLiteDatabase(final String path, final int openFlags,
264 CursorFactory cursorFactory, DatabaseErrorHandler errorHandler,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800265 int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs,
266 String journalMode, String syncMode) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700267 mCursorFactory = cursorFactory;
268 mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler();
269 mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700270 mConfigurationLocked.lookasideSlotSize = lookasideSlotSize;
271 mConfigurationLocked.lookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700272 // Disable lookaside allocator on low-RAM devices
273 if (ActivityManager.isLowRamDeviceStatic()) {
274 mConfigurationLocked.lookasideSlotCount = 0;
275 mConfigurationLocked.lookasideSlotSize = 0;
276 }
277 long effectiveTimeoutMs = Long.MAX_VALUE;
278 // Never close idle connections for in-memory databases
279 if (!mConfigurationLocked.isInMemoryDb()) {
280 // First, check app-specific value. Otherwise use defaults
281 // -1 in idleConnectionTimeoutMs indicates unset value
282 if (idleConnectionTimeoutMs >= 0) {
283 effectiveTimeoutMs = idleConnectionTimeoutMs;
284 } else if (DEBUG_CLOSE_IDLE_CONNECTIONS) {
285 effectiveTimeoutMs = SQLiteGlobal.getIdleConnectionTimeout();
286 }
287 }
288 mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800289 mConfigurationLocked.journalMode = journalMode;
290 mConfigurationLocked.syncMode = syncMode;
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -0700291 mConfigurationLocked.useCompatibilityWal = SQLiteGlobal.isCompatibilityWalSupported();
Fyodor Kupolovee90c032017-12-12 11:52:57 -0800292 if (!mConfigurationLocked.isInMemoryDb() && SQLiteCompatibilityWalFlags.areFlagsSet()) {
293 mConfigurationLocked.useCompatibilityWal = SQLiteCompatibilityWalFlags
294 .isCompatibilityWalSupported();
295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700297
Jeff Browne5360fb2011-10-31 17:48:13 -0700298 @Override
299 protected void finalize() throws Throwable {
300 try {
301 dispose(true);
302 } finally {
303 super.finalize();
304 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700305 }
306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 @Override
308 protected void onAllReferencesReleased() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700309 dispose(false);
310 }
311
312 private void dispose(boolean finalized) {
313 final SQLiteConnectionPool pool;
314 synchronized (mLock) {
315 if (mCloseGuardLocked != null) {
316 if (finalized) {
317 mCloseGuardLocked.warnIfOpen();
318 }
319 mCloseGuardLocked.close();
320 }
321
322 pool = mConnectionPoolLocked;
323 mConnectionPoolLocked = null;
324 }
325
326 if (!finalized) {
327 synchronized (sActiveDatabases) {
328 sActiveDatabases.remove(this);
329 }
330
331 if (pool != null) {
332 pool.close();
333 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 }
335 }
336
337 /**
338 * Attempts to release memory that SQLite holds but does not require to
339 * operate properly. Typically this memory will come from the page cache.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700340 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 * @return the number of bytes actually released
342 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700343 public static int releaseMemory() {
344 return SQLiteGlobal.releaseMemory();
345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346
347 /**
348 * Control whether or not the SQLiteDatabase is made thread-safe by using locks
349 * around critical sections. This is pretty expensive, so if you know that your
350 * DB will only be used by a single thread then you should set this to false.
351 * The default is true.
352 * @param lockingEnabled set to true to enable locks, false otherwise
Jeff Browne5360fb2011-10-31 17:48:13 -0700353 *
354 * @deprecated This method now does nothing. Do not use.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700356 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357 public void setLockingEnabled(boolean lockingEnabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 }
359
360 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700361 * Gets a label to use when describing the database in log messages.
362 * @return The label.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700364 String getLabel() {
365 synchronized (mLock) {
366 return mConfigurationLocked.label;
367 }
368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369
Jeff Browne5360fb2011-10-31 17:48:13 -0700370 /**
371 * Sends a corruption message to the database error handler.
372 */
373 void onCorruption() {
374 EventLog.writeEvent(EVENT_DB_CORRUPT, getLabel());
Vasu Noriccd95442010-05-28 17:04:16 -0700375 mErrorHandler.onCorruption(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 }
377
378 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700379 * Gets the {@link SQLiteSession} that belongs to this thread for this database.
380 * Once a thread has obtained a session, it will continue to obtain the same
381 * session even after the database has been closed (although the session will not
382 * be usable). However, a thread that does not already have a session cannot
383 * obtain one after the database has been closed.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700384 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700385 * The idea is that threads that have active connections to the database may still
386 * have work to complete even after the call to {@link #close}. Active database
387 * connections are not actually disposed until they are released by the threads
388 * that own them.
389 *
390 * @return The session, never null.
391 *
392 * @throws IllegalStateException if the thread does not yet have a session and
393 * the database is not open.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700395 SQLiteSession getThreadSession() {
396 return mThreadSession.get(); // initialValue() throws if database closed
Vasu Nori6d970252010-10-05 10:48:49 -0700397 }
Vasu Nori16057fa2011-03-18 11:40:37 -0700398
Jeff Browne5360fb2011-10-31 17:48:13 -0700399 SQLiteSession createSession() {
400 final SQLiteConnectionPool pool;
401 synchronized (mLock) {
402 throwIfNotOpenLocked();
403 pool = mConnectionPoolLocked;
Vasu Nori6d970252010-10-05 10:48:49 -0700404 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700405 return new SQLiteSession(pool);
Vasu Norid4608a32011-02-03 16:24:06 -0800406 }
407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700409 * Gets default connection flags that are appropriate for this thread, taking into
410 * account whether the thread is acting on behalf of the UI.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800411 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700412 * @param readOnly True if the connection should be read-only.
413 * @return The connection flags.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700415 int getThreadDefaultConnectionFlags(boolean readOnly) {
416 int flags = readOnly ? SQLiteConnectionPool.CONNECTION_FLAG_READ_ONLY :
417 SQLiteConnectionPool.CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY;
418 if (isMainThread()) {
419 flags |= SQLiteConnectionPool.CONNECTION_FLAG_INTERACTIVE;
420 }
421 return flags;
Vasu Nori16057fa2011-03-18 11:40:37 -0700422 }
423
Jeff Browne5360fb2011-10-31 17:48:13 -0700424 private static boolean isMainThread() {
425 // FIXME: There should be a better way to do this.
426 // Would also be nice to have something that would work across Binder calls.
427 Looper looper = Looper.myLooper();
428 return looper != null && looper == Looper.getMainLooper();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 }
430
431 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700432 * Begins a transaction in EXCLUSIVE mode.
433 * <p>
434 * Transactions can be nested.
435 * When the outer transaction is ended all of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 * the work done in that transaction and all of the nested transactions will be committed or
437 * rolled back. The changes will be rolled back if any transaction is ended without being
438 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700439 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 * <p>Here is the standard idiom for transactions:
441 *
442 * <pre>
443 * db.beginTransaction();
444 * try {
445 * ...
446 * db.setTransactionSuccessful();
447 * } finally {
448 * db.endTransaction();
449 * }
450 * </pre>
451 */
452 public void beginTransaction() {
Vasu Nori6c354da2010-04-26 23:33:39 -0700453 beginTransaction(null /* transactionStatusCallback */, true);
454 }
455
456 /**
457 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
458 * the outer transaction is ended all of the work done in that transaction
459 * and all of the nested transactions will be committed or rolled back. The
460 * changes will be rolled back if any transaction is ended without being
461 * marked as clean (by calling setTransactionSuccessful). Otherwise they
462 * will be committed.
463 * <p>
464 * Here is the standard idiom for transactions:
465 *
466 * <pre>
467 * db.beginTransactionNonExclusive();
468 * try {
469 * ...
470 * db.setTransactionSuccessful();
471 * } finally {
472 * db.endTransaction();
473 * }
474 * </pre>
475 */
476 public void beginTransactionNonExclusive() {
477 beginTransaction(null /* transactionStatusCallback */, false);
Fred Quintanac4516a72009-09-03 12:14:06 -0700478 }
479
480 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700481 * Begins a transaction in EXCLUSIVE mode.
482 * <p>
483 * Transactions can be nested.
484 * When the outer transaction is ended all of
Fred Quintanac4516a72009-09-03 12:14:06 -0700485 * the work done in that transaction and all of the nested transactions will be committed or
486 * rolled back. The changes will be rolled back if any transaction is ended without being
487 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700488 * </p>
Fred Quintanac4516a72009-09-03 12:14:06 -0700489 * <p>Here is the standard idiom for transactions:
490 *
491 * <pre>
492 * db.beginTransactionWithListener(listener);
493 * try {
494 * ...
495 * db.setTransactionSuccessful();
496 * } finally {
497 * db.endTransaction();
498 * }
499 * </pre>
Vasu Noriccd95442010-05-28 17:04:16 -0700500 *
Fred Quintanac4516a72009-09-03 12:14:06 -0700501 * @param transactionListener listener that should be notified when the transaction begins,
502 * commits, or is rolled back, either explicitly or by a call to
503 * {@link #yieldIfContendedSafely}.
504 */
505 public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
Vasu Nori6c354da2010-04-26 23:33:39 -0700506 beginTransaction(transactionListener, true);
507 }
508
509 /**
510 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
511 * the outer transaction is ended all of the work done in that transaction
512 * and all of the nested transactions will be committed or rolled back. The
513 * changes will be rolled back if any transaction is ended without being
514 * marked as clean (by calling setTransactionSuccessful). Otherwise they
515 * will be committed.
516 * <p>
517 * Here is the standard idiom for transactions:
518 *
519 * <pre>
520 * db.beginTransactionWithListenerNonExclusive(listener);
521 * try {
522 * ...
523 * db.setTransactionSuccessful();
524 * } finally {
525 * db.endTransaction();
526 * }
527 * </pre>
528 *
529 * @param transactionListener listener that should be notified when the
530 * transaction begins, commits, or is rolled back, either
531 * explicitly or by a call to {@link #yieldIfContendedSafely}.
532 */
533 public void beginTransactionWithListenerNonExclusive(
534 SQLiteTransactionListener transactionListener) {
535 beginTransaction(transactionListener, false);
536 }
537
538 private void beginTransaction(SQLiteTransactionListener transactionListener,
539 boolean exclusive) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800540 acquireReference();
541 try {
542 getThreadSession().beginTransaction(
543 exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
544 SQLiteSession.TRANSACTION_MODE_IMMEDIATE,
545 transactionListener,
546 getThreadDefaultConnectionFlags(false /*readOnly*/), null);
547 } finally {
548 releaseReference();
549 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 }
551
552 /**
553 * End a transaction. See beginTransaction for notes about how to use this and when transactions
554 * are committed and rolled back.
555 */
556 public void endTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800557 acquireReference();
558 try {
559 getThreadSession().endTransaction(null);
560 } finally {
561 releaseReference();
562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563 }
564
565 /**
566 * Marks the current transaction as successful. Do not do any more database work between
567 * calling this and calling endTransaction. Do as little non-database work as possible in that
568 * situation too. If any errors are encountered between this and endTransaction the transaction
569 * will still be committed.
570 *
571 * @throws IllegalStateException if the current thread is not in a transaction or the
572 * transaction is already marked as successful.
573 */
574 public void setTransactionSuccessful() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800575 acquireReference();
576 try {
577 getThreadSession().setTransactionSuccessful();
578 } finally {
579 releaseReference();
580 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 }
582
583 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700584 * Returns true if the current thread has a transaction pending.
585 *
586 * @return True if the current thread is in a transaction.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 */
588 public boolean inTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800589 acquireReference();
590 try {
591 return getThreadSession().hasTransaction();
592 } finally {
593 releaseReference();
594 }
Vasu Norice38b982010-07-22 13:57:13 -0700595 }
596
597 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700598 * Returns true if the current thread is holding an active connection to the database.
Vasu Norice38b982010-07-22 13:57:13 -0700599 * <p>
Jeff Browne5360fb2011-10-31 17:48:13 -0700600 * The name of this method comes from a time when having an active connection
601 * to the database meant that the thread was holding an actual lock on the
602 * database. Nowadays, there is no longer a true "database lock" although threads
603 * may block if they cannot acquire a database connection to perform a
604 * particular operation.
605 * </p>
Vasu Norice38b982010-07-22 13:57:13 -0700606 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700607 * @return True if the current thread is holding an active connection to the database.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 */
609 public boolean isDbLockedByCurrentThread() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800610 acquireReference();
611 try {
612 return getThreadSession().hasConnection();
613 } finally {
614 releaseReference();
615 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 }
617
618 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700619 * Always returns false.
620 * <p>
621 * There is no longer the concept of a database lock, so this method always returns false.
622 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700624 * @return False.
625 * @deprecated Always returns false. Do not use this method.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700627 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628 public boolean isDbLockedByOtherThreads() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700629 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630 }
631
632 /**
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.
636 * @return true if the transaction was yielded
637 * @deprecated if the db is locked more than once (becuase of nested transactions) then the lock
638 * will not be yielded. Use yieldIfContendedSafely instead.
639 */
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700640 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800641 public boolean yieldIfContended() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700642 return yieldIfContendedHelper(false /* do not check yielding */,
643 -1 /* sleepAfterYieldDelay */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644 }
645
646 /**
647 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
648 * successful so far. Do not call setTransactionSuccessful before calling this. When this
649 * returns a new transaction will have been created but not marked as successful. This assumes
650 * that there are no nested transactions (beginTransaction has only been called once) and will
Fred Quintana5c7aede2009-08-27 21:41:27 -0700651 * throw an exception if that is not the case.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652 * @return true if the transaction was yielded
653 */
654 public boolean yieldIfContendedSafely() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700655 return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800656 }
657
Fred Quintana5c7aede2009-08-27 21:41:27 -0700658 /**
659 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
660 * successful so far. Do not call setTransactionSuccessful before calling this. When this
661 * returns a new transaction will have been created but not marked as successful. This assumes
662 * that there are no nested transactions (beginTransaction has only been called once) and will
663 * throw an exception if that is not the case.
664 * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if
665 * the lock was actually yielded. This will allow other background threads to make some
666 * more progress than they would if we started the transaction immediately.
667 * @return true if the transaction was yielded
668 */
669 public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
670 return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay);
671 }
672
Jeff Browne5360fb2011-10-31 17:48:13 -0700673 private boolean yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800674 acquireReference();
675 try {
676 return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null);
677 } finally {
678 releaseReference();
679 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680 }
681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700683 * Deprecated.
Vasu Nori95675132010-07-21 16:24:40 -0700684 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685 */
Vasu Nori95675132010-07-21 16:24:40 -0700686 @Deprecated
687 public Map<String, String> getSyncedTables() {
688 return new HashMap<String, String>(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 }
690
691 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692 * Open the database according to the flags {@link #OPEN_READWRITE}
693 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
694 *
695 * <p>Sets the locale of the database to the the system's current locale.
696 * Call {@link #setLocale} if you would like something else.</p>
697 *
698 * @param path to database file to open and/or create
699 * @param factory an optional factory class that is called to instantiate a
700 * cursor when query is called, or null for default
701 * @param flags to control database access mode
702 * @return the newly opened database
703 * @throws SQLiteException if the database cannot be opened
704 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700705 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
706 @DatabaseOpenFlags int flags) {
Jeff Brown47847f32012-03-22 19:13:11 -0700707 return openDatabase(path, factory, flags, null);
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700708 }
709
710 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700711 * Open the database according to the specified {@link OpenParams parameters}
712 *
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700713 * @param path path to database file to open and/or create.
714 * <p><strong>Important:</strong> The file should be constructed either from an absolute path or
715 * by using {@link android.content.Context#getDatabasePath(String)}.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700716 * @param openParams configuration parameters that are used for opening {@link SQLiteDatabase}
717 * @return the newly opened database
718 * @throws SQLiteException if the database cannot be opened
719 */
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700720 public static SQLiteDatabase openDatabase(@NonNull File path,
721 @NonNull OpenParams openParams) {
722 return openDatabase(path.getPath(), openParams);
723 }
724
725 private static SQLiteDatabase openDatabase(@NonNull String path,
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700726 @NonNull OpenParams openParams) {
727 Preconditions.checkArgument(openParams != null, "OpenParams cannot be null");
728 SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags,
729 openParams.mCursorFactory, openParams.mErrorHandler,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700730 openParams.mLookasideSlotSize, openParams.mLookasideSlotCount,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800731 openParams.mIdleConnectionTimeout, openParams.mJournalMode, openParams.mSyncMode);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700732 db.open();
733 return db;
734 }
735
736 /**
Vasu Nori74f170f2010-06-01 18:06:18 -0700737 * Open the database according to the flags {@link #OPEN_READWRITE}
738 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
739 *
740 * <p>Sets the locale of the database to the the system's current locale.
741 * Call {@link #setLocale} if you would like something else.</p>
742 *
743 * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be
744 * used to handle corruption when sqlite reports database corruption.</p>
745 *
746 * @param path to database file to open and/or create
747 * @param factory an optional factory class that is called to instantiate a
748 * cursor when query is called, or null for default
749 * @param flags to control database access mode
750 * @param errorHandler the {@link DatabaseErrorHandler} obj to be used to handle corruption
751 * when sqlite reports database corruption
752 * @return the newly opened database
753 * @throws SQLiteException if the database cannot be opened
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700754 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700755 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
756 @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler) {
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800757 SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1, -1, null,
758 null);
Jeff Browne5360fb2011-10-31 17:48:13 -0700759 db.open();
760 return db;
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700761 }
762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 /**
764 * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
765 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700766 public static SQLiteDatabase openOrCreateDatabase(@NonNull File file,
767 @Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768 return openOrCreateDatabase(file.getPath(), factory);
769 }
770
771 /**
772 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
773 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700774 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
775 @Nullable CursorFactory factory) {
Jeff Brown47847f32012-03-22 19:13:11 -0700776 return openDatabase(path, factory, CREATE_IF_NECESSARY, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 }
778
779 /**
Vasu Nori6c354da2010-04-26 23:33:39 -0700780 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler).
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700781 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700782 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
783 @Nullable CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler) {
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700784 return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler);
785 }
786
Jeff Brown559d0642012-02-29 10:19:12 -0800787 /**
Jeff Brown79087e42012-03-01 19:52:44 -0800788 * Deletes a database including its journal file and other auxiliary files
789 * that may have been created by the database engine.
790 *
791 * @param file The database file path.
792 * @return True if the database was successfully deleted.
793 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700794 public static boolean deleteDatabase(@NonNull File file) {
Jeff Brown79087e42012-03-01 19:52:44 -0800795 if (file == null) {
796 throw new IllegalArgumentException("file must not be null");
797 }
798
799 boolean deleted = false;
800 deleted |= file.delete();
801 deleted |= new File(file.getPath() + "-journal").delete();
802 deleted |= new File(file.getPath() + "-shm").delete();
803 deleted |= new File(file.getPath() + "-wal").delete();
804
805 File dir = file.getParentFile();
806 if (dir != null) {
807 final String prefix = file.getName() + "-mj";
Jeff Brownfce58902014-01-24 13:20:57 -0800808 File[] files = dir.listFiles(new FileFilter() {
Jeff Brown79087e42012-03-01 19:52:44 -0800809 @Override
810 public boolean accept(File candidate) {
811 return candidate.getName().startsWith(prefix);
812 }
Jeff Brownfce58902014-01-24 13:20:57 -0800813 });
814 if (files != null) {
815 for (File masterJournal : files) {
816 deleted |= masterJournal.delete();
817 }
Jeff Brown79087e42012-03-01 19:52:44 -0800818 }
819 }
820 return deleted;
821 }
822
823 /**
Jeff Brown559d0642012-02-29 10:19:12 -0800824 * Reopens the database in read-write mode.
825 * If the database is already read-write, does nothing.
826 *
827 * @throws SQLiteException if the database could not be reopened as requested, in which
828 * case it remains open in read only mode.
829 * @throws IllegalStateException if the database is not open.
830 *
831 * @see #isReadOnly()
832 * @hide
833 */
834 public void reopenReadWrite() {
835 synchronized (mLock) {
836 throwIfNotOpenLocked();
837
838 if (!isReadOnlyLocked()) {
839 return; // nothing to do
840 }
841
842 // Reopen the database in read-write mode.
843 final int oldOpenFlags = mConfigurationLocked.openFlags;
844 mConfigurationLocked.openFlags = (mConfigurationLocked.openFlags & ~OPEN_READ_MASK)
845 | OPEN_READWRITE;
846 try {
847 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
848 } catch (RuntimeException ex) {
849 mConfigurationLocked.openFlags = oldOpenFlags;
850 throw ex;
851 }
852 }
853 }
854
Jeff Browne5360fb2011-10-31 17:48:13 -0700855 private void open() {
856 try {
857 try {
858 openInner();
859 } catch (SQLiteDatabaseCorruptException ex) {
860 onCorruption();
861 openInner();
862 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700863 } catch (SQLiteException ex) {
864 Log.e(TAG, "Failed to open database '" + getLabel() + "'.", ex);
865 close();
866 throw ex;
867 }
868 }
869
870 private void openInner() {
871 synchronized (mLock) {
872 assert mConnectionPoolLocked == null;
873 mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked);
874 mCloseGuardLocked.open("close");
875 }
876
877 synchronized (sActiveDatabases) {
878 sActiveDatabases.put(this, null);
879 }
880 }
881
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700882 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 * Create a memory backed SQLite database. Its contents will be destroyed
884 * when the database is closed.
885 *
886 * <p>Sets the locale of the database to the the system's current locale.
887 * Call {@link #setLocale} if you would like something else.</p>
888 *
889 * @param factory an optional factory class that is called to instantiate a
890 * cursor when query is called
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700891 * @return a SQLiteDatabase instance
892 * @throws SQLiteException if the database cannot be created
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700894 @NonNull
895 public static SQLiteDatabase create(@Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800896 // This is a magic string with special meaning for SQLite.
Jeff Browne5360fb2011-10-31 17:48:13 -0700897 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
898 factory, CREATE_IF_NECESSARY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899 }
900
901 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700902 * Create a memory backed SQLite database. Its contents will be destroyed
903 * when the database is closed.
904 *
905 * <p>Sets the locale of the database to the the system's current locale.
906 * Call {@link #setLocale} if you would like something else.</p>
907 * @param openParams configuration parameters that are used for opening SQLiteDatabase
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700908 * @return a SQLiteDatabase instance
909 * @throws SQLException if the database cannot be created
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700910 */
911 @NonNull
912 public static SQLiteDatabase createInMemory(@NonNull OpenParams openParams) {
913 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
914 openParams.toBuilder().addOpenFlags(CREATE_IF_NECESSARY).build());
915 }
916
917 /**
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400918 * Registers a CustomFunction callback as a function that can be called from
Jeff Browne5360fb2011-10-31 17:48:13 -0700919 * SQLite database triggers.
920 *
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400921 * @param name the name of the sqlite3 function
922 * @param numArgs the number of arguments for the function
923 * @param function callback to call when the function is executed
924 * @hide
925 */
926 public void addCustomFunction(String name, int numArgs, CustomFunction function) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700927 // Create wrapper (also validates arguments).
928 SQLiteCustomFunction wrapper = new SQLiteCustomFunction(name, numArgs, function);
929
930 synchronized (mLock) {
931 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -0700932
Jeff Browne5360fb2011-10-31 17:48:13 -0700933 mConfigurationLocked.customFunctions.add(wrapper);
Jeff Browne67ca422012-03-21 17:24:05 -0700934 try {
935 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
936 } catch (RuntimeException ex) {
937 mConfigurationLocked.customFunctions.remove(wrapper);
938 throw ex;
939 }
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400940 }
941 }
942
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400943 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 * Gets the database version.
945 *
946 * @return the database version
947 */
948 public int getVersion() {
Vasu Noriccd95442010-05-28 17:04:16 -0700949 return ((Long) DatabaseUtils.longForQuery(this, "PRAGMA user_version;", null)).intValue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 }
951
952 /**
953 * Sets the database version.
954 *
955 * @param version the new database version
956 */
957 public void setVersion(int version) {
958 execSQL("PRAGMA user_version = " + version);
959 }
960
961 /**
962 * Returns the maximum size the database may grow to.
963 *
964 * @return the new maximum database size
965 */
966 public long getMaximumSize() {
Vasu Noriccd95442010-05-28 17:04:16 -0700967 long pageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count;", null);
968 return pageCount * getPageSize();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800969 }
970
971 /**
972 * Sets the maximum size the database will grow to. The maximum size cannot
973 * be set below the current size.
974 *
975 * @param numBytes the maximum database size, in bytes
976 * @return the new maximum database size
977 */
978 public long setMaximumSize(long numBytes) {
Vasu Noriccd95442010-05-28 17:04:16 -0700979 long pageSize = getPageSize();
980 long numPages = numBytes / pageSize;
981 // If numBytes isn't a multiple of pageSize, bump up a page
982 if ((numBytes % pageSize) != 0) {
983 numPages++;
Vasu Norif3cf8a42010-03-23 11:41:44 -0700984 }
Vasu Noriccd95442010-05-28 17:04:16 -0700985 long newPageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count = " + numPages,
986 null);
987 return newPageCount * pageSize;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 }
989
990 /**
991 * Returns the current database page size, in bytes.
992 *
993 * @return the database page size, in bytes
994 */
995 public long getPageSize() {
Vasu Noriccd95442010-05-28 17:04:16 -0700996 return DatabaseUtils.longForQuery(this, "PRAGMA page_size;", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 }
998
999 /**
1000 * Sets the database page size. The page size must be a power of two. This
1001 * method does not work if any data has been written to the database file,
1002 * and must be called right after the database has been created.
1003 *
1004 * @param numBytes the database page size, in bytes
1005 */
1006 public void setPageSize(long numBytes) {
1007 execSQL("PRAGMA page_size = " + numBytes);
1008 }
1009
1010 /**
1011 * Mark this table as syncable. When an update occurs in this table the
1012 * _sync_dirty field will be set to ensure proper syncing operation.
1013 *
1014 * @param table the table to mark as syncable
1015 * @param deletedTable The deleted table that corresponds to the
1016 * syncable table
Vasu Nori95675132010-07-21 16:24:40 -07001017 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 */
Vasu Nori95675132010-07-21 16:24:40 -07001019 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 public void markTableSyncable(String table, String deletedTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021 }
1022
1023 /**
1024 * Mark this table as syncable, with the _sync_dirty residing in another
1025 * table. When an update occurs in this table the _sync_dirty field of the
1026 * row in updateTable with the _id in foreignKey will be set to
1027 * ensure proper syncing operation.
1028 *
1029 * @param table an update on this table will trigger a sync time removal
1030 * @param foreignKey this is the column in table whose value is an _id in
1031 * updateTable
1032 * @param updateTable this is the table that will have its _sync_dirty
Vasu Nori95675132010-07-21 16:24:40 -07001033 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034 */
Vasu Nori95675132010-07-21 16:24:40 -07001035 @Deprecated
1036 public void markTableSyncable(String table, String foreignKey, String updateTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001037 }
1038
1039 /**
1040 * Finds the name of the first table, which is editable.
1041 *
1042 * @param tables a list of tables
1043 * @return the first table listed
1044 */
1045 public static String findEditTable(String tables) {
1046 if (!TextUtils.isEmpty(tables)) {
1047 // find the first word terminated by either a space or a comma
1048 int spacepos = tables.indexOf(' ');
1049 int commapos = tables.indexOf(',');
1050
1051 if (spacepos > 0 && (spacepos < commapos || commapos < 0)) {
1052 return tables.substring(0, spacepos);
1053 } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) {
1054 return tables.substring(0, commapos);
1055 }
1056 return tables;
1057 } else {
1058 throw new IllegalStateException("Invalid tables");
1059 }
1060 }
1061
1062 /**
1063 * Compiles an SQL statement into a reusable pre-compiled statement object.
1064 * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the
1065 * statement and fill in those values with {@link SQLiteProgram#bindString}
1066 * and {@link SQLiteProgram#bindLong} each time you want to run the
1067 * statement. Statements may not return result sets larger than 1x1.
Vasu Nori2827d6d2010-07-04 00:26:18 -07001068 *<p>
1069 * No two threads should be using the same {@link SQLiteStatement} at the same time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070 *
1071 * @param sql The raw SQL statement, may contain ? for unknown values to be
1072 * bound later.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001073 * @return A pre-compiled {@link SQLiteStatement} object. Note that
1074 * {@link SQLiteStatement}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075 */
1076 public SQLiteStatement compileStatement(String sql) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001077 acquireReference();
1078 try {
1079 return new SQLiteStatement(this, sql, null);
1080 } finally {
1081 releaseReference();
1082 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001083 }
1084
1085 /**
1086 * Query the given URL, returning a {@link Cursor} over the result set.
1087 *
1088 * @param distinct true if you want each row to be unique, false otherwise.
1089 * @param table The table name to compile the query against.
1090 * @param columns A list of which columns to return. Passing null will
1091 * return all columns, which is discouraged to prevent reading
1092 * data from storage that isn't going to be used.
1093 * @param selection A filter declaring which rows to return, formatted as an
1094 * SQL WHERE clause (excluding the WHERE itself). Passing null
1095 * will return all rows for the given table.
1096 * @param selectionArgs You may include ?s in selection, which will be
1097 * replaced by the values from selectionArgs, in order that they
1098 * appear in the selection. The values will be bound as Strings.
1099 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1100 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1101 * will cause the rows to not be grouped.
1102 * @param having A filter declare which row groups to include in the cursor,
1103 * if row grouping is being used, formatted as an SQL HAVING
1104 * clause (excluding the HAVING itself). Passing null will cause
1105 * all row groups to be included, and is required when row
1106 * grouping is not being used.
1107 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1108 * (excluding the ORDER BY itself). Passing null will use the
1109 * default sort order, which may be unordered.
1110 * @param limit Limits the number of rows returned by the query,
1111 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001112 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1113 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114 * @see Cursor
1115 */
1116 public Cursor query(boolean distinct, String table, String[] columns,
1117 String selection, String[] selectionArgs, String groupBy,
1118 String having, String orderBy, String limit) {
1119 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown75ea64f2012-01-25 19:37:13 -08001120 groupBy, having, orderBy, limit, null);
1121 }
1122
1123 /**
1124 * Query the given URL, returning a {@link Cursor} over the result set.
1125 *
1126 * @param distinct true if you want each row to be unique, false otherwise.
1127 * @param table The table name to compile the query against.
1128 * @param columns A list of which columns to return. Passing null will
1129 * return all columns, which is discouraged to prevent reading
1130 * data from storage that isn't going to be used.
1131 * @param selection A filter declaring which rows to return, formatted as an
1132 * SQL WHERE clause (excluding the WHERE itself). Passing null
1133 * will return all rows for the given table.
1134 * @param selectionArgs You may include ?s in selection, which will be
1135 * replaced by the values from selectionArgs, in order that they
1136 * appear in the selection. The values will be bound as Strings.
1137 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1138 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1139 * will cause the rows to not be grouped.
1140 * @param having A filter declare which row groups to include in the cursor,
1141 * if row grouping is being used, formatted as an SQL HAVING
1142 * clause (excluding the HAVING itself). Passing null will cause
1143 * all row groups to be included, and is required when row
1144 * grouping is not being used.
1145 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1146 * (excluding the ORDER BY itself). Passing null will use the
1147 * default sort order, which may be unordered.
1148 * @param limit Limits the number of rows returned by the query,
1149 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001150 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001151 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1152 * when the query is executed.
1153 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1154 * {@link Cursor}s are not synchronized, see the documentation for more details.
1155 * @see Cursor
1156 */
1157 public Cursor query(boolean distinct, String table, String[] columns,
1158 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001159 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001160 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001161 groupBy, having, orderBy, limit, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 }
1163
1164 /**
1165 * Query the given URL, returning a {@link Cursor} over the result set.
1166 *
1167 * @param cursorFactory the cursor factory to use, or null for the default factory
1168 * @param distinct true if you want each row to be unique, false otherwise.
1169 * @param table The table name to compile the query against.
1170 * @param columns A list of which columns to return. Passing null will
1171 * return all columns, which is discouraged to prevent reading
1172 * data from storage that isn't going to be used.
1173 * @param selection A filter declaring which rows to return, formatted as an
1174 * SQL WHERE clause (excluding the WHERE itself). Passing null
1175 * will return all rows for the given table.
1176 * @param selectionArgs You may include ?s in selection, which will be
1177 * replaced by the values from selectionArgs, in order that they
1178 * appear in the selection. The values will be bound as Strings.
1179 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1180 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1181 * will cause the rows to not be grouped.
1182 * @param having A filter declare which row groups to include in the cursor,
1183 * if row grouping is being used, formatted as an SQL HAVING
1184 * clause (excluding the HAVING itself). Passing null will cause
1185 * all row groups to be included, and is required when row
1186 * grouping is not being used.
1187 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1188 * (excluding the ORDER BY itself). Passing null will use the
1189 * default sort order, which may be unordered.
1190 * @param limit Limits the number of rows returned by the query,
1191 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001192 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1193 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001194 * @see Cursor
1195 */
1196 public Cursor queryWithFactory(CursorFactory cursorFactory,
1197 boolean distinct, String table, String[] columns,
1198 String selection, String[] selectionArgs, String groupBy,
1199 String having, String orderBy, String limit) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001200 return queryWithFactory(cursorFactory, distinct, table, columns, selection,
1201 selectionArgs, groupBy, having, orderBy, limit, null);
1202 }
1203
1204 /**
1205 * Query the given URL, returning a {@link Cursor} over the result set.
1206 *
1207 * @param cursorFactory the cursor factory to use, or null for the default factory
1208 * @param distinct true if you want each row to be unique, false otherwise.
1209 * @param table The table name to compile the query against.
1210 * @param columns A list of which columns to return. Passing null will
1211 * return all columns, which is discouraged to prevent reading
1212 * data from storage that isn't going to be used.
1213 * @param selection A filter declaring which rows to return, formatted as an
1214 * SQL WHERE clause (excluding the WHERE itself). Passing null
1215 * will return all rows for the given table.
1216 * @param selectionArgs You may include ?s in selection, which will be
1217 * replaced by the values from selectionArgs, in order that they
1218 * appear in the selection. The values will be bound as Strings.
1219 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1220 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1221 * will cause the rows to not be grouped.
1222 * @param having A filter declare which row groups to include in the cursor,
1223 * if row grouping is being used, formatted as an SQL HAVING
1224 * clause (excluding the HAVING itself). Passing null will cause
1225 * all row groups to be included, and is required when row
1226 * grouping is not being used.
1227 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1228 * (excluding the ORDER BY itself). Passing null will use the
1229 * default sort order, which may be unordered.
1230 * @param limit Limits the number of rows returned by the query,
1231 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001232 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001233 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1234 * when the query is executed.
1235 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1236 * {@link Cursor}s are not synchronized, see the documentation for more details.
1237 * @see Cursor
1238 */
1239 public Cursor queryWithFactory(CursorFactory cursorFactory,
1240 boolean distinct, String table, String[] columns,
1241 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001242 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001243 acquireReference();
1244 try {
1245 String sql = SQLiteQueryBuilder.buildQueryString(
1246 distinct, table, columns, selection, groupBy, having, orderBy, limit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001247
Jeff Brown03bd3022012-03-06 13:48:56 -08001248 return rawQueryWithFactory(cursorFactory, sql, selectionArgs,
1249 findEditTable(table), cancellationSignal);
1250 } finally {
1251 releaseReference();
1252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 }
1254
1255 /**
1256 * Query the given table, returning a {@link Cursor} over the result set.
1257 *
1258 * @param table The table name to compile the query against.
1259 * @param columns A list of which columns to return. Passing null will
1260 * return all columns, which is discouraged to prevent reading
1261 * data from storage that isn't going to be used.
1262 * @param selection A filter declaring which rows to return, formatted as an
1263 * SQL WHERE clause (excluding the WHERE itself). Passing null
1264 * will return all rows for the given table.
1265 * @param selectionArgs You may include ?s in selection, which will be
1266 * replaced by the values from selectionArgs, in order that they
1267 * appear in the selection. The values will be bound as Strings.
1268 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1269 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1270 * will cause the rows to not be grouped.
1271 * @param having A filter declare which row groups to include in the cursor,
1272 * if row grouping is being used, formatted as an SQL HAVING
1273 * clause (excluding the HAVING itself). Passing null will cause
1274 * all row groups to be included, and is required when row
1275 * grouping is not being used.
1276 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1277 * (excluding the ORDER BY itself). Passing null will use the
1278 * default sort order, which may be unordered.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001279 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1280 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001281 * @see Cursor
1282 */
1283 public Cursor query(String table, String[] columns, String selection,
1284 String[] selectionArgs, String groupBy, String having,
1285 String orderBy) {
1286
1287 return query(false, table, columns, selection, selectionArgs, groupBy,
1288 having, orderBy, null /* limit */);
1289 }
1290
1291 /**
1292 * Query the given table, returning a {@link Cursor} over the result set.
1293 *
1294 * @param table The table name to compile the query against.
1295 * @param columns A list of which columns to return. Passing null will
1296 * return all columns, which is discouraged to prevent reading
1297 * data from storage that isn't going to be used.
1298 * @param selection A filter declaring which rows to return, formatted as an
1299 * SQL WHERE clause (excluding the WHERE itself). Passing null
1300 * will return all rows for the given table.
1301 * @param selectionArgs You may include ?s in selection, which will be
1302 * replaced by the values from selectionArgs, in order that they
1303 * appear in the selection. The values will be bound as Strings.
1304 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1305 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1306 * will cause the rows to not be grouped.
1307 * @param having A filter declare which row groups to include in the cursor,
1308 * if row grouping is being used, formatted as an SQL HAVING
1309 * clause (excluding the HAVING itself). Passing null will cause
1310 * all row groups to be included, and is required when row
1311 * grouping is not being used.
1312 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1313 * (excluding the ORDER BY itself). Passing null will use the
1314 * default sort order, which may be unordered.
1315 * @param limit Limits the number of rows returned by the query,
1316 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001317 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1318 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 * @see Cursor
1320 */
1321 public Cursor query(String table, String[] columns, String selection,
1322 String[] selectionArgs, String groupBy, String having,
1323 String orderBy, String limit) {
1324
1325 return query(false, table, columns, selection, selectionArgs, groupBy,
1326 having, orderBy, limit);
1327 }
1328
1329 /**
1330 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1331 *
1332 * @param sql the SQL query. The SQL string must not be ; terminated
1333 * @param selectionArgs You may include ?s in where clause in the query,
1334 * which will be replaced by the values from selectionArgs. The
1335 * values will be bound as Strings.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001336 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1337 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001338 */
1339 public Cursor rawQuery(String sql, String[] selectionArgs) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001340 return rawQueryWithFactory(null, sql, selectionArgs, null, null);
1341 }
1342
1343 /**
1344 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1345 *
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.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001350 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001351 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1352 * when the query is executed.
1353 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1354 * {@link Cursor}s are not synchronized, see the documentation for more details.
1355 */
1356 public Cursor rawQuery(String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001357 CancellationSignal cancellationSignal) {
1358 return rawQueryWithFactory(null, sql, selectionArgs, null, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001359 }
1360
1361 /**
1362 * Runs the provided SQL and returns a cursor over the result set.
1363 *
1364 * @param cursorFactory the cursor factory to use, or null for the default factory
1365 * @param sql the SQL query. The SQL string must not be ; terminated
1366 * @param selectionArgs You may include ?s in where clause in the query,
1367 * which will be replaced by the values from selectionArgs. The
1368 * values will be bound as Strings.
1369 * @param editTable the name of the first table, which is editable
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001370 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1371 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 */
1373 public Cursor rawQueryWithFactory(
1374 CursorFactory cursorFactory, String sql, String[] selectionArgs,
1375 String editTable) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001376 return rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable, null);
1377 }
1378
1379 /**
1380 * Runs the provided SQL and returns a cursor over the result set.
1381 *
1382 * @param cursorFactory the cursor factory to use, or null for the default factory
1383 * @param sql the SQL query. The SQL string must not be ; terminated
1384 * @param selectionArgs You may include ?s in where clause in the query,
1385 * which will be replaced by the values from selectionArgs. The
1386 * values will be bound as Strings.
1387 * @param editTable the name of the first table, which is editable
Jeff Brown4c1241d2012-02-02 17:05:00 -08001388 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001389 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1390 * when the query is executed.
1391 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1392 * {@link Cursor}s are not synchronized, see the documentation for more details.
1393 */
1394 public Cursor rawQueryWithFactory(
1395 CursorFactory cursorFactory, String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001396 String editTable, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001397 acquireReference();
1398 try {
1399 SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
1400 cancellationSignal);
1401 return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
1402 selectionArgs);
1403 } finally {
1404 releaseReference();
1405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 }
1407
1408 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001409 * Convenience method for inserting a row into the database.
1410 *
1411 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001412 * @param nullColumnHack optional; may be <code>null</code>.
1413 * SQL doesn't allow inserting a completely empty row without
1414 * naming at least one column name. If your provided <code>values</code> is
1415 * empty, no column names are known and an empty row can't be inserted.
1416 * If not set to null, the <code>nullColumnHack</code> parameter
1417 * provides the name of nullable column name to explicitly insert a NULL into
1418 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 * @param values this map contains the initial column values for the
1420 * row. The keys should be the column names and the values the
1421 * column values
1422 * @return the row ID of the newly inserted row, or -1 if an error occurred
1423 */
1424 public long insert(String table, String nullColumnHack, ContentValues values) {
1425 try {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001426 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 } catch (SQLException e) {
1428 Log.e(TAG, "Error inserting " + values, e);
1429 return -1;
1430 }
1431 }
1432
1433 /**
1434 * Convenience method for inserting a row into the database.
1435 *
1436 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001437 * @param nullColumnHack optional; may be <code>null</code>.
1438 * SQL doesn't allow inserting a completely empty row without
1439 * naming at least one column name. If your provided <code>values</code> is
1440 * empty, no column names are known and an empty row can't be inserted.
1441 * If not set to null, the <code>nullColumnHack</code> parameter
1442 * provides the name of nullable column name to explicitly insert a NULL into
1443 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 * @param values this map contains the initial column values for the
1445 * row. The keys should be the column names and the values the
1446 * column values
1447 * @throws SQLException
1448 * @return the row ID of the newly inserted row, or -1 if an error occurred
1449 */
1450 public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
1451 throws SQLException {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001452 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 }
1454
1455 /**
1456 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001457 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 *
1459 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001460 * @param nullColumnHack optional; may be <code>null</code>.
1461 * SQL doesn't allow inserting a completely empty row without
1462 * naming at least one column name. If your provided <code>initialValues</code> is
1463 * empty, no column names are known and an empty row can't be inserted.
1464 * If not set to null, the <code>nullColumnHack</code> parameter
1465 * provides the name of nullable column name to explicitly insert a NULL into
1466 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001468 * 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 -08001469 * @return the row ID of the newly inserted row, or -1 if an error occurred
1470 */
1471 public long replace(String table, String nullColumnHack, ContentValues initialValues) {
1472 try {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001473 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001474 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 } catch (SQLException e) {
1476 Log.e(TAG, "Error inserting " + initialValues, e);
1477 return -1;
1478 }
1479 }
1480
1481 /**
1482 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001483 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 *
1485 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001486 * @param nullColumnHack optional; may be <code>null</code>.
1487 * SQL doesn't allow inserting a completely empty row without
1488 * naming at least one column name. If your provided <code>initialValues</code> is
1489 * empty, no column names are known and an empty row can't be inserted.
1490 * If not set to null, the <code>nullColumnHack</code> parameter
1491 * provides the name of nullable column name to explicitly insert a NULL into
1492 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001494 * 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 -08001495 * @throws SQLException
1496 * @return the row ID of the newly inserted row, or -1 if an error occurred
1497 */
1498 public long replaceOrThrow(String table, String nullColumnHack,
1499 ContentValues initialValues) throws SQLException {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001500 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001501 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 }
1503
1504 /**
1505 * General method for inserting a row into the database.
1506 *
1507 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001508 * @param nullColumnHack optional; may be <code>null</code>.
1509 * SQL doesn't allow inserting a completely empty row without
1510 * naming at least one column name. If your provided <code>initialValues</code> is
1511 * empty, no column names are known and an empty row can't be inserted.
1512 * If not set to null, the <code>nullColumnHack</code> parameter
1513 * provides the name of nullable column name to explicitly insert a NULL into
1514 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 * @param initialValues this map contains the initial column values for the
1516 * row. The keys should be the column names and the values the
1517 * column values
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001518 * @param conflictAlgorithm for insert conflict resolver
Steve Pomeroyc240b602013-03-14 00:42:10 -04001519 * @return the row ID of the newly inserted row OR <code>-1</code> if either the
1520 * input parameter <code>conflictAlgorithm</code> = {@link #CONFLICT_IGNORE}
1521 * or an error occurred.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 */
1523 public long insertWithOnConflict(String table, String nullColumnHack,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001524 ContentValues initialValues, int conflictAlgorithm) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001525 acquireReference();
1526 try {
1527 StringBuilder sql = new StringBuilder();
1528 sql.append("INSERT");
1529 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1530 sql.append(" INTO ");
1531 sql.append(table);
1532 sql.append('(');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533
Jeff Brown03bd3022012-03-06 13:48:56 -08001534 Object[] bindArgs = null;
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001535 int size = (initialValues != null && !initialValues.isEmpty())
Jeff Brown03bd3022012-03-06 13:48:56 -08001536 ? initialValues.size() : 0;
1537 if (size > 0) {
1538 bindArgs = new Object[size];
1539 int i = 0;
1540 for (String colName : initialValues.keySet()) {
1541 sql.append((i > 0) ? "," : "");
1542 sql.append(colName);
1543 bindArgs[i++] = initialValues.get(colName);
1544 }
1545 sql.append(')');
1546 sql.append(" VALUES (");
1547 for (i = 0; i < size; i++) {
1548 sql.append((i > 0) ? ",?" : "?");
1549 }
1550 } else {
1551 sql.append(nullColumnHack + ") VALUES (NULL");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 sql.append(')');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554
Jeff Brown03bd3022012-03-06 13:48:56 -08001555 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1556 try {
1557 return statement.executeInsert();
1558 } finally {
1559 statement.close();
1560 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001562 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 }
1564 }
1565
1566 /**
1567 * Convenience method for deleting rows in the database.
1568 *
1569 * @param table the table to delete from
1570 * @param whereClause the optional WHERE clause to apply when deleting.
1571 * Passing null will delete all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001572 * @param whereArgs You may include ?s in the where clause, which
1573 * will be replaced by the values from whereArgs. The values
1574 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 * @return the number of rows affected if a whereClause is passed in, 0
1576 * otherwise. To remove all rows and get a count pass "1" as the
1577 * whereClause.
1578 */
1579 public int delete(String table, String whereClause, String[] whereArgs) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001580 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001582 SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table +
1583 (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
1584 try {
1585 return statement.executeUpdateDelete();
1586 } finally {
1587 statement.close();
1588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001590 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 }
1592 }
1593
1594 /**
1595 * Convenience method for updating rows in the database.
1596 *
1597 * @param table the table to update in
1598 * @param values a map from column names to new column values. null is a
1599 * valid value that will be translated to NULL.
1600 * @param whereClause the optional WHERE clause to apply when updating.
1601 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001602 * @param whereArgs You may include ?s in the where clause, which
1603 * will be replaced by the values from whereArgs. The values
1604 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605 * @return the number of rows affected
1606 */
1607 public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001608 return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001609 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 /**
1612 * Convenience method for updating rows in the database.
1613 *
1614 * @param table the table to update in
1615 * @param values a map from column names to new column values. null is a
1616 * valid value that will be translated to NULL.
1617 * @param whereClause the optional WHERE clause to apply when updating.
1618 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001619 * @param whereArgs You may include ?s in the where clause, which
1620 * will be replaced by the values from whereArgs. The values
1621 * will be bound as Strings.
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001622 * @param conflictAlgorithm for update conflict resolver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 * @return the number of rows affected
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 */
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001625 public int updateWithOnConflict(String table, ContentValues values,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001626 String whereClause, String[] whereArgs, int conflictAlgorithm) {
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001627 if (values == null || values.isEmpty()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628 throw new IllegalArgumentException("Empty values");
1629 }
1630
Jeff Brown03bd3022012-03-06 13:48:56 -08001631 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001633 StringBuilder sql = new StringBuilder(120);
1634 sql.append("UPDATE ");
1635 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1636 sql.append(table);
1637 sql.append(" SET ");
1638
1639 // move all bind args to one array
1640 int setValuesSize = values.size();
1641 int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
1642 Object[] bindArgs = new Object[bindArgsSize];
1643 int i = 0;
1644 for (String colName : values.keySet()) {
1645 sql.append((i > 0) ? "," : "");
1646 sql.append(colName);
1647 bindArgs[i++] = values.get(colName);
1648 sql.append("=?");
1649 }
1650 if (whereArgs != null) {
1651 for (i = setValuesSize; i < bindArgsSize; i++) {
1652 bindArgs[i] = whereArgs[i - setValuesSize];
1653 }
1654 }
1655 if (!TextUtils.isEmpty(whereClause)) {
1656 sql.append(" WHERE ");
1657 sql.append(whereClause);
1658 }
1659
1660 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1661 try {
1662 return statement.executeUpdateDelete();
1663 } finally {
1664 statement.close();
1665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001667 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 }
1669 }
1670
1671 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001672 * Execute a single SQL statement that is NOT a SELECT
1673 * or any other SQL statement that returns data.
1674 * <p>
Vasu Norice38b982010-07-22 13:57:13 -07001675 * It has no means to return any data (such as the number of affected rows).
Vasu Noriccd95442010-05-28 17:04:16 -07001676 * Instead, you're encouraged to use {@link #insert(String, String, ContentValues)},
1677 * {@link #update(String, ContentValues, String, String[])}, et al, when possible.
1678 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001679 * <p>
1680 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1681 * automatically managed by this class. So, do not set journal_mode
1682 * using "PRAGMA journal_mode'<value>" statement if your app is using
1683 * {@link #enableWriteAheadLogging()}
1684 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 *
Vasu Noriccd95442010-05-28 17:04:16 -07001686 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1687 * not supported.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001688 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001689 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001690 public void execSQL(String sql) throws SQLException {
Vasu Nori16057fa2011-03-18 11:40:37 -07001691 executeSql(sql, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001692 }
1693
1694 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001695 * Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE.
1696 * <p>
1697 * For INSERT statements, use any of the following instead.
1698 * <ul>
1699 * <li>{@link #insert(String, String, ContentValues)}</li>
1700 * <li>{@link #insertOrThrow(String, String, ContentValues)}</li>
1701 * <li>{@link #insertWithOnConflict(String, String, ContentValues, int)}</li>
1702 * </ul>
1703 * <p>
1704 * For UPDATE statements, use any of the following instead.
1705 * <ul>
1706 * <li>{@link #update(String, ContentValues, String, String[])}</li>
1707 * <li>{@link #updateWithOnConflict(String, ContentValues, String, String[], int)}</li>
1708 * </ul>
1709 * <p>
1710 * For DELETE statements, use any of the following instead.
1711 * <ul>
1712 * <li>{@link #delete(String, String, String[])}</li>
1713 * </ul>
1714 * <p>
1715 * For example, the following are good candidates for using this method:
1716 * <ul>
1717 * <li>ALTER TABLE</li>
1718 * <li>CREATE or DROP table / trigger / view / index / virtual table</li>
1719 * <li>REINDEX</li>
1720 * <li>RELEASE</li>
1721 * <li>SAVEPOINT</li>
1722 * <li>PRAGMA that returns no data</li>
1723 * </ul>
1724 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001725 * <p>
1726 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1727 * automatically managed by this class. So, do not set journal_mode
1728 * using "PRAGMA journal_mode'<value>" statement if your app is using
1729 * {@link #enableWriteAheadLogging()}
1730 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 *
Vasu Noriccd95442010-05-28 17:04:16 -07001732 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1733 * not supported.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001734 * @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001735 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001737 public void execSQL(String sql, Object[] bindArgs) throws SQLException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 if (bindArgs == null) {
1739 throw new IllegalArgumentException("Empty bindArgs");
1740 }
Vasu Norib83cb7c2010-09-14 13:36:01 -07001741 executeSql(sql, bindArgs);
Vasu Norice38b982010-07-22 13:57:13 -07001742 }
1743
Vasu Nori54025902010-09-14 12:14:26 -07001744 private int executeSql(String sql, Object[] bindArgs) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001745 acquireReference();
1746 try {
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001747 final int statementType = DatabaseUtils.getSqlStatementType(sql);
1748 if (statementType == DatabaseUtils.STATEMENT_ATTACH) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001749 boolean disableWal = false;
1750 synchronized (mLock) {
1751 if (!mHasAttachedDbsLocked) {
1752 mHasAttachedDbsLocked = true;
1753 disableWal = true;
Fyodor Kupolovfd9c4a52017-07-13 15:36:57 -07001754 mConnectionPoolLocked.disableIdleConnectionHandler();
Jeff Brown03bd3022012-03-06 13:48:56 -08001755 }
1756 }
1757 if (disableWal) {
1758 disableWriteAheadLogging();
Jeff Browne5360fb2011-10-31 17:48:13 -07001759 }
1760 }
Jeff Browne5360fb2011-10-31 17:48:13 -07001761
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001762 try (SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs)) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001763 return statement.executeUpdateDelete();
1764 } finally {
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001765 // If schema was updated, close non-primary connections, otherwise they might
1766 // have outdated schema information
1767 if (statementType == DatabaseUtils.STATEMENT_DDL) {
1768 mConnectionPoolLocked.closeAvailableNonPrimaryConnectionsAndLogExceptions();
1769 }
Jeff Brown03bd3022012-03-06 13:48:56 -08001770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001772 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 }
1775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 /**
Makoto Onuki17aa1b72015-12-16 14:02:01 -08001777 * Verifies that a SQL SELECT statement is valid by compiling it.
1778 * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
1779 *
1780 * @param sql SQL to be validated
1781 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
1782 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1783 * when the query is executed.
1784 * @throws SQLiteException if {@code sql} is invalid
1785 */
1786 public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal) {
1787 getThreadSession().prepare(sql,
1788 getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null);
1789 }
1790
1791 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001792 * Returns true if the database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001793 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001794 * @return True if database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001795 */
1796 public boolean isReadOnly() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001797 synchronized (mLock) {
1798 return isReadOnlyLocked();
1799 }
1800 }
1801
1802 private boolean isReadOnlyLocked() {
1803 return (mConfigurationLocked.openFlags & OPEN_READ_MASK) == OPEN_READONLY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 }
1805
1806 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001807 * Returns true if the database is in-memory db.
1808 *
1809 * @return True if the database is in-memory.
1810 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 */
Jeff Browne5360fb2011-10-31 17:48:13 -07001812 public boolean isInMemoryDatabase() {
1813 synchronized (mLock) {
1814 return mConfigurationLocked.isInMemoryDb();
1815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001816 }
1817
Jeff Browne5360fb2011-10-31 17:48:13 -07001818 /**
1819 * Returns true if the database is currently open.
1820 *
1821 * @return True if the database is currently open (has not been closed).
1822 */
1823 public boolean isOpen() {
1824 synchronized (mLock) {
1825 return mConnectionPoolLocked != null;
1826 }
1827 }
1828
1829 /**
1830 * Returns true if the new version code is greater than the current database version.
1831 *
1832 * @param newVersion The new version code.
Mark Lu1e202082016-08-30 17:41:25 -07001833 * @return True if the new version code is greater than the current database version.
Jeff Browne5360fb2011-10-31 17:48:13 -07001834 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 public boolean needUpgrade(int newVersion) {
1836 return newVersion > getVersion();
1837 }
1838
1839 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001840 * Gets the path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001842 * @return The path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 */
1844 public final String getPath() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001845 synchronized (mLock) {
1846 return mConfigurationLocked.path;
Christopher Tatead9e8b12011-10-05 17:49:26 -07001847 }
Brad Fitzpatrick722802e2010-03-23 22:22:16 -07001848 }
1849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001850 /**
1851 * Sets the locale for this database. Does nothing if this database has
Jeff Brown1d9f7422012-03-15 14:32:32 -07001852 * the {@link #NO_LOCALIZED_COLLATORS} flag set or was opened read only.
Jeff Browne5360fb2011-10-31 17:48:13 -07001853 *
1854 * @param locale The new locale.
1855 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 * @throws SQLException if the locale could not be set. The most common reason
1857 * for this is that there is no collator available for the locale you requested.
1858 * In this case the database remains unchanged.
1859 */
1860 public void setLocale(Locale locale) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001861 if (locale == null) {
1862 throw new IllegalArgumentException("locale must not be null.");
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001863 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001864
Jeff Browne5360fb2011-10-31 17:48:13 -07001865 synchronized (mLock) {
1866 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001867
1868 final Locale oldLocale = mConfigurationLocked.locale;
Jeff Browne5360fb2011-10-31 17:48:13 -07001869 mConfigurationLocked.locale = locale;
Jeff Browne67ca422012-03-21 17:24:05 -07001870 try {
1871 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1872 } catch (RuntimeException ex) {
1873 mConfigurationLocked.locale = oldLocale;
1874 throw ex;
1875 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001876 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001877 }
1878
Vasu Norie495d1f2010-01-06 16:34:19 -08001879 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001880 * Sets the maximum size of the prepared-statement cache for this database.
Vasu Norie495d1f2010-01-06 16:34:19 -08001881 * (size of the cache = number of compiled-sql-statements stored in the cache).
Vasu Noriccd95442010-05-28 17:04:16 -07001882 *<p>
Vasu Norib729dcc2010-09-14 11:35:49 -07001883 * Maximum cache size can ONLY be increased from its current size (default = 10).
Vasu Noriccd95442010-05-28 17:04:16 -07001884 * If this method is called with smaller size than the current maximum value,
1885 * then IllegalStateException is thrown.
Vasu Norib729dcc2010-09-14 11:35:49 -07001886 *<p>
1887 * This method is thread-safe.
Vasu Norie495d1f2010-01-06 16:34:19 -08001888 *
Vasu Nori90a367262010-04-12 12:49:09 -07001889 * @param cacheSize the size of the cache. can be (0 to {@link #MAX_SQL_CACHE_SIZE})
Jeff Browne5360fb2011-10-31 17:48:13 -07001890 * @throws IllegalStateException if input cacheSize > {@link #MAX_SQL_CACHE_SIZE}.
Vasu Norie495d1f2010-01-06 16:34:19 -08001891 */
Vasu Nori54025902010-09-14 12:14:26 -07001892 public void setMaxSqlCacheSize(int cacheSize) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001893 if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) {
1894 throw new IllegalStateException(
1895 "expected value between 0 and " + MAX_SQL_CACHE_SIZE);
Vasu Nori587423a2010-09-27 18:18:34 -07001896 }
Vasu Nori587423a2010-09-27 18:18:34 -07001897
Jeff Browne5360fb2011-10-31 17:48:13 -07001898 synchronized (mLock) {
1899 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001900
1901 final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize;
Jeff Browne5360fb2011-10-31 17:48:13 -07001902 mConfigurationLocked.maxSqlCacheSize = cacheSize;
Jeff Browne67ca422012-03-21 17:24:05 -07001903 try {
1904 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1905 } catch (RuntimeException ex) {
1906 mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize;
1907 throw ex;
1908 }
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001909 }
1910 }
1911
Vasu Nori6c354da2010-04-26 23:33:39 -07001912 /**
Jeff Brown96496ad2012-03-23 14:38:06 -07001913 * Sets whether foreign key constraints are enabled for the database.
1914 * <p>
1915 * By default, foreign key constraints are not enforced by the database.
1916 * This method allows an application to enable foreign key constraints.
1917 * It must be called each time the database is opened to ensure that foreign
1918 * key constraints are enabled for the session.
1919 * </p><p>
1920 * A good time to call this method is right after calling {@link #openOrCreateDatabase}
1921 * or in the {@link SQLiteOpenHelper#onConfigure} callback.
1922 * </p><p>
1923 * When foreign key constraints are disabled, the database does not check whether
1924 * changes to the database will violate foreign key constraints. Likewise, when
1925 * foreign key constraints are disabled, the database will not execute cascade
1926 * delete or update triggers. As a result, it is possible for the database
1927 * state to become inconsistent. To perform a database integrity check,
1928 * call {@link #isDatabaseIntegrityOk}.
1929 * </p><p>
1930 * This method must not be called while a transaction is in progress.
1931 * </p><p>
1932 * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a>
1933 * for more details about foreign key constraint support.
1934 * </p>
1935 *
1936 * @param enable True to enable foreign key constraints, false to disable them.
1937 *
1938 * @throws IllegalStateException if the are transactions is in progress
1939 * when this method is called.
1940 */
1941 public void setForeignKeyConstraintsEnabled(boolean enable) {
1942 synchronized (mLock) {
1943 throwIfNotOpenLocked();
1944
1945 if (mConfigurationLocked.foreignKeyConstraintsEnabled == enable) {
1946 return;
1947 }
1948
1949 mConfigurationLocked.foreignKeyConstraintsEnabled = enable;
1950 try {
1951 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1952 } catch (RuntimeException ex) {
1953 mConfigurationLocked.foreignKeyConstraintsEnabled = !enable;
1954 throw ex;
1955 }
1956 }
1957 }
1958
1959 /**
Jeff Brown47847f32012-03-22 19:13:11 -07001960 * This method enables parallel execution of queries from multiple threads on the
1961 * same database. It does this by opening multiple connections to the database
1962 * and using a different database connection for each query. The database
1963 * journal mode is also changed to enable writes to proceed concurrently with reads.
Vasu Nori6c354da2010-04-26 23:33:39 -07001964 * <p>
Jeff Brown47847f32012-03-22 19:13:11 -07001965 * When write-ahead logging is not enabled (the default), it is not possible for
1966 * reads and writes to occur on the database at the same time. Before modifying the
1967 * database, the writer implicitly acquires an exclusive lock on the database which
1968 * prevents readers from accessing the database until the write is completed.
1969 * </p><p>
1970 * In contrast, when write-ahead logging is enabled (by calling this method), write
1971 * operations occur in a separate log file which allows reads to proceed concurrently.
1972 * While a write is in progress, readers on other threads will perceive the state
1973 * of the database as it was before the write began. When the write completes, readers
1974 * on other threads will then perceive the new state of the database.
1975 * </p><p>
1976 * It is a good idea to enable write-ahead logging whenever a database will be
1977 * concurrently accessed and modified by multiple threads at the same time.
1978 * However, write-ahead logging uses significantly more memory than ordinary
1979 * journaling because there are multiple connections to the same database.
1980 * So if a database will only be used by a single thread, or if optimizing
1981 * concurrency is not very important, then write-ahead logging should be disabled.
1982 * </p><p>
1983 * After calling this method, execution of queries in parallel is enabled as long as
1984 * the database remains open. To disable execution of queries in parallel, either
1985 * call {@link #disableWriteAheadLogging} or close the database and reopen it.
1986 * </p><p>
1987 * The maximum number of connections used to execute queries in parallel is
Vasu Nori6c354da2010-04-26 23:33:39 -07001988 * dependent upon the device memory and possibly other properties.
Jeff Brown47847f32012-03-22 19:13:11 -07001989 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07001990 * If a query is part of a transaction, then it is executed on the same database handle the
1991 * transaction was begun.
Jeff Brown47847f32012-03-22 19:13:11 -07001992 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07001993 * Writers should use {@link #beginTransactionNonExclusive()} or
1994 * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
Jeff Brown47847f32012-03-22 19:13:11 -07001995 * to start a transaction. Non-exclusive mode allows database file to be in readable
1996 * by other threads executing queries.
1997 * </p><p>
1998 * If the database has any attached databases, then execution of queries in parallel is NOT
1999 * possible. Likewise, write-ahead logging is not supported for read-only databases
2000 * or memory databases. In such cases, {@link #enableWriteAheadLogging} returns false.
2001 * </p><p>
2002 * The best way to enable write-ahead logging is to pass the
2003 * {@link #ENABLE_WRITE_AHEAD_LOGGING} flag to {@link #openDatabase}. This is
2004 * more efficient than calling {@link #enableWriteAheadLogging}.
2005 * <code><pre>
2006 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2007 * SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
2008 * myDatabaseErrorHandler);
2009 * db.enableWriteAheadLogging();
2010 * </pre></code>
2011 * </p><p>
2012 * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging}
2013 * after opening the database.
2014 * <code><pre>
2015 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2016 * SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
2017 * db.enableWriteAheadLogging();
2018 * </pre></code>
2019 * </p><p>
2020 * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for
2021 * more details about how write-ahead logging works.
Vasu Nori6c354da2010-04-26 23:33:39 -07002022 * </p>
2023 *
Jeff Brown47847f32012-03-22 19:13:11 -07002024 * @return True if write-ahead logging is enabled.
Jeff Browne67ca422012-03-21 17:24:05 -07002025 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002026 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002027 * time this method is called. WAL mode can only be changed when there are no
2028 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002029 *
2030 * @see #ENABLE_WRITE_AHEAD_LOGGING
2031 * @see #disableWriteAheadLogging
Vasu Nori6c354da2010-04-26 23:33:39 -07002032 */
Vasu Noriffe06122010-09-27 12:32:57 -07002033 public boolean enableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002034 synchronized (mLock) {
2035 throwIfNotOpenLocked();
2036
Jeff Brown47847f32012-03-22 19:13:11 -07002037 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002038 return true;
2039 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002040
2041 if (isReadOnlyLocked()) {
2042 // WAL doesn't make sense for readonly-databases.
2043 // TODO: True, but connection pooling does still make sense...
2044 return false;
2045 }
2046
2047 if (mConfigurationLocked.isInMemoryDb()) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002048 Log.i(TAG, "can't enable WAL for memory databases.");
2049 return false;
2050 }
2051
2052 // make sure this database has NO attached databases because sqlite's write-ahead-logging
2053 // doesn't work for databases with attached databases
Jeff Browne5360fb2011-10-31 17:48:13 -07002054 if (mHasAttachedDbsLocked) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002055 if (Log.isLoggable(TAG, Log.DEBUG)) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002056 Log.d(TAG, "this database: " + mConfigurationLocked.label
2057 + " has attached databases. can't enable WAL.");
Paul Westbrookdae6d372011-02-17 10:59:56 -08002058 }
2059 return false;
2060 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002061
Jeff Brown47847f32012-03-22 19:13:11 -07002062 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002063 try {
2064 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2065 } catch (RuntimeException ex) {
Jeff Brown47847f32012-03-22 19:13:11 -07002066 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002067 throw ex;
2068 }
Paul Westbrookdae6d372011-02-17 10:59:56 -08002069 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002070 return true;
Vasu Nori6c354da2010-04-26 23:33:39 -07002071 }
2072
Vasu Nori2827d6d2010-07-04 00:26:18 -07002073 /**
Vasu Nori7b04c412010-07-20 10:31:21 -07002074 * This method disables the features enabled by {@link #enableWriteAheadLogging()}.
Jeff Browne67ca422012-03-21 17:24:05 -07002075 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002076 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002077 * time this method is called. WAL mode can only be changed when there are no
2078 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002079 *
2080 * @see #enableWriteAheadLogging
Vasu Nori2827d6d2010-07-04 00:26:18 -07002081 */
Vasu Nori7b04c412010-07-20 10:31:21 -07002082 public void disableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002083 synchronized (mLock) {
2084 throwIfNotOpenLocked();
2085
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002086 final boolean oldUseCompatibilityWal = mConfigurationLocked.useCompatibilityWal;
2087 final int oldFlags = mConfigurationLocked.openFlags;
2088 if (!oldUseCompatibilityWal && (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002089 return;
Paul Westbrookdae6d372011-02-17 10:59:56 -08002090 }
Vasu Nori8d111032010-06-22 18:34:21 -07002091
Jeff Brown47847f32012-03-22 19:13:11 -07002092 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002093 // If an app explicitly disables WAL, do not even use compatibility mode
2094 mConfigurationLocked.useCompatibilityWal = false;
2095
Jeff Browne67ca422012-03-21 17:24:05 -07002096 try {
2097 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2098 } catch (RuntimeException ex) {
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002099 mConfigurationLocked.openFlags = oldFlags;
2100 mConfigurationLocked.useCompatibilityWal = oldUseCompatibilityWal;
Jeff Browne67ca422012-03-21 17:24:05 -07002101 throw ex;
2102 }
Vasu Nori65a88832010-07-16 15:14:08 -07002103 }
Vasu Nori6c354da2010-04-26 23:33:39 -07002104 }
2105
Vasu Norif3cf8a42010-03-23 11:41:44 -07002106 /**
Jeff Brown47847f32012-03-22 19:13:11 -07002107 * Returns true if write-ahead logging has been enabled for this database.
2108 *
2109 * @return True if write-ahead logging has been enabled for this database.
2110 *
2111 * @see #enableWriteAheadLogging
2112 * @see #ENABLE_WRITE_AHEAD_LOGGING
2113 */
2114 public boolean isWriteAheadLoggingEnabled() {
2115 synchronized (mLock) {
2116 throwIfNotOpenLocked();
2117
2118 return (mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2119 }
2120 }
2121
2122 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002123 * Collect statistics about all open databases in the current process.
2124 * Used by bug report.
Vasu Norif3cf8a42010-03-23 11:41:44 -07002125 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002126 static ArrayList<DbStats> getDbStats() {
Vasu Noric3849202010-03-09 10:47:25 -08002127 ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002128 for (SQLiteDatabase db : getActiveDatabases()) {
2129 db.collectDbStats(dbStatsList);
Vasu Nori24675612010-09-27 14:54:19 -07002130 }
Vasu Noric3849202010-03-09 10:47:25 -08002131 return dbStatsList;
2132 }
2133
Jeff Browne5360fb2011-10-31 17:48:13 -07002134 private void collectDbStats(ArrayList<DbStats> dbStatsList) {
2135 synchronized (mLock) {
2136 if (mConnectionPoolLocked != null) {
2137 mConnectionPoolLocked.collectDbStats(dbStatsList);
2138 }
2139 }
2140 }
2141
2142 private static ArrayList<SQLiteDatabase> getActiveDatabases() {
2143 ArrayList<SQLiteDatabase> databases = new ArrayList<SQLiteDatabase>();
2144 synchronized (sActiveDatabases) {
2145 databases.addAll(sActiveDatabases.keySet());
2146 }
2147 return databases;
2148 }
2149
2150 /**
2151 * Dump detailed information about all open databases in the current process.
2152 * Used by bug report.
2153 */
Jeff Browna9be4152012-01-18 15:29:57 -08002154 static void dumpAll(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002155 for (SQLiteDatabase db : getActiveDatabases()) {
Jeff Browna9be4152012-01-18 15:29:57 -08002156 db.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002157 }
2158 }
2159
Jeff Browna9be4152012-01-18 15:29:57 -08002160 private void dump(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002161 synchronized (mLock) {
2162 if (mConnectionPoolLocked != null) {
2163 printer.println("");
Jeff Browna9be4152012-01-18 15:29:57 -08002164 mConnectionPoolLocked.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002165 }
2166 }
2167 }
2168
Vasu Noric3849202010-03-09 10:47:25 -08002169 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002170 * Returns list of full pathnames of all attached databases including the main database
2171 * by executing 'pragma database_list' on the database.
2172 *
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002173 * @return ArrayList of pairs of (database name, database file path) or null if the database
2174 * is not open.
Vasu Noric3849202010-03-09 10:47:25 -08002175 */
Vasu Noria017eda2011-01-27 10:52:55 -08002176 public List<Pair<String, String>> getAttachedDbs() {
Vasu Noric3849202010-03-09 10:47:25 -08002177 ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002178 synchronized (mLock) {
2179 if (mConnectionPoolLocked == null) {
2180 return null; // not open
2181 }
2182
2183 if (!mHasAttachedDbsLocked) {
2184 // No attached databases.
2185 // There is a small window where attached databases exist but this flag is not
2186 // set yet. This can occur when this thread is in a race condition with another
2187 // thread that is executing the SQL statement: "attach database <blah> as <foo>"
2188 // If this thread is NOT ok with such a race condition (and thus possibly not
2189 // receivethe entire list of attached databases), then the caller should ensure
2190 // that no thread is executing any SQL statements while a thread is calling this
2191 // method. Typically, this method is called when 'adb bugreport' is done or the
2192 // caller wants to collect stats on the database and all its attached databases.
2193 attachedDbs.add(new Pair<String, String>("main", mConfigurationLocked.path));
2194 return attachedDbs;
2195 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002196
2197 acquireReference();
Vasu Nori24675612010-09-27 14:54:19 -07002198 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002199
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002200 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002201 // has attached databases. query sqlite to get the list of attached databases.
2202 Cursor c = null;
2203 try {
2204 c = rawQuery("pragma database_list;", null);
2205 while (c.moveToNext()) {
2206 // sqlite returns a row for each database in the returned list of databases.
2207 // in each row,
2208 // 1st column is the database name such as main, or the database
2209 // name specified on the "ATTACH" command
2210 // 2nd column is the database file path.
2211 attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2)));
2212 }
2213 } finally {
2214 if (c != null) {
2215 c.close();
2216 }
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002217 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002218 return attachedDbs;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002219 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08002220 releaseReference();
Vasu Noric3849202010-03-09 10:47:25 -08002221 }
Vasu Noric3849202010-03-09 10:47:25 -08002222 }
2223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002224 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002225 * Runs 'pragma integrity_check' on the given database (and all the attached databases)
2226 * and returns true if the given database (and all its attached databases) pass integrity_check,
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002227 * false otherwise.
Vasu Noriccd95442010-05-28 17:04:16 -07002228 *<p>
2229 * If the result is false, then this method logs the errors reported by the integrity_check
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002230 * command execution.
Vasu Noriccd95442010-05-28 17:04:16 -07002231 *<p>
2232 * Note that 'pragma integrity_check' on a database can take a long time.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002233 *
2234 * @return true if the given database (and all its attached databases) pass integrity_check,
Vasu Noriccd95442010-05-28 17:04:16 -07002235 * false otherwise.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002236 */
2237 public boolean isDatabaseIntegrityOk() {
Jeff Brown03bd3022012-03-06 13:48:56 -08002238 acquireReference();
Vasu Noribfe1dc22010-08-25 16:29:02 -07002239 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002240 List<Pair<String, String>> attachedDbs = null;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002241 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002242 attachedDbs = getAttachedDbs();
2243 if (attachedDbs == null) {
2244 throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " +
2245 "be retrieved. probably because the database is closed");
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002246 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002247 } catch (SQLiteException e) {
2248 // can't get attachedDb list. do integrity check on the main database
2249 attachedDbs = new ArrayList<Pair<String, String>>();
2250 attachedDbs.add(new Pair<String, String>("main", getPath()));
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002251 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002252
2253 for (int i = 0; i < attachedDbs.size(); i++) {
2254 Pair<String, String> p = attachedDbs.get(i);
2255 SQLiteStatement prog = null;
2256 try {
2257 prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);");
2258 String rslt = prog.simpleQueryForString();
2259 if (!rslt.equalsIgnoreCase("ok")) {
2260 // integrity_checker failed on main or attached databases
2261 Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt);
2262 return false;
2263 }
2264 } finally {
2265 if (prog != null) prog.close();
2266 }
2267 }
2268 } finally {
2269 releaseReference();
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002270 }
Vasu Noribfe1dc22010-08-25 16:29:02 -07002271 return true;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002272 }
2273
Jeff Browne5360fb2011-10-31 17:48:13 -07002274 @Override
2275 public String toString() {
2276 return "SQLiteDatabase: " + getPath();
2277 }
2278
Jeff Browne5360fb2011-10-31 17:48:13 -07002279 private void throwIfNotOpenLocked() {
2280 if (mConnectionPoolLocked == null) {
2281 throw new IllegalStateException("The database '" + mConfigurationLocked.label
2282 + "' is not open.");
2283 }
2284 }
Vasu Nori3ef94e22010-02-05 14:49:04 -08002285
2286 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002287 * Used to allow returning sub-classes of {@link Cursor} when calling query.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002288 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002289 public interface CursorFactory {
2290 /**
2291 * See {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}.
2292 */
2293 public Cursor newCursor(SQLiteDatabase db,
2294 SQLiteCursorDriver masterQuery, String editTable,
2295 SQLiteQuery query);
2296 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002297
2298 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002299 * A callback interface for a custom sqlite3 function.
2300 * This can be used to create a function that can be called from
2301 * sqlite3 database triggers.
2302 * @hide
Vasu Noric3849202010-03-09 10:47:25 -08002303 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002304 public interface CustomFunction {
2305 public void callback(String[] args);
2306 }
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002307
2308 /**
2309 * Wrapper for configuration parameters that are used for opening {@link SQLiteDatabase}
2310 */
2311 public static final class OpenParams {
2312 private final int mOpenFlags;
2313 private final CursorFactory mCursorFactory;
2314 private final DatabaseErrorHandler mErrorHandler;
2315 private final int mLookasideSlotSize;
2316 private final int mLookasideSlotCount;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002317 private final long mIdleConnectionTimeout;
2318 private final String mJournalMode;
2319 private final String mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002320
2321 private OpenParams(int openFlags, CursorFactory cursorFactory,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002322 DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002323 long idleConnectionTimeout, String journalMode, String syncMode) {
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002324 mOpenFlags = openFlags;
2325 mCursorFactory = cursorFactory;
2326 mErrorHandler = errorHandler;
2327 mLookasideSlotSize = lookasideSlotSize;
2328 mLookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002329 mIdleConnectionTimeout = idleConnectionTimeout;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002330 mJournalMode = journalMode;
2331 mSyncMode = syncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002332 }
2333
2334 /**
2335 * Returns size in bytes of each lookaside slot or -1 if not set.
2336 *
2337 * @see Builder#setLookasideConfig(int, int)
2338 */
2339 @IntRange(from = -1)
2340 public int getLookasideSlotSize() {
2341 return mLookasideSlotSize;
2342 }
2343
2344 /**
2345 * Returns total number of lookaside memory slots per database connection or -1 if not
2346 * set.
2347 *
2348 * @see Builder#setLookasideConfig(int, int)
2349 */
2350 @IntRange(from = -1)
2351 public int getLookasideSlotCount() {
2352 return mLookasideSlotCount;
2353 }
2354
2355 /**
Fyodor Kupolov76436c02017-08-03 17:56:44 -07002356 * Returns flags to control database access mode. Default value is 0.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002357 *
2358 * @see Builder#setOpenFlags(int)
2359 */
2360 @DatabaseOpenFlags
2361 public int getOpenFlags() {
2362 return mOpenFlags;
2363 }
2364
2365 /**
2366 * Returns an optional factory class that is called to instantiate a cursor when query
2367 * is called
2368 *
2369 * @see Builder#setCursorFactory(CursorFactory)
2370 */
2371 @Nullable
2372 public CursorFactory getCursorFactory() {
2373 return mCursorFactory;
2374 }
2375
2376 /**
2377 * Returns handler for database corruption errors
2378 *
2379 * @see Builder#setErrorHandler(DatabaseErrorHandler)
2380 */
2381 @Nullable
2382 public DatabaseErrorHandler getErrorHandler() {
2383 return mErrorHandler;
2384 }
2385
2386 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002387 * Returns maximum number of milliseconds that SQLite connection is allowed to be idle
2388 * before it is closed and removed from the pool.
2389 * <p>If the value isn't set, the timeout defaults to the system wide timeout
2390 *
2391 * @return timeout in milliseconds or -1 if the value wasn't set.
2392 */
2393 public long getIdleConnectionTimeout() {
2394 return mIdleConnectionTimeout;
2395 }
2396
2397 /**
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002398 * Returns <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>.
2399 * This journal mode will only be used if {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING}
2400 * flag is not set, otherwise a platform will use "WAL" journal mode.
2401 * @see Builder#setJournalMode(String)
2402 */
2403 @Nullable
2404 public String getJournalMode() {
2405 return mJournalMode;
2406 }
2407
2408 /**
2409 * Returns <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>.
2410 * This value will only be used when {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag
2411 * is not set, otherwise a system wide default will be used.
2412 * @see Builder#setSynchronousMode(String)
2413 */
2414 @Nullable
2415 public String getSynchronousMode() {
2416 return mSyncMode;
2417 }
2418
2419 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002420 * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with
2421 * {@code this} parameters.
2422 * @hide
2423 */
2424 @NonNull
2425 public Builder toBuilder() {
2426 return new Builder(this);
2427 }
2428
2429 /**
2430 * Builder for {@link OpenParams}.
2431 */
2432 public static final class Builder {
2433 private int mLookasideSlotSize = -1;
2434 private int mLookasideSlotCount = -1;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002435 private long mIdleConnectionTimeout = -1;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002436 private int mOpenFlags;
2437 private CursorFactory mCursorFactory;
2438 private DatabaseErrorHandler mErrorHandler;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002439 private String mJournalMode;
2440 private String mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002441
2442 public Builder() {
2443 }
2444
2445 public Builder(OpenParams params) {
2446 mLookasideSlotSize = params.mLookasideSlotSize;
2447 mLookasideSlotCount = params.mLookasideSlotCount;
2448 mOpenFlags = params.mOpenFlags;
2449 mCursorFactory = params.mCursorFactory;
2450 mErrorHandler = params.mErrorHandler;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002451 mJournalMode = params.mJournalMode;
2452 mSyncMode = params.mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002453 }
2454
2455 /**
2456 * Configures
2457 * <a href="https://sqlite.org/malloc.html#lookaside">lookaside memory allocator</a>
2458 *
2459 * <p>SQLite default settings will be used, if this method isn't called.
2460 * Use {@code setLookasideConfig(0,0)} to disable lookaside
2461 *
Fyodor Kupolov05a0f0f2017-06-30 19:00:00 -07002462 * <p><strong>Note:</strong> Provided slotSize/slotCount configuration is just a
2463 * recommendation. The system may choose different values depending on a device, e.g.
2464 * lookaside allocations can be disabled on low-RAM devices
2465 *
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002466 * @param slotSize The size in bytes of each lookaside slot.
2467 * @param slotCount The total number of lookaside memory slots per database connection.
2468 */
2469 public Builder setLookasideConfig(@IntRange(from = 0) final int slotSize,
2470 @IntRange(from = 0) final int slotCount) {
2471 Preconditions.checkArgument(slotSize >= 0,
2472 "lookasideSlotCount cannot be negative");
2473 Preconditions.checkArgument(slotCount >= 0,
2474 "lookasideSlotSize cannot be negative");
2475 Preconditions.checkArgument(
2476 (slotSize > 0 && slotCount > 0) || (slotCount == 0 && slotSize == 0),
2477 "Invalid configuration: " + slotSize + ", " + slotCount);
2478
2479 mLookasideSlotSize = slotSize;
2480 mLookasideSlotCount = slotCount;
2481 return this;
2482 }
2483
2484 /**
2485 * Returns true if {@link #ENABLE_WRITE_AHEAD_LOGGING} flag is set
2486 * @hide
2487 */
2488 public boolean isWriteAheadLoggingEnabled() {
2489 return (mOpenFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2490 }
2491
2492 /**
2493 * Sets flags to control database access mode
2494 * @param openFlags The new flags to set
2495 * @see #OPEN_READWRITE
2496 * @see #OPEN_READONLY
2497 * @see #CREATE_IF_NECESSARY
2498 * @see #NO_LOCALIZED_COLLATORS
2499 * @see #ENABLE_WRITE_AHEAD_LOGGING
2500 * @return same builder instance for chaining multiple calls into a single statement
2501 */
2502 @NonNull
2503 public Builder setOpenFlags(@DatabaseOpenFlags int openFlags) {
2504 mOpenFlags = openFlags;
2505 return this;
2506 }
2507
2508 /**
2509 * Adds flags to control database access mode
2510 *
2511 * @param openFlags The new flags to add
2512 * @return same builder instance for chaining multiple calls into a single statement
2513 */
2514 @NonNull
2515 public Builder addOpenFlags(@DatabaseOpenFlags int openFlags) {
2516 mOpenFlags |= openFlags;
2517 return this;
2518 }
2519
2520 /**
2521 * Removes database access mode flags
2522 *
2523 * @param openFlags Flags to remove
2524 * @return same builder instance for chaining multiple calls into a single statement
2525 */
2526 @NonNull
2527 public Builder removeOpenFlags(@DatabaseOpenFlags int openFlags) {
2528 mOpenFlags &= ~openFlags;
2529 return this;
2530 }
2531
2532 /**
2533 * Sets {@link #ENABLE_WRITE_AHEAD_LOGGING} flag if {@code enabled} is {@code true},
2534 * unsets otherwise
2535 * @hide
2536 */
2537 public void setWriteAheadLoggingEnabled(boolean enabled) {
2538 if (enabled) {
2539 addOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2540 } else {
2541 removeOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2542 }
2543 }
2544
2545 /**
2546 * Set an optional factory class that is called to instantiate a cursor when query
2547 * is called.
2548 *
2549 * @param cursorFactory instance
2550 * @return same builder instance for chaining multiple calls into a single statement
2551 */
2552 @NonNull
2553 public Builder setCursorFactory(@Nullable CursorFactory cursorFactory) {
2554 mCursorFactory = cursorFactory;
2555 return this;
2556 }
2557
2558
2559 /**
2560 * Sets {@link DatabaseErrorHandler} object to handle db corruption errors
2561 */
2562 @NonNull
2563 public Builder setErrorHandler(@Nullable DatabaseErrorHandler errorHandler) {
2564 mErrorHandler = errorHandler;
2565 return this;
2566 }
2567
2568 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002569 * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle
2570 * before it is closed and removed from the pool.
2571 *
2572 * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE}
2573 * to allow unlimited idle connections.
2574 */
2575 @NonNull
2576 public Builder setIdleConnectionTimeout(
2577 @IntRange(from = 0) long idleConnectionTimeoutMs) {
2578 Preconditions.checkArgument(idleConnectionTimeoutMs >= 0,
2579 "idle connection timeout cannot be negative");
2580 mIdleConnectionTimeout = idleConnectionTimeoutMs;
2581 return this;
2582 }
2583
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002584
2585 /**
2586 * Sets <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>
2587 * to use when {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag is not set.
2588 */
2589 @NonNull
2590 public Builder setJournalMode(@NonNull String journalMode) {
2591 Preconditions.checkNotNull(journalMode);
2592 mJournalMode = journalMode;
2593 return this;
2594 }
2595
2596 /**
2597 * Sets <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>
2598 * to use when {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag is not set.
2599 * @return
2600 */
2601 @NonNull
2602 public Builder setSynchronousMode(@NonNull String syncMode) {
2603 Preconditions.checkNotNull(syncMode);
2604 mSyncMode = syncMode;
2605 return this;
2606 }
2607
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002608 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002609 * Creates an instance of {@link OpenParams} with the options that were previously set
2610 * on this builder
2611 */
2612 @NonNull
2613 public OpenParams build() {
2614 return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002615 mLookasideSlotCount, mIdleConnectionTimeout, mJournalMode, mSyncMode);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002616 }
2617 }
2618 }
2619
2620 /** @hide */
2621 @IntDef(flag = true, prefix = {"OPEN_", "CREATE_", "NO_", "ENABLE_"}, value = {
2622 OPEN_READWRITE,
2623 OPEN_READONLY,
2624 CREATE_IF_NECESSARY,
2625 NO_LOCALIZED_COLLATORS,
2626 ENABLE_WRITE_AHEAD_LOGGING
2627 })
2628 @Retention(RetentionPolicy.SOURCE)
2629 public @interface DatabaseOpenFlags {}
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002631}
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002632