blob: db991482b2460634a47e6b989e4578343fca7b41 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.database.sqlite;
18
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070019import android.annotation.IntDef;
20import android.annotation.IntRange;
Makoto Onuki17aa1b72015-12-16 14:02:01 -080021import android.annotation.NonNull;
22import android.annotation.Nullable;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070023import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.ContentValues;
25import android.database.Cursor;
Vasu Nori062fc7ce2010-03-31 16:13:05 -070026import android.database.DatabaseErrorHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.database.DatabaseUtils;
Vasu Nori062fc7ce2010-03-31 16:13:05 -070028import android.database.DefaultDatabaseErrorHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.database.SQLException;
Vasu Noric3849202010-03-09 10:47:25 -080030import android.database.sqlite.SQLiteDebug.DbStats;
Jeff Browna7771df2012-05-07 20:06:46 -070031import android.os.CancellationSignal;
Jeff Browne5360fb2011-10-31 17:48:13 -070032import android.os.Looper;
Jeff Browna7771df2012-05-07 20:06:46 -070033import android.os.OperationCanceledException;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070034import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.util.EventLog;
Dmitri Plotnikov90142c92009-09-15 10:52:17 -070037import android.util.Log;
Vasu Noric3849202010-03-09 10:47:25 -080038import android.util.Pair;
Jeff Browne5360fb2011-10-31 17:48:13 -070039import android.util.Printer;
40
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070041import com.android.internal.util.Preconditions;
42
Jeff Browne5360fb2011-10-31 17:48:13 -070043import dalvik.system.CloseGuard;
44
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import java.io.File;
Jeff Brown79087e42012-03-01 19:52:44 -080046import java.io.FileFilter;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070047import java.lang.annotation.Retention;
48import java.lang.annotation.RetentionPolicy;
Vasu Noric3849202010-03-09 10:47:25 -080049import java.util.ArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import java.util.HashMap;
Jesse Wilson9b5a9352011-02-10 11:19:09 -080051import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import java.util.Locale;
53import java.util.Map;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import java.util.WeakHashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055
56/**
57 * Exposes methods to manage a SQLite database.
Jeff Browne5360fb2011-10-31 17:48:13 -070058 *
59 * <p>
60 * SQLiteDatabase has methods to create, delete, execute SQL commands, and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 * perform other common database management tasks.
Jeff Browne5360fb2011-10-31 17:48:13 -070062 * </p><p>
63 * See the Notepad sample application in the SDK for an example of creating
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 * and managing a database.
Jeff Browne5360fb2011-10-31 17:48:13 -070065 * </p><p>
66 * Database names must be unique within an application, not across all applications.
67 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 *
69 * <h3>Localized Collation - ORDER BY</h3>
Jeff Browne5360fb2011-10-31 17:48:13 -070070 * <p>
71 * In addition to SQLite's default <code>BINARY</code> collator, Android supplies
72 * two more, <code>LOCALIZED</code>, which changes with the system's current locale,
73 * and <code>UNICODE</code>, which is the Unicode Collation Algorithm and not tailored
74 * to the current locale.
75 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 */
Jeff Brownbaefdfa2012-03-05 10:33:13 -080077public final class SQLiteDatabase extends SQLiteClosable {
Vasu Norifb16cbd2010-07-25 16:38:48 -070078 private static final String TAG = "SQLiteDatabase";
Jeff Browne5360fb2011-10-31 17:48:13 -070079
Jeff Hamilton082c2af2009-09-29 11:49:51 -070080 private static final int EVENT_DB_CORRUPT = 75004;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081
Fyodor Kupolov535672992017-08-30 18:16:31 -070082 // By default idle connections are not closed
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070083 private static final boolean DEBUG_CLOSE_IDLE_CONNECTIONS = SystemProperties
Fyodor Kupolov535672992017-08-30 18:16:31 -070084 .getBoolean("persist.debug.sqlite.close_idle_connections", false);
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070085
Jeff Browne5360fb2011-10-31 17:48:13 -070086 // Stores reference to all databases opened in the current process.
87 // (The referent Object is not used at this time.)
88 // INVARIANT: Guarded by sActiveDatabases.
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070089 private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases = new WeakHashMap<>();
Jeff Browne5360fb2011-10-31 17:48:13 -070090
91 // Thread-local for database sessions that belong to this database.
92 // Each thread has its own database session.
93 // INVARIANT: Immutable.
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070094 private final ThreadLocal<SQLiteSession> mThreadSession = ThreadLocal
95 .withInitial(this::createSession);
Jeff Browne5360fb2011-10-31 17:48:13 -070096
97 // The optional factory to use when creating new Cursors. May be null.
98 // INVARIANT: Immutable.
99 private final CursorFactory mCursorFactory;
100
101 // Error handler to be used when SQLite returns corruption errors.
102 // INVARIANT: Immutable.
103 private final DatabaseErrorHandler mErrorHandler;
104
105 // Shared database state lock.
106 // This lock guards all of the shared state of the database, such as its
107 // configuration, whether it is open or closed, and so on. This lock should
108 // be held for as little time as possible.
109 //
110 // The lock MUST NOT be held while attempting to acquire database connections or
111 // while executing SQL statements on behalf of the client as it can lead to deadlock.
112 //
113 // It is ok to hold the lock while reconfiguring the connection pool or dumping
114 // statistics because those operations are non-reentrant and do not try to acquire
115 // connections that might be held by other threads.
116 //
117 // Basic rule: grab the lock, access or modify global state, release the lock, then
118 // do the required SQL work.
119 private final Object mLock = new Object();
120
121 // Warns if the database is finalized without being closed properly.
122 // INVARIANT: Guarded by mLock.
123 private final CloseGuard mCloseGuardLocked = CloseGuard.get();
124
125 // The database configuration.
126 // INVARIANT: Guarded by mLock.
127 private final SQLiteDatabaseConfiguration mConfigurationLocked;
128
129 // The connection pool for the database, null when closed.
130 // The pool itself is thread-safe, but the reference to it can only be acquired
131 // when the lock is held.
132 // INVARIANT: Guarded by mLock.
133 private SQLiteConnectionPool mConnectionPoolLocked;
134
135 // True if the database has attached databases.
136 // INVARIANT: Guarded by mLock.
137 private boolean mHasAttachedDbsLocked;
138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700140 * When a constraint violation occurs, an immediate ROLLBACK occurs,
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800141 * thus ending the current transaction, and the command aborts with a
142 * return code of SQLITE_CONSTRAINT. If no transaction is active
143 * (other than the implied transaction that is created on every command)
Jeff Browne5360fb2011-10-31 17:48:13 -0700144 * then this algorithm works the same as ABORT.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800145 */
146 public static final int CONFLICT_ROLLBACK = 1;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700147
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800148 /**
149 * When a constraint violation occurs,no ROLLBACK is executed
150 * so changes from prior commands within the same transaction
151 * are preserved. This is the default behavior.
152 */
153 public static final int CONFLICT_ABORT = 2;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700154
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800155 /**
156 * When a constraint violation occurs, the command aborts with a return
157 * code SQLITE_CONSTRAINT. But any changes to the database that
158 * the command made prior to encountering the constraint violation
159 * are preserved and are not backed out.
160 */
161 public static final int CONFLICT_FAIL = 3;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700162
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800163 /**
164 * When a constraint violation occurs, the one row that contains
165 * the constraint violation is not inserted or changed.
166 * But the command continues executing normally. Other rows before and
167 * after the row that contained the constraint violation continue to be
168 * inserted or updated normally. No error is returned.
169 */
170 public static final int CONFLICT_IGNORE = 4;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700171
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800172 /**
173 * When a UNIQUE constraint violation occurs, the pre-existing rows that
174 * are causing the constraint violation are removed prior to inserting
175 * or updating the current row. Thus the insert or update always occurs.
176 * The command continues executing normally. No error is returned.
177 * If a NOT NULL constraint violation occurs, the NULL value is replaced
178 * by the default value for that column. If the column has no default
179 * value, then the ABORT algorithm is used. If a CHECK constraint
180 * violation occurs then the IGNORE algorithm is used. When this conflict
181 * resolution strategy deletes rows in order to satisfy a constraint,
182 * it does not invoke delete triggers on those rows.
Jeff Browne5360fb2011-10-31 17:48:13 -0700183 * This behavior might change in a future release.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800184 */
185 public static final int CONFLICT_REPLACE = 5;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700186
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800187 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700188 * Use the following when no conflict action is specified.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800189 */
190 public static final int CONFLICT_NONE = 0;
Jeff Browne5360fb2011-10-31 17:48:13 -0700191
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800192 private static final String[] CONFLICT_VALUES = new String[]
193 {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 /**
196 * Maximum Length Of A LIKE Or GLOB Pattern
197 * The pattern matching algorithm used in the default LIKE and GLOB implementation
198 * of SQLite can exhibit O(N^2) performance (where N is the number of characters in
199 * the pattern) for certain pathological cases. To avoid denial-of-service attacks
200 * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes.
201 * The default value of this limit is 50000. A modern workstation can evaluate
202 * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly.
203 * The denial of service problem only comes into play when the pattern length gets
204 * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns
205 * are at most a few dozen bytes in length, paranoid application developers may
206 * want to reduce this parameter to something in the range of a few hundred
207 * if they know that external users are able to generate arbitrary patterns.
208 */
209 public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000;
210
211 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700212 * Open flag: Flag for {@link #openDatabase} to open the database for reading and writing.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 * If the disk is full, this may fail even before you actually write anything.
214 *
215 * {@more} Note that the value of this flag is 0, so it is the default.
216 */
217 public static final int OPEN_READWRITE = 0x00000000; // update native code if changing
218
219 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700220 * Open flag: Flag for {@link #openDatabase} to open the database for reading only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 * This is the only reliable way to open a database if the disk may be full.
222 */
223 public static final int OPEN_READONLY = 0x00000001; // update native code if changing
224
225 private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing
226
227 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700228 * Open flag: Flag for {@link #openDatabase} to open the database without support for
229 * localized collators.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 *
231 * {@more} This causes the collator <code>LOCALIZED</code> not to be created.
232 * You must be consistent when using this flag to use the setting the database was
233 * created with. If this is set, {@link #setLocale} will do nothing.
234 */
235 public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing
236
237 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700238 * Open flag: Flag for {@link #openDatabase} to create the database file if it does not
239 * already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 */
241 public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing
242
243 /**
Jeff Brown47847f32012-03-22 19:13:11 -0700244 * Open flag: Flag for {@link #openDatabase} to open the database file with
245 * write-ahead logging enabled by default. Using this flag is more efficient
246 * than calling {@link #enableWriteAheadLogging}.
247 *
248 * Write-ahead logging cannot be used with read-only databases so the value of
249 * this flag is ignored if the database is opened read-only.
250 *
251 * @see #enableWriteAheadLogging
252 */
253 public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;
254
255 /**
Fyodor Kupolov692573b2018-03-06 12:34:36 -0800256 * Open flag: Flag for {@link #openDatabase} to disable Compatibility WAL when opening database.
257 *
258 * @hide
259 */
260 public static final int DISABLE_COMPATIBILITY_WAL = 0x40000000;
261
262 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700263 * Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}.
Vasu Norib729dcc2010-09-14 11:35:49 -0700264 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700265 * Each prepared-statement is between 1K - 6K, depending on the complexity of the
266 * SQL statement & schema. A large SQL cache may use a significant amount of memory.
Vasu Norie495d1f2010-01-06 16:34:19 -0800267 */
Vasu Nori90a367262010-04-12 12:49:09 -0700268 public static final int MAX_SQL_CACHE_SIZE = 100;
Vasu Norib729dcc2010-09-14 11:35:49 -0700269
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700270 private SQLiteDatabase(final String path, final int openFlags,
271 CursorFactory cursorFactory, DatabaseErrorHandler errorHandler,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800272 int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs,
273 String journalMode, String syncMode) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700274 mCursorFactory = cursorFactory;
275 mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler();
276 mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700277 mConfigurationLocked.lookasideSlotSize = lookasideSlotSize;
278 mConfigurationLocked.lookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700279 // Disable lookaside allocator on low-RAM devices
280 if (ActivityManager.isLowRamDeviceStatic()) {
281 mConfigurationLocked.lookasideSlotCount = 0;
282 mConfigurationLocked.lookasideSlotSize = 0;
283 }
284 long effectiveTimeoutMs = Long.MAX_VALUE;
285 // Never close idle connections for in-memory databases
286 if (!mConfigurationLocked.isInMemoryDb()) {
287 // First, check app-specific value. Otherwise use defaults
288 // -1 in idleConnectionTimeoutMs indicates unset value
289 if (idleConnectionTimeoutMs >= 0) {
290 effectiveTimeoutMs = idleConnectionTimeoutMs;
291 } else if (DEBUG_CLOSE_IDLE_CONNECTIONS) {
292 effectiveTimeoutMs = SQLiteGlobal.getIdleConnectionTimeout();
293 }
294 }
295 mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800296 mConfigurationLocked.journalMode = journalMode;
297 mConfigurationLocked.syncMode = syncMode;
Fyodor Kupolov692573b2018-03-06 12:34:36 -0800298 if (!SQLiteGlobal.isCompatibilityWalSupported() || (
299 SQLiteCompatibilityWalFlags.areFlagsSet() && !SQLiteCompatibilityWalFlags
300 .isCompatibilityWalSupported())) {
301 mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
Fyodor Kupolovee90c032017-12-12 11:52:57 -0800302 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700304
Jeff Browne5360fb2011-10-31 17:48:13 -0700305 @Override
306 protected void finalize() throws Throwable {
307 try {
308 dispose(true);
309 } finally {
310 super.finalize();
311 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700312 }
313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 @Override
315 protected void onAllReferencesReleased() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700316 dispose(false);
317 }
318
319 private void dispose(boolean finalized) {
320 final SQLiteConnectionPool pool;
321 synchronized (mLock) {
322 if (mCloseGuardLocked != null) {
323 if (finalized) {
324 mCloseGuardLocked.warnIfOpen();
325 }
326 mCloseGuardLocked.close();
327 }
328
329 pool = mConnectionPoolLocked;
330 mConnectionPoolLocked = null;
331 }
332
333 if (!finalized) {
334 synchronized (sActiveDatabases) {
335 sActiveDatabases.remove(this);
336 }
337
338 if (pool != null) {
339 pool.close();
340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 }
342 }
343
344 /**
345 * Attempts to release memory that SQLite holds but does not require to
346 * operate properly. Typically this memory will come from the page cache.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700347 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 * @return the number of bytes actually released
349 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700350 public static int releaseMemory() {
351 return SQLiteGlobal.releaseMemory();
352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353
354 /**
355 * Control whether or not the SQLiteDatabase is made thread-safe by using locks
356 * around critical sections. This is pretty expensive, so if you know that your
357 * DB will only be used by a single thread then you should set this to false.
358 * The default is true.
359 * @param lockingEnabled set to true to enable locks, false otherwise
Jeff Browne5360fb2011-10-31 17:48:13 -0700360 *
361 * @deprecated This method now does nothing. Do not use.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700363 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 public void setLockingEnabled(boolean lockingEnabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 }
366
367 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700368 * Gets a label to use when describing the database in log messages.
369 * @return The label.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700371 String getLabel() {
372 synchronized (mLock) {
373 return mConfigurationLocked.label;
374 }
375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376
Jeff Browne5360fb2011-10-31 17:48:13 -0700377 /**
378 * Sends a corruption message to the database error handler.
379 */
380 void onCorruption() {
381 EventLog.writeEvent(EVENT_DB_CORRUPT, getLabel());
Vasu Noriccd95442010-05-28 17:04:16 -0700382 mErrorHandler.onCorruption(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 }
384
385 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700386 * Gets the {@link SQLiteSession} that belongs to this thread for this database.
387 * Once a thread has obtained a session, it will continue to obtain the same
388 * session even after the database has been closed (although the session will not
389 * be usable). However, a thread that does not already have a session cannot
390 * obtain one after the database has been closed.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700391 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700392 * The idea is that threads that have active connections to the database may still
393 * have work to complete even after the call to {@link #close}. Active database
394 * connections are not actually disposed until they are released by the threads
395 * that own them.
396 *
397 * @return The session, never null.
398 *
399 * @throws IllegalStateException if the thread does not yet have a session and
400 * the database is not open.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700402 SQLiteSession getThreadSession() {
403 return mThreadSession.get(); // initialValue() throws if database closed
Vasu Nori6d970252010-10-05 10:48:49 -0700404 }
Vasu Nori16057fa2011-03-18 11:40:37 -0700405
Jeff Browne5360fb2011-10-31 17:48:13 -0700406 SQLiteSession createSession() {
407 final SQLiteConnectionPool pool;
408 synchronized (mLock) {
409 throwIfNotOpenLocked();
410 pool = mConnectionPoolLocked;
Vasu Nori6d970252010-10-05 10:48:49 -0700411 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700412 return new SQLiteSession(pool);
Vasu Norid4608a32011-02-03 16:24:06 -0800413 }
414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700416 * Gets default connection flags that are appropriate for this thread, taking into
417 * account whether the thread is acting on behalf of the UI.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700419 * @param readOnly True if the connection should be read-only.
420 * @return The connection flags.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700422 int getThreadDefaultConnectionFlags(boolean readOnly) {
423 int flags = readOnly ? SQLiteConnectionPool.CONNECTION_FLAG_READ_ONLY :
424 SQLiteConnectionPool.CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY;
425 if (isMainThread()) {
426 flags |= SQLiteConnectionPool.CONNECTION_FLAG_INTERACTIVE;
427 }
428 return flags;
Vasu Nori16057fa2011-03-18 11:40:37 -0700429 }
430
Jeff Browne5360fb2011-10-31 17:48:13 -0700431 private static boolean isMainThread() {
432 // FIXME: There should be a better way to do this.
433 // Would also be nice to have something that would work across Binder calls.
434 Looper looper = Looper.myLooper();
435 return looper != null && looper == Looper.getMainLooper();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 }
437
438 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700439 * Begins a transaction in EXCLUSIVE mode.
440 * <p>
441 * Transactions can be nested.
442 * When the outer transaction is ended all of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 * the work done in that transaction and all of the nested transactions will be committed or
444 * rolled back. The changes will be rolled back if any transaction is ended without being
445 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700446 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 * <p>Here is the standard idiom for transactions:
448 *
449 * <pre>
450 * db.beginTransaction();
451 * try {
452 * ...
453 * db.setTransactionSuccessful();
454 * } finally {
455 * db.endTransaction();
456 * }
457 * </pre>
458 */
459 public void beginTransaction() {
Vasu Nori6c354da2010-04-26 23:33:39 -0700460 beginTransaction(null /* transactionStatusCallback */, true);
461 }
462
463 /**
464 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
465 * the outer transaction is ended all of the work done in that transaction
466 * and all of the nested transactions will be committed or rolled back. The
467 * changes will be rolled back if any transaction is ended without being
468 * marked as clean (by calling setTransactionSuccessful). Otherwise they
469 * will be committed.
470 * <p>
471 * Here is the standard idiom for transactions:
472 *
473 * <pre>
474 * db.beginTransactionNonExclusive();
475 * try {
476 * ...
477 * db.setTransactionSuccessful();
478 * } finally {
479 * db.endTransaction();
480 * }
481 * </pre>
482 */
483 public void beginTransactionNonExclusive() {
484 beginTransaction(null /* transactionStatusCallback */, false);
Fred Quintanac4516a72009-09-03 12:14:06 -0700485 }
486
487 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700488 * Begins a transaction in EXCLUSIVE mode.
489 * <p>
490 * Transactions can be nested.
491 * When the outer transaction is ended all of
Fred Quintanac4516a72009-09-03 12:14:06 -0700492 * the work done in that transaction and all of the nested transactions will be committed or
493 * rolled back. The changes will be rolled back if any transaction is ended without being
494 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700495 * </p>
Fred Quintanac4516a72009-09-03 12:14:06 -0700496 * <p>Here is the standard idiom for transactions:
497 *
498 * <pre>
499 * db.beginTransactionWithListener(listener);
500 * try {
501 * ...
502 * db.setTransactionSuccessful();
503 * } finally {
504 * db.endTransaction();
505 * }
506 * </pre>
Vasu Noriccd95442010-05-28 17:04:16 -0700507 *
Fred Quintanac4516a72009-09-03 12:14:06 -0700508 * @param transactionListener listener that should be notified when the transaction begins,
509 * commits, or is rolled back, either explicitly or by a call to
510 * {@link #yieldIfContendedSafely}.
511 */
512 public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
Vasu Nori6c354da2010-04-26 23:33:39 -0700513 beginTransaction(transactionListener, true);
514 }
515
516 /**
517 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
518 * the outer transaction is ended all of the work done in that transaction
519 * and all of the nested transactions will be committed or rolled back. The
520 * changes will be rolled back if any transaction is ended without being
521 * marked as clean (by calling setTransactionSuccessful). Otherwise they
522 * will be committed.
523 * <p>
524 * Here is the standard idiom for transactions:
525 *
526 * <pre>
527 * db.beginTransactionWithListenerNonExclusive(listener);
528 * try {
529 * ...
530 * db.setTransactionSuccessful();
531 * } finally {
532 * db.endTransaction();
533 * }
534 * </pre>
535 *
536 * @param transactionListener listener that should be notified when the
537 * transaction begins, commits, or is rolled back, either
538 * explicitly or by a call to {@link #yieldIfContendedSafely}.
539 */
540 public void beginTransactionWithListenerNonExclusive(
541 SQLiteTransactionListener transactionListener) {
542 beginTransaction(transactionListener, false);
543 }
544
545 private void beginTransaction(SQLiteTransactionListener transactionListener,
546 boolean exclusive) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800547 acquireReference();
548 try {
549 getThreadSession().beginTransaction(
550 exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
551 SQLiteSession.TRANSACTION_MODE_IMMEDIATE,
552 transactionListener,
553 getThreadDefaultConnectionFlags(false /*readOnly*/), null);
554 } finally {
555 releaseReference();
556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 }
558
559 /**
560 * End a transaction. See beginTransaction for notes about how to use this and when transactions
561 * are committed and rolled back.
562 */
563 public void endTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800564 acquireReference();
565 try {
566 getThreadSession().endTransaction(null);
567 } finally {
568 releaseReference();
569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 }
571
572 /**
573 * Marks the current transaction as successful. Do not do any more database work between
574 * calling this and calling endTransaction. Do as little non-database work as possible in that
575 * situation too. If any errors are encountered between this and endTransaction the transaction
576 * will still be committed.
577 *
578 * @throws IllegalStateException if the current thread is not in a transaction or the
579 * transaction is already marked as successful.
580 */
581 public void setTransactionSuccessful() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800582 acquireReference();
583 try {
584 getThreadSession().setTransactionSuccessful();
585 } finally {
586 releaseReference();
587 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800588 }
589
590 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700591 * Returns true if the current thread has a transaction pending.
592 *
593 * @return True if the current thread is in a transaction.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 */
595 public boolean inTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800596 acquireReference();
597 try {
598 return getThreadSession().hasTransaction();
599 } finally {
600 releaseReference();
601 }
Vasu Norice38b982010-07-22 13:57:13 -0700602 }
603
604 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700605 * Returns true if the current thread is holding an active connection to the database.
Vasu Norice38b982010-07-22 13:57:13 -0700606 * <p>
Jeff Browne5360fb2011-10-31 17:48:13 -0700607 * The name of this method comes from a time when having an active connection
608 * to the database meant that the thread was holding an actual lock on the
609 * database. Nowadays, there is no longer a true "database lock" although threads
610 * may block if they cannot acquire a database connection to perform a
611 * particular operation.
612 * </p>
Vasu Norice38b982010-07-22 13:57:13 -0700613 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700614 * @return True if the current thread is holding an active connection to the database.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615 */
616 public boolean isDbLockedByCurrentThread() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800617 acquireReference();
618 try {
619 return getThreadSession().hasConnection();
620 } finally {
621 releaseReference();
622 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 }
624
625 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700626 * Always returns false.
627 * <p>
628 * There is no longer the concept of a database lock, so this method always returns false.
629 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700631 * @return False.
632 * @deprecated Always returns false. Do not use this method.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700634 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800635 public boolean isDbLockedByOtherThreads() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700636 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637 }
638
639 /**
640 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
641 * successful so far. Do not call setTransactionSuccessful before calling this. When this
642 * returns a new transaction will have been created but not marked as successful.
643 * @return true if the transaction was yielded
kopriva7364c112018-09-27 11:02:07 -0700644 * @deprecated if the db is locked more than once (because of nested transactions) then the lock
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 * will not be yielded. Use yieldIfContendedSafely instead.
646 */
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700647 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648 public boolean yieldIfContended() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700649 return yieldIfContendedHelper(false /* do not check yielding */,
650 -1 /* sleepAfterYieldDelay */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800651 }
652
653 /**
654 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
655 * successful so far. Do not call setTransactionSuccessful before calling this. When this
656 * returns a new transaction will have been created but not marked as successful. This assumes
657 * that there are no nested transactions (beginTransaction has only been called once) and will
Fred Quintana5c7aede2009-08-27 21:41:27 -0700658 * throw an exception if that is not the case.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 * @return true if the transaction was yielded
660 */
661 public boolean yieldIfContendedSafely() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700662 return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663 }
664
Fred Quintana5c7aede2009-08-27 21:41:27 -0700665 /**
666 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
667 * successful so far. Do not call setTransactionSuccessful before calling this. When this
668 * returns a new transaction will have been created but not marked as successful. This assumes
669 * that there are no nested transactions (beginTransaction has only been called once) and will
670 * throw an exception if that is not the case.
671 * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if
672 * the lock was actually yielded. This will allow other background threads to make some
673 * more progress than they would if we started the transaction immediately.
674 * @return true if the transaction was yielded
675 */
676 public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
677 return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay);
678 }
679
Jeff Browne5360fb2011-10-31 17:48:13 -0700680 private boolean yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800681 acquireReference();
682 try {
683 return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null);
684 } finally {
685 releaseReference();
686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800687 }
688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700690 * Deprecated.
Vasu Nori95675132010-07-21 16:24:40 -0700691 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692 */
Vasu Nori95675132010-07-21 16:24:40 -0700693 @Deprecated
694 public Map<String, String> getSyncedTables() {
695 return new HashMap<String, String>(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696 }
697
698 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800699 * Open the database according to the flags {@link #OPEN_READWRITE}
700 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
701 *
702 * <p>Sets the locale of the database to the the system's current locale.
703 * Call {@link #setLocale} if you would like something else.</p>
704 *
705 * @param path to database file to open and/or create
706 * @param factory an optional factory class that is called to instantiate a
707 * cursor when query is called, or null for default
708 * @param flags to control database access mode
709 * @return the newly opened database
710 * @throws SQLiteException if the database cannot be opened
711 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700712 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
713 @DatabaseOpenFlags int flags) {
Jeff Brown47847f32012-03-22 19:13:11 -0700714 return openDatabase(path, factory, flags, null);
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700715 }
716
717 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700718 * Open the database according to the specified {@link OpenParams parameters}
719 *
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700720 * @param path path to database file to open and/or create.
721 * <p><strong>Important:</strong> The file should be constructed either from an absolute path or
722 * by using {@link android.content.Context#getDatabasePath(String)}.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700723 * @param openParams configuration parameters that are used for opening {@link SQLiteDatabase}
724 * @return the newly opened database
725 * @throws SQLiteException if the database cannot be opened
726 */
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700727 public static SQLiteDatabase openDatabase(@NonNull File path,
728 @NonNull OpenParams openParams) {
729 return openDatabase(path.getPath(), openParams);
730 }
731
732 private static SQLiteDatabase openDatabase(@NonNull String path,
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700733 @NonNull OpenParams openParams) {
734 Preconditions.checkArgument(openParams != null, "OpenParams cannot be null");
735 SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags,
736 openParams.mCursorFactory, openParams.mErrorHandler,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700737 openParams.mLookasideSlotSize, openParams.mLookasideSlotCount,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800738 openParams.mIdleConnectionTimeout, openParams.mJournalMode, openParams.mSyncMode);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700739 db.open();
740 return db;
741 }
742
743 /**
Vasu Nori74f170f2010-06-01 18:06:18 -0700744 * Open the database according to the flags {@link #OPEN_READWRITE}
745 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
746 *
747 * <p>Sets the locale of the database to the the system's current locale.
748 * Call {@link #setLocale} if you would like something else.</p>
749 *
750 * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be
751 * used to handle corruption when sqlite reports database corruption.</p>
752 *
753 * @param path to database file to open and/or create
754 * @param factory an optional factory class that is called to instantiate a
755 * cursor when query is called, or null for default
756 * @param flags to control database access mode
757 * @param errorHandler the {@link DatabaseErrorHandler} obj to be used to handle corruption
758 * when sqlite reports database corruption
759 * @return the newly opened database
760 * @throws SQLiteException if the database cannot be opened
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700761 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700762 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
763 @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler) {
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800764 SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1, -1, null,
765 null);
Jeff Browne5360fb2011-10-31 17:48:13 -0700766 db.open();
767 return db;
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700768 }
769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770 /**
771 * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
772 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700773 public static SQLiteDatabase openOrCreateDatabase(@NonNull File file,
774 @Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775 return openOrCreateDatabase(file.getPath(), factory);
776 }
777
778 /**
779 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
780 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700781 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
782 @Nullable CursorFactory factory) {
Jeff Brown47847f32012-03-22 19:13:11 -0700783 return openDatabase(path, factory, CREATE_IF_NECESSARY, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 }
785
786 /**
Vasu Nori6c354da2010-04-26 23:33:39 -0700787 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler).
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700788 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700789 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
790 @Nullable CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler) {
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700791 return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler);
792 }
793
Jeff Brown559d0642012-02-29 10:19:12 -0800794 /**
Jeff Brown79087e42012-03-01 19:52:44 -0800795 * Deletes a database including its journal file and other auxiliary files
796 * that may have been created by the database engine.
797 *
798 * @param file The database file path.
799 * @return True if the database was successfully deleted.
800 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700801 public static boolean deleteDatabase(@NonNull File file) {
Jeff Brown79087e42012-03-01 19:52:44 -0800802 if (file == null) {
803 throw new IllegalArgumentException("file must not be null");
804 }
805
806 boolean deleted = false;
807 deleted |= file.delete();
808 deleted |= new File(file.getPath() + "-journal").delete();
809 deleted |= new File(file.getPath() + "-shm").delete();
810 deleted |= new File(file.getPath() + "-wal").delete();
811
812 File dir = file.getParentFile();
813 if (dir != null) {
814 final String prefix = file.getName() + "-mj";
Jeff Brownfce58902014-01-24 13:20:57 -0800815 File[] files = dir.listFiles(new FileFilter() {
Jeff Brown79087e42012-03-01 19:52:44 -0800816 @Override
817 public boolean accept(File candidate) {
818 return candidate.getName().startsWith(prefix);
819 }
Jeff Brownfce58902014-01-24 13:20:57 -0800820 });
821 if (files != null) {
822 for (File masterJournal : files) {
823 deleted |= masterJournal.delete();
824 }
Jeff Brown79087e42012-03-01 19:52:44 -0800825 }
826 }
827 return deleted;
828 }
829
830 /**
Jeff Brown559d0642012-02-29 10:19:12 -0800831 * Reopens the database in read-write mode.
832 * If the database is already read-write, does nothing.
833 *
834 * @throws SQLiteException if the database could not be reopened as requested, in which
835 * case it remains open in read only mode.
836 * @throws IllegalStateException if the database is not open.
837 *
838 * @see #isReadOnly()
839 * @hide
840 */
841 public void reopenReadWrite() {
842 synchronized (mLock) {
843 throwIfNotOpenLocked();
844
845 if (!isReadOnlyLocked()) {
846 return; // nothing to do
847 }
848
849 // Reopen the database in read-write mode.
850 final int oldOpenFlags = mConfigurationLocked.openFlags;
851 mConfigurationLocked.openFlags = (mConfigurationLocked.openFlags & ~OPEN_READ_MASK)
852 | OPEN_READWRITE;
853 try {
854 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
855 } catch (RuntimeException ex) {
856 mConfigurationLocked.openFlags = oldOpenFlags;
857 throw ex;
858 }
859 }
860 }
861
Jeff Browne5360fb2011-10-31 17:48:13 -0700862 private void open() {
863 try {
864 try {
865 openInner();
866 } catch (SQLiteDatabaseCorruptException ex) {
867 onCorruption();
868 openInner();
869 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700870 } catch (SQLiteException ex) {
871 Log.e(TAG, "Failed to open database '" + getLabel() + "'.", ex);
872 close();
873 throw ex;
874 }
875 }
876
877 private void openInner() {
878 synchronized (mLock) {
879 assert mConnectionPoolLocked == null;
880 mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked);
881 mCloseGuardLocked.open("close");
882 }
883
884 synchronized (sActiveDatabases) {
885 sActiveDatabases.put(this, null);
886 }
887 }
888
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700889 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 * Create a memory backed SQLite database. Its contents will be destroyed
891 * when the database is closed.
892 *
893 * <p>Sets the locale of the database to the the system's current locale.
894 * Call {@link #setLocale} if you would like something else.</p>
895 *
896 * @param factory an optional factory class that is called to instantiate a
897 * cursor when query is called
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700898 * @return a SQLiteDatabase instance
899 * @throws SQLiteException if the database cannot be created
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700901 @NonNull
902 public static SQLiteDatabase create(@Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903 // This is a magic string with special meaning for SQLite.
Jeff Browne5360fb2011-10-31 17:48:13 -0700904 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
905 factory, CREATE_IF_NECESSARY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 }
907
908 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700909 * Create a memory backed SQLite database. Its contents will be destroyed
910 * when the database is closed.
911 *
912 * <p>Sets the locale of the database to the the system's current locale.
913 * Call {@link #setLocale} if you would like something else.</p>
914 * @param openParams configuration parameters that are used for opening SQLiteDatabase
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700915 * @return a SQLiteDatabase instance
916 * @throws SQLException if the database cannot be created
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700917 */
918 @NonNull
919 public static SQLiteDatabase createInMemory(@NonNull OpenParams openParams) {
920 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
921 openParams.toBuilder().addOpenFlags(CREATE_IF_NECESSARY).build());
922 }
923
924 /**
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400925 * Registers a CustomFunction callback as a function that can be called from
Jeff Browne5360fb2011-10-31 17:48:13 -0700926 * SQLite database triggers.
927 *
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400928 * @param name the name of the sqlite3 function
929 * @param numArgs the number of arguments for the function
930 * @param function callback to call when the function is executed
931 * @hide
932 */
933 public void addCustomFunction(String name, int numArgs, CustomFunction function) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700934 // Create wrapper (also validates arguments).
935 SQLiteCustomFunction wrapper = new SQLiteCustomFunction(name, numArgs, function);
936
937 synchronized (mLock) {
938 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -0700939
Jeff Browne5360fb2011-10-31 17:48:13 -0700940 mConfigurationLocked.customFunctions.add(wrapper);
Jeff Browne67ca422012-03-21 17:24:05 -0700941 try {
942 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
943 } catch (RuntimeException ex) {
944 mConfigurationLocked.customFunctions.remove(wrapper);
945 throw ex;
946 }
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400947 }
948 }
949
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400950 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800951 * Gets the database version.
952 *
953 * @return the database version
954 */
955 public int getVersion() {
Vasu Noriccd95442010-05-28 17:04:16 -0700956 return ((Long) DatabaseUtils.longForQuery(this, "PRAGMA user_version;", null)).intValue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 }
958
959 /**
960 * Sets the database version.
961 *
962 * @param version the new database version
963 */
964 public void setVersion(int version) {
965 execSQL("PRAGMA user_version = " + version);
966 }
967
968 /**
969 * Returns the maximum size the database may grow to.
970 *
971 * @return the new maximum database size
972 */
973 public long getMaximumSize() {
Vasu Noriccd95442010-05-28 17:04:16 -0700974 long pageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count;", null);
975 return pageCount * getPageSize();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800976 }
977
978 /**
979 * Sets the maximum size the database will grow to. The maximum size cannot
980 * be set below the current size.
981 *
982 * @param numBytes the maximum database size, in bytes
983 * @return the new maximum database size
984 */
985 public long setMaximumSize(long numBytes) {
Vasu Noriccd95442010-05-28 17:04:16 -0700986 long pageSize = getPageSize();
987 long numPages = numBytes / pageSize;
988 // If numBytes isn't a multiple of pageSize, bump up a page
989 if ((numBytes % pageSize) != 0) {
990 numPages++;
Vasu Norif3cf8a42010-03-23 11:41:44 -0700991 }
Vasu Noriccd95442010-05-28 17:04:16 -0700992 long newPageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count = " + numPages,
993 null);
994 return newPageCount * pageSize;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 }
996
997 /**
998 * Returns the current database page size, in bytes.
999 *
1000 * @return the database page size, in bytes
1001 */
1002 public long getPageSize() {
Vasu Noriccd95442010-05-28 17:04:16 -07001003 return DatabaseUtils.longForQuery(this, "PRAGMA page_size;", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 }
1005
1006 /**
1007 * Sets the database page size. The page size must be a power of two. This
1008 * method does not work if any data has been written to the database file,
1009 * and must be called right after the database has been created.
1010 *
1011 * @param numBytes the database page size, in bytes
1012 */
1013 public void setPageSize(long numBytes) {
1014 execSQL("PRAGMA page_size = " + numBytes);
1015 }
1016
1017 /**
1018 * Mark this table as syncable. When an update occurs in this table the
1019 * _sync_dirty field will be set to ensure proper syncing operation.
1020 *
1021 * @param table the table to mark as syncable
1022 * @param deletedTable The deleted table that corresponds to the
1023 * syncable table
Vasu Nori95675132010-07-21 16:24:40 -07001024 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 */
Vasu Nori95675132010-07-21 16:24:40 -07001026 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027 public void markTableSyncable(String table, String deletedTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001028 }
1029
1030 /**
1031 * Mark this table as syncable, with the _sync_dirty residing in another
1032 * table. When an update occurs in this table the _sync_dirty field of the
1033 * row in updateTable with the _id in foreignKey will be set to
1034 * ensure proper syncing operation.
1035 *
1036 * @param table an update on this table will trigger a sync time removal
1037 * @param foreignKey this is the column in table whose value is an _id in
1038 * updateTable
1039 * @param updateTable this is the table that will have its _sync_dirty
Vasu Nori95675132010-07-21 16:24:40 -07001040 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 */
Vasu Nori95675132010-07-21 16:24:40 -07001042 @Deprecated
1043 public void markTableSyncable(String table, String foreignKey, String updateTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 }
1045
1046 /**
1047 * Finds the name of the first table, which is editable.
1048 *
1049 * @param tables a list of tables
1050 * @return the first table listed
1051 */
1052 public static String findEditTable(String tables) {
1053 if (!TextUtils.isEmpty(tables)) {
1054 // find the first word terminated by either a space or a comma
1055 int spacepos = tables.indexOf(' ');
1056 int commapos = tables.indexOf(',');
1057
1058 if (spacepos > 0 && (spacepos < commapos || commapos < 0)) {
1059 return tables.substring(0, spacepos);
1060 } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) {
1061 return tables.substring(0, commapos);
1062 }
1063 return tables;
1064 } else {
1065 throw new IllegalStateException("Invalid tables");
1066 }
1067 }
1068
1069 /**
1070 * Compiles an SQL statement into a reusable pre-compiled statement object.
1071 * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the
1072 * statement and fill in those values with {@link SQLiteProgram#bindString}
1073 * and {@link SQLiteProgram#bindLong} each time you want to run the
1074 * statement. Statements may not return result sets larger than 1x1.
Vasu Nori2827d6d2010-07-04 00:26:18 -07001075 *<p>
1076 * No two threads should be using the same {@link SQLiteStatement} at the same time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 *
1078 * @param sql The raw SQL statement, may contain ? for unknown values to be
1079 * bound later.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001080 * @return A pre-compiled {@link SQLiteStatement} object. Note that
1081 * {@link SQLiteStatement}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 */
1083 public SQLiteStatement compileStatement(String sql) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001084 acquireReference();
1085 try {
1086 return new SQLiteStatement(this, sql, null);
1087 } finally {
1088 releaseReference();
1089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 }
1091
1092 /**
1093 * Query the given URL, returning a {@link Cursor} over the result set.
1094 *
1095 * @param distinct true if you want each row to be unique, false otherwise.
1096 * @param table The table name to compile the query against.
1097 * @param columns A list of which columns to return. Passing null will
1098 * return all columns, which is discouraged to prevent reading
1099 * data from storage that isn't going to be used.
1100 * @param selection A filter declaring which rows to return, formatted as an
1101 * SQL WHERE clause (excluding the WHERE itself). Passing null
1102 * will return all rows for the given table.
1103 * @param selectionArgs You may include ?s in selection, which will be
1104 * replaced by the values from selectionArgs, in order that they
1105 * appear in the selection. The values will be bound as Strings.
1106 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1107 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1108 * will cause the rows to not be grouped.
1109 * @param having A filter declare which row groups to include in the cursor,
1110 * if row grouping is being used, formatted as an SQL HAVING
1111 * clause (excluding the HAVING itself). Passing null will cause
1112 * all row groups to be included, and is required when row
1113 * grouping is not being used.
1114 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1115 * (excluding the ORDER BY itself). Passing null will use the
1116 * default sort order, which may be unordered.
1117 * @param limit Limits the number of rows returned by the query,
1118 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001119 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1120 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 * @see Cursor
1122 */
1123 public Cursor query(boolean distinct, String table, String[] columns,
1124 String selection, String[] selectionArgs, String groupBy,
1125 String having, String orderBy, String limit) {
1126 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown75ea64f2012-01-25 19:37:13 -08001127 groupBy, having, orderBy, limit, null);
1128 }
1129
1130 /**
1131 * Query the given URL, returning a {@link Cursor} over the result set.
1132 *
1133 * @param distinct true if you want each row to be unique, false otherwise.
1134 * @param table The table name to compile the query against.
1135 * @param columns A list of which columns to return. Passing null will
1136 * return all columns, which is discouraged to prevent reading
1137 * data from storage that isn't going to be used.
1138 * @param selection A filter declaring which rows to return, formatted as an
1139 * SQL WHERE clause (excluding the WHERE itself). Passing null
1140 * will return all rows for the given table.
1141 * @param selectionArgs You may include ?s in selection, which will be
1142 * replaced by the values from selectionArgs, in order that they
1143 * appear in the selection. The values will be bound as Strings.
1144 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1145 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1146 * will cause the rows to not be grouped.
1147 * @param having A filter declare which row groups to include in the cursor,
1148 * if row grouping is being used, formatted as an SQL HAVING
1149 * clause (excluding the HAVING itself). Passing null will cause
1150 * all row groups to be included, and is required when row
1151 * grouping is not being used.
1152 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1153 * (excluding the ORDER BY itself). Passing null will use the
1154 * default sort order, which may be unordered.
1155 * @param limit Limits the number of rows returned by the query,
1156 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001157 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001158 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1159 * when the query is executed.
1160 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1161 * {@link Cursor}s are not synchronized, see the documentation for more details.
1162 * @see Cursor
1163 */
1164 public Cursor query(boolean distinct, String table, String[] columns,
1165 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001166 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001167 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001168 groupBy, having, orderBy, limit, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 }
1170
1171 /**
1172 * Query the given URL, returning a {@link Cursor} over the result set.
1173 *
1174 * @param cursorFactory the cursor factory to use, or null for the default factory
1175 * @param distinct true if you want each row to be unique, false otherwise.
1176 * @param table The table name to compile the query against.
1177 * @param columns A list of which columns to return. Passing null will
1178 * return all columns, which is discouraged to prevent reading
1179 * data from storage that isn't going to be used.
1180 * @param selection A filter declaring which rows to return, formatted as an
1181 * SQL WHERE clause (excluding the WHERE itself). Passing null
1182 * will return all rows for the given table.
1183 * @param selectionArgs You may include ?s in selection, which will be
1184 * replaced by the values from selectionArgs, in order that they
1185 * appear in the selection. The values will be bound as Strings.
1186 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1187 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1188 * will cause the rows to not be grouped.
1189 * @param having A filter declare which row groups to include in the cursor,
1190 * if row grouping is being used, formatted as an SQL HAVING
1191 * clause (excluding the HAVING itself). Passing null will cause
1192 * all row groups to be included, and is required when row
1193 * grouping is not being used.
1194 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1195 * (excluding the ORDER BY itself). Passing null will use the
1196 * default sort order, which may be unordered.
1197 * @param limit Limits the number of rows returned by the query,
1198 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001199 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1200 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 * @see Cursor
1202 */
1203 public Cursor queryWithFactory(CursorFactory cursorFactory,
1204 boolean distinct, String table, String[] columns,
1205 String selection, String[] selectionArgs, String groupBy,
1206 String having, String orderBy, String limit) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001207 return queryWithFactory(cursorFactory, distinct, table, columns, selection,
1208 selectionArgs, groupBy, having, orderBy, limit, null);
1209 }
1210
1211 /**
1212 * Query the given URL, returning a {@link Cursor} over the result set.
1213 *
1214 * @param cursorFactory the cursor factory to use, or null for the default factory
1215 * @param distinct true if you want each row to be unique, false otherwise.
1216 * @param table The table name to compile the query against.
1217 * @param columns A list of which columns to return. Passing null will
1218 * return all columns, which is discouraged to prevent reading
1219 * data from storage that isn't going to be used.
1220 * @param selection A filter declaring which rows to return, formatted as an
1221 * SQL WHERE clause (excluding the WHERE itself). Passing null
1222 * will return all rows for the given table.
1223 * @param selectionArgs You may include ?s in selection, which will be
1224 * replaced by the values from selectionArgs, in order that they
1225 * appear in the selection. The values will be bound as Strings.
1226 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1227 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1228 * will cause the rows to not be grouped.
1229 * @param having A filter declare which row groups to include in the cursor,
1230 * if row grouping is being used, formatted as an SQL HAVING
1231 * clause (excluding the HAVING itself). Passing null will cause
1232 * all row groups to be included, and is required when row
1233 * grouping is not being used.
1234 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1235 * (excluding the ORDER BY itself). Passing null will use the
1236 * default sort order, which may be unordered.
1237 * @param limit Limits the number of rows returned by the query,
1238 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001239 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001240 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1241 * when the query is executed.
1242 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1243 * {@link Cursor}s are not synchronized, see the documentation for more details.
1244 * @see Cursor
1245 */
1246 public Cursor queryWithFactory(CursorFactory cursorFactory,
1247 boolean distinct, String table, String[] columns,
1248 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001249 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001250 acquireReference();
1251 try {
1252 String sql = SQLiteQueryBuilder.buildQueryString(
1253 distinct, table, columns, selection, groupBy, having, orderBy, limit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001254
Jeff Brown03bd3022012-03-06 13:48:56 -08001255 return rawQueryWithFactory(cursorFactory, sql, selectionArgs,
1256 findEditTable(table), cancellationSignal);
1257 } finally {
1258 releaseReference();
1259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 }
1261
1262 /**
1263 * Query the given table, returning a {@link Cursor} over the result set.
1264 *
1265 * @param table The table name to compile the query against.
1266 * @param columns A list of which columns to return. Passing null will
1267 * return all columns, which is discouraged to prevent reading
1268 * data from storage that isn't going to be used.
1269 * @param selection A filter declaring which rows to return, formatted as an
1270 * SQL WHERE clause (excluding the WHERE itself). Passing null
1271 * will return all rows for the given table.
1272 * @param selectionArgs You may include ?s in selection, which will be
1273 * replaced by the values from selectionArgs, in order that they
1274 * appear in the selection. The values will be bound as Strings.
1275 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1276 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1277 * will cause the rows to not be grouped.
1278 * @param having A filter declare which row groups to include in the cursor,
1279 * if row grouping is being used, formatted as an SQL HAVING
1280 * clause (excluding the HAVING itself). Passing null will cause
1281 * all row groups to be included, and is required when row
1282 * grouping is not being used.
1283 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1284 * (excluding the ORDER BY itself). Passing null will use the
1285 * default sort order, which may be unordered.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001286 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1287 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288 * @see Cursor
1289 */
1290 public Cursor query(String table, String[] columns, String selection,
1291 String[] selectionArgs, String groupBy, String having,
1292 String orderBy) {
1293
1294 return query(false, table, columns, selection, selectionArgs, groupBy,
1295 having, orderBy, null /* limit */);
1296 }
1297
1298 /**
1299 * Query the given table, returning a {@link Cursor} over the result set.
1300 *
1301 * @param table The table name to compile the query against.
1302 * @param columns A list of which columns to return. Passing null will
1303 * return all columns, which is discouraged to prevent reading
1304 * data from storage that isn't going to be used.
1305 * @param selection A filter declaring which rows to return, formatted as an
1306 * SQL WHERE clause (excluding the WHERE itself). Passing null
1307 * will return all rows for the given table.
1308 * @param selectionArgs You may include ?s in selection, which will be
1309 * replaced by the values from selectionArgs, in order that they
1310 * appear in the selection. The values will be bound as Strings.
1311 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1312 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1313 * will cause the rows to not be grouped.
1314 * @param having A filter declare which row groups to include in the cursor,
1315 * if row grouping is being used, formatted as an SQL HAVING
1316 * clause (excluding the HAVING itself). Passing null will cause
1317 * all row groups to be included, and is required when row
1318 * grouping is not being used.
1319 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1320 * (excluding the ORDER BY itself). Passing null will use the
1321 * default sort order, which may be unordered.
1322 * @param limit Limits the number of rows returned by the query,
1323 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001324 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1325 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001326 * @see Cursor
1327 */
1328 public Cursor query(String table, String[] columns, String selection,
1329 String[] selectionArgs, String groupBy, String having,
1330 String orderBy, String limit) {
1331
1332 return query(false, table, columns, selection, selectionArgs, groupBy,
1333 having, orderBy, limit);
1334 }
1335
1336 /**
1337 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1338 *
1339 * @param sql the SQL query. The SQL string must not be ; terminated
1340 * @param selectionArgs You may include ?s in where clause in the query,
1341 * which will be replaced by the values from selectionArgs. The
1342 * values will be bound as Strings.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001343 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1344 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001345 */
1346 public Cursor rawQuery(String sql, String[] selectionArgs) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001347 return rawQueryWithFactory(null, sql, selectionArgs, null, null);
1348 }
1349
1350 /**
1351 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1352 *
1353 * @param sql the SQL query. The SQL string must not be ; terminated
1354 * @param selectionArgs You may include ?s in where clause in the query,
1355 * which will be replaced by the values from selectionArgs. The
1356 * values will be bound as Strings.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001357 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001358 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1359 * when the query is executed.
1360 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1361 * {@link Cursor}s are not synchronized, see the documentation for more details.
1362 */
1363 public Cursor rawQuery(String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001364 CancellationSignal cancellationSignal) {
1365 return rawQueryWithFactory(null, sql, selectionArgs, null, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 }
1367
1368 /**
1369 * Runs the provided SQL and returns a cursor over the result set.
1370 *
1371 * @param cursorFactory the cursor factory to use, or null for the default factory
1372 * @param sql the SQL query. The SQL string must not be ; terminated
1373 * @param selectionArgs You may include ?s in where clause in the query,
1374 * which will be replaced by the values from selectionArgs. The
1375 * values will be bound as Strings.
1376 * @param editTable the name of the first table, which is editable
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001377 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1378 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 */
1380 public Cursor rawQueryWithFactory(
1381 CursorFactory cursorFactory, String sql, String[] selectionArgs,
1382 String editTable) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001383 return rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable, null);
1384 }
1385
1386 /**
1387 * Runs the provided SQL and returns a cursor over the result set.
1388 *
1389 * @param cursorFactory the cursor factory to use, or null for the default factory
1390 * @param sql the SQL query. The SQL string must not be ; terminated
1391 * @param selectionArgs You may include ?s in where clause in the query,
1392 * which will be replaced by the values from selectionArgs. The
1393 * values will be bound as Strings.
1394 * @param editTable the name of the first table, which is editable
Jeff Brown4c1241d2012-02-02 17:05:00 -08001395 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001396 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1397 * when the query is executed.
1398 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1399 * {@link Cursor}s are not synchronized, see the documentation for more details.
1400 */
1401 public Cursor rawQueryWithFactory(
1402 CursorFactory cursorFactory, String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001403 String editTable, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001404 acquireReference();
1405 try {
1406 SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
1407 cancellationSignal);
1408 return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
1409 selectionArgs);
1410 } finally {
1411 releaseReference();
1412 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 }
1414
1415 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001416 * Convenience method for inserting a row into the database.
1417 *
1418 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001419 * @param nullColumnHack optional; may be <code>null</code>.
1420 * SQL doesn't allow inserting a completely empty row without
1421 * naming at least one column name. If your provided <code>values</code> is
1422 * empty, no column names are known and an empty row can't be inserted.
1423 * If not set to null, the <code>nullColumnHack</code> parameter
1424 * provides the name of nullable column name to explicitly insert a NULL into
1425 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 * @param values this map contains the initial column values for the
1427 * row. The keys should be the column names and the values the
1428 * column values
1429 * @return the row ID of the newly inserted row, or -1 if an error occurred
1430 */
1431 public long insert(String table, String nullColumnHack, ContentValues values) {
1432 try {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001433 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 } catch (SQLException e) {
1435 Log.e(TAG, "Error inserting " + values, e);
1436 return -1;
1437 }
1438 }
1439
1440 /**
1441 * Convenience method for inserting a row into the database.
1442 *
1443 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001444 * @param nullColumnHack optional; may be <code>null</code>.
1445 * SQL doesn't allow inserting a completely empty row without
1446 * naming at least one column name. If your provided <code>values</code> is
1447 * empty, no column names are known and an empty row can't be inserted.
1448 * If not set to null, the <code>nullColumnHack</code> parameter
1449 * provides the name of nullable column name to explicitly insert a NULL into
1450 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 * @param values this map contains the initial column values for the
1452 * row. The keys should be the column names and the values the
1453 * column values
1454 * @throws SQLException
1455 * @return the row ID of the newly inserted row, or -1 if an error occurred
1456 */
1457 public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
1458 throws SQLException {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001459 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 }
1461
1462 /**
1463 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001464 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465 *
1466 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001467 * @param nullColumnHack optional; may be <code>null</code>.
1468 * SQL doesn't allow inserting a completely empty row without
1469 * naming at least one column name. If your provided <code>initialValues</code> is
1470 * empty, no column names are known and an empty row can't be inserted.
1471 * If not set to null, the <code>nullColumnHack</code> parameter
1472 * provides the name of nullable column name to explicitly insert a NULL into
1473 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001475 * 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 -08001476 * @return the row ID of the newly inserted row, or -1 if an error occurred
1477 */
1478 public long replace(String table, String nullColumnHack, ContentValues initialValues) {
1479 try {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001480 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001481 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482 } catch (SQLException e) {
1483 Log.e(TAG, "Error inserting " + initialValues, e);
1484 return -1;
1485 }
1486 }
1487
1488 /**
1489 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001490 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 *
1492 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001493 * @param nullColumnHack optional; may be <code>null</code>.
1494 * SQL doesn't allow inserting a completely empty row without
1495 * naming at least one column name. If your provided <code>initialValues</code> is
1496 * empty, no column names are known and an empty row can't be inserted.
1497 * If not set to null, the <code>nullColumnHack</code> parameter
1498 * provides the name of nullable column name to explicitly insert a NULL into
1499 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001501 * 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 -08001502 * @throws SQLException
1503 * @return the row ID of the newly inserted row, or -1 if an error occurred
1504 */
1505 public long replaceOrThrow(String table, String nullColumnHack,
1506 ContentValues initialValues) throws SQLException {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001507 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001508 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 }
1510
1511 /**
1512 * General method for inserting a row into the database.
1513 *
1514 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001515 * @param nullColumnHack optional; may be <code>null</code>.
1516 * SQL doesn't allow inserting a completely empty row without
1517 * naming at least one column name. If your provided <code>initialValues</code> is
1518 * empty, no column names are known and an empty row can't be inserted.
1519 * If not set to null, the <code>nullColumnHack</code> parameter
1520 * provides the name of nullable column name to explicitly insert a NULL into
1521 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 * @param initialValues this map contains the initial column values for the
1523 * row. The keys should be the column names and the values the
1524 * column values
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001525 * @param conflictAlgorithm for insert conflict resolver
Steve Pomeroyc240b602013-03-14 00:42:10 -04001526 * @return the row ID of the newly inserted row OR <code>-1</code> if either the
1527 * input parameter <code>conflictAlgorithm</code> = {@link #CONFLICT_IGNORE}
1528 * or an error occurred.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529 */
1530 public long insertWithOnConflict(String table, String nullColumnHack,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001531 ContentValues initialValues, int conflictAlgorithm) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001532 acquireReference();
1533 try {
1534 StringBuilder sql = new StringBuilder();
1535 sql.append("INSERT");
1536 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1537 sql.append(" INTO ");
1538 sql.append(table);
1539 sql.append('(');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540
Jeff Brown03bd3022012-03-06 13:48:56 -08001541 Object[] bindArgs = null;
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001542 int size = (initialValues != null && !initialValues.isEmpty())
Jeff Brown03bd3022012-03-06 13:48:56 -08001543 ? initialValues.size() : 0;
1544 if (size > 0) {
1545 bindArgs = new Object[size];
1546 int i = 0;
1547 for (String colName : initialValues.keySet()) {
1548 sql.append((i > 0) ? "," : "");
1549 sql.append(colName);
1550 bindArgs[i++] = initialValues.get(colName);
1551 }
1552 sql.append(')');
1553 sql.append(" VALUES (");
1554 for (i = 0; i < size; i++) {
1555 sql.append((i > 0) ? ",?" : "?");
1556 }
1557 } else {
1558 sql.append(nullColumnHack + ") VALUES (NULL");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 sql.append(')');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561
Jeff Brown03bd3022012-03-06 13:48:56 -08001562 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1563 try {
1564 return statement.executeInsert();
1565 } finally {
1566 statement.close();
1567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001569 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 }
1571 }
1572
1573 /**
1574 * Convenience method for deleting rows in the database.
1575 *
1576 * @param table the table to delete from
1577 * @param whereClause the optional WHERE clause to apply when deleting.
1578 * Passing null will delete all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001579 * @param whereArgs You may include ?s in the where clause, which
1580 * will be replaced by the values from whereArgs. The values
1581 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 * @return the number of rows affected if a whereClause is passed in, 0
1583 * otherwise. To remove all rows and get a count pass "1" as the
1584 * whereClause.
1585 */
1586 public int delete(String table, String whereClause, String[] whereArgs) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001587 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001589 SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table +
1590 (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
1591 try {
1592 return statement.executeUpdateDelete();
1593 } finally {
1594 statement.close();
1595 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001597 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 }
1599 }
1600
1601 /**
1602 * Convenience method for updating rows in the database.
1603 *
1604 * @param table the table to update in
1605 * @param values a map from column names to new column values. null is a
1606 * valid value that will be translated to NULL.
1607 * @param whereClause the optional WHERE clause to apply when updating.
1608 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001609 * @param whereArgs You may include ?s in the where clause, which
1610 * will be replaced by the values from whereArgs. The values
1611 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001612 * @return the number of rows affected
1613 */
1614 public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001615 return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001616 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 /**
1619 * Convenience method for updating rows in the database.
1620 *
1621 * @param table the table to update in
1622 * @param values a map from column names to new column values. null is a
1623 * valid value that will be translated to NULL.
1624 * @param whereClause the optional WHERE clause to apply when updating.
1625 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001626 * @param whereArgs You may include ?s in the where clause, which
1627 * will be replaced by the values from whereArgs. The values
1628 * will be bound as Strings.
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001629 * @param conflictAlgorithm for update conflict resolver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001630 * @return the number of rows affected
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 */
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001632 public int updateWithOnConflict(String table, ContentValues values,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001633 String whereClause, String[] whereArgs, int conflictAlgorithm) {
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001634 if (values == null || values.isEmpty()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 throw new IllegalArgumentException("Empty values");
1636 }
1637
Jeff Brown03bd3022012-03-06 13:48:56 -08001638 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001640 StringBuilder sql = new StringBuilder(120);
1641 sql.append("UPDATE ");
1642 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1643 sql.append(table);
1644 sql.append(" SET ");
1645
1646 // move all bind args to one array
1647 int setValuesSize = values.size();
1648 int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
1649 Object[] bindArgs = new Object[bindArgsSize];
1650 int i = 0;
1651 for (String colName : values.keySet()) {
1652 sql.append((i > 0) ? "," : "");
1653 sql.append(colName);
1654 bindArgs[i++] = values.get(colName);
1655 sql.append("=?");
1656 }
1657 if (whereArgs != null) {
1658 for (i = setValuesSize; i < bindArgsSize; i++) {
1659 bindArgs[i] = whereArgs[i - setValuesSize];
1660 }
1661 }
1662 if (!TextUtils.isEmpty(whereClause)) {
1663 sql.append(" WHERE ");
1664 sql.append(whereClause);
1665 }
1666
1667 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1668 try {
1669 return statement.executeUpdateDelete();
1670 } finally {
1671 statement.close();
1672 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001674 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 }
1676 }
1677
1678 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001679 * Execute a single SQL statement that is NOT a SELECT
1680 * or any other SQL statement that returns data.
1681 * <p>
Vasu Norice38b982010-07-22 13:57:13 -07001682 * It has no means to return any data (such as the number of affected rows).
Vasu Noriccd95442010-05-28 17:04:16 -07001683 * Instead, you're encouraged to use {@link #insert(String, String, ContentValues)},
1684 * {@link #update(String, ContentValues, String, String[])}, et al, when possible.
1685 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001686 * <p>
1687 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1688 * automatically managed by this class. So, do not set journal_mode
1689 * using "PRAGMA journal_mode'<value>" statement if your app is using
1690 * {@link #enableWriteAheadLogging()}
1691 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001692 *
Vasu Noriccd95442010-05-28 17:04:16 -07001693 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1694 * not supported.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001695 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001696 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001697 public void execSQL(String sql) throws SQLException {
Vasu Nori16057fa2011-03-18 11:40:37 -07001698 executeSql(sql, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 }
1700
1701 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001702 * Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE.
1703 * <p>
1704 * For INSERT statements, use any of the following instead.
1705 * <ul>
1706 * <li>{@link #insert(String, String, ContentValues)}</li>
1707 * <li>{@link #insertOrThrow(String, String, ContentValues)}</li>
1708 * <li>{@link #insertWithOnConflict(String, String, ContentValues, int)}</li>
1709 * </ul>
1710 * <p>
1711 * For UPDATE statements, use any of the following instead.
1712 * <ul>
1713 * <li>{@link #update(String, ContentValues, String, String[])}</li>
1714 * <li>{@link #updateWithOnConflict(String, ContentValues, String, String[], int)}</li>
1715 * </ul>
1716 * <p>
1717 * For DELETE statements, use any of the following instead.
1718 * <ul>
1719 * <li>{@link #delete(String, String, String[])}</li>
1720 * </ul>
1721 * <p>
1722 * For example, the following are good candidates for using this method:
1723 * <ul>
1724 * <li>ALTER TABLE</li>
1725 * <li>CREATE or DROP table / trigger / view / index / virtual table</li>
1726 * <li>REINDEX</li>
1727 * <li>RELEASE</li>
1728 * <li>SAVEPOINT</li>
1729 * <li>PRAGMA that returns no data</li>
1730 * </ul>
1731 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001732 * <p>
1733 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1734 * automatically managed by this class. So, do not set journal_mode
1735 * using "PRAGMA journal_mode'<value>" statement if your app is using
1736 * {@link #enableWriteAheadLogging()}
1737 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 *
Vasu Noriccd95442010-05-28 17:04:16 -07001739 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1740 * not supported.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 * @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001742 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001744 public void execSQL(String sql, Object[] bindArgs) throws SQLException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 if (bindArgs == null) {
1746 throw new IllegalArgumentException("Empty bindArgs");
1747 }
Vasu Norib83cb7c2010-09-14 13:36:01 -07001748 executeSql(sql, bindArgs);
Vasu Norice38b982010-07-22 13:57:13 -07001749 }
1750
Jeff Sharkey50699422018-07-25 14:52:14 -06001751 /** {@hide} */
1752 public int executeSql(String sql, Object[] bindArgs) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001753 acquireReference();
1754 try {
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001755 final int statementType = DatabaseUtils.getSqlStatementType(sql);
1756 if (statementType == DatabaseUtils.STATEMENT_ATTACH) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001757 boolean disableWal = false;
1758 synchronized (mLock) {
1759 if (!mHasAttachedDbsLocked) {
1760 mHasAttachedDbsLocked = true;
1761 disableWal = true;
Fyodor Kupolovfd9c4a52017-07-13 15:36:57 -07001762 mConnectionPoolLocked.disableIdleConnectionHandler();
Jeff Brown03bd3022012-03-06 13:48:56 -08001763 }
1764 }
1765 if (disableWal) {
1766 disableWriteAheadLogging();
Jeff Browne5360fb2011-10-31 17:48:13 -07001767 }
1768 }
Jeff Browne5360fb2011-10-31 17:48:13 -07001769
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001770 try (SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs)) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001771 return statement.executeUpdateDelete();
1772 } finally {
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001773 // If schema was updated, close non-primary connections, otherwise they might
1774 // have outdated schema information
1775 if (statementType == DatabaseUtils.STATEMENT_DDL) {
1776 mConnectionPoolLocked.closeAvailableNonPrimaryConnectionsAndLogExceptions();
1777 }
Jeff Brown03bd3022012-03-06 13:48:56 -08001778 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001779 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001780 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 }
1783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 /**
Makoto Onuki17aa1b72015-12-16 14:02:01 -08001785 * Verifies that a SQL SELECT statement is valid by compiling it.
1786 * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
1787 *
1788 * @param sql SQL to be validated
1789 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
1790 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1791 * when the query is executed.
1792 * @throws SQLiteException if {@code sql} is invalid
1793 */
1794 public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal) {
1795 getThreadSession().prepare(sql,
1796 getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null);
1797 }
1798
1799 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001800 * Returns true if the database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001802 * @return True if database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 */
1804 public boolean isReadOnly() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001805 synchronized (mLock) {
1806 return isReadOnlyLocked();
1807 }
1808 }
1809
1810 private boolean isReadOnlyLocked() {
1811 return (mConfigurationLocked.openFlags & OPEN_READ_MASK) == OPEN_READONLY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 }
1813
1814 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001815 * Returns true if the database is in-memory db.
1816 *
1817 * @return True if the database is in-memory.
1818 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001819 */
Jeff Browne5360fb2011-10-31 17:48:13 -07001820 public boolean isInMemoryDatabase() {
1821 synchronized (mLock) {
1822 return mConfigurationLocked.isInMemoryDb();
1823 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001824 }
1825
Jeff Browne5360fb2011-10-31 17:48:13 -07001826 /**
1827 * Returns true if the database is currently open.
1828 *
1829 * @return True if the database is currently open (has not been closed).
1830 */
1831 public boolean isOpen() {
1832 synchronized (mLock) {
1833 return mConnectionPoolLocked != null;
1834 }
1835 }
1836
1837 /**
1838 * Returns true if the new version code is greater than the current database version.
1839 *
1840 * @param newVersion The new version code.
Mark Lu1e202082016-08-30 17:41:25 -07001841 * @return True if the new version code is greater than the current database version.
Jeff Browne5360fb2011-10-31 17:48:13 -07001842 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 public boolean needUpgrade(int newVersion) {
1844 return newVersion > getVersion();
1845 }
1846
1847 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001848 * Gets the path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001850 * @return The path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001851 */
1852 public final String getPath() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001853 synchronized (mLock) {
1854 return mConfigurationLocked.path;
Christopher Tatead9e8b12011-10-05 17:49:26 -07001855 }
Brad Fitzpatrick722802e2010-03-23 22:22:16 -07001856 }
1857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001858 /**
1859 * Sets the locale for this database. Does nothing if this database has
Jeff Brown1d9f7422012-03-15 14:32:32 -07001860 * the {@link #NO_LOCALIZED_COLLATORS} flag set or was opened read only.
Jeff Browne5360fb2011-10-31 17:48:13 -07001861 *
1862 * @param locale The new locale.
1863 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864 * @throws SQLException if the locale could not be set. The most common reason
1865 * for this is that there is no collator available for the locale you requested.
1866 * In this case the database remains unchanged.
1867 */
1868 public void setLocale(Locale locale) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001869 if (locale == null) {
1870 throw new IllegalArgumentException("locale must not be null.");
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001871 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001872
Jeff Browne5360fb2011-10-31 17:48:13 -07001873 synchronized (mLock) {
1874 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001875
1876 final Locale oldLocale = mConfigurationLocked.locale;
Jeff Browne5360fb2011-10-31 17:48:13 -07001877 mConfigurationLocked.locale = locale;
Jeff Browne67ca422012-03-21 17:24:05 -07001878 try {
1879 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1880 } catch (RuntimeException ex) {
1881 mConfigurationLocked.locale = oldLocale;
1882 throw ex;
1883 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001884 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001885 }
1886
Vasu Norie495d1f2010-01-06 16:34:19 -08001887 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001888 * Sets the maximum size of the prepared-statement cache for this database.
Vasu Norie495d1f2010-01-06 16:34:19 -08001889 * (size of the cache = number of compiled-sql-statements stored in the cache).
Vasu Noriccd95442010-05-28 17:04:16 -07001890 *<p>
Vasu Norib729dcc2010-09-14 11:35:49 -07001891 * Maximum cache size can ONLY be increased from its current size (default = 10).
Vasu Noriccd95442010-05-28 17:04:16 -07001892 * If this method is called with smaller size than the current maximum value,
1893 * then IllegalStateException is thrown.
Vasu Norib729dcc2010-09-14 11:35:49 -07001894 *<p>
1895 * This method is thread-safe.
Vasu Norie495d1f2010-01-06 16:34:19 -08001896 *
Vasu Nori90a367262010-04-12 12:49:09 -07001897 * @param cacheSize the size of the cache. can be (0 to {@link #MAX_SQL_CACHE_SIZE})
Jeff Browne5360fb2011-10-31 17:48:13 -07001898 * @throws IllegalStateException if input cacheSize > {@link #MAX_SQL_CACHE_SIZE}.
Vasu Norie495d1f2010-01-06 16:34:19 -08001899 */
Vasu Nori54025902010-09-14 12:14:26 -07001900 public void setMaxSqlCacheSize(int cacheSize) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001901 if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) {
1902 throw new IllegalStateException(
1903 "expected value between 0 and " + MAX_SQL_CACHE_SIZE);
Vasu Nori587423a2010-09-27 18:18:34 -07001904 }
Vasu Nori587423a2010-09-27 18:18:34 -07001905
Jeff Browne5360fb2011-10-31 17:48:13 -07001906 synchronized (mLock) {
1907 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001908
1909 final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize;
Jeff Browne5360fb2011-10-31 17:48:13 -07001910 mConfigurationLocked.maxSqlCacheSize = cacheSize;
Jeff Browne67ca422012-03-21 17:24:05 -07001911 try {
1912 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1913 } catch (RuntimeException ex) {
1914 mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize;
1915 throw ex;
1916 }
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001917 }
1918 }
1919
Vasu Nori6c354da2010-04-26 23:33:39 -07001920 /**
Jeff Brown96496ad2012-03-23 14:38:06 -07001921 * Sets whether foreign key constraints are enabled for the database.
1922 * <p>
1923 * By default, foreign key constraints are not enforced by the database.
1924 * This method allows an application to enable foreign key constraints.
1925 * It must be called each time the database is opened to ensure that foreign
1926 * key constraints are enabled for the session.
1927 * </p><p>
1928 * A good time to call this method is right after calling {@link #openOrCreateDatabase}
1929 * or in the {@link SQLiteOpenHelper#onConfigure} callback.
1930 * </p><p>
1931 * When foreign key constraints are disabled, the database does not check whether
1932 * changes to the database will violate foreign key constraints. Likewise, when
1933 * foreign key constraints are disabled, the database will not execute cascade
1934 * delete or update triggers. As a result, it is possible for the database
1935 * state to become inconsistent. To perform a database integrity check,
1936 * call {@link #isDatabaseIntegrityOk}.
1937 * </p><p>
1938 * This method must not be called while a transaction is in progress.
1939 * </p><p>
1940 * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a>
1941 * for more details about foreign key constraint support.
1942 * </p>
1943 *
1944 * @param enable True to enable foreign key constraints, false to disable them.
1945 *
1946 * @throws IllegalStateException if the are transactions is in progress
1947 * when this method is called.
1948 */
1949 public void setForeignKeyConstraintsEnabled(boolean enable) {
1950 synchronized (mLock) {
1951 throwIfNotOpenLocked();
1952
1953 if (mConfigurationLocked.foreignKeyConstraintsEnabled == enable) {
1954 return;
1955 }
1956
1957 mConfigurationLocked.foreignKeyConstraintsEnabled = enable;
1958 try {
1959 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1960 } catch (RuntimeException ex) {
1961 mConfigurationLocked.foreignKeyConstraintsEnabled = !enable;
1962 throw ex;
1963 }
1964 }
1965 }
1966
1967 /**
Jeff Brown47847f32012-03-22 19:13:11 -07001968 * This method enables parallel execution of queries from multiple threads on the
1969 * same database. It does this by opening multiple connections to the database
1970 * and using a different database connection for each query. The database
1971 * journal mode is also changed to enable writes to proceed concurrently with reads.
Vasu Nori6c354da2010-04-26 23:33:39 -07001972 * <p>
Jeff Brown47847f32012-03-22 19:13:11 -07001973 * When write-ahead logging is not enabled (the default), it is not possible for
1974 * reads and writes to occur on the database at the same time. Before modifying the
1975 * database, the writer implicitly acquires an exclusive lock on the database which
1976 * prevents readers from accessing the database until the write is completed.
1977 * </p><p>
1978 * In contrast, when write-ahead logging is enabled (by calling this method), write
1979 * operations occur in a separate log file which allows reads to proceed concurrently.
1980 * While a write is in progress, readers on other threads will perceive the state
1981 * of the database as it was before the write began. When the write completes, readers
1982 * on other threads will then perceive the new state of the database.
1983 * </p><p>
1984 * It is a good idea to enable write-ahead logging whenever a database will be
1985 * concurrently accessed and modified by multiple threads at the same time.
1986 * However, write-ahead logging uses significantly more memory than ordinary
1987 * journaling because there are multiple connections to the same database.
1988 * So if a database will only be used by a single thread, or if optimizing
1989 * concurrency is not very important, then write-ahead logging should be disabled.
1990 * </p><p>
1991 * After calling this method, execution of queries in parallel is enabled as long as
1992 * the database remains open. To disable execution of queries in parallel, either
1993 * call {@link #disableWriteAheadLogging} or close the database and reopen it.
1994 * </p><p>
1995 * The maximum number of connections used to execute queries in parallel is
Vasu Nori6c354da2010-04-26 23:33:39 -07001996 * dependent upon the device memory and possibly other properties.
Jeff Brown47847f32012-03-22 19:13:11 -07001997 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07001998 * If a query is part of a transaction, then it is executed on the same database handle the
1999 * transaction was begun.
Jeff Brown47847f32012-03-22 19:13:11 -07002000 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07002001 * Writers should use {@link #beginTransactionNonExclusive()} or
2002 * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
Jeff Brown47847f32012-03-22 19:13:11 -07002003 * to start a transaction. Non-exclusive mode allows database file to be in readable
2004 * by other threads executing queries.
2005 * </p><p>
2006 * If the database has any attached databases, then execution of queries in parallel is NOT
2007 * possible. Likewise, write-ahead logging is not supported for read-only databases
2008 * or memory databases. In such cases, {@link #enableWriteAheadLogging} returns false.
2009 * </p><p>
2010 * The best way to enable write-ahead logging is to pass the
2011 * {@link #ENABLE_WRITE_AHEAD_LOGGING} flag to {@link #openDatabase}. This is
2012 * more efficient than calling {@link #enableWriteAheadLogging}.
2013 * <code><pre>
2014 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2015 * SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
2016 * myDatabaseErrorHandler);
Jeff Brown47847f32012-03-22 19:13:11 -07002017 * </pre></code>
2018 * </p><p>
2019 * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging}
2020 * after opening the database.
2021 * <code><pre>
2022 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2023 * SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
2024 * db.enableWriteAheadLogging();
2025 * </pre></code>
2026 * </p><p>
2027 * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for
2028 * more details about how write-ahead logging works.
Vasu Nori6c354da2010-04-26 23:33:39 -07002029 * </p>
2030 *
Jeff Brown47847f32012-03-22 19:13:11 -07002031 * @return True if write-ahead logging is enabled.
Jeff Browne67ca422012-03-21 17:24:05 -07002032 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002033 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002034 * time this method is called. WAL mode can only be changed when there are no
2035 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002036 *
2037 * @see #ENABLE_WRITE_AHEAD_LOGGING
2038 * @see #disableWriteAheadLogging
Vasu Nori6c354da2010-04-26 23:33:39 -07002039 */
Vasu Noriffe06122010-09-27 12:32:57 -07002040 public boolean enableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002041 synchronized (mLock) {
2042 throwIfNotOpenLocked();
2043
Jeff Brown47847f32012-03-22 19:13:11 -07002044 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002045 return true;
2046 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002047
2048 if (isReadOnlyLocked()) {
2049 // WAL doesn't make sense for readonly-databases.
2050 // TODO: True, but connection pooling does still make sense...
2051 return false;
2052 }
2053
2054 if (mConfigurationLocked.isInMemoryDb()) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002055 Log.i(TAG, "can't enable WAL for memory databases.");
2056 return false;
2057 }
2058
2059 // make sure this database has NO attached databases because sqlite's write-ahead-logging
2060 // doesn't work for databases with attached databases
Jeff Browne5360fb2011-10-31 17:48:13 -07002061 if (mHasAttachedDbsLocked) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002062 if (Log.isLoggable(TAG, Log.DEBUG)) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002063 Log.d(TAG, "this database: " + mConfigurationLocked.label
2064 + " has attached databases. can't enable WAL.");
Paul Westbrookdae6d372011-02-17 10:59:56 -08002065 }
2066 return false;
2067 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002068
Jeff Brown47847f32012-03-22 19:13:11 -07002069 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002070 try {
2071 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2072 } catch (RuntimeException ex) {
Jeff Brown47847f32012-03-22 19:13:11 -07002073 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002074 throw ex;
2075 }
Paul Westbrookdae6d372011-02-17 10:59:56 -08002076 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002077 return true;
Vasu Nori6c354da2010-04-26 23:33:39 -07002078 }
2079
Vasu Nori2827d6d2010-07-04 00:26:18 -07002080 /**
Vasu Nori7b04c412010-07-20 10:31:21 -07002081 * This method disables the features enabled by {@link #enableWriteAheadLogging()}.
Jeff Browne67ca422012-03-21 17:24:05 -07002082 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002083 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002084 * time this method is called. WAL mode can only be changed when there are no
2085 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002086 *
2087 * @see #enableWriteAheadLogging
Vasu Nori2827d6d2010-07-04 00:26:18 -07002088 */
Vasu Nori7b04c412010-07-20 10:31:21 -07002089 public void disableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002090 synchronized (mLock) {
2091 throwIfNotOpenLocked();
2092
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002093 final int oldFlags = mConfigurationLocked.openFlags;
Fyodor Kupolov692573b2018-03-06 12:34:36 -08002094 final boolean walDisabled = (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0;
2095 final boolean compatibilityWalDisabled = (oldFlags & DISABLE_COMPATIBILITY_WAL) != 0;
2096 if (walDisabled && compatibilityWalDisabled) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002097 return;
Paul Westbrookdae6d372011-02-17 10:59:56 -08002098 }
Vasu Nori8d111032010-06-22 18:34:21 -07002099
Jeff Brown47847f32012-03-22 19:13:11 -07002100 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Fyodor Kupolov692573b2018-03-06 12:34:36 -08002101 // If an app explicitly disables WAL, compatibility mode should be disabled too
2102 mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002103
Jeff Browne67ca422012-03-21 17:24:05 -07002104 try {
2105 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2106 } catch (RuntimeException ex) {
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002107 mConfigurationLocked.openFlags = oldFlags;
Jeff Browne67ca422012-03-21 17:24:05 -07002108 throw ex;
2109 }
Vasu Nori65a88832010-07-16 15:14:08 -07002110 }
Vasu Nori6c354da2010-04-26 23:33:39 -07002111 }
2112
Vasu Norif3cf8a42010-03-23 11:41:44 -07002113 /**
Jeff Brown47847f32012-03-22 19:13:11 -07002114 * Returns true if write-ahead logging has been enabled for this database.
2115 *
2116 * @return True if write-ahead logging has been enabled for this database.
2117 *
2118 * @see #enableWriteAheadLogging
2119 * @see #ENABLE_WRITE_AHEAD_LOGGING
2120 */
2121 public boolean isWriteAheadLoggingEnabled() {
2122 synchronized (mLock) {
2123 throwIfNotOpenLocked();
2124
2125 return (mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2126 }
2127 }
2128
2129 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002130 * Collect statistics about all open databases in the current process.
2131 * Used by bug report.
Vasu Norif3cf8a42010-03-23 11:41:44 -07002132 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002133 static ArrayList<DbStats> getDbStats() {
Vasu Noric3849202010-03-09 10:47:25 -08002134 ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002135 for (SQLiteDatabase db : getActiveDatabases()) {
2136 db.collectDbStats(dbStatsList);
Vasu Nori24675612010-09-27 14:54:19 -07002137 }
Vasu Noric3849202010-03-09 10:47:25 -08002138 return dbStatsList;
2139 }
2140
Jeff Browne5360fb2011-10-31 17:48:13 -07002141 private void collectDbStats(ArrayList<DbStats> dbStatsList) {
2142 synchronized (mLock) {
2143 if (mConnectionPoolLocked != null) {
2144 mConnectionPoolLocked.collectDbStats(dbStatsList);
2145 }
2146 }
2147 }
2148
2149 private static ArrayList<SQLiteDatabase> getActiveDatabases() {
2150 ArrayList<SQLiteDatabase> databases = new ArrayList<SQLiteDatabase>();
2151 synchronized (sActiveDatabases) {
2152 databases.addAll(sActiveDatabases.keySet());
2153 }
2154 return databases;
2155 }
2156
2157 /**
2158 * Dump detailed information about all open databases in the current process.
2159 * Used by bug report.
2160 */
Jeff Browna9be4152012-01-18 15:29:57 -08002161 static void dumpAll(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002162 for (SQLiteDatabase db : getActiveDatabases()) {
Jeff Browna9be4152012-01-18 15:29:57 -08002163 db.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002164 }
2165 }
2166
Jeff Browna9be4152012-01-18 15:29:57 -08002167 private void dump(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002168 synchronized (mLock) {
2169 if (mConnectionPoolLocked != null) {
2170 printer.println("");
Jeff Browna9be4152012-01-18 15:29:57 -08002171 mConnectionPoolLocked.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002172 }
2173 }
2174 }
2175
Vasu Noric3849202010-03-09 10:47:25 -08002176 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002177 * Returns list of full pathnames of all attached databases including the main database
2178 * by executing 'pragma database_list' on the database.
2179 *
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002180 * @return ArrayList of pairs of (database name, database file path) or null if the database
2181 * is not open.
Vasu Noric3849202010-03-09 10:47:25 -08002182 */
Vasu Noria017eda2011-01-27 10:52:55 -08002183 public List<Pair<String, String>> getAttachedDbs() {
Vasu Noric3849202010-03-09 10:47:25 -08002184 ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002185 synchronized (mLock) {
2186 if (mConnectionPoolLocked == null) {
2187 return null; // not open
2188 }
2189
2190 if (!mHasAttachedDbsLocked) {
2191 // No attached databases.
2192 // There is a small window where attached databases exist but this flag is not
2193 // set yet. This can occur when this thread is in a race condition with another
2194 // thread that is executing the SQL statement: "attach database <blah> as <foo>"
2195 // If this thread is NOT ok with such a race condition (and thus possibly not
2196 // receivethe entire list of attached databases), then the caller should ensure
2197 // that no thread is executing any SQL statements while a thread is calling this
2198 // method. Typically, this method is called when 'adb bugreport' is done or the
2199 // caller wants to collect stats on the database and all its attached databases.
2200 attachedDbs.add(new Pair<String, String>("main", mConfigurationLocked.path));
2201 return attachedDbs;
2202 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002203
2204 acquireReference();
Vasu Nori24675612010-09-27 14:54:19 -07002205 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002206
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002207 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002208 // has attached databases. query sqlite to get the list of attached databases.
2209 Cursor c = null;
2210 try {
2211 c = rawQuery("pragma database_list;", null);
2212 while (c.moveToNext()) {
2213 // sqlite returns a row for each database in the returned list of databases.
2214 // in each row,
2215 // 1st column is the database name such as main, or the database
2216 // name specified on the "ATTACH" command
2217 // 2nd column is the database file path.
2218 attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2)));
2219 }
2220 } finally {
2221 if (c != null) {
2222 c.close();
2223 }
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002224 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002225 return attachedDbs;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002226 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08002227 releaseReference();
Vasu Noric3849202010-03-09 10:47:25 -08002228 }
Vasu Noric3849202010-03-09 10:47:25 -08002229 }
2230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002231 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002232 * Runs 'pragma integrity_check' on the given database (and all the attached databases)
2233 * and returns true if the given database (and all its attached databases) pass integrity_check,
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002234 * false otherwise.
Vasu Noriccd95442010-05-28 17:04:16 -07002235 *<p>
2236 * If the result is false, then this method logs the errors reported by the integrity_check
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002237 * command execution.
Vasu Noriccd95442010-05-28 17:04:16 -07002238 *<p>
2239 * Note that 'pragma integrity_check' on a database can take a long time.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002240 *
2241 * @return true if the given database (and all its attached databases) pass integrity_check,
Vasu Noriccd95442010-05-28 17:04:16 -07002242 * false otherwise.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002243 */
2244 public boolean isDatabaseIntegrityOk() {
Jeff Brown03bd3022012-03-06 13:48:56 -08002245 acquireReference();
Vasu Noribfe1dc22010-08-25 16:29:02 -07002246 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002247 List<Pair<String, String>> attachedDbs = null;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002248 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002249 attachedDbs = getAttachedDbs();
2250 if (attachedDbs == null) {
2251 throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " +
2252 "be retrieved. probably because the database is closed");
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002253 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002254 } catch (SQLiteException e) {
2255 // can't get attachedDb list. do integrity check on the main database
2256 attachedDbs = new ArrayList<Pair<String, String>>();
2257 attachedDbs.add(new Pair<String, String>("main", getPath()));
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002258 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002259
2260 for (int i = 0; i < attachedDbs.size(); i++) {
2261 Pair<String, String> p = attachedDbs.get(i);
2262 SQLiteStatement prog = null;
2263 try {
2264 prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);");
2265 String rslt = prog.simpleQueryForString();
2266 if (!rslt.equalsIgnoreCase("ok")) {
2267 // integrity_checker failed on main or attached databases
2268 Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt);
2269 return false;
2270 }
2271 } finally {
2272 if (prog != null) prog.close();
2273 }
2274 }
2275 } finally {
2276 releaseReference();
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002277 }
Vasu Noribfe1dc22010-08-25 16:29:02 -07002278 return true;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002279 }
2280
Jeff Browne5360fb2011-10-31 17:48:13 -07002281 @Override
2282 public String toString() {
2283 return "SQLiteDatabase: " + getPath();
2284 }
2285
Jeff Browne5360fb2011-10-31 17:48:13 -07002286 private void throwIfNotOpenLocked() {
2287 if (mConnectionPoolLocked == null) {
2288 throw new IllegalStateException("The database '" + mConfigurationLocked.label
2289 + "' is not open.");
2290 }
2291 }
Vasu Nori3ef94e22010-02-05 14:49:04 -08002292
2293 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002294 * Used to allow returning sub-classes of {@link Cursor} when calling query.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002296 public interface CursorFactory {
2297 /**
2298 * See {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}.
2299 */
2300 public Cursor newCursor(SQLiteDatabase db,
2301 SQLiteCursorDriver masterQuery, String editTable,
2302 SQLiteQuery query);
2303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002304
2305 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002306 * A callback interface for a custom sqlite3 function.
2307 * This can be used to create a function that can be called from
2308 * sqlite3 database triggers.
2309 * @hide
Vasu Noric3849202010-03-09 10:47:25 -08002310 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002311 public interface CustomFunction {
2312 public void callback(String[] args);
2313 }
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002314
2315 /**
2316 * Wrapper for configuration parameters that are used for opening {@link SQLiteDatabase}
2317 */
2318 public static final class OpenParams {
2319 private final int mOpenFlags;
2320 private final CursorFactory mCursorFactory;
2321 private final DatabaseErrorHandler mErrorHandler;
2322 private final int mLookasideSlotSize;
2323 private final int mLookasideSlotCount;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002324 private final long mIdleConnectionTimeout;
2325 private final String mJournalMode;
2326 private final String mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002327
2328 private OpenParams(int openFlags, CursorFactory cursorFactory,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002329 DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002330 long idleConnectionTimeout, String journalMode, String syncMode) {
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002331 mOpenFlags = openFlags;
2332 mCursorFactory = cursorFactory;
2333 mErrorHandler = errorHandler;
2334 mLookasideSlotSize = lookasideSlotSize;
2335 mLookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002336 mIdleConnectionTimeout = idleConnectionTimeout;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002337 mJournalMode = journalMode;
2338 mSyncMode = syncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002339 }
2340
2341 /**
2342 * Returns size in bytes of each lookaside slot or -1 if not set.
2343 *
2344 * @see Builder#setLookasideConfig(int, int)
2345 */
2346 @IntRange(from = -1)
2347 public int getLookasideSlotSize() {
2348 return mLookasideSlotSize;
2349 }
2350
2351 /**
2352 * Returns total number of lookaside memory slots per database connection or -1 if not
2353 * set.
2354 *
2355 * @see Builder#setLookasideConfig(int, int)
2356 */
2357 @IntRange(from = -1)
2358 public int getLookasideSlotCount() {
2359 return mLookasideSlotCount;
2360 }
2361
2362 /**
Fyodor Kupolov76436c02017-08-03 17:56:44 -07002363 * Returns flags to control database access mode. Default value is 0.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002364 *
2365 * @see Builder#setOpenFlags(int)
2366 */
2367 @DatabaseOpenFlags
2368 public int getOpenFlags() {
2369 return mOpenFlags;
2370 }
2371
2372 /**
2373 * Returns an optional factory class that is called to instantiate a cursor when query
2374 * is called
2375 *
2376 * @see Builder#setCursorFactory(CursorFactory)
2377 */
2378 @Nullable
2379 public CursorFactory getCursorFactory() {
2380 return mCursorFactory;
2381 }
2382
2383 /**
2384 * Returns handler for database corruption errors
2385 *
2386 * @see Builder#setErrorHandler(DatabaseErrorHandler)
2387 */
2388 @Nullable
2389 public DatabaseErrorHandler getErrorHandler() {
2390 return mErrorHandler;
2391 }
2392
2393 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002394 * Returns maximum number of milliseconds that SQLite connection is allowed to be idle
2395 * before it is closed and removed from the pool.
2396 * <p>If the value isn't set, the timeout defaults to the system wide timeout
2397 *
2398 * @return timeout in milliseconds or -1 if the value wasn't set.
2399 */
2400 public long getIdleConnectionTimeout() {
2401 return mIdleConnectionTimeout;
2402 }
2403
2404 /**
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002405 * Returns <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>.
2406 * This journal mode will only be used if {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING}
2407 * flag is not set, otherwise a platform will use "WAL" journal mode.
2408 * @see Builder#setJournalMode(String)
2409 */
2410 @Nullable
2411 public String getJournalMode() {
2412 return mJournalMode;
2413 }
2414
2415 /**
2416 * Returns <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>.
Fyodor Kupolov8ba20892018-06-01 12:11:42 -07002417 * If not set, a system wide default will be used.
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002418 * @see Builder#setSynchronousMode(String)
2419 */
2420 @Nullable
2421 public String getSynchronousMode() {
2422 return mSyncMode;
2423 }
2424
2425 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002426 * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with
2427 * {@code this} parameters.
2428 * @hide
2429 */
2430 @NonNull
2431 public Builder toBuilder() {
2432 return new Builder(this);
2433 }
2434
2435 /**
2436 * Builder for {@link OpenParams}.
2437 */
2438 public static final class Builder {
2439 private int mLookasideSlotSize = -1;
2440 private int mLookasideSlotCount = -1;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002441 private long mIdleConnectionTimeout = -1;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002442 private int mOpenFlags;
2443 private CursorFactory mCursorFactory;
2444 private DatabaseErrorHandler mErrorHandler;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002445 private String mJournalMode;
2446 private String mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002447
2448 public Builder() {
2449 }
2450
2451 public Builder(OpenParams params) {
2452 mLookasideSlotSize = params.mLookasideSlotSize;
2453 mLookasideSlotCount = params.mLookasideSlotCount;
2454 mOpenFlags = params.mOpenFlags;
2455 mCursorFactory = params.mCursorFactory;
2456 mErrorHandler = params.mErrorHandler;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002457 mJournalMode = params.mJournalMode;
2458 mSyncMode = params.mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002459 }
2460
2461 /**
2462 * Configures
2463 * <a href="https://sqlite.org/malloc.html#lookaside">lookaside memory allocator</a>
2464 *
2465 * <p>SQLite default settings will be used, if this method isn't called.
2466 * Use {@code setLookasideConfig(0,0)} to disable lookaside
2467 *
Fyodor Kupolov05a0f0f2017-06-30 19:00:00 -07002468 * <p><strong>Note:</strong> Provided slotSize/slotCount configuration is just a
2469 * recommendation. The system may choose different values depending on a device, e.g.
2470 * lookaside allocations can be disabled on low-RAM devices
2471 *
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002472 * @param slotSize The size in bytes of each lookaside slot.
2473 * @param slotCount The total number of lookaside memory slots per database connection.
2474 */
2475 public Builder setLookasideConfig(@IntRange(from = 0) final int slotSize,
2476 @IntRange(from = 0) final int slotCount) {
2477 Preconditions.checkArgument(slotSize >= 0,
2478 "lookasideSlotCount cannot be negative");
2479 Preconditions.checkArgument(slotCount >= 0,
2480 "lookasideSlotSize cannot be negative");
2481 Preconditions.checkArgument(
2482 (slotSize > 0 && slotCount > 0) || (slotCount == 0 && slotSize == 0),
2483 "Invalid configuration: " + slotSize + ", " + slotCount);
2484
2485 mLookasideSlotSize = slotSize;
2486 mLookasideSlotCount = slotCount;
2487 return this;
2488 }
2489
2490 /**
2491 * Returns true if {@link #ENABLE_WRITE_AHEAD_LOGGING} flag is set
2492 * @hide
2493 */
2494 public boolean isWriteAheadLoggingEnabled() {
2495 return (mOpenFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2496 }
2497
2498 /**
2499 * Sets flags to control database access mode
2500 * @param openFlags The new flags to set
2501 * @see #OPEN_READWRITE
2502 * @see #OPEN_READONLY
2503 * @see #CREATE_IF_NECESSARY
2504 * @see #NO_LOCALIZED_COLLATORS
2505 * @see #ENABLE_WRITE_AHEAD_LOGGING
2506 * @return same builder instance for chaining multiple calls into a single statement
2507 */
2508 @NonNull
2509 public Builder setOpenFlags(@DatabaseOpenFlags int openFlags) {
2510 mOpenFlags = openFlags;
2511 return this;
2512 }
2513
2514 /**
2515 * Adds flags to control database access mode
2516 *
2517 * @param openFlags The new flags to add
2518 * @return same builder instance for chaining multiple calls into a single statement
2519 */
2520 @NonNull
2521 public Builder addOpenFlags(@DatabaseOpenFlags int openFlags) {
2522 mOpenFlags |= openFlags;
2523 return this;
2524 }
2525
2526 /**
2527 * Removes database access mode flags
2528 *
2529 * @param openFlags Flags to remove
2530 * @return same builder instance for chaining multiple calls into a single statement
2531 */
2532 @NonNull
2533 public Builder removeOpenFlags(@DatabaseOpenFlags int openFlags) {
2534 mOpenFlags &= ~openFlags;
2535 return this;
2536 }
2537
2538 /**
2539 * Sets {@link #ENABLE_WRITE_AHEAD_LOGGING} flag if {@code enabled} is {@code true},
2540 * unsets otherwise
2541 * @hide
2542 */
2543 public void setWriteAheadLoggingEnabled(boolean enabled) {
2544 if (enabled) {
2545 addOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2546 } else {
2547 removeOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2548 }
2549 }
2550
2551 /**
2552 * Set an optional factory class that is called to instantiate a cursor when query
2553 * is called.
2554 *
2555 * @param cursorFactory instance
2556 * @return same builder instance for chaining multiple calls into a single statement
2557 */
2558 @NonNull
2559 public Builder setCursorFactory(@Nullable CursorFactory cursorFactory) {
2560 mCursorFactory = cursorFactory;
2561 return this;
2562 }
2563
2564
2565 /**
2566 * Sets {@link DatabaseErrorHandler} object to handle db corruption errors
2567 */
2568 @NonNull
2569 public Builder setErrorHandler(@Nullable DatabaseErrorHandler errorHandler) {
2570 mErrorHandler = errorHandler;
2571 return this;
2572 }
2573
2574 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002575 * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle
2576 * before it is closed and removed from the pool.
2577 *
2578 * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE}
2579 * to allow unlimited idle connections.
2580 */
2581 @NonNull
2582 public Builder setIdleConnectionTimeout(
2583 @IntRange(from = 0) long idleConnectionTimeoutMs) {
2584 Preconditions.checkArgument(idleConnectionTimeoutMs >= 0,
2585 "idle connection timeout cannot be negative");
2586 mIdleConnectionTimeout = idleConnectionTimeoutMs;
2587 return this;
2588 }
2589
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002590
2591 /**
2592 * Sets <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>
2593 * to use when {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag is not set.
2594 */
2595 @NonNull
2596 public Builder setJournalMode(@NonNull String journalMode) {
2597 Preconditions.checkNotNull(journalMode);
2598 mJournalMode = journalMode;
2599 return this;
2600 }
2601
2602 /**
2603 * Sets <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>
Fyodor Kupolov8ba20892018-06-01 12:11:42 -07002604 * .
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002605 * @return
2606 */
2607 @NonNull
2608 public Builder setSynchronousMode(@NonNull String syncMode) {
2609 Preconditions.checkNotNull(syncMode);
2610 mSyncMode = syncMode;
2611 return this;
2612 }
2613
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002614 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002615 * Creates an instance of {@link OpenParams} with the options that were previously set
2616 * on this builder
2617 */
2618 @NonNull
2619 public OpenParams build() {
2620 return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002621 mLookasideSlotCount, mIdleConnectionTimeout, mJournalMode, mSyncMode);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002622 }
2623 }
2624 }
2625
2626 /** @hide */
2627 @IntDef(flag = true, prefix = {"OPEN_", "CREATE_", "NO_", "ENABLE_"}, value = {
2628 OPEN_READWRITE,
2629 OPEN_READONLY,
2630 CREATE_IF_NECESSARY,
2631 NO_LOCALIZED_COLLATORS,
2632 ENABLE_WRITE_AHEAD_LOGGING
2633 })
2634 @Retention(RetentionPolicy.SOURCE)
2635 public @interface DatabaseOpenFlags {}
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002637}
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002638