blob: 44c78aa783a73670f3dd291bb0a74e5765981327 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.database.sqlite;
18
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070019import android.annotation.IntDef;
20import android.annotation.IntRange;
Makoto Onuki17aa1b72015-12-16 14:02:01 -080021import android.annotation.NonNull;
22import android.annotation.Nullable;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070023import android.app.ActivityManager;
Makoto Onukiee93ad22018-10-18 16:24:13 -070024import android.app.ActivityThread;
Artur Satayev26958002019-12-10 17:47:52 +000025import android.compat.annotation.UnsupportedAppUsage;
Makoto Onukiee93ad22018-10-18 16:24:13 -070026import 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;
Daulet Zhanguzinb7ac8d32019-12-30 16:54:39 +000063import java.util.Objects;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import java.util.WeakHashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065
66/**
67 * Exposes methods to manage a SQLite database.
Jeff Browne5360fb2011-10-31 17:48:13 -070068 *
69 * <p>
70 * SQLiteDatabase has methods to create, delete, execute SQL commands, and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071 * perform other common database management tasks.
Jeff Browne5360fb2011-10-31 17:48:13 -070072 * </p><p>
73 * See the Notepad sample application in the SDK for an example of creating
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074 * and managing a database.
Jeff Browne5360fb2011-10-31 17:48:13 -070075 * </p><p>
76 * Database names must be unique within an application, not across all applications.
77 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078 *
79 * <h3>Localized Collation - ORDER BY</h3>
Jeff Browne5360fb2011-10-31 17:48:13 -070080 * <p>
81 * In addition to SQLite's default <code>BINARY</code> collator, Android supplies
82 * two more, <code>LOCALIZED</code>, which changes with the system's current locale,
83 * and <code>UNICODE</code>, which is the Unicode Collation Algorithm and not tailored
84 * to the current locale.
85 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086 */
Jeff Brownbaefdfa2012-03-05 10:33:13 -080087public final class SQLiteDatabase extends SQLiteClosable {
Vasu Norifb16cbd2010-07-25 16:38:48 -070088 private static final String TAG = "SQLiteDatabase";
Jeff Browne5360fb2011-10-31 17:48:13 -070089
Jeff Hamilton082c2af2009-09-29 11:49:51 -070090 private static final int EVENT_DB_CORRUPT = 75004;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091
Fyodor Kupolov535672992017-08-30 18:16:31 -070092 // By default idle connections are not closed
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070093 private static final boolean DEBUG_CLOSE_IDLE_CONNECTIONS = SystemProperties
Fyodor Kupolov535672992017-08-30 18:16:31 -070094 .getBoolean("persist.debug.sqlite.close_idle_connections", false);
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070095
Jeff Browne5360fb2011-10-31 17:48:13 -070096 // Stores reference to all databases opened in the current process.
97 // (The referent Object is not used at this time.)
98 // INVARIANT: Guarded by sActiveDatabases.
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070099 private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases = new WeakHashMap<>();
Jeff Browne5360fb2011-10-31 17:48:13 -0700100
101 // Thread-local for database sessions that belong to this database.
102 // Each thread has its own database session.
103 // INVARIANT: Immutable.
Mathew Inwood41b31942018-08-10 16:00:53 +0100104 @UnsupportedAppUsage
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700105 private final ThreadLocal<SQLiteSession> mThreadSession = ThreadLocal
106 .withInitial(this::createSession);
Jeff Browne5360fb2011-10-31 17:48:13 -0700107
108 // The optional factory to use when creating new Cursors. May be null.
109 // INVARIANT: Immutable.
110 private final CursorFactory mCursorFactory;
111
112 // Error handler to be used when SQLite returns corruption errors.
113 // INVARIANT: Immutable.
114 private final DatabaseErrorHandler mErrorHandler;
115
116 // Shared database state lock.
117 // This lock guards all of the shared state of the database, such as its
118 // configuration, whether it is open or closed, and so on. This lock should
119 // be held for as little time as possible.
120 //
121 // The lock MUST NOT be held while attempting to acquire database connections or
122 // while executing SQL statements on behalf of the client as it can lead to deadlock.
123 //
124 // It is ok to hold the lock while reconfiguring the connection pool or dumping
125 // statistics because those operations are non-reentrant and do not try to acquire
126 // connections that might be held by other threads.
127 //
128 // Basic rule: grab the lock, access or modify global state, release the lock, then
129 // do the required SQL work.
130 private final Object mLock = new Object();
131
132 // Warns if the database is finalized without being closed properly.
133 // INVARIANT: Guarded by mLock.
134 private final CloseGuard mCloseGuardLocked = CloseGuard.get();
135
136 // The database configuration.
137 // INVARIANT: Guarded by mLock.
Mathew Inwood41b31942018-08-10 16:00:53 +0100138 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -0700139 private final SQLiteDatabaseConfiguration mConfigurationLocked;
140
141 // The connection pool for the database, null when closed.
142 // The pool itself is thread-safe, but the reference to it can only be acquired
143 // when the lock is held.
144 // INVARIANT: Guarded by mLock.
Mathew Inwood41b31942018-08-10 16:00:53 +0100145 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -0700146 private SQLiteConnectionPool mConnectionPoolLocked;
147
148 // True if the database has attached databases.
149 // INVARIANT: Guarded by mLock.
150 private boolean mHasAttachedDbsLocked;
151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700153 * When a constraint violation occurs, an immediate ROLLBACK occurs,
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800154 * thus ending the current transaction, and the command aborts with a
155 * return code of SQLITE_CONSTRAINT. If no transaction is active
156 * (other than the implied transaction that is created on every command)
Jeff Browne5360fb2011-10-31 17:48:13 -0700157 * then this algorithm works the same as ABORT.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800158 */
159 public static final int CONFLICT_ROLLBACK = 1;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700160
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800161 /**
162 * When a constraint violation occurs,no ROLLBACK is executed
163 * so changes from prior commands within the same transaction
164 * are preserved. This is the default behavior.
165 */
166 public static final int CONFLICT_ABORT = 2;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700167
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800168 /**
169 * When a constraint violation occurs, the command aborts with a return
170 * code SQLITE_CONSTRAINT. But any changes to the database that
171 * the command made prior to encountering the constraint violation
172 * are preserved and are not backed out.
173 */
174 public static final int CONFLICT_FAIL = 3;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700175
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800176 /**
177 * When a constraint violation occurs, the one row that contains
178 * the constraint violation is not inserted or changed.
179 * But the command continues executing normally. Other rows before and
180 * after the row that contained the constraint violation continue to be
181 * inserted or updated normally. No error is returned.
182 */
183 public static final int CONFLICT_IGNORE = 4;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700184
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800185 /**
186 * When a UNIQUE constraint violation occurs, the pre-existing rows that
187 * are causing the constraint violation are removed prior to inserting
188 * or updating the current row. Thus the insert or update always occurs.
189 * The command continues executing normally. No error is returned.
190 * If a NOT NULL constraint violation occurs, the NULL value is replaced
191 * by the default value for that column. If the column has no default
192 * value, then the ABORT algorithm is used. If a CHECK constraint
193 * violation occurs then the IGNORE algorithm is used. When this conflict
194 * resolution strategy deletes rows in order to satisfy a constraint,
195 * it does not invoke delete triggers on those rows.
Jeff Browne5360fb2011-10-31 17:48:13 -0700196 * This behavior might change in a future release.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800197 */
198 public static final int CONFLICT_REPLACE = 5;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700199
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800200 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700201 * Use the following when no conflict action is specified.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800202 */
203 public static final int CONFLICT_NONE = 0;
Jeff Browne5360fb2011-10-31 17:48:13 -0700204
Jeff Sharkey6adc98c2018-07-12 19:47:49 -0600205 /** {@hide} */
Mathew Inwood41b31942018-08-10 16:00:53 +0100206 @UnsupportedAppUsage
Jeff Sharkey6adc98c2018-07-12 19:47:49 -0600207 public static final String[] CONFLICT_VALUES = new String[]
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800208 {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 /**
211 * Maximum Length Of A LIKE Or GLOB Pattern
212 * The pattern matching algorithm used in the default LIKE and GLOB implementation
213 * of SQLite can exhibit O(N^2) performance (where N is the number of characters in
214 * the pattern) for certain pathological cases. To avoid denial-of-service attacks
215 * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes.
216 * The default value of this limit is 50000. A modern workstation can evaluate
217 * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly.
218 * The denial of service problem only comes into play when the pattern length gets
219 * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns
220 * are at most a few dozen bytes in length, paranoid application developers may
221 * want to reduce this parameter to something in the range of a few hundred
222 * if they know that external users are able to generate arbitrary patterns.
223 */
224 public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000;
225
226 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700227 * Open flag: Flag for {@link #openDatabase} to open the database for reading and writing.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 * If the disk is full, this may fail even before you actually write anything.
229 *
230 * {@more} Note that the value of this flag is 0, so it is the default.
231 */
232 public static final int OPEN_READWRITE = 0x00000000; // update native code if changing
233
234 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700235 * Open flag: Flag for {@link #openDatabase} to open the database for reading only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 * This is the only reliable way to open a database if the disk may be full.
237 */
238 public static final int OPEN_READONLY = 0x00000001; // update native code if changing
239
240 private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing
241
242 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700243 * Open flag: Flag for {@link #openDatabase} to open the database without support for
244 * localized collators.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 *
246 * {@more} This causes the collator <code>LOCALIZED</code> not to be created.
247 * You must be consistent when using this flag to use the setting the database was
248 * created with. If this is set, {@link #setLocale} will do nothing.
249 */
250 public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing
251
252 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700253 * Open flag: Flag for {@link #openDatabase} to create the database file if it does not
254 * already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 */
256 public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing
257
258 /**
Jeff Brown47847f32012-03-22 19:13:11 -0700259 * Open flag: Flag for {@link #openDatabase} to open the database file with
260 * write-ahead logging enabled by default. Using this flag is more efficient
261 * than calling {@link #enableWriteAheadLogging}.
262 *
263 * Write-ahead logging cannot be used with read-only databases so the value of
264 * this flag is ignored if the database is opened read-only.
265 *
266 * @see #enableWriteAheadLogging
267 */
268 public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;
269
Narayan Kamathb8280432019-02-21 13:20:51 +0000270
271 // Note: The below value was only used on Android Pie.
272 // public static final int DISABLE_COMPATIBILITY_WAL = 0x40000000;
273
Jeff Brown47847f32012-03-22 19:13:11 -0700274 /**
Narayan Kamathb8280432019-02-21 13:20:51 +0000275 * Open flag: Flag for {@link #openDatabase} to enable the legacy Compatibility WAL when opening
276 * database.
Fyodor Kupolov692573b2018-03-06 12:34:36 -0800277 *
278 * @hide
279 */
Narayan Kamathb8280432019-02-21 13:20:51 +0000280 public static final int ENABLE_LEGACY_COMPATIBILITY_WAL = 0x80000000;
Fyodor Kupolov692573b2018-03-06 12:34:36 -0800281
282 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700283 * Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}.
Vasu Norib729dcc2010-09-14 11:35:49 -0700284 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700285 * Each prepared-statement is between 1K - 6K, depending on the complexity of the
286 * SQL statement & schema. A large SQL cache may use a significant amount of memory.
Vasu Norie495d1f2010-01-06 16:34:19 -0800287 */
Vasu Nori90a367262010-04-12 12:49:09 -0700288 public static final int MAX_SQL_CACHE_SIZE = 100;
Vasu Norib729dcc2010-09-14 11:35:49 -0700289
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700290 private SQLiteDatabase(final String path, final int openFlags,
291 CursorFactory cursorFactory, DatabaseErrorHandler errorHandler,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800292 int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs,
293 String journalMode, String syncMode) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700294 mCursorFactory = cursorFactory;
295 mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler();
296 mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700297 mConfigurationLocked.lookasideSlotSize = lookasideSlotSize;
298 mConfigurationLocked.lookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700299 // Disable lookaside allocator on low-RAM devices
300 if (ActivityManager.isLowRamDeviceStatic()) {
301 mConfigurationLocked.lookasideSlotCount = 0;
302 mConfigurationLocked.lookasideSlotSize = 0;
303 }
304 long effectiveTimeoutMs = Long.MAX_VALUE;
305 // Never close idle connections for in-memory databases
306 if (!mConfigurationLocked.isInMemoryDb()) {
307 // First, check app-specific value. Otherwise use defaults
308 // -1 in idleConnectionTimeoutMs indicates unset value
309 if (idleConnectionTimeoutMs >= 0) {
310 effectiveTimeoutMs = idleConnectionTimeoutMs;
311 } else if (DEBUG_CLOSE_IDLE_CONNECTIONS) {
312 effectiveTimeoutMs = SQLiteGlobal.getIdleConnectionTimeout();
313 }
314 }
315 mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800316 mConfigurationLocked.journalMode = journalMode;
317 mConfigurationLocked.syncMode = syncMode;
Narayan Kamathb8280432019-02-21 13:20:51 +0000318 if (SQLiteCompatibilityWalFlags.isLegacyCompatibilityWalEnabled()) {
319 mConfigurationLocked.openFlags |= ENABLE_LEGACY_COMPATIBILITY_WAL;
Fyodor Kupolovee90c032017-12-12 11:52:57 -0800320 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700322
Jeff Browne5360fb2011-10-31 17:48:13 -0700323 @Override
324 protected void finalize() throws Throwable {
325 try {
326 dispose(true);
327 } finally {
328 super.finalize();
329 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700330 }
331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800332 @Override
333 protected void onAllReferencesReleased() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700334 dispose(false);
335 }
336
337 private void dispose(boolean finalized) {
338 final SQLiteConnectionPool pool;
339 synchronized (mLock) {
340 if (mCloseGuardLocked != null) {
341 if (finalized) {
342 mCloseGuardLocked.warnIfOpen();
343 }
344 mCloseGuardLocked.close();
345 }
346
347 pool = mConnectionPoolLocked;
348 mConnectionPoolLocked = null;
349 }
350
351 if (!finalized) {
352 synchronized (sActiveDatabases) {
353 sActiveDatabases.remove(this);
354 }
355
356 if (pool != null) {
357 pool.close();
358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 }
360 }
361
362 /**
363 * Attempts to release memory that SQLite holds but does not require to
364 * operate properly. Typically this memory will come from the page cache.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700365 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 * @return the number of bytes actually released
367 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700368 public static int releaseMemory() {
369 return SQLiteGlobal.releaseMemory();
370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371
372 /**
373 * Control whether or not the SQLiteDatabase is made thread-safe by using locks
374 * around critical sections. This is pretty expensive, so if you know that your
375 * DB will only be used by a single thread then you should set this to false.
376 * The default is true.
377 * @param lockingEnabled set to true to enable locks, false otherwise
Jeff Browne5360fb2011-10-31 17:48:13 -0700378 *
379 * @deprecated This method now does nothing. Do not use.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800380 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700381 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 public void setLockingEnabled(boolean lockingEnabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 }
384
385 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700386 * Gets a label to use when describing the database in log messages.
387 * @return The label.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700389 String getLabel() {
390 synchronized (mLock) {
391 return mConfigurationLocked.label;
392 }
393 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394
Jeff Browne5360fb2011-10-31 17:48:13 -0700395 /**
396 * Sends a corruption message to the database error handler.
397 */
398 void onCorruption() {
399 EventLog.writeEvent(EVENT_DB_CORRUPT, getLabel());
Vasu Noriccd95442010-05-28 17:04:16 -0700400 mErrorHandler.onCorruption(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 }
402
403 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700404 * Gets the {@link SQLiteSession} that belongs to this thread for this database.
405 * Once a thread has obtained a session, it will continue to obtain the same
406 * session even after the database has been closed (although the session will not
407 * be usable). However, a thread that does not already have a session cannot
408 * obtain one after the database has been closed.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700409 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700410 * The idea is that threads that have active connections to the database may still
411 * have work to complete even after the call to {@link #close}. Active database
412 * connections are not actually disposed until they are released by the threads
413 * that own them.
414 *
415 * @return The session, never null.
416 *
417 * @throws IllegalStateException if the thread does not yet have a session and
418 * the database is not open.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 */
Mathew Inwood41b31942018-08-10 16:00:53 +0100420 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -0700421 SQLiteSession getThreadSession() {
422 return mThreadSession.get(); // initialValue() throws if database closed
Vasu Nori6d970252010-10-05 10:48:49 -0700423 }
Vasu Nori16057fa2011-03-18 11:40:37 -0700424
Jeff Browne5360fb2011-10-31 17:48:13 -0700425 SQLiteSession createSession() {
426 final SQLiteConnectionPool pool;
427 synchronized (mLock) {
428 throwIfNotOpenLocked();
429 pool = mConnectionPoolLocked;
Vasu Nori6d970252010-10-05 10:48:49 -0700430 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700431 return new SQLiteSession(pool);
Vasu Norid4608a32011-02-03 16:24:06 -0800432 }
433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700435 * Gets default connection flags that are appropriate for this thread, taking into
436 * account whether the thread is acting on behalf of the UI.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700438 * @param readOnly True if the connection should be read-only.
439 * @return The connection flags.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700441 int getThreadDefaultConnectionFlags(boolean readOnly) {
442 int flags = readOnly ? SQLiteConnectionPool.CONNECTION_FLAG_READ_ONLY :
443 SQLiteConnectionPool.CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY;
444 if (isMainThread()) {
445 flags |= SQLiteConnectionPool.CONNECTION_FLAG_INTERACTIVE;
446 }
447 return flags;
Vasu Nori16057fa2011-03-18 11:40:37 -0700448 }
449
Jeff Browne5360fb2011-10-31 17:48:13 -0700450 private static boolean isMainThread() {
451 // FIXME: There should be a better way to do this.
452 // Would also be nice to have something that would work across Binder calls.
453 Looper looper = Looper.myLooper();
454 return looper != null && looper == Looper.getMainLooper();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 }
456
457 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700458 * Begins a transaction in EXCLUSIVE mode.
459 * <p>
460 * Transactions can be nested.
461 * When the outer transaction is ended all of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 * the work done in that transaction and all of the nested transactions will be committed or
463 * rolled back. The changes will be rolled back if any transaction is ended without being
464 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700465 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 * <p>Here is the standard idiom for transactions:
467 *
468 * <pre>
469 * db.beginTransaction();
470 * try {
471 * ...
472 * db.setTransactionSuccessful();
473 * } finally {
474 * db.endTransaction();
475 * }
476 * </pre>
477 */
478 public void beginTransaction() {
Vasu Nori6c354da2010-04-26 23:33:39 -0700479 beginTransaction(null /* transactionStatusCallback */, true);
480 }
481
482 /**
483 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
484 * the outer transaction is ended all of the work done in that transaction
485 * and all of the nested transactions will be committed or rolled back. The
486 * changes will be rolled back if any transaction is ended without being
487 * marked as clean (by calling setTransactionSuccessful). Otherwise they
488 * will be committed.
489 * <p>
490 * Here is the standard idiom for transactions:
491 *
492 * <pre>
493 * db.beginTransactionNonExclusive();
494 * try {
495 * ...
496 * db.setTransactionSuccessful();
497 * } finally {
498 * db.endTransaction();
499 * }
500 * </pre>
501 */
502 public void beginTransactionNonExclusive() {
503 beginTransaction(null /* transactionStatusCallback */, false);
Fred Quintanac4516a72009-09-03 12:14:06 -0700504 }
505
506 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700507 * Begins a transaction in EXCLUSIVE mode.
508 * <p>
509 * Transactions can be nested.
510 * When the outer transaction is ended all of
Fred Quintanac4516a72009-09-03 12:14:06 -0700511 * the work done in that transaction and all of the nested transactions will be committed or
512 * rolled back. The changes will be rolled back if any transaction is ended without being
513 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700514 * </p>
Fred Quintanac4516a72009-09-03 12:14:06 -0700515 * <p>Here is the standard idiom for transactions:
516 *
517 * <pre>
518 * db.beginTransactionWithListener(listener);
519 * try {
520 * ...
521 * db.setTransactionSuccessful();
522 * } finally {
523 * db.endTransaction();
524 * }
525 * </pre>
Vasu Noriccd95442010-05-28 17:04:16 -0700526 *
Fred Quintanac4516a72009-09-03 12:14:06 -0700527 * @param transactionListener listener that should be notified when the transaction begins,
528 * commits, or is rolled back, either explicitly or by a call to
529 * {@link #yieldIfContendedSafely}.
530 */
531 public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
Vasu Nori6c354da2010-04-26 23:33:39 -0700532 beginTransaction(transactionListener, true);
533 }
534
535 /**
536 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
537 * the outer transaction is ended all of the work done in that transaction
538 * and all of the nested transactions will be committed or rolled back. The
539 * changes will be rolled back if any transaction is ended without being
540 * marked as clean (by calling setTransactionSuccessful). Otherwise they
541 * will be committed.
542 * <p>
543 * Here is the standard idiom for transactions:
544 *
545 * <pre>
546 * db.beginTransactionWithListenerNonExclusive(listener);
547 * try {
548 * ...
549 * db.setTransactionSuccessful();
550 * } finally {
551 * db.endTransaction();
552 * }
553 * </pre>
554 *
555 * @param transactionListener listener that should be notified when the
556 * transaction begins, commits, or is rolled back, either
557 * explicitly or by a call to {@link #yieldIfContendedSafely}.
558 */
559 public void beginTransactionWithListenerNonExclusive(
560 SQLiteTransactionListener transactionListener) {
561 beginTransaction(transactionListener, false);
562 }
563
Mathew Inwood41b31942018-08-10 16:00:53 +0100564 @UnsupportedAppUsage
Vasu Nori6c354da2010-04-26 23:33:39 -0700565 private void beginTransaction(SQLiteTransactionListener transactionListener,
566 boolean exclusive) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800567 acquireReference();
568 try {
569 getThreadSession().beginTransaction(
570 exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
571 SQLiteSession.TRANSACTION_MODE_IMMEDIATE,
572 transactionListener,
573 getThreadDefaultConnectionFlags(false /*readOnly*/), null);
574 } finally {
575 releaseReference();
576 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 }
578
579 /**
580 * End a transaction. See beginTransaction for notes about how to use this and when transactions
581 * are committed and rolled back.
582 */
583 public void endTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800584 acquireReference();
585 try {
586 getThreadSession().endTransaction(null);
587 } finally {
588 releaseReference();
589 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 }
591
592 /**
593 * Marks the current transaction as successful. Do not do any more database work between
594 * calling this and calling endTransaction. Do as little non-database work as possible in that
595 * situation too. If any errors are encountered between this and endTransaction the transaction
596 * will still be committed.
597 *
598 * @throws IllegalStateException if the current thread is not in a transaction or the
599 * transaction is already marked as successful.
600 */
601 public void setTransactionSuccessful() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800602 acquireReference();
603 try {
604 getThreadSession().setTransactionSuccessful();
605 } finally {
606 releaseReference();
607 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 }
609
610 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700611 * Returns true if the current thread has a transaction pending.
612 *
613 * @return True if the current thread is in a transaction.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614 */
615 public boolean inTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800616 acquireReference();
617 try {
618 return getThreadSession().hasTransaction();
619 } finally {
620 releaseReference();
621 }
Vasu Norice38b982010-07-22 13:57:13 -0700622 }
623
624 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700625 * Returns true if the current thread is holding an active connection to the database.
Vasu Norice38b982010-07-22 13:57:13 -0700626 * <p>
Jeff Browne5360fb2011-10-31 17:48:13 -0700627 * The name of this method comes from a time when having an active connection
628 * to the database meant that the thread was holding an actual lock on the
629 * database. Nowadays, there is no longer a true "database lock" although threads
630 * may block if they cannot acquire a database connection to perform a
631 * particular operation.
632 * </p>
Vasu Norice38b982010-07-22 13:57:13 -0700633 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700634 * @return True if the current thread is holding an active connection to the database.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800635 */
636 public boolean isDbLockedByCurrentThread() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800637 acquireReference();
638 try {
639 return getThreadSession().hasConnection();
640 } finally {
641 releaseReference();
642 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 }
644
645 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700646 * Always returns false.
647 * <p>
648 * There is no longer the concept of a database lock, so this method always returns false.
649 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800650 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700651 * @return False.
652 * @deprecated Always returns false. Do not use this method.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700654 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800655 public boolean isDbLockedByOtherThreads() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700656 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800657 }
658
659 /**
660 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
661 * successful so far. Do not call setTransactionSuccessful before calling this. When this
662 * returns a new transaction will have been created but not marked as successful.
663 * @return true if the transaction was yielded
kopriva7364c112018-09-27 11:02:07 -0700664 * @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 -0800665 * will not be yielded. Use yieldIfContendedSafely instead.
666 */
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700667 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 public boolean yieldIfContended() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700669 return yieldIfContendedHelper(false /* do not check yielding */,
670 -1 /* sleepAfterYieldDelay */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671 }
672
673 /**
674 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
675 * successful so far. Do not call setTransactionSuccessful before calling this. When this
676 * returns a new transaction will have been created but not marked as successful. This assumes
677 * that there are no nested transactions (beginTransaction has only been called once) and will
Fred Quintana5c7aede2009-08-27 21:41:27 -0700678 * throw an exception if that is not the case.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679 * @return true if the transaction was yielded
680 */
681 public boolean yieldIfContendedSafely() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700682 return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683 }
684
Fred Quintana5c7aede2009-08-27 21:41:27 -0700685 /**
686 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
687 * successful so far. Do not call setTransactionSuccessful before calling this. When this
688 * returns a new transaction will have been created but not marked as successful. This assumes
689 * that there are no nested transactions (beginTransaction has only been called once) and will
690 * throw an exception if that is not the case.
691 * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if
692 * the lock was actually yielded. This will allow other background threads to make some
693 * more progress than they would if we started the transaction immediately.
694 * @return true if the transaction was yielded
695 */
696 public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
697 return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay);
698 }
699
Jeff Browne5360fb2011-10-31 17:48:13 -0700700 private boolean yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800701 acquireReference();
702 try {
703 return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null);
704 } finally {
705 releaseReference();
706 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 }
708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700710 * Deprecated.
Vasu Nori95675132010-07-21 16:24:40 -0700711 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 */
Vasu Nori95675132010-07-21 16:24:40 -0700713 @Deprecated
714 public Map<String, String> getSyncedTables() {
715 return new HashMap<String, String>(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 }
717
718 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 * Open the database according to the flags {@link #OPEN_READWRITE}
720 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
721 *
722 * <p>Sets the locale of the database to the the system's current locale.
723 * Call {@link #setLocale} if you would like something else.</p>
724 *
725 * @param path to database file to open and/or create
726 * @param factory an optional factory class that is called to instantiate a
727 * cursor when query is called, or null for default
728 * @param flags to control database access mode
729 * @return the newly opened database
730 * @throws SQLiteException if the database cannot be opened
731 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700732 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
733 @DatabaseOpenFlags int flags) {
Jeff Brown47847f32012-03-22 19:13:11 -0700734 return openDatabase(path, factory, flags, null);
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700735 }
736
737 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700738 * Open the database according to the specified {@link OpenParams parameters}
739 *
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700740 * @param path path to database file to open and/or create.
741 * <p><strong>Important:</strong> The file should be constructed either from an absolute path or
742 * by using {@link android.content.Context#getDatabasePath(String)}.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700743 * @param openParams configuration parameters that are used for opening {@link SQLiteDatabase}
744 * @return the newly opened database
745 * @throws SQLiteException if the database cannot be opened
746 */
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700747 public static SQLiteDatabase openDatabase(@NonNull File path,
748 @NonNull OpenParams openParams) {
749 return openDatabase(path.getPath(), openParams);
750 }
751
Mathew Inwood41b31942018-08-10 16:00:53 +0100752 @UnsupportedAppUsage
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700753 private static SQLiteDatabase openDatabase(@NonNull String path,
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700754 @NonNull OpenParams openParams) {
755 Preconditions.checkArgument(openParams != null, "OpenParams cannot be null");
756 SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags,
757 openParams.mCursorFactory, openParams.mErrorHandler,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700758 openParams.mLookasideSlotSize, openParams.mLookasideSlotCount,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800759 openParams.mIdleConnectionTimeout, openParams.mJournalMode, openParams.mSyncMode);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700760 db.open();
761 return db;
762 }
763
764 /**
Vasu Nori74f170f2010-06-01 18:06:18 -0700765 * Open the database according to the flags {@link #OPEN_READWRITE}
766 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
767 *
768 * <p>Sets the locale of the database to the the system's current locale.
769 * Call {@link #setLocale} if you would like something else.</p>
770 *
771 * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be
772 * used to handle corruption when sqlite reports database corruption.</p>
773 *
774 * @param path to database file to open and/or create
775 * @param factory an optional factory class that is called to instantiate a
776 * cursor when query is called, or null for default
777 * @param flags to control database access mode
778 * @param errorHandler the {@link DatabaseErrorHandler} obj to be used to handle corruption
779 * when sqlite reports database corruption
780 * @return the newly opened database
781 * @throws SQLiteException if the database cannot be opened
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700782 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700783 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
784 @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler) {
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800785 SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1, -1, null,
786 null);
Jeff Browne5360fb2011-10-31 17:48:13 -0700787 db.open();
788 return db;
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700789 }
790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 /**
792 * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
793 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700794 public static SQLiteDatabase openOrCreateDatabase(@NonNull File file,
795 @Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 return openOrCreateDatabase(file.getPath(), factory);
797 }
798
799 /**
800 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
801 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700802 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
803 @Nullable CursorFactory factory) {
Jeff Brown47847f32012-03-22 19:13:11 -0700804 return openDatabase(path, factory, CREATE_IF_NECESSARY, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 }
806
807 /**
Vasu Nori6c354da2010-04-26 23:33:39 -0700808 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler).
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700809 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700810 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
811 @Nullable CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler) {
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700812 return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler);
813 }
814
Jeff Brown559d0642012-02-29 10:19:12 -0800815 /**
Jeff Brown79087e42012-03-01 19:52:44 -0800816 * Deletes a database including its journal file and other auxiliary files
817 * that may have been created by the database engine.
818 *
819 * @param file The database file path.
820 * @return True if the database was successfully deleted.
821 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700822 public static boolean deleteDatabase(@NonNull File file) {
Makoto Onukiee93ad22018-10-18 16:24:13 -0700823 return deleteDatabase(file, /*removeCheckFile=*/ true);
824 }
825
826
827 /** @hide */
828 public static boolean deleteDatabase(@NonNull File file, boolean removeCheckFile) {
Jeff Brown79087e42012-03-01 19:52:44 -0800829 if (file == null) {
830 throw new IllegalArgumentException("file must not be null");
831 }
832
833 boolean deleted = false;
834 deleted |= file.delete();
835 deleted |= new File(file.getPath() + "-journal").delete();
836 deleted |= new File(file.getPath() + "-shm").delete();
837 deleted |= new File(file.getPath() + "-wal").delete();
838
Makoto Onukiee93ad22018-10-18 16:24:13 -0700839 // This file is not a standard SQLite file, so don't update the deleted flag.
840 new File(file.getPath() + SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX).delete();
841
Jeff Brown79087e42012-03-01 19:52:44 -0800842 File dir = file.getParentFile();
843 if (dir != null) {
844 final String prefix = file.getName() + "-mj";
Jeff Brownfce58902014-01-24 13:20:57 -0800845 File[] files = dir.listFiles(new FileFilter() {
Jeff Brown79087e42012-03-01 19:52:44 -0800846 @Override
847 public boolean accept(File candidate) {
848 return candidate.getName().startsWith(prefix);
849 }
Jeff Brownfce58902014-01-24 13:20:57 -0800850 });
851 if (files != null) {
852 for (File masterJournal : files) {
853 deleted |= masterJournal.delete();
854 }
Jeff Brown79087e42012-03-01 19:52:44 -0800855 }
856 }
857 return deleted;
858 }
859
860 /**
Jeff Brown559d0642012-02-29 10:19:12 -0800861 * Reopens the database in read-write mode.
862 * If the database is already read-write, does nothing.
863 *
864 * @throws SQLiteException if the database could not be reopened as requested, in which
865 * case it remains open in read only mode.
866 * @throws IllegalStateException if the database is not open.
867 *
868 * @see #isReadOnly()
869 * @hide
870 */
Mathew Inwood41b31942018-08-10 16:00:53 +0100871 @UnsupportedAppUsage
Jeff Brown559d0642012-02-29 10:19:12 -0800872 public void reopenReadWrite() {
873 synchronized (mLock) {
874 throwIfNotOpenLocked();
875
876 if (!isReadOnlyLocked()) {
877 return; // nothing to do
878 }
879
880 // Reopen the database in read-write mode.
881 final int oldOpenFlags = mConfigurationLocked.openFlags;
882 mConfigurationLocked.openFlags = (mConfigurationLocked.openFlags & ~OPEN_READ_MASK)
883 | OPEN_READWRITE;
884 try {
885 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
886 } catch (RuntimeException ex) {
887 mConfigurationLocked.openFlags = oldOpenFlags;
888 throw ex;
889 }
890 }
891 }
892
Jeff Browne5360fb2011-10-31 17:48:13 -0700893 private void open() {
894 try {
895 try {
896 openInner();
Makoto Onuki7a8261d2019-02-01 12:54:55 -0800897 } catch (RuntimeException ex) {
898 if (SQLiteDatabaseCorruptException.isCorruptException(ex)) {
899 Log.e(TAG, "Database corruption detected in open()", ex);
900 onCorruption();
901 openInner();
902 } else {
903 throw ex;
904 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700905 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700906 } catch (SQLiteException ex) {
907 Log.e(TAG, "Failed to open database '" + getLabel() + "'.", ex);
908 close();
909 throw ex;
910 }
911 }
912
913 private void openInner() {
914 synchronized (mLock) {
915 assert mConnectionPoolLocked == null;
916 mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked);
917 mCloseGuardLocked.open("close");
918 }
919
920 synchronized (sActiveDatabases) {
921 sActiveDatabases.put(this, null);
922 }
923 }
924
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700925 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 * Create a memory backed SQLite database. Its contents will be destroyed
927 * when the database is closed.
928 *
929 * <p>Sets the locale of the database to the the system's current locale.
930 * Call {@link #setLocale} if you would like something else.</p>
931 *
932 * @param factory an optional factory class that is called to instantiate a
933 * cursor when query is called
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700934 * @return a SQLiteDatabase instance
935 * @throws SQLiteException if the database cannot be created
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700937 @NonNull
938 public static SQLiteDatabase create(@Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 // This is a magic string with special meaning for SQLite.
Jeff Browne5360fb2011-10-31 17:48:13 -0700940 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
941 factory, CREATE_IF_NECESSARY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 }
943
944 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700945 * Create a memory backed SQLite database. Its contents will be destroyed
946 * when the database is closed.
947 *
948 * <p>Sets the locale of the database to the the system's current locale.
949 * Call {@link #setLocale} if you would like something else.</p>
950 * @param openParams configuration parameters that are used for opening SQLiteDatabase
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700951 * @return a SQLiteDatabase instance
952 * @throws SQLException if the database cannot be created
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700953 */
954 @NonNull
955 public static SQLiteDatabase createInMemory(@NonNull OpenParams openParams) {
956 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
957 openParams.toBuilder().addOpenFlags(CREATE_IF_NECESSARY).build());
958 }
959
960 /**
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400961 * Registers a CustomFunction callback as a function that can be called from
Jeff Browne5360fb2011-10-31 17:48:13 -0700962 * SQLite database triggers.
963 *
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400964 * @param name the name of the sqlite3 function
965 * @param numArgs the number of arguments for the function
966 * @param function callback to call when the function is executed
967 * @hide
968 */
969 public void addCustomFunction(String name, int numArgs, CustomFunction function) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700970 // Create wrapper (also validates arguments).
971 SQLiteCustomFunction wrapper = new SQLiteCustomFunction(name, numArgs, function);
972
973 synchronized (mLock) {
974 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -0700975
Jeff Browne5360fb2011-10-31 17:48:13 -0700976 mConfigurationLocked.customFunctions.add(wrapper);
Jeff Browne67ca422012-03-21 17:24:05 -0700977 try {
978 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
979 } catch (RuntimeException ex) {
980 mConfigurationLocked.customFunctions.remove(wrapper);
981 throw ex;
982 }
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400983 }
984 }
985
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400986 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 * Gets the database version.
988 *
989 * @return the database version
990 */
991 public int getVersion() {
Vasu Noriccd95442010-05-28 17:04:16 -0700992 return ((Long) DatabaseUtils.longForQuery(this, "PRAGMA user_version;", null)).intValue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 }
994
995 /**
996 * Sets the database version.
997 *
998 * @param version the new database version
999 */
1000 public void setVersion(int version) {
1001 execSQL("PRAGMA user_version = " + version);
1002 }
1003
1004 /**
1005 * Returns the maximum size the database may grow to.
1006 *
1007 * @return the new maximum database size
1008 */
1009 public long getMaximumSize() {
Vasu Noriccd95442010-05-28 17:04:16 -07001010 long pageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count;", null);
1011 return pageCount * getPageSize();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 }
1013
1014 /**
1015 * Sets the maximum size the database will grow to. The maximum size cannot
1016 * be set below the current size.
1017 *
1018 * @param numBytes the maximum database size, in bytes
1019 * @return the new maximum database size
1020 */
1021 public long setMaximumSize(long numBytes) {
Vasu Noriccd95442010-05-28 17:04:16 -07001022 long pageSize = getPageSize();
1023 long numPages = numBytes / pageSize;
1024 // If numBytes isn't a multiple of pageSize, bump up a page
1025 if ((numBytes % pageSize) != 0) {
1026 numPages++;
Vasu Norif3cf8a42010-03-23 11:41:44 -07001027 }
Vasu Noriccd95442010-05-28 17:04:16 -07001028 long newPageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count = " + numPages,
1029 null);
1030 return newPageCount * pageSize;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 }
1032
1033 /**
1034 * Returns the current database page size, in bytes.
1035 *
1036 * @return the database page size, in bytes
1037 */
1038 public long getPageSize() {
Vasu Noriccd95442010-05-28 17:04:16 -07001039 return DatabaseUtils.longForQuery(this, "PRAGMA page_size;", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 }
1041
1042 /**
1043 * Sets the database page size. The page size must be a power of two. This
1044 * method does not work if any data has been written to the database file,
1045 * and must be called right after the database has been created.
1046 *
1047 * @param numBytes the database page size, in bytes
1048 */
1049 public void setPageSize(long numBytes) {
1050 execSQL("PRAGMA page_size = " + numBytes);
1051 }
1052
1053 /**
1054 * Mark this table as syncable. When an update occurs in this table the
1055 * _sync_dirty field will be set to ensure proper syncing operation.
1056 *
1057 * @param table the table to mark as syncable
1058 * @param deletedTable The deleted table that corresponds to the
1059 * syncable table
Vasu Nori95675132010-07-21 16:24:40 -07001060 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061 */
Vasu Nori95675132010-07-21 16:24:40 -07001062 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 public void markTableSyncable(String table, String deletedTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 }
1065
1066 /**
1067 * Mark this table as syncable, with the _sync_dirty residing in another
1068 * table. When an update occurs in this table the _sync_dirty field of the
1069 * row in updateTable with the _id in foreignKey will be set to
1070 * ensure proper syncing operation.
1071 *
1072 * @param table an update on this table will trigger a sync time removal
1073 * @param foreignKey this is the column in table whose value is an _id in
1074 * updateTable
1075 * @param updateTable this is the table that will have its _sync_dirty
Vasu Nori95675132010-07-21 16:24:40 -07001076 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 */
Vasu Nori95675132010-07-21 16:24:40 -07001078 @Deprecated
1079 public void markTableSyncable(String table, String foreignKey, String updateTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 }
1081
1082 /**
1083 * Finds the name of the first table, which is editable.
1084 *
1085 * @param tables a list of tables
1086 * @return the first table listed
1087 */
1088 public static String findEditTable(String tables) {
1089 if (!TextUtils.isEmpty(tables)) {
1090 // find the first word terminated by either a space or a comma
1091 int spacepos = tables.indexOf(' ');
1092 int commapos = tables.indexOf(',');
1093
1094 if (spacepos > 0 && (spacepos < commapos || commapos < 0)) {
1095 return tables.substring(0, spacepos);
1096 } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) {
1097 return tables.substring(0, commapos);
1098 }
1099 return tables;
1100 } else {
1101 throw new IllegalStateException("Invalid tables");
1102 }
1103 }
1104
1105 /**
1106 * Compiles an SQL statement into a reusable pre-compiled statement object.
1107 * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the
1108 * statement and fill in those values with {@link SQLiteProgram#bindString}
1109 * and {@link SQLiteProgram#bindLong} each time you want to run the
1110 * statement. Statements may not return result sets larger than 1x1.
Vasu Nori2827d6d2010-07-04 00:26:18 -07001111 *<p>
1112 * No two threads should be using the same {@link SQLiteStatement} at the same time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 *
1114 * @param sql The raw SQL statement, may contain ? for unknown values to be
1115 * bound later.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001116 * @return A pre-compiled {@link SQLiteStatement} object. Note that
1117 * {@link SQLiteStatement}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 */
1119 public SQLiteStatement compileStatement(String sql) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001120 acquireReference();
1121 try {
1122 return new SQLiteStatement(this, sql, null);
1123 } finally {
1124 releaseReference();
1125 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001126 }
1127
1128 /**
1129 * Query the given URL, returning a {@link Cursor} over the result set.
1130 *
1131 * @param distinct true if you want each row to be unique, false otherwise.
1132 * @param table The table name to compile the query against.
1133 * @param columns A list of which columns to return. Passing null will
1134 * return all columns, which is discouraged to prevent reading
1135 * data from storage that isn't going to be used.
1136 * @param selection A filter declaring which rows to return, formatted as an
1137 * SQL WHERE clause (excluding the WHERE itself). Passing null
1138 * will return all rows for the given table.
1139 * @param selectionArgs You may include ?s in selection, which will be
1140 * replaced by the values from selectionArgs, in order that they
1141 * appear in the selection. The values will be bound as Strings.
1142 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1143 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1144 * will cause the rows to not be grouped.
1145 * @param having A filter declare which row groups to include in the cursor,
1146 * if row grouping is being used, formatted as an SQL HAVING
1147 * clause (excluding the HAVING itself). Passing null will cause
1148 * all row groups to be included, and is required when row
1149 * grouping is not being used.
1150 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1151 * (excluding the ORDER BY itself). Passing null will use the
1152 * default sort order, which may be unordered.
1153 * @param limit Limits the number of rows returned by the query,
1154 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001155 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1156 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 * @see Cursor
1158 */
1159 public Cursor query(boolean distinct, String table, String[] columns,
1160 String selection, String[] selectionArgs, String groupBy,
1161 String having, String orderBy, String limit) {
1162 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown75ea64f2012-01-25 19:37:13 -08001163 groupBy, having, orderBy, limit, null);
1164 }
1165
1166 /**
1167 * Query the given URL, returning a {@link Cursor} over the result set.
1168 *
1169 * @param distinct true if you want each row to be unique, false otherwise.
1170 * @param table The table name to compile the query against.
1171 * @param columns A list of which columns to return. Passing null will
1172 * return all columns, which is discouraged to prevent reading
1173 * data from storage that isn't going to be used.
1174 * @param selection A filter declaring which rows to return, formatted as an
1175 * SQL WHERE clause (excluding the WHERE itself). Passing null
1176 * will return all rows for the given table.
1177 * @param selectionArgs You may include ?s in selection, which will be
1178 * replaced by the values from selectionArgs, in order that they
1179 * appear in the selection. The values will be bound as Strings.
1180 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1181 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1182 * will cause the rows to not be grouped.
1183 * @param having A filter declare which row groups to include in the cursor,
1184 * if row grouping is being used, formatted as an SQL HAVING
1185 * clause (excluding the HAVING itself). Passing null will cause
1186 * all row groups to be included, and is required when row
1187 * grouping is not being used.
1188 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1189 * (excluding the ORDER BY itself). Passing null will use the
1190 * default sort order, which may be unordered.
1191 * @param limit Limits the number of rows returned by the query,
1192 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001193 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001194 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1195 * when the query is executed.
1196 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1197 * {@link Cursor}s are not synchronized, see the documentation for more details.
1198 * @see Cursor
1199 */
1200 public Cursor query(boolean distinct, String table, String[] columns,
1201 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001202 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001203 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001204 groupBy, having, orderBy, limit, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 }
1206
1207 /**
1208 * Query the given URL, returning a {@link Cursor} over the result set.
1209 *
1210 * @param cursorFactory the cursor factory to use, or null for the default factory
1211 * @param distinct true if you want each row to be unique, false otherwise.
1212 * @param table The table name to compile the query against.
1213 * @param columns A list of which columns to return. Passing null will
1214 * return all columns, which is discouraged to prevent reading
1215 * data from storage that isn't going to be used.
1216 * @param selection A filter declaring which rows to return, formatted as an
1217 * SQL WHERE clause (excluding the WHERE itself). Passing null
1218 * will return all rows for the given table.
1219 * @param selectionArgs You may include ?s in selection, which will be
1220 * replaced by the values from selectionArgs, in order that they
1221 * appear in the selection. The values will be bound as Strings.
1222 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1223 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1224 * will cause the rows to not be grouped.
1225 * @param having A filter declare which row groups to include in the cursor,
1226 * if row grouping is being used, formatted as an SQL HAVING
1227 * clause (excluding the HAVING itself). Passing null will cause
1228 * all row groups to be included, and is required when row
1229 * grouping is not being used.
1230 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1231 * (excluding the ORDER BY itself). Passing null will use the
1232 * default sort order, which may be unordered.
1233 * @param limit Limits the number of rows returned by the query,
1234 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001235 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1236 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 * @see Cursor
1238 */
1239 public Cursor queryWithFactory(CursorFactory cursorFactory,
1240 boolean distinct, String table, String[] columns,
1241 String selection, String[] selectionArgs, String groupBy,
1242 String having, String orderBy, String limit) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001243 return queryWithFactory(cursorFactory, distinct, table, columns, selection,
1244 selectionArgs, groupBy, having, orderBy, limit, null);
1245 }
1246
1247 /**
1248 * Query the given URL, returning a {@link Cursor} over the result set.
1249 *
1250 * @param cursorFactory the cursor factory to use, or null for the default factory
1251 * @param distinct true if you want each row to be unique, false otherwise.
1252 * @param table The table name to compile the query against.
1253 * @param columns A list of which columns to return. Passing null will
1254 * return all columns, which is discouraged to prevent reading
1255 * data from storage that isn't going to be used.
1256 * @param selection A filter declaring which rows to return, formatted as an
1257 * SQL WHERE clause (excluding the WHERE itself). Passing null
1258 * will return all rows for the given table.
1259 * @param selectionArgs You may include ?s in selection, which will be
1260 * replaced by the values from selectionArgs, in order that they
1261 * appear in the selection. The values will be bound as Strings.
1262 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1263 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1264 * will cause the rows to not be grouped.
1265 * @param having A filter declare which row groups to include in the cursor,
1266 * if row grouping is being used, formatted as an SQL HAVING
1267 * clause (excluding the HAVING itself). Passing null will cause
1268 * all row groups to be included, and is required when row
1269 * grouping is not being used.
1270 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1271 * (excluding the ORDER BY itself). Passing null will use the
1272 * default sort order, which may be unordered.
1273 * @param limit Limits the number of rows returned by the query,
1274 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001275 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001276 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1277 * when the query is executed.
1278 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1279 * {@link Cursor}s are not synchronized, see the documentation for more details.
1280 * @see Cursor
1281 */
1282 public Cursor queryWithFactory(CursorFactory cursorFactory,
1283 boolean distinct, String table, String[] columns,
1284 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001285 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001286 acquireReference();
1287 try {
1288 String sql = SQLiteQueryBuilder.buildQueryString(
1289 distinct, table, columns, selection, groupBy, having, orderBy, limit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001290
Jeff Brown03bd3022012-03-06 13:48:56 -08001291 return rawQueryWithFactory(cursorFactory, sql, selectionArgs,
1292 findEditTable(table), cancellationSignal);
1293 } finally {
1294 releaseReference();
1295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001296 }
1297
1298 /**
1299 * Query the given table, returning a {@link Cursor} over the result set.
1300 *
1301 * @param table The table name to compile the query against.
1302 * @param columns A list of which columns to return. Passing null will
1303 * return all columns, which is discouraged to prevent reading
1304 * data from storage that isn't going to be used.
1305 * @param selection A filter declaring which rows to return, formatted as an
1306 * SQL WHERE clause (excluding the WHERE itself). Passing null
1307 * will return all rows for the given table.
1308 * @param selectionArgs You may include ?s in selection, which will be
1309 * replaced by the values from selectionArgs, in order that they
1310 * appear in the selection. The values will be bound as Strings.
1311 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1312 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1313 * will cause the rows to not be grouped.
1314 * @param having A filter declare which row groups to include in the cursor,
1315 * if row grouping is being used, formatted as an SQL HAVING
1316 * clause (excluding the HAVING itself). Passing null will cause
1317 * all row groups to be included, and is required when row
1318 * grouping is not being used.
1319 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1320 * (excluding the ORDER BY itself). Passing null will use the
1321 * default sort order, which may be unordered.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001322 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1323 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324 * @see Cursor
1325 */
1326 public Cursor query(String table, String[] columns, String selection,
1327 String[] selectionArgs, String groupBy, String having,
1328 String orderBy) {
1329
1330 return query(false, table, columns, selection, selectionArgs, groupBy,
1331 having, orderBy, null /* limit */);
1332 }
1333
1334 /**
1335 * Query the given table, returning a {@link Cursor} over the result set.
1336 *
1337 * @param table The table name to compile the query against.
1338 * @param columns A list of which columns to return. Passing null will
1339 * return all columns, which is discouraged to prevent reading
1340 * data from storage that isn't going to be used.
1341 * @param selection A filter declaring which rows to return, formatted as an
1342 * SQL WHERE clause (excluding the WHERE itself). Passing null
1343 * will return all rows for the given table.
1344 * @param selectionArgs You may include ?s in selection, which will be
1345 * replaced by the values from selectionArgs, in order that they
1346 * appear in the selection. The values will be bound as Strings.
1347 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1348 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1349 * will cause the rows to not be grouped.
1350 * @param having A filter declare which row groups to include in the cursor,
1351 * if row grouping is being used, formatted as an SQL HAVING
1352 * clause (excluding the HAVING itself). Passing null will cause
1353 * all row groups to be included, and is required when row
1354 * grouping is not being used.
1355 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1356 * (excluding the ORDER BY itself). Passing null will use the
1357 * default sort order, which may be unordered.
1358 * @param limit Limits the number of rows returned by the query,
1359 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001360 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1361 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362 * @see Cursor
1363 */
1364 public Cursor query(String table, String[] columns, String selection,
1365 String[] selectionArgs, String groupBy, String having,
1366 String orderBy, String limit) {
1367
1368 return query(false, table, columns, selection, selectionArgs, groupBy,
1369 having, orderBy, limit);
1370 }
1371
1372 /**
1373 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1374 *
1375 * @param sql the SQL query. The SQL string must not be ; terminated
1376 * @param selectionArgs You may include ?s in where clause in the query,
1377 * which will be replaced by the values from selectionArgs. The
1378 * values will be bound as Strings.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001379 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1380 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 */
1382 public Cursor rawQuery(String sql, String[] selectionArgs) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001383 return rawQueryWithFactory(null, sql, selectionArgs, null, null);
1384 }
1385
1386 /**
1387 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1388 *
1389 * @param sql the SQL query. The SQL string must not be ; terminated
1390 * @param selectionArgs You may include ?s in where clause in the query,
1391 * which will be replaced by the values from selectionArgs. The
1392 * values will be bound as Strings.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001393 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001394 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1395 * when the query is executed.
1396 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1397 * {@link Cursor}s are not synchronized, see the documentation for more details.
1398 */
1399 public Cursor rawQuery(String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001400 CancellationSignal cancellationSignal) {
1401 return rawQueryWithFactory(null, sql, selectionArgs, null, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 }
1403
1404 /**
1405 * Runs the provided SQL and returns a cursor over the result set.
1406 *
1407 * @param cursorFactory the cursor factory to use, or null for the default factory
1408 * @param sql the SQL query. The SQL string must not be ; terminated
1409 * @param selectionArgs You may include ?s in where clause in the query,
1410 * which will be replaced by the values from selectionArgs. The
1411 * values will be bound as Strings.
1412 * @param editTable the name of the first table, which is editable
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001413 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1414 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001415 */
1416 public Cursor rawQueryWithFactory(
1417 CursorFactory cursorFactory, String sql, String[] selectionArgs,
1418 String editTable) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001419 return rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable, null);
1420 }
1421
1422 /**
1423 * Runs the provided SQL and returns a cursor over the result set.
1424 *
1425 * @param cursorFactory the cursor factory to use, or null for the default factory
1426 * @param sql the SQL query. The SQL string must not be ; terminated
1427 * @param selectionArgs You may include ?s in where clause in the query,
1428 * which will be replaced by the values from selectionArgs. The
1429 * values will be bound as Strings.
1430 * @param editTable the name of the first table, which is editable
Jeff Brown4c1241d2012-02-02 17:05:00 -08001431 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001432 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1433 * when the query is executed.
1434 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1435 * {@link Cursor}s are not synchronized, see the documentation for more details.
1436 */
1437 public Cursor rawQueryWithFactory(
1438 CursorFactory cursorFactory, String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001439 String editTable, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001440 acquireReference();
1441 try {
1442 SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
1443 cancellationSignal);
1444 return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
1445 selectionArgs);
1446 } finally {
1447 releaseReference();
1448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 }
1450
1451 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 * Convenience method for inserting a row into the database.
1453 *
1454 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001455 * @param nullColumnHack optional; may be <code>null</code>.
1456 * SQL doesn't allow inserting a completely empty row without
1457 * naming at least one column name. If your provided <code>values</code> is
1458 * empty, no column names are known and an empty row can't be inserted.
1459 * If not set to null, the <code>nullColumnHack</code> parameter
1460 * provides the name of nullable column name to explicitly insert a NULL into
1461 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462 * @param values this map contains the initial column values for the
1463 * row. The keys should be the column names and the values the
1464 * column values
1465 * @return the row ID of the newly inserted row, or -1 if an error occurred
1466 */
1467 public long insert(String table, String nullColumnHack, ContentValues values) {
1468 try {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001469 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 } catch (SQLException e) {
1471 Log.e(TAG, "Error inserting " + values, e);
1472 return -1;
1473 }
1474 }
1475
1476 /**
1477 * Convenience method for inserting a row into the database.
1478 *
1479 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001480 * @param nullColumnHack optional; may be <code>null</code>.
1481 * SQL doesn't allow inserting a completely empty row without
1482 * naming at least one column name. If your provided <code>values</code> is
1483 * empty, no column names are known and an empty row can't be inserted.
1484 * If not set to null, the <code>nullColumnHack</code> parameter
1485 * provides the name of nullable column name to explicitly insert a NULL into
1486 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 * @param values this map contains the initial column values for the
1488 * row. The keys should be the column names and the values the
1489 * column values
1490 * @throws SQLException
1491 * @return the row ID of the newly inserted row, or -1 if an error occurred
1492 */
1493 public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
1494 throws SQLException {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001495 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 }
1497
1498 /**
1499 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001500 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 *
1502 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001503 * @param nullColumnHack optional; may be <code>null</code>.
1504 * SQL doesn't allow inserting a completely empty row without
1505 * naming at least one column name. If your provided <code>initialValues</code> is
1506 * empty, no column names are known and an empty row can't be inserted.
1507 * If not set to null, the <code>nullColumnHack</code> parameter
1508 * provides the name of nullable column name to explicitly insert a NULL into
1509 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001511 * 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 -08001512 * @return the row ID of the newly inserted row, or -1 if an error occurred
1513 */
1514 public long replace(String table, String nullColumnHack, ContentValues initialValues) {
1515 try {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001516 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001517 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 } catch (SQLException e) {
1519 Log.e(TAG, "Error inserting " + initialValues, e);
1520 return -1;
1521 }
1522 }
1523
1524 /**
1525 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001526 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001527 *
1528 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001529 * @param nullColumnHack optional; may be <code>null</code>.
1530 * SQL doesn't allow inserting a completely empty row without
1531 * naming at least one column name. If your provided <code>initialValues</code> is
1532 * empty, no column names are known and an empty row can't be inserted.
1533 * If not set to null, the <code>nullColumnHack</code> parameter
1534 * provides the name of nullable column name to explicitly insert a NULL into
1535 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001537 * 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 -08001538 * @throws SQLException
1539 * @return the row ID of the newly inserted row, or -1 if an error occurred
1540 */
1541 public long replaceOrThrow(String table, String nullColumnHack,
1542 ContentValues initialValues) throws SQLException {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001543 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001544 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 }
1546
1547 /**
1548 * General method for inserting a row into the database.
1549 *
1550 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001551 * @param nullColumnHack optional; may be <code>null</code>.
1552 * SQL doesn't allow inserting a completely empty row without
1553 * naming at least one column name. If your provided <code>initialValues</code> is
1554 * empty, no column names are known and an empty row can't be inserted.
1555 * If not set to null, the <code>nullColumnHack</code> parameter
1556 * provides the name of nullable column name to explicitly insert a NULL into
1557 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 * @param initialValues this map contains the initial column values for the
1559 * row. The keys should be the column names and the values the
1560 * column values
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001561 * @param conflictAlgorithm for insert conflict resolver
Steve Pomeroyc240b602013-03-14 00:42:10 -04001562 * @return the row ID of the newly inserted row OR <code>-1</code> if either the
1563 * input parameter <code>conflictAlgorithm</code> = {@link #CONFLICT_IGNORE}
1564 * or an error occurred.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 */
1566 public long insertWithOnConflict(String table, String nullColumnHack,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001567 ContentValues initialValues, int conflictAlgorithm) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001568 acquireReference();
1569 try {
1570 StringBuilder sql = new StringBuilder();
1571 sql.append("INSERT");
1572 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1573 sql.append(" INTO ");
1574 sql.append(table);
1575 sql.append('(');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576
Jeff Brown03bd3022012-03-06 13:48:56 -08001577 Object[] bindArgs = null;
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001578 int size = (initialValues != null && !initialValues.isEmpty())
Jeff Brown03bd3022012-03-06 13:48:56 -08001579 ? initialValues.size() : 0;
1580 if (size > 0) {
1581 bindArgs = new Object[size];
1582 int i = 0;
1583 for (String colName : initialValues.keySet()) {
1584 sql.append((i > 0) ? "," : "");
1585 sql.append(colName);
1586 bindArgs[i++] = initialValues.get(colName);
1587 }
1588 sql.append(')');
1589 sql.append(" VALUES (");
1590 for (i = 0; i < size; i++) {
1591 sql.append((i > 0) ? ",?" : "?");
1592 }
1593 } else {
1594 sql.append(nullColumnHack + ") VALUES (NULL");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 sql.append(')');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597
Jeff Brown03bd3022012-03-06 13:48:56 -08001598 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1599 try {
1600 return statement.executeInsert();
1601 } finally {
1602 statement.close();
1603 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001605 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 }
1607 }
1608
1609 /**
1610 * Convenience method for deleting rows in the database.
1611 *
1612 * @param table the table to delete from
1613 * @param whereClause the optional WHERE clause to apply when deleting.
1614 * Passing null will delete all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001615 * @param whereArgs You may include ?s in the where clause, which
1616 * will be replaced by the values from whereArgs. The values
1617 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 * @return the number of rows affected if a whereClause is passed in, 0
1619 * otherwise. To remove all rows and get a count pass "1" as the
1620 * whereClause.
1621 */
1622 public int delete(String table, String whereClause, String[] whereArgs) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001623 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001625 SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table +
1626 (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
1627 try {
1628 return statement.executeUpdateDelete();
1629 } finally {
1630 statement.close();
1631 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001633 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 }
1635 }
1636
1637 /**
1638 * Convenience method for updating rows in the database.
1639 *
1640 * @param table the table to update in
1641 * @param values a map from column names to new column values. null is a
1642 * valid value that will be translated to NULL.
1643 * @param whereClause the optional WHERE clause to apply when updating.
1644 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001645 * @param whereArgs You may include ?s in the where clause, which
1646 * will be replaced by the values from whereArgs. The values
1647 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 * @return the number of rows affected
1649 */
1650 public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001651 return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 /**
1655 * Convenience method for updating rows in the database.
1656 *
1657 * @param table the table to update in
1658 * @param values a map from column names to new column values. null is a
1659 * valid value that will be translated to NULL.
1660 * @param whereClause the optional WHERE clause to apply when updating.
1661 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001662 * @param whereArgs You may include ?s in the where clause, which
1663 * will be replaced by the values from whereArgs. The values
1664 * will be bound as Strings.
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001665 * @param conflictAlgorithm for update conflict resolver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 * @return the number of rows affected
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001667 */
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001668 public int updateWithOnConflict(String table, ContentValues values,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001669 String whereClause, String[] whereArgs, int conflictAlgorithm) {
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001670 if (values == null || values.isEmpty()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 throw new IllegalArgumentException("Empty values");
1672 }
1673
Jeff Brown03bd3022012-03-06 13:48:56 -08001674 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001676 StringBuilder sql = new StringBuilder(120);
1677 sql.append("UPDATE ");
1678 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1679 sql.append(table);
1680 sql.append(" SET ");
1681
1682 // move all bind args to one array
1683 int setValuesSize = values.size();
1684 int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
1685 Object[] bindArgs = new Object[bindArgsSize];
1686 int i = 0;
1687 for (String colName : values.keySet()) {
1688 sql.append((i > 0) ? "," : "");
1689 sql.append(colName);
1690 bindArgs[i++] = values.get(colName);
1691 sql.append("=?");
1692 }
1693 if (whereArgs != null) {
1694 for (i = setValuesSize; i < bindArgsSize; i++) {
1695 bindArgs[i] = whereArgs[i - setValuesSize];
1696 }
1697 }
1698 if (!TextUtils.isEmpty(whereClause)) {
1699 sql.append(" WHERE ");
1700 sql.append(whereClause);
1701 }
1702
1703 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1704 try {
1705 return statement.executeUpdateDelete();
1706 } finally {
1707 statement.close();
1708 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001710 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711 }
1712 }
1713
1714 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001715 * Execute a single SQL statement that is NOT a SELECT
1716 * or any other SQL statement that returns data.
1717 * <p>
Vasu Norice38b982010-07-22 13:57:13 -07001718 * It has no means to return any data (such as the number of affected rows).
Vasu Noriccd95442010-05-28 17:04:16 -07001719 * Instead, you're encouraged to use {@link #insert(String, String, ContentValues)},
1720 * {@link #update(String, ContentValues, String, String[])}, et al, when possible.
1721 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001722 * <p>
1723 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1724 * automatically managed by this class. So, do not set journal_mode
1725 * using "PRAGMA journal_mode'<value>" statement if your app is using
1726 * {@link #enableWriteAheadLogging()}
1727 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 *
Vasu Noriccd95442010-05-28 17:04:16 -07001729 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1730 * not supported.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001731 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001732 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001733 public void execSQL(String sql) throws SQLException {
Vasu Nori16057fa2011-03-18 11:40:37 -07001734 executeSql(sql, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735 }
1736
1737 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001738 * Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE.
1739 * <p>
1740 * For INSERT statements, use any of the following instead.
1741 * <ul>
1742 * <li>{@link #insert(String, String, ContentValues)}</li>
1743 * <li>{@link #insertOrThrow(String, String, ContentValues)}</li>
1744 * <li>{@link #insertWithOnConflict(String, String, ContentValues, int)}</li>
1745 * </ul>
1746 * <p>
1747 * For UPDATE statements, use any of the following instead.
1748 * <ul>
1749 * <li>{@link #update(String, ContentValues, String, String[])}</li>
1750 * <li>{@link #updateWithOnConflict(String, ContentValues, String, String[], int)}</li>
1751 * </ul>
1752 * <p>
1753 * For DELETE statements, use any of the following instead.
1754 * <ul>
1755 * <li>{@link #delete(String, String, String[])}</li>
1756 * </ul>
1757 * <p>
1758 * For example, the following are good candidates for using this method:
1759 * <ul>
1760 * <li>ALTER TABLE</li>
1761 * <li>CREATE or DROP table / trigger / view / index / virtual table</li>
1762 * <li>REINDEX</li>
1763 * <li>RELEASE</li>
1764 * <li>SAVEPOINT</li>
1765 * <li>PRAGMA that returns no data</li>
1766 * </ul>
1767 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001768 * <p>
1769 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1770 * automatically managed by this class. So, do not set journal_mode
1771 * using "PRAGMA journal_mode'<value>" statement if your app is using
1772 * {@link #enableWriteAheadLogging()}
1773 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 *
Vasu Noriccd95442010-05-28 17:04:16 -07001775 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1776 * not supported.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777 * @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001778 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001779 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001780 public void execSQL(String sql, Object[] bindArgs) throws SQLException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 if (bindArgs == null) {
1782 throw new IllegalArgumentException("Empty bindArgs");
1783 }
Vasu Norib83cb7c2010-09-14 13:36:01 -07001784 executeSql(sql, bindArgs);
Vasu Norice38b982010-07-22 13:57:13 -07001785 }
1786
Jeff Sharkey6adc98c2018-07-12 19:47:49 -06001787 /** {@hide} */
1788 public int executeSql(String sql, Object[] bindArgs) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001789 acquireReference();
1790 try {
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001791 final int statementType = DatabaseUtils.getSqlStatementType(sql);
1792 if (statementType == DatabaseUtils.STATEMENT_ATTACH) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001793 boolean disableWal = false;
1794 synchronized (mLock) {
1795 if (!mHasAttachedDbsLocked) {
1796 mHasAttachedDbsLocked = true;
1797 disableWal = true;
Fyodor Kupolovfd9c4a52017-07-13 15:36:57 -07001798 mConnectionPoolLocked.disableIdleConnectionHandler();
Jeff Brown03bd3022012-03-06 13:48:56 -08001799 }
1800 }
1801 if (disableWal) {
1802 disableWriteAheadLogging();
Jeff Browne5360fb2011-10-31 17:48:13 -07001803 }
1804 }
Jeff Browne5360fb2011-10-31 17:48:13 -07001805
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001806 try (SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs)) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001807 return statement.executeUpdateDelete();
1808 } finally {
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001809 // If schema was updated, close non-primary connections, otherwise they might
1810 // have outdated schema information
1811 if (statementType == DatabaseUtils.STATEMENT_DDL) {
1812 mConnectionPoolLocked.closeAvailableNonPrimaryConnectionsAndLogExceptions();
1813 }
Jeff Brown03bd3022012-03-06 13:48:56 -08001814 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001816 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 }
1819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 /**
Makoto Onuki17aa1b72015-12-16 14:02:01 -08001821 * Verifies that a SQL SELECT statement is valid by compiling it.
1822 * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
1823 *
1824 * @param sql SQL to be validated
1825 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
1826 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1827 * when the query is executed.
1828 * @throws SQLiteException if {@code sql} is invalid
1829 */
1830 public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal) {
1831 getThreadSession().prepare(sql,
1832 getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null);
1833 }
1834
1835 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001836 * Returns true if the database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001838 * @return True if database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 */
1840 public boolean isReadOnly() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001841 synchronized (mLock) {
1842 return isReadOnlyLocked();
1843 }
1844 }
1845
1846 private boolean isReadOnlyLocked() {
1847 return (mConfigurationLocked.openFlags & OPEN_READ_MASK) == OPEN_READONLY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848 }
1849
1850 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001851 * Returns true if the database is in-memory db.
1852 *
1853 * @return True if the database is in-memory.
1854 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001855 */
Jeff Browne5360fb2011-10-31 17:48:13 -07001856 public boolean isInMemoryDatabase() {
1857 synchronized (mLock) {
1858 return mConfigurationLocked.isInMemoryDb();
1859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 }
1861
Jeff Browne5360fb2011-10-31 17:48:13 -07001862 /**
1863 * Returns true if the database is currently open.
1864 *
1865 * @return True if the database is currently open (has not been closed).
1866 */
1867 public boolean isOpen() {
1868 synchronized (mLock) {
1869 return mConnectionPoolLocked != null;
1870 }
1871 }
1872
1873 /**
1874 * Returns true if the new version code is greater than the current database version.
1875 *
1876 * @param newVersion The new version code.
Mark Lu1e202082016-08-30 17:41:25 -07001877 * @return True if the new version code is greater than the current database version.
Jeff Browne5360fb2011-10-31 17:48:13 -07001878 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001879 public boolean needUpgrade(int newVersion) {
1880 return newVersion > getVersion();
1881 }
1882
1883 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001884 * Gets the path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001886 * @return The path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001887 */
1888 public final String getPath() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001889 synchronized (mLock) {
1890 return mConfigurationLocked.path;
Christopher Tatead9e8b12011-10-05 17:49:26 -07001891 }
Brad Fitzpatrick722802e2010-03-23 22:22:16 -07001892 }
1893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 /**
1895 * Sets the locale for this database. Does nothing if this database has
Jeff Brown1d9f7422012-03-15 14:32:32 -07001896 * the {@link #NO_LOCALIZED_COLLATORS} flag set or was opened read only.
Jeff Browne5360fb2011-10-31 17:48:13 -07001897 *
1898 * @param locale The new locale.
1899 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001900 * @throws SQLException if the locale could not be set. The most common reason
1901 * for this is that there is no collator available for the locale you requested.
1902 * In this case the database remains unchanged.
1903 */
1904 public void setLocale(Locale locale) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001905 if (locale == null) {
1906 throw new IllegalArgumentException("locale must not be null.");
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001907 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001908
Jeff Browne5360fb2011-10-31 17:48:13 -07001909 synchronized (mLock) {
1910 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001911
1912 final Locale oldLocale = mConfigurationLocked.locale;
Jeff Browne5360fb2011-10-31 17:48:13 -07001913 mConfigurationLocked.locale = locale;
Jeff Browne67ca422012-03-21 17:24:05 -07001914 try {
1915 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1916 } catch (RuntimeException ex) {
1917 mConfigurationLocked.locale = oldLocale;
1918 throw ex;
1919 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001920 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001921 }
1922
Vasu Norie495d1f2010-01-06 16:34:19 -08001923 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001924 * Sets the maximum size of the prepared-statement cache for this database.
Vasu Norie495d1f2010-01-06 16:34:19 -08001925 * (size of the cache = number of compiled-sql-statements stored in the cache).
Vasu Noriccd95442010-05-28 17:04:16 -07001926 *<p>
Vasu Norib729dcc2010-09-14 11:35:49 -07001927 * Maximum cache size can ONLY be increased from its current size (default = 10).
Vasu Noriccd95442010-05-28 17:04:16 -07001928 * If this method is called with smaller size than the current maximum value,
1929 * then IllegalStateException is thrown.
Vasu Norib729dcc2010-09-14 11:35:49 -07001930 *<p>
1931 * This method is thread-safe.
Vasu Norie495d1f2010-01-06 16:34:19 -08001932 *
Vasu Nori90a367262010-04-12 12:49:09 -07001933 * @param cacheSize the size of the cache. can be (0 to {@link #MAX_SQL_CACHE_SIZE})
Jeff Browne5360fb2011-10-31 17:48:13 -07001934 * @throws IllegalStateException if input cacheSize > {@link #MAX_SQL_CACHE_SIZE}.
Vasu Norie495d1f2010-01-06 16:34:19 -08001935 */
Vasu Nori54025902010-09-14 12:14:26 -07001936 public void setMaxSqlCacheSize(int cacheSize) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001937 if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) {
1938 throw new IllegalStateException(
1939 "expected value between 0 and " + MAX_SQL_CACHE_SIZE);
Vasu Nori587423a2010-09-27 18:18:34 -07001940 }
Vasu Nori587423a2010-09-27 18:18:34 -07001941
Jeff Browne5360fb2011-10-31 17:48:13 -07001942 synchronized (mLock) {
1943 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001944
1945 final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize;
Jeff Browne5360fb2011-10-31 17:48:13 -07001946 mConfigurationLocked.maxSqlCacheSize = cacheSize;
Jeff Browne67ca422012-03-21 17:24:05 -07001947 try {
1948 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1949 } catch (RuntimeException ex) {
1950 mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize;
1951 throw ex;
1952 }
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001953 }
1954 }
1955
Vasu Nori6c354da2010-04-26 23:33:39 -07001956 /**
Jeff Brown96496ad2012-03-23 14:38:06 -07001957 * Sets whether foreign key constraints are enabled for the database.
1958 * <p>
1959 * By default, foreign key constraints are not enforced by the database.
1960 * This method allows an application to enable foreign key constraints.
1961 * It must be called each time the database is opened to ensure that foreign
1962 * key constraints are enabled for the session.
1963 * </p><p>
1964 * A good time to call this method is right after calling {@link #openOrCreateDatabase}
1965 * or in the {@link SQLiteOpenHelper#onConfigure} callback.
1966 * </p><p>
1967 * When foreign key constraints are disabled, the database does not check whether
1968 * changes to the database will violate foreign key constraints. Likewise, when
1969 * foreign key constraints are disabled, the database will not execute cascade
1970 * delete or update triggers. As a result, it is possible for the database
1971 * state to become inconsistent. To perform a database integrity check,
1972 * call {@link #isDatabaseIntegrityOk}.
1973 * </p><p>
1974 * This method must not be called while a transaction is in progress.
1975 * </p><p>
1976 * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a>
1977 * for more details about foreign key constraint support.
1978 * </p>
1979 *
1980 * @param enable True to enable foreign key constraints, false to disable them.
1981 *
1982 * @throws IllegalStateException if the are transactions is in progress
1983 * when this method is called.
1984 */
1985 public void setForeignKeyConstraintsEnabled(boolean enable) {
1986 synchronized (mLock) {
1987 throwIfNotOpenLocked();
1988
1989 if (mConfigurationLocked.foreignKeyConstraintsEnabled == enable) {
1990 return;
1991 }
1992
1993 mConfigurationLocked.foreignKeyConstraintsEnabled = enable;
1994 try {
1995 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1996 } catch (RuntimeException ex) {
1997 mConfigurationLocked.foreignKeyConstraintsEnabled = !enable;
1998 throw ex;
1999 }
2000 }
2001 }
2002
2003 /**
Jeff Brown47847f32012-03-22 19:13:11 -07002004 * This method enables parallel execution of queries from multiple threads on the
2005 * same database. It does this by opening multiple connections to the database
2006 * and using a different database connection for each query. The database
2007 * journal mode is also changed to enable writes to proceed concurrently with reads.
Vasu Nori6c354da2010-04-26 23:33:39 -07002008 * <p>
Jeff Brown47847f32012-03-22 19:13:11 -07002009 * When write-ahead logging is not enabled (the default), it is not possible for
2010 * reads and writes to occur on the database at the same time. Before modifying the
2011 * database, the writer implicitly acquires an exclusive lock on the database which
2012 * prevents readers from accessing the database until the write is completed.
2013 * </p><p>
2014 * In contrast, when write-ahead logging is enabled (by calling this method), write
2015 * operations occur in a separate log file which allows reads to proceed concurrently.
2016 * While a write is in progress, readers on other threads will perceive the state
2017 * of the database as it was before the write began. When the write completes, readers
2018 * on other threads will then perceive the new state of the database.
2019 * </p><p>
2020 * It is a good idea to enable write-ahead logging whenever a database will be
2021 * concurrently accessed and modified by multiple threads at the same time.
2022 * However, write-ahead logging uses significantly more memory than ordinary
2023 * journaling because there are multiple connections to the same database.
2024 * So if a database will only be used by a single thread, or if optimizing
2025 * concurrency is not very important, then write-ahead logging should be disabled.
2026 * </p><p>
2027 * After calling this method, execution of queries in parallel is enabled as long as
2028 * the database remains open. To disable execution of queries in parallel, either
2029 * call {@link #disableWriteAheadLogging} or close the database and reopen it.
2030 * </p><p>
2031 * The maximum number of connections used to execute queries in parallel is
Vasu Nori6c354da2010-04-26 23:33:39 -07002032 * dependent upon the device memory and possibly other properties.
Jeff Brown47847f32012-03-22 19:13:11 -07002033 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07002034 * If a query is part of a transaction, then it is executed on the same database handle the
2035 * transaction was begun.
Jeff Brown47847f32012-03-22 19:13:11 -07002036 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07002037 * Writers should use {@link #beginTransactionNonExclusive()} or
2038 * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
Jeff Brown47847f32012-03-22 19:13:11 -07002039 * to start a transaction. Non-exclusive mode allows database file to be in readable
2040 * by other threads executing queries.
2041 * </p><p>
2042 * If the database has any attached databases, then execution of queries in parallel is NOT
2043 * possible. Likewise, write-ahead logging is not supported for read-only databases
2044 * or memory databases. In such cases, {@link #enableWriteAheadLogging} returns false.
2045 * </p><p>
2046 * The best way to enable write-ahead logging is to pass the
2047 * {@link #ENABLE_WRITE_AHEAD_LOGGING} flag to {@link #openDatabase}. This is
2048 * more efficient than calling {@link #enableWriteAheadLogging}.
2049 * <code><pre>
2050 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2051 * SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
2052 * myDatabaseErrorHandler);
Jeff Brown47847f32012-03-22 19:13:11 -07002053 * </pre></code>
2054 * </p><p>
2055 * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging}
2056 * after opening the database.
2057 * <code><pre>
2058 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2059 * SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
2060 * db.enableWriteAheadLogging();
2061 * </pre></code>
2062 * </p><p>
2063 * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for
2064 * more details about how write-ahead logging works.
Vasu Nori6c354da2010-04-26 23:33:39 -07002065 * </p>
2066 *
Jeff Brown47847f32012-03-22 19:13:11 -07002067 * @return True if write-ahead logging is enabled.
Jeff Browne67ca422012-03-21 17:24:05 -07002068 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002069 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002070 * time this method is called. WAL mode can only be changed when there are no
2071 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002072 *
2073 * @see #ENABLE_WRITE_AHEAD_LOGGING
2074 * @see #disableWriteAheadLogging
Vasu Nori6c354da2010-04-26 23:33:39 -07002075 */
Vasu Noriffe06122010-09-27 12:32:57 -07002076 public boolean enableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002077 synchronized (mLock) {
2078 throwIfNotOpenLocked();
2079
Jeff Brown47847f32012-03-22 19:13:11 -07002080 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002081 return true;
2082 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002083
2084 if (isReadOnlyLocked()) {
2085 // WAL doesn't make sense for readonly-databases.
2086 // TODO: True, but connection pooling does still make sense...
2087 return false;
2088 }
2089
2090 if (mConfigurationLocked.isInMemoryDb()) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002091 Log.i(TAG, "can't enable WAL for memory databases.");
2092 return false;
2093 }
2094
2095 // make sure this database has NO attached databases because sqlite's write-ahead-logging
2096 // doesn't work for databases with attached databases
Jeff Browne5360fb2011-10-31 17:48:13 -07002097 if (mHasAttachedDbsLocked) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002098 if (Log.isLoggable(TAG, Log.DEBUG)) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002099 Log.d(TAG, "this database: " + mConfigurationLocked.label
2100 + " has attached databases. can't enable WAL.");
Paul Westbrookdae6d372011-02-17 10:59:56 -08002101 }
2102 return false;
2103 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002104
Jeff Brown47847f32012-03-22 19:13:11 -07002105 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002106 try {
2107 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2108 } catch (RuntimeException ex) {
Jeff Brown47847f32012-03-22 19:13:11 -07002109 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002110 throw ex;
2111 }
Paul Westbrookdae6d372011-02-17 10:59:56 -08002112 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002113 return true;
Vasu Nori6c354da2010-04-26 23:33:39 -07002114 }
2115
Vasu Nori2827d6d2010-07-04 00:26:18 -07002116 /**
Vasu Nori7b04c412010-07-20 10:31:21 -07002117 * This method disables the features enabled by {@link #enableWriteAheadLogging()}.
Jeff Browne67ca422012-03-21 17:24:05 -07002118 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002119 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002120 * time this method is called. WAL mode can only be changed when there are no
2121 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002122 *
2123 * @see #enableWriteAheadLogging
Vasu Nori2827d6d2010-07-04 00:26:18 -07002124 */
Vasu Nori7b04c412010-07-20 10:31:21 -07002125 public void disableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002126 synchronized (mLock) {
2127 throwIfNotOpenLocked();
2128
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002129 final int oldFlags = mConfigurationLocked.openFlags;
Narayan Kamathb8280432019-02-21 13:20:51 +00002130 final boolean walEnabled = (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2131 final boolean compatibilityWalEnabled =
2132 (oldFlags & ENABLE_LEGACY_COMPATIBILITY_WAL) != 0;
2133 // WAL was never enabled for this database, so there's nothing left to do.
2134 if (!walEnabled && !compatibilityWalEnabled) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002135 return;
Paul Westbrookdae6d372011-02-17 10:59:56 -08002136 }
Vasu Nori8d111032010-06-22 18:34:21 -07002137
Narayan Kamathb8280432019-02-21 13:20:51 +00002138 // If an app explicitly disables WAL, it takes priority over any directive
2139 // to use the legacy "compatibility WAL" mode.
Jeff Brown47847f32012-03-22 19:13:11 -07002140 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Narayan Kamathb8280432019-02-21 13:20:51 +00002141 mConfigurationLocked.openFlags &= ~ENABLE_LEGACY_COMPATIBILITY_WAL;
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002142
Jeff Browne67ca422012-03-21 17:24:05 -07002143 try {
2144 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2145 } catch (RuntimeException ex) {
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002146 mConfigurationLocked.openFlags = oldFlags;
Jeff Browne67ca422012-03-21 17:24:05 -07002147 throw ex;
2148 }
Vasu Nori65a88832010-07-16 15:14:08 -07002149 }
Vasu Nori6c354da2010-04-26 23:33:39 -07002150 }
2151
Vasu Norif3cf8a42010-03-23 11:41:44 -07002152 /**
Jeff Brown47847f32012-03-22 19:13:11 -07002153 * Returns true if write-ahead logging has been enabled for this database.
2154 *
2155 * @return True if write-ahead logging has been enabled for this database.
2156 *
2157 * @see #enableWriteAheadLogging
2158 * @see #ENABLE_WRITE_AHEAD_LOGGING
2159 */
2160 public boolean isWriteAheadLoggingEnabled() {
2161 synchronized (mLock) {
2162 throwIfNotOpenLocked();
2163
2164 return (mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2165 }
2166 }
2167
2168 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002169 * Collect statistics about all open databases in the current process.
2170 * Used by bug report.
Vasu Norif3cf8a42010-03-23 11:41:44 -07002171 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002172 static ArrayList<DbStats> getDbStats() {
Vasu Noric3849202010-03-09 10:47:25 -08002173 ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002174 for (SQLiteDatabase db : getActiveDatabases()) {
2175 db.collectDbStats(dbStatsList);
Vasu Nori24675612010-09-27 14:54:19 -07002176 }
Vasu Noric3849202010-03-09 10:47:25 -08002177 return dbStatsList;
2178 }
2179
Mathew Inwood41b31942018-08-10 16:00:53 +01002180 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -07002181 private void collectDbStats(ArrayList<DbStats> dbStatsList) {
2182 synchronized (mLock) {
2183 if (mConnectionPoolLocked != null) {
2184 mConnectionPoolLocked.collectDbStats(dbStatsList);
2185 }
2186 }
2187 }
2188
Mathew Inwood41b31942018-08-10 16:00:53 +01002189 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -07002190 private static ArrayList<SQLiteDatabase> getActiveDatabases() {
2191 ArrayList<SQLiteDatabase> databases = new ArrayList<SQLiteDatabase>();
2192 synchronized (sActiveDatabases) {
2193 databases.addAll(sActiveDatabases.keySet());
2194 }
2195 return databases;
2196 }
2197
2198 /**
2199 * Dump detailed information about all open databases in the current process.
2200 * Used by bug report.
2201 */
Makoto Onukiee93ad22018-10-18 16:24:13 -07002202 static void dumpAll(Printer printer, boolean verbose, boolean isSystem) {
2203 // Use this ArraySet to collect file paths.
2204 final ArraySet<String> directories = new ArraySet<>();
2205
Jeff Browne5360fb2011-10-31 17:48:13 -07002206 for (SQLiteDatabase db : getActiveDatabases()) {
Makoto Onukiee93ad22018-10-18 16:24:13 -07002207 db.dump(printer, verbose, isSystem, directories);
2208 }
2209
2210 // Dump DB files in the directories.
2211 if (directories.size() > 0) {
2212 final String[] dirs = directories.toArray(new String[directories.size()]);
2213 Arrays.sort(dirs);
2214 for (String dir : dirs) {
2215 dumpDatabaseDirectory(printer, new File(dir), isSystem);
2216 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002217 }
2218 }
2219
Makoto Onukiee93ad22018-10-18 16:24:13 -07002220 private void dump(Printer printer, boolean verbose, boolean isSystem, ArraySet directories) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002221 synchronized (mLock) {
2222 if (mConnectionPoolLocked != null) {
2223 printer.println("");
Makoto Onukiee93ad22018-10-18 16:24:13 -07002224 mConnectionPoolLocked.dump(printer, verbose, directories);
Jeff Browne5360fb2011-10-31 17:48:13 -07002225 }
2226 }
2227 }
2228
Makoto Onukiee93ad22018-10-18 16:24:13 -07002229 private static void dumpDatabaseDirectory(Printer pw, File dir, boolean isSystem) {
2230 pw.println("");
2231 pw.println("Database files in " + dir.getAbsolutePath() + ":");
2232 final File[] files = dir.listFiles();
2233 if (files == null || files.length == 0) {
2234 pw.println(" [none]");
2235 return;
2236 }
2237 Arrays.sort(files, (a, b) -> a.getName().compareTo(b.getName()));
2238
2239 for (File f : files) {
2240 if (isSystem) {
2241 // If called within the system server, the directory contains other files too, so
2242 // filter by file extensions.
2243 // (If it's an app, just print all files because they may not use *.db
2244 // extension.)
2245 final String name = f.getName();
2246 if (!(name.endsWith(".db") || name.endsWith(".db-wal")
2247 || name.endsWith(".db-journal")
2248 || name.endsWith(SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX))) {
2249 continue;
2250 }
2251 }
2252 pw.println(String.format(" %-40s %7db %s", f.getName(), f.length(),
2253 SQLiteDatabase.getFileTimestamps(f.getAbsolutePath())));
2254 }
2255 }
2256
Vasu Noric3849202010-03-09 10:47:25 -08002257 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002258 * Returns list of full pathnames of all attached databases including the main database
2259 * by executing 'pragma database_list' on the database.
2260 *
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002261 * @return ArrayList of pairs of (database name, database file path) or null if the database
2262 * is not open.
Vasu Noric3849202010-03-09 10:47:25 -08002263 */
Vasu Noria017eda2011-01-27 10:52:55 -08002264 public List<Pair<String, String>> getAttachedDbs() {
Vasu Noric3849202010-03-09 10:47:25 -08002265 ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002266 synchronized (mLock) {
2267 if (mConnectionPoolLocked == null) {
2268 return null; // not open
2269 }
2270
2271 if (!mHasAttachedDbsLocked) {
2272 // No attached databases.
2273 // There is a small window where attached databases exist but this flag is not
2274 // set yet. This can occur when this thread is in a race condition with another
2275 // thread that is executing the SQL statement: "attach database <blah> as <foo>"
2276 // If this thread is NOT ok with such a race condition (and thus possibly not
2277 // receivethe entire list of attached databases), then the caller should ensure
2278 // that no thread is executing any SQL statements while a thread is calling this
2279 // method. Typically, this method is called when 'adb bugreport' is done or the
2280 // caller wants to collect stats on the database and all its attached databases.
2281 attachedDbs.add(new Pair<String, String>("main", mConfigurationLocked.path));
2282 return attachedDbs;
2283 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002284
2285 acquireReference();
Vasu Nori24675612010-09-27 14:54:19 -07002286 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002287
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002288 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002289 // has attached databases. query sqlite to get the list of attached databases.
2290 Cursor c = null;
2291 try {
2292 c = rawQuery("pragma database_list;", null);
2293 while (c.moveToNext()) {
2294 // sqlite returns a row for each database in the returned list of databases.
2295 // in each row,
2296 // 1st column is the database name such as main, or the database
2297 // name specified on the "ATTACH" command
2298 // 2nd column is the database file path.
2299 attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2)));
2300 }
2301 } finally {
2302 if (c != null) {
2303 c.close();
2304 }
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002305 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002306 return attachedDbs;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002307 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08002308 releaseReference();
Vasu Noric3849202010-03-09 10:47:25 -08002309 }
Vasu Noric3849202010-03-09 10:47:25 -08002310 }
2311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002313 * Runs 'pragma integrity_check' on the given database (and all the attached databases)
2314 * and returns true if the given database (and all its attached databases) pass integrity_check,
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002315 * false otherwise.
Vasu Noriccd95442010-05-28 17:04:16 -07002316 *<p>
2317 * If the result is false, then this method logs the errors reported by the integrity_check
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002318 * command execution.
Vasu Noriccd95442010-05-28 17:04:16 -07002319 *<p>
2320 * Note that 'pragma integrity_check' on a database can take a long time.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002321 *
2322 * @return true if the given database (and all its attached databases) pass integrity_check,
Vasu Noriccd95442010-05-28 17:04:16 -07002323 * false otherwise.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002324 */
2325 public boolean isDatabaseIntegrityOk() {
Jeff Brown03bd3022012-03-06 13:48:56 -08002326 acquireReference();
Vasu Noribfe1dc22010-08-25 16:29:02 -07002327 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002328 List<Pair<String, String>> attachedDbs = null;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002329 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002330 attachedDbs = getAttachedDbs();
2331 if (attachedDbs == null) {
2332 throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " +
2333 "be retrieved. probably because the database is closed");
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002334 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002335 } catch (SQLiteException e) {
2336 // can't get attachedDb list. do integrity check on the main database
2337 attachedDbs = new ArrayList<Pair<String, String>>();
2338 attachedDbs.add(new Pair<String, String>("main", getPath()));
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002339 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002340
2341 for (int i = 0; i < attachedDbs.size(); i++) {
2342 Pair<String, String> p = attachedDbs.get(i);
2343 SQLiteStatement prog = null;
2344 try {
2345 prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);");
2346 String rslt = prog.simpleQueryForString();
2347 if (!rslt.equalsIgnoreCase("ok")) {
2348 // integrity_checker failed on main or attached databases
2349 Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt);
2350 return false;
2351 }
2352 } finally {
2353 if (prog != null) prog.close();
2354 }
2355 }
2356 } finally {
2357 releaseReference();
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002358 }
Vasu Noribfe1dc22010-08-25 16:29:02 -07002359 return true;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002360 }
2361
Jeff Browne5360fb2011-10-31 17:48:13 -07002362 @Override
2363 public String toString() {
2364 return "SQLiteDatabase: " + getPath();
2365 }
2366
Jeff Browne5360fb2011-10-31 17:48:13 -07002367 private void throwIfNotOpenLocked() {
2368 if (mConnectionPoolLocked == null) {
2369 throw new IllegalStateException("The database '" + mConfigurationLocked.label
2370 + "' is not open.");
2371 }
2372 }
Vasu Nori3ef94e22010-02-05 14:49:04 -08002373
2374 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002375 * Used to allow returning sub-classes of {@link Cursor} when calling query.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002377 public interface CursorFactory {
2378 /**
2379 * See {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}.
2380 */
2381 public Cursor newCursor(SQLiteDatabase db,
2382 SQLiteCursorDriver masterQuery, String editTable,
2383 SQLiteQuery query);
2384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002385
2386 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002387 * A callback interface for a custom sqlite3 function.
2388 * This can be used to create a function that can be called from
2389 * sqlite3 database triggers.
2390 * @hide
Vasu Noric3849202010-03-09 10:47:25 -08002391 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002392 public interface CustomFunction {
2393 public void callback(String[] args);
2394 }
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002395
2396 /**
2397 * Wrapper for configuration parameters that are used for opening {@link SQLiteDatabase}
2398 */
2399 public static final class OpenParams {
2400 private final int mOpenFlags;
2401 private final CursorFactory mCursorFactory;
2402 private final DatabaseErrorHandler mErrorHandler;
2403 private final int mLookasideSlotSize;
2404 private final int mLookasideSlotCount;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002405 private final long mIdleConnectionTimeout;
2406 private final String mJournalMode;
2407 private final String mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002408
2409 private OpenParams(int openFlags, CursorFactory cursorFactory,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002410 DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002411 long idleConnectionTimeout, String journalMode, String syncMode) {
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002412 mOpenFlags = openFlags;
2413 mCursorFactory = cursorFactory;
2414 mErrorHandler = errorHandler;
2415 mLookasideSlotSize = lookasideSlotSize;
2416 mLookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002417 mIdleConnectionTimeout = idleConnectionTimeout;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002418 mJournalMode = journalMode;
2419 mSyncMode = syncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002420 }
2421
2422 /**
2423 * Returns size in bytes of each lookaside slot or -1 if not set.
2424 *
2425 * @see Builder#setLookasideConfig(int, int)
2426 */
2427 @IntRange(from = -1)
2428 public int getLookasideSlotSize() {
2429 return mLookasideSlotSize;
2430 }
2431
2432 /**
2433 * Returns total number of lookaside memory slots per database connection or -1 if not
2434 * set.
2435 *
2436 * @see Builder#setLookasideConfig(int, int)
2437 */
2438 @IntRange(from = -1)
2439 public int getLookasideSlotCount() {
2440 return mLookasideSlotCount;
2441 }
2442
2443 /**
Fyodor Kupolov76436c02017-08-03 17:56:44 -07002444 * Returns flags to control database access mode. Default value is 0.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002445 *
2446 * @see Builder#setOpenFlags(int)
2447 */
2448 @DatabaseOpenFlags
2449 public int getOpenFlags() {
2450 return mOpenFlags;
2451 }
2452
2453 /**
2454 * Returns an optional factory class that is called to instantiate a cursor when query
2455 * is called
2456 *
2457 * @see Builder#setCursorFactory(CursorFactory)
2458 */
2459 @Nullable
2460 public CursorFactory getCursorFactory() {
2461 return mCursorFactory;
2462 }
2463
2464 /**
2465 * Returns handler for database corruption errors
2466 *
2467 * @see Builder#setErrorHandler(DatabaseErrorHandler)
2468 */
2469 @Nullable
2470 public DatabaseErrorHandler getErrorHandler() {
2471 return mErrorHandler;
2472 }
2473
2474 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002475 * Returns maximum number of milliseconds that SQLite connection is allowed to be idle
2476 * before it is closed and removed from the pool.
2477 * <p>If the value isn't set, the timeout defaults to the system wide timeout
2478 *
2479 * @return timeout in milliseconds or -1 if the value wasn't set.
2480 */
2481 public long getIdleConnectionTimeout() {
2482 return mIdleConnectionTimeout;
2483 }
2484
2485 /**
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002486 * Returns <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>.
2487 * This journal mode will only be used if {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING}
2488 * flag is not set, otherwise a platform will use "WAL" journal mode.
2489 * @see Builder#setJournalMode(String)
2490 */
2491 @Nullable
2492 public String getJournalMode() {
2493 return mJournalMode;
2494 }
2495
2496 /**
2497 * Returns <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>.
Fyodor Kupolov8ba20892018-06-01 12:11:42 -07002498 * If not set, a system wide default will be used.
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002499 * @see Builder#setSynchronousMode(String)
2500 */
2501 @Nullable
2502 public String getSynchronousMode() {
2503 return mSyncMode;
2504 }
2505
2506 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002507 * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with
2508 * {@code this} parameters.
2509 * @hide
2510 */
2511 @NonNull
2512 public Builder toBuilder() {
2513 return new Builder(this);
2514 }
2515
2516 /**
2517 * Builder for {@link OpenParams}.
2518 */
2519 public static final class Builder {
2520 private int mLookasideSlotSize = -1;
2521 private int mLookasideSlotCount = -1;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002522 private long mIdleConnectionTimeout = -1;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002523 private int mOpenFlags;
2524 private CursorFactory mCursorFactory;
2525 private DatabaseErrorHandler mErrorHandler;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002526 private String mJournalMode;
2527 private String mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002528
2529 public Builder() {
2530 }
2531
2532 public Builder(OpenParams params) {
2533 mLookasideSlotSize = params.mLookasideSlotSize;
2534 mLookasideSlotCount = params.mLookasideSlotCount;
2535 mOpenFlags = params.mOpenFlags;
2536 mCursorFactory = params.mCursorFactory;
2537 mErrorHandler = params.mErrorHandler;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002538 mJournalMode = params.mJournalMode;
2539 mSyncMode = params.mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002540 }
2541
2542 /**
2543 * Configures
2544 * <a href="https://sqlite.org/malloc.html#lookaside">lookaside memory allocator</a>
2545 *
2546 * <p>SQLite default settings will be used, if this method isn't called.
2547 * Use {@code setLookasideConfig(0,0)} to disable lookaside
2548 *
Fyodor Kupolov05a0f0f2017-06-30 19:00:00 -07002549 * <p><strong>Note:</strong> Provided slotSize/slotCount configuration is just a
2550 * recommendation. The system may choose different values depending on a device, e.g.
2551 * lookaside allocations can be disabled on low-RAM devices
2552 *
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002553 * @param slotSize The size in bytes of each lookaside slot.
2554 * @param slotCount The total number of lookaside memory slots per database connection.
2555 */
2556 public Builder setLookasideConfig(@IntRange(from = 0) final int slotSize,
2557 @IntRange(from = 0) final int slotCount) {
2558 Preconditions.checkArgument(slotSize >= 0,
2559 "lookasideSlotCount cannot be negative");
2560 Preconditions.checkArgument(slotCount >= 0,
2561 "lookasideSlotSize cannot be negative");
2562 Preconditions.checkArgument(
2563 (slotSize > 0 && slotCount > 0) || (slotCount == 0 && slotSize == 0),
2564 "Invalid configuration: " + slotSize + ", " + slotCount);
2565
2566 mLookasideSlotSize = slotSize;
2567 mLookasideSlotCount = slotCount;
2568 return this;
2569 }
2570
2571 /**
2572 * Returns true if {@link #ENABLE_WRITE_AHEAD_LOGGING} flag is set
2573 * @hide
2574 */
2575 public boolean isWriteAheadLoggingEnabled() {
2576 return (mOpenFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2577 }
2578
2579 /**
2580 * Sets flags to control database access mode
2581 * @param openFlags The new flags to set
2582 * @see #OPEN_READWRITE
2583 * @see #OPEN_READONLY
2584 * @see #CREATE_IF_NECESSARY
2585 * @see #NO_LOCALIZED_COLLATORS
2586 * @see #ENABLE_WRITE_AHEAD_LOGGING
2587 * @return same builder instance for chaining multiple calls into a single statement
2588 */
2589 @NonNull
2590 public Builder setOpenFlags(@DatabaseOpenFlags int openFlags) {
2591 mOpenFlags = openFlags;
2592 return this;
2593 }
2594
2595 /**
2596 * Adds flags to control database access mode
2597 *
2598 * @param openFlags The new flags to add
2599 * @return same builder instance for chaining multiple calls into a single statement
2600 */
2601 @NonNull
2602 public Builder addOpenFlags(@DatabaseOpenFlags int openFlags) {
2603 mOpenFlags |= openFlags;
2604 return this;
2605 }
2606
2607 /**
2608 * Removes database access mode flags
2609 *
2610 * @param openFlags Flags to remove
2611 * @return same builder instance for chaining multiple calls into a single statement
2612 */
2613 @NonNull
2614 public Builder removeOpenFlags(@DatabaseOpenFlags int openFlags) {
2615 mOpenFlags &= ~openFlags;
2616 return this;
2617 }
2618
2619 /**
2620 * Sets {@link #ENABLE_WRITE_AHEAD_LOGGING} flag if {@code enabled} is {@code true},
2621 * unsets otherwise
2622 * @hide
2623 */
2624 public void setWriteAheadLoggingEnabled(boolean enabled) {
2625 if (enabled) {
2626 addOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2627 } else {
2628 removeOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2629 }
2630 }
2631
2632 /**
2633 * Set an optional factory class that is called to instantiate a cursor when query
2634 * is called.
2635 *
2636 * @param cursorFactory instance
2637 * @return same builder instance for chaining multiple calls into a single statement
2638 */
2639 @NonNull
2640 public Builder setCursorFactory(@Nullable CursorFactory cursorFactory) {
2641 mCursorFactory = cursorFactory;
2642 return this;
2643 }
2644
2645
2646 /**
2647 * Sets {@link DatabaseErrorHandler} object to handle db corruption errors
2648 */
2649 @NonNull
2650 public Builder setErrorHandler(@Nullable DatabaseErrorHandler errorHandler) {
2651 mErrorHandler = errorHandler;
2652 return this;
2653 }
2654
2655 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002656 * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle
2657 * before it is closed and removed from the pool.
2658 *
Makoto Onuki1a904792019-02-28 12:04:52 -08002659 * <p><b>DO NOT USE</b> this method.
2660 * This feature has negative side effects that are very hard to foresee.
2661 * <p>A connection timeout allows the system to internally close a connection to
2662 * a SQLite database after a given timeout, which is good for reducing app's memory
2663 * consumption.
2664 * <b>However</b> the side effect is it <b>will reset all of SQLite's per-connection
2665 * states</b>, which are typically modified with a {@code PRAGMA} statement, and
2666 * these states <b>will not be restored</b> when a connection is re-established
2667 * internally, and the system does not provide a callback for an app to reconfigure a
2668 * connection.
2669 * This feature may only be used if an app relies on none of such per-connection states.
Makoto Onukib15186c2019-01-28 14:43:41 -08002670 *
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002671 * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE}
2672 * to allow unlimited idle connections.
Makoto Onukib15186c2019-01-28 14:43:41 -08002673 *
2674 * @see SQLiteOpenHelper#setIdleConnectionTimeout(long)
2675 *
Makoto Onuki1a904792019-02-28 12:04:52 -08002676 * @deprecated DO NOT USE this method. See the javadoc for the details.
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002677 */
2678 @NonNull
Makoto Onukib15186c2019-01-28 14:43:41 -08002679 @Deprecated
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002680 public Builder setIdleConnectionTimeout(
2681 @IntRange(from = 0) long idleConnectionTimeoutMs) {
2682 Preconditions.checkArgument(idleConnectionTimeoutMs >= 0,
2683 "idle connection timeout cannot be negative");
2684 mIdleConnectionTimeout = idleConnectionTimeoutMs;
2685 return this;
2686 }
2687
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002688
2689 /**
2690 * Sets <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>
2691 * to use when {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag is not set.
2692 */
2693 @NonNull
2694 public Builder setJournalMode(@NonNull String journalMode) {
Daulet Zhanguzinb7ac8d32019-12-30 16:54:39 +00002695 Objects.requireNonNull(journalMode);
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002696 mJournalMode = journalMode;
2697 return this;
2698 }
2699
Makoto Onukiee93ad22018-10-18 16:24:13 -07002700 /**w
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002701 * Sets <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>
Fyodor Kupolov8ba20892018-06-01 12:11:42 -07002702 * .
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002703 * @return
2704 */
2705 @NonNull
2706 public Builder setSynchronousMode(@NonNull String syncMode) {
Daulet Zhanguzinb7ac8d32019-12-30 16:54:39 +00002707 Objects.requireNonNull(syncMode);
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002708 mSyncMode = syncMode;
2709 return this;
2710 }
2711
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002712 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002713 * Creates an instance of {@link OpenParams} with the options that were previously set
2714 * on this builder
2715 */
2716 @NonNull
2717 public OpenParams build() {
2718 return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002719 mLookasideSlotCount, mIdleConnectionTimeout, mJournalMode, mSyncMode);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002720 }
2721 }
2722 }
2723
2724 /** @hide */
2725 @IntDef(flag = true, prefix = {"OPEN_", "CREATE_", "NO_", "ENABLE_"}, value = {
2726 OPEN_READWRITE,
2727 OPEN_READONLY,
2728 CREATE_IF_NECESSARY,
2729 NO_LOCALIZED_COLLATORS,
2730 ENABLE_WRITE_AHEAD_LOGGING
2731 })
2732 @Retention(RetentionPolicy.SOURCE)
2733 public @interface DatabaseOpenFlags {}
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002734
Makoto Onukiee93ad22018-10-18 16:24:13 -07002735 /** @hide */
2736 public static void wipeDetected(String filename, String reason) {
2737 wtfAsSystemServer(TAG, "DB wipe detected:"
2738 + " package=" + ActivityThread.currentPackageName()
2739 + " reason=" + reason
2740 + " file=" + filename
2741 + " " + getFileTimestamps(filename)
2742 + " checkfile " + getFileTimestamps(filename + SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX),
2743 new Throwable("STACKTRACE"));
2744 }
2745
2746 /** @hide */
2747 public static String getFileTimestamps(String path) {
2748 try {
2749 BasicFileAttributes attr = Files.readAttributes(
2750 FileSystems.getDefault().getPath(path), BasicFileAttributes.class);
2751 return "ctime=" + attr.creationTime()
2752 + " mtime=" + attr.lastModifiedTime()
2753 + " atime=" + attr.lastAccessTime();
2754 } catch (IOException e) {
2755 return "[unable to obtain timestamp]";
2756 }
2757 }
2758
2759 /** @hide */
2760 static void wtfAsSystemServer(String tag, String message, Throwable stacktrace) {
2761 Log.e(tag, message, stacktrace);
2762 ContentResolver.onDbCorruption(tag, message, stacktrace);
2763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002764}
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002765