blob: 01557c59f8ac030babd5d466e1e9e131fc084b02 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.database.sqlite;
18
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070019import android.annotation.IntDef;
20import android.annotation.IntRange;
Makoto Onuki17aa1b72015-12-16 14:02:01 -080021import android.annotation.NonNull;
22import android.annotation.Nullable;
Mathew Inwoodf86bea92018-08-10 16:10:20 +010023import android.annotation.UnsupportedAppUsage;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070024import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.content.ContentValues;
26import android.database.Cursor;
Vasu Nori062fc7ce2010-03-31 16:13:05 -070027import android.database.DatabaseErrorHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.database.DatabaseUtils;
Vasu Nori062fc7ce2010-03-31 16:13:05 -070029import android.database.DefaultDatabaseErrorHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.database.SQLException;
Vasu Noric3849202010-03-09 10:47:25 -080031import android.database.sqlite.SQLiteDebug.DbStats;
Jeff Browna7771df2012-05-07 20:06:46 -070032import android.os.CancellationSignal;
Jeff Browne5360fb2011-10-31 17:48:13 -070033import android.os.Looper;
Jeff Browna7771df2012-05-07 20:06:46 -070034import android.os.OperationCanceledException;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070035import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.util.EventLog;
Dmitri Plotnikov90142c92009-09-15 10:52:17 -070038import android.util.Log;
Vasu Noric3849202010-03-09 10:47:25 -080039import android.util.Pair;
Jeff Browne5360fb2011-10-31 17:48:13 -070040import android.util.Printer;
41
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070042import com.android.internal.util.Preconditions;
43
Jeff Browne5360fb2011-10-31 17:48:13 -070044import dalvik.system.CloseGuard;
45
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import java.io.File;
Jeff Brown79087e42012-03-01 19:52:44 -080047import java.io.FileFilter;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070048import java.lang.annotation.Retention;
49import java.lang.annotation.RetentionPolicy;
Vasu Noric3849202010-03-09 10:47:25 -080050import java.util.ArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import java.util.HashMap;
Jesse Wilson9b5a9352011-02-10 11:19:09 -080052import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053import java.util.Locale;
54import java.util.Map;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import java.util.WeakHashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056
57/**
58 * Exposes methods to manage a SQLite database.
Jeff Browne5360fb2011-10-31 17:48:13 -070059 *
60 * <p>
61 * SQLiteDatabase has methods to create, delete, execute SQL commands, and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062 * perform other common database management tasks.
Jeff Browne5360fb2011-10-31 17:48:13 -070063 * </p><p>
64 * See the Notepad sample application in the SDK for an example of creating
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 * and managing a database.
Jeff Browne5360fb2011-10-31 17:48:13 -070066 * </p><p>
67 * Database names must be unique within an application, not across all applications.
68 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069 *
70 * <h3>Localized Collation - ORDER BY</h3>
Jeff Browne5360fb2011-10-31 17:48:13 -070071 * <p>
72 * In addition to SQLite's default <code>BINARY</code> collator, Android supplies
73 * two more, <code>LOCALIZED</code>, which changes with the system's current locale,
74 * and <code>UNICODE</code>, which is the Unicode Collation Algorithm and not tailored
75 * to the current locale.
76 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077 */
Jeff Brownbaefdfa2012-03-05 10:33:13 -080078public final class SQLiteDatabase extends SQLiteClosable {
Vasu Norifb16cbd2010-07-25 16:38:48 -070079 private static final String TAG = "SQLiteDatabase";
Jeff Browne5360fb2011-10-31 17:48:13 -070080
Jeff Hamilton082c2af2009-09-29 11:49:51 -070081 private static final int EVENT_DB_CORRUPT = 75004;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082
Fyodor Kupolov535672992017-08-30 18:16:31 -070083 // By default idle connections are not closed
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070084 private static final boolean DEBUG_CLOSE_IDLE_CONNECTIONS = SystemProperties
Fyodor Kupolov535672992017-08-30 18:16:31 -070085 .getBoolean("persist.debug.sqlite.close_idle_connections", false);
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070086
Jeff Browne5360fb2011-10-31 17:48:13 -070087 // Stores reference to all databases opened in the current process.
88 // (The referent Object is not used at this time.)
89 // INVARIANT: Guarded by sActiveDatabases.
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070090 private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases = new WeakHashMap<>();
Jeff Browne5360fb2011-10-31 17:48:13 -070091
92 // Thread-local for database sessions that belong to this database.
93 // Each thread has its own database session.
94 // INVARIANT: Immutable.
Mathew Inwoodf86bea92018-08-10 16:10:20 +010095 @UnsupportedAppUsage
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070096 private final ThreadLocal<SQLiteSession> mThreadSession = ThreadLocal
97 .withInitial(this::createSession);
Jeff Browne5360fb2011-10-31 17:48:13 -070098
99 // The optional factory to use when creating new Cursors. May be null.
100 // INVARIANT: Immutable.
101 private final CursorFactory mCursorFactory;
102
103 // Error handler to be used when SQLite returns corruption errors.
104 // INVARIANT: Immutable.
105 private final DatabaseErrorHandler mErrorHandler;
106
107 // Shared database state lock.
108 // This lock guards all of the shared state of the database, such as its
109 // configuration, whether it is open or closed, and so on. This lock should
110 // be held for as little time as possible.
111 //
112 // The lock MUST NOT be held while attempting to acquire database connections or
113 // while executing SQL statements on behalf of the client as it can lead to deadlock.
114 //
115 // It is ok to hold the lock while reconfiguring the connection pool or dumping
116 // statistics because those operations are non-reentrant and do not try to acquire
117 // connections that might be held by other threads.
118 //
119 // Basic rule: grab the lock, access or modify global state, release the lock, then
120 // do the required SQL work.
121 private final Object mLock = new Object();
122
123 // Warns if the database is finalized without being closed properly.
124 // INVARIANT: Guarded by mLock.
125 private final CloseGuard mCloseGuardLocked = CloseGuard.get();
126
127 // The database configuration.
128 // INVARIANT: Guarded by mLock.
Mathew Inwoodf86bea92018-08-10 16:10:20 +0100129 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -0700130 private final SQLiteDatabaseConfiguration mConfigurationLocked;
131
132 // The connection pool for the database, null when closed.
133 // The pool itself is thread-safe, but the reference to it can only be acquired
134 // when the lock is held.
135 // INVARIANT: Guarded by mLock.
Mathew Inwoodf86bea92018-08-10 16:10:20 +0100136 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -0700137 private SQLiteConnectionPool mConnectionPoolLocked;
138
139 // True if the database has attached databases.
140 // INVARIANT: Guarded by mLock.
141 private boolean mHasAttachedDbsLocked;
142
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700144 * When a constraint violation occurs, an immediate ROLLBACK occurs,
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800145 * thus ending the current transaction, and the command aborts with a
146 * return code of SQLITE_CONSTRAINT. If no transaction is active
147 * (other than the implied transaction that is created on every command)
Jeff Browne5360fb2011-10-31 17:48:13 -0700148 * then this algorithm works the same as ABORT.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800149 */
150 public static final int CONFLICT_ROLLBACK = 1;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700151
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800152 /**
153 * When a constraint violation occurs,no ROLLBACK is executed
154 * so changes from prior commands within the same transaction
155 * are preserved. This is the default behavior.
156 */
157 public static final int CONFLICT_ABORT = 2;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700158
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800159 /**
160 * When a constraint violation occurs, the command aborts with a return
161 * code SQLITE_CONSTRAINT. But any changes to the database that
162 * the command made prior to encountering the constraint violation
163 * are preserved and are not backed out.
164 */
165 public static final int CONFLICT_FAIL = 3;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700166
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800167 /**
168 * When a constraint violation occurs, the one row that contains
169 * the constraint violation is not inserted or changed.
170 * But the command continues executing normally. Other rows before and
171 * after the row that contained the constraint violation continue to be
172 * inserted or updated normally. No error is returned.
173 */
174 public static final int CONFLICT_IGNORE = 4;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700175
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800176 /**
177 * When a UNIQUE constraint violation occurs, the pre-existing rows that
178 * are causing the constraint violation are removed prior to inserting
179 * or updating the current row. Thus the insert or update always occurs.
180 * The command continues executing normally. No error is returned.
181 * If a NOT NULL constraint violation occurs, the NULL value is replaced
182 * by the default value for that column. If the column has no default
183 * value, then the ABORT algorithm is used. If a CHECK constraint
184 * violation occurs then the IGNORE algorithm is used. When this conflict
185 * resolution strategy deletes rows in order to satisfy a constraint,
186 * it does not invoke delete triggers on those rows.
Jeff Browne5360fb2011-10-31 17:48:13 -0700187 * This behavior might change in a future release.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800188 */
189 public static final int CONFLICT_REPLACE = 5;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700190
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800191 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700192 * Use the following when no conflict action is specified.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800193 */
194 public static final int CONFLICT_NONE = 0;
Jeff Browne5360fb2011-10-31 17:48:13 -0700195
Jeff Sharkey3e26b7d2018-07-12 19:47:49 -0600196 /** {@hide} */
Mathew Inwoodf86bea92018-08-10 16:10:20 +0100197 @UnsupportedAppUsage
Jeff Sharkey3e26b7d2018-07-12 19:47:49 -0600198 public static final String[] CONFLICT_VALUES = new String[]
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800199 {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 /**
202 * Maximum Length Of A LIKE Or GLOB Pattern
203 * The pattern matching algorithm used in the default LIKE and GLOB implementation
204 * of SQLite can exhibit O(N^2) performance (where N is the number of characters in
205 * the pattern) for certain pathological cases. To avoid denial-of-service attacks
206 * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes.
207 * The default value of this limit is 50000. A modern workstation can evaluate
208 * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly.
209 * The denial of service problem only comes into play when the pattern length gets
210 * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns
211 * are at most a few dozen bytes in length, paranoid application developers may
212 * want to reduce this parameter to something in the range of a few hundred
213 * if they know that external users are able to generate arbitrary patterns.
214 */
215 public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000;
216
217 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700218 * Open flag: Flag for {@link #openDatabase} to open the database for reading and writing.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 * If the disk is full, this may fail even before you actually write anything.
220 *
221 * {@more} Note that the value of this flag is 0, so it is the default.
222 */
223 public static final int OPEN_READWRITE = 0x00000000; // update native code if changing
224
225 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700226 * Open flag: Flag for {@link #openDatabase} to open the database for reading only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 * This is the only reliable way to open a database if the disk may be full.
228 */
229 public static final int OPEN_READONLY = 0x00000001; // update native code if changing
230
231 private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing
232
233 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700234 * Open flag: Flag for {@link #openDatabase} to open the database without support for
235 * localized collators.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 *
237 * {@more} This causes the collator <code>LOCALIZED</code> not to be created.
238 * You must be consistent when using this flag to use the setting the database was
239 * created with. If this is set, {@link #setLocale} will do nothing.
240 */
241 public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing
242
243 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700244 * Open flag: Flag for {@link #openDatabase} to create the database file if it does not
245 * already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 */
247 public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing
248
249 /**
Jeff Brown47847f32012-03-22 19:13:11 -0700250 * Open flag: Flag for {@link #openDatabase} to open the database file with
251 * write-ahead logging enabled by default. Using this flag is more efficient
252 * than calling {@link #enableWriteAheadLogging}.
253 *
254 * Write-ahead logging cannot be used with read-only databases so the value of
255 * this flag is ignored if the database is opened read-only.
256 *
257 * @see #enableWriteAheadLogging
258 */
259 public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;
260
261 /**
Fyodor Kupolov692573b2018-03-06 12:34:36 -0800262 * Open flag: Flag for {@link #openDatabase} to disable Compatibility WAL when opening database.
263 *
264 * @hide
265 */
266 public static final int DISABLE_COMPATIBILITY_WAL = 0x40000000;
267
268 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700269 * Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}.
Vasu Norib729dcc2010-09-14 11:35:49 -0700270 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700271 * Each prepared-statement is between 1K - 6K, depending on the complexity of the
272 * SQL statement & schema. A large SQL cache may use a significant amount of memory.
Vasu Norie495d1f2010-01-06 16:34:19 -0800273 */
Vasu Nori90a367262010-04-12 12:49:09 -0700274 public static final int MAX_SQL_CACHE_SIZE = 100;
Vasu Norib729dcc2010-09-14 11:35:49 -0700275
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700276 private SQLiteDatabase(final String path, final int openFlags,
277 CursorFactory cursorFactory, DatabaseErrorHandler errorHandler,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800278 int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs,
279 String journalMode, String syncMode) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700280 mCursorFactory = cursorFactory;
281 mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler();
282 mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700283 mConfigurationLocked.lookasideSlotSize = lookasideSlotSize;
284 mConfigurationLocked.lookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700285 // Disable lookaside allocator on low-RAM devices
286 if (ActivityManager.isLowRamDeviceStatic()) {
287 mConfigurationLocked.lookasideSlotCount = 0;
288 mConfigurationLocked.lookasideSlotSize = 0;
289 }
290 long effectiveTimeoutMs = Long.MAX_VALUE;
291 // Never close idle connections for in-memory databases
292 if (!mConfigurationLocked.isInMemoryDb()) {
293 // First, check app-specific value. Otherwise use defaults
294 // -1 in idleConnectionTimeoutMs indicates unset value
295 if (idleConnectionTimeoutMs >= 0) {
296 effectiveTimeoutMs = idleConnectionTimeoutMs;
297 } else if (DEBUG_CLOSE_IDLE_CONNECTIONS) {
298 effectiveTimeoutMs = SQLiteGlobal.getIdleConnectionTimeout();
299 }
300 }
301 mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800302 mConfigurationLocked.journalMode = journalMode;
303 mConfigurationLocked.syncMode = syncMode;
Fyodor Kupolov692573b2018-03-06 12:34:36 -0800304 if (!SQLiteGlobal.isCompatibilityWalSupported() || (
305 SQLiteCompatibilityWalFlags.areFlagsSet() && !SQLiteCompatibilityWalFlags
306 .isCompatibilityWalSupported())) {
307 mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
Fyodor Kupolovee90c032017-12-12 11:52:57 -0800308 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800309 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700310
Jeff Browne5360fb2011-10-31 17:48:13 -0700311 @Override
312 protected void finalize() throws Throwable {
313 try {
314 dispose(true);
315 } finally {
316 super.finalize();
317 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700318 }
319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 @Override
321 protected void onAllReferencesReleased() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700322 dispose(false);
323 }
324
325 private void dispose(boolean finalized) {
326 final SQLiteConnectionPool pool;
327 synchronized (mLock) {
328 if (mCloseGuardLocked != null) {
329 if (finalized) {
330 mCloseGuardLocked.warnIfOpen();
331 }
332 mCloseGuardLocked.close();
333 }
334
335 pool = mConnectionPoolLocked;
336 mConnectionPoolLocked = null;
337 }
338
339 if (!finalized) {
340 synchronized (sActiveDatabases) {
341 sActiveDatabases.remove(this);
342 }
343
344 if (pool != null) {
345 pool.close();
346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 }
348 }
349
350 /**
351 * Attempts to release memory that SQLite holds but does not require to
352 * operate properly. Typically this memory will come from the page cache.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700353 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 * @return the number of bytes actually released
355 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700356 public static int releaseMemory() {
357 return SQLiteGlobal.releaseMemory();
358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359
360 /**
361 * Control whether or not the SQLiteDatabase is made thread-safe by using locks
362 * around critical sections. This is pretty expensive, so if you know that your
363 * DB will only be used by a single thread then you should set this to false.
364 * The default is true.
365 * @param lockingEnabled set to true to enable locks, false otherwise
Jeff Browne5360fb2011-10-31 17:48:13 -0700366 *
367 * @deprecated This method now does nothing. Do not use.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700369 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 public void setLockingEnabled(boolean lockingEnabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 }
372
373 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700374 * Gets a label to use when describing the database in log messages.
375 * @return The label.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700377 String getLabel() {
378 synchronized (mLock) {
379 return mConfigurationLocked.label;
380 }
381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382
Jeff Browne5360fb2011-10-31 17:48:13 -0700383 /**
384 * Sends a corruption message to the database error handler.
385 */
386 void onCorruption() {
387 EventLog.writeEvent(EVENT_DB_CORRUPT, getLabel());
Vasu Noriccd95442010-05-28 17:04:16 -0700388 mErrorHandler.onCorruption(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 }
390
391 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700392 * Gets the {@link SQLiteSession} that belongs to this thread for this database.
393 * Once a thread has obtained a session, it will continue to obtain the same
394 * session even after the database has been closed (although the session will not
395 * be usable). However, a thread that does not already have a session cannot
396 * obtain one after the database has been closed.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700397 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700398 * The idea is that threads that have active connections to the database may still
399 * have work to complete even after the call to {@link #close}. Active database
400 * connections are not actually disposed until they are released by the threads
401 * that own them.
402 *
403 * @return The session, never null.
404 *
405 * @throws IllegalStateException if the thread does not yet have a session and
406 * the database is not open.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 */
Mathew Inwoodf86bea92018-08-10 16:10:20 +0100408 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -0700409 SQLiteSession getThreadSession() {
410 return mThreadSession.get(); // initialValue() throws if database closed
Vasu Nori6d970252010-10-05 10:48:49 -0700411 }
Vasu Nori16057fa2011-03-18 11:40:37 -0700412
Jeff Browne5360fb2011-10-31 17:48:13 -0700413 SQLiteSession createSession() {
414 final SQLiteConnectionPool pool;
415 synchronized (mLock) {
416 throwIfNotOpenLocked();
417 pool = mConnectionPoolLocked;
Vasu Nori6d970252010-10-05 10:48:49 -0700418 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700419 return new SQLiteSession(pool);
Vasu Norid4608a32011-02-03 16:24:06 -0800420 }
421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700423 * Gets default connection flags that are appropriate for this thread, taking into
424 * account whether the thread is acting on behalf of the UI.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700426 * @param readOnly True if the connection should be read-only.
427 * @return The connection flags.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700429 int getThreadDefaultConnectionFlags(boolean readOnly) {
430 int flags = readOnly ? SQLiteConnectionPool.CONNECTION_FLAG_READ_ONLY :
431 SQLiteConnectionPool.CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY;
432 if (isMainThread()) {
433 flags |= SQLiteConnectionPool.CONNECTION_FLAG_INTERACTIVE;
434 }
435 return flags;
Vasu Nori16057fa2011-03-18 11:40:37 -0700436 }
437
Jeff Browne5360fb2011-10-31 17:48:13 -0700438 private static boolean isMainThread() {
439 // FIXME: There should be a better way to do this.
440 // Would also be nice to have something that would work across Binder calls.
441 Looper looper = Looper.myLooper();
442 return looper != null && looper == Looper.getMainLooper();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 }
444
445 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700446 * Begins a transaction in EXCLUSIVE mode.
447 * <p>
448 * Transactions can be nested.
449 * When the outer transaction is ended all of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450 * the work done in that transaction and all of the nested transactions will be committed or
451 * rolled back. The changes will be rolled back if any transaction is ended without being
452 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700453 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 * <p>Here is the standard idiom for transactions:
455 *
456 * <pre>
457 * db.beginTransaction();
458 * try {
459 * ...
460 * db.setTransactionSuccessful();
461 * } finally {
462 * db.endTransaction();
463 * }
464 * </pre>
465 */
466 public void beginTransaction() {
Vasu Nori6c354da2010-04-26 23:33:39 -0700467 beginTransaction(null /* transactionStatusCallback */, true);
468 }
469
470 /**
471 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
472 * the outer transaction is ended all of the work done in that transaction
473 * and all of the nested transactions will be committed or rolled back. The
474 * changes will be rolled back if any transaction is ended without being
475 * marked as clean (by calling setTransactionSuccessful). Otherwise they
476 * will be committed.
477 * <p>
478 * Here is the standard idiom for transactions:
479 *
480 * <pre>
481 * db.beginTransactionNonExclusive();
482 * try {
483 * ...
484 * db.setTransactionSuccessful();
485 * } finally {
486 * db.endTransaction();
487 * }
488 * </pre>
489 */
490 public void beginTransactionNonExclusive() {
491 beginTransaction(null /* transactionStatusCallback */, false);
Fred Quintanac4516a72009-09-03 12:14:06 -0700492 }
493
494 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700495 * Begins a transaction in EXCLUSIVE mode.
496 * <p>
497 * Transactions can be nested.
498 * When the outer transaction is ended all of
Fred Quintanac4516a72009-09-03 12:14:06 -0700499 * the work done in that transaction and all of the nested transactions will be committed or
500 * rolled back. The changes will be rolled back if any transaction is ended without being
501 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700502 * </p>
Fred Quintanac4516a72009-09-03 12:14:06 -0700503 * <p>Here is the standard idiom for transactions:
504 *
505 * <pre>
506 * db.beginTransactionWithListener(listener);
507 * try {
508 * ...
509 * db.setTransactionSuccessful();
510 * } finally {
511 * db.endTransaction();
512 * }
513 * </pre>
Vasu Noriccd95442010-05-28 17:04:16 -0700514 *
Fred Quintanac4516a72009-09-03 12:14:06 -0700515 * @param transactionListener listener that should be notified when the transaction begins,
516 * commits, or is rolled back, either explicitly or by a call to
517 * {@link #yieldIfContendedSafely}.
518 */
519 public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
Vasu Nori6c354da2010-04-26 23:33:39 -0700520 beginTransaction(transactionListener, true);
521 }
522
523 /**
524 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
525 * the outer transaction is ended all of the work done in that transaction
526 * and all of the nested transactions will be committed or rolled back. The
527 * changes will be rolled back if any transaction is ended without being
528 * marked as clean (by calling setTransactionSuccessful). Otherwise they
529 * will be committed.
530 * <p>
531 * Here is the standard idiom for transactions:
532 *
533 * <pre>
534 * db.beginTransactionWithListenerNonExclusive(listener);
535 * try {
536 * ...
537 * db.setTransactionSuccessful();
538 * } finally {
539 * db.endTransaction();
540 * }
541 * </pre>
542 *
543 * @param transactionListener listener that should be notified when the
544 * transaction begins, commits, or is rolled back, either
545 * explicitly or by a call to {@link #yieldIfContendedSafely}.
546 */
547 public void beginTransactionWithListenerNonExclusive(
548 SQLiteTransactionListener transactionListener) {
549 beginTransaction(transactionListener, false);
550 }
551
Mathew Inwoodf86bea92018-08-10 16:10:20 +0100552 @UnsupportedAppUsage
Vasu Nori6c354da2010-04-26 23:33:39 -0700553 private void beginTransaction(SQLiteTransactionListener transactionListener,
554 boolean exclusive) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800555 acquireReference();
556 try {
557 getThreadSession().beginTransaction(
558 exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
559 SQLiteSession.TRANSACTION_MODE_IMMEDIATE,
560 transactionListener,
561 getThreadDefaultConnectionFlags(false /*readOnly*/), null);
562 } finally {
563 releaseReference();
564 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565 }
566
567 /**
568 * End a transaction. See beginTransaction for notes about how to use this and when transactions
569 * are committed and rolled back.
570 */
571 public void endTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800572 acquireReference();
573 try {
574 getThreadSession().endTransaction(null);
575 } finally {
576 releaseReference();
577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800578 }
579
580 /**
581 * Marks the current transaction as successful. Do not do any more database work between
582 * calling this and calling endTransaction. Do as little non-database work as possible in that
583 * situation too. If any errors are encountered between this and endTransaction the transaction
584 * will still be committed.
585 *
586 * @throws IllegalStateException if the current thread is not in a transaction or the
587 * transaction is already marked as successful.
588 */
589 public void setTransactionSuccessful() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800590 acquireReference();
591 try {
592 getThreadSession().setTransactionSuccessful();
593 } finally {
594 releaseReference();
595 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 }
597
598 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700599 * Returns true if the current thread has a transaction pending.
600 *
601 * @return True if the current thread is in a transaction.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 */
603 public boolean inTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800604 acquireReference();
605 try {
606 return getThreadSession().hasTransaction();
607 } finally {
608 releaseReference();
609 }
Vasu Norice38b982010-07-22 13:57:13 -0700610 }
611
612 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700613 * Returns true if the current thread is holding an active connection to the database.
Vasu Norice38b982010-07-22 13:57:13 -0700614 * <p>
Jeff Browne5360fb2011-10-31 17:48:13 -0700615 * The name of this method comes from a time when having an active connection
616 * to the database meant that the thread was holding an actual lock on the
617 * database. Nowadays, there is no longer a true "database lock" although threads
618 * may block if they cannot acquire a database connection to perform a
619 * particular operation.
620 * </p>
Vasu Norice38b982010-07-22 13:57:13 -0700621 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700622 * @return True if the current thread is holding an active connection to the database.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 */
624 public boolean isDbLockedByCurrentThread() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800625 acquireReference();
626 try {
627 return getThreadSession().hasConnection();
628 } finally {
629 releaseReference();
630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631 }
632
633 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700634 * Always returns false.
635 * <p>
636 * There is no longer the concept of a database lock, so this method always returns false.
637 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700639 * @return False.
640 * @deprecated Always returns false. Do not use this method.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800641 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700642 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 public boolean isDbLockedByOtherThreads() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700644 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 }
646
647 /**
648 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
649 * successful so far. Do not call setTransactionSuccessful before calling this. When this
650 * returns a new transaction will have been created but not marked as successful.
651 * @return true if the transaction was yielded
652 * @deprecated if the db is locked more than once (becuase of nested transactions) then the lock
653 * will not be yielded. Use yieldIfContendedSafely instead.
654 */
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700655 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800656 public boolean yieldIfContended() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700657 return yieldIfContendedHelper(false /* do not check yielding */,
658 -1 /* sleepAfterYieldDelay */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 }
660
661 /**
662 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
663 * successful so far. Do not call setTransactionSuccessful before calling this. When this
664 * returns a new transaction will have been created but not marked as successful. This assumes
665 * that there are no nested transactions (beginTransaction has only been called once) and will
Fred Quintana5c7aede2009-08-27 21:41:27 -0700666 * throw an exception if that is not the case.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 * @return true if the transaction was yielded
668 */
669 public boolean yieldIfContendedSafely() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700670 return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671 }
672
Fred Quintana5c7aede2009-08-27 21:41:27 -0700673 /**
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
678 * throw an exception if that is not the case.
679 * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if
680 * the lock was actually yielded. This will allow other background threads to make some
681 * more progress than they would if we started the transaction immediately.
682 * @return true if the transaction was yielded
683 */
684 public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
685 return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay);
686 }
687
Jeff Browne5360fb2011-10-31 17:48:13 -0700688 private boolean yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800689 acquireReference();
690 try {
691 return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null);
692 } finally {
693 releaseReference();
694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695 }
696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700698 * Deprecated.
Vasu Nori95675132010-07-21 16:24:40 -0700699 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 */
Vasu Nori95675132010-07-21 16:24:40 -0700701 @Deprecated
702 public Map<String, String> getSyncedTables() {
703 return new HashMap<String, String>(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 }
705
706 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 * Open the database according to the flags {@link #OPEN_READWRITE}
708 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
709 *
710 * <p>Sets the locale of the database to the the system's current locale.
711 * Call {@link #setLocale} if you would like something else.</p>
712 *
713 * @param path to database file to open and/or create
714 * @param factory an optional factory class that is called to instantiate a
715 * cursor when query is called, or null for default
716 * @param flags to control database access mode
717 * @return the newly opened database
718 * @throws SQLiteException if the database cannot be opened
719 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700720 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
721 @DatabaseOpenFlags int flags) {
Jeff Brown47847f32012-03-22 19:13:11 -0700722 return openDatabase(path, factory, flags, null);
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700723 }
724
725 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700726 * Open the database according to the specified {@link OpenParams parameters}
727 *
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700728 * @param path path to database file to open and/or create.
729 * <p><strong>Important:</strong> The file should be constructed either from an absolute path or
730 * by using {@link android.content.Context#getDatabasePath(String)}.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700731 * @param openParams configuration parameters that are used for opening {@link SQLiteDatabase}
732 * @return the newly opened database
733 * @throws SQLiteException if the database cannot be opened
734 */
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700735 public static SQLiteDatabase openDatabase(@NonNull File path,
736 @NonNull OpenParams openParams) {
737 return openDatabase(path.getPath(), openParams);
738 }
739
Mathew Inwoodf86bea92018-08-10 16:10:20 +0100740 @UnsupportedAppUsage
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700741 private static SQLiteDatabase openDatabase(@NonNull String path,
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700742 @NonNull OpenParams openParams) {
743 Preconditions.checkArgument(openParams != null, "OpenParams cannot be null");
744 SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags,
745 openParams.mCursorFactory, openParams.mErrorHandler,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700746 openParams.mLookasideSlotSize, openParams.mLookasideSlotCount,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800747 openParams.mIdleConnectionTimeout, openParams.mJournalMode, openParams.mSyncMode);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700748 db.open();
749 return db;
750 }
751
752 /**
Vasu Nori74f170f2010-06-01 18:06:18 -0700753 * Open the database according to the flags {@link #OPEN_READWRITE}
754 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
755 *
756 * <p>Sets the locale of the database to the the system's current locale.
757 * Call {@link #setLocale} if you would like something else.</p>
758 *
759 * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be
760 * used to handle corruption when sqlite reports database corruption.</p>
761 *
762 * @param path to database file to open and/or create
763 * @param factory an optional factory class that is called to instantiate a
764 * cursor when query is called, or null for default
765 * @param flags to control database access mode
766 * @param errorHandler the {@link DatabaseErrorHandler} obj to be used to handle corruption
767 * when sqlite reports database corruption
768 * @return the newly opened database
769 * @throws SQLiteException if the database cannot be opened
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700770 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700771 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
772 @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler) {
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800773 SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1, -1, null,
774 null);
Jeff Browne5360fb2011-10-31 17:48:13 -0700775 db.open();
776 return db;
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700777 }
778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 /**
780 * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
781 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700782 public static SQLiteDatabase openOrCreateDatabase(@NonNull File file,
783 @Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 return openOrCreateDatabase(file.getPath(), factory);
785 }
786
787 /**
788 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
789 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700790 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
791 @Nullable CursorFactory factory) {
Jeff Brown47847f32012-03-22 19:13:11 -0700792 return openDatabase(path, factory, CREATE_IF_NECESSARY, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 }
794
795 /**
Vasu Nori6c354da2010-04-26 23:33:39 -0700796 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler).
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700797 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700798 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
799 @Nullable CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler) {
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700800 return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler);
801 }
802
Jeff Brown559d0642012-02-29 10:19:12 -0800803 /**
Jeff Brown79087e42012-03-01 19:52:44 -0800804 * Deletes a database including its journal file and other auxiliary files
805 * that may have been created by the database engine.
806 *
807 * @param file The database file path.
808 * @return True if the database was successfully deleted.
809 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700810 public static boolean deleteDatabase(@NonNull File file) {
Jeff Brown79087e42012-03-01 19:52:44 -0800811 if (file == null) {
812 throw new IllegalArgumentException("file must not be null");
813 }
814
815 boolean deleted = false;
816 deleted |= file.delete();
817 deleted |= new File(file.getPath() + "-journal").delete();
818 deleted |= new File(file.getPath() + "-shm").delete();
819 deleted |= new File(file.getPath() + "-wal").delete();
820
821 File dir = file.getParentFile();
822 if (dir != null) {
823 final String prefix = file.getName() + "-mj";
Jeff Brownfce58902014-01-24 13:20:57 -0800824 File[] files = dir.listFiles(new FileFilter() {
Jeff Brown79087e42012-03-01 19:52:44 -0800825 @Override
826 public boolean accept(File candidate) {
827 return candidate.getName().startsWith(prefix);
828 }
Jeff Brownfce58902014-01-24 13:20:57 -0800829 });
830 if (files != null) {
831 for (File masterJournal : files) {
832 deleted |= masterJournal.delete();
833 }
Jeff Brown79087e42012-03-01 19:52:44 -0800834 }
835 }
836 return deleted;
837 }
838
839 /**
Jeff Brown559d0642012-02-29 10:19:12 -0800840 * Reopens the database in read-write mode.
841 * If the database is already read-write, does nothing.
842 *
843 * @throws SQLiteException if the database could not be reopened as requested, in which
844 * case it remains open in read only mode.
845 * @throws IllegalStateException if the database is not open.
846 *
847 * @see #isReadOnly()
848 * @hide
849 */
Mathew Inwoodf86bea92018-08-10 16:10:20 +0100850 @UnsupportedAppUsage
Jeff Brown559d0642012-02-29 10:19:12 -0800851 public void reopenReadWrite() {
852 synchronized (mLock) {
853 throwIfNotOpenLocked();
854
855 if (!isReadOnlyLocked()) {
856 return; // nothing to do
857 }
858
859 // Reopen the database in read-write mode.
860 final int oldOpenFlags = mConfigurationLocked.openFlags;
861 mConfigurationLocked.openFlags = (mConfigurationLocked.openFlags & ~OPEN_READ_MASK)
862 | OPEN_READWRITE;
863 try {
864 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
865 } catch (RuntimeException ex) {
866 mConfigurationLocked.openFlags = oldOpenFlags;
867 throw ex;
868 }
869 }
870 }
871
Jeff Browne5360fb2011-10-31 17:48:13 -0700872 private void open() {
873 try {
874 try {
875 openInner();
876 } catch (SQLiteDatabaseCorruptException ex) {
877 onCorruption();
878 openInner();
879 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700880 } catch (SQLiteException ex) {
881 Log.e(TAG, "Failed to open database '" + getLabel() + "'.", ex);
882 close();
883 throw ex;
884 }
885 }
886
887 private void openInner() {
888 synchronized (mLock) {
889 assert mConnectionPoolLocked == null;
890 mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked);
891 mCloseGuardLocked.open("close");
892 }
893
894 synchronized (sActiveDatabases) {
895 sActiveDatabases.put(this, null);
896 }
897 }
898
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700899 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 * Create a memory backed SQLite database. Its contents will be destroyed
901 * when the database is closed.
902 *
903 * <p>Sets the locale of the database to the the system's current locale.
904 * Call {@link #setLocale} if you would like something else.</p>
905 *
906 * @param factory an optional factory class that is called to instantiate a
907 * cursor when query is called
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700908 * @return a SQLiteDatabase instance
909 * @throws SQLiteException if the database cannot be created
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700911 @NonNull
912 public static SQLiteDatabase create(@Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 // This is a magic string with special meaning for SQLite.
Jeff Browne5360fb2011-10-31 17:48:13 -0700914 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
915 factory, CREATE_IF_NECESSARY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916 }
917
918 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700919 * Create a memory backed SQLite database. Its contents will be destroyed
920 * when the database is closed.
921 *
922 * <p>Sets the locale of the database to the the system's current locale.
923 * Call {@link #setLocale} if you would like something else.</p>
924 * @param openParams configuration parameters that are used for opening SQLiteDatabase
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700925 * @return a SQLiteDatabase instance
926 * @throws SQLException if the database cannot be created
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700927 */
928 @NonNull
929 public static SQLiteDatabase createInMemory(@NonNull OpenParams openParams) {
930 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
931 openParams.toBuilder().addOpenFlags(CREATE_IF_NECESSARY).build());
932 }
933
934 /**
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400935 * Registers a CustomFunction callback as a function that can be called from
Jeff Browne5360fb2011-10-31 17:48:13 -0700936 * SQLite database triggers.
937 *
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400938 * @param name the name of the sqlite3 function
939 * @param numArgs the number of arguments for the function
940 * @param function callback to call when the function is executed
941 * @hide
942 */
943 public void addCustomFunction(String name, int numArgs, CustomFunction function) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700944 // Create wrapper (also validates arguments).
945 SQLiteCustomFunction wrapper = new SQLiteCustomFunction(name, numArgs, function);
946
947 synchronized (mLock) {
948 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -0700949
Jeff Browne5360fb2011-10-31 17:48:13 -0700950 mConfigurationLocked.customFunctions.add(wrapper);
Jeff Browne67ca422012-03-21 17:24:05 -0700951 try {
952 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
953 } catch (RuntimeException ex) {
954 mConfigurationLocked.customFunctions.remove(wrapper);
955 throw ex;
956 }
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400957 }
958 }
959
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400960 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 * Gets the database version.
962 *
963 * @return the database version
964 */
965 public int getVersion() {
Vasu Noriccd95442010-05-28 17:04:16 -0700966 return ((Long) DatabaseUtils.longForQuery(this, "PRAGMA user_version;", null)).intValue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 }
968
969 /**
970 * Sets the database version.
971 *
972 * @param version the new database version
973 */
974 public void setVersion(int version) {
975 execSQL("PRAGMA user_version = " + version);
976 }
977
978 /**
979 * Returns the maximum size the database may grow to.
980 *
981 * @return the new maximum database size
982 */
983 public long getMaximumSize() {
Vasu Noriccd95442010-05-28 17:04:16 -0700984 long pageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count;", null);
985 return pageCount * getPageSize();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 }
987
988 /**
989 * Sets the maximum size the database will grow to. The maximum size cannot
990 * be set below the current size.
991 *
992 * @param numBytes the maximum database size, in bytes
993 * @return the new maximum database size
994 */
995 public long setMaximumSize(long numBytes) {
Vasu Noriccd95442010-05-28 17:04:16 -0700996 long pageSize = getPageSize();
997 long numPages = numBytes / pageSize;
998 // If numBytes isn't a multiple of pageSize, bump up a page
999 if ((numBytes % pageSize) != 0) {
1000 numPages++;
Vasu Norif3cf8a42010-03-23 11:41:44 -07001001 }
Vasu Noriccd95442010-05-28 17:04:16 -07001002 long newPageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count = " + numPages,
1003 null);
1004 return newPageCount * pageSize;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 }
1006
1007 /**
1008 * Returns the current database page size, in bytes.
1009 *
1010 * @return the database page size, in bytes
1011 */
1012 public long getPageSize() {
Vasu Noriccd95442010-05-28 17:04:16 -07001013 return DatabaseUtils.longForQuery(this, "PRAGMA page_size;", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 }
1015
1016 /**
1017 * Sets the database page size. The page size must be a power of two. This
1018 * method does not work if any data has been written to the database file,
1019 * and must be called right after the database has been created.
1020 *
1021 * @param numBytes the database page size, in bytes
1022 */
1023 public void setPageSize(long numBytes) {
1024 execSQL("PRAGMA page_size = " + numBytes);
1025 }
1026
1027 /**
1028 * Mark this table as syncable. When an update occurs in this table the
1029 * _sync_dirty field will be set to ensure proper syncing operation.
1030 *
1031 * @param table the table to mark as syncable
1032 * @param deletedTable The deleted table that corresponds to the
1033 * syncable table
Vasu Nori95675132010-07-21 16:24:40 -07001034 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 */
Vasu Nori95675132010-07-21 16:24:40 -07001036 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001037 public void markTableSyncable(String table, String deletedTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 }
1039
1040 /**
1041 * Mark this table as syncable, with the _sync_dirty residing in another
1042 * table. When an update occurs in this table the _sync_dirty field of the
1043 * row in updateTable with the _id in foreignKey will be set to
1044 * ensure proper syncing operation.
1045 *
1046 * @param table an update on this table will trigger a sync time removal
1047 * @param foreignKey this is the column in table whose value is an _id in
1048 * updateTable
1049 * @param updateTable this is the table that will have its _sync_dirty
Vasu Nori95675132010-07-21 16:24:40 -07001050 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 */
Vasu Nori95675132010-07-21 16:24:40 -07001052 @Deprecated
1053 public void markTableSyncable(String table, String foreignKey, String updateTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 }
1055
1056 /**
1057 * Finds the name of the first table, which is editable.
1058 *
1059 * @param tables a list of tables
1060 * @return the first table listed
1061 */
1062 public static String findEditTable(String tables) {
1063 if (!TextUtils.isEmpty(tables)) {
1064 // find the first word terminated by either a space or a comma
1065 int spacepos = tables.indexOf(' ');
1066 int commapos = tables.indexOf(',');
1067
1068 if (spacepos > 0 && (spacepos < commapos || commapos < 0)) {
1069 return tables.substring(0, spacepos);
1070 } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) {
1071 return tables.substring(0, commapos);
1072 }
1073 return tables;
1074 } else {
1075 throw new IllegalStateException("Invalid tables");
1076 }
1077 }
1078
1079 /**
1080 * Compiles an SQL statement into a reusable pre-compiled statement object.
1081 * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the
1082 * statement and fill in those values with {@link SQLiteProgram#bindString}
1083 * and {@link SQLiteProgram#bindLong} each time you want to run the
1084 * statement. Statements may not return result sets larger than 1x1.
Vasu Nori2827d6d2010-07-04 00:26:18 -07001085 *<p>
1086 * No two threads should be using the same {@link SQLiteStatement} at the same time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 *
1088 * @param sql The raw SQL statement, may contain ? for unknown values to be
1089 * bound later.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001090 * @return A pre-compiled {@link SQLiteStatement} object. Note that
1091 * {@link SQLiteStatement}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 */
1093 public SQLiteStatement compileStatement(String sql) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001094 acquireReference();
1095 try {
1096 return new SQLiteStatement(this, sql, null);
1097 } finally {
1098 releaseReference();
1099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 }
1101
1102 /**
1103 * Query the given URL, returning a {@link Cursor} over the result set.
1104 *
1105 * @param distinct true if you want each row to be unique, false otherwise.
1106 * @param table The table name to compile the query against.
1107 * @param columns A list of which columns to return. Passing null will
1108 * return all columns, which is discouraged to prevent reading
1109 * data from storage that isn't going to be used.
1110 * @param selection A filter declaring which rows to return, formatted as an
1111 * SQL WHERE clause (excluding the WHERE itself). Passing null
1112 * will return all rows for the given table.
1113 * @param selectionArgs You may include ?s in selection, which will be
1114 * replaced by the values from selectionArgs, in order that they
1115 * appear in the selection. The values will be bound as Strings.
1116 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1117 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1118 * will cause the rows to not be grouped.
1119 * @param having A filter declare which row groups to include in the cursor,
1120 * if row grouping is being used, formatted as an SQL HAVING
1121 * clause (excluding the HAVING itself). Passing null will cause
1122 * all row groups to be included, and is required when row
1123 * grouping is not being used.
1124 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1125 * (excluding the ORDER BY itself). Passing null will use the
1126 * default sort order, which may be unordered.
1127 * @param limit Limits the number of rows returned by the query,
1128 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001129 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1130 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 * @see Cursor
1132 */
1133 public Cursor query(boolean distinct, String table, String[] columns,
1134 String selection, String[] selectionArgs, String groupBy,
1135 String having, String orderBy, String limit) {
1136 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown75ea64f2012-01-25 19:37:13 -08001137 groupBy, having, orderBy, limit, null);
1138 }
1139
1140 /**
1141 * Query the given URL, returning a {@link Cursor} over the result set.
1142 *
1143 * @param distinct true if you want each row to be unique, false otherwise.
1144 * @param table The table name to compile the query against.
1145 * @param columns A list of which columns to return. Passing null will
1146 * return all columns, which is discouraged to prevent reading
1147 * data from storage that isn't going to be used.
1148 * @param selection A filter declaring which rows to return, formatted as an
1149 * SQL WHERE clause (excluding the WHERE itself). Passing null
1150 * will return all rows for the given table.
1151 * @param selectionArgs You may include ?s in selection, which will be
1152 * replaced by the values from selectionArgs, in order that they
1153 * appear in the selection. The values will be bound as Strings.
1154 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1155 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1156 * will cause the rows to not be grouped.
1157 * @param having A filter declare which row groups to include in the cursor,
1158 * if row grouping is being used, formatted as an SQL HAVING
1159 * clause (excluding the HAVING itself). Passing null will cause
1160 * all row groups to be included, and is required when row
1161 * grouping is not being used.
1162 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1163 * (excluding the ORDER BY itself). Passing null will use the
1164 * default sort order, which may be unordered.
1165 * @param limit Limits the number of rows returned by the query,
1166 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001167 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001168 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1169 * when the query is executed.
1170 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1171 * {@link Cursor}s are not synchronized, see the documentation for more details.
1172 * @see Cursor
1173 */
1174 public Cursor query(boolean distinct, String table, String[] columns,
1175 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001176 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001177 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001178 groupBy, having, orderBy, limit, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 }
1180
1181 /**
1182 * Query the given URL, returning a {@link Cursor} over the result set.
1183 *
1184 * @param cursorFactory the cursor factory to use, or null for the default factory
1185 * @param distinct true if you want each row to be unique, false otherwise.
1186 * @param table The table name to compile the query against.
1187 * @param columns A list of which columns to return. Passing null will
1188 * return all columns, which is discouraged to prevent reading
1189 * data from storage that isn't going to be used.
1190 * @param selection A filter declaring which rows to return, formatted as an
1191 * SQL WHERE clause (excluding the WHERE itself). Passing null
1192 * will return all rows for the given table.
1193 * @param selectionArgs You may include ?s in selection, which will be
1194 * replaced by the values from selectionArgs, in order that they
1195 * appear in the selection. The values will be bound as Strings.
1196 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1197 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1198 * will cause the rows to not be grouped.
1199 * @param having A filter declare which row groups to include in the cursor,
1200 * if row grouping is being used, formatted as an SQL HAVING
1201 * clause (excluding the HAVING itself). Passing null will cause
1202 * all row groups to be included, and is required when row
1203 * grouping is not being used.
1204 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1205 * (excluding the ORDER BY itself). Passing null will use the
1206 * default sort order, which may be unordered.
1207 * @param limit Limits the number of rows returned by the query,
1208 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001209 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1210 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001211 * @see Cursor
1212 */
1213 public Cursor queryWithFactory(CursorFactory cursorFactory,
1214 boolean distinct, String table, String[] columns,
1215 String selection, String[] selectionArgs, String groupBy,
1216 String having, String orderBy, String limit) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001217 return queryWithFactory(cursorFactory, distinct, table, columns, selection,
1218 selectionArgs, groupBy, having, orderBy, limit, null);
1219 }
1220
1221 /**
1222 * Query the given URL, returning a {@link Cursor} over the result set.
1223 *
1224 * @param cursorFactory the cursor factory to use, or null for the default factory
1225 * @param distinct true if you want each row to be unique, false otherwise.
1226 * @param table The table name to compile the query against.
1227 * @param columns A list of which columns to return. Passing null will
1228 * return all columns, which is discouraged to prevent reading
1229 * data from storage that isn't going to be used.
1230 * @param selection A filter declaring which rows to return, formatted as an
1231 * SQL WHERE clause (excluding the WHERE itself). Passing null
1232 * will return all rows for the given table.
1233 * @param selectionArgs You may include ?s in selection, which will be
1234 * replaced by the values from selectionArgs, in order that they
1235 * appear in the selection. The values will be bound as Strings.
1236 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1237 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1238 * will cause the rows to not be grouped.
1239 * @param having A filter declare which row groups to include in the cursor,
1240 * if row grouping is being used, formatted as an SQL HAVING
1241 * clause (excluding the HAVING itself). Passing null will cause
1242 * all row groups to be included, and is required when row
1243 * grouping is not being used.
1244 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1245 * (excluding the ORDER BY itself). Passing null will use the
1246 * default sort order, which may be unordered.
1247 * @param limit Limits the number of rows returned by the query,
1248 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001249 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001250 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1251 * when the query is executed.
1252 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1253 * {@link Cursor}s are not synchronized, see the documentation for more details.
1254 * @see Cursor
1255 */
1256 public Cursor queryWithFactory(CursorFactory cursorFactory,
1257 boolean distinct, String table, String[] columns,
1258 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001259 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001260 acquireReference();
1261 try {
1262 String sql = SQLiteQueryBuilder.buildQueryString(
1263 distinct, table, columns, selection, groupBy, having, orderBy, limit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264
Jeff Brown03bd3022012-03-06 13:48:56 -08001265 return rawQueryWithFactory(cursorFactory, sql, selectionArgs,
1266 findEditTable(table), cancellationSignal);
1267 } finally {
1268 releaseReference();
1269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270 }
1271
1272 /**
1273 * Query the given table, returning a {@link Cursor} over the result set.
1274 *
1275 * @param table The table name to compile the query against.
1276 * @param columns A list of which columns to return. Passing null will
1277 * return all columns, which is discouraged to prevent reading
1278 * data from storage that isn't going to be used.
1279 * @param selection A filter declaring which rows to return, formatted as an
1280 * SQL WHERE clause (excluding the WHERE itself). Passing null
1281 * will return all rows for the given table.
1282 * @param selectionArgs You may include ?s in selection, which will be
1283 * replaced by the values from selectionArgs, in order that they
1284 * appear in the selection. The values will be bound as Strings.
1285 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1286 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1287 * will cause the rows to not be grouped.
1288 * @param having A filter declare which row groups to include in the cursor,
1289 * if row grouping is being used, formatted as an SQL HAVING
1290 * clause (excluding the HAVING itself). Passing null will cause
1291 * all row groups to be included, and is required when row
1292 * grouping is not being used.
1293 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1294 * (excluding the ORDER BY itself). Passing null will use the
1295 * default sort order, which may be unordered.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001296 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1297 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001298 * @see Cursor
1299 */
1300 public Cursor query(String table, String[] columns, String selection,
1301 String[] selectionArgs, String groupBy, String having,
1302 String orderBy) {
1303
1304 return query(false, table, columns, selection, selectionArgs, groupBy,
1305 having, orderBy, null /* limit */);
1306 }
1307
1308 /**
1309 * Query the given table, returning a {@link Cursor} over the result set.
1310 *
1311 * @param table The table name to compile the query against.
1312 * @param columns A list of which columns to return. Passing null will
1313 * return all columns, which is discouraged to prevent reading
1314 * data from storage that isn't going to be used.
1315 * @param selection A filter declaring which rows to return, formatted as an
1316 * SQL WHERE clause (excluding the WHERE itself). Passing null
1317 * will return all rows for the given table.
1318 * @param selectionArgs You may include ?s in selection, which will be
1319 * replaced by the values from selectionArgs, in order that they
1320 * appear in the selection. The values will be bound as Strings.
1321 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1322 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1323 * will cause the rows to not be grouped.
1324 * @param having A filter declare which row groups to include in the cursor,
1325 * if row grouping is being used, formatted as an SQL HAVING
1326 * clause (excluding the HAVING itself). Passing null will cause
1327 * all row groups to be included, and is required when row
1328 * grouping is not being used.
1329 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1330 * (excluding the ORDER BY itself). Passing null will use the
1331 * default sort order, which may be unordered.
1332 * @param limit Limits the number of rows returned by the query,
1333 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001334 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1335 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 * @see Cursor
1337 */
1338 public Cursor query(String table, String[] columns, String selection,
1339 String[] selectionArgs, String groupBy, String having,
1340 String orderBy, String limit) {
1341
1342 return query(false, table, columns, selection, selectionArgs, groupBy,
1343 having, orderBy, limit);
1344 }
1345
1346 /**
1347 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1348 *
1349 * @param sql the SQL query. The SQL string must not be ; terminated
1350 * @param selectionArgs You may include ?s in where clause in the query,
1351 * which will be replaced by the values from selectionArgs. The
1352 * values will be bound as Strings.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001353 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1354 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001355 */
1356 public Cursor rawQuery(String sql, String[] selectionArgs) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001357 return rawQueryWithFactory(null, sql, selectionArgs, null, null);
1358 }
1359
1360 /**
1361 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1362 *
1363 * @param sql the SQL query. The SQL string must not be ; terminated
1364 * @param selectionArgs You may include ?s in where clause in the query,
1365 * which will be replaced by the values from selectionArgs. The
1366 * values will be bound as Strings.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001367 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001368 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1369 * when the query is executed.
1370 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1371 * {@link Cursor}s are not synchronized, see the documentation for more details.
1372 */
1373 public Cursor rawQuery(String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001374 CancellationSignal cancellationSignal) {
1375 return rawQueryWithFactory(null, sql, selectionArgs, null, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001376 }
1377
1378 /**
1379 * Runs the provided SQL and returns a cursor over the result set.
1380 *
1381 * @param cursorFactory the cursor factory to use, or null for the default factory
1382 * @param sql the SQL query. The SQL string must not be ; terminated
1383 * @param selectionArgs You may include ?s in where clause in the query,
1384 * which will be replaced by the values from selectionArgs. The
1385 * values will be bound as Strings.
1386 * @param editTable the name of the first table, which is editable
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001387 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1388 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 */
1390 public Cursor rawQueryWithFactory(
1391 CursorFactory cursorFactory, String sql, String[] selectionArgs,
1392 String editTable) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001393 return rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable, null);
1394 }
1395
1396 /**
1397 * Runs the provided SQL and returns a cursor over the result set.
1398 *
1399 * @param cursorFactory the cursor factory to use, or null for the default factory
1400 * @param sql the SQL query. The SQL string must not be ; terminated
1401 * @param selectionArgs You may include ?s in where clause in the query,
1402 * which will be replaced by the values from selectionArgs. The
1403 * values will be bound as Strings.
1404 * @param editTable the name of the first table, which is editable
Jeff Brown4c1241d2012-02-02 17:05:00 -08001405 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001406 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1407 * when the query is executed.
1408 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1409 * {@link Cursor}s are not synchronized, see the documentation for more details.
1410 */
1411 public Cursor rawQueryWithFactory(
1412 CursorFactory cursorFactory, String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001413 String editTable, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001414 acquireReference();
1415 try {
1416 SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
1417 cancellationSignal);
1418 return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
1419 selectionArgs);
1420 } finally {
1421 releaseReference();
1422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 }
1424
1425 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 * Convenience method for inserting a row into the database.
1427 *
1428 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001429 * @param nullColumnHack optional; may be <code>null</code>.
1430 * SQL doesn't allow inserting a completely empty row without
1431 * naming at least one column name. If your provided <code>values</code> is
1432 * empty, no column names are known and an empty row can't be inserted.
1433 * If not set to null, the <code>nullColumnHack</code> parameter
1434 * provides the name of nullable column name to explicitly insert a NULL into
1435 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001436 * @param values this map contains the initial column values for the
1437 * row. The keys should be the column names and the values the
1438 * column values
1439 * @return the row ID of the newly inserted row, or -1 if an error occurred
1440 */
1441 public long insert(String table, String nullColumnHack, ContentValues values) {
1442 try {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001443 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 } catch (SQLException e) {
1445 Log.e(TAG, "Error inserting " + values, e);
1446 return -1;
1447 }
1448 }
1449
1450 /**
1451 * Convenience method for inserting a row into the database.
1452 *
1453 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001454 * @param nullColumnHack optional; may be <code>null</code>.
1455 * SQL doesn't allow inserting a completely empty row without
1456 * naming at least one column name. If your provided <code>values</code> is
1457 * empty, no column names are known and an empty row can't be inserted.
1458 * If not set to null, the <code>nullColumnHack</code> parameter
1459 * provides the name of nullable column name to explicitly insert a NULL into
1460 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 * @param values this map contains the initial column values for the
1462 * row. The keys should be the column names and the values the
1463 * column values
1464 * @throws SQLException
1465 * @return the row ID of the newly inserted row, or -1 if an error occurred
1466 */
1467 public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
1468 throws SQLException {
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 }
1471
1472 /**
1473 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001474 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 *
1476 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001477 * @param nullColumnHack optional; may be <code>null</code>.
1478 * SQL doesn't allow inserting a completely empty row without
1479 * naming at least one column name. If your provided <code>initialValues</code> is
1480 * empty, no column names are known and an empty row can't be inserted.
1481 * If not set to null, the <code>nullColumnHack</code> parameter
1482 * provides the name of nullable column name to explicitly insert a NULL into
1483 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001485 * 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 -08001486 * @return the row ID of the newly inserted row, or -1 if an error occurred
1487 */
1488 public long replace(String table, String nullColumnHack, ContentValues initialValues) {
1489 try {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001490 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001491 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 } catch (SQLException e) {
1493 Log.e(TAG, "Error inserting " + initialValues, e);
1494 return -1;
1495 }
1496 }
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 * @throws SQLException
1513 * @return the row ID of the newly inserted row, or -1 if an error occurred
1514 */
1515 public long replaceOrThrow(String table, String nullColumnHack,
1516 ContentValues initialValues) throws SQLException {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001517 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001518 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 }
1520
1521 /**
1522 * General method for inserting a row into the database.
1523 *
1524 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001525 * @param nullColumnHack optional; may be <code>null</code>.
1526 * SQL doesn't allow inserting a completely empty row without
1527 * naming at least one column name. If your provided <code>initialValues</code> is
1528 * empty, no column names are known and an empty row can't be inserted.
1529 * If not set to null, the <code>nullColumnHack</code> parameter
1530 * provides the name of nullable column name to explicitly insert a NULL into
1531 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 * @param initialValues this map contains the initial column values for the
1533 * row. The keys should be the column names and the values the
1534 * column values
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001535 * @param conflictAlgorithm for insert conflict resolver
Steve Pomeroyc240b602013-03-14 00:42:10 -04001536 * @return the row ID of the newly inserted row OR <code>-1</code> if either the
1537 * input parameter <code>conflictAlgorithm</code> = {@link #CONFLICT_IGNORE}
1538 * or an error occurred.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 */
1540 public long insertWithOnConflict(String table, String nullColumnHack,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001541 ContentValues initialValues, int conflictAlgorithm) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001542 acquireReference();
1543 try {
1544 StringBuilder sql = new StringBuilder();
1545 sql.append("INSERT");
1546 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1547 sql.append(" INTO ");
1548 sql.append(table);
1549 sql.append('(');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550
Jeff Brown03bd3022012-03-06 13:48:56 -08001551 Object[] bindArgs = null;
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001552 int size = (initialValues != null && !initialValues.isEmpty())
Jeff Brown03bd3022012-03-06 13:48:56 -08001553 ? initialValues.size() : 0;
1554 if (size > 0) {
1555 bindArgs = new Object[size];
1556 int i = 0;
1557 for (String colName : initialValues.keySet()) {
1558 sql.append((i > 0) ? "," : "");
1559 sql.append(colName);
1560 bindArgs[i++] = initialValues.get(colName);
1561 }
1562 sql.append(')');
1563 sql.append(" VALUES (");
1564 for (i = 0; i < size; i++) {
1565 sql.append((i > 0) ? ",?" : "?");
1566 }
1567 } else {
1568 sql.append(nullColumnHack + ") VALUES (NULL");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 sql.append(')');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571
Jeff Brown03bd3022012-03-06 13:48:56 -08001572 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1573 try {
1574 return statement.executeInsert();
1575 } finally {
1576 statement.close();
1577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001578 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001579 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 }
1581 }
1582
1583 /**
1584 * Convenience method for deleting rows in the database.
1585 *
1586 * @param table the table to delete from
1587 * @param whereClause the optional WHERE clause to apply when deleting.
1588 * Passing null will delete all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001589 * @param whereArgs You may include ?s in the where clause, which
1590 * will be replaced by the values from whereArgs. The values
1591 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 * @return the number of rows affected if a whereClause is passed in, 0
1593 * otherwise. To remove all rows and get a count pass "1" as the
1594 * whereClause.
1595 */
1596 public int delete(String table, String whereClause, String[] whereArgs) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001597 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001599 SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table +
1600 (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
1601 try {
1602 return statement.executeUpdateDelete();
1603 } finally {
1604 statement.close();
1605 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001607 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 }
1609 }
1610
1611 /**
1612 * Convenience method for updating rows in the database.
1613 *
1614 * @param table the table to update in
1615 * @param values a map from column names to new column values. null is a
1616 * valid value that will be translated to NULL.
1617 * @param whereClause the optional WHERE clause to apply when updating.
1618 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001619 * @param whereArgs You may include ?s in the where clause, which
1620 * will be replaced by the values from whereArgs. The values
1621 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 * @return the number of rows affected
1623 */
1624 public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001625 return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628 /**
1629 * Convenience method for updating rows in the database.
1630 *
1631 * @param table the table to update in
1632 * @param values a map from column names to new column values. null is a
1633 * valid value that will be translated to NULL.
1634 * @param whereClause the optional WHERE clause to apply when updating.
1635 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001636 * @param whereArgs You may include ?s in the where clause, which
1637 * will be replaced by the values from whereArgs. The values
1638 * will be bound as Strings.
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001639 * @param conflictAlgorithm for update conflict resolver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 * @return the number of rows affected
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 */
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001642 public int updateWithOnConflict(String table, ContentValues values,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001643 String whereClause, String[] whereArgs, int conflictAlgorithm) {
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001644 if (values == null || values.isEmpty()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 throw new IllegalArgumentException("Empty values");
1646 }
1647
Jeff Brown03bd3022012-03-06 13:48:56 -08001648 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001650 StringBuilder sql = new StringBuilder(120);
1651 sql.append("UPDATE ");
1652 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1653 sql.append(table);
1654 sql.append(" SET ");
1655
1656 // move all bind args to one array
1657 int setValuesSize = values.size();
1658 int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
1659 Object[] bindArgs = new Object[bindArgsSize];
1660 int i = 0;
1661 for (String colName : values.keySet()) {
1662 sql.append((i > 0) ? "," : "");
1663 sql.append(colName);
1664 bindArgs[i++] = values.get(colName);
1665 sql.append("=?");
1666 }
1667 if (whereArgs != null) {
1668 for (i = setValuesSize; i < bindArgsSize; i++) {
1669 bindArgs[i] = whereArgs[i - setValuesSize];
1670 }
1671 }
1672 if (!TextUtils.isEmpty(whereClause)) {
1673 sql.append(" WHERE ");
1674 sql.append(whereClause);
1675 }
1676
1677 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1678 try {
1679 return statement.executeUpdateDelete();
1680 } finally {
1681 statement.close();
1682 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001684 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 }
1686 }
1687
1688 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001689 * Execute a single SQL statement that is NOT a SELECT
1690 * or any other SQL statement that returns data.
1691 * <p>
Vasu Norice38b982010-07-22 13:57:13 -07001692 * It has no means to return any data (such as the number of affected rows).
Vasu Noriccd95442010-05-28 17:04:16 -07001693 * Instead, you're encouraged to use {@link #insert(String, String, ContentValues)},
1694 * {@link #update(String, ContentValues, String, String[])}, et al, when possible.
1695 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001696 * <p>
1697 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1698 * automatically managed by this class. So, do not set journal_mode
1699 * using "PRAGMA journal_mode'<value>" statement if your app is using
1700 * {@link #enableWriteAheadLogging()}
1701 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 *
Vasu Noriccd95442010-05-28 17:04:16 -07001703 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1704 * not supported.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001705 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001706 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001707 public void execSQL(String sql) throws SQLException {
Vasu Nori16057fa2011-03-18 11:40:37 -07001708 executeSql(sql, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 }
1710
1711 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001712 * Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE.
1713 * <p>
1714 * For INSERT statements, use any of the following instead.
1715 * <ul>
1716 * <li>{@link #insert(String, String, ContentValues)}</li>
1717 * <li>{@link #insertOrThrow(String, String, ContentValues)}</li>
1718 * <li>{@link #insertWithOnConflict(String, String, ContentValues, int)}</li>
1719 * </ul>
1720 * <p>
1721 * For UPDATE statements, use any of the following instead.
1722 * <ul>
1723 * <li>{@link #update(String, ContentValues, String, String[])}</li>
1724 * <li>{@link #updateWithOnConflict(String, ContentValues, String, String[], int)}</li>
1725 * </ul>
1726 * <p>
1727 * For DELETE statements, use any of the following instead.
1728 * <ul>
1729 * <li>{@link #delete(String, String, String[])}</li>
1730 * </ul>
1731 * <p>
1732 * For example, the following are good candidates for using this method:
1733 * <ul>
1734 * <li>ALTER TABLE</li>
1735 * <li>CREATE or DROP table / trigger / view / index / virtual table</li>
1736 * <li>REINDEX</li>
1737 * <li>RELEASE</li>
1738 * <li>SAVEPOINT</li>
1739 * <li>PRAGMA that returns no data</li>
1740 * </ul>
1741 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001742 * <p>
1743 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1744 * automatically managed by this class. So, do not set journal_mode
1745 * using "PRAGMA journal_mode'<value>" statement if your app is using
1746 * {@link #enableWriteAheadLogging()}
1747 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 *
Vasu Noriccd95442010-05-28 17:04:16 -07001749 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1750 * not supported.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751 * @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001752 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001754 public void execSQL(String sql, Object[] bindArgs) throws SQLException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 if (bindArgs == null) {
1756 throw new IllegalArgumentException("Empty bindArgs");
1757 }
Vasu Norib83cb7c2010-09-14 13:36:01 -07001758 executeSql(sql, bindArgs);
Vasu Norice38b982010-07-22 13:57:13 -07001759 }
1760
Jeff Sharkey19b3d912018-07-25 14:52:14 -06001761 /** {@hide} */
1762 public int executeSql(String sql, Object[] bindArgs) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001763 acquireReference();
1764 try {
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001765 final int statementType = DatabaseUtils.getSqlStatementType(sql);
1766 if (statementType == DatabaseUtils.STATEMENT_ATTACH) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001767 boolean disableWal = false;
1768 synchronized (mLock) {
1769 if (!mHasAttachedDbsLocked) {
1770 mHasAttachedDbsLocked = true;
1771 disableWal = true;
Fyodor Kupolovfd9c4a52017-07-13 15:36:57 -07001772 mConnectionPoolLocked.disableIdleConnectionHandler();
Jeff Brown03bd3022012-03-06 13:48:56 -08001773 }
1774 }
1775 if (disableWal) {
1776 disableWriteAheadLogging();
Jeff Browne5360fb2011-10-31 17:48:13 -07001777 }
1778 }
Jeff Browne5360fb2011-10-31 17:48:13 -07001779
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001780 try (SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs)) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001781 return statement.executeUpdateDelete();
1782 } finally {
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001783 // If schema was updated, close non-primary connections, otherwise they might
1784 // have outdated schema information
1785 if (statementType == DatabaseUtils.STATEMENT_DDL) {
1786 mConnectionPoolLocked.closeAvailableNonPrimaryConnectionsAndLogExceptions();
1787 }
Jeff Brown03bd3022012-03-06 13:48:56 -08001788 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001790 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 }
1793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 /**
Makoto Onuki17aa1b72015-12-16 14:02:01 -08001795 * Verifies that a SQL SELECT statement is valid by compiling it.
1796 * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
1797 *
1798 * @param sql SQL to be validated
1799 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
1800 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1801 * when the query is executed.
1802 * @throws SQLiteException if {@code sql} is invalid
1803 */
1804 public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal) {
1805 getThreadSession().prepare(sql,
1806 getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null);
1807 }
1808
1809 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001810 * Returns true if the database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001812 * @return True if database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001813 */
1814 public boolean isReadOnly() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001815 synchronized (mLock) {
1816 return isReadOnlyLocked();
1817 }
1818 }
1819
1820 private boolean isReadOnlyLocked() {
1821 return (mConfigurationLocked.openFlags & OPEN_READ_MASK) == OPEN_READONLY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001822 }
1823
1824 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001825 * Returns true if the database is in-memory db.
1826 *
1827 * @return True if the database is in-memory.
1828 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 */
Jeff Browne5360fb2011-10-31 17:48:13 -07001830 public boolean isInMemoryDatabase() {
1831 synchronized (mLock) {
1832 return mConfigurationLocked.isInMemoryDb();
1833 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001834 }
1835
Jeff Browne5360fb2011-10-31 17:48:13 -07001836 /**
1837 * Returns true if the database is currently open.
1838 *
1839 * @return True if the database is currently open (has not been closed).
1840 */
1841 public boolean isOpen() {
1842 synchronized (mLock) {
1843 return mConnectionPoolLocked != null;
1844 }
1845 }
1846
1847 /**
1848 * Returns true if the new version code is greater than the current database version.
1849 *
1850 * @param newVersion The new version code.
Mark Lu1e202082016-08-30 17:41:25 -07001851 * @return True if the new version code is greater than the current database version.
Jeff Browne5360fb2011-10-31 17:48:13 -07001852 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 public boolean needUpgrade(int newVersion) {
1854 return newVersion > getVersion();
1855 }
1856
1857 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001858 * Gets the path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001859 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001860 * @return The path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001861 */
1862 public final String getPath() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001863 synchronized (mLock) {
1864 return mConfigurationLocked.path;
Christopher Tatead9e8b12011-10-05 17:49:26 -07001865 }
Brad Fitzpatrick722802e2010-03-23 22:22:16 -07001866 }
1867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 /**
1869 * Sets the locale for this database. Does nothing if this database has
Jeff Brown1d9f7422012-03-15 14:32:32 -07001870 * the {@link #NO_LOCALIZED_COLLATORS} flag set or was opened read only.
Jeff Browne5360fb2011-10-31 17:48:13 -07001871 *
1872 * @param locale The new locale.
1873 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001874 * @throws SQLException if the locale could not be set. The most common reason
1875 * for this is that there is no collator available for the locale you requested.
1876 * In this case the database remains unchanged.
1877 */
1878 public void setLocale(Locale locale) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001879 if (locale == null) {
1880 throw new IllegalArgumentException("locale must not be null.");
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001881 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001882
Jeff Browne5360fb2011-10-31 17:48:13 -07001883 synchronized (mLock) {
1884 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001885
1886 final Locale oldLocale = mConfigurationLocked.locale;
Jeff Browne5360fb2011-10-31 17:48:13 -07001887 mConfigurationLocked.locale = locale;
Jeff Browne67ca422012-03-21 17:24:05 -07001888 try {
1889 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1890 } catch (RuntimeException ex) {
1891 mConfigurationLocked.locale = oldLocale;
1892 throw ex;
1893 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001894 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001895 }
1896
Vasu Norie495d1f2010-01-06 16:34:19 -08001897 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001898 * Sets the maximum size of the prepared-statement cache for this database.
Vasu Norie495d1f2010-01-06 16:34:19 -08001899 * (size of the cache = number of compiled-sql-statements stored in the cache).
Vasu Noriccd95442010-05-28 17:04:16 -07001900 *<p>
Vasu Norib729dcc2010-09-14 11:35:49 -07001901 * Maximum cache size can ONLY be increased from its current size (default = 10).
Vasu Noriccd95442010-05-28 17:04:16 -07001902 * If this method is called with smaller size than the current maximum value,
1903 * then IllegalStateException is thrown.
Vasu Norib729dcc2010-09-14 11:35:49 -07001904 *<p>
1905 * This method is thread-safe.
Vasu Norie495d1f2010-01-06 16:34:19 -08001906 *
Vasu Nori90a367262010-04-12 12:49:09 -07001907 * @param cacheSize the size of the cache. can be (0 to {@link #MAX_SQL_CACHE_SIZE})
Jeff Browne5360fb2011-10-31 17:48:13 -07001908 * @throws IllegalStateException if input cacheSize > {@link #MAX_SQL_CACHE_SIZE}.
Vasu Norie495d1f2010-01-06 16:34:19 -08001909 */
Vasu Nori54025902010-09-14 12:14:26 -07001910 public void setMaxSqlCacheSize(int cacheSize) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001911 if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) {
1912 throw new IllegalStateException(
1913 "expected value between 0 and " + MAX_SQL_CACHE_SIZE);
Vasu Nori587423a2010-09-27 18:18:34 -07001914 }
Vasu Nori587423a2010-09-27 18:18:34 -07001915
Jeff Browne5360fb2011-10-31 17:48:13 -07001916 synchronized (mLock) {
1917 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001918
1919 final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize;
Jeff Browne5360fb2011-10-31 17:48:13 -07001920 mConfigurationLocked.maxSqlCacheSize = cacheSize;
Jeff Browne67ca422012-03-21 17:24:05 -07001921 try {
1922 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1923 } catch (RuntimeException ex) {
1924 mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize;
1925 throw ex;
1926 }
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001927 }
1928 }
1929
Vasu Nori6c354da2010-04-26 23:33:39 -07001930 /**
Jeff Brown96496ad2012-03-23 14:38:06 -07001931 * Sets whether foreign key constraints are enabled for the database.
1932 * <p>
1933 * By default, foreign key constraints are not enforced by the database.
1934 * This method allows an application to enable foreign key constraints.
1935 * It must be called each time the database is opened to ensure that foreign
1936 * key constraints are enabled for the session.
1937 * </p><p>
1938 * A good time to call this method is right after calling {@link #openOrCreateDatabase}
1939 * or in the {@link SQLiteOpenHelper#onConfigure} callback.
1940 * </p><p>
1941 * When foreign key constraints are disabled, the database does not check whether
1942 * changes to the database will violate foreign key constraints. Likewise, when
1943 * foreign key constraints are disabled, the database will not execute cascade
1944 * delete or update triggers. As a result, it is possible for the database
1945 * state to become inconsistent. To perform a database integrity check,
1946 * call {@link #isDatabaseIntegrityOk}.
1947 * </p><p>
1948 * This method must not be called while a transaction is in progress.
1949 * </p><p>
1950 * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a>
1951 * for more details about foreign key constraint support.
1952 * </p>
1953 *
1954 * @param enable True to enable foreign key constraints, false to disable them.
1955 *
1956 * @throws IllegalStateException if the are transactions is in progress
1957 * when this method is called.
1958 */
1959 public void setForeignKeyConstraintsEnabled(boolean enable) {
1960 synchronized (mLock) {
1961 throwIfNotOpenLocked();
1962
1963 if (mConfigurationLocked.foreignKeyConstraintsEnabled == enable) {
1964 return;
1965 }
1966
1967 mConfigurationLocked.foreignKeyConstraintsEnabled = enable;
1968 try {
1969 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1970 } catch (RuntimeException ex) {
1971 mConfigurationLocked.foreignKeyConstraintsEnabled = !enable;
1972 throw ex;
1973 }
1974 }
1975 }
1976
1977 /**
Jeff Brown47847f32012-03-22 19:13:11 -07001978 * This method enables parallel execution of queries from multiple threads on the
1979 * same database. It does this by opening multiple connections to the database
1980 * and using a different database connection for each query. The database
1981 * journal mode is also changed to enable writes to proceed concurrently with reads.
Vasu Nori6c354da2010-04-26 23:33:39 -07001982 * <p>
Jeff Brown47847f32012-03-22 19:13:11 -07001983 * When write-ahead logging is not enabled (the default), it is not possible for
1984 * reads and writes to occur on the database at the same time. Before modifying the
1985 * database, the writer implicitly acquires an exclusive lock on the database which
1986 * prevents readers from accessing the database until the write is completed.
1987 * </p><p>
1988 * In contrast, when write-ahead logging is enabled (by calling this method), write
1989 * operations occur in a separate log file which allows reads to proceed concurrently.
1990 * While a write is in progress, readers on other threads will perceive the state
1991 * of the database as it was before the write began. When the write completes, readers
1992 * on other threads will then perceive the new state of the database.
1993 * </p><p>
1994 * It is a good idea to enable write-ahead logging whenever a database will be
1995 * concurrently accessed and modified by multiple threads at the same time.
1996 * However, write-ahead logging uses significantly more memory than ordinary
1997 * journaling because there are multiple connections to the same database.
1998 * So if a database will only be used by a single thread, or if optimizing
1999 * concurrency is not very important, then write-ahead logging should be disabled.
2000 * </p><p>
2001 * After calling this method, execution of queries in parallel is enabled as long as
2002 * the database remains open. To disable execution of queries in parallel, either
2003 * call {@link #disableWriteAheadLogging} or close the database and reopen it.
2004 * </p><p>
2005 * The maximum number of connections used to execute queries in parallel is
Vasu Nori6c354da2010-04-26 23:33:39 -07002006 * dependent upon the device memory and possibly other properties.
Jeff Brown47847f32012-03-22 19:13:11 -07002007 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07002008 * If a query is part of a transaction, then it is executed on the same database handle the
2009 * transaction was begun.
Jeff Brown47847f32012-03-22 19:13:11 -07002010 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07002011 * Writers should use {@link #beginTransactionNonExclusive()} or
2012 * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
Jeff Brown47847f32012-03-22 19:13:11 -07002013 * to start a transaction. Non-exclusive mode allows database file to be in readable
2014 * by other threads executing queries.
2015 * </p><p>
2016 * If the database has any attached databases, then execution of queries in parallel is NOT
2017 * possible. Likewise, write-ahead logging is not supported for read-only databases
2018 * or memory databases. In such cases, {@link #enableWriteAheadLogging} returns false.
2019 * </p><p>
2020 * The best way to enable write-ahead logging is to pass the
2021 * {@link #ENABLE_WRITE_AHEAD_LOGGING} flag to {@link #openDatabase}. This is
2022 * more efficient than calling {@link #enableWriteAheadLogging}.
2023 * <code><pre>
2024 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2025 * SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
2026 * myDatabaseErrorHandler);
Jeff Brown47847f32012-03-22 19:13:11 -07002027 * </pre></code>
2028 * </p><p>
2029 * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging}
2030 * after opening the database.
2031 * <code><pre>
2032 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2033 * SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
2034 * db.enableWriteAheadLogging();
2035 * </pre></code>
2036 * </p><p>
2037 * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for
2038 * more details about how write-ahead logging works.
Vasu Nori6c354da2010-04-26 23:33:39 -07002039 * </p>
2040 *
Jeff Brown47847f32012-03-22 19:13:11 -07002041 * @return True if write-ahead logging is enabled.
Jeff Browne67ca422012-03-21 17:24:05 -07002042 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002043 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002044 * time this method is called. WAL mode can only be changed when there are no
2045 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002046 *
2047 * @see #ENABLE_WRITE_AHEAD_LOGGING
2048 * @see #disableWriteAheadLogging
Vasu Nori6c354da2010-04-26 23:33:39 -07002049 */
Vasu Noriffe06122010-09-27 12:32:57 -07002050 public boolean enableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002051 synchronized (mLock) {
2052 throwIfNotOpenLocked();
2053
Jeff Brown47847f32012-03-22 19:13:11 -07002054 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002055 return true;
2056 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002057
2058 if (isReadOnlyLocked()) {
2059 // WAL doesn't make sense for readonly-databases.
2060 // TODO: True, but connection pooling does still make sense...
2061 return false;
2062 }
2063
2064 if (mConfigurationLocked.isInMemoryDb()) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002065 Log.i(TAG, "can't enable WAL for memory databases.");
2066 return false;
2067 }
2068
2069 // make sure this database has NO attached databases because sqlite's write-ahead-logging
2070 // doesn't work for databases with attached databases
Jeff Browne5360fb2011-10-31 17:48:13 -07002071 if (mHasAttachedDbsLocked) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002072 if (Log.isLoggable(TAG, Log.DEBUG)) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002073 Log.d(TAG, "this database: " + mConfigurationLocked.label
2074 + " has attached databases. can't enable WAL.");
Paul Westbrookdae6d372011-02-17 10:59:56 -08002075 }
2076 return false;
2077 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002078
Jeff Brown47847f32012-03-22 19:13:11 -07002079 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002080 try {
2081 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2082 } catch (RuntimeException ex) {
Jeff Brown47847f32012-03-22 19:13:11 -07002083 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002084 throw ex;
2085 }
Paul Westbrookdae6d372011-02-17 10:59:56 -08002086 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002087 return true;
Vasu Nori6c354da2010-04-26 23:33:39 -07002088 }
2089
Vasu Nori2827d6d2010-07-04 00:26:18 -07002090 /**
Vasu Nori7b04c412010-07-20 10:31:21 -07002091 * This method disables the features enabled by {@link #enableWriteAheadLogging()}.
Jeff Browne67ca422012-03-21 17:24:05 -07002092 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002093 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002094 * time this method is called. WAL mode can only be changed when there are no
2095 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002096 *
2097 * @see #enableWriteAheadLogging
Vasu Nori2827d6d2010-07-04 00:26:18 -07002098 */
Vasu Nori7b04c412010-07-20 10:31:21 -07002099 public void disableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002100 synchronized (mLock) {
2101 throwIfNotOpenLocked();
2102
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002103 final int oldFlags = mConfigurationLocked.openFlags;
Fyodor Kupolov692573b2018-03-06 12:34:36 -08002104 final boolean walDisabled = (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0;
2105 final boolean compatibilityWalDisabled = (oldFlags & DISABLE_COMPATIBILITY_WAL) != 0;
2106 if (walDisabled && compatibilityWalDisabled) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002107 return;
Paul Westbrookdae6d372011-02-17 10:59:56 -08002108 }
Vasu Nori8d111032010-06-22 18:34:21 -07002109
Jeff Brown47847f32012-03-22 19:13:11 -07002110 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Fyodor Kupolov692573b2018-03-06 12:34:36 -08002111 // If an app explicitly disables WAL, compatibility mode should be disabled too
2112 mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002113
Jeff Browne67ca422012-03-21 17:24:05 -07002114 try {
2115 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2116 } catch (RuntimeException ex) {
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002117 mConfigurationLocked.openFlags = oldFlags;
Jeff Browne67ca422012-03-21 17:24:05 -07002118 throw ex;
2119 }
Vasu Nori65a88832010-07-16 15:14:08 -07002120 }
Vasu Nori6c354da2010-04-26 23:33:39 -07002121 }
2122
Vasu Norif3cf8a42010-03-23 11:41:44 -07002123 /**
Jeff Brown47847f32012-03-22 19:13:11 -07002124 * Returns true if write-ahead logging has been enabled for this database.
2125 *
2126 * @return True if write-ahead logging has been enabled for this database.
2127 *
2128 * @see #enableWriteAheadLogging
2129 * @see #ENABLE_WRITE_AHEAD_LOGGING
2130 */
2131 public boolean isWriteAheadLoggingEnabled() {
2132 synchronized (mLock) {
2133 throwIfNotOpenLocked();
2134
2135 return (mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2136 }
2137 }
2138
2139 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002140 * Collect statistics about all open databases in the current process.
2141 * Used by bug report.
Vasu Norif3cf8a42010-03-23 11:41:44 -07002142 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002143 static ArrayList<DbStats> getDbStats() {
Vasu Noric3849202010-03-09 10:47:25 -08002144 ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002145 for (SQLiteDatabase db : getActiveDatabases()) {
2146 db.collectDbStats(dbStatsList);
Vasu Nori24675612010-09-27 14:54:19 -07002147 }
Vasu Noric3849202010-03-09 10:47:25 -08002148 return dbStatsList;
2149 }
2150
Mathew Inwoodf86bea92018-08-10 16:10:20 +01002151 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -07002152 private void collectDbStats(ArrayList<DbStats> dbStatsList) {
2153 synchronized (mLock) {
2154 if (mConnectionPoolLocked != null) {
2155 mConnectionPoolLocked.collectDbStats(dbStatsList);
2156 }
2157 }
2158 }
2159
Mathew Inwoodf86bea92018-08-10 16:10:20 +01002160 @UnsupportedAppUsage
Jeff Browne5360fb2011-10-31 17:48:13 -07002161 private static ArrayList<SQLiteDatabase> getActiveDatabases() {
2162 ArrayList<SQLiteDatabase> databases = new ArrayList<SQLiteDatabase>();
2163 synchronized (sActiveDatabases) {
2164 databases.addAll(sActiveDatabases.keySet());
2165 }
2166 return databases;
2167 }
2168
2169 /**
2170 * Dump detailed information about all open databases in the current process.
2171 * Used by bug report.
2172 */
Jeff Browna9be4152012-01-18 15:29:57 -08002173 static void dumpAll(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002174 for (SQLiteDatabase db : getActiveDatabases()) {
Jeff Browna9be4152012-01-18 15:29:57 -08002175 db.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002176 }
2177 }
2178
Jeff Browna9be4152012-01-18 15:29:57 -08002179 private void dump(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002180 synchronized (mLock) {
2181 if (mConnectionPoolLocked != null) {
2182 printer.println("");
Jeff Browna9be4152012-01-18 15:29:57 -08002183 mConnectionPoolLocked.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002184 }
2185 }
2186 }
2187
Vasu Noric3849202010-03-09 10:47:25 -08002188 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002189 * Returns list of full pathnames of all attached databases including the main database
2190 * by executing 'pragma database_list' on the database.
2191 *
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002192 * @return ArrayList of pairs of (database name, database file path) or null if the database
2193 * is not open.
Vasu Noric3849202010-03-09 10:47:25 -08002194 */
Vasu Noria017eda2011-01-27 10:52:55 -08002195 public List<Pair<String, String>> getAttachedDbs() {
Vasu Noric3849202010-03-09 10:47:25 -08002196 ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002197 synchronized (mLock) {
2198 if (mConnectionPoolLocked == null) {
2199 return null; // not open
2200 }
2201
2202 if (!mHasAttachedDbsLocked) {
2203 // No attached databases.
2204 // There is a small window where attached databases exist but this flag is not
2205 // set yet. This can occur when this thread is in a race condition with another
2206 // thread that is executing the SQL statement: "attach database <blah> as <foo>"
2207 // If this thread is NOT ok with such a race condition (and thus possibly not
2208 // receivethe entire list of attached databases), then the caller should ensure
2209 // that no thread is executing any SQL statements while a thread is calling this
2210 // method. Typically, this method is called when 'adb bugreport' is done or the
2211 // caller wants to collect stats on the database and all its attached databases.
2212 attachedDbs.add(new Pair<String, String>("main", mConfigurationLocked.path));
2213 return attachedDbs;
2214 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002215
2216 acquireReference();
Vasu Nori24675612010-09-27 14:54:19 -07002217 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002218
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002219 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002220 // has attached databases. query sqlite to get the list of attached databases.
2221 Cursor c = null;
2222 try {
2223 c = rawQuery("pragma database_list;", null);
2224 while (c.moveToNext()) {
2225 // sqlite returns a row for each database in the returned list of databases.
2226 // in each row,
2227 // 1st column is the database name such as main, or the database
2228 // name specified on the "ATTACH" command
2229 // 2nd column is the database file path.
2230 attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2)));
2231 }
2232 } finally {
2233 if (c != null) {
2234 c.close();
2235 }
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002236 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002237 return attachedDbs;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002238 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08002239 releaseReference();
Vasu Noric3849202010-03-09 10:47:25 -08002240 }
Vasu Noric3849202010-03-09 10:47:25 -08002241 }
2242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002243 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002244 * Runs 'pragma integrity_check' on the given database (and all the attached databases)
2245 * and returns true if the given database (and all its attached databases) pass integrity_check,
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002246 * false otherwise.
Vasu Noriccd95442010-05-28 17:04:16 -07002247 *<p>
2248 * If the result is false, then this method logs the errors reported by the integrity_check
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002249 * command execution.
Vasu Noriccd95442010-05-28 17:04:16 -07002250 *<p>
2251 * Note that 'pragma integrity_check' on a database can take a long time.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002252 *
2253 * @return true if the given database (and all its attached databases) pass integrity_check,
Vasu Noriccd95442010-05-28 17:04:16 -07002254 * false otherwise.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002255 */
2256 public boolean isDatabaseIntegrityOk() {
Jeff Brown03bd3022012-03-06 13:48:56 -08002257 acquireReference();
Vasu Noribfe1dc22010-08-25 16:29:02 -07002258 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002259 List<Pair<String, String>> attachedDbs = null;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002260 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002261 attachedDbs = getAttachedDbs();
2262 if (attachedDbs == null) {
2263 throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " +
2264 "be retrieved. probably because the database is closed");
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002265 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002266 } catch (SQLiteException e) {
2267 // can't get attachedDb list. do integrity check on the main database
2268 attachedDbs = new ArrayList<Pair<String, String>>();
2269 attachedDbs.add(new Pair<String, String>("main", getPath()));
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002270 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002271
2272 for (int i = 0; i < attachedDbs.size(); i++) {
2273 Pair<String, String> p = attachedDbs.get(i);
2274 SQLiteStatement prog = null;
2275 try {
2276 prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);");
2277 String rslt = prog.simpleQueryForString();
2278 if (!rslt.equalsIgnoreCase("ok")) {
2279 // integrity_checker failed on main or attached databases
2280 Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt);
2281 return false;
2282 }
2283 } finally {
2284 if (prog != null) prog.close();
2285 }
2286 }
2287 } finally {
2288 releaseReference();
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002289 }
Vasu Noribfe1dc22010-08-25 16:29:02 -07002290 return true;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002291 }
2292
Jeff Browne5360fb2011-10-31 17:48:13 -07002293 @Override
2294 public String toString() {
2295 return "SQLiteDatabase: " + getPath();
2296 }
2297
Jeff Browne5360fb2011-10-31 17:48:13 -07002298 private void throwIfNotOpenLocked() {
2299 if (mConnectionPoolLocked == null) {
2300 throw new IllegalStateException("The database '" + mConfigurationLocked.label
2301 + "' is not open.");
2302 }
2303 }
Vasu Nori3ef94e22010-02-05 14:49:04 -08002304
2305 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002306 * Used to allow returning sub-classes of {@link Cursor} when calling query.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002307 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002308 public interface CursorFactory {
2309 /**
2310 * See {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}.
2311 */
2312 public Cursor newCursor(SQLiteDatabase db,
2313 SQLiteCursorDriver masterQuery, String editTable,
2314 SQLiteQuery query);
2315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002316
2317 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002318 * A callback interface for a custom sqlite3 function.
2319 * This can be used to create a function that can be called from
2320 * sqlite3 database triggers.
2321 * @hide
Vasu Noric3849202010-03-09 10:47:25 -08002322 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002323 public interface CustomFunction {
2324 public void callback(String[] args);
2325 }
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002326
2327 /**
2328 * Wrapper for configuration parameters that are used for opening {@link SQLiteDatabase}
2329 */
2330 public static final class OpenParams {
2331 private final int mOpenFlags;
2332 private final CursorFactory mCursorFactory;
2333 private final DatabaseErrorHandler mErrorHandler;
2334 private final int mLookasideSlotSize;
2335 private final int mLookasideSlotCount;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002336 private final long mIdleConnectionTimeout;
2337 private final String mJournalMode;
2338 private final String mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002339
2340 private OpenParams(int openFlags, CursorFactory cursorFactory,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002341 DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002342 long idleConnectionTimeout, String journalMode, String syncMode) {
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002343 mOpenFlags = openFlags;
2344 mCursorFactory = cursorFactory;
2345 mErrorHandler = errorHandler;
2346 mLookasideSlotSize = lookasideSlotSize;
2347 mLookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002348 mIdleConnectionTimeout = idleConnectionTimeout;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002349 mJournalMode = journalMode;
2350 mSyncMode = syncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002351 }
2352
2353 /**
2354 * Returns size in bytes of each lookaside slot or -1 if not set.
2355 *
2356 * @see Builder#setLookasideConfig(int, int)
2357 */
2358 @IntRange(from = -1)
2359 public int getLookasideSlotSize() {
2360 return mLookasideSlotSize;
2361 }
2362
2363 /**
2364 * Returns total number of lookaside memory slots per database connection or -1 if not
2365 * set.
2366 *
2367 * @see Builder#setLookasideConfig(int, int)
2368 */
2369 @IntRange(from = -1)
2370 public int getLookasideSlotCount() {
2371 return mLookasideSlotCount;
2372 }
2373
2374 /**
Fyodor Kupolov76436c02017-08-03 17:56:44 -07002375 * Returns flags to control database access mode. Default value is 0.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002376 *
2377 * @see Builder#setOpenFlags(int)
2378 */
2379 @DatabaseOpenFlags
2380 public int getOpenFlags() {
2381 return mOpenFlags;
2382 }
2383
2384 /**
2385 * Returns an optional factory class that is called to instantiate a cursor when query
2386 * is called
2387 *
2388 * @see Builder#setCursorFactory(CursorFactory)
2389 */
2390 @Nullable
2391 public CursorFactory getCursorFactory() {
2392 return mCursorFactory;
2393 }
2394
2395 /**
2396 * Returns handler for database corruption errors
2397 *
2398 * @see Builder#setErrorHandler(DatabaseErrorHandler)
2399 */
2400 @Nullable
2401 public DatabaseErrorHandler getErrorHandler() {
2402 return mErrorHandler;
2403 }
2404
2405 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002406 * Returns maximum number of milliseconds that SQLite connection is allowed to be idle
2407 * before it is closed and removed from the pool.
2408 * <p>If the value isn't set, the timeout defaults to the system wide timeout
2409 *
2410 * @return timeout in milliseconds or -1 if the value wasn't set.
2411 */
2412 public long getIdleConnectionTimeout() {
2413 return mIdleConnectionTimeout;
2414 }
2415
2416 /**
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002417 * Returns <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>.
2418 * This journal mode will only be used if {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING}
2419 * flag is not set, otherwise a platform will use "WAL" journal mode.
2420 * @see Builder#setJournalMode(String)
2421 */
2422 @Nullable
2423 public String getJournalMode() {
2424 return mJournalMode;
2425 }
2426
2427 /**
2428 * Returns <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>.
Fyodor Kupolov8ba20892018-06-01 12:11:42 -07002429 * If not set, a system wide default will be used.
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002430 * @see Builder#setSynchronousMode(String)
2431 */
2432 @Nullable
2433 public String getSynchronousMode() {
2434 return mSyncMode;
2435 }
2436
2437 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002438 * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with
2439 * {@code this} parameters.
2440 * @hide
2441 */
2442 @NonNull
2443 public Builder toBuilder() {
2444 return new Builder(this);
2445 }
2446
2447 /**
2448 * Builder for {@link OpenParams}.
2449 */
2450 public static final class Builder {
2451 private int mLookasideSlotSize = -1;
2452 private int mLookasideSlotCount = -1;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002453 private long mIdleConnectionTimeout = -1;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002454 private int mOpenFlags;
2455 private CursorFactory mCursorFactory;
2456 private DatabaseErrorHandler mErrorHandler;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002457 private String mJournalMode;
2458 private String mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002459
2460 public Builder() {
2461 }
2462
2463 public Builder(OpenParams params) {
2464 mLookasideSlotSize = params.mLookasideSlotSize;
2465 mLookasideSlotCount = params.mLookasideSlotCount;
2466 mOpenFlags = params.mOpenFlags;
2467 mCursorFactory = params.mCursorFactory;
2468 mErrorHandler = params.mErrorHandler;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002469 mJournalMode = params.mJournalMode;
2470 mSyncMode = params.mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002471 }
2472
2473 /**
2474 * Configures
2475 * <a href="https://sqlite.org/malloc.html#lookaside">lookaside memory allocator</a>
2476 *
2477 * <p>SQLite default settings will be used, if this method isn't called.
2478 * Use {@code setLookasideConfig(0,0)} to disable lookaside
2479 *
Fyodor Kupolov05a0f0f2017-06-30 19:00:00 -07002480 * <p><strong>Note:</strong> Provided slotSize/slotCount configuration is just a
2481 * recommendation. The system may choose different values depending on a device, e.g.
2482 * lookaside allocations can be disabled on low-RAM devices
2483 *
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002484 * @param slotSize The size in bytes of each lookaside slot.
2485 * @param slotCount The total number of lookaside memory slots per database connection.
2486 */
2487 public Builder setLookasideConfig(@IntRange(from = 0) final int slotSize,
2488 @IntRange(from = 0) final int slotCount) {
2489 Preconditions.checkArgument(slotSize >= 0,
2490 "lookasideSlotCount cannot be negative");
2491 Preconditions.checkArgument(slotCount >= 0,
2492 "lookasideSlotSize cannot be negative");
2493 Preconditions.checkArgument(
2494 (slotSize > 0 && slotCount > 0) || (slotCount == 0 && slotSize == 0),
2495 "Invalid configuration: " + slotSize + ", " + slotCount);
2496
2497 mLookasideSlotSize = slotSize;
2498 mLookasideSlotCount = slotCount;
2499 return this;
2500 }
2501
2502 /**
2503 * Returns true if {@link #ENABLE_WRITE_AHEAD_LOGGING} flag is set
2504 * @hide
2505 */
2506 public boolean isWriteAheadLoggingEnabled() {
2507 return (mOpenFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2508 }
2509
2510 /**
2511 * Sets flags to control database access mode
2512 * @param openFlags The new flags to set
2513 * @see #OPEN_READWRITE
2514 * @see #OPEN_READONLY
2515 * @see #CREATE_IF_NECESSARY
2516 * @see #NO_LOCALIZED_COLLATORS
2517 * @see #ENABLE_WRITE_AHEAD_LOGGING
2518 * @return same builder instance for chaining multiple calls into a single statement
2519 */
2520 @NonNull
2521 public Builder setOpenFlags(@DatabaseOpenFlags int openFlags) {
2522 mOpenFlags = openFlags;
2523 return this;
2524 }
2525
2526 /**
2527 * Adds flags to control database access mode
2528 *
2529 * @param openFlags The new flags to add
2530 * @return same builder instance for chaining multiple calls into a single statement
2531 */
2532 @NonNull
2533 public Builder addOpenFlags(@DatabaseOpenFlags int openFlags) {
2534 mOpenFlags |= openFlags;
2535 return this;
2536 }
2537
2538 /**
2539 * Removes database access mode flags
2540 *
2541 * @param openFlags Flags to remove
2542 * @return same builder instance for chaining multiple calls into a single statement
2543 */
2544 @NonNull
2545 public Builder removeOpenFlags(@DatabaseOpenFlags int openFlags) {
2546 mOpenFlags &= ~openFlags;
2547 return this;
2548 }
2549
2550 /**
2551 * Sets {@link #ENABLE_WRITE_AHEAD_LOGGING} flag if {@code enabled} is {@code true},
2552 * unsets otherwise
2553 * @hide
2554 */
2555 public void setWriteAheadLoggingEnabled(boolean enabled) {
2556 if (enabled) {
2557 addOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2558 } else {
2559 removeOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2560 }
2561 }
2562
2563 /**
2564 * Set an optional factory class that is called to instantiate a cursor when query
2565 * is called.
2566 *
2567 * @param cursorFactory instance
2568 * @return same builder instance for chaining multiple calls into a single statement
2569 */
2570 @NonNull
2571 public Builder setCursorFactory(@Nullable CursorFactory cursorFactory) {
2572 mCursorFactory = cursorFactory;
2573 return this;
2574 }
2575
2576
2577 /**
2578 * Sets {@link DatabaseErrorHandler} object to handle db corruption errors
2579 */
2580 @NonNull
2581 public Builder setErrorHandler(@Nullable DatabaseErrorHandler errorHandler) {
2582 mErrorHandler = errorHandler;
2583 return this;
2584 }
2585
2586 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002587 * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle
2588 * before it is closed and removed from the pool.
2589 *
2590 * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE}
2591 * to allow unlimited idle connections.
2592 */
2593 @NonNull
2594 public Builder setIdleConnectionTimeout(
2595 @IntRange(from = 0) long idleConnectionTimeoutMs) {
2596 Preconditions.checkArgument(idleConnectionTimeoutMs >= 0,
2597 "idle connection timeout cannot be negative");
2598 mIdleConnectionTimeout = idleConnectionTimeoutMs;
2599 return this;
2600 }
2601
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002602
2603 /**
2604 * Sets <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>
2605 * to use when {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag is not set.
2606 */
2607 @NonNull
2608 public Builder setJournalMode(@NonNull String journalMode) {
2609 Preconditions.checkNotNull(journalMode);
2610 mJournalMode = journalMode;
2611 return this;
2612 }
2613
2614 /**
2615 * Sets <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>
Fyodor Kupolov8ba20892018-06-01 12:11:42 -07002616 * .
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002617 * @return
2618 */
2619 @NonNull
2620 public Builder setSynchronousMode(@NonNull String syncMode) {
2621 Preconditions.checkNotNull(syncMode);
2622 mSyncMode = syncMode;
2623 return this;
2624 }
2625
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002626 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002627 * Creates an instance of {@link OpenParams} with the options that were previously set
2628 * on this builder
2629 */
2630 @NonNull
2631 public OpenParams build() {
2632 return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002633 mLookasideSlotCount, mIdleConnectionTimeout, mJournalMode, mSyncMode);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002634 }
2635 }
2636 }
2637
2638 /** @hide */
2639 @IntDef(flag = true, prefix = {"OPEN_", "CREATE_", "NO_", "ENABLE_"}, value = {
2640 OPEN_READWRITE,
2641 OPEN_READONLY,
2642 CREATE_IF_NECESSARY,
2643 NO_LOCALIZED_COLLATORS,
2644 ENABLE_WRITE_AHEAD_LOGGING
2645 })
2646 @Retention(RetentionPolicy.SOURCE)
2647 public @interface DatabaseOpenFlags {}
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002649}
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002650