blob: a1b0803e0203109d35a4c769c11c33d3faaa6a8a [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;
Mathew Inwood41b31942018-08-10 16:00:53 +010023import android.annotation.UnsupportedAppUsage;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070024import android.app.ActivityManager;
Makoto Onukiee93ad22018-10-18 16:24:13 -070025import android.app.ActivityThread;
26import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.content.ContentValues;
28import android.database.Cursor;
Vasu Nori062fc7ce2010-03-31 16:13:05 -070029import android.database.DatabaseErrorHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.database.DatabaseUtils;
Vasu Nori062fc7ce2010-03-31 16:13:05 -070031import android.database.DefaultDatabaseErrorHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.database.SQLException;
Vasu Noric3849202010-03-09 10:47:25 -080033import android.database.sqlite.SQLiteDebug.DbStats;
Jeff Browna7771df2012-05-07 20:06:46 -070034import android.os.CancellationSignal;
Jeff Browne5360fb2011-10-31 17:48:13 -070035import android.os.Looper;
Jeff Browna7771df2012-05-07 20:06:46 -070036import android.os.OperationCanceledException;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070037import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.text.TextUtils;
Makoto Onukiee93ad22018-10-18 16:24:13 -070039import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.util.EventLog;
Dmitri Plotnikov90142c92009-09-15 10:52:17 -070041import android.util.Log;
Vasu Noric3849202010-03-09 10:47:25 -080042import android.util.Pair;
Jeff Browne5360fb2011-10-31 17:48:13 -070043import android.util.Printer;
44
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070045import com.android.internal.util.Preconditions;
46
Jeff Browne5360fb2011-10-31 17:48:13 -070047import dalvik.system.CloseGuard;
48
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import java.io.File;
Jeff Brown79087e42012-03-01 19:52:44 -080050import java.io.FileFilter;
Makoto Onukiee93ad22018-10-18 16:24:13 -070051import java.io.IOException;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070052import java.lang.annotation.Retention;
53import java.lang.annotation.RetentionPolicy;
Makoto Onukiee93ad22018-10-18 16:24:13 -070054import java.nio.file.FileSystems;
55import java.nio.file.Files;
56import java.nio.file.attribute.BasicFileAttributes;
Vasu Noric3849202010-03-09 10:47:25 -080057import java.util.ArrayList;
Makoto Onukiee93ad22018-10-18 16:24:13 -070058import java.util.Arrays;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import java.util.HashMap;
Jesse Wilson9b5a9352011-02-10 11:19:09 -080060import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import java.util.Locale;
62import java.util.Map;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import java.util.WeakHashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064
65/**
66 * Exposes methods to manage a SQLite database.
Jeff Browne5360fb2011-10-31 17:48:13 -070067 *
68 * <p>
69 * SQLiteDatabase has methods to create, delete, execute SQL commands, and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070 * perform other common database management tasks.
Jeff Browne5360fb2011-10-31 17:48:13 -070071 * </p><p>
72 * See the Notepad sample application in the SDK for an example of creating
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073 * and managing a database.
Jeff Browne5360fb2011-10-31 17:48:13 -070074 * </p><p>
75 * Database names must be unique within an application, not across all applications.
76 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077 *
78 * <h3>Localized Collation - ORDER BY</h3>
Jeff Browne5360fb2011-10-31 17:48:13 -070079 * <p>
80 * In addition to SQLite's default <code>BINARY</code> collator, Android supplies
81 * two more, <code>LOCALIZED</code>, which changes with the system's current locale,
82 * and <code>UNICODE</code>, which is the Unicode Collation Algorithm and not tailored
83 * to the current locale.
84 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 */
Jeff Brownbaefdfa2012-03-05 10:33:13 -080086public final class SQLiteDatabase extends SQLiteClosable {
Vasu Norifb16cbd2010-07-25 16:38:48 -070087 private static final String TAG = "SQLiteDatabase";
Jeff Browne5360fb2011-10-31 17:48:13 -070088
Jeff Hamilton082c2af2009-09-29 11:49:51 -070089 private static final int EVENT_DB_CORRUPT = 75004;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090
Fyodor Kupolov535672992017-08-30 18:16:31 -070091 // By default idle connections are not closed
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070092 private static final boolean DEBUG_CLOSE_IDLE_CONNECTIONS = SystemProperties
Fyodor Kupolov535672992017-08-30 18:16:31 -070093 .getBoolean("persist.debug.sqlite.close_idle_connections", false);
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070094
Jeff Browne5360fb2011-10-31 17:48:13 -070095 // Stores reference to all databases opened in the current process.
96 // (The referent Object is not used at this time.)
97 // INVARIANT: Guarded by sActiveDatabases.
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070098 private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases = new WeakHashMap<>();
Jeff Browne5360fb2011-10-31 17:48:13 -070099
100 // Thread-local for database sessions that belong to this database.
101 // Each thread has its own database session.
102 // INVARIANT: Immutable.
Mathew Inwood41b31942018-08-10 16:00:53 +0100103 @UnsupportedAppUsage
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700104 private final ThreadLocal<SQLiteSession> mThreadSession = ThreadLocal
105 .withInitial(this::createSession);
Jeff Browne5360fb2011-10-31 17:48:13 -0700106
107 // The optional factory to use when creating new Cursors. May be null.
108 // INVARIANT: Immutable.
109 private final CursorFactory mCursorFactory;
110
111 // Error handler to be used when SQLite returns corruption errors.
112 // INVARIANT: Immutable.
113 private final DatabaseErrorHandler mErrorHandler;
114
115 // Shared database state lock.
116 // This lock guards all of the shared state of the database, such as its
117 // configuration, whether it is open or closed, and so on. This lock should
118 // be held for as little time as possible.
119 //
120 // The lock MUST NOT be held while attempting to acquire database connections or
121 // while executing SQL statements on behalf of the client as it can lead to deadlock.
122 //
123 // It is ok to hold the lock while reconfiguring the connection pool or dumping
124 // statistics because those operations are non-reentrant and do not try to acquire
125 // connections that might be held by other threads.
126 //
127 // Basic rule: grab the lock, access or modify global state, release the lock, then
128 // do the required SQL work.
129 private final Object mLock = new Object();
130
131 // Warns if the database is finalized without being closed properly.
132 // INVARIANT: Guarded by mLock.
133 private final CloseGuard mCloseGuardLocked = CloseGuard.get();
134
135 // The database configuration.
136 // INVARIANT: Guarded by mLock.
Mathew Inwood41b31942018-08-10 16:00:53 +0100137 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -0700138 private final SQLiteDatabaseConfiguration mConfigurationLocked;
139
140 // The connection pool for the database, null when closed.
141 // The pool itself is thread-safe, but the reference to it can only be acquired
142 // when the lock is held.
143 // INVARIANT: Guarded by mLock.
Mathew Inwood41b31942018-08-10 16:00:53 +0100144 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -0700145 private SQLiteConnectionPool mConnectionPoolLocked;
146
147 // True if the database has attached databases.
148 // INVARIANT: Guarded by mLock.
149 private boolean mHasAttachedDbsLocked;
150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700152 * When a constraint violation occurs, an immediate ROLLBACK occurs,
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800153 * thus ending the current transaction, and the command aborts with a
154 * return code of SQLITE_CONSTRAINT. If no transaction is active
155 * (other than the implied transaction that is created on every command)
Jeff Browne5360fb2011-10-31 17:48:13 -0700156 * then this algorithm works the same as ABORT.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800157 */
158 public static final int CONFLICT_ROLLBACK = 1;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700159
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800160 /**
161 * When a constraint violation occurs,no ROLLBACK is executed
162 * so changes from prior commands within the same transaction
163 * are preserved. This is the default behavior.
164 */
165 public static final int CONFLICT_ABORT = 2;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700166
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800167 /**
168 * When a constraint violation occurs, the command aborts with a return
169 * code SQLITE_CONSTRAINT. But any changes to the database that
170 * the command made prior to encountering the constraint violation
171 * are preserved and are not backed out.
172 */
173 public static final int CONFLICT_FAIL = 3;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700174
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800175 /**
176 * When a constraint violation occurs, the one row that contains
177 * the constraint violation is not inserted or changed.
178 * But the command continues executing normally. Other rows before and
179 * after the row that contained the constraint violation continue to be
180 * inserted or updated normally. No error is returned.
181 */
182 public static final int CONFLICT_IGNORE = 4;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700183
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800184 /**
185 * When a UNIQUE constraint violation occurs, the pre-existing rows that
186 * are causing the constraint violation are removed prior to inserting
187 * or updating the current row. Thus the insert or update always occurs.
188 * The command continues executing normally. No error is returned.
189 * If a NOT NULL constraint violation occurs, the NULL value is replaced
190 * by the default value for that column. If the column has no default
191 * value, then the ABORT algorithm is used. If a CHECK constraint
192 * violation occurs then the IGNORE algorithm is used. When this conflict
193 * resolution strategy deletes rows in order to satisfy a constraint,
194 * it does not invoke delete triggers on those rows.
Jeff Browne5360fb2011-10-31 17:48:13 -0700195 * This behavior might change in a future release.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800196 */
197 public static final int CONFLICT_REPLACE = 5;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700198
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800199 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700200 * Use the following when no conflict action is specified.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800201 */
202 public static final int CONFLICT_NONE = 0;
Jeff Browne5360fb2011-10-31 17:48:13 -0700203
Jeff Sharkey6adc98c2018-07-12 19:47:49 -0600204 /** {@hide} */
Mathew Inwood41b31942018-08-10 16:00:53 +0100205 @UnsupportedAppUsage
Jeff Sharkey6adc98c2018-07-12 19:47:49 -0600206 public static final String[] CONFLICT_VALUES = new String[]
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800207 {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 /**
210 * Maximum Length Of A LIKE Or GLOB Pattern
211 * The pattern matching algorithm used in the default LIKE and GLOB implementation
212 * of SQLite can exhibit O(N^2) performance (where N is the number of characters in
213 * the pattern) for certain pathological cases. To avoid denial-of-service attacks
214 * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes.
215 * The default value of this limit is 50000. A modern workstation can evaluate
216 * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly.
217 * The denial of service problem only comes into play when the pattern length gets
218 * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns
219 * are at most a few dozen bytes in length, paranoid application developers may
220 * want to reduce this parameter to something in the range of a few hundred
221 * if they know that external users are able to generate arbitrary patterns.
222 */
223 public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000;
224
225 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700226 * Open flag: Flag for {@link #openDatabase} to open the database for reading and writing.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 * If the disk is full, this may fail even before you actually write anything.
228 *
229 * {@more} Note that the value of this flag is 0, so it is the default.
230 */
231 public static final int OPEN_READWRITE = 0x00000000; // update native code if changing
232
233 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700234 * Open flag: Flag for {@link #openDatabase} to open the database for reading only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 * This is the only reliable way to open a database if the disk may be full.
236 */
237 public static final int OPEN_READONLY = 0x00000001; // update native code if changing
238
239 private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing
240
241 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700242 * Open flag: Flag for {@link #openDatabase} to open the database without support for
243 * localized collators.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 *
245 * {@more} This causes the collator <code>LOCALIZED</code> not to be created.
246 * You must be consistent when using this flag to use the setting the database was
247 * created with. If this is set, {@link #setLocale} will do nothing.
248 */
249 public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing
250
251 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700252 * Open flag: Flag for {@link #openDatabase} to create the database file if it does not
253 * already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 */
255 public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing
256
257 /**
Jeff Brown47847f32012-03-22 19:13:11 -0700258 * Open flag: Flag for {@link #openDatabase} to open the database file with
259 * write-ahead logging enabled by default. Using this flag is more efficient
260 * than calling {@link #enableWriteAheadLogging}.
261 *
262 * Write-ahead logging cannot be used with read-only databases so the value of
263 * this flag is ignored if the database is opened read-only.
264 *
265 * @see #enableWriteAheadLogging
266 */
267 public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;
268
269 /**
Fyodor Kupolov692573b2018-03-06 12:34:36 -0800270 * Open flag: Flag for {@link #openDatabase} to disable Compatibility WAL when opening database.
271 *
272 * @hide
273 */
274 public static final int DISABLE_COMPATIBILITY_WAL = 0x40000000;
275
276 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700277 * Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}.
Vasu Norib729dcc2010-09-14 11:35:49 -0700278 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700279 * Each prepared-statement is between 1K - 6K, depending on the complexity of the
280 * SQL statement & schema. A large SQL cache may use a significant amount of memory.
Vasu Norie495d1f2010-01-06 16:34:19 -0800281 */
Vasu Nori90a367262010-04-12 12:49:09 -0700282 public static final int MAX_SQL_CACHE_SIZE = 100;
Vasu Norib729dcc2010-09-14 11:35:49 -0700283
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700284 private SQLiteDatabase(final String path, final int openFlags,
285 CursorFactory cursorFactory, DatabaseErrorHandler errorHandler,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800286 int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs,
287 String journalMode, String syncMode) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700288 mCursorFactory = cursorFactory;
289 mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler();
290 mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700291 mConfigurationLocked.lookasideSlotSize = lookasideSlotSize;
292 mConfigurationLocked.lookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700293 // Disable lookaside allocator on low-RAM devices
294 if (ActivityManager.isLowRamDeviceStatic()) {
295 mConfigurationLocked.lookasideSlotCount = 0;
296 mConfigurationLocked.lookasideSlotSize = 0;
297 }
298 long effectiveTimeoutMs = Long.MAX_VALUE;
299 // Never close idle connections for in-memory databases
300 if (!mConfigurationLocked.isInMemoryDb()) {
301 // First, check app-specific value. Otherwise use defaults
302 // -1 in idleConnectionTimeoutMs indicates unset value
303 if (idleConnectionTimeoutMs >= 0) {
304 effectiveTimeoutMs = idleConnectionTimeoutMs;
305 } else if (DEBUG_CLOSE_IDLE_CONNECTIONS) {
306 effectiveTimeoutMs = SQLiteGlobal.getIdleConnectionTimeout();
307 }
308 }
309 mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800310 mConfigurationLocked.journalMode = journalMode;
311 mConfigurationLocked.syncMode = syncMode;
Fyodor Kupolov692573b2018-03-06 12:34:36 -0800312 if (!SQLiteGlobal.isCompatibilityWalSupported() || (
313 SQLiteCompatibilityWalFlags.areFlagsSet() && !SQLiteCompatibilityWalFlags
314 .isCompatibilityWalSupported())) {
315 mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
Fyodor Kupolovee90c032017-12-12 11:52:57 -0800316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700318
Jeff Browne5360fb2011-10-31 17:48:13 -0700319 @Override
320 protected void finalize() throws Throwable {
321 try {
322 dispose(true);
323 } finally {
324 super.finalize();
325 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700326 }
327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 @Override
329 protected void onAllReferencesReleased() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700330 dispose(false);
331 }
332
333 private void dispose(boolean finalized) {
334 final SQLiteConnectionPool pool;
335 synchronized (mLock) {
336 if (mCloseGuardLocked != null) {
337 if (finalized) {
338 mCloseGuardLocked.warnIfOpen();
339 }
340 mCloseGuardLocked.close();
341 }
342
343 pool = mConnectionPoolLocked;
344 mConnectionPoolLocked = null;
345 }
346
347 if (!finalized) {
348 synchronized (sActiveDatabases) {
349 sActiveDatabases.remove(this);
350 }
351
352 if (pool != null) {
353 pool.close();
354 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 }
356 }
357
358 /**
359 * Attempts to release memory that SQLite holds but does not require to
360 * operate properly. Typically this memory will come from the page cache.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700361 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 * @return the number of bytes actually released
363 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700364 public static int releaseMemory() {
365 return SQLiteGlobal.releaseMemory();
366 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367
368 /**
369 * Control whether or not the SQLiteDatabase is made thread-safe by using locks
370 * around critical sections. This is pretty expensive, so if you know that your
371 * DB will only be used by a single thread then you should set this to false.
372 * The default is true.
373 * @param lockingEnabled set to true to enable locks, false otherwise
Jeff Browne5360fb2011-10-31 17:48:13 -0700374 *
375 * @deprecated This method now does nothing. Do not use.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700377 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 public void setLockingEnabled(boolean lockingEnabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 }
380
381 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700382 * Gets a label to use when describing the database in log messages.
383 * @return The label.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700385 String getLabel() {
386 synchronized (mLock) {
387 return mConfigurationLocked.label;
388 }
389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390
Jeff Browne5360fb2011-10-31 17:48:13 -0700391 /**
392 * Sends a corruption message to the database error handler.
393 */
394 void onCorruption() {
395 EventLog.writeEvent(EVENT_DB_CORRUPT, getLabel());
Vasu Noriccd95442010-05-28 17:04:16 -0700396 mErrorHandler.onCorruption(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 }
398
399 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700400 * Gets the {@link SQLiteSession} that belongs to this thread for this database.
401 * Once a thread has obtained a session, it will continue to obtain the same
402 * session even after the database has been closed (although the session will not
403 * be usable). However, a thread that does not already have a session cannot
404 * obtain one after the database has been closed.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700405 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700406 * The idea is that threads that have active connections to the database may still
407 * have work to complete even after the call to {@link #close}. Active database
408 * connections are not actually disposed until they are released by the threads
409 * that own them.
410 *
411 * @return The session, never null.
412 *
413 * @throws IllegalStateException if the thread does not yet have a session and
414 * the database is not open.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 */
Mathew Inwood41b31942018-08-10 16:00:53 +0100416 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -0700417 SQLiteSession getThreadSession() {
418 return mThreadSession.get(); // initialValue() throws if database closed
Vasu Nori6d970252010-10-05 10:48:49 -0700419 }
Vasu Nori16057fa2011-03-18 11:40:37 -0700420
Jeff Browne5360fb2011-10-31 17:48:13 -0700421 SQLiteSession createSession() {
422 final SQLiteConnectionPool pool;
423 synchronized (mLock) {
424 throwIfNotOpenLocked();
425 pool = mConnectionPoolLocked;
Vasu Nori6d970252010-10-05 10:48:49 -0700426 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700427 return new SQLiteSession(pool);
Vasu Norid4608a32011-02-03 16:24:06 -0800428 }
429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700431 * Gets default connection flags that are appropriate for this thread, taking into
432 * account whether the thread is acting on behalf of the UI.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700434 * @param readOnly True if the connection should be read-only.
435 * @return The connection flags.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700437 int getThreadDefaultConnectionFlags(boolean readOnly) {
438 int flags = readOnly ? SQLiteConnectionPool.CONNECTION_FLAG_READ_ONLY :
439 SQLiteConnectionPool.CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY;
440 if (isMainThread()) {
441 flags |= SQLiteConnectionPool.CONNECTION_FLAG_INTERACTIVE;
442 }
443 return flags;
Vasu Nori16057fa2011-03-18 11:40:37 -0700444 }
445
Jeff Browne5360fb2011-10-31 17:48:13 -0700446 private static boolean isMainThread() {
447 // FIXME: There should be a better way to do this.
448 // Would also be nice to have something that would work across Binder calls.
449 Looper looper = Looper.myLooper();
450 return looper != null && looper == Looper.getMainLooper();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451 }
452
453 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700454 * Begins a transaction in EXCLUSIVE mode.
455 * <p>
456 * Transactions can be nested.
457 * When the outer transaction is ended all of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 * the work done in that transaction and all of the nested transactions will be committed or
459 * rolled back. The changes will be rolled back if any transaction is ended without being
460 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700461 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 * <p>Here is the standard idiom for transactions:
463 *
464 * <pre>
465 * db.beginTransaction();
466 * try {
467 * ...
468 * db.setTransactionSuccessful();
469 * } finally {
470 * db.endTransaction();
471 * }
472 * </pre>
473 */
474 public void beginTransaction() {
Vasu Nori6c354da2010-04-26 23:33:39 -0700475 beginTransaction(null /* transactionStatusCallback */, true);
476 }
477
478 /**
479 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
480 * the outer transaction is ended all of the work done in that transaction
481 * and all of the nested transactions will be committed or rolled back. The
482 * changes will be rolled back if any transaction is ended without being
483 * marked as clean (by calling setTransactionSuccessful). Otherwise they
484 * will be committed.
485 * <p>
486 * Here is the standard idiom for transactions:
487 *
488 * <pre>
489 * db.beginTransactionNonExclusive();
490 * try {
491 * ...
492 * db.setTransactionSuccessful();
493 * } finally {
494 * db.endTransaction();
495 * }
496 * </pre>
497 */
498 public void beginTransactionNonExclusive() {
499 beginTransaction(null /* transactionStatusCallback */, false);
Fred Quintanac4516a72009-09-03 12:14:06 -0700500 }
501
502 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700503 * Begins a transaction in EXCLUSIVE mode.
504 * <p>
505 * Transactions can be nested.
506 * When the outer transaction is ended all of
Fred Quintanac4516a72009-09-03 12:14:06 -0700507 * the work done in that transaction and all of the nested transactions will be committed or
508 * rolled back. The changes will be rolled back if any transaction is ended without being
509 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700510 * </p>
Fred Quintanac4516a72009-09-03 12:14:06 -0700511 * <p>Here is the standard idiom for transactions:
512 *
513 * <pre>
514 * db.beginTransactionWithListener(listener);
515 * try {
516 * ...
517 * db.setTransactionSuccessful();
518 * } finally {
519 * db.endTransaction();
520 * }
521 * </pre>
Vasu Noriccd95442010-05-28 17:04:16 -0700522 *
Fred Quintanac4516a72009-09-03 12:14:06 -0700523 * @param transactionListener listener that should be notified when the transaction begins,
524 * commits, or is rolled back, either explicitly or by a call to
525 * {@link #yieldIfContendedSafely}.
526 */
527 public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
Vasu Nori6c354da2010-04-26 23:33:39 -0700528 beginTransaction(transactionListener, true);
529 }
530
531 /**
532 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
533 * the outer transaction is ended all of the work done in that transaction
534 * and all of the nested transactions will be committed or rolled back. The
535 * changes will be rolled back if any transaction is ended without being
536 * marked as clean (by calling setTransactionSuccessful). Otherwise they
537 * will be committed.
538 * <p>
539 * Here is the standard idiom for transactions:
540 *
541 * <pre>
542 * db.beginTransactionWithListenerNonExclusive(listener);
543 * try {
544 * ...
545 * db.setTransactionSuccessful();
546 * } finally {
547 * db.endTransaction();
548 * }
549 * </pre>
550 *
551 * @param transactionListener listener that should be notified when the
552 * transaction begins, commits, or is rolled back, either
553 * explicitly or by a call to {@link #yieldIfContendedSafely}.
554 */
555 public void beginTransactionWithListenerNonExclusive(
556 SQLiteTransactionListener transactionListener) {
557 beginTransaction(transactionListener, false);
558 }
559
Mathew Inwood41b31942018-08-10 16:00:53 +0100560 @UnsupportedAppUsage
Vasu Nori6c354da2010-04-26 23:33:39 -0700561 private void beginTransaction(SQLiteTransactionListener transactionListener,
562 boolean exclusive) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800563 acquireReference();
564 try {
565 getThreadSession().beginTransaction(
566 exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
567 SQLiteSession.TRANSACTION_MODE_IMMEDIATE,
568 transactionListener,
569 getThreadDefaultConnectionFlags(false /*readOnly*/), null);
570 } finally {
571 releaseReference();
572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800573 }
574
575 /**
576 * End a transaction. See beginTransaction for notes about how to use this and when transactions
577 * are committed and rolled back.
578 */
579 public void endTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800580 acquireReference();
581 try {
582 getThreadSession().endTransaction(null);
583 } finally {
584 releaseReference();
585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800586 }
587
588 /**
589 * Marks the current transaction as successful. Do not do any more database work between
590 * calling this and calling endTransaction. Do as little non-database work as possible in that
591 * situation too. If any errors are encountered between this and endTransaction the transaction
592 * will still be committed.
593 *
594 * @throws IllegalStateException if the current thread is not in a transaction or the
595 * transaction is already marked as successful.
596 */
597 public void setTransactionSuccessful() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800598 acquireReference();
599 try {
600 getThreadSession().setTransactionSuccessful();
601 } finally {
602 releaseReference();
603 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 }
605
606 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700607 * Returns true if the current thread has a transaction pending.
608 *
609 * @return True if the current thread is in a transaction.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 */
611 public boolean inTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800612 acquireReference();
613 try {
614 return getThreadSession().hasTransaction();
615 } finally {
616 releaseReference();
617 }
Vasu Norice38b982010-07-22 13:57:13 -0700618 }
619
620 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700621 * Returns true if the current thread is holding an active connection to the database.
Vasu Norice38b982010-07-22 13:57:13 -0700622 * <p>
Jeff Browne5360fb2011-10-31 17:48:13 -0700623 * The name of this method comes from a time when having an active connection
624 * to the database meant that the thread was holding an actual lock on the
625 * database. Nowadays, there is no longer a true "database lock" although threads
626 * may block if they cannot acquire a database connection to perform a
627 * particular operation.
628 * </p>
Vasu Norice38b982010-07-22 13:57:13 -0700629 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700630 * @return True if the current thread is holding an active connection to the database.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631 */
632 public boolean isDbLockedByCurrentThread() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800633 acquireReference();
634 try {
635 return getThreadSession().hasConnection();
636 } finally {
637 releaseReference();
638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800639 }
640
641 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700642 * Always returns false.
643 * <p>
644 * There is no longer the concept of a database lock, so this method always returns false.
645 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700647 * @return False.
648 * @deprecated Always returns false. Do not use this method.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700650 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800651 public boolean isDbLockedByOtherThreads() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700652 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653 }
654
655 /**
656 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
657 * successful so far. Do not call setTransactionSuccessful before calling this. When this
658 * returns a new transaction will have been created but not marked as successful.
659 * @return true if the transaction was yielded
kopriva7364c112018-09-27 11:02:07 -0700660 * @deprecated if the db is locked more than once (because of nested transactions) then the lock
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661 * will not be yielded. Use yieldIfContendedSafely instead.
662 */
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700663 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664 public boolean yieldIfContended() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700665 return yieldIfContendedHelper(false /* do not check yielding */,
666 -1 /* sleepAfterYieldDelay */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 }
668
669 /**
670 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
671 * successful so far. Do not call setTransactionSuccessful before calling this. When this
672 * returns a new transaction will have been created but not marked as successful. This assumes
673 * that there are no nested transactions (beginTransaction has only been called once) and will
Fred Quintana5c7aede2009-08-27 21:41:27 -0700674 * throw an exception if that is not the case.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675 * @return true if the transaction was yielded
676 */
677 public boolean yieldIfContendedSafely() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700678 return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679 }
680
Fred Quintana5c7aede2009-08-27 21:41:27 -0700681 /**
682 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
683 * successful so far. Do not call setTransactionSuccessful before calling this. When this
684 * returns a new transaction will have been created but not marked as successful. This assumes
685 * that there are no nested transactions (beginTransaction has only been called once) and will
686 * throw an exception if that is not the case.
687 * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if
688 * the lock was actually yielded. This will allow other background threads to make some
689 * more progress than they would if we started the transaction immediately.
690 * @return true if the transaction was yielded
691 */
692 public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
693 return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay);
694 }
695
Jeff Browne5360fb2011-10-31 17:48:13 -0700696 private boolean yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800697 acquireReference();
698 try {
699 return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null);
700 } finally {
701 releaseReference();
702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703 }
704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700706 * Deprecated.
Vasu Nori95675132010-07-21 16:24:40 -0700707 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 */
Vasu Nori95675132010-07-21 16:24:40 -0700709 @Deprecated
710 public Map<String, String> getSyncedTables() {
711 return new HashMap<String, String>(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 }
713
714 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715 * Open the database according to the flags {@link #OPEN_READWRITE}
716 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
717 *
718 * <p>Sets the locale of the database to the the system's current locale.
719 * Call {@link #setLocale} if you would like something else.</p>
720 *
721 * @param path to database file to open and/or create
722 * @param factory an optional factory class that is called to instantiate a
723 * cursor when query is called, or null for default
724 * @param flags to control database access mode
725 * @return the newly opened database
726 * @throws SQLiteException if the database cannot be opened
727 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700728 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
729 @DatabaseOpenFlags int flags) {
Jeff Brown47847f32012-03-22 19:13:11 -0700730 return openDatabase(path, factory, flags, null);
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700731 }
732
733 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700734 * Open the database according to the specified {@link OpenParams parameters}
735 *
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700736 * @param path path to database file to open and/or create.
737 * <p><strong>Important:</strong> The file should be constructed either from an absolute path or
738 * by using {@link android.content.Context#getDatabasePath(String)}.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700739 * @param openParams configuration parameters that are used for opening {@link SQLiteDatabase}
740 * @return the newly opened database
741 * @throws SQLiteException if the database cannot be opened
742 */
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700743 public static SQLiteDatabase openDatabase(@NonNull File path,
744 @NonNull OpenParams openParams) {
745 return openDatabase(path.getPath(), openParams);
746 }
747
Mathew Inwood41b31942018-08-10 16:00:53 +0100748 @UnsupportedAppUsage
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700749 private static SQLiteDatabase openDatabase(@NonNull String path,
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700750 @NonNull OpenParams openParams) {
751 Preconditions.checkArgument(openParams != null, "OpenParams cannot be null");
752 SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags,
753 openParams.mCursorFactory, openParams.mErrorHandler,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700754 openParams.mLookasideSlotSize, openParams.mLookasideSlotCount,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800755 openParams.mIdleConnectionTimeout, openParams.mJournalMode, openParams.mSyncMode);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700756 db.open();
757 return db;
758 }
759
760 /**
Vasu Nori74f170f2010-06-01 18:06:18 -0700761 * Open the database according to the flags {@link #OPEN_READWRITE}
762 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
763 *
764 * <p>Sets the locale of the database to the the system's current locale.
765 * Call {@link #setLocale} if you would like something else.</p>
766 *
767 * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be
768 * used to handle corruption when sqlite reports database corruption.</p>
769 *
770 * @param path to database file to open and/or create
771 * @param factory an optional factory class that is called to instantiate a
772 * cursor when query is called, or null for default
773 * @param flags to control database access mode
774 * @param errorHandler the {@link DatabaseErrorHandler} obj to be used to handle corruption
775 * when sqlite reports database corruption
776 * @return the newly opened database
777 * @throws SQLiteException if the database cannot be opened
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700778 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700779 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
780 @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler) {
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800781 SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1, -1, null,
782 null);
Jeff Browne5360fb2011-10-31 17:48:13 -0700783 db.open();
784 return db;
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700785 }
786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 /**
788 * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
789 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700790 public static SQLiteDatabase openOrCreateDatabase(@NonNull File file,
791 @Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792 return openOrCreateDatabase(file.getPath(), factory);
793 }
794
795 /**
796 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
797 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700798 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
799 @Nullable CursorFactory factory) {
Jeff Brown47847f32012-03-22 19:13:11 -0700800 return openDatabase(path, factory, CREATE_IF_NECESSARY, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 }
802
803 /**
Vasu Nori6c354da2010-04-26 23:33:39 -0700804 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler).
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700805 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700806 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
807 @Nullable CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler) {
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700808 return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler);
809 }
810
Jeff Brown559d0642012-02-29 10:19:12 -0800811 /**
Jeff Brown79087e42012-03-01 19:52:44 -0800812 * Deletes a database including its journal file and other auxiliary files
813 * that may have been created by the database engine.
814 *
815 * @param file The database file path.
816 * @return True if the database was successfully deleted.
817 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700818 public static boolean deleteDatabase(@NonNull File file) {
Makoto Onukiee93ad22018-10-18 16:24:13 -0700819 return deleteDatabase(file, /*removeCheckFile=*/ true);
820 }
821
822
823 /** @hide */
824 public static boolean deleteDatabase(@NonNull File file, boolean removeCheckFile) {
Jeff Brown79087e42012-03-01 19:52:44 -0800825 if (file == null) {
826 throw new IllegalArgumentException("file must not be null");
827 }
828
829 boolean deleted = false;
830 deleted |= file.delete();
831 deleted |= new File(file.getPath() + "-journal").delete();
832 deleted |= new File(file.getPath() + "-shm").delete();
833 deleted |= new File(file.getPath() + "-wal").delete();
834
Makoto Onukiee93ad22018-10-18 16:24:13 -0700835 // This file is not a standard SQLite file, so don't update the deleted flag.
836 new File(file.getPath() + SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX).delete();
837
Jeff Brown79087e42012-03-01 19:52:44 -0800838 File dir = file.getParentFile();
839 if (dir != null) {
840 final String prefix = file.getName() + "-mj";
Jeff Brownfce58902014-01-24 13:20:57 -0800841 File[] files = dir.listFiles(new FileFilter() {
Jeff Brown79087e42012-03-01 19:52:44 -0800842 @Override
843 public boolean accept(File candidate) {
844 return candidate.getName().startsWith(prefix);
845 }
Jeff Brownfce58902014-01-24 13:20:57 -0800846 });
847 if (files != null) {
848 for (File masterJournal : files) {
849 deleted |= masterJournal.delete();
850 }
Jeff Brown79087e42012-03-01 19:52:44 -0800851 }
852 }
853 return deleted;
854 }
855
856 /**
Jeff Brown559d0642012-02-29 10:19:12 -0800857 * Reopens the database in read-write mode.
858 * If the database is already read-write, does nothing.
859 *
860 * @throws SQLiteException if the database could not be reopened as requested, in which
861 * case it remains open in read only mode.
862 * @throws IllegalStateException if the database is not open.
863 *
864 * @see #isReadOnly()
865 * @hide
866 */
Mathew Inwood41b31942018-08-10 16:00:53 +0100867 @UnsupportedAppUsage
Jeff Brown559d0642012-02-29 10:19:12 -0800868 public void reopenReadWrite() {
869 synchronized (mLock) {
870 throwIfNotOpenLocked();
871
872 if (!isReadOnlyLocked()) {
873 return; // nothing to do
874 }
875
876 // Reopen the database in read-write mode.
877 final int oldOpenFlags = mConfigurationLocked.openFlags;
878 mConfigurationLocked.openFlags = (mConfigurationLocked.openFlags & ~OPEN_READ_MASK)
879 | OPEN_READWRITE;
880 try {
881 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
882 } catch (RuntimeException ex) {
883 mConfigurationLocked.openFlags = oldOpenFlags;
884 throw ex;
885 }
886 }
887 }
888
Jeff Browne5360fb2011-10-31 17:48:13 -0700889 private void open() {
890 try {
891 try {
892 openInner();
893 } catch (SQLiteDatabaseCorruptException ex) {
894 onCorruption();
895 openInner();
896 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700897 } catch (SQLiteException ex) {
898 Log.e(TAG, "Failed to open database '" + getLabel() + "'.", ex);
899 close();
900 throw ex;
901 }
902 }
903
904 private void openInner() {
905 synchronized (mLock) {
906 assert mConnectionPoolLocked == null;
907 mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked);
908 mCloseGuardLocked.open("close");
909 }
910
911 synchronized (sActiveDatabases) {
912 sActiveDatabases.put(this, null);
913 }
914 }
915
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700916 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 * Create a memory backed SQLite database. Its contents will be destroyed
918 * when the database is closed.
919 *
920 * <p>Sets the locale of the database to the the system's current locale.
921 * Call {@link #setLocale} if you would like something else.</p>
922 *
923 * @param factory an optional factory class that is called to instantiate a
924 * cursor when query is called
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700925 * @return a SQLiteDatabase instance
926 * @throws SQLiteException if the database cannot be created
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700928 @NonNull
929 public static SQLiteDatabase create(@Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 // This is a magic string with special meaning for SQLite.
Jeff Browne5360fb2011-10-31 17:48:13 -0700931 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
932 factory, CREATE_IF_NECESSARY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 }
934
935 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700936 * Create a memory backed SQLite database. Its contents will be destroyed
937 * when the database is closed.
938 *
939 * <p>Sets the locale of the database to the the system's current locale.
940 * Call {@link #setLocale} if you would like something else.</p>
941 * @param openParams configuration parameters that are used for opening SQLiteDatabase
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700942 * @return a SQLiteDatabase instance
943 * @throws SQLException if the database cannot be created
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700944 */
945 @NonNull
946 public static SQLiteDatabase createInMemory(@NonNull OpenParams openParams) {
947 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
948 openParams.toBuilder().addOpenFlags(CREATE_IF_NECESSARY).build());
949 }
950
951 /**
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400952 * Registers a CustomFunction callback as a function that can be called from
Jeff Browne5360fb2011-10-31 17:48:13 -0700953 * SQLite database triggers.
954 *
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400955 * @param name the name of the sqlite3 function
956 * @param numArgs the number of arguments for the function
957 * @param function callback to call when the function is executed
958 * @hide
959 */
960 public void addCustomFunction(String name, int numArgs, CustomFunction function) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700961 // Create wrapper (also validates arguments).
962 SQLiteCustomFunction wrapper = new SQLiteCustomFunction(name, numArgs, function);
963
964 synchronized (mLock) {
965 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -0700966
Jeff Browne5360fb2011-10-31 17:48:13 -0700967 mConfigurationLocked.customFunctions.add(wrapper);
Jeff Browne67ca422012-03-21 17:24:05 -0700968 try {
969 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
970 } catch (RuntimeException ex) {
971 mConfigurationLocked.customFunctions.remove(wrapper);
972 throw ex;
973 }
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400974 }
975 }
976
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400977 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 * Gets the database version.
979 *
980 * @return the database version
981 */
982 public int getVersion() {
Vasu Noriccd95442010-05-28 17:04:16 -0700983 return ((Long) DatabaseUtils.longForQuery(this, "PRAGMA user_version;", null)).intValue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 }
985
986 /**
987 * Sets the database version.
988 *
989 * @param version the new database version
990 */
991 public void setVersion(int version) {
992 execSQL("PRAGMA user_version = " + version);
993 }
994
995 /**
996 * Returns the maximum size the database may grow to.
997 *
998 * @return the new maximum database size
999 */
1000 public long getMaximumSize() {
Vasu Noriccd95442010-05-28 17:04:16 -07001001 long pageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count;", null);
1002 return pageCount * getPageSize();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 }
1004
1005 /**
1006 * Sets the maximum size the database will grow to. The maximum size cannot
1007 * be set below the current size.
1008 *
1009 * @param numBytes the maximum database size, in bytes
1010 * @return the new maximum database size
1011 */
1012 public long setMaximumSize(long numBytes) {
Vasu Noriccd95442010-05-28 17:04:16 -07001013 long pageSize = getPageSize();
1014 long numPages = numBytes / pageSize;
1015 // If numBytes isn't a multiple of pageSize, bump up a page
1016 if ((numBytes % pageSize) != 0) {
1017 numPages++;
Vasu Norif3cf8a42010-03-23 11:41:44 -07001018 }
Vasu Noriccd95442010-05-28 17:04:16 -07001019 long newPageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count = " + numPages,
1020 null);
1021 return newPageCount * pageSize;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 }
1023
1024 /**
1025 * Returns the current database page size, in bytes.
1026 *
1027 * @return the database page size, in bytes
1028 */
1029 public long getPageSize() {
Vasu Noriccd95442010-05-28 17:04:16 -07001030 return DatabaseUtils.longForQuery(this, "PRAGMA page_size;", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 }
1032
1033 /**
1034 * Sets the database page size. The page size must be a power of two. This
1035 * method does not work if any data has been written to the database file,
1036 * and must be called right after the database has been created.
1037 *
1038 * @param numBytes the database page size, in bytes
1039 */
1040 public void setPageSize(long numBytes) {
1041 execSQL("PRAGMA page_size = " + numBytes);
1042 }
1043
1044 /**
1045 * Mark this table as syncable. When an update occurs in this table the
1046 * _sync_dirty field will be set to ensure proper syncing operation.
1047 *
1048 * @param table the table to mark as syncable
1049 * @param deletedTable The deleted table that corresponds to the
1050 * syncable table
Vasu Nori95675132010-07-21 16:24:40 -07001051 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001052 */
Vasu Nori95675132010-07-21 16:24:40 -07001053 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 public void markTableSyncable(String table, String deletedTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 }
1056
1057 /**
1058 * Mark this table as syncable, with the _sync_dirty residing in another
1059 * table. When an update occurs in this table the _sync_dirty field of the
1060 * row in updateTable with the _id in foreignKey will be set to
1061 * ensure proper syncing operation.
1062 *
1063 * @param table an update on this table will trigger a sync time removal
1064 * @param foreignKey this is the column in table whose value is an _id in
1065 * updateTable
1066 * @param updateTable this is the table that will have its _sync_dirty
Vasu Nori95675132010-07-21 16:24:40 -07001067 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 */
Vasu Nori95675132010-07-21 16:24:40 -07001069 @Deprecated
1070 public void markTableSyncable(String table, String foreignKey, String updateTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 }
1072
1073 /**
1074 * Finds the name of the first table, which is editable.
1075 *
1076 * @param tables a list of tables
1077 * @return the first table listed
1078 */
1079 public static String findEditTable(String tables) {
1080 if (!TextUtils.isEmpty(tables)) {
1081 // find the first word terminated by either a space or a comma
1082 int spacepos = tables.indexOf(' ');
1083 int commapos = tables.indexOf(',');
1084
1085 if (spacepos > 0 && (spacepos < commapos || commapos < 0)) {
1086 return tables.substring(0, spacepos);
1087 } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) {
1088 return tables.substring(0, commapos);
1089 }
1090 return tables;
1091 } else {
1092 throw new IllegalStateException("Invalid tables");
1093 }
1094 }
1095
1096 /**
1097 * Compiles an SQL statement into a reusable pre-compiled statement object.
1098 * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the
1099 * statement and fill in those values with {@link SQLiteProgram#bindString}
1100 * and {@link SQLiteProgram#bindLong} each time you want to run the
1101 * statement. Statements may not return result sets larger than 1x1.
Vasu Nori2827d6d2010-07-04 00:26:18 -07001102 *<p>
1103 * No two threads should be using the same {@link SQLiteStatement} at the same time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 *
1105 * @param sql The raw SQL statement, may contain ? for unknown values to be
1106 * bound later.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001107 * @return A pre-compiled {@link SQLiteStatement} object. Note that
1108 * {@link SQLiteStatement}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 */
1110 public SQLiteStatement compileStatement(String sql) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001111 acquireReference();
1112 try {
1113 return new SQLiteStatement(this, sql, null);
1114 } finally {
1115 releaseReference();
1116 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001117 }
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 Hamiltonf3ca9a52010-05-12 15:04:33 -07001146 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1147 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 * @see Cursor
1149 */
1150 public Cursor query(boolean distinct, String table, String[] columns,
1151 String selection, String[] selectionArgs, String groupBy,
1152 String having, String orderBy, String limit) {
1153 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown75ea64f2012-01-25 19:37:13 -08001154 groupBy, having, orderBy, limit, null);
1155 }
1156
1157 /**
1158 * Query the given URL, returning a {@link Cursor} over the result set.
1159 *
1160 * @param distinct true if you want each row to be unique, false otherwise.
1161 * @param table The table name to compile the query against.
1162 * @param columns A list of which columns to return. Passing null will
1163 * return all columns, which is discouraged to prevent reading
1164 * data from storage that isn't going to be used.
1165 * @param selection A filter declaring which rows to return, formatted as an
1166 * SQL WHERE clause (excluding the WHERE itself). Passing null
1167 * will return all rows for the given table.
1168 * @param selectionArgs You may include ?s in selection, which will be
1169 * replaced by the values from selectionArgs, in order that they
1170 * appear in the selection. The values will be bound as Strings.
1171 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1172 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1173 * will cause the rows to not be grouped.
1174 * @param having A filter declare which row groups to include in the cursor,
1175 * if row grouping is being used, formatted as an SQL HAVING
1176 * clause (excluding the HAVING itself). Passing null will cause
1177 * all row groups to be included, and is required when row
1178 * grouping is not being used.
1179 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1180 * (excluding the ORDER BY itself). Passing null will use the
1181 * default sort order, which may be unordered.
1182 * @param limit Limits the number of rows returned by the query,
1183 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001184 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001185 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1186 * when the query is executed.
1187 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1188 * {@link Cursor}s are not synchronized, see the documentation for more details.
1189 * @see Cursor
1190 */
1191 public Cursor query(boolean distinct, String table, String[] columns,
1192 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001193 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001194 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001195 groupBy, having, orderBy, limit, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196 }
1197
1198 /**
1199 * Query the given URL, returning a {@link Cursor} over the result set.
1200 *
1201 * @param cursorFactory the cursor factory to use, or null for the default factory
1202 * @param distinct true if you want each row to be unique, false otherwise.
1203 * @param table The table name to compile the query against.
1204 * @param columns A list of which columns to return. Passing null will
1205 * return all columns, which is discouraged to prevent reading
1206 * data from storage that isn't going to be used.
1207 * @param selection A filter declaring which rows to return, formatted as an
1208 * SQL WHERE clause (excluding the WHERE itself). Passing null
1209 * will return all rows for the given table.
1210 * @param selectionArgs You may include ?s in selection, which will be
1211 * replaced by the values from selectionArgs, in order that they
1212 * appear in the selection. The values will be bound as Strings.
1213 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1214 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1215 * will cause the rows to not be grouped.
1216 * @param having A filter declare which row groups to include in the cursor,
1217 * if row grouping is being used, formatted as an SQL HAVING
1218 * clause (excluding the HAVING itself). Passing null will cause
1219 * all row groups to be included, and is required when row
1220 * grouping is not being used.
1221 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1222 * (excluding the ORDER BY itself). Passing null will use the
1223 * default sort order, which may be unordered.
1224 * @param limit Limits the number of rows returned by the query,
1225 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001226 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1227 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 * @see Cursor
1229 */
1230 public Cursor queryWithFactory(CursorFactory cursorFactory,
1231 boolean distinct, String table, String[] columns,
1232 String selection, String[] selectionArgs, String groupBy,
1233 String having, String orderBy, String limit) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001234 return queryWithFactory(cursorFactory, distinct, table, columns, selection,
1235 selectionArgs, groupBy, having, orderBy, limit, null);
1236 }
1237
1238 /**
1239 * Query the given URL, returning a {@link Cursor} over the result set.
1240 *
1241 * @param cursorFactory the cursor factory to use, or null for the default factory
1242 * @param distinct true if you want each row to be unique, false otherwise.
1243 * @param table The table name to compile the query against.
1244 * @param columns A list of which columns to return. Passing null will
1245 * return all columns, which is discouraged to prevent reading
1246 * data from storage that isn't going to be used.
1247 * @param selection A filter declaring which rows to return, formatted as an
1248 * SQL WHERE clause (excluding the WHERE itself). Passing null
1249 * will return all rows for the given table.
1250 * @param selectionArgs You may include ?s in selection, which will be
1251 * replaced by the values from selectionArgs, in order that they
1252 * appear in the selection. The values will be bound as Strings.
1253 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1254 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1255 * will cause the rows to not be grouped.
1256 * @param having A filter declare which row groups to include in the cursor,
1257 * if row grouping is being used, formatted as an SQL HAVING
1258 * clause (excluding the HAVING itself). Passing null will cause
1259 * all row groups to be included, and is required when row
1260 * grouping is not being used.
1261 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1262 * (excluding the ORDER BY itself). Passing null will use the
1263 * default sort order, which may be unordered.
1264 * @param limit Limits the number of rows returned by the query,
1265 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001266 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001267 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1268 * when the query is executed.
1269 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1270 * {@link Cursor}s are not synchronized, see the documentation for more details.
1271 * @see Cursor
1272 */
1273 public Cursor queryWithFactory(CursorFactory cursorFactory,
1274 boolean distinct, String table, String[] columns,
1275 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001276 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001277 acquireReference();
1278 try {
1279 String sql = SQLiteQueryBuilder.buildQueryString(
1280 distinct, table, columns, selection, groupBy, having, orderBy, limit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001281
Jeff Brown03bd3022012-03-06 13:48:56 -08001282 return rawQueryWithFactory(cursorFactory, sql, selectionArgs,
1283 findEditTable(table), cancellationSignal);
1284 } finally {
1285 releaseReference();
1286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 }
1288
1289 /**
1290 * Query the given table, returning a {@link Cursor} over the result set.
1291 *
1292 * @param table The table name to compile the query against.
1293 * @param columns A list of which columns to return. Passing null will
1294 * return all columns, which is discouraged to prevent reading
1295 * data from storage that isn't going to be used.
1296 * @param selection A filter declaring which rows to return, formatted as an
1297 * SQL WHERE clause (excluding the WHERE itself). Passing null
1298 * will return all rows for the given table.
1299 * @param selectionArgs You may include ?s in selection, which will be
1300 * replaced by the values from selectionArgs, in order that they
1301 * appear in the selection. The values will be bound as Strings.
1302 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1303 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1304 * will cause the rows to not be grouped.
1305 * @param having A filter declare which row groups to include in the cursor,
1306 * if row grouping is being used, formatted as an SQL HAVING
1307 * clause (excluding the HAVING itself). Passing null will cause
1308 * all row groups to be included, and is required when row
1309 * grouping is not being used.
1310 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1311 * (excluding the ORDER BY itself). Passing null will use the
1312 * default sort order, which may be unordered.
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) {
1320
1321 return query(false, table, columns, selection, selectionArgs, groupBy,
1322 having, orderBy, null /* limit */);
1323 }
1324
1325 /**
1326 * Query the given table, returning a {@link Cursor} over the result set.
1327 *
1328 * @param table The table name to compile the query against.
1329 * @param columns A list of which columns to return. Passing null will
1330 * return all columns, which is discouraged to prevent reading
1331 * data from storage that isn't going to be used.
1332 * @param selection A filter declaring which rows to return, formatted as an
1333 * SQL WHERE clause (excluding the WHERE itself). Passing null
1334 * will return all rows for the given table.
1335 * @param selectionArgs You may include ?s in selection, which will be
1336 * replaced by the values from selectionArgs, in order that they
1337 * appear in the selection. The values will be bound as Strings.
1338 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1339 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1340 * will cause the rows to not be grouped.
1341 * @param having A filter declare which row groups to include in the cursor,
1342 * if row grouping is being used, formatted as an SQL HAVING
1343 * clause (excluding the HAVING itself). Passing null will cause
1344 * all row groups to be included, and is required when row
1345 * grouping is not being used.
1346 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1347 * (excluding the ORDER BY itself). Passing null will use the
1348 * default sort order, which may be unordered.
1349 * @param limit Limits the number of rows returned by the query,
1350 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001351 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1352 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 * @see Cursor
1354 */
1355 public Cursor query(String table, String[] columns, String selection,
1356 String[] selectionArgs, String groupBy, String having,
1357 String orderBy, String limit) {
1358
1359 return query(false, table, columns, selection, selectionArgs, groupBy,
1360 having, orderBy, limit);
1361 }
1362
1363 /**
1364 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1365 *
1366 * @param sql the SQL query. The SQL string must not be ; terminated
1367 * @param selectionArgs You may include ?s in where clause in the query,
1368 * which will be replaced by the values from selectionArgs. The
1369 * values will be bound as Strings.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001370 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1371 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 */
1373 public Cursor rawQuery(String sql, String[] selectionArgs) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001374 return rawQueryWithFactory(null, sql, selectionArgs, null, null);
1375 }
1376
1377 /**
1378 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1379 *
1380 * @param sql the SQL query. The SQL string must not be ; terminated
1381 * @param selectionArgs You may include ?s in where clause in the query,
1382 * which will be replaced by the values from selectionArgs. The
1383 * values will be bound as Strings.
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 rawQuery(String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001391 CancellationSignal cancellationSignal) {
1392 return rawQueryWithFactory(null, sql, selectionArgs, null, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 }
1394
1395 /**
1396 * Runs the provided SQL and returns a cursor over the result set.
1397 *
1398 * @param cursorFactory the cursor factory to use, or null for the default factory
1399 * @param sql the SQL query. The SQL string must not be ; terminated
1400 * @param selectionArgs You may include ?s in where clause in the query,
1401 * which will be replaced by the values from selectionArgs. The
1402 * values will be bound as Strings.
1403 * @param editTable the name of the first table, which is editable
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001404 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1405 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 */
1407 public Cursor rawQueryWithFactory(
1408 CursorFactory cursorFactory, String sql, String[] selectionArgs,
1409 String editTable) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001410 return rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable, null);
1411 }
1412
1413 /**
1414 * Runs the provided SQL and returns a cursor over the result set.
1415 *
1416 * @param cursorFactory the cursor factory to use, or null for the default factory
1417 * @param sql the SQL query. The SQL string must not be ; terminated
1418 * @param selectionArgs You may include ?s in where clause in the query,
1419 * which will be replaced by the values from selectionArgs. The
1420 * values will be bound as Strings.
1421 * @param editTable the name of the first table, which is editable
Jeff Brown4c1241d2012-02-02 17:05:00 -08001422 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001423 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1424 * when the query is executed.
1425 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1426 * {@link Cursor}s are not synchronized, see the documentation for more details.
1427 */
1428 public Cursor rawQueryWithFactory(
1429 CursorFactory cursorFactory, String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001430 String editTable, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001431 acquireReference();
1432 try {
1433 SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
1434 cancellationSignal);
1435 return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
1436 selectionArgs);
1437 } finally {
1438 releaseReference();
1439 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 }
1441
1442 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 * Convenience method for inserting a row into the database.
1444 *
1445 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001446 * @param nullColumnHack optional; may be <code>null</code>.
1447 * SQL doesn't allow inserting a completely empty row without
1448 * naming at least one column name. If your provided <code>values</code> is
1449 * empty, no column names are known and an empty row can't be inserted.
1450 * If not set to null, the <code>nullColumnHack</code> parameter
1451 * provides the name of nullable column name to explicitly insert a NULL into
1452 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 * @param values this map contains the initial column values for the
1454 * row. The keys should be the column names and the values the
1455 * column values
1456 * @return the row ID of the newly inserted row, or -1 if an error occurred
1457 */
1458 public long insert(String table, String nullColumnHack, ContentValues values) {
1459 try {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001460 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 } catch (SQLException e) {
1462 Log.e(TAG, "Error inserting " + values, e);
1463 return -1;
1464 }
1465 }
1466
1467 /**
1468 * Convenience method for inserting a row into the database.
1469 *
1470 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001471 * @param nullColumnHack optional; may be <code>null</code>.
1472 * SQL doesn't allow inserting a completely empty row without
1473 * naming at least one column name. If your provided <code>values</code> is
1474 * empty, no column names are known and an empty row can't be inserted.
1475 * If not set to null, the <code>nullColumnHack</code> parameter
1476 * provides the name of nullable column name to explicitly insert a NULL into
1477 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 * @param values this map contains the initial column values for the
1479 * row. The keys should be the column names and the values the
1480 * column values
1481 * @throws SQLException
1482 * @return the row ID of the newly inserted row, or -1 if an error occurred
1483 */
1484 public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
1485 throws SQLException {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001486 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 }
1488
1489 /**
1490 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001491 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 *
1493 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001494 * @param nullColumnHack optional; may be <code>null</code>.
1495 * SQL doesn't allow inserting a completely empty row without
1496 * naming at least one column name. If your provided <code>initialValues</code> is
1497 * empty, no column names are known and an empty row can't be inserted.
1498 * If not set to null, the <code>nullColumnHack</code> parameter
1499 * provides the name of nullable column name to explicitly insert a NULL into
1500 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001502 * 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 -08001503 * @return the row ID of the newly inserted row, or -1 if an error occurred
1504 */
1505 public long replace(String table, String nullColumnHack, ContentValues initialValues) {
1506 try {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001507 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001508 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 } catch (SQLException e) {
1510 Log.e(TAG, "Error inserting " + initialValues, e);
1511 return -1;
1512 }
1513 }
1514
1515 /**
1516 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001517 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 *
1519 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001520 * @param nullColumnHack optional; may be <code>null</code>.
1521 * SQL doesn't allow inserting a completely empty row without
1522 * naming at least one column name. If your provided <code>initialValues</code> is
1523 * empty, no column names are known and an empty row can't be inserted.
1524 * If not set to null, the <code>nullColumnHack</code> parameter
1525 * provides the name of nullable column name to explicitly insert a NULL into
1526 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001527 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001528 * 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 -08001529 * @throws SQLException
1530 * @return the row ID of the newly inserted row, or -1 if an error occurred
1531 */
1532 public long replaceOrThrow(String table, String nullColumnHack,
1533 ContentValues initialValues) throws SQLException {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001534 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001535 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 }
1537
1538 /**
1539 * General method for inserting a row into the database.
1540 *
1541 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001542 * @param nullColumnHack optional; may be <code>null</code>.
1543 * SQL doesn't allow inserting a completely empty row without
1544 * naming at least one column name. If your provided <code>initialValues</code> is
1545 * empty, no column names are known and an empty row can't be inserted.
1546 * If not set to null, the <code>nullColumnHack</code> parameter
1547 * provides the name of nullable column name to explicitly insert a NULL into
1548 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 * @param initialValues this map contains the initial column values for the
1550 * row. The keys should be the column names and the values the
1551 * column values
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001552 * @param conflictAlgorithm for insert conflict resolver
Steve Pomeroyc240b602013-03-14 00:42:10 -04001553 * @return the row ID of the newly inserted row OR <code>-1</code> if either the
1554 * input parameter <code>conflictAlgorithm</code> = {@link #CONFLICT_IGNORE}
1555 * or an error occurred.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001556 */
1557 public long insertWithOnConflict(String table, String nullColumnHack,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001558 ContentValues initialValues, int conflictAlgorithm) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001559 acquireReference();
1560 try {
1561 StringBuilder sql = new StringBuilder();
1562 sql.append("INSERT");
1563 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1564 sql.append(" INTO ");
1565 sql.append(table);
1566 sql.append('(');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567
Jeff Brown03bd3022012-03-06 13:48:56 -08001568 Object[] bindArgs = null;
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001569 int size = (initialValues != null && !initialValues.isEmpty())
Jeff Brown03bd3022012-03-06 13:48:56 -08001570 ? initialValues.size() : 0;
1571 if (size > 0) {
1572 bindArgs = new Object[size];
1573 int i = 0;
1574 for (String colName : initialValues.keySet()) {
1575 sql.append((i > 0) ? "," : "");
1576 sql.append(colName);
1577 bindArgs[i++] = initialValues.get(colName);
1578 }
1579 sql.append(')');
1580 sql.append(" VALUES (");
1581 for (i = 0; i < size; i++) {
1582 sql.append((i > 0) ? ",?" : "?");
1583 }
1584 } else {
1585 sql.append(nullColumnHack + ") VALUES (NULL");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 sql.append(')');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588
Jeff Brown03bd3022012-03-06 13:48:56 -08001589 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1590 try {
1591 return statement.executeInsert();
1592 } finally {
1593 statement.close();
1594 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001596 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 }
1598 }
1599
1600 /**
1601 * Convenience method for deleting rows in the database.
1602 *
1603 * @param table the table to delete from
1604 * @param whereClause the optional WHERE clause to apply when deleting.
1605 * Passing null will delete all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001606 * @param whereArgs You may include ?s in the where clause, which
1607 * will be replaced by the values from whereArgs. The values
1608 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001609 * @return the number of rows affected if a whereClause is passed in, 0
1610 * otherwise. To remove all rows and get a count pass "1" as the
1611 * whereClause.
1612 */
1613 public int delete(String table, String whereClause, String[] whereArgs) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001614 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001616 SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table +
1617 (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
1618 try {
1619 return statement.executeUpdateDelete();
1620 } finally {
1621 statement.close();
1622 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001624 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 }
1626 }
1627
1628 /**
1629 * Convenience method for updating rows in the database.
1630 *
1631 * @param table the table to update in
1632 * @param values a map from column names to new column values. null is a
1633 * valid value that will be translated to NULL.
1634 * @param whereClause the optional WHERE clause to apply when updating.
1635 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001636 * @param whereArgs You may include ?s in the where clause, which
1637 * will be replaced by the values from whereArgs. The values
1638 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 * @return the number of rows affected
1640 */
1641 public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001642 return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 /**
1646 * Convenience method for updating rows in the database.
1647 *
1648 * @param table the table to update in
1649 * @param values a map from column names to new column values. null is a
1650 * valid value that will be translated to NULL.
1651 * @param whereClause the optional WHERE clause to apply when updating.
1652 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001653 * @param whereArgs You may include ?s in the where clause, which
1654 * will be replaced by the values from whereArgs. The values
1655 * will be bound as Strings.
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001656 * @param conflictAlgorithm for update conflict resolver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 * @return the number of rows affected
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 */
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001659 public int updateWithOnConflict(String table, ContentValues values,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001660 String whereClause, String[] whereArgs, int conflictAlgorithm) {
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001661 if (values == null || values.isEmpty()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 throw new IllegalArgumentException("Empty values");
1663 }
1664
Jeff Brown03bd3022012-03-06 13:48:56 -08001665 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001667 StringBuilder sql = new StringBuilder(120);
1668 sql.append("UPDATE ");
1669 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1670 sql.append(table);
1671 sql.append(" SET ");
1672
1673 // move all bind args to one array
1674 int setValuesSize = values.size();
1675 int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
1676 Object[] bindArgs = new Object[bindArgsSize];
1677 int i = 0;
1678 for (String colName : values.keySet()) {
1679 sql.append((i > 0) ? "," : "");
1680 sql.append(colName);
1681 bindArgs[i++] = values.get(colName);
1682 sql.append("=?");
1683 }
1684 if (whereArgs != null) {
1685 for (i = setValuesSize; i < bindArgsSize; i++) {
1686 bindArgs[i] = whereArgs[i - setValuesSize];
1687 }
1688 }
1689 if (!TextUtils.isEmpty(whereClause)) {
1690 sql.append(" WHERE ");
1691 sql.append(whereClause);
1692 }
1693
1694 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1695 try {
1696 return statement.executeUpdateDelete();
1697 } finally {
1698 statement.close();
1699 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001701 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 }
1703 }
1704
1705 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001706 * Execute a single SQL statement that is NOT a SELECT
1707 * or any other SQL statement that returns data.
1708 * <p>
Vasu Norice38b982010-07-22 13:57:13 -07001709 * It has no means to return any data (such as the number of affected rows).
Vasu Noriccd95442010-05-28 17:04:16 -07001710 * Instead, you're encouraged to use {@link #insert(String, String, ContentValues)},
1711 * {@link #update(String, ContentValues, String, String[])}, et al, when possible.
1712 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001713 * <p>
1714 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1715 * automatically managed by this class. So, do not set journal_mode
1716 * using "PRAGMA journal_mode'<value>" statement if your app is using
1717 * {@link #enableWriteAheadLogging()}
1718 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001719 *
Vasu Noriccd95442010-05-28 17:04:16 -07001720 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1721 * not supported.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001722 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001724 public void execSQL(String sql) throws SQLException {
Vasu Nori16057fa2011-03-18 11:40:37 -07001725 executeSql(sql, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726 }
1727
1728 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001729 * Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE.
1730 * <p>
1731 * For INSERT statements, use any of the following instead.
1732 * <ul>
1733 * <li>{@link #insert(String, String, ContentValues)}</li>
1734 * <li>{@link #insertOrThrow(String, String, ContentValues)}</li>
1735 * <li>{@link #insertWithOnConflict(String, String, ContentValues, int)}</li>
1736 * </ul>
1737 * <p>
1738 * For UPDATE statements, use any of the following instead.
1739 * <ul>
1740 * <li>{@link #update(String, ContentValues, String, String[])}</li>
1741 * <li>{@link #updateWithOnConflict(String, ContentValues, String, String[], int)}</li>
1742 * </ul>
1743 * <p>
1744 * For DELETE statements, use any of the following instead.
1745 * <ul>
1746 * <li>{@link #delete(String, String, String[])}</li>
1747 * </ul>
1748 * <p>
1749 * For example, the following are good candidates for using this method:
1750 * <ul>
1751 * <li>ALTER TABLE</li>
1752 * <li>CREATE or DROP table / trigger / view / index / virtual table</li>
1753 * <li>REINDEX</li>
1754 * <li>RELEASE</li>
1755 * <li>SAVEPOINT</li>
1756 * <li>PRAGMA that returns no data</li>
1757 * </ul>
1758 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001759 * <p>
1760 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1761 * automatically managed by this class. So, do not set journal_mode
1762 * using "PRAGMA journal_mode'<value>" statement if your app is using
1763 * {@link #enableWriteAheadLogging()}
1764 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 *
Vasu Noriccd95442010-05-28 17:04:16 -07001766 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1767 * not supported.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 * @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001769 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001771 public void execSQL(String sql, Object[] bindArgs) throws SQLException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 if (bindArgs == null) {
1773 throw new IllegalArgumentException("Empty bindArgs");
1774 }
Vasu Norib83cb7c2010-09-14 13:36:01 -07001775 executeSql(sql, bindArgs);
Vasu Norice38b982010-07-22 13:57:13 -07001776 }
1777
Jeff Sharkey6adc98c2018-07-12 19:47:49 -06001778 /** {@hide} */
1779 public int executeSql(String sql, Object[] bindArgs) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001780 acquireReference();
1781 try {
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001782 final int statementType = DatabaseUtils.getSqlStatementType(sql);
1783 if (statementType == DatabaseUtils.STATEMENT_ATTACH) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001784 boolean disableWal = false;
1785 synchronized (mLock) {
1786 if (!mHasAttachedDbsLocked) {
1787 mHasAttachedDbsLocked = true;
1788 disableWal = true;
Fyodor Kupolovfd9c4a52017-07-13 15:36:57 -07001789 mConnectionPoolLocked.disableIdleConnectionHandler();
Jeff Brown03bd3022012-03-06 13:48:56 -08001790 }
1791 }
1792 if (disableWal) {
1793 disableWriteAheadLogging();
Jeff Browne5360fb2011-10-31 17:48:13 -07001794 }
1795 }
Jeff Browne5360fb2011-10-31 17:48:13 -07001796
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001797 try (SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs)) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001798 return statement.executeUpdateDelete();
1799 } finally {
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001800 // If schema was updated, close non-primary connections, otherwise they might
1801 // have outdated schema information
1802 if (statementType == DatabaseUtils.STATEMENT_DDL) {
1803 mConnectionPoolLocked.closeAvailableNonPrimaryConnectionsAndLogExceptions();
1804 }
Jeff Brown03bd3022012-03-06 13:48:56 -08001805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001806 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001807 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 }
1810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 /**
Makoto Onuki17aa1b72015-12-16 14:02:01 -08001812 * Verifies that a SQL SELECT statement is valid by compiling it.
1813 * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
1814 *
1815 * @param sql SQL to be validated
1816 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
1817 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1818 * when the query is executed.
1819 * @throws SQLiteException if {@code sql} is invalid
1820 */
1821 public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal) {
1822 getThreadSession().prepare(sql,
1823 getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null);
1824 }
1825
1826 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001827 * Returns true if the database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001828 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001829 * @return True if database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 */
1831 public boolean isReadOnly() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001832 synchronized (mLock) {
1833 return isReadOnlyLocked();
1834 }
1835 }
1836
1837 private boolean isReadOnlyLocked() {
1838 return (mConfigurationLocked.openFlags & OPEN_READ_MASK) == OPEN_READONLY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 }
1840
1841 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001842 * Returns true if the database is in-memory db.
1843 *
1844 * @return True if the database is in-memory.
1845 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 */
Jeff Browne5360fb2011-10-31 17:48:13 -07001847 public boolean isInMemoryDatabase() {
1848 synchronized (mLock) {
1849 return mConfigurationLocked.isInMemoryDb();
1850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001851 }
1852
Jeff Browne5360fb2011-10-31 17:48:13 -07001853 /**
1854 * Returns true if the database is currently open.
1855 *
1856 * @return True if the database is currently open (has not been closed).
1857 */
1858 public boolean isOpen() {
1859 synchronized (mLock) {
1860 return mConnectionPoolLocked != null;
1861 }
1862 }
1863
1864 /**
1865 * Returns true if the new version code is greater than the current database version.
1866 *
1867 * @param newVersion The new version code.
Mark Lu1e202082016-08-30 17:41:25 -07001868 * @return True if the new version code is greater than the current database version.
Jeff Browne5360fb2011-10-31 17:48:13 -07001869 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001870 public boolean needUpgrade(int newVersion) {
1871 return newVersion > getVersion();
1872 }
1873
1874 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001875 * Gets the path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001877 * @return The path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001878 */
1879 public final String getPath() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001880 synchronized (mLock) {
1881 return mConfigurationLocked.path;
Christopher Tatead9e8b12011-10-05 17:49:26 -07001882 }
Brad Fitzpatrick722802e2010-03-23 22:22:16 -07001883 }
1884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 /**
1886 * Sets the locale for this database. Does nothing if this database has
Jeff Brown1d9f7422012-03-15 14:32:32 -07001887 * the {@link #NO_LOCALIZED_COLLATORS} flag set or was opened read only.
Jeff Browne5360fb2011-10-31 17:48:13 -07001888 *
1889 * @param locale The new locale.
1890 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001891 * @throws SQLException if the locale could not be set. The most common reason
1892 * for this is that there is no collator available for the locale you requested.
1893 * In this case the database remains unchanged.
1894 */
1895 public void setLocale(Locale locale) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001896 if (locale == null) {
1897 throw new IllegalArgumentException("locale must not be null.");
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001898 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001899
Jeff Browne5360fb2011-10-31 17:48:13 -07001900 synchronized (mLock) {
1901 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001902
1903 final Locale oldLocale = mConfigurationLocked.locale;
Jeff Browne5360fb2011-10-31 17:48:13 -07001904 mConfigurationLocked.locale = locale;
Jeff Browne67ca422012-03-21 17:24:05 -07001905 try {
1906 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1907 } catch (RuntimeException ex) {
1908 mConfigurationLocked.locale = oldLocale;
1909 throw ex;
1910 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001911 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001912 }
1913
Vasu Norie495d1f2010-01-06 16:34:19 -08001914 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001915 * Sets the maximum size of the prepared-statement cache for this database.
Vasu Norie495d1f2010-01-06 16:34:19 -08001916 * (size of the cache = number of compiled-sql-statements stored in the cache).
Vasu Noriccd95442010-05-28 17:04:16 -07001917 *<p>
Vasu Norib729dcc2010-09-14 11:35:49 -07001918 * Maximum cache size can ONLY be increased from its current size (default = 10).
Vasu Noriccd95442010-05-28 17:04:16 -07001919 * If this method is called with smaller size than the current maximum value,
1920 * then IllegalStateException is thrown.
Vasu Norib729dcc2010-09-14 11:35:49 -07001921 *<p>
1922 * This method is thread-safe.
Vasu Norie495d1f2010-01-06 16:34:19 -08001923 *
Vasu Nori90a367262010-04-12 12:49:09 -07001924 * @param cacheSize the size of the cache. can be (0 to {@link #MAX_SQL_CACHE_SIZE})
Jeff Browne5360fb2011-10-31 17:48:13 -07001925 * @throws IllegalStateException if input cacheSize > {@link #MAX_SQL_CACHE_SIZE}.
Vasu Norie495d1f2010-01-06 16:34:19 -08001926 */
Vasu Nori54025902010-09-14 12:14:26 -07001927 public void setMaxSqlCacheSize(int cacheSize) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001928 if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) {
1929 throw new IllegalStateException(
1930 "expected value between 0 and " + MAX_SQL_CACHE_SIZE);
Vasu Nori587423a2010-09-27 18:18:34 -07001931 }
Vasu Nori587423a2010-09-27 18:18:34 -07001932
Jeff Browne5360fb2011-10-31 17:48:13 -07001933 synchronized (mLock) {
1934 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001935
1936 final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize;
Jeff Browne5360fb2011-10-31 17:48:13 -07001937 mConfigurationLocked.maxSqlCacheSize = cacheSize;
Jeff Browne67ca422012-03-21 17:24:05 -07001938 try {
1939 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1940 } catch (RuntimeException ex) {
1941 mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize;
1942 throw ex;
1943 }
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001944 }
1945 }
1946
Vasu Nori6c354da2010-04-26 23:33:39 -07001947 /**
Jeff Brown96496ad2012-03-23 14:38:06 -07001948 * Sets whether foreign key constraints are enabled for the database.
1949 * <p>
1950 * By default, foreign key constraints are not enforced by the database.
1951 * This method allows an application to enable foreign key constraints.
1952 * It must be called each time the database is opened to ensure that foreign
1953 * key constraints are enabled for the session.
1954 * </p><p>
1955 * A good time to call this method is right after calling {@link #openOrCreateDatabase}
1956 * or in the {@link SQLiteOpenHelper#onConfigure} callback.
1957 * </p><p>
1958 * When foreign key constraints are disabled, the database does not check whether
1959 * changes to the database will violate foreign key constraints. Likewise, when
1960 * foreign key constraints are disabled, the database will not execute cascade
1961 * delete or update triggers. As a result, it is possible for the database
1962 * state to become inconsistent. To perform a database integrity check,
1963 * call {@link #isDatabaseIntegrityOk}.
1964 * </p><p>
1965 * This method must not be called while a transaction is in progress.
1966 * </p><p>
1967 * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a>
1968 * for more details about foreign key constraint support.
1969 * </p>
1970 *
1971 * @param enable True to enable foreign key constraints, false to disable them.
1972 *
1973 * @throws IllegalStateException if the are transactions is in progress
1974 * when this method is called.
1975 */
1976 public void setForeignKeyConstraintsEnabled(boolean enable) {
1977 synchronized (mLock) {
1978 throwIfNotOpenLocked();
1979
1980 if (mConfigurationLocked.foreignKeyConstraintsEnabled == enable) {
1981 return;
1982 }
1983
1984 mConfigurationLocked.foreignKeyConstraintsEnabled = enable;
1985 try {
1986 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1987 } catch (RuntimeException ex) {
1988 mConfigurationLocked.foreignKeyConstraintsEnabled = !enable;
1989 throw ex;
1990 }
1991 }
1992 }
1993
1994 /**
Jeff Brown47847f32012-03-22 19:13:11 -07001995 * This method enables parallel execution of queries from multiple threads on the
1996 * same database. It does this by opening multiple connections to the database
1997 * and using a different database connection for each query. The database
1998 * journal mode is also changed to enable writes to proceed concurrently with reads.
Vasu Nori6c354da2010-04-26 23:33:39 -07001999 * <p>
Jeff Brown47847f32012-03-22 19:13:11 -07002000 * When write-ahead logging is not enabled (the default), it is not possible for
2001 * reads and writes to occur on the database at the same time. Before modifying the
2002 * database, the writer implicitly acquires an exclusive lock on the database which
2003 * prevents readers from accessing the database until the write is completed.
2004 * </p><p>
2005 * In contrast, when write-ahead logging is enabled (by calling this method), write
2006 * operations occur in a separate log file which allows reads to proceed concurrently.
2007 * While a write is in progress, readers on other threads will perceive the state
2008 * of the database as it was before the write began. When the write completes, readers
2009 * on other threads will then perceive the new state of the database.
2010 * </p><p>
2011 * It is a good idea to enable write-ahead logging whenever a database will be
2012 * concurrently accessed and modified by multiple threads at the same time.
2013 * However, write-ahead logging uses significantly more memory than ordinary
2014 * journaling because there are multiple connections to the same database.
2015 * So if a database will only be used by a single thread, or if optimizing
2016 * concurrency is not very important, then write-ahead logging should be disabled.
2017 * </p><p>
2018 * After calling this method, execution of queries in parallel is enabled as long as
2019 * the database remains open. To disable execution of queries in parallel, either
2020 * call {@link #disableWriteAheadLogging} or close the database and reopen it.
2021 * </p><p>
2022 * The maximum number of connections used to execute queries in parallel is
Vasu Nori6c354da2010-04-26 23:33:39 -07002023 * dependent upon the device memory and possibly other properties.
Jeff Brown47847f32012-03-22 19:13:11 -07002024 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07002025 * If a query is part of a transaction, then it is executed on the same database handle the
2026 * transaction was begun.
Jeff Brown47847f32012-03-22 19:13:11 -07002027 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07002028 * Writers should use {@link #beginTransactionNonExclusive()} or
2029 * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
Jeff Brown47847f32012-03-22 19:13:11 -07002030 * to start a transaction. Non-exclusive mode allows database file to be in readable
2031 * by other threads executing queries.
2032 * </p><p>
2033 * If the database has any attached databases, then execution of queries in parallel is NOT
2034 * possible. Likewise, write-ahead logging is not supported for read-only databases
2035 * or memory databases. In such cases, {@link #enableWriteAheadLogging} returns false.
2036 * </p><p>
2037 * The best way to enable write-ahead logging is to pass the
2038 * {@link #ENABLE_WRITE_AHEAD_LOGGING} flag to {@link #openDatabase}. This is
2039 * more efficient than calling {@link #enableWriteAheadLogging}.
2040 * <code><pre>
2041 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2042 * SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
2043 * myDatabaseErrorHandler);
Jeff Brown47847f32012-03-22 19:13:11 -07002044 * </pre></code>
2045 * </p><p>
2046 * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging}
2047 * after opening the database.
2048 * <code><pre>
2049 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2050 * SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
2051 * db.enableWriteAheadLogging();
2052 * </pre></code>
2053 * </p><p>
2054 * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for
2055 * more details about how write-ahead logging works.
Vasu Nori6c354da2010-04-26 23:33:39 -07002056 * </p>
2057 *
Jeff Brown47847f32012-03-22 19:13:11 -07002058 * @return True if write-ahead logging is enabled.
Jeff Browne67ca422012-03-21 17:24:05 -07002059 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002060 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002061 * time this method is called. WAL mode can only be changed when there are no
2062 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002063 *
2064 * @see #ENABLE_WRITE_AHEAD_LOGGING
2065 * @see #disableWriteAheadLogging
Vasu Nori6c354da2010-04-26 23:33:39 -07002066 */
Vasu Noriffe06122010-09-27 12:32:57 -07002067 public boolean enableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002068 synchronized (mLock) {
2069 throwIfNotOpenLocked();
2070
Jeff Brown47847f32012-03-22 19:13:11 -07002071 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002072 return true;
2073 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002074
2075 if (isReadOnlyLocked()) {
2076 // WAL doesn't make sense for readonly-databases.
2077 // TODO: True, but connection pooling does still make sense...
2078 return false;
2079 }
2080
2081 if (mConfigurationLocked.isInMemoryDb()) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002082 Log.i(TAG, "can't enable WAL for memory databases.");
2083 return false;
2084 }
2085
2086 // make sure this database has NO attached databases because sqlite's write-ahead-logging
2087 // doesn't work for databases with attached databases
Jeff Browne5360fb2011-10-31 17:48:13 -07002088 if (mHasAttachedDbsLocked) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002089 if (Log.isLoggable(TAG, Log.DEBUG)) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002090 Log.d(TAG, "this database: " + mConfigurationLocked.label
2091 + " has attached databases. can't enable WAL.");
Paul Westbrookdae6d372011-02-17 10:59:56 -08002092 }
2093 return false;
2094 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002095
Jeff Brown47847f32012-03-22 19:13:11 -07002096 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002097 try {
2098 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2099 } catch (RuntimeException ex) {
Jeff Brown47847f32012-03-22 19:13:11 -07002100 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002101 throw ex;
2102 }
Paul Westbrookdae6d372011-02-17 10:59:56 -08002103 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002104 return true;
Vasu Nori6c354da2010-04-26 23:33:39 -07002105 }
2106
Vasu Nori2827d6d2010-07-04 00:26:18 -07002107 /**
Vasu Nori7b04c412010-07-20 10:31:21 -07002108 * This method disables the features enabled by {@link #enableWriteAheadLogging()}.
Jeff Browne67ca422012-03-21 17:24:05 -07002109 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002110 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002111 * time this method is called. WAL mode can only be changed when there are no
2112 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002113 *
2114 * @see #enableWriteAheadLogging
Vasu Nori2827d6d2010-07-04 00:26:18 -07002115 */
Vasu Nori7b04c412010-07-20 10:31:21 -07002116 public void disableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002117 synchronized (mLock) {
2118 throwIfNotOpenLocked();
2119
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002120 final int oldFlags = mConfigurationLocked.openFlags;
Fyodor Kupolov692573b2018-03-06 12:34:36 -08002121 final boolean walDisabled = (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0;
2122 final boolean compatibilityWalDisabled = (oldFlags & DISABLE_COMPATIBILITY_WAL) != 0;
2123 if (walDisabled && compatibilityWalDisabled) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002124 return;
Paul Westbrookdae6d372011-02-17 10:59:56 -08002125 }
Vasu Nori8d111032010-06-22 18:34:21 -07002126
Jeff Brown47847f32012-03-22 19:13:11 -07002127 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Fyodor Kupolov692573b2018-03-06 12:34:36 -08002128 // If an app explicitly disables WAL, compatibility mode should be disabled too
2129 mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002130
Jeff Browne67ca422012-03-21 17:24:05 -07002131 try {
2132 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2133 } catch (RuntimeException ex) {
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002134 mConfigurationLocked.openFlags = oldFlags;
Jeff Browne67ca422012-03-21 17:24:05 -07002135 throw ex;
2136 }
Vasu Nori65a88832010-07-16 15:14:08 -07002137 }
Vasu Nori6c354da2010-04-26 23:33:39 -07002138 }
2139
Vasu Norif3cf8a42010-03-23 11:41:44 -07002140 /**
Jeff Brown47847f32012-03-22 19:13:11 -07002141 * Returns true if write-ahead logging has been enabled for this database.
2142 *
2143 * @return True if write-ahead logging has been enabled for this database.
2144 *
2145 * @see #enableWriteAheadLogging
2146 * @see #ENABLE_WRITE_AHEAD_LOGGING
2147 */
2148 public boolean isWriteAheadLoggingEnabled() {
2149 synchronized (mLock) {
2150 throwIfNotOpenLocked();
2151
2152 return (mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2153 }
2154 }
2155
2156 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002157 * Collect statistics about all open databases in the current process.
2158 * Used by bug report.
Vasu Norif3cf8a42010-03-23 11:41:44 -07002159 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002160 static ArrayList<DbStats> getDbStats() {
Vasu Noric3849202010-03-09 10:47:25 -08002161 ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002162 for (SQLiteDatabase db : getActiveDatabases()) {
2163 db.collectDbStats(dbStatsList);
Vasu Nori24675612010-09-27 14:54:19 -07002164 }
Vasu Noric3849202010-03-09 10:47:25 -08002165 return dbStatsList;
2166 }
2167
Mathew Inwood41b31942018-08-10 16:00:53 +01002168 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -07002169 private void collectDbStats(ArrayList<DbStats> dbStatsList) {
2170 synchronized (mLock) {
2171 if (mConnectionPoolLocked != null) {
2172 mConnectionPoolLocked.collectDbStats(dbStatsList);
2173 }
2174 }
2175 }
2176
Mathew Inwood41b31942018-08-10 16:00:53 +01002177 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -07002178 private static ArrayList<SQLiteDatabase> getActiveDatabases() {
2179 ArrayList<SQLiteDatabase> databases = new ArrayList<SQLiteDatabase>();
2180 synchronized (sActiveDatabases) {
2181 databases.addAll(sActiveDatabases.keySet());
2182 }
2183 return databases;
2184 }
2185
2186 /**
2187 * Dump detailed information about all open databases in the current process.
2188 * Used by bug report.
2189 */
Makoto Onukiee93ad22018-10-18 16:24:13 -07002190 static void dumpAll(Printer printer, boolean verbose, boolean isSystem) {
2191 // Use this ArraySet to collect file paths.
2192 final ArraySet<String> directories = new ArraySet<>();
2193
Jeff Browne5360fb2011-10-31 17:48:13 -07002194 for (SQLiteDatabase db : getActiveDatabases()) {
Makoto Onukiee93ad22018-10-18 16:24:13 -07002195 db.dump(printer, verbose, isSystem, directories);
2196 }
2197
2198 // Dump DB files in the directories.
2199 if (directories.size() > 0) {
2200 final String[] dirs = directories.toArray(new String[directories.size()]);
2201 Arrays.sort(dirs);
2202 for (String dir : dirs) {
2203 dumpDatabaseDirectory(printer, new File(dir), isSystem);
2204 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002205 }
2206 }
2207
Makoto Onukiee93ad22018-10-18 16:24:13 -07002208 private void dump(Printer printer, boolean verbose, boolean isSystem, ArraySet directories) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002209 synchronized (mLock) {
2210 if (mConnectionPoolLocked != null) {
2211 printer.println("");
Makoto Onukiee93ad22018-10-18 16:24:13 -07002212 mConnectionPoolLocked.dump(printer, verbose, directories);
Jeff Browne5360fb2011-10-31 17:48:13 -07002213 }
2214 }
2215 }
2216
Makoto Onukiee93ad22018-10-18 16:24:13 -07002217 private static void dumpDatabaseDirectory(Printer pw, File dir, boolean isSystem) {
2218 pw.println("");
2219 pw.println("Database files in " + dir.getAbsolutePath() + ":");
2220 final File[] files = dir.listFiles();
2221 if (files == null || files.length == 0) {
2222 pw.println(" [none]");
2223 return;
2224 }
2225 Arrays.sort(files, (a, b) -> a.getName().compareTo(b.getName()));
2226
2227 for (File f : files) {
2228 if (isSystem) {
2229 // If called within the system server, the directory contains other files too, so
2230 // filter by file extensions.
2231 // (If it's an app, just print all files because they may not use *.db
2232 // extension.)
2233 final String name = f.getName();
2234 if (!(name.endsWith(".db") || name.endsWith(".db-wal")
2235 || name.endsWith(".db-journal")
2236 || name.endsWith(SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX))) {
2237 continue;
2238 }
2239 }
2240 pw.println(String.format(" %-40s %7db %s", f.getName(), f.length(),
2241 SQLiteDatabase.getFileTimestamps(f.getAbsolutePath())));
2242 }
2243 }
2244
Vasu Noric3849202010-03-09 10:47:25 -08002245 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002246 * Returns list of full pathnames of all attached databases including the main database
2247 * by executing 'pragma database_list' on the database.
2248 *
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002249 * @return ArrayList of pairs of (database name, database file path) or null if the database
2250 * is not open.
Vasu Noric3849202010-03-09 10:47:25 -08002251 */
Vasu Noria017eda2011-01-27 10:52:55 -08002252 public List<Pair<String, String>> getAttachedDbs() {
Vasu Noric3849202010-03-09 10:47:25 -08002253 ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002254 synchronized (mLock) {
2255 if (mConnectionPoolLocked == null) {
2256 return null; // not open
2257 }
2258
2259 if (!mHasAttachedDbsLocked) {
2260 // No attached databases.
2261 // There is a small window where attached databases exist but this flag is not
2262 // set yet. This can occur when this thread is in a race condition with another
2263 // thread that is executing the SQL statement: "attach database <blah> as <foo>"
2264 // If this thread is NOT ok with such a race condition (and thus possibly not
2265 // receivethe entire list of attached databases), then the caller should ensure
2266 // that no thread is executing any SQL statements while a thread is calling this
2267 // method. Typically, this method is called when 'adb bugreport' is done or the
2268 // caller wants to collect stats on the database and all its attached databases.
2269 attachedDbs.add(new Pair<String, String>("main", mConfigurationLocked.path));
2270 return attachedDbs;
2271 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002272
2273 acquireReference();
Vasu Nori24675612010-09-27 14:54:19 -07002274 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002275
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002276 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002277 // has attached databases. query sqlite to get the list of attached databases.
2278 Cursor c = null;
2279 try {
2280 c = rawQuery("pragma database_list;", null);
2281 while (c.moveToNext()) {
2282 // sqlite returns a row for each database in the returned list of databases.
2283 // in each row,
2284 // 1st column is the database name such as main, or the database
2285 // name specified on the "ATTACH" command
2286 // 2nd column is the database file path.
2287 attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2)));
2288 }
2289 } finally {
2290 if (c != null) {
2291 c.close();
2292 }
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002293 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002294 return attachedDbs;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002295 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08002296 releaseReference();
Vasu Noric3849202010-03-09 10:47:25 -08002297 }
Vasu Noric3849202010-03-09 10:47:25 -08002298 }
2299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002300 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002301 * Runs 'pragma integrity_check' on the given database (and all the attached databases)
2302 * and returns true if the given database (and all its attached databases) pass integrity_check,
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002303 * false otherwise.
Vasu Noriccd95442010-05-28 17:04:16 -07002304 *<p>
2305 * If the result is false, then this method logs the errors reported by the integrity_check
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002306 * command execution.
Vasu Noriccd95442010-05-28 17:04:16 -07002307 *<p>
2308 * Note that 'pragma integrity_check' on a database can take a long time.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002309 *
2310 * @return true if the given database (and all its attached databases) pass integrity_check,
Vasu Noriccd95442010-05-28 17:04:16 -07002311 * false otherwise.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002312 */
2313 public boolean isDatabaseIntegrityOk() {
Jeff Brown03bd3022012-03-06 13:48:56 -08002314 acquireReference();
Vasu Noribfe1dc22010-08-25 16:29:02 -07002315 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002316 List<Pair<String, String>> attachedDbs = null;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002317 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002318 attachedDbs = getAttachedDbs();
2319 if (attachedDbs == null) {
2320 throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " +
2321 "be retrieved. probably because the database is closed");
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002322 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002323 } catch (SQLiteException e) {
2324 // can't get attachedDb list. do integrity check on the main database
2325 attachedDbs = new ArrayList<Pair<String, String>>();
2326 attachedDbs.add(new Pair<String, String>("main", getPath()));
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002327 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002328
2329 for (int i = 0; i < attachedDbs.size(); i++) {
2330 Pair<String, String> p = attachedDbs.get(i);
2331 SQLiteStatement prog = null;
2332 try {
2333 prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);");
2334 String rslt = prog.simpleQueryForString();
2335 if (!rslt.equalsIgnoreCase("ok")) {
2336 // integrity_checker failed on main or attached databases
2337 Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt);
2338 return false;
2339 }
2340 } finally {
2341 if (prog != null) prog.close();
2342 }
2343 }
2344 } finally {
2345 releaseReference();
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002346 }
Vasu Noribfe1dc22010-08-25 16:29:02 -07002347 return true;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002348 }
2349
Jeff Browne5360fb2011-10-31 17:48:13 -07002350 @Override
2351 public String toString() {
2352 return "SQLiteDatabase: " + getPath();
2353 }
2354
Jeff Browne5360fb2011-10-31 17:48:13 -07002355 private void throwIfNotOpenLocked() {
2356 if (mConnectionPoolLocked == null) {
2357 throw new IllegalStateException("The database '" + mConfigurationLocked.label
2358 + "' is not open.");
2359 }
2360 }
Vasu Nori3ef94e22010-02-05 14:49:04 -08002361
2362 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002363 * Used to allow returning sub-classes of {@link Cursor} when calling query.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002364 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002365 public interface CursorFactory {
2366 /**
2367 * See {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}.
2368 */
2369 public Cursor newCursor(SQLiteDatabase db,
2370 SQLiteCursorDriver masterQuery, String editTable,
2371 SQLiteQuery query);
2372 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002373
2374 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002375 * A callback interface for a custom sqlite3 function.
2376 * This can be used to create a function that can be called from
2377 * sqlite3 database triggers.
2378 * @hide
Vasu Noric3849202010-03-09 10:47:25 -08002379 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002380 public interface CustomFunction {
2381 public void callback(String[] args);
2382 }
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002383
2384 /**
2385 * Wrapper for configuration parameters that are used for opening {@link SQLiteDatabase}
2386 */
2387 public static final class OpenParams {
2388 private final int mOpenFlags;
2389 private final CursorFactory mCursorFactory;
2390 private final DatabaseErrorHandler mErrorHandler;
2391 private final int mLookasideSlotSize;
2392 private final int mLookasideSlotCount;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002393 private final long mIdleConnectionTimeout;
2394 private final String mJournalMode;
2395 private final String mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002396
2397 private OpenParams(int openFlags, CursorFactory cursorFactory,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002398 DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002399 long idleConnectionTimeout, String journalMode, String syncMode) {
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002400 mOpenFlags = openFlags;
2401 mCursorFactory = cursorFactory;
2402 mErrorHandler = errorHandler;
2403 mLookasideSlotSize = lookasideSlotSize;
2404 mLookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002405 mIdleConnectionTimeout = idleConnectionTimeout;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002406 mJournalMode = journalMode;
2407 mSyncMode = syncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002408 }
2409
2410 /**
2411 * Returns size in bytes of each lookaside slot or -1 if not set.
2412 *
2413 * @see Builder#setLookasideConfig(int, int)
2414 */
2415 @IntRange(from = -1)
2416 public int getLookasideSlotSize() {
2417 return mLookasideSlotSize;
2418 }
2419
2420 /**
2421 * Returns total number of lookaside memory slots per database connection or -1 if not
2422 * set.
2423 *
2424 * @see Builder#setLookasideConfig(int, int)
2425 */
2426 @IntRange(from = -1)
2427 public int getLookasideSlotCount() {
2428 return mLookasideSlotCount;
2429 }
2430
2431 /**
Fyodor Kupolov76436c02017-08-03 17:56:44 -07002432 * Returns flags to control database access mode. Default value is 0.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002433 *
2434 * @see Builder#setOpenFlags(int)
2435 */
2436 @DatabaseOpenFlags
2437 public int getOpenFlags() {
2438 return mOpenFlags;
2439 }
2440
2441 /**
2442 * Returns an optional factory class that is called to instantiate a cursor when query
2443 * is called
2444 *
2445 * @see Builder#setCursorFactory(CursorFactory)
2446 */
2447 @Nullable
2448 public CursorFactory getCursorFactory() {
2449 return mCursorFactory;
2450 }
2451
2452 /**
2453 * Returns handler for database corruption errors
2454 *
2455 * @see Builder#setErrorHandler(DatabaseErrorHandler)
2456 */
2457 @Nullable
2458 public DatabaseErrorHandler getErrorHandler() {
2459 return mErrorHandler;
2460 }
2461
2462 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002463 * Returns maximum number of milliseconds that SQLite connection is allowed to be idle
2464 * before it is closed and removed from the pool.
2465 * <p>If the value isn't set, the timeout defaults to the system wide timeout
2466 *
2467 * @return timeout in milliseconds or -1 if the value wasn't set.
2468 */
2469 public long getIdleConnectionTimeout() {
2470 return mIdleConnectionTimeout;
2471 }
2472
2473 /**
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002474 * Returns <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>.
2475 * This journal mode will only be used if {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING}
2476 * flag is not set, otherwise a platform will use "WAL" journal mode.
2477 * @see Builder#setJournalMode(String)
2478 */
2479 @Nullable
2480 public String getJournalMode() {
2481 return mJournalMode;
2482 }
2483
2484 /**
2485 * Returns <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>.
Fyodor Kupolov8ba20892018-06-01 12:11:42 -07002486 * If not set, a system wide default will be used.
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002487 * @see Builder#setSynchronousMode(String)
2488 */
2489 @Nullable
2490 public String getSynchronousMode() {
2491 return mSyncMode;
2492 }
2493
2494 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002495 * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with
2496 * {@code this} parameters.
2497 * @hide
2498 */
2499 @NonNull
2500 public Builder toBuilder() {
2501 return new Builder(this);
2502 }
2503
2504 /**
2505 * Builder for {@link OpenParams}.
2506 */
2507 public static final class Builder {
2508 private int mLookasideSlotSize = -1;
2509 private int mLookasideSlotCount = -1;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002510 private long mIdleConnectionTimeout = -1;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002511 private int mOpenFlags;
2512 private CursorFactory mCursorFactory;
2513 private DatabaseErrorHandler mErrorHandler;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002514 private String mJournalMode;
2515 private String mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002516
2517 public Builder() {
2518 }
2519
2520 public Builder(OpenParams params) {
2521 mLookasideSlotSize = params.mLookasideSlotSize;
2522 mLookasideSlotCount = params.mLookasideSlotCount;
2523 mOpenFlags = params.mOpenFlags;
2524 mCursorFactory = params.mCursorFactory;
2525 mErrorHandler = params.mErrorHandler;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002526 mJournalMode = params.mJournalMode;
2527 mSyncMode = params.mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002528 }
2529
2530 /**
2531 * Configures
2532 * <a href="https://sqlite.org/malloc.html#lookaside">lookaside memory allocator</a>
2533 *
2534 * <p>SQLite default settings will be used, if this method isn't called.
2535 * Use {@code setLookasideConfig(0,0)} to disable lookaside
2536 *
Fyodor Kupolov05a0f0f2017-06-30 19:00:00 -07002537 * <p><strong>Note:</strong> Provided slotSize/slotCount configuration is just a
2538 * recommendation. The system may choose different values depending on a device, e.g.
2539 * lookaside allocations can be disabled on low-RAM devices
2540 *
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002541 * @param slotSize The size in bytes of each lookaside slot.
2542 * @param slotCount The total number of lookaside memory slots per database connection.
2543 */
2544 public Builder setLookasideConfig(@IntRange(from = 0) final int slotSize,
2545 @IntRange(from = 0) final int slotCount) {
2546 Preconditions.checkArgument(slotSize >= 0,
2547 "lookasideSlotCount cannot be negative");
2548 Preconditions.checkArgument(slotCount >= 0,
2549 "lookasideSlotSize cannot be negative");
2550 Preconditions.checkArgument(
2551 (slotSize > 0 && slotCount > 0) || (slotCount == 0 && slotSize == 0),
2552 "Invalid configuration: " + slotSize + ", " + slotCount);
2553
2554 mLookasideSlotSize = slotSize;
2555 mLookasideSlotCount = slotCount;
2556 return this;
2557 }
2558
2559 /**
2560 * Returns true if {@link #ENABLE_WRITE_AHEAD_LOGGING} flag is set
2561 * @hide
2562 */
2563 public boolean isWriteAheadLoggingEnabled() {
2564 return (mOpenFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2565 }
2566
2567 /**
2568 * Sets flags to control database access mode
2569 * @param openFlags The new flags to set
2570 * @see #OPEN_READWRITE
2571 * @see #OPEN_READONLY
2572 * @see #CREATE_IF_NECESSARY
2573 * @see #NO_LOCALIZED_COLLATORS
2574 * @see #ENABLE_WRITE_AHEAD_LOGGING
2575 * @return same builder instance for chaining multiple calls into a single statement
2576 */
2577 @NonNull
2578 public Builder setOpenFlags(@DatabaseOpenFlags int openFlags) {
2579 mOpenFlags = openFlags;
2580 return this;
2581 }
2582
2583 /**
2584 * Adds flags to control database access mode
2585 *
2586 * @param openFlags The new flags to add
2587 * @return same builder instance for chaining multiple calls into a single statement
2588 */
2589 @NonNull
2590 public Builder addOpenFlags(@DatabaseOpenFlags int openFlags) {
2591 mOpenFlags |= openFlags;
2592 return this;
2593 }
2594
2595 /**
2596 * Removes database access mode flags
2597 *
2598 * @param openFlags Flags to remove
2599 * @return same builder instance for chaining multiple calls into a single statement
2600 */
2601 @NonNull
2602 public Builder removeOpenFlags(@DatabaseOpenFlags int openFlags) {
2603 mOpenFlags &= ~openFlags;
2604 return this;
2605 }
2606
2607 /**
2608 * Sets {@link #ENABLE_WRITE_AHEAD_LOGGING} flag if {@code enabled} is {@code true},
2609 * unsets otherwise
2610 * @hide
2611 */
2612 public void setWriteAheadLoggingEnabled(boolean enabled) {
2613 if (enabled) {
2614 addOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2615 } else {
2616 removeOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2617 }
2618 }
2619
2620 /**
2621 * Set an optional factory class that is called to instantiate a cursor when query
2622 * is called.
2623 *
2624 * @param cursorFactory instance
2625 * @return same builder instance for chaining multiple calls into a single statement
2626 */
2627 @NonNull
2628 public Builder setCursorFactory(@Nullable CursorFactory cursorFactory) {
2629 mCursorFactory = cursorFactory;
2630 return this;
2631 }
2632
2633
2634 /**
2635 * Sets {@link DatabaseErrorHandler} object to handle db corruption errors
2636 */
2637 @NonNull
2638 public Builder setErrorHandler(@Nullable DatabaseErrorHandler errorHandler) {
2639 mErrorHandler = errorHandler;
2640 return this;
2641 }
2642
2643 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002644 * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle
2645 * before it is closed and removed from the pool.
2646 *
Makoto Onukib15186c2019-01-28 14:43:41 -08002647 * <p>DO NOT USE this method unless you fully understand the implication
2648 * of what it does.
2649 * A connection timeout allows the system to internally close a connection to a SQLite
2650 * database after a given timeout.
2651 * This is good for reducing app's memory consumption, but it has
2652 * side effects that are hard to predict. For example, SQLite internally maintains
2653 * a lot of "per-connection" states that apps can typically modify with a {@code PRAGMA}
2654 * statement, and such states will be reset once the connection is closed.
2655 * The system does not provide a callback that would allow apps to
2656 * reconfigure a newly created connection and thus there's no way to re-configure
2657 * connections when they're re-made internally. Do not use it unless you're sure
2658 * your app uses no per-connection states.
2659 *
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002660 * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE}
2661 * to allow unlimited idle connections.
Makoto Onukib15186c2019-01-28 14:43:41 -08002662 *
2663 * @see SQLiteOpenHelper#setIdleConnectionTimeout(long)
2664 *
2665 * @deprecated DO NOT USE this method unless you fully understand the implication
2666 * of what it does.
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002667 */
2668 @NonNull
Makoto Onukib15186c2019-01-28 14:43:41 -08002669 @Deprecated
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002670 public Builder setIdleConnectionTimeout(
2671 @IntRange(from = 0) long idleConnectionTimeoutMs) {
2672 Preconditions.checkArgument(idleConnectionTimeoutMs >= 0,
2673 "idle connection timeout cannot be negative");
2674 mIdleConnectionTimeout = idleConnectionTimeoutMs;
2675 return this;
2676 }
2677
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002678
2679 /**
2680 * Sets <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>
2681 * to use when {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag is not set.
2682 */
2683 @NonNull
2684 public Builder setJournalMode(@NonNull String journalMode) {
2685 Preconditions.checkNotNull(journalMode);
2686 mJournalMode = journalMode;
2687 return this;
2688 }
2689
Makoto Onukiee93ad22018-10-18 16:24:13 -07002690 /**w
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002691 * Sets <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>
Fyodor Kupolov8ba20892018-06-01 12:11:42 -07002692 * .
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002693 * @return
2694 */
2695 @NonNull
2696 public Builder setSynchronousMode(@NonNull String syncMode) {
2697 Preconditions.checkNotNull(syncMode);
2698 mSyncMode = syncMode;
2699 return this;
2700 }
2701
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002702 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002703 * Creates an instance of {@link OpenParams} with the options that were previously set
2704 * on this builder
2705 */
2706 @NonNull
2707 public OpenParams build() {
2708 return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002709 mLookasideSlotCount, mIdleConnectionTimeout, mJournalMode, mSyncMode);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002710 }
2711 }
2712 }
2713
2714 /** @hide */
2715 @IntDef(flag = true, prefix = {"OPEN_", "CREATE_", "NO_", "ENABLE_"}, value = {
2716 OPEN_READWRITE,
2717 OPEN_READONLY,
2718 CREATE_IF_NECESSARY,
2719 NO_LOCALIZED_COLLATORS,
2720 ENABLE_WRITE_AHEAD_LOGGING
2721 })
2722 @Retention(RetentionPolicy.SOURCE)
2723 public @interface DatabaseOpenFlags {}
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002724
Makoto Onukiee93ad22018-10-18 16:24:13 -07002725 /** @hide */
2726 public static void wipeDetected(String filename, String reason) {
2727 wtfAsSystemServer(TAG, "DB wipe detected:"
2728 + " package=" + ActivityThread.currentPackageName()
2729 + " reason=" + reason
2730 + " file=" + filename
2731 + " " + getFileTimestamps(filename)
2732 + " checkfile " + getFileTimestamps(filename + SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX),
2733 new Throwable("STACKTRACE"));
2734 }
2735
2736 /** @hide */
2737 public static String getFileTimestamps(String path) {
2738 try {
2739 BasicFileAttributes attr = Files.readAttributes(
2740 FileSystems.getDefault().getPath(path), BasicFileAttributes.class);
2741 return "ctime=" + attr.creationTime()
2742 + " mtime=" + attr.lastModifiedTime()
2743 + " atime=" + attr.lastAccessTime();
2744 } catch (IOException e) {
2745 return "[unable to obtain timestamp]";
2746 }
2747 }
2748
2749 /** @hide */
2750 static void wtfAsSystemServer(String tag, String message, Throwable stacktrace) {
2751 Log.e(tag, message, stacktrace);
2752 ContentResolver.onDbCorruption(tag, message, stacktrace);
2753 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002754}
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002755