blob: 09bb9c69dc09210d8341d4640ce34f612b413e01 [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();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700293
Jeff Browne5360fb2011-10-31 17:48:13 -0700294 @Override
295 protected void finalize() throws Throwable {
296 try {
297 dispose(true);
298 } finally {
299 super.finalize();
300 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700301 }
302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 @Override
304 protected void onAllReferencesReleased() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700305 dispose(false);
306 }
307
308 private void dispose(boolean finalized) {
309 final SQLiteConnectionPool pool;
310 synchronized (mLock) {
311 if (mCloseGuardLocked != null) {
312 if (finalized) {
313 mCloseGuardLocked.warnIfOpen();
314 }
315 mCloseGuardLocked.close();
316 }
317
318 pool = mConnectionPoolLocked;
319 mConnectionPoolLocked = null;
320 }
321
322 if (!finalized) {
323 synchronized (sActiveDatabases) {
324 sActiveDatabases.remove(this);
325 }
326
327 if (pool != null) {
328 pool.close();
329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 }
331 }
332
333 /**
334 * Attempts to release memory that SQLite holds but does not require to
335 * operate properly. Typically this memory will come from the page cache.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700336 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 * @return the number of bytes actually released
338 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700339 public static int releaseMemory() {
340 return SQLiteGlobal.releaseMemory();
341 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342
343 /**
344 * Control whether or not the SQLiteDatabase is made thread-safe by using locks
345 * around critical sections. This is pretty expensive, so if you know that your
346 * DB will only be used by a single thread then you should set this to false.
347 * The default is true.
348 * @param lockingEnabled set to true to enable locks, false otherwise
Jeff Browne5360fb2011-10-31 17:48:13 -0700349 *
350 * @deprecated This method now does nothing. Do not use.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700352 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 public void setLockingEnabled(boolean lockingEnabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 }
355
356 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700357 * Gets a label to use when describing the database in log messages.
358 * @return The label.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700360 String getLabel() {
361 synchronized (mLock) {
362 return mConfigurationLocked.label;
363 }
364 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365
Jeff Browne5360fb2011-10-31 17:48:13 -0700366 /**
367 * Sends a corruption message to the database error handler.
368 */
369 void onCorruption() {
370 EventLog.writeEvent(EVENT_DB_CORRUPT, getLabel());
Vasu Noriccd95442010-05-28 17:04:16 -0700371 mErrorHandler.onCorruption(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 }
373
374 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700375 * Gets the {@link SQLiteSession} that belongs to this thread for this database.
376 * Once a thread has obtained a session, it will continue to obtain the same
377 * session even after the database has been closed (although the session will not
378 * be usable). However, a thread that does not already have a session cannot
379 * obtain one after the database has been closed.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700380 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700381 * The idea is that threads that have active connections to the database may still
382 * have work to complete even after the call to {@link #close}. Active database
383 * connections are not actually disposed until they are released by the threads
384 * that own them.
385 *
386 * @return The session, never null.
387 *
388 * @throws IllegalStateException if the thread does not yet have a session and
389 * the database is not open.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700391 SQLiteSession getThreadSession() {
392 return mThreadSession.get(); // initialValue() throws if database closed
Vasu Nori6d970252010-10-05 10:48:49 -0700393 }
Vasu Nori16057fa2011-03-18 11:40:37 -0700394
Jeff Browne5360fb2011-10-31 17:48:13 -0700395 SQLiteSession createSession() {
396 final SQLiteConnectionPool pool;
397 synchronized (mLock) {
398 throwIfNotOpenLocked();
399 pool = mConnectionPoolLocked;
Vasu Nori6d970252010-10-05 10:48:49 -0700400 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700401 return new SQLiteSession(pool);
Vasu Norid4608a32011-02-03 16:24:06 -0800402 }
403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700405 * Gets default connection flags that are appropriate for this thread, taking into
406 * account whether the thread is acting on behalf of the UI.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700408 * @param readOnly True if the connection should be read-only.
409 * @return The connection flags.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700411 int getThreadDefaultConnectionFlags(boolean readOnly) {
412 int flags = readOnly ? SQLiteConnectionPool.CONNECTION_FLAG_READ_ONLY :
413 SQLiteConnectionPool.CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY;
414 if (isMainThread()) {
415 flags |= SQLiteConnectionPool.CONNECTION_FLAG_INTERACTIVE;
416 }
417 return flags;
Vasu Nori16057fa2011-03-18 11:40:37 -0700418 }
419
Jeff Browne5360fb2011-10-31 17:48:13 -0700420 private static boolean isMainThread() {
421 // FIXME: There should be a better way to do this.
422 // Would also be nice to have something that would work across Binder calls.
423 Looper looper = Looper.myLooper();
424 return looper != null && looper == Looper.getMainLooper();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425 }
426
427 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700428 * Begins a transaction in EXCLUSIVE mode.
429 * <p>
430 * Transactions can be nested.
431 * When the outer transaction is ended all of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 * the work done in that transaction and all of the nested transactions will be committed or
433 * rolled back. The changes will be rolled back if any transaction is ended without being
434 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700435 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 * <p>Here is the standard idiom for transactions:
437 *
438 * <pre>
439 * db.beginTransaction();
440 * try {
441 * ...
442 * db.setTransactionSuccessful();
443 * } finally {
444 * db.endTransaction();
445 * }
446 * </pre>
447 */
448 public void beginTransaction() {
Vasu Nori6c354da2010-04-26 23:33:39 -0700449 beginTransaction(null /* transactionStatusCallback */, true);
450 }
451
452 /**
453 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
454 * the outer transaction is ended all of the work done in that transaction
455 * and all of the nested transactions will be committed or rolled back. The
456 * changes will be rolled back if any transaction is ended without being
457 * marked as clean (by calling setTransactionSuccessful). Otherwise they
458 * will be committed.
459 * <p>
460 * Here is the standard idiom for transactions:
461 *
462 * <pre>
463 * db.beginTransactionNonExclusive();
464 * try {
465 * ...
466 * db.setTransactionSuccessful();
467 * } finally {
468 * db.endTransaction();
469 * }
470 * </pre>
471 */
472 public void beginTransactionNonExclusive() {
473 beginTransaction(null /* transactionStatusCallback */, false);
Fred Quintanac4516a72009-09-03 12:14:06 -0700474 }
475
476 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700477 * Begins a transaction in EXCLUSIVE mode.
478 * <p>
479 * Transactions can be nested.
480 * When the outer transaction is ended all of
Fred Quintanac4516a72009-09-03 12:14:06 -0700481 * the work done in that transaction and all of the nested transactions will be committed or
482 * rolled back. The changes will be rolled back if any transaction is ended without being
483 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700484 * </p>
Fred Quintanac4516a72009-09-03 12:14:06 -0700485 * <p>Here is the standard idiom for transactions:
486 *
487 * <pre>
488 * db.beginTransactionWithListener(listener);
489 * try {
490 * ...
491 * db.setTransactionSuccessful();
492 * } finally {
493 * db.endTransaction();
494 * }
495 * </pre>
Vasu Noriccd95442010-05-28 17:04:16 -0700496 *
Fred Quintanac4516a72009-09-03 12:14:06 -0700497 * @param transactionListener listener that should be notified when the transaction begins,
498 * commits, or is rolled back, either explicitly or by a call to
499 * {@link #yieldIfContendedSafely}.
500 */
501 public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
Vasu Nori6c354da2010-04-26 23:33:39 -0700502 beginTransaction(transactionListener, true);
503 }
504
505 /**
506 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
507 * the outer transaction is ended all of the work done in that transaction
508 * and all of the nested transactions will be committed or rolled back. The
509 * changes will be rolled back if any transaction is ended without being
510 * marked as clean (by calling setTransactionSuccessful). Otherwise they
511 * will be committed.
512 * <p>
513 * Here is the standard idiom for transactions:
514 *
515 * <pre>
516 * db.beginTransactionWithListenerNonExclusive(listener);
517 * try {
518 * ...
519 * db.setTransactionSuccessful();
520 * } finally {
521 * db.endTransaction();
522 * }
523 * </pre>
524 *
525 * @param transactionListener listener that should be notified when the
526 * transaction begins, commits, or is rolled back, either
527 * explicitly or by a call to {@link #yieldIfContendedSafely}.
528 */
529 public void beginTransactionWithListenerNonExclusive(
530 SQLiteTransactionListener transactionListener) {
531 beginTransaction(transactionListener, false);
532 }
533
534 private void beginTransaction(SQLiteTransactionListener transactionListener,
535 boolean exclusive) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800536 acquireReference();
537 try {
538 getThreadSession().beginTransaction(
539 exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
540 SQLiteSession.TRANSACTION_MODE_IMMEDIATE,
541 transactionListener,
542 getThreadDefaultConnectionFlags(false /*readOnly*/), null);
543 } finally {
544 releaseReference();
545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 }
547
548 /**
549 * End a transaction. See beginTransaction for notes about how to use this and when transactions
550 * are committed and rolled back.
551 */
552 public void endTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800553 acquireReference();
554 try {
555 getThreadSession().endTransaction(null);
556 } finally {
557 releaseReference();
558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559 }
560
561 /**
562 * Marks the current transaction as successful. Do not do any more database work between
563 * calling this and calling endTransaction. Do as little non-database work as possible in that
564 * situation too. If any errors are encountered between this and endTransaction the transaction
565 * will still be committed.
566 *
567 * @throws IllegalStateException if the current thread is not in a transaction or the
568 * transaction is already marked as successful.
569 */
570 public void setTransactionSuccessful() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800571 acquireReference();
572 try {
573 getThreadSession().setTransactionSuccessful();
574 } finally {
575 releaseReference();
576 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 }
578
579 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700580 * Returns true if the current thread has a transaction pending.
581 *
582 * @return True if the current thread is in a transaction.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 */
584 public boolean inTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800585 acquireReference();
586 try {
587 return getThreadSession().hasTransaction();
588 } finally {
589 releaseReference();
590 }
Vasu Norice38b982010-07-22 13:57:13 -0700591 }
592
593 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700594 * Returns true if the current thread is holding an active connection to the database.
Vasu Norice38b982010-07-22 13:57:13 -0700595 * <p>
Jeff Browne5360fb2011-10-31 17:48:13 -0700596 * The name of this method comes from a time when having an active connection
597 * to the database meant that the thread was holding an actual lock on the
598 * database. Nowadays, there is no longer a true "database lock" although threads
599 * may block if they cannot acquire a database connection to perform a
600 * particular operation.
601 * </p>
Vasu Norice38b982010-07-22 13:57:13 -0700602 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700603 * @return True if the current thread is holding an active connection to the database.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 */
605 public boolean isDbLockedByCurrentThread() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800606 acquireReference();
607 try {
608 return getThreadSession().hasConnection();
609 } finally {
610 releaseReference();
611 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 }
613
614 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700615 * Always returns false.
616 * <p>
617 * There is no longer the concept of a database lock, so this method always returns false.
618 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700620 * @return False.
621 * @deprecated Always returns false. Do not use this method.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800622 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700623 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 public boolean isDbLockedByOtherThreads() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700625 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 }
627
628 /**
629 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
630 * successful so far. Do not call setTransactionSuccessful before calling this. When this
631 * returns a new transaction will have been created but not marked as successful.
632 * @return true if the transaction was yielded
633 * @deprecated if the db is locked more than once (becuase of nested transactions) then the lock
634 * will not be yielded. Use yieldIfContendedSafely instead.
635 */
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700636 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637 public boolean yieldIfContended() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700638 return yieldIfContendedHelper(false /* do not check yielding */,
639 -1 /* sleepAfterYieldDelay */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640 }
641
642 /**
643 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
644 * successful so far. Do not call setTransactionSuccessful before calling this. When this
645 * returns a new transaction will have been created but not marked as successful. This assumes
646 * that there are no nested transactions (beginTransaction has only been called once) and will
Fred Quintana5c7aede2009-08-27 21:41:27 -0700647 * throw an exception if that is not the case.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648 * @return true if the transaction was yielded
649 */
650 public boolean yieldIfContendedSafely() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700651 return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652 }
653
Fred Quintana5c7aede2009-08-27 21:41:27 -0700654 /**
655 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
656 * successful so far. Do not call setTransactionSuccessful before calling this. When this
657 * returns a new transaction will have been created but not marked as successful. This assumes
658 * that there are no nested transactions (beginTransaction has only been called once) and will
659 * throw an exception if that is not the case.
660 * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if
661 * the lock was actually yielded. This will allow other background threads to make some
662 * more progress than they would if we started the transaction immediately.
663 * @return true if the transaction was yielded
664 */
665 public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
666 return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay);
667 }
668
Jeff Browne5360fb2011-10-31 17:48:13 -0700669 private boolean yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800670 acquireReference();
671 try {
672 return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null);
673 } finally {
674 releaseReference();
675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 }
677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700679 * Deprecated.
Vasu Nori95675132010-07-21 16:24:40 -0700680 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 */
Vasu Nori95675132010-07-21 16:24:40 -0700682 @Deprecated
683 public Map<String, String> getSyncedTables() {
684 return new HashMap<String, String>(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685 }
686
687 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 * Open the database according to the flags {@link #OPEN_READWRITE}
689 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
690 *
691 * <p>Sets the locale of the database to the the system's current locale.
692 * Call {@link #setLocale} if you would like something else.</p>
693 *
694 * @param path to database file to open and/or create
695 * @param factory an optional factory class that is called to instantiate a
696 * cursor when query is called, or null for default
697 * @param flags to control database access mode
698 * @return the newly opened database
699 * @throws SQLiteException if the database cannot be opened
700 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700701 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
702 @DatabaseOpenFlags int flags) {
Jeff Brown47847f32012-03-22 19:13:11 -0700703 return openDatabase(path, factory, flags, null);
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700704 }
705
706 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700707 * Open the database according to the specified {@link OpenParams parameters}
708 *
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700709 * @param path path to database file to open and/or create.
710 * <p><strong>Important:</strong> The file should be constructed either from an absolute path or
711 * by using {@link android.content.Context#getDatabasePath(String)}.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700712 * @param openParams configuration parameters that are used for opening {@link SQLiteDatabase}
713 * @return the newly opened database
714 * @throws SQLiteException if the database cannot be opened
715 */
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700716 public static SQLiteDatabase openDatabase(@NonNull File path,
717 @NonNull OpenParams openParams) {
718 return openDatabase(path.getPath(), openParams);
719 }
720
721 private static SQLiteDatabase openDatabase(@NonNull String path,
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700722 @NonNull OpenParams openParams) {
723 Preconditions.checkArgument(openParams != null, "OpenParams cannot be null");
724 SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags,
725 openParams.mCursorFactory, openParams.mErrorHandler,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700726 openParams.mLookasideSlotSize, openParams.mLookasideSlotCount,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800727 openParams.mIdleConnectionTimeout, openParams.mJournalMode, openParams.mSyncMode);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700728 db.open();
729 return db;
730 }
731
732 /**
Vasu Nori74f170f2010-06-01 18:06:18 -0700733 * Open the database according to the flags {@link #OPEN_READWRITE}
734 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
735 *
736 * <p>Sets the locale of the database to the the system's current locale.
737 * Call {@link #setLocale} if you would like something else.</p>
738 *
739 * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be
740 * used to handle corruption when sqlite reports database corruption.</p>
741 *
742 * @param path to database file to open and/or create
743 * @param factory an optional factory class that is called to instantiate a
744 * cursor when query is called, or null for default
745 * @param flags to control database access mode
746 * @param errorHandler the {@link DatabaseErrorHandler} obj to be used to handle corruption
747 * when sqlite reports database corruption
748 * @return the newly opened database
749 * @throws SQLiteException if the database cannot be opened
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700750 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700751 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
752 @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler) {
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800753 SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1, -1, null,
754 null);
Jeff Browne5360fb2011-10-31 17:48:13 -0700755 db.open();
756 return db;
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700757 }
758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 /**
760 * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
761 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700762 public static SQLiteDatabase openOrCreateDatabase(@NonNull File file,
763 @Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800764 return openOrCreateDatabase(file.getPath(), factory);
765 }
766
767 /**
768 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
769 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700770 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
771 @Nullable CursorFactory factory) {
Jeff Brown47847f32012-03-22 19:13:11 -0700772 return openDatabase(path, factory, CREATE_IF_NECESSARY, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 }
774
775 /**
Vasu Nori6c354da2010-04-26 23:33:39 -0700776 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler).
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700777 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700778 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
779 @Nullable CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler) {
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700780 return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler);
781 }
782
Jeff Brown559d0642012-02-29 10:19:12 -0800783 /**
Jeff Brown79087e42012-03-01 19:52:44 -0800784 * Deletes a database including its journal file and other auxiliary files
785 * that may have been created by the database engine.
786 *
787 * @param file The database file path.
788 * @return True if the database was successfully deleted.
789 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700790 public static boolean deleteDatabase(@NonNull File file) {
Jeff Brown79087e42012-03-01 19:52:44 -0800791 if (file == null) {
792 throw new IllegalArgumentException("file must not be null");
793 }
794
795 boolean deleted = false;
796 deleted |= file.delete();
797 deleted |= new File(file.getPath() + "-journal").delete();
798 deleted |= new File(file.getPath() + "-shm").delete();
799 deleted |= new File(file.getPath() + "-wal").delete();
800
801 File dir = file.getParentFile();
802 if (dir != null) {
803 final String prefix = file.getName() + "-mj";
Jeff Brownfce58902014-01-24 13:20:57 -0800804 File[] files = dir.listFiles(new FileFilter() {
Jeff Brown79087e42012-03-01 19:52:44 -0800805 @Override
806 public boolean accept(File candidate) {
807 return candidate.getName().startsWith(prefix);
808 }
Jeff Brownfce58902014-01-24 13:20:57 -0800809 });
810 if (files != null) {
811 for (File masterJournal : files) {
812 deleted |= masterJournal.delete();
813 }
Jeff Brown79087e42012-03-01 19:52:44 -0800814 }
815 }
816 return deleted;
817 }
818
819 /**
Jeff Brown559d0642012-02-29 10:19:12 -0800820 * Reopens the database in read-write mode.
821 * If the database is already read-write, does nothing.
822 *
823 * @throws SQLiteException if the database could not be reopened as requested, in which
824 * case it remains open in read only mode.
825 * @throws IllegalStateException if the database is not open.
826 *
827 * @see #isReadOnly()
828 * @hide
829 */
830 public void reopenReadWrite() {
831 synchronized (mLock) {
832 throwIfNotOpenLocked();
833
834 if (!isReadOnlyLocked()) {
835 return; // nothing to do
836 }
837
838 // Reopen the database in read-write mode.
839 final int oldOpenFlags = mConfigurationLocked.openFlags;
840 mConfigurationLocked.openFlags = (mConfigurationLocked.openFlags & ~OPEN_READ_MASK)
841 | OPEN_READWRITE;
842 try {
843 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
844 } catch (RuntimeException ex) {
845 mConfigurationLocked.openFlags = oldOpenFlags;
846 throw ex;
847 }
848 }
849 }
850
Jeff Browne5360fb2011-10-31 17:48:13 -0700851 private void open() {
852 try {
853 try {
854 openInner();
855 } catch (SQLiteDatabaseCorruptException ex) {
856 onCorruption();
857 openInner();
858 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700859 } catch (SQLiteException ex) {
860 Log.e(TAG, "Failed to open database '" + getLabel() + "'.", ex);
861 close();
862 throw ex;
863 }
864 }
865
866 private void openInner() {
867 synchronized (mLock) {
868 assert mConnectionPoolLocked == null;
869 mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked);
870 mCloseGuardLocked.open("close");
871 }
872
873 synchronized (sActiveDatabases) {
874 sActiveDatabases.put(this, null);
875 }
876 }
877
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700878 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 * Create a memory backed SQLite database. Its contents will be destroyed
880 * when the database is closed.
881 *
882 * <p>Sets the locale of the database to the the system's current locale.
883 * Call {@link #setLocale} if you would like something else.</p>
884 *
885 * @param factory an optional factory class that is called to instantiate a
886 * cursor when query is called
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700887 * @return a SQLiteDatabase instance
888 * @throws SQLiteException if the database cannot be created
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800889 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700890 @NonNull
891 public static SQLiteDatabase create(@Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892 // This is a magic string with special meaning for SQLite.
Jeff Browne5360fb2011-10-31 17:48:13 -0700893 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
894 factory, CREATE_IF_NECESSARY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 }
896
897 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700898 * Create a memory backed SQLite database. Its contents will be destroyed
899 * when the database is closed.
900 *
901 * <p>Sets the locale of the database to the the system's current locale.
902 * Call {@link #setLocale} if you would like something else.</p>
903 * @param openParams configuration parameters that are used for opening SQLiteDatabase
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700904 * @return a SQLiteDatabase instance
905 * @throws SQLException if the database cannot be created
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700906 */
907 @NonNull
908 public static SQLiteDatabase createInMemory(@NonNull OpenParams openParams) {
909 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
910 openParams.toBuilder().addOpenFlags(CREATE_IF_NECESSARY).build());
911 }
912
913 /**
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400914 * Registers a CustomFunction callback as a function that can be called from
Jeff Browne5360fb2011-10-31 17:48:13 -0700915 * SQLite database triggers.
916 *
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400917 * @param name the name of the sqlite3 function
918 * @param numArgs the number of arguments for the function
919 * @param function callback to call when the function is executed
920 * @hide
921 */
922 public void addCustomFunction(String name, int numArgs, CustomFunction function) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700923 // Create wrapper (also validates arguments).
924 SQLiteCustomFunction wrapper = new SQLiteCustomFunction(name, numArgs, function);
925
926 synchronized (mLock) {
927 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -0700928
Jeff Browne5360fb2011-10-31 17:48:13 -0700929 mConfigurationLocked.customFunctions.add(wrapper);
Jeff Browne67ca422012-03-21 17:24:05 -0700930 try {
931 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
932 } catch (RuntimeException ex) {
933 mConfigurationLocked.customFunctions.remove(wrapper);
934 throw ex;
935 }
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400936 }
937 }
938
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400939 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800940 * Gets the database version.
941 *
942 * @return the database version
943 */
944 public int getVersion() {
Vasu Noriccd95442010-05-28 17:04:16 -0700945 return ((Long) DatabaseUtils.longForQuery(this, "PRAGMA user_version;", null)).intValue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 }
947
948 /**
949 * Sets the database version.
950 *
951 * @param version the new database version
952 */
953 public void setVersion(int version) {
954 execSQL("PRAGMA user_version = " + version);
955 }
956
957 /**
958 * Returns the maximum size the database may grow to.
959 *
960 * @return the new maximum database size
961 */
962 public long getMaximumSize() {
Vasu Noriccd95442010-05-28 17:04:16 -0700963 long pageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count;", null);
964 return pageCount * getPageSize();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 }
966
967 /**
968 * Sets the maximum size the database will grow to. The maximum size cannot
969 * be set below the current size.
970 *
971 * @param numBytes the maximum database size, in bytes
972 * @return the new maximum database size
973 */
974 public long setMaximumSize(long numBytes) {
Vasu Noriccd95442010-05-28 17:04:16 -0700975 long pageSize = getPageSize();
976 long numPages = numBytes / pageSize;
977 // If numBytes isn't a multiple of pageSize, bump up a page
978 if ((numBytes % pageSize) != 0) {
979 numPages++;
Vasu Norif3cf8a42010-03-23 11:41:44 -0700980 }
Vasu Noriccd95442010-05-28 17:04:16 -0700981 long newPageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count = " + numPages,
982 null);
983 return newPageCount * pageSize;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 }
985
986 /**
987 * Returns the current database page size, in bytes.
988 *
989 * @return the database page size, in bytes
990 */
991 public long getPageSize() {
Vasu Noriccd95442010-05-28 17:04:16 -0700992 return DatabaseUtils.longForQuery(this, "PRAGMA page_size;", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 }
994
995 /**
996 * Sets the database page size. The page size must be a power of two. This
997 * method does not work if any data has been written to the database file,
998 * and must be called right after the database has been created.
999 *
1000 * @param numBytes the database page size, in bytes
1001 */
1002 public void setPageSize(long numBytes) {
1003 execSQL("PRAGMA page_size = " + numBytes);
1004 }
1005
1006 /**
1007 * Mark this table as syncable. When an update occurs in this table the
1008 * _sync_dirty field will be set to ensure proper syncing operation.
1009 *
1010 * @param table the table to mark as syncable
1011 * @param deletedTable The deleted table that corresponds to the
1012 * syncable table
Vasu Nori95675132010-07-21 16:24:40 -07001013 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 */
Vasu Nori95675132010-07-21 16:24:40 -07001015 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 public void markTableSyncable(String table, String deletedTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 }
1018
1019 /**
1020 * Mark this table as syncable, with the _sync_dirty residing in another
1021 * table. When an update occurs in this table the _sync_dirty field of the
1022 * row in updateTable with the _id in foreignKey will be set to
1023 * ensure proper syncing operation.
1024 *
1025 * @param table an update on this table will trigger a sync time removal
1026 * @param foreignKey this is the column in table whose value is an _id in
1027 * updateTable
1028 * @param updateTable this is the table that will have its _sync_dirty
Vasu Nori95675132010-07-21 16:24:40 -07001029 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 */
Vasu Nori95675132010-07-21 16:24:40 -07001031 @Deprecated
1032 public void markTableSyncable(String table, String foreignKey, String updateTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 }
1034
1035 /**
1036 * Finds the name of the first table, which is editable.
1037 *
1038 * @param tables a list of tables
1039 * @return the first table listed
1040 */
1041 public static String findEditTable(String tables) {
1042 if (!TextUtils.isEmpty(tables)) {
1043 // find the first word terminated by either a space or a comma
1044 int spacepos = tables.indexOf(' ');
1045 int commapos = tables.indexOf(',');
1046
1047 if (spacepos > 0 && (spacepos < commapos || commapos < 0)) {
1048 return tables.substring(0, spacepos);
1049 } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) {
1050 return tables.substring(0, commapos);
1051 }
1052 return tables;
1053 } else {
1054 throw new IllegalStateException("Invalid tables");
1055 }
1056 }
1057
1058 /**
1059 * Compiles an SQL statement into a reusable pre-compiled statement object.
1060 * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the
1061 * statement and fill in those values with {@link SQLiteProgram#bindString}
1062 * and {@link SQLiteProgram#bindLong} each time you want to run the
1063 * statement. Statements may not return result sets larger than 1x1.
Vasu Nori2827d6d2010-07-04 00:26:18 -07001064 *<p>
1065 * No two threads should be using the same {@link SQLiteStatement} at the same time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 *
1067 * @param sql The raw SQL statement, may contain ? for unknown values to be
1068 * bound later.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001069 * @return A pre-compiled {@link SQLiteStatement} object. Note that
1070 * {@link SQLiteStatement}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 */
1072 public SQLiteStatement compileStatement(String sql) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001073 acquireReference();
1074 try {
1075 return new SQLiteStatement(this, sql, null);
1076 } finally {
1077 releaseReference();
1078 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079 }
1080
1081 /**
1082 * Query the given URL, returning a {@link Cursor} over the result set.
1083 *
1084 * @param distinct true if you want each row to be unique, false otherwise.
1085 * @param table The table name to compile the query against.
1086 * @param columns A list of which columns to return. Passing null will
1087 * return all columns, which is discouraged to prevent reading
1088 * data from storage that isn't going to be used.
1089 * @param selection A filter declaring which rows to return, formatted as an
1090 * SQL WHERE clause (excluding the WHERE itself). Passing null
1091 * will return all rows for the given table.
1092 * @param selectionArgs You may include ?s in selection, which will be
1093 * replaced by the values from selectionArgs, in order that they
1094 * appear in the selection. The values will be bound as Strings.
1095 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1096 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1097 * will cause the rows to not be grouped.
1098 * @param having A filter declare which row groups to include in the cursor,
1099 * if row grouping is being used, formatted as an SQL HAVING
1100 * clause (excluding the HAVING itself). Passing null will cause
1101 * all row groups to be included, and is required when row
1102 * grouping is not being used.
1103 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1104 * (excluding the ORDER BY itself). Passing null will use the
1105 * default sort order, which may be unordered.
1106 * @param limit Limits the number of rows returned by the query,
1107 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001108 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1109 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 * @see Cursor
1111 */
1112 public Cursor query(boolean distinct, String table, String[] columns,
1113 String selection, String[] selectionArgs, String groupBy,
1114 String having, String orderBy, String limit) {
1115 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown75ea64f2012-01-25 19:37:13 -08001116 groupBy, having, orderBy, limit, null);
1117 }
1118
1119 /**
1120 * Query the given URL, returning a {@link Cursor} over the result set.
1121 *
1122 * @param distinct true if you want each row to be unique, false otherwise.
1123 * @param table The table name to compile the query against.
1124 * @param columns A list of which columns to return. Passing null will
1125 * return all columns, which is discouraged to prevent reading
1126 * data from storage that isn't going to be used.
1127 * @param selection A filter declaring which rows to return, formatted as an
1128 * SQL WHERE clause (excluding the WHERE itself). Passing null
1129 * will return all rows for the given table.
1130 * @param selectionArgs You may include ?s in selection, which will be
1131 * replaced by the values from selectionArgs, in order that they
1132 * appear in the selection. The values will be bound as Strings.
1133 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1134 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1135 * will cause the rows to not be grouped.
1136 * @param having A filter declare which row groups to include in the cursor,
1137 * if row grouping is being used, formatted as an SQL HAVING
1138 * clause (excluding the HAVING itself). Passing null will cause
1139 * all row groups to be included, and is required when row
1140 * grouping is not being used.
1141 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1142 * (excluding the ORDER BY itself). Passing null will use the
1143 * default sort order, which may be unordered.
1144 * @param limit Limits the number of rows returned by the query,
1145 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001146 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001147 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1148 * when the query is executed.
1149 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1150 * {@link Cursor}s are not synchronized, see the documentation for more details.
1151 * @see Cursor
1152 */
1153 public Cursor query(boolean distinct, String table, String[] columns,
1154 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001155 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001156 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001157 groupBy, having, orderBy, limit, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158 }
1159
1160 /**
1161 * Query the given URL, returning a {@link Cursor} over the result set.
1162 *
1163 * @param cursorFactory the cursor factory to use, or null for the default factory
1164 * @param distinct true if you want each row to be unique, false otherwise.
1165 * @param table The table name to compile the query against.
1166 * @param columns A list of which columns to return. Passing null will
1167 * return all columns, which is discouraged to prevent reading
1168 * data from storage that isn't going to be used.
1169 * @param selection A filter declaring which rows to return, formatted as an
1170 * SQL WHERE clause (excluding the WHERE itself). Passing null
1171 * will return all rows for the given table.
1172 * @param selectionArgs You may include ?s in selection, which will be
1173 * replaced by the values from selectionArgs, in order that they
1174 * appear in the selection. The values will be bound as Strings.
1175 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1176 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1177 * will cause the rows to not be grouped.
1178 * @param having A filter declare which row groups to include in the cursor,
1179 * if row grouping is being used, formatted as an SQL HAVING
1180 * clause (excluding the HAVING itself). Passing null will cause
1181 * all row groups to be included, and is required when row
1182 * grouping is not being used.
1183 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1184 * (excluding the ORDER BY itself). Passing null will use the
1185 * default sort order, which may be unordered.
1186 * @param limit Limits the number of rows returned by the query,
1187 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001188 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1189 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 * @see Cursor
1191 */
1192 public Cursor queryWithFactory(CursorFactory cursorFactory,
1193 boolean distinct, String table, String[] columns,
1194 String selection, String[] selectionArgs, String groupBy,
1195 String having, String orderBy, String limit) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001196 return queryWithFactory(cursorFactory, distinct, table, columns, selection,
1197 selectionArgs, groupBy, having, orderBy, limit, null);
1198 }
1199
1200 /**
1201 * Query the given URL, returning a {@link Cursor} over the result set.
1202 *
1203 * @param cursorFactory the cursor factory to use, or null for the default factory
1204 * @param distinct true if you want each row to be unique, false otherwise.
1205 * @param table The table name to compile the query against.
1206 * @param columns A list of which columns to return. Passing null will
1207 * return all columns, which is discouraged to prevent reading
1208 * data from storage that isn't going to be used.
1209 * @param selection A filter declaring which rows to return, formatted as an
1210 * SQL WHERE clause (excluding the WHERE itself). Passing null
1211 * will return all rows for the given table.
1212 * @param selectionArgs You may include ?s in selection, which will be
1213 * replaced by the values from selectionArgs, in order that they
1214 * appear in the selection. The values will be bound as Strings.
1215 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1216 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1217 * will cause the rows to not be grouped.
1218 * @param having A filter declare which row groups to include in the cursor,
1219 * if row grouping is being used, formatted as an SQL HAVING
1220 * clause (excluding the HAVING itself). Passing null will cause
1221 * all row groups to be included, and is required when row
1222 * grouping is not being used.
1223 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1224 * (excluding the ORDER BY itself). Passing null will use the
1225 * default sort order, which may be unordered.
1226 * @param limit Limits the number of rows returned by the query,
1227 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001228 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001229 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1230 * when the query is executed.
1231 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1232 * {@link Cursor}s are not synchronized, see the documentation for more details.
1233 * @see Cursor
1234 */
1235 public Cursor queryWithFactory(CursorFactory cursorFactory,
1236 boolean distinct, String table, String[] columns,
1237 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001238 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001239 acquireReference();
1240 try {
1241 String sql = SQLiteQueryBuilder.buildQueryString(
1242 distinct, table, columns, selection, groupBy, having, orderBy, limit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243
Jeff Brown03bd3022012-03-06 13:48:56 -08001244 return rawQueryWithFactory(cursorFactory, sql, selectionArgs,
1245 findEditTable(table), cancellationSignal);
1246 } finally {
1247 releaseReference();
1248 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 }
1250
1251 /**
1252 * Query the given table, returning a {@link Cursor} over the result set.
1253 *
1254 * @param table The table name to compile the query against.
1255 * @param columns A list of which columns to return. Passing null will
1256 * return all columns, which is discouraged to prevent reading
1257 * data from storage that isn't going to be used.
1258 * @param selection A filter declaring which rows to return, formatted as an
1259 * SQL WHERE clause (excluding the WHERE itself). Passing null
1260 * will return all rows for the given table.
1261 * @param selectionArgs You may include ?s in selection, which will be
1262 * replaced by the values from selectionArgs, in order that they
1263 * appear in the selection. The values will be bound as Strings.
1264 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1265 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1266 * will cause the rows to not be grouped.
1267 * @param having A filter declare which row groups to include in the cursor,
1268 * if row grouping is being used, formatted as an SQL HAVING
1269 * clause (excluding the HAVING itself). Passing null will cause
1270 * all row groups to be included, and is required when row
1271 * grouping is not being used.
1272 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1273 * (excluding the ORDER BY itself). Passing null will use the
1274 * default sort order, which may be unordered.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001275 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1276 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001277 * @see Cursor
1278 */
1279 public Cursor query(String table, String[] columns, String selection,
1280 String[] selectionArgs, String groupBy, String having,
1281 String orderBy) {
1282
1283 return query(false, table, columns, selection, selectionArgs, groupBy,
1284 having, orderBy, null /* limit */);
1285 }
1286
1287 /**
1288 * Query the given table, returning a {@link Cursor} over the result set.
1289 *
1290 * @param table The table name to compile the query against.
1291 * @param columns A list of which columns to return. Passing null will
1292 * return all columns, which is discouraged to prevent reading
1293 * data from storage that isn't going to be used.
1294 * @param selection A filter declaring which rows to return, formatted as an
1295 * SQL WHERE clause (excluding the WHERE itself). Passing null
1296 * will return all rows for the given table.
1297 * @param selectionArgs You may include ?s in selection, which will be
1298 * replaced by the values from selectionArgs, in order that they
1299 * appear in the selection. The values will be bound as Strings.
1300 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1301 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1302 * will cause the rows to not be grouped.
1303 * @param having A filter declare which row groups to include in the cursor,
1304 * if row grouping is being used, formatted as an SQL HAVING
1305 * clause (excluding the HAVING itself). Passing null will cause
1306 * all row groups to be included, and is required when row
1307 * grouping is not being used.
1308 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1309 * (excluding the ORDER BY itself). Passing null will use the
1310 * default sort order, which may be unordered.
1311 * @param limit Limits the number of rows returned by the query,
1312 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001313 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1314 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001315 * @see Cursor
1316 */
1317 public Cursor query(String table, String[] columns, String selection,
1318 String[] selectionArgs, String groupBy, String having,
1319 String orderBy, String limit) {
1320
1321 return query(false, table, columns, selection, selectionArgs, groupBy,
1322 having, orderBy, limit);
1323 }
1324
1325 /**
1326 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1327 *
1328 * @param sql the SQL query. The SQL string must not be ; terminated
1329 * @param selectionArgs You may include ?s in where clause in the query,
1330 * which will be replaced by the values from selectionArgs. The
1331 * values will be bound as Strings.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001332 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1333 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001334 */
1335 public Cursor rawQuery(String sql, String[] selectionArgs) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001336 return rawQueryWithFactory(null, sql, selectionArgs, null, null);
1337 }
1338
1339 /**
1340 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1341 *
1342 * @param sql the SQL query. The SQL string must not be ; terminated
1343 * @param selectionArgs You may include ?s in where clause in the query,
1344 * which will be replaced by the values from selectionArgs. The
1345 * values will be bound as Strings.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001346 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001347 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1348 * when the query is executed.
1349 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1350 * {@link Cursor}s are not synchronized, see the documentation for more details.
1351 */
1352 public Cursor rawQuery(String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001353 CancellationSignal cancellationSignal) {
1354 return rawQueryWithFactory(null, sql, selectionArgs, null, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001355 }
1356
1357 /**
1358 * Runs the provided SQL and returns a cursor over the result set.
1359 *
1360 * @param cursorFactory the cursor factory to use, or null for the default factory
1361 * @param sql the SQL query. The SQL string must not be ; terminated
1362 * @param selectionArgs You may include ?s in where clause in the query,
1363 * which will be replaced by the values from selectionArgs. The
1364 * values will be bound as Strings.
1365 * @param editTable the name of the first table, which is editable
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001366 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1367 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 */
1369 public Cursor rawQueryWithFactory(
1370 CursorFactory cursorFactory, String sql, String[] selectionArgs,
1371 String editTable) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001372 return rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable, null);
1373 }
1374
1375 /**
1376 * Runs the provided SQL and returns a cursor over the result set.
1377 *
1378 * @param cursorFactory the cursor factory to use, or null for the default factory
1379 * @param sql the SQL query. The SQL string must not be ; terminated
1380 * @param selectionArgs You may include ?s in where clause in the query,
1381 * which will be replaced by the values from selectionArgs. The
1382 * values will be bound as Strings.
1383 * @param editTable the name of the first table, which is editable
Jeff Brown4c1241d2012-02-02 17:05:00 -08001384 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001385 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1386 * when the query is executed.
1387 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1388 * {@link Cursor}s are not synchronized, see the documentation for more details.
1389 */
1390 public Cursor rawQueryWithFactory(
1391 CursorFactory cursorFactory, String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001392 String editTable, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001393 acquireReference();
1394 try {
1395 SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
1396 cancellationSignal);
1397 return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
1398 selectionArgs);
1399 } finally {
1400 releaseReference();
1401 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 }
1403
1404 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 * Convenience method for inserting a row into the database.
1406 *
1407 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001408 * @param nullColumnHack optional; may be <code>null</code>.
1409 * SQL doesn't allow inserting a completely empty row without
1410 * naming at least one column name. If your provided <code>values</code> is
1411 * empty, no column names are known and an empty row can't be inserted.
1412 * If not set to null, the <code>nullColumnHack</code> parameter
1413 * provides the name of nullable column name to explicitly insert a NULL into
1414 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001415 * @param values this map contains the initial column values for the
1416 * row. The keys should be the column names and the values the
1417 * column values
1418 * @return the row ID of the newly inserted row, or -1 if an error occurred
1419 */
1420 public long insert(String table, String nullColumnHack, ContentValues values) {
1421 try {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001422 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 } catch (SQLException e) {
1424 Log.e(TAG, "Error inserting " + values, e);
1425 return -1;
1426 }
1427 }
1428
1429 /**
1430 * Convenience method for inserting a row into the database.
1431 *
1432 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001433 * @param nullColumnHack optional; may be <code>null</code>.
1434 * SQL doesn't allow inserting a completely empty row without
1435 * naming at least one column name. If your provided <code>values</code> is
1436 * empty, no column names are known and an empty row can't be inserted.
1437 * If not set to null, the <code>nullColumnHack</code> parameter
1438 * provides the name of nullable column name to explicitly insert a NULL into
1439 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 * @param values this map contains the initial column values for the
1441 * row. The keys should be the column names and the values the
1442 * column values
1443 * @throws SQLException
1444 * @return the row ID of the newly inserted row, or -1 if an error occurred
1445 */
1446 public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
1447 throws SQLException {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001448 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 }
1450
1451 /**
1452 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001453 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 *
1455 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001456 * @param nullColumnHack optional; may be <code>null</code>.
1457 * SQL doesn't allow inserting a completely empty row without
1458 * naming at least one column name. If your provided <code>initialValues</code> is
1459 * empty, no column names are known and an empty row can't be inserted.
1460 * If not set to null, the <code>nullColumnHack</code> parameter
1461 * provides the name of nullable column name to explicitly insert a NULL into
1462 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001464 * 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 -08001465 * @return the row ID of the newly inserted row, or -1 if an error occurred
1466 */
1467 public long replace(String table, String nullColumnHack, ContentValues initialValues) {
1468 try {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001469 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001470 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 } catch (SQLException e) {
1472 Log.e(TAG, "Error inserting " + initialValues, e);
1473 return -1;
1474 }
1475 }
1476
1477 /**
1478 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001479 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 *
1481 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001482 * @param nullColumnHack optional; may be <code>null</code>.
1483 * SQL doesn't allow inserting a completely empty row without
1484 * naming at least one column name. If your provided <code>initialValues</code> is
1485 * empty, no column names are known and an empty row can't be inserted.
1486 * If not set to null, the <code>nullColumnHack</code> parameter
1487 * provides the name of nullable column name to explicitly insert a NULL into
1488 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001490 * 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 -08001491 * @throws SQLException
1492 * @return the row ID of the newly inserted row, or -1 if an error occurred
1493 */
1494 public long replaceOrThrow(String table, String nullColumnHack,
1495 ContentValues initialValues) throws SQLException {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001496 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001497 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001498 }
1499
1500 /**
1501 * General method for inserting a row into the database.
1502 *
1503 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001504 * @param nullColumnHack optional; may be <code>null</code>.
1505 * SQL doesn't allow inserting a completely empty row without
1506 * naming at least one column name. If your provided <code>initialValues</code> is
1507 * empty, no column names are known and an empty row can't be inserted.
1508 * If not set to null, the <code>nullColumnHack</code> parameter
1509 * provides the name of nullable column name to explicitly insert a NULL into
1510 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 * @param initialValues this map contains the initial column values for the
1512 * row. The keys should be the column names and the values the
1513 * column values
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001514 * @param conflictAlgorithm for insert conflict resolver
Steve Pomeroyc240b602013-03-14 00:42:10 -04001515 * @return the row ID of the newly inserted row OR <code>-1</code> if either the
1516 * input parameter <code>conflictAlgorithm</code> = {@link #CONFLICT_IGNORE}
1517 * or an error occurred.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 */
1519 public long insertWithOnConflict(String table, String nullColumnHack,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001520 ContentValues initialValues, int conflictAlgorithm) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001521 acquireReference();
1522 try {
1523 StringBuilder sql = new StringBuilder();
1524 sql.append("INSERT");
1525 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1526 sql.append(" INTO ");
1527 sql.append(table);
1528 sql.append('(');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529
Jeff Brown03bd3022012-03-06 13:48:56 -08001530 Object[] bindArgs = null;
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001531 int size = (initialValues != null && !initialValues.isEmpty())
Jeff Brown03bd3022012-03-06 13:48:56 -08001532 ? initialValues.size() : 0;
1533 if (size > 0) {
1534 bindArgs = new Object[size];
1535 int i = 0;
1536 for (String colName : initialValues.keySet()) {
1537 sql.append((i > 0) ? "," : "");
1538 sql.append(colName);
1539 bindArgs[i++] = initialValues.get(colName);
1540 }
1541 sql.append(')');
1542 sql.append(" VALUES (");
1543 for (i = 0; i < size; i++) {
1544 sql.append((i > 0) ? ",?" : "?");
1545 }
1546 } else {
1547 sql.append(nullColumnHack + ") VALUES (NULL");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 sql.append(')');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550
Jeff Brown03bd3022012-03-06 13:48:56 -08001551 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1552 try {
1553 return statement.executeInsert();
1554 } finally {
1555 statement.close();
1556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001557 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001558 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 }
1560 }
1561
1562 /**
1563 * Convenience method for deleting rows in the database.
1564 *
1565 * @param table the table to delete from
1566 * @param whereClause the optional WHERE clause to apply when deleting.
1567 * Passing null will delete all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001568 * @param whereArgs You may include ?s in the where clause, which
1569 * will be replaced by the values from whereArgs. The values
1570 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 * @return the number of rows affected if a whereClause is passed in, 0
1572 * otherwise. To remove all rows and get a count pass "1" as the
1573 * whereClause.
1574 */
1575 public int delete(String table, String whereClause, String[] whereArgs) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001576 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001578 SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table +
1579 (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
1580 try {
1581 return statement.executeUpdateDelete();
1582 } finally {
1583 statement.close();
1584 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001586 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 }
1588 }
1589
1590 /**
1591 * Convenience method for updating rows in the database.
1592 *
1593 * @param table the table to update in
1594 * @param values a map from column names to new column values. null is a
1595 * valid value that will be translated to NULL.
1596 * @param whereClause the optional WHERE clause to apply when updating.
1597 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001598 * @param whereArgs You may include ?s in the where clause, which
1599 * will be replaced by the values from whereArgs. The values
1600 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 * @return the number of rows affected
1602 */
1603 public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001604 return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 /**
1608 * Convenience method for updating rows in the database.
1609 *
1610 * @param table the table to update in
1611 * @param values a map from column names to new column values. null is a
1612 * valid value that will be translated to NULL.
1613 * @param whereClause the optional WHERE clause to apply when updating.
1614 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001615 * @param whereArgs You may include ?s in the where clause, which
1616 * will be replaced by the values from whereArgs. The values
1617 * will be bound as Strings.
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001618 * @param conflictAlgorithm for update conflict resolver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 * @return the number of rows affected
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 */
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001621 public int updateWithOnConflict(String table, ContentValues values,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001622 String whereClause, String[] whereArgs, int conflictAlgorithm) {
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001623 if (values == null || values.isEmpty()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 throw new IllegalArgumentException("Empty values");
1625 }
1626
Jeff Brown03bd3022012-03-06 13:48:56 -08001627 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001629 StringBuilder sql = new StringBuilder(120);
1630 sql.append("UPDATE ");
1631 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1632 sql.append(table);
1633 sql.append(" SET ");
1634
1635 // move all bind args to one array
1636 int setValuesSize = values.size();
1637 int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
1638 Object[] bindArgs = new Object[bindArgsSize];
1639 int i = 0;
1640 for (String colName : values.keySet()) {
1641 sql.append((i > 0) ? "," : "");
1642 sql.append(colName);
1643 bindArgs[i++] = values.get(colName);
1644 sql.append("=?");
1645 }
1646 if (whereArgs != null) {
1647 for (i = setValuesSize; i < bindArgsSize; i++) {
1648 bindArgs[i] = whereArgs[i - setValuesSize];
1649 }
1650 }
1651 if (!TextUtils.isEmpty(whereClause)) {
1652 sql.append(" WHERE ");
1653 sql.append(whereClause);
1654 }
1655
1656 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1657 try {
1658 return statement.executeUpdateDelete();
1659 } finally {
1660 statement.close();
1661 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001663 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664 }
1665 }
1666
1667 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001668 * Execute a single SQL statement that is NOT a SELECT
1669 * or any other SQL statement that returns data.
1670 * <p>
Vasu Norice38b982010-07-22 13:57:13 -07001671 * It has no means to return any data (such as the number of affected rows).
Vasu Noriccd95442010-05-28 17:04:16 -07001672 * Instead, you're encouraged to use {@link #insert(String, String, ContentValues)},
1673 * {@link #update(String, ContentValues, String, String[])}, et al, when possible.
1674 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001675 * <p>
1676 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1677 * automatically managed by this class. So, do not set journal_mode
1678 * using "PRAGMA journal_mode'<value>" statement if your app is using
1679 * {@link #enableWriteAheadLogging()}
1680 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001681 *
Vasu Noriccd95442010-05-28 17:04:16 -07001682 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1683 * not supported.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001684 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001686 public void execSQL(String sql) throws SQLException {
Vasu Nori16057fa2011-03-18 11:40:37 -07001687 executeSql(sql, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 }
1689
1690 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001691 * Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE.
1692 * <p>
1693 * For INSERT statements, use any of the following instead.
1694 * <ul>
1695 * <li>{@link #insert(String, String, ContentValues)}</li>
1696 * <li>{@link #insertOrThrow(String, String, ContentValues)}</li>
1697 * <li>{@link #insertWithOnConflict(String, String, ContentValues, int)}</li>
1698 * </ul>
1699 * <p>
1700 * For UPDATE statements, use any of the following instead.
1701 * <ul>
1702 * <li>{@link #update(String, ContentValues, String, String[])}</li>
1703 * <li>{@link #updateWithOnConflict(String, ContentValues, String, String[], int)}</li>
1704 * </ul>
1705 * <p>
1706 * For DELETE statements, use any of the following instead.
1707 * <ul>
1708 * <li>{@link #delete(String, String, String[])}</li>
1709 * </ul>
1710 * <p>
1711 * For example, the following are good candidates for using this method:
1712 * <ul>
1713 * <li>ALTER TABLE</li>
1714 * <li>CREATE or DROP table / trigger / view / index / virtual table</li>
1715 * <li>REINDEX</li>
1716 * <li>RELEASE</li>
1717 * <li>SAVEPOINT</li>
1718 * <li>PRAGMA that returns no data</li>
1719 * </ul>
1720 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001721 * <p>
1722 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1723 * automatically managed by this class. So, do not set journal_mode
1724 * using "PRAGMA journal_mode'<value>" statement if your app is using
1725 * {@link #enableWriteAheadLogging()}
1726 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 *
Vasu Noriccd95442010-05-28 17:04:16 -07001728 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1729 * not supported.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001730 * @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001731 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001732 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001733 public void execSQL(String sql, Object[] bindArgs) throws SQLException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001734 if (bindArgs == null) {
1735 throw new IllegalArgumentException("Empty bindArgs");
1736 }
Vasu Norib83cb7c2010-09-14 13:36:01 -07001737 executeSql(sql, bindArgs);
Vasu Norice38b982010-07-22 13:57:13 -07001738 }
1739
Vasu Nori54025902010-09-14 12:14:26 -07001740 private int executeSql(String sql, Object[] bindArgs) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001741 acquireReference();
1742 try {
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001743 final int statementType = DatabaseUtils.getSqlStatementType(sql);
1744 if (statementType == DatabaseUtils.STATEMENT_ATTACH) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001745 boolean disableWal = false;
1746 synchronized (mLock) {
1747 if (!mHasAttachedDbsLocked) {
1748 mHasAttachedDbsLocked = true;
1749 disableWal = true;
Fyodor Kupolovfd9c4a52017-07-13 15:36:57 -07001750 mConnectionPoolLocked.disableIdleConnectionHandler();
Jeff Brown03bd3022012-03-06 13:48:56 -08001751 }
1752 }
1753 if (disableWal) {
1754 disableWriteAheadLogging();
Jeff Browne5360fb2011-10-31 17:48:13 -07001755 }
1756 }
Jeff Browne5360fb2011-10-31 17:48:13 -07001757
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001758 try (SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs)) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001759 return statement.executeUpdateDelete();
1760 } finally {
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001761 // If schema was updated, close non-primary connections, otherwise they might
1762 // have outdated schema information
1763 if (statementType == DatabaseUtils.STATEMENT_DDL) {
1764 mConnectionPoolLocked.closeAvailableNonPrimaryConnectionsAndLogExceptions();
1765 }
Jeff Brown03bd3022012-03-06 13:48:56 -08001766 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001768 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 }
1771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 /**
Makoto Onuki17aa1b72015-12-16 14:02:01 -08001773 * Verifies that a SQL SELECT statement is valid by compiling it.
1774 * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
1775 *
1776 * @param sql SQL to be validated
1777 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
1778 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1779 * when the query is executed.
1780 * @throws SQLiteException if {@code sql} is invalid
1781 */
1782 public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal) {
1783 getThreadSession().prepare(sql,
1784 getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null);
1785 }
1786
1787 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001788 * Returns true if the database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001790 * @return True if database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791 */
1792 public boolean isReadOnly() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001793 synchronized (mLock) {
1794 return isReadOnlyLocked();
1795 }
1796 }
1797
1798 private boolean isReadOnlyLocked() {
1799 return (mConfigurationLocked.openFlags & OPEN_READ_MASK) == OPEN_READONLY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001800 }
1801
1802 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001803 * Returns true if the database is in-memory db.
1804 *
1805 * @return True if the database is in-memory.
1806 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001807 */
Jeff Browne5360fb2011-10-31 17:48:13 -07001808 public boolean isInMemoryDatabase() {
1809 synchronized (mLock) {
1810 return mConfigurationLocked.isInMemoryDb();
1811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 }
1813
Jeff Browne5360fb2011-10-31 17:48:13 -07001814 /**
1815 * Returns true if the database is currently open.
1816 *
1817 * @return True if the database is currently open (has not been closed).
1818 */
1819 public boolean isOpen() {
1820 synchronized (mLock) {
1821 return mConnectionPoolLocked != null;
1822 }
1823 }
1824
1825 /**
1826 * Returns true if the new version code is greater than the current database version.
1827 *
1828 * @param newVersion The new version code.
Mark Lu1e202082016-08-30 17:41:25 -07001829 * @return True if the new version code is greater than the current database version.
Jeff Browne5360fb2011-10-31 17:48:13 -07001830 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001831 public boolean needUpgrade(int newVersion) {
1832 return newVersion > getVersion();
1833 }
1834
1835 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001836 * Gets the path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001838 * @return The path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 */
1840 public final String getPath() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001841 synchronized (mLock) {
1842 return mConfigurationLocked.path;
Christopher Tatead9e8b12011-10-05 17:49:26 -07001843 }
Brad Fitzpatrick722802e2010-03-23 22:22:16 -07001844 }
1845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 /**
1847 * Sets the locale for this database. Does nothing if this database has
Jeff Brown1d9f7422012-03-15 14:32:32 -07001848 * the {@link #NO_LOCALIZED_COLLATORS} flag set or was opened read only.
Jeff Browne5360fb2011-10-31 17:48:13 -07001849 *
1850 * @param locale The new locale.
1851 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 * @throws SQLException if the locale could not be set. The most common reason
1853 * for this is that there is no collator available for the locale you requested.
1854 * In this case the database remains unchanged.
1855 */
1856 public void setLocale(Locale locale) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001857 if (locale == null) {
1858 throw new IllegalArgumentException("locale must not be null.");
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001859 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001860
Jeff Browne5360fb2011-10-31 17:48:13 -07001861 synchronized (mLock) {
1862 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001863
1864 final Locale oldLocale = mConfigurationLocked.locale;
Jeff Browne5360fb2011-10-31 17:48:13 -07001865 mConfigurationLocked.locale = locale;
Jeff Browne67ca422012-03-21 17:24:05 -07001866 try {
1867 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1868 } catch (RuntimeException ex) {
1869 mConfigurationLocked.locale = oldLocale;
1870 throw ex;
1871 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001872 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001873 }
1874
Vasu Norie495d1f2010-01-06 16:34:19 -08001875 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001876 * Sets the maximum size of the prepared-statement cache for this database.
Vasu Norie495d1f2010-01-06 16:34:19 -08001877 * (size of the cache = number of compiled-sql-statements stored in the cache).
Vasu Noriccd95442010-05-28 17:04:16 -07001878 *<p>
Vasu Norib729dcc2010-09-14 11:35:49 -07001879 * Maximum cache size can ONLY be increased from its current size (default = 10).
Vasu Noriccd95442010-05-28 17:04:16 -07001880 * If this method is called with smaller size than the current maximum value,
1881 * then IllegalStateException is thrown.
Vasu Norib729dcc2010-09-14 11:35:49 -07001882 *<p>
1883 * This method is thread-safe.
Vasu Norie495d1f2010-01-06 16:34:19 -08001884 *
Vasu Nori90a367262010-04-12 12:49:09 -07001885 * @param cacheSize the size of the cache. can be (0 to {@link #MAX_SQL_CACHE_SIZE})
Jeff Browne5360fb2011-10-31 17:48:13 -07001886 * @throws IllegalStateException if input cacheSize > {@link #MAX_SQL_CACHE_SIZE}.
Vasu Norie495d1f2010-01-06 16:34:19 -08001887 */
Vasu Nori54025902010-09-14 12:14:26 -07001888 public void setMaxSqlCacheSize(int cacheSize) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001889 if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) {
1890 throw new IllegalStateException(
1891 "expected value between 0 and " + MAX_SQL_CACHE_SIZE);
Vasu Nori587423a2010-09-27 18:18:34 -07001892 }
Vasu Nori587423a2010-09-27 18:18:34 -07001893
Jeff Browne5360fb2011-10-31 17:48:13 -07001894 synchronized (mLock) {
1895 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001896
1897 final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize;
Jeff Browne5360fb2011-10-31 17:48:13 -07001898 mConfigurationLocked.maxSqlCacheSize = cacheSize;
Jeff Browne67ca422012-03-21 17:24:05 -07001899 try {
1900 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1901 } catch (RuntimeException ex) {
1902 mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize;
1903 throw ex;
1904 }
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001905 }
1906 }
1907
Vasu Nori6c354da2010-04-26 23:33:39 -07001908 /**
Jeff Brown96496ad2012-03-23 14:38:06 -07001909 * Sets whether foreign key constraints are enabled for the database.
1910 * <p>
1911 * By default, foreign key constraints are not enforced by the database.
1912 * This method allows an application to enable foreign key constraints.
1913 * It must be called each time the database is opened to ensure that foreign
1914 * key constraints are enabled for the session.
1915 * </p><p>
1916 * A good time to call this method is right after calling {@link #openOrCreateDatabase}
1917 * or in the {@link SQLiteOpenHelper#onConfigure} callback.
1918 * </p><p>
1919 * When foreign key constraints are disabled, the database does not check whether
1920 * changes to the database will violate foreign key constraints. Likewise, when
1921 * foreign key constraints are disabled, the database will not execute cascade
1922 * delete or update triggers. As a result, it is possible for the database
1923 * state to become inconsistent. To perform a database integrity check,
1924 * call {@link #isDatabaseIntegrityOk}.
1925 * </p><p>
1926 * This method must not be called while a transaction is in progress.
1927 * </p><p>
1928 * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a>
1929 * for more details about foreign key constraint support.
1930 * </p>
1931 *
1932 * @param enable True to enable foreign key constraints, false to disable them.
1933 *
1934 * @throws IllegalStateException if the are transactions is in progress
1935 * when this method is called.
1936 */
1937 public void setForeignKeyConstraintsEnabled(boolean enable) {
1938 synchronized (mLock) {
1939 throwIfNotOpenLocked();
1940
1941 if (mConfigurationLocked.foreignKeyConstraintsEnabled == enable) {
1942 return;
1943 }
1944
1945 mConfigurationLocked.foreignKeyConstraintsEnabled = enable;
1946 try {
1947 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1948 } catch (RuntimeException ex) {
1949 mConfigurationLocked.foreignKeyConstraintsEnabled = !enable;
1950 throw ex;
1951 }
1952 }
1953 }
1954
1955 /**
Jeff Brown47847f32012-03-22 19:13:11 -07001956 * This method enables parallel execution of queries from multiple threads on the
1957 * same database. It does this by opening multiple connections to the database
1958 * and using a different database connection for each query. The database
1959 * journal mode is also changed to enable writes to proceed concurrently with reads.
Vasu Nori6c354da2010-04-26 23:33:39 -07001960 * <p>
Jeff Brown47847f32012-03-22 19:13:11 -07001961 * When write-ahead logging is not enabled (the default), it is not possible for
1962 * reads and writes to occur on the database at the same time. Before modifying the
1963 * database, the writer implicitly acquires an exclusive lock on the database which
1964 * prevents readers from accessing the database until the write is completed.
1965 * </p><p>
1966 * In contrast, when write-ahead logging is enabled (by calling this method), write
1967 * operations occur in a separate log file which allows reads to proceed concurrently.
1968 * While a write is in progress, readers on other threads will perceive the state
1969 * of the database as it was before the write began. When the write completes, readers
1970 * on other threads will then perceive the new state of the database.
1971 * </p><p>
1972 * It is a good idea to enable write-ahead logging whenever a database will be
1973 * concurrently accessed and modified by multiple threads at the same time.
1974 * However, write-ahead logging uses significantly more memory than ordinary
1975 * journaling because there are multiple connections to the same database.
1976 * So if a database will only be used by a single thread, or if optimizing
1977 * concurrency is not very important, then write-ahead logging should be disabled.
1978 * </p><p>
1979 * After calling this method, execution of queries in parallel is enabled as long as
1980 * the database remains open. To disable execution of queries in parallel, either
1981 * call {@link #disableWriteAheadLogging} or close the database and reopen it.
1982 * </p><p>
1983 * The maximum number of connections used to execute queries in parallel is
Vasu Nori6c354da2010-04-26 23:33:39 -07001984 * dependent upon the device memory and possibly other properties.
Jeff Brown47847f32012-03-22 19:13:11 -07001985 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07001986 * If a query is part of a transaction, then it is executed on the same database handle the
1987 * transaction was begun.
Jeff Brown47847f32012-03-22 19:13:11 -07001988 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07001989 * Writers should use {@link #beginTransactionNonExclusive()} or
1990 * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
Jeff Brown47847f32012-03-22 19:13:11 -07001991 * to start a transaction. Non-exclusive mode allows database file to be in readable
1992 * by other threads executing queries.
1993 * </p><p>
1994 * If the database has any attached databases, then execution of queries in parallel is NOT
1995 * possible. Likewise, write-ahead logging is not supported for read-only databases
1996 * or memory databases. In such cases, {@link #enableWriteAheadLogging} returns false.
1997 * </p><p>
1998 * The best way to enable write-ahead logging is to pass the
1999 * {@link #ENABLE_WRITE_AHEAD_LOGGING} flag to {@link #openDatabase}. This is
2000 * more efficient than calling {@link #enableWriteAheadLogging}.
2001 * <code><pre>
2002 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2003 * SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
2004 * myDatabaseErrorHandler);
2005 * db.enableWriteAheadLogging();
2006 * </pre></code>
2007 * </p><p>
2008 * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging}
2009 * after opening the database.
2010 * <code><pre>
2011 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2012 * SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
2013 * db.enableWriteAheadLogging();
2014 * </pre></code>
2015 * </p><p>
2016 * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for
2017 * more details about how write-ahead logging works.
Vasu Nori6c354da2010-04-26 23:33:39 -07002018 * </p>
2019 *
Jeff Brown47847f32012-03-22 19:13:11 -07002020 * @return True if write-ahead logging is enabled.
Jeff Browne67ca422012-03-21 17:24:05 -07002021 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002022 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002023 * time this method is called. WAL mode can only be changed when there are no
2024 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002025 *
2026 * @see #ENABLE_WRITE_AHEAD_LOGGING
2027 * @see #disableWriteAheadLogging
Vasu Nori6c354da2010-04-26 23:33:39 -07002028 */
Vasu Noriffe06122010-09-27 12:32:57 -07002029 public boolean enableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002030 synchronized (mLock) {
2031 throwIfNotOpenLocked();
2032
Jeff Brown47847f32012-03-22 19:13:11 -07002033 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002034 return true;
2035 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002036
2037 if (isReadOnlyLocked()) {
2038 // WAL doesn't make sense for readonly-databases.
2039 // TODO: True, but connection pooling does still make sense...
2040 return false;
2041 }
2042
2043 if (mConfigurationLocked.isInMemoryDb()) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002044 Log.i(TAG, "can't enable WAL for memory databases.");
2045 return false;
2046 }
2047
2048 // make sure this database has NO attached databases because sqlite's write-ahead-logging
2049 // doesn't work for databases with attached databases
Jeff Browne5360fb2011-10-31 17:48:13 -07002050 if (mHasAttachedDbsLocked) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002051 if (Log.isLoggable(TAG, Log.DEBUG)) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002052 Log.d(TAG, "this database: " + mConfigurationLocked.label
2053 + " has attached databases. can't enable WAL.");
Paul Westbrookdae6d372011-02-17 10:59:56 -08002054 }
2055 return false;
2056 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002057
Jeff Brown47847f32012-03-22 19:13:11 -07002058 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002059 try {
2060 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2061 } catch (RuntimeException ex) {
Jeff Brown47847f32012-03-22 19:13:11 -07002062 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002063 throw ex;
2064 }
Paul Westbrookdae6d372011-02-17 10:59:56 -08002065 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002066 return true;
Vasu Nori6c354da2010-04-26 23:33:39 -07002067 }
2068
Vasu Nori2827d6d2010-07-04 00:26:18 -07002069 /**
Vasu Nori7b04c412010-07-20 10:31:21 -07002070 * This method disables the features enabled by {@link #enableWriteAheadLogging()}.
Jeff Browne67ca422012-03-21 17:24:05 -07002071 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002072 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002073 * time this method is called. WAL mode can only be changed when there are no
2074 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002075 *
2076 * @see #enableWriteAheadLogging
Vasu Nori2827d6d2010-07-04 00:26:18 -07002077 */
Vasu Nori7b04c412010-07-20 10:31:21 -07002078 public void disableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002079 synchronized (mLock) {
2080 throwIfNotOpenLocked();
2081
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002082 final boolean oldUseCompatibilityWal = mConfigurationLocked.useCompatibilityWal;
2083 final int oldFlags = mConfigurationLocked.openFlags;
2084 if (!oldUseCompatibilityWal && (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002085 return;
Paul Westbrookdae6d372011-02-17 10:59:56 -08002086 }
Vasu Nori8d111032010-06-22 18:34:21 -07002087
Jeff Brown47847f32012-03-22 19:13:11 -07002088 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002089 // If an app explicitly disables WAL, do not even use compatibility mode
2090 mConfigurationLocked.useCompatibilityWal = false;
2091
Jeff Browne67ca422012-03-21 17:24:05 -07002092 try {
2093 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2094 } catch (RuntimeException ex) {
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002095 mConfigurationLocked.openFlags = oldFlags;
2096 mConfigurationLocked.useCompatibilityWal = oldUseCompatibilityWal;
Jeff Browne67ca422012-03-21 17:24:05 -07002097 throw ex;
2098 }
Vasu Nori65a88832010-07-16 15:14:08 -07002099 }
Vasu Nori6c354da2010-04-26 23:33:39 -07002100 }
2101
Vasu Norif3cf8a42010-03-23 11:41:44 -07002102 /**
Jeff Brown47847f32012-03-22 19:13:11 -07002103 * Returns true if write-ahead logging has been enabled for this database.
2104 *
2105 * @return True if write-ahead logging has been enabled for this database.
2106 *
2107 * @see #enableWriteAheadLogging
2108 * @see #ENABLE_WRITE_AHEAD_LOGGING
2109 */
2110 public boolean isWriteAheadLoggingEnabled() {
2111 synchronized (mLock) {
2112 throwIfNotOpenLocked();
2113
2114 return (mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2115 }
2116 }
2117
2118 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002119 * Collect statistics about all open databases in the current process.
2120 * Used by bug report.
Vasu Norif3cf8a42010-03-23 11:41:44 -07002121 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002122 static ArrayList<DbStats> getDbStats() {
Vasu Noric3849202010-03-09 10:47:25 -08002123 ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002124 for (SQLiteDatabase db : getActiveDatabases()) {
2125 db.collectDbStats(dbStatsList);
Vasu Nori24675612010-09-27 14:54:19 -07002126 }
Vasu Noric3849202010-03-09 10:47:25 -08002127 return dbStatsList;
2128 }
2129
Jeff Browne5360fb2011-10-31 17:48:13 -07002130 private void collectDbStats(ArrayList<DbStats> dbStatsList) {
2131 synchronized (mLock) {
2132 if (mConnectionPoolLocked != null) {
2133 mConnectionPoolLocked.collectDbStats(dbStatsList);
2134 }
2135 }
2136 }
2137
2138 private static ArrayList<SQLiteDatabase> getActiveDatabases() {
2139 ArrayList<SQLiteDatabase> databases = new ArrayList<SQLiteDatabase>();
2140 synchronized (sActiveDatabases) {
2141 databases.addAll(sActiveDatabases.keySet());
2142 }
2143 return databases;
2144 }
2145
2146 /**
2147 * Dump detailed information about all open databases in the current process.
2148 * Used by bug report.
2149 */
Jeff Browna9be4152012-01-18 15:29:57 -08002150 static void dumpAll(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002151 for (SQLiteDatabase db : getActiveDatabases()) {
Jeff Browna9be4152012-01-18 15:29:57 -08002152 db.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002153 }
2154 }
2155
Jeff Browna9be4152012-01-18 15:29:57 -08002156 private void dump(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002157 synchronized (mLock) {
2158 if (mConnectionPoolLocked != null) {
2159 printer.println("");
Jeff Browna9be4152012-01-18 15:29:57 -08002160 mConnectionPoolLocked.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002161 }
2162 }
2163 }
2164
Vasu Noric3849202010-03-09 10:47:25 -08002165 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002166 * Returns list of full pathnames of all attached databases including the main database
2167 * by executing 'pragma database_list' on the database.
2168 *
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002169 * @return ArrayList of pairs of (database name, database file path) or null if the database
2170 * is not open.
Vasu Noric3849202010-03-09 10:47:25 -08002171 */
Vasu Noria017eda2011-01-27 10:52:55 -08002172 public List<Pair<String, String>> getAttachedDbs() {
Vasu Noric3849202010-03-09 10:47:25 -08002173 ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002174 synchronized (mLock) {
2175 if (mConnectionPoolLocked == null) {
2176 return null; // not open
2177 }
2178
2179 if (!mHasAttachedDbsLocked) {
2180 // No attached databases.
2181 // There is a small window where attached databases exist but this flag is not
2182 // set yet. This can occur when this thread is in a race condition with another
2183 // thread that is executing the SQL statement: "attach database <blah> as <foo>"
2184 // If this thread is NOT ok with such a race condition (and thus possibly not
2185 // receivethe entire list of attached databases), then the caller should ensure
2186 // that no thread is executing any SQL statements while a thread is calling this
2187 // method. Typically, this method is called when 'adb bugreport' is done or the
2188 // caller wants to collect stats on the database and all its attached databases.
2189 attachedDbs.add(new Pair<String, String>("main", mConfigurationLocked.path));
2190 return attachedDbs;
2191 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002192
2193 acquireReference();
Vasu Nori24675612010-09-27 14:54:19 -07002194 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002195
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002196 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002197 // has attached databases. query sqlite to get the list of attached databases.
2198 Cursor c = null;
2199 try {
2200 c = rawQuery("pragma database_list;", null);
2201 while (c.moveToNext()) {
2202 // sqlite returns a row for each database in the returned list of databases.
2203 // in each row,
2204 // 1st column is the database name such as main, or the database
2205 // name specified on the "ATTACH" command
2206 // 2nd column is the database file path.
2207 attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2)));
2208 }
2209 } finally {
2210 if (c != null) {
2211 c.close();
2212 }
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002213 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002214 return attachedDbs;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002215 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08002216 releaseReference();
Vasu Noric3849202010-03-09 10:47:25 -08002217 }
Vasu Noric3849202010-03-09 10:47:25 -08002218 }
2219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002220 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002221 * Runs 'pragma integrity_check' on the given database (and all the attached databases)
2222 * and returns true if the given database (and all its attached databases) pass integrity_check,
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002223 * false otherwise.
Vasu Noriccd95442010-05-28 17:04:16 -07002224 *<p>
2225 * If the result is false, then this method logs the errors reported by the integrity_check
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002226 * command execution.
Vasu Noriccd95442010-05-28 17:04:16 -07002227 *<p>
2228 * Note that 'pragma integrity_check' on a database can take a long time.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002229 *
2230 * @return true if the given database (and all its attached databases) pass integrity_check,
Vasu Noriccd95442010-05-28 17:04:16 -07002231 * false otherwise.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002232 */
2233 public boolean isDatabaseIntegrityOk() {
Jeff Brown03bd3022012-03-06 13:48:56 -08002234 acquireReference();
Vasu Noribfe1dc22010-08-25 16:29:02 -07002235 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002236 List<Pair<String, String>> attachedDbs = null;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002237 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002238 attachedDbs = getAttachedDbs();
2239 if (attachedDbs == null) {
2240 throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " +
2241 "be retrieved. probably because the database is closed");
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002242 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002243 } catch (SQLiteException e) {
2244 // can't get attachedDb list. do integrity check on the main database
2245 attachedDbs = new ArrayList<Pair<String, String>>();
2246 attachedDbs.add(new Pair<String, String>("main", getPath()));
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002247 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002248
2249 for (int i = 0; i < attachedDbs.size(); i++) {
2250 Pair<String, String> p = attachedDbs.get(i);
2251 SQLiteStatement prog = null;
2252 try {
2253 prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);");
2254 String rslt = prog.simpleQueryForString();
2255 if (!rslt.equalsIgnoreCase("ok")) {
2256 // integrity_checker failed on main or attached databases
2257 Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt);
2258 return false;
2259 }
2260 } finally {
2261 if (prog != null) prog.close();
2262 }
2263 }
2264 } finally {
2265 releaseReference();
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002266 }
Vasu Noribfe1dc22010-08-25 16:29:02 -07002267 return true;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002268 }
2269
Jeff Browne5360fb2011-10-31 17:48:13 -07002270 @Override
2271 public String toString() {
2272 return "SQLiteDatabase: " + getPath();
2273 }
2274
Jeff Browne5360fb2011-10-31 17:48:13 -07002275 private void throwIfNotOpenLocked() {
2276 if (mConnectionPoolLocked == null) {
2277 throw new IllegalStateException("The database '" + mConfigurationLocked.label
2278 + "' is not open.");
2279 }
2280 }
Vasu Nori3ef94e22010-02-05 14:49:04 -08002281
2282 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002283 * Used to allow returning sub-classes of {@link Cursor} when calling query.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002284 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002285 public interface CursorFactory {
2286 /**
2287 * See {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}.
2288 */
2289 public Cursor newCursor(SQLiteDatabase db,
2290 SQLiteCursorDriver masterQuery, String editTable,
2291 SQLiteQuery query);
2292 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293
2294 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002295 * A callback interface for a custom sqlite3 function.
2296 * This can be used to create a function that can be called from
2297 * sqlite3 database triggers.
2298 * @hide
Vasu Noric3849202010-03-09 10:47:25 -08002299 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002300 public interface CustomFunction {
2301 public void callback(String[] args);
2302 }
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002303
2304 /**
2305 * Wrapper for configuration parameters that are used for opening {@link SQLiteDatabase}
2306 */
2307 public static final class OpenParams {
2308 private final int mOpenFlags;
2309 private final CursorFactory mCursorFactory;
2310 private final DatabaseErrorHandler mErrorHandler;
2311 private final int mLookasideSlotSize;
2312 private final int mLookasideSlotCount;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002313 private final long mIdleConnectionTimeout;
2314 private final String mJournalMode;
2315 private final String mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002316
2317 private OpenParams(int openFlags, CursorFactory cursorFactory,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002318 DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002319 long idleConnectionTimeout, String journalMode, String syncMode) {
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002320 mOpenFlags = openFlags;
2321 mCursorFactory = cursorFactory;
2322 mErrorHandler = errorHandler;
2323 mLookasideSlotSize = lookasideSlotSize;
2324 mLookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002325 mIdleConnectionTimeout = idleConnectionTimeout;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002326 mJournalMode = journalMode;
2327 mSyncMode = syncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002328 }
2329
2330 /**
2331 * Returns size in bytes of each lookaside slot or -1 if not set.
2332 *
2333 * @see Builder#setLookasideConfig(int, int)
2334 */
2335 @IntRange(from = -1)
2336 public int getLookasideSlotSize() {
2337 return mLookasideSlotSize;
2338 }
2339
2340 /**
2341 * Returns total number of lookaside memory slots per database connection or -1 if not
2342 * set.
2343 *
2344 * @see Builder#setLookasideConfig(int, int)
2345 */
2346 @IntRange(from = -1)
2347 public int getLookasideSlotCount() {
2348 return mLookasideSlotCount;
2349 }
2350
2351 /**
Fyodor Kupolov76436c02017-08-03 17:56:44 -07002352 * Returns flags to control database access mode. Default value is 0.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002353 *
2354 * @see Builder#setOpenFlags(int)
2355 */
2356 @DatabaseOpenFlags
2357 public int getOpenFlags() {
2358 return mOpenFlags;
2359 }
2360
2361 /**
2362 * Returns an optional factory class that is called to instantiate a cursor when query
2363 * is called
2364 *
2365 * @see Builder#setCursorFactory(CursorFactory)
2366 */
2367 @Nullable
2368 public CursorFactory getCursorFactory() {
2369 return mCursorFactory;
2370 }
2371
2372 /**
2373 * Returns handler for database corruption errors
2374 *
2375 * @see Builder#setErrorHandler(DatabaseErrorHandler)
2376 */
2377 @Nullable
2378 public DatabaseErrorHandler getErrorHandler() {
2379 return mErrorHandler;
2380 }
2381
2382 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002383 * Returns maximum number of milliseconds that SQLite connection is allowed to be idle
2384 * before it is closed and removed from the pool.
2385 * <p>If the value isn't set, the timeout defaults to the system wide timeout
2386 *
2387 * @return timeout in milliseconds or -1 if the value wasn't set.
2388 */
2389 public long getIdleConnectionTimeout() {
2390 return mIdleConnectionTimeout;
2391 }
2392
2393 /**
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002394 * Returns <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>.
2395 * This journal mode will only be used if {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING}
2396 * flag is not set, otherwise a platform will use "WAL" journal mode.
2397 * @see Builder#setJournalMode(String)
2398 */
2399 @Nullable
2400 public String getJournalMode() {
2401 return mJournalMode;
2402 }
2403
2404 /**
2405 * Returns <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>.
2406 * This value will only be used when {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag
2407 * is not set, otherwise a system wide default will be used.
2408 * @see Builder#setSynchronousMode(String)
2409 */
2410 @Nullable
2411 public String getSynchronousMode() {
2412 return mSyncMode;
2413 }
2414
2415 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002416 * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with
2417 * {@code this} parameters.
2418 * @hide
2419 */
2420 @NonNull
2421 public Builder toBuilder() {
2422 return new Builder(this);
2423 }
2424
2425 /**
2426 * Builder for {@link OpenParams}.
2427 */
2428 public static final class Builder {
2429 private int mLookasideSlotSize = -1;
2430 private int mLookasideSlotCount = -1;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002431 private long mIdleConnectionTimeout = -1;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002432 private int mOpenFlags;
2433 private CursorFactory mCursorFactory;
2434 private DatabaseErrorHandler mErrorHandler;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002435 private String mJournalMode;
2436 private String mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002437
2438 public Builder() {
2439 }
2440
2441 public Builder(OpenParams params) {
2442 mLookasideSlotSize = params.mLookasideSlotSize;
2443 mLookasideSlotCount = params.mLookasideSlotCount;
2444 mOpenFlags = params.mOpenFlags;
2445 mCursorFactory = params.mCursorFactory;
2446 mErrorHandler = params.mErrorHandler;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002447 mJournalMode = params.mJournalMode;
2448 mSyncMode = params.mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002449 }
2450
2451 /**
2452 * Configures
2453 * <a href="https://sqlite.org/malloc.html#lookaside">lookaside memory allocator</a>
2454 *
2455 * <p>SQLite default settings will be used, if this method isn't called.
2456 * Use {@code setLookasideConfig(0,0)} to disable lookaside
2457 *
Fyodor Kupolov05a0f0f2017-06-30 19:00:00 -07002458 * <p><strong>Note:</strong> Provided slotSize/slotCount configuration is just a
2459 * recommendation. The system may choose different values depending on a device, e.g.
2460 * lookaside allocations can be disabled on low-RAM devices
2461 *
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002462 * @param slotSize The size in bytes of each lookaside slot.
2463 * @param slotCount The total number of lookaside memory slots per database connection.
2464 */
2465 public Builder setLookasideConfig(@IntRange(from = 0) final int slotSize,
2466 @IntRange(from = 0) final int slotCount) {
2467 Preconditions.checkArgument(slotSize >= 0,
2468 "lookasideSlotCount cannot be negative");
2469 Preconditions.checkArgument(slotCount >= 0,
2470 "lookasideSlotSize cannot be negative");
2471 Preconditions.checkArgument(
2472 (slotSize > 0 && slotCount > 0) || (slotCount == 0 && slotSize == 0),
2473 "Invalid configuration: " + slotSize + ", " + slotCount);
2474
2475 mLookasideSlotSize = slotSize;
2476 mLookasideSlotCount = slotCount;
2477 return this;
2478 }
2479
2480 /**
2481 * Returns true if {@link #ENABLE_WRITE_AHEAD_LOGGING} flag is set
2482 * @hide
2483 */
2484 public boolean isWriteAheadLoggingEnabled() {
2485 return (mOpenFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2486 }
2487
2488 /**
2489 * Sets flags to control database access mode
2490 * @param openFlags The new flags to set
2491 * @see #OPEN_READWRITE
2492 * @see #OPEN_READONLY
2493 * @see #CREATE_IF_NECESSARY
2494 * @see #NO_LOCALIZED_COLLATORS
2495 * @see #ENABLE_WRITE_AHEAD_LOGGING
2496 * @return same builder instance for chaining multiple calls into a single statement
2497 */
2498 @NonNull
2499 public Builder setOpenFlags(@DatabaseOpenFlags int openFlags) {
2500 mOpenFlags = openFlags;
2501 return this;
2502 }
2503
2504 /**
2505 * Adds flags to control database access mode
2506 *
2507 * @param openFlags The new flags to add
2508 * @return same builder instance for chaining multiple calls into a single statement
2509 */
2510 @NonNull
2511 public Builder addOpenFlags(@DatabaseOpenFlags int openFlags) {
2512 mOpenFlags |= openFlags;
2513 return this;
2514 }
2515
2516 /**
2517 * Removes database access mode flags
2518 *
2519 * @param openFlags Flags to remove
2520 * @return same builder instance for chaining multiple calls into a single statement
2521 */
2522 @NonNull
2523 public Builder removeOpenFlags(@DatabaseOpenFlags int openFlags) {
2524 mOpenFlags &= ~openFlags;
2525 return this;
2526 }
2527
2528 /**
2529 * Sets {@link #ENABLE_WRITE_AHEAD_LOGGING} flag if {@code enabled} is {@code true},
2530 * unsets otherwise
2531 * @hide
2532 */
2533 public void setWriteAheadLoggingEnabled(boolean enabled) {
2534 if (enabled) {
2535 addOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2536 } else {
2537 removeOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2538 }
2539 }
2540
2541 /**
2542 * Set an optional factory class that is called to instantiate a cursor when query
2543 * is called.
2544 *
2545 * @param cursorFactory instance
2546 * @return same builder instance for chaining multiple calls into a single statement
2547 */
2548 @NonNull
2549 public Builder setCursorFactory(@Nullable CursorFactory cursorFactory) {
2550 mCursorFactory = cursorFactory;
2551 return this;
2552 }
2553
2554
2555 /**
2556 * Sets {@link DatabaseErrorHandler} object to handle db corruption errors
2557 */
2558 @NonNull
2559 public Builder setErrorHandler(@Nullable DatabaseErrorHandler errorHandler) {
2560 mErrorHandler = errorHandler;
2561 return this;
2562 }
2563
2564 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002565 * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle
2566 * before it is closed and removed from the pool.
2567 *
2568 * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE}
2569 * to allow unlimited idle connections.
2570 */
2571 @NonNull
2572 public Builder setIdleConnectionTimeout(
2573 @IntRange(from = 0) long idleConnectionTimeoutMs) {
2574 Preconditions.checkArgument(idleConnectionTimeoutMs >= 0,
2575 "idle connection timeout cannot be negative");
2576 mIdleConnectionTimeout = idleConnectionTimeoutMs;
2577 return this;
2578 }
2579
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002580
2581 /**
2582 * Sets <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>
2583 * to use when {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag is not set.
2584 */
2585 @NonNull
2586 public Builder setJournalMode(@NonNull String journalMode) {
2587 Preconditions.checkNotNull(journalMode);
2588 mJournalMode = journalMode;
2589 return this;
2590 }
2591
2592 /**
2593 * Sets <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>
2594 * to use when {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag is not set.
2595 * @return
2596 */
2597 @NonNull
2598 public Builder setSynchronousMode(@NonNull String syncMode) {
2599 Preconditions.checkNotNull(syncMode);
2600 mSyncMode = syncMode;
2601 return this;
2602 }
2603
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002604 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002605 * Creates an instance of {@link OpenParams} with the options that were previously set
2606 * on this builder
2607 */
2608 @NonNull
2609 public OpenParams build() {
2610 return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002611 mLookasideSlotCount, mIdleConnectionTimeout, mJournalMode, mSyncMode);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002612 }
2613 }
2614 }
2615
2616 /** @hide */
2617 @IntDef(flag = true, prefix = {"OPEN_", "CREATE_", "NO_", "ENABLE_"}, value = {
2618 OPEN_READWRITE,
2619 OPEN_READONLY,
2620 CREATE_IF_NECESSARY,
2621 NO_LOCALIZED_COLLATORS,
2622 ENABLE_WRITE_AHEAD_LOGGING
2623 })
2624 @Retention(RetentionPolicy.SOURCE)
2625 public @interface DatabaseOpenFlags {}
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002627}
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002628