blob: a4b989a7249284abaab00cf07c919124d5177a72 [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
Jeff Sharkey6adc98c2018-07-12 19:47:49 -0600192 /** {@hide} */
193 public static final String[] CONFLICT_VALUES = new String[]
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800194 {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 /**
197 * Maximum Length Of A LIKE Or GLOB Pattern
198 * The pattern matching algorithm used in the default LIKE and GLOB implementation
199 * of SQLite can exhibit O(N^2) performance (where N is the number of characters in
200 * the pattern) for certain pathological cases. To avoid denial-of-service attacks
201 * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes.
202 * The default value of this limit is 50000. A modern workstation can evaluate
203 * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly.
204 * The denial of service problem only comes into play when the pattern length gets
205 * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns
206 * are at most a few dozen bytes in length, paranoid application developers may
207 * want to reduce this parameter to something in the range of a few hundred
208 * if they know that external users are able to generate arbitrary patterns.
209 */
210 public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000;
211
212 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700213 * Open flag: Flag for {@link #openDatabase} to open the database for reading and writing.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 * If the disk is full, this may fail even before you actually write anything.
215 *
216 * {@more} Note that the value of this flag is 0, so it is the default.
217 */
218 public static final int OPEN_READWRITE = 0x00000000; // update native code if changing
219
220 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700221 * Open flag: Flag for {@link #openDatabase} to open the database for reading only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 * This is the only reliable way to open a database if the disk may be full.
223 */
224 public static final int OPEN_READONLY = 0x00000001; // update native code if changing
225
226 private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing
227
228 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700229 * Open flag: Flag for {@link #openDatabase} to open the database without support for
230 * localized collators.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 *
232 * {@more} This causes the collator <code>LOCALIZED</code> not to be created.
233 * You must be consistent when using this flag to use the setting the database was
234 * created with. If this is set, {@link #setLocale} will do nothing.
235 */
236 public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing
237
238 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700239 * Open flag: Flag for {@link #openDatabase} to create the database file if it does not
240 * already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 */
242 public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing
243
244 /**
Jeff Brown47847f32012-03-22 19:13:11 -0700245 * Open flag: Flag for {@link #openDatabase} to open the database file with
246 * write-ahead logging enabled by default. Using this flag is more efficient
247 * than calling {@link #enableWriteAheadLogging}.
248 *
249 * Write-ahead logging cannot be used with read-only databases so the value of
250 * this flag is ignored if the database is opened read-only.
251 *
252 * @see #enableWriteAheadLogging
253 */
254 public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;
255
256 /**
Fyodor Kupolov692573b2018-03-06 12:34:36 -0800257 * Open flag: Flag for {@link #openDatabase} to disable Compatibility WAL when opening database.
258 *
259 * @hide
260 */
261 public static final int DISABLE_COMPATIBILITY_WAL = 0x40000000;
262
263 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700264 * Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}.
Vasu Norib729dcc2010-09-14 11:35:49 -0700265 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700266 * Each prepared-statement is between 1K - 6K, depending on the complexity of the
267 * SQL statement & schema. A large SQL cache may use a significant amount of memory.
Vasu Norie495d1f2010-01-06 16:34:19 -0800268 */
Vasu Nori90a367262010-04-12 12:49:09 -0700269 public static final int MAX_SQL_CACHE_SIZE = 100;
Vasu Norib729dcc2010-09-14 11:35:49 -0700270
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700271 private SQLiteDatabase(final String path, final int openFlags,
272 CursorFactory cursorFactory, DatabaseErrorHandler errorHandler,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800273 int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs,
274 String journalMode, String syncMode) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700275 mCursorFactory = cursorFactory;
276 mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler();
277 mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700278 mConfigurationLocked.lookasideSlotSize = lookasideSlotSize;
279 mConfigurationLocked.lookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700280 // Disable lookaside allocator on low-RAM devices
281 if (ActivityManager.isLowRamDeviceStatic()) {
282 mConfigurationLocked.lookasideSlotCount = 0;
283 mConfigurationLocked.lookasideSlotSize = 0;
284 }
285 long effectiveTimeoutMs = Long.MAX_VALUE;
286 // Never close idle connections for in-memory databases
287 if (!mConfigurationLocked.isInMemoryDb()) {
288 // First, check app-specific value. Otherwise use defaults
289 // -1 in idleConnectionTimeoutMs indicates unset value
290 if (idleConnectionTimeoutMs >= 0) {
291 effectiveTimeoutMs = idleConnectionTimeoutMs;
292 } else if (DEBUG_CLOSE_IDLE_CONNECTIONS) {
293 effectiveTimeoutMs = SQLiteGlobal.getIdleConnectionTimeout();
294 }
295 }
296 mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800297 mConfigurationLocked.journalMode = journalMode;
298 mConfigurationLocked.syncMode = syncMode;
Fyodor Kupolov692573b2018-03-06 12:34:36 -0800299 if (!SQLiteGlobal.isCompatibilityWalSupported() || (
300 SQLiteCompatibilityWalFlags.areFlagsSet() && !SQLiteCompatibilityWalFlags
301 .isCompatibilityWalSupported())) {
302 mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
Fyodor Kupolovee90c032017-12-12 11:52:57 -0800303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700305
Jeff Browne5360fb2011-10-31 17:48:13 -0700306 @Override
307 protected void finalize() throws Throwable {
308 try {
309 dispose(true);
310 } finally {
311 super.finalize();
312 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700313 }
314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 @Override
316 protected void onAllReferencesReleased() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700317 dispose(false);
318 }
319
320 private void dispose(boolean finalized) {
321 final SQLiteConnectionPool pool;
322 synchronized (mLock) {
323 if (mCloseGuardLocked != null) {
324 if (finalized) {
325 mCloseGuardLocked.warnIfOpen();
326 }
327 mCloseGuardLocked.close();
328 }
329
330 pool = mConnectionPoolLocked;
331 mConnectionPoolLocked = null;
332 }
333
334 if (!finalized) {
335 synchronized (sActiveDatabases) {
336 sActiveDatabases.remove(this);
337 }
338
339 if (pool != null) {
340 pool.close();
341 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 }
343 }
344
345 /**
346 * Attempts to release memory that SQLite holds but does not require to
347 * operate properly. Typically this memory will come from the page cache.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700348 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 * @return the number of bytes actually released
350 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700351 public static int releaseMemory() {
352 return SQLiteGlobal.releaseMemory();
353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354
355 /**
356 * Control whether or not the SQLiteDatabase is made thread-safe by using locks
357 * around critical sections. This is pretty expensive, so if you know that your
358 * DB will only be used by a single thread then you should set this to false.
359 * The default is true.
360 * @param lockingEnabled set to true to enable locks, false otherwise
Jeff Browne5360fb2011-10-31 17:48:13 -0700361 *
362 * @deprecated This method now does nothing. Do not use.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700364 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 public void setLockingEnabled(boolean lockingEnabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 }
367
368 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700369 * Gets a label to use when describing the database in log messages.
370 * @return The label.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700372 String getLabel() {
373 synchronized (mLock) {
374 return mConfigurationLocked.label;
375 }
376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377
Jeff Browne5360fb2011-10-31 17:48:13 -0700378 /**
379 * Sends a corruption message to the database error handler.
380 */
381 void onCorruption() {
382 EventLog.writeEvent(EVENT_DB_CORRUPT, getLabel());
Vasu Noriccd95442010-05-28 17:04:16 -0700383 mErrorHandler.onCorruption(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 }
385
386 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700387 * Gets the {@link SQLiteSession} that belongs to this thread for this database.
388 * Once a thread has obtained a session, it will continue to obtain the same
389 * session even after the database has been closed (although the session will not
390 * be usable). However, a thread that does not already have a session cannot
391 * obtain one after the database has been closed.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700392 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700393 * The idea is that threads that have active connections to the database may still
394 * have work to complete even after the call to {@link #close}. Active database
395 * connections are not actually disposed until they are released by the threads
396 * that own them.
397 *
398 * @return The session, never null.
399 *
400 * @throws IllegalStateException if the thread does not yet have a session and
401 * the database is not open.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700403 SQLiteSession getThreadSession() {
404 return mThreadSession.get(); // initialValue() throws if database closed
Vasu Nori6d970252010-10-05 10:48:49 -0700405 }
Vasu Nori16057fa2011-03-18 11:40:37 -0700406
Jeff Browne5360fb2011-10-31 17:48:13 -0700407 SQLiteSession createSession() {
408 final SQLiteConnectionPool pool;
409 synchronized (mLock) {
410 throwIfNotOpenLocked();
411 pool = mConnectionPoolLocked;
Vasu Nori6d970252010-10-05 10:48:49 -0700412 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700413 return new SQLiteSession(pool);
Vasu Norid4608a32011-02-03 16:24:06 -0800414 }
415
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700417 * Gets default connection flags that are appropriate for this thread, taking into
418 * account whether the thread is acting on behalf of the UI.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700420 * @param readOnly True if the connection should be read-only.
421 * @return The connection flags.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700423 int getThreadDefaultConnectionFlags(boolean readOnly) {
424 int flags = readOnly ? SQLiteConnectionPool.CONNECTION_FLAG_READ_ONLY :
425 SQLiteConnectionPool.CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY;
426 if (isMainThread()) {
427 flags |= SQLiteConnectionPool.CONNECTION_FLAG_INTERACTIVE;
428 }
429 return flags;
Vasu Nori16057fa2011-03-18 11:40:37 -0700430 }
431
Jeff Browne5360fb2011-10-31 17:48:13 -0700432 private static boolean isMainThread() {
433 // FIXME: There should be a better way to do this.
434 // Would also be nice to have something that would work across Binder calls.
435 Looper looper = Looper.myLooper();
436 return looper != null && looper == Looper.getMainLooper();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 }
438
439 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700440 * Begins a transaction in EXCLUSIVE mode.
441 * <p>
442 * Transactions can be nested.
443 * When the outer transaction is ended all of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 * the work done in that transaction and all of the nested transactions will be committed or
445 * rolled back. The changes will be rolled back if any transaction is ended without being
446 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700447 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 * <p>Here is the standard idiom for transactions:
449 *
450 * <pre>
451 * db.beginTransaction();
452 * try {
453 * ...
454 * db.setTransactionSuccessful();
455 * } finally {
456 * db.endTransaction();
457 * }
458 * </pre>
459 */
460 public void beginTransaction() {
Vasu Nori6c354da2010-04-26 23:33:39 -0700461 beginTransaction(null /* transactionStatusCallback */, true);
462 }
463
464 /**
465 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
466 * the outer transaction is ended all of the work done in that transaction
467 * and all of the nested transactions will be committed or rolled back. The
468 * changes will be rolled back if any transaction is ended without being
469 * marked as clean (by calling setTransactionSuccessful). Otherwise they
470 * will be committed.
471 * <p>
472 * Here is the standard idiom for transactions:
473 *
474 * <pre>
475 * db.beginTransactionNonExclusive();
476 * try {
477 * ...
478 * db.setTransactionSuccessful();
479 * } finally {
480 * db.endTransaction();
481 * }
482 * </pre>
483 */
484 public void beginTransactionNonExclusive() {
485 beginTransaction(null /* transactionStatusCallback */, false);
Fred Quintanac4516a72009-09-03 12:14:06 -0700486 }
487
488 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700489 * Begins a transaction in EXCLUSIVE mode.
490 * <p>
491 * Transactions can be nested.
492 * When the outer transaction is ended all of
Fred Quintanac4516a72009-09-03 12:14:06 -0700493 * the work done in that transaction and all of the nested transactions will be committed or
494 * rolled back. The changes will be rolled back if any transaction is ended without being
495 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700496 * </p>
Fred Quintanac4516a72009-09-03 12:14:06 -0700497 * <p>Here is the standard idiom for transactions:
498 *
499 * <pre>
500 * db.beginTransactionWithListener(listener);
501 * try {
502 * ...
503 * db.setTransactionSuccessful();
504 * } finally {
505 * db.endTransaction();
506 * }
507 * </pre>
Vasu Noriccd95442010-05-28 17:04:16 -0700508 *
Fred Quintanac4516a72009-09-03 12:14:06 -0700509 * @param transactionListener listener that should be notified when the transaction begins,
510 * commits, or is rolled back, either explicitly or by a call to
511 * {@link #yieldIfContendedSafely}.
512 */
513 public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
Vasu Nori6c354da2010-04-26 23:33:39 -0700514 beginTransaction(transactionListener, true);
515 }
516
517 /**
518 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
519 * the outer transaction is ended all of the work done in that transaction
520 * and all of the nested transactions will be committed or rolled back. The
521 * changes will be rolled back if any transaction is ended without being
522 * marked as clean (by calling setTransactionSuccessful). Otherwise they
523 * will be committed.
524 * <p>
525 * Here is the standard idiom for transactions:
526 *
527 * <pre>
528 * db.beginTransactionWithListenerNonExclusive(listener);
529 * try {
530 * ...
531 * db.setTransactionSuccessful();
532 * } finally {
533 * db.endTransaction();
534 * }
535 * </pre>
536 *
537 * @param transactionListener listener that should be notified when the
538 * transaction begins, commits, or is rolled back, either
539 * explicitly or by a call to {@link #yieldIfContendedSafely}.
540 */
541 public void beginTransactionWithListenerNonExclusive(
542 SQLiteTransactionListener transactionListener) {
543 beginTransaction(transactionListener, false);
544 }
545
546 private void beginTransaction(SQLiteTransactionListener transactionListener,
547 boolean exclusive) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800548 acquireReference();
549 try {
550 getThreadSession().beginTransaction(
551 exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
552 SQLiteSession.TRANSACTION_MODE_IMMEDIATE,
553 transactionListener,
554 getThreadDefaultConnectionFlags(false /*readOnly*/), null);
555 } finally {
556 releaseReference();
557 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 }
559
560 /**
561 * End a transaction. See beginTransaction for notes about how to use this and when transactions
562 * are committed and rolled back.
563 */
564 public void endTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800565 acquireReference();
566 try {
567 getThreadSession().endTransaction(null);
568 } finally {
569 releaseReference();
570 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 }
572
573 /**
574 * Marks the current transaction as successful. Do not do any more database work between
575 * calling this and calling endTransaction. Do as little non-database work as possible in that
576 * situation too. If any errors are encountered between this and endTransaction the transaction
577 * will still be committed.
578 *
579 * @throws IllegalStateException if the current thread is not in a transaction or the
580 * transaction is already marked as successful.
581 */
582 public void setTransactionSuccessful() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800583 acquireReference();
584 try {
585 getThreadSession().setTransactionSuccessful();
586 } finally {
587 releaseReference();
588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 }
590
591 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700592 * Returns true if the current thread has a transaction pending.
593 *
594 * @return True if the current thread is in a transaction.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 */
596 public boolean inTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800597 acquireReference();
598 try {
599 return getThreadSession().hasTransaction();
600 } finally {
601 releaseReference();
602 }
Vasu Norice38b982010-07-22 13:57:13 -0700603 }
604
605 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700606 * Returns true if the current thread is holding an active connection to the database.
Vasu Norice38b982010-07-22 13:57:13 -0700607 * <p>
Jeff Browne5360fb2011-10-31 17:48:13 -0700608 * The name of this method comes from a time when having an active connection
609 * to the database meant that the thread was holding an actual lock on the
610 * database. Nowadays, there is no longer a true "database lock" although threads
611 * may block if they cannot acquire a database connection to perform a
612 * particular operation.
613 * </p>
Vasu Norice38b982010-07-22 13:57:13 -0700614 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700615 * @return True if the current thread is holding an active connection to the database.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 */
617 public boolean isDbLockedByCurrentThread() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800618 acquireReference();
619 try {
620 return getThreadSession().hasConnection();
621 } finally {
622 releaseReference();
623 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 }
625
626 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700627 * Always returns false.
628 * <p>
629 * There is no longer the concept of a database lock, so this method always returns false.
630 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700632 * @return False.
633 * @deprecated Always returns false. Do not use this method.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700635 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 public boolean isDbLockedByOtherThreads() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700637 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638 }
639
640 /**
641 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
642 * successful so far. Do not call setTransactionSuccessful before calling this. When this
643 * returns a new transaction will have been created but not marked as successful.
644 * @return true if the transaction was yielded
645 * @deprecated if the db is locked more than once (becuase of nested transactions) then the lock
646 * will not be yielded. Use yieldIfContendedSafely instead.
647 */
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700648 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 public boolean yieldIfContended() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700650 return yieldIfContendedHelper(false /* do not check yielding */,
651 -1 /* sleepAfterYieldDelay */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652 }
653
654 /**
655 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
656 * successful so far. Do not call setTransactionSuccessful before calling this. When this
657 * returns a new transaction will have been created but not marked as successful. This assumes
658 * that there are no nested transactions (beginTransaction has only been called once) and will
Fred Quintana5c7aede2009-08-27 21:41:27 -0700659 * throw an exception if that is not the case.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660 * @return true if the transaction was yielded
661 */
662 public boolean yieldIfContendedSafely() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700663 return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664 }
665
Fred Quintana5c7aede2009-08-27 21:41:27 -0700666 /**
667 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
668 * successful so far. Do not call setTransactionSuccessful before calling this. When this
669 * returns a new transaction will have been created but not marked as successful. This assumes
670 * that there are no nested transactions (beginTransaction has only been called once) and will
671 * throw an exception if that is not the case.
672 * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if
673 * the lock was actually yielded. This will allow other background threads to make some
674 * more progress than they would if we started the transaction immediately.
675 * @return true if the transaction was yielded
676 */
677 public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
678 return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay);
679 }
680
Jeff Browne5360fb2011-10-31 17:48:13 -0700681 private boolean yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800682 acquireReference();
683 try {
684 return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null);
685 } finally {
686 releaseReference();
687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 }
689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700691 * Deprecated.
Vasu Nori95675132010-07-21 16:24:40 -0700692 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693 */
Vasu Nori95675132010-07-21 16:24:40 -0700694 @Deprecated
695 public Map<String, String> getSyncedTables() {
696 return new HashMap<String, String>(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 }
698
699 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 * Open the database according to the flags {@link #OPEN_READWRITE}
701 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
702 *
703 * <p>Sets the locale of the database to the the system's current locale.
704 * Call {@link #setLocale} if you would like something else.</p>
705 *
706 * @param path to database file to open and/or create
707 * @param factory an optional factory class that is called to instantiate a
708 * cursor when query is called, or null for default
709 * @param flags to control database access mode
710 * @return the newly opened database
711 * @throws SQLiteException if the database cannot be opened
712 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700713 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
714 @DatabaseOpenFlags int flags) {
Jeff Brown47847f32012-03-22 19:13:11 -0700715 return openDatabase(path, factory, flags, null);
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700716 }
717
718 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700719 * Open the database according to the specified {@link OpenParams parameters}
720 *
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700721 * @param path path to database file to open and/or create.
722 * <p><strong>Important:</strong> The file should be constructed either from an absolute path or
723 * by using {@link android.content.Context#getDatabasePath(String)}.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700724 * @param openParams configuration parameters that are used for opening {@link SQLiteDatabase}
725 * @return the newly opened database
726 * @throws SQLiteException if the database cannot be opened
727 */
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700728 public static SQLiteDatabase openDatabase(@NonNull File path,
729 @NonNull OpenParams openParams) {
730 return openDatabase(path.getPath(), openParams);
731 }
732
733 private static SQLiteDatabase openDatabase(@NonNull String path,
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700734 @NonNull OpenParams openParams) {
735 Preconditions.checkArgument(openParams != null, "OpenParams cannot be null");
736 SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags,
737 openParams.mCursorFactory, openParams.mErrorHandler,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700738 openParams.mLookasideSlotSize, openParams.mLookasideSlotCount,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800739 openParams.mIdleConnectionTimeout, openParams.mJournalMode, openParams.mSyncMode);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700740 db.open();
741 return db;
742 }
743
744 /**
Vasu Nori74f170f2010-06-01 18:06:18 -0700745 * Open the database according to the flags {@link #OPEN_READWRITE}
746 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
747 *
748 * <p>Sets the locale of the database to the the system's current locale.
749 * Call {@link #setLocale} if you would like something else.</p>
750 *
751 * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be
752 * used to handle corruption when sqlite reports database corruption.</p>
753 *
754 * @param path to database file to open and/or create
755 * @param factory an optional factory class that is called to instantiate a
756 * cursor when query is called, or null for default
757 * @param flags to control database access mode
758 * @param errorHandler the {@link DatabaseErrorHandler} obj to be used to handle corruption
759 * when sqlite reports database corruption
760 * @return the newly opened database
761 * @throws SQLiteException if the database cannot be opened
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700762 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700763 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
764 @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler) {
Fyodor Kupolov13a4b372017-11-07 18:45:35 -0800765 SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1, -1, null,
766 null);
Jeff Browne5360fb2011-10-31 17:48:13 -0700767 db.open();
768 return db;
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700769 }
770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800771 /**
772 * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
773 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700774 public static SQLiteDatabase openOrCreateDatabase(@NonNull File file,
775 @Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 return openOrCreateDatabase(file.getPath(), factory);
777 }
778
779 /**
780 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
781 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700782 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
783 @Nullable CursorFactory factory) {
Jeff Brown47847f32012-03-22 19:13:11 -0700784 return openDatabase(path, factory, CREATE_IF_NECESSARY, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 }
786
787 /**
Vasu Nori6c354da2010-04-26 23:33:39 -0700788 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler).
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700789 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700790 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
791 @Nullable CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler) {
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700792 return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler);
793 }
794
Jeff Brown559d0642012-02-29 10:19:12 -0800795 /**
Jeff Brown79087e42012-03-01 19:52:44 -0800796 * Deletes a database including its journal file and other auxiliary files
797 * that may have been created by the database engine.
798 *
799 * @param file The database file path.
800 * @return True if the database was successfully deleted.
801 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700802 public static boolean deleteDatabase(@NonNull File file) {
Jeff Brown79087e42012-03-01 19:52:44 -0800803 if (file == null) {
804 throw new IllegalArgumentException("file must not be null");
805 }
806
807 boolean deleted = false;
808 deleted |= file.delete();
809 deleted |= new File(file.getPath() + "-journal").delete();
810 deleted |= new File(file.getPath() + "-shm").delete();
811 deleted |= new File(file.getPath() + "-wal").delete();
812
813 File dir = file.getParentFile();
814 if (dir != null) {
815 final String prefix = file.getName() + "-mj";
Jeff Brownfce58902014-01-24 13:20:57 -0800816 File[] files = dir.listFiles(new FileFilter() {
Jeff Brown79087e42012-03-01 19:52:44 -0800817 @Override
818 public boolean accept(File candidate) {
819 return candidate.getName().startsWith(prefix);
820 }
Jeff Brownfce58902014-01-24 13:20:57 -0800821 });
822 if (files != null) {
823 for (File masterJournal : files) {
824 deleted |= masterJournal.delete();
825 }
Jeff Brown79087e42012-03-01 19:52:44 -0800826 }
827 }
828 return deleted;
829 }
830
831 /**
Jeff Brown559d0642012-02-29 10:19:12 -0800832 * Reopens the database in read-write mode.
833 * If the database is already read-write, does nothing.
834 *
835 * @throws SQLiteException if the database could not be reopened as requested, in which
836 * case it remains open in read only mode.
837 * @throws IllegalStateException if the database is not open.
838 *
839 * @see #isReadOnly()
840 * @hide
841 */
842 public void reopenReadWrite() {
843 synchronized (mLock) {
844 throwIfNotOpenLocked();
845
846 if (!isReadOnlyLocked()) {
847 return; // nothing to do
848 }
849
850 // Reopen the database in read-write mode.
851 final int oldOpenFlags = mConfigurationLocked.openFlags;
852 mConfigurationLocked.openFlags = (mConfigurationLocked.openFlags & ~OPEN_READ_MASK)
853 | OPEN_READWRITE;
854 try {
855 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
856 } catch (RuntimeException ex) {
857 mConfigurationLocked.openFlags = oldOpenFlags;
858 throw ex;
859 }
860 }
861 }
862
Jeff Browne5360fb2011-10-31 17:48:13 -0700863 private void open() {
864 try {
865 try {
866 openInner();
867 } catch (SQLiteDatabaseCorruptException ex) {
868 onCorruption();
869 openInner();
870 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700871 } catch (SQLiteException ex) {
872 Log.e(TAG, "Failed to open database '" + getLabel() + "'.", ex);
873 close();
874 throw ex;
875 }
876 }
877
878 private void openInner() {
879 synchronized (mLock) {
880 assert mConnectionPoolLocked == null;
881 mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked);
882 mCloseGuardLocked.open("close");
883 }
884
885 synchronized (sActiveDatabases) {
886 sActiveDatabases.put(this, null);
887 }
888 }
889
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700890 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 * Create a memory backed SQLite database. Its contents will be destroyed
892 * when the database is closed.
893 *
894 * <p>Sets the locale of the database to the the system's current locale.
895 * Call {@link #setLocale} if you would like something else.</p>
896 *
897 * @param factory an optional factory class that is called to instantiate a
898 * cursor when query is called
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700899 * @return a SQLiteDatabase instance
900 * @throws SQLiteException if the database cannot be created
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800901 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700902 @NonNull
903 public static SQLiteDatabase create(@Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800904 // This is a magic string with special meaning for SQLite.
Jeff Browne5360fb2011-10-31 17:48:13 -0700905 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
906 factory, CREATE_IF_NECESSARY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 }
908
909 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700910 * Create a memory backed SQLite database. Its contents will be destroyed
911 * when the database is closed.
912 *
913 * <p>Sets the locale of the database to the the system's current locale.
914 * Call {@link #setLocale} if you would like something else.</p>
915 * @param openParams configuration parameters that are used for opening SQLiteDatabase
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700916 * @return a SQLiteDatabase instance
917 * @throws SQLException if the database cannot be created
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700918 */
919 @NonNull
920 public static SQLiteDatabase createInMemory(@NonNull OpenParams openParams) {
921 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
922 openParams.toBuilder().addOpenFlags(CREATE_IF_NECESSARY).build());
923 }
924
925 /**
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400926 * Registers a CustomFunction callback as a function that can be called from
Jeff Browne5360fb2011-10-31 17:48:13 -0700927 * SQLite database triggers.
928 *
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400929 * @param name the name of the sqlite3 function
930 * @param numArgs the number of arguments for the function
931 * @param function callback to call when the function is executed
932 * @hide
933 */
934 public void addCustomFunction(String name, int numArgs, CustomFunction function) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700935 // Create wrapper (also validates arguments).
936 SQLiteCustomFunction wrapper = new SQLiteCustomFunction(name, numArgs, function);
937
938 synchronized (mLock) {
939 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -0700940
Jeff Browne5360fb2011-10-31 17:48:13 -0700941 mConfigurationLocked.customFunctions.add(wrapper);
Jeff Browne67ca422012-03-21 17:24:05 -0700942 try {
943 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
944 } catch (RuntimeException ex) {
945 mConfigurationLocked.customFunctions.remove(wrapper);
946 throw ex;
947 }
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400948 }
949 }
950
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400951 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 * Gets the database version.
953 *
954 * @return the database version
955 */
956 public int getVersion() {
Vasu Noriccd95442010-05-28 17:04:16 -0700957 return ((Long) DatabaseUtils.longForQuery(this, "PRAGMA user_version;", null)).intValue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958 }
959
960 /**
961 * Sets the database version.
962 *
963 * @param version the new database version
964 */
965 public void setVersion(int version) {
966 execSQL("PRAGMA user_version = " + version);
967 }
968
969 /**
970 * Returns the maximum size the database may grow to.
971 *
972 * @return the new maximum database size
973 */
974 public long getMaximumSize() {
Vasu Noriccd95442010-05-28 17:04:16 -0700975 long pageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count;", null);
976 return pageCount * getPageSize();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 }
978
979 /**
980 * Sets the maximum size the database will grow to. The maximum size cannot
981 * be set below the current size.
982 *
983 * @param numBytes the maximum database size, in bytes
984 * @return the new maximum database size
985 */
986 public long setMaximumSize(long numBytes) {
Vasu Noriccd95442010-05-28 17:04:16 -0700987 long pageSize = getPageSize();
988 long numPages = numBytes / pageSize;
989 // If numBytes isn't a multiple of pageSize, bump up a page
990 if ((numBytes % pageSize) != 0) {
991 numPages++;
Vasu Norif3cf8a42010-03-23 11:41:44 -0700992 }
Vasu Noriccd95442010-05-28 17:04:16 -0700993 long newPageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count = " + numPages,
994 null);
995 return newPageCount * pageSize;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 }
997
998 /**
999 * Returns the current database page size, in bytes.
1000 *
1001 * @return the database page size, in bytes
1002 */
1003 public long getPageSize() {
Vasu Noriccd95442010-05-28 17:04:16 -07001004 return DatabaseUtils.longForQuery(this, "PRAGMA page_size;", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 }
1006
1007 /**
1008 * Sets the database page size. The page size must be a power of two. This
1009 * method does not work if any data has been written to the database file,
1010 * and must be called right after the database has been created.
1011 *
1012 * @param numBytes the database page size, in bytes
1013 */
1014 public void setPageSize(long numBytes) {
1015 execSQL("PRAGMA page_size = " + numBytes);
1016 }
1017
1018 /**
1019 * Mark this table as syncable. When an update occurs in this table the
1020 * _sync_dirty field will be set to ensure proper syncing operation.
1021 *
1022 * @param table the table to mark as syncable
1023 * @param deletedTable The deleted table that corresponds to the
1024 * syncable table
Vasu Nori95675132010-07-21 16:24:40 -07001025 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026 */
Vasu Nori95675132010-07-21 16:24:40 -07001027 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001028 public void markTableSyncable(String table, String deletedTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 }
1030
1031 /**
1032 * Mark this table as syncable, with the _sync_dirty residing in another
1033 * table. When an update occurs in this table the _sync_dirty field of the
1034 * row in updateTable with the _id in foreignKey will be set to
1035 * ensure proper syncing operation.
1036 *
1037 * @param table an update on this table will trigger a sync time removal
1038 * @param foreignKey this is the column in table whose value is an _id in
1039 * updateTable
1040 * @param updateTable this is the table that will have its _sync_dirty
Vasu Nori95675132010-07-21 16:24:40 -07001041 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042 */
Vasu Nori95675132010-07-21 16:24:40 -07001043 @Deprecated
1044 public void markTableSyncable(String table, String foreignKey, String updateTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 }
1046
1047 /**
1048 * Finds the name of the first table, which is editable.
1049 *
1050 * @param tables a list of tables
1051 * @return the first table listed
1052 */
1053 public static String findEditTable(String tables) {
1054 if (!TextUtils.isEmpty(tables)) {
1055 // find the first word terminated by either a space or a comma
1056 int spacepos = tables.indexOf(' ');
1057 int commapos = tables.indexOf(',');
1058
1059 if (spacepos > 0 && (spacepos < commapos || commapos < 0)) {
1060 return tables.substring(0, spacepos);
1061 } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) {
1062 return tables.substring(0, commapos);
1063 }
1064 return tables;
1065 } else {
1066 throw new IllegalStateException("Invalid tables");
1067 }
1068 }
1069
1070 /**
1071 * Compiles an SQL statement into a reusable pre-compiled statement object.
1072 * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the
1073 * statement and fill in those values with {@link SQLiteProgram#bindString}
1074 * and {@link SQLiteProgram#bindLong} each time you want to run the
1075 * statement. Statements may not return result sets larger than 1x1.
Vasu Nori2827d6d2010-07-04 00:26:18 -07001076 *<p>
1077 * No two threads should be using the same {@link SQLiteStatement} at the same time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001078 *
1079 * @param sql The raw SQL statement, may contain ? for unknown values to be
1080 * bound later.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001081 * @return A pre-compiled {@link SQLiteStatement} object. Note that
1082 * {@link SQLiteStatement}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001083 */
1084 public SQLiteStatement compileStatement(String sql) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001085 acquireReference();
1086 try {
1087 return new SQLiteStatement(this, sql, null);
1088 } finally {
1089 releaseReference();
1090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 }
1092
1093 /**
1094 * Query the given URL, returning a {@link Cursor} over the result set.
1095 *
1096 * @param distinct true if you want each row to be unique, false otherwise.
1097 * @param table The table name to compile the query against.
1098 * @param columns A list of which columns to return. Passing null will
1099 * return all columns, which is discouraged to prevent reading
1100 * data from storage that isn't going to be used.
1101 * @param selection A filter declaring which rows to return, formatted as an
1102 * SQL WHERE clause (excluding the WHERE itself). Passing null
1103 * will return all rows for the given table.
1104 * @param selectionArgs You may include ?s in selection, which will be
1105 * replaced by the values from selectionArgs, in order that they
1106 * appear in the selection. The values will be bound as Strings.
1107 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1108 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1109 * will cause the rows to not be grouped.
1110 * @param having A filter declare which row groups to include in the cursor,
1111 * if row grouping is being used, formatted as an SQL HAVING
1112 * clause (excluding the HAVING itself). Passing null will cause
1113 * all row groups to be included, and is required when row
1114 * grouping is not being used.
1115 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1116 * (excluding the ORDER BY itself). Passing null will use the
1117 * default sort order, which may be unordered.
1118 * @param limit Limits the number of rows returned by the query,
1119 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001120 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1121 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122 * @see Cursor
1123 */
1124 public Cursor query(boolean distinct, String table, String[] columns,
1125 String selection, String[] selectionArgs, String groupBy,
1126 String having, String orderBy, String limit) {
1127 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown75ea64f2012-01-25 19:37:13 -08001128 groupBy, having, orderBy, limit, null);
1129 }
1130
1131 /**
1132 * Query the given URL, returning a {@link Cursor} over the result set.
1133 *
1134 * @param distinct true if you want each row to be unique, false otherwise.
1135 * @param table The table name to compile the query against.
1136 * @param columns A list of which columns to return. Passing null will
1137 * return all columns, which is discouraged to prevent reading
1138 * data from storage that isn't going to be used.
1139 * @param selection A filter declaring which rows to return, formatted as an
1140 * SQL WHERE clause (excluding the WHERE itself). Passing null
1141 * will return all rows for the given table.
1142 * @param selectionArgs You may include ?s in selection, which will be
1143 * replaced by the values from selectionArgs, in order that they
1144 * appear in the selection. The values will be bound as Strings.
1145 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1146 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1147 * will cause the rows to not be grouped.
1148 * @param having A filter declare which row groups to include in the cursor,
1149 * if row grouping is being used, formatted as an SQL HAVING
1150 * clause (excluding the HAVING itself). Passing null will cause
1151 * all row groups to be included, and is required when row
1152 * grouping is not being used.
1153 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1154 * (excluding the ORDER BY itself). Passing null will use the
1155 * default sort order, which may be unordered.
1156 * @param limit Limits the number of rows returned by the query,
1157 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001158 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001159 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1160 * when the query is executed.
1161 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1162 * {@link Cursor}s are not synchronized, see the documentation for more details.
1163 * @see Cursor
1164 */
1165 public Cursor query(boolean distinct, String table, String[] columns,
1166 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001167 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001168 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001169 groupBy, having, orderBy, limit, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170 }
1171
1172 /**
1173 * Query the given URL, returning a {@link Cursor} over the result set.
1174 *
1175 * @param cursorFactory the cursor factory to use, or null for the default factory
1176 * @param distinct true if you want each row to be unique, false otherwise.
1177 * @param table The table name to compile the query against.
1178 * @param columns A list of which columns to return. Passing null will
1179 * return all columns, which is discouraged to prevent reading
1180 * data from storage that isn't going to be used.
1181 * @param selection A filter declaring which rows to return, formatted as an
1182 * SQL WHERE clause (excluding the WHERE itself). Passing null
1183 * will return all rows for the given table.
1184 * @param selectionArgs You may include ?s in selection, which will be
1185 * replaced by the values from selectionArgs, in order that they
1186 * appear in the selection. The values will be bound as Strings.
1187 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1188 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1189 * will cause the rows to not be grouped.
1190 * @param having A filter declare which row groups to include in the cursor,
1191 * if row grouping is being used, formatted as an SQL HAVING
1192 * clause (excluding the HAVING itself). Passing null will cause
1193 * all row groups to be included, and is required when row
1194 * grouping is not being used.
1195 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1196 * (excluding the ORDER BY itself). Passing null will use the
1197 * default sort order, which may be unordered.
1198 * @param limit Limits the number of rows returned by the query,
1199 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001200 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1201 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001202 * @see Cursor
1203 */
1204 public Cursor queryWithFactory(CursorFactory cursorFactory,
1205 boolean distinct, String table, String[] columns,
1206 String selection, String[] selectionArgs, String groupBy,
1207 String having, String orderBy, String limit) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001208 return queryWithFactory(cursorFactory, distinct, table, columns, selection,
1209 selectionArgs, groupBy, having, orderBy, limit, null);
1210 }
1211
1212 /**
1213 * Query the given URL, returning a {@link Cursor} over the result set.
1214 *
1215 * @param cursorFactory the cursor factory to use, or null for the default factory
1216 * @param distinct true if you want each row to be unique, false otherwise.
1217 * @param table The table name to compile the query against.
1218 * @param columns A list of which columns to return. Passing null will
1219 * return all columns, which is discouraged to prevent reading
1220 * data from storage that isn't going to be used.
1221 * @param selection A filter declaring which rows to return, formatted as an
1222 * SQL WHERE clause (excluding the WHERE itself). Passing null
1223 * will return all rows for the given table.
1224 * @param selectionArgs You may include ?s in selection, which will be
1225 * replaced by the values from selectionArgs, in order that they
1226 * appear in the selection. The values will be bound as Strings.
1227 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1228 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1229 * will cause the rows to not be grouped.
1230 * @param having A filter declare which row groups to include in the cursor,
1231 * if row grouping is being used, formatted as an SQL HAVING
1232 * clause (excluding the HAVING itself). Passing null will cause
1233 * all row groups to be included, and is required when row
1234 * grouping is not being used.
1235 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1236 * (excluding the ORDER BY itself). Passing null will use the
1237 * default sort order, which may be unordered.
1238 * @param limit Limits the number of rows returned by the query,
1239 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001240 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001241 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1242 * when the query is executed.
1243 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1244 * {@link Cursor}s are not synchronized, see the documentation for more details.
1245 * @see Cursor
1246 */
1247 public Cursor queryWithFactory(CursorFactory cursorFactory,
1248 boolean distinct, String table, String[] columns,
1249 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001250 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001251 acquireReference();
1252 try {
1253 String sql = SQLiteQueryBuilder.buildQueryString(
1254 distinct, table, columns, selection, groupBy, having, orderBy, limit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255
Jeff Brown03bd3022012-03-06 13:48:56 -08001256 return rawQueryWithFactory(cursorFactory, sql, selectionArgs,
1257 findEditTable(table), cancellationSignal);
1258 } finally {
1259 releaseReference();
1260 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001261 }
1262
1263 /**
1264 * Query the given table, returning a {@link Cursor} over the result set.
1265 *
1266 * @param table The table name to compile the query against.
1267 * @param columns A list of which columns to return. Passing null will
1268 * return all columns, which is discouraged to prevent reading
1269 * data from storage that isn't going to be used.
1270 * @param selection A filter declaring which rows to return, formatted as an
1271 * SQL WHERE clause (excluding the WHERE itself). Passing null
1272 * will return all rows for the given table.
1273 * @param selectionArgs You may include ?s in selection, which will be
1274 * replaced by the values from selectionArgs, in order that they
1275 * appear in the selection. The values will be bound as Strings.
1276 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1277 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1278 * will cause the rows to not be grouped.
1279 * @param having A filter declare which row groups to include in the cursor,
1280 * if row grouping is being used, formatted as an SQL HAVING
1281 * clause (excluding the HAVING itself). Passing null will cause
1282 * all row groups to be included, and is required when row
1283 * grouping is not being used.
1284 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1285 * (excluding the ORDER BY itself). Passing null will use the
1286 * default sort order, which may be unordered.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001287 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1288 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001289 * @see Cursor
1290 */
1291 public Cursor query(String table, String[] columns, String selection,
1292 String[] selectionArgs, String groupBy, String having,
1293 String orderBy) {
1294
1295 return query(false, table, columns, selection, selectionArgs, groupBy,
1296 having, orderBy, null /* limit */);
1297 }
1298
1299 /**
1300 * Query the given table, returning a {@link Cursor} over the result set.
1301 *
1302 * @param table The table name to compile the query against.
1303 * @param columns A list of which columns to return. Passing null will
1304 * return all columns, which is discouraged to prevent reading
1305 * data from storage that isn't going to be used.
1306 * @param selection A filter declaring which rows to return, formatted as an
1307 * SQL WHERE clause (excluding the WHERE itself). Passing null
1308 * will return all rows for the given table.
1309 * @param selectionArgs You may include ?s in selection, which will be
1310 * replaced by the values from selectionArgs, in order that they
1311 * appear in the selection. The values will be bound as Strings.
1312 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1313 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1314 * will cause the rows to not be grouped.
1315 * @param having A filter declare which row groups to include in the cursor,
1316 * if row grouping is being used, formatted as an SQL HAVING
1317 * clause (excluding the HAVING itself). Passing null will cause
1318 * all row groups to be included, and is required when row
1319 * grouping is not being used.
1320 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1321 * (excluding the ORDER BY itself). Passing null will use the
1322 * default sort order, which may be unordered.
1323 * @param limit Limits the number of rows returned by the query,
1324 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001325 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1326 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327 * @see Cursor
1328 */
1329 public Cursor query(String table, String[] columns, String selection,
1330 String[] selectionArgs, String groupBy, String having,
1331 String orderBy, String limit) {
1332
1333 return query(false, table, columns, selection, selectionArgs, groupBy,
1334 having, orderBy, limit);
1335 }
1336
1337 /**
1338 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1339 *
1340 * @param sql the SQL query. The SQL string must not be ; terminated
1341 * @param selectionArgs You may include ?s in where clause in the query,
1342 * which will be replaced by the values from selectionArgs. The
1343 * values will be bound as Strings.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001344 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1345 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 */
1347 public Cursor rawQuery(String sql, String[] selectionArgs) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001348 return rawQueryWithFactory(null, sql, selectionArgs, null, null);
1349 }
1350
1351 /**
1352 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1353 *
1354 * @param sql the SQL query. The SQL string must not be ; terminated
1355 * @param selectionArgs You may include ?s in where clause in the query,
1356 * which will be replaced by the values from selectionArgs. The
1357 * values will be bound as Strings.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001358 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001359 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1360 * when the query is executed.
1361 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1362 * {@link Cursor}s are not synchronized, see the documentation for more details.
1363 */
1364 public Cursor rawQuery(String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001365 CancellationSignal cancellationSignal) {
1366 return rawQueryWithFactory(null, sql, selectionArgs, null, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367 }
1368
1369 /**
1370 * Runs the provided SQL and returns a cursor over the result set.
1371 *
1372 * @param cursorFactory the cursor factory to use, or null for the default factory
1373 * @param sql the SQL query. The SQL string must not be ; terminated
1374 * @param selectionArgs You may include ?s in where clause in the query,
1375 * which will be replaced by the values from selectionArgs. The
1376 * values will be bound as Strings.
1377 * @param editTable the name of the first table, which is editable
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001378 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1379 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 */
1381 public Cursor rawQueryWithFactory(
1382 CursorFactory cursorFactory, String sql, String[] selectionArgs,
1383 String editTable) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001384 return rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable, null);
1385 }
1386
1387 /**
1388 * Runs the provided SQL and returns a cursor over the result set.
1389 *
1390 * @param cursorFactory the cursor factory to use, or null for the default factory
1391 * @param sql the SQL query. The SQL string must not be ; terminated
1392 * @param selectionArgs You may include ?s in where clause in the query,
1393 * which will be replaced by the values from selectionArgs. The
1394 * values will be bound as Strings.
1395 * @param editTable the name of the first table, which is editable
Jeff Brown4c1241d2012-02-02 17:05:00 -08001396 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001397 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1398 * when the query is executed.
1399 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1400 * {@link Cursor}s are not synchronized, see the documentation for more details.
1401 */
1402 public Cursor rawQueryWithFactory(
1403 CursorFactory cursorFactory, String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001404 String editTable, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001405 acquireReference();
1406 try {
1407 SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
1408 cancellationSignal);
1409 return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
1410 selectionArgs);
1411 } finally {
1412 releaseReference();
1413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 }
1415
1416 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 * Convenience method for inserting a row into the database.
1418 *
1419 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001420 * @param nullColumnHack optional; may be <code>null</code>.
1421 * SQL doesn't allow inserting a completely empty row without
1422 * naming at least one column name. If your provided <code>values</code> is
1423 * empty, no column names are known and an empty row can't be inserted.
1424 * If not set to null, the <code>nullColumnHack</code> parameter
1425 * provides the name of nullable column name to explicitly insert a NULL into
1426 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 * @param values this map contains the initial column values for the
1428 * row. The keys should be the column names and the values the
1429 * column values
1430 * @return the row ID of the newly inserted row, or -1 if an error occurred
1431 */
1432 public long insert(String table, String nullColumnHack, ContentValues values) {
1433 try {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001434 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 } catch (SQLException e) {
1436 Log.e(TAG, "Error inserting " + values, e);
1437 return -1;
1438 }
1439 }
1440
1441 /**
1442 * Convenience method for inserting a row into the database.
1443 *
1444 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001445 * @param nullColumnHack optional; may be <code>null</code>.
1446 * SQL doesn't allow inserting a completely empty row without
1447 * naming at least one column name. If your provided <code>values</code> is
1448 * empty, no column names are known and an empty row can't be inserted.
1449 * If not set to null, the <code>nullColumnHack</code> parameter
1450 * provides the name of nullable column name to explicitly insert a NULL into
1451 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 * @param values this map contains the initial column values for the
1453 * row. The keys should be the column names and the values the
1454 * column values
1455 * @throws SQLException
1456 * @return the row ID of the newly inserted row, or -1 if an error occurred
1457 */
1458 public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
1459 throws SQLException {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001460 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 }
1462
1463 /**
1464 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001465 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 *
1467 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001468 * @param nullColumnHack optional; may be <code>null</code>.
1469 * SQL doesn't allow inserting a completely empty row without
1470 * naming at least one column name. If your provided <code>initialValues</code> is
1471 * empty, no column names are known and an empty row can't be inserted.
1472 * If not set to null, the <code>nullColumnHack</code> parameter
1473 * provides the name of nullable column name to explicitly insert a NULL into
1474 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001476 * 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 -08001477 * @return the row ID of the newly inserted row, or -1 if an error occurred
1478 */
1479 public long replace(String table, String nullColumnHack, ContentValues initialValues) {
1480 try {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001481 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001482 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 } catch (SQLException e) {
1484 Log.e(TAG, "Error inserting " + initialValues, e);
1485 return -1;
1486 }
1487 }
1488
1489 /**
1490 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001491 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 *
1493 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001494 * @param nullColumnHack optional; may be <code>null</code>.
1495 * SQL doesn't allow inserting a completely empty row without
1496 * naming at least one column name. If your provided <code>initialValues</code> is
1497 * empty, no column names are known and an empty row can't be inserted.
1498 * If not set to null, the <code>nullColumnHack</code> parameter
1499 * provides the name of nullable column name to explicitly insert a NULL into
1500 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001502 * the row. The keys should be the column names and the values the column values.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 * @throws SQLException
1504 * @return the row ID of the newly inserted row, or -1 if an error occurred
1505 */
1506 public long replaceOrThrow(String table, String nullColumnHack,
1507 ContentValues initialValues) throws SQLException {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001508 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001509 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 }
1511
1512 /**
1513 * General method for inserting a row into the database.
1514 *
1515 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001516 * @param nullColumnHack optional; may be <code>null</code>.
1517 * SQL doesn't allow inserting a completely empty row without
1518 * naming at least one column name. If your provided <code>initialValues</code> is
1519 * empty, no column names are known and an empty row can't be inserted.
1520 * If not set to null, the <code>nullColumnHack</code> parameter
1521 * provides the name of nullable column name to explicitly insert a NULL into
1522 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 * @param initialValues this map contains the initial column values for the
1524 * row. The keys should be the column names and the values the
1525 * column values
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001526 * @param conflictAlgorithm for insert conflict resolver
Steve Pomeroyc240b602013-03-14 00:42:10 -04001527 * @return the row ID of the newly inserted row OR <code>-1</code> if either the
1528 * input parameter <code>conflictAlgorithm</code> = {@link #CONFLICT_IGNORE}
1529 * or an error occurred.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 */
1531 public long insertWithOnConflict(String table, String nullColumnHack,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001532 ContentValues initialValues, int conflictAlgorithm) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001533 acquireReference();
1534 try {
1535 StringBuilder sql = new StringBuilder();
1536 sql.append("INSERT");
1537 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1538 sql.append(" INTO ");
1539 sql.append(table);
1540 sql.append('(');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001541
Jeff Brown03bd3022012-03-06 13:48:56 -08001542 Object[] bindArgs = null;
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001543 int size = (initialValues != null && !initialValues.isEmpty())
Jeff Brown03bd3022012-03-06 13:48:56 -08001544 ? initialValues.size() : 0;
1545 if (size > 0) {
1546 bindArgs = new Object[size];
1547 int i = 0;
1548 for (String colName : initialValues.keySet()) {
1549 sql.append((i > 0) ? "," : "");
1550 sql.append(colName);
1551 bindArgs[i++] = initialValues.get(colName);
1552 }
1553 sql.append(')');
1554 sql.append(" VALUES (");
1555 for (i = 0; i < size; i++) {
1556 sql.append((i > 0) ? ",?" : "?");
1557 }
1558 } else {
1559 sql.append(nullColumnHack + ") VALUES (NULL");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 sql.append(')');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562
Jeff Brown03bd3022012-03-06 13:48:56 -08001563 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1564 try {
1565 return statement.executeInsert();
1566 } finally {
1567 statement.close();
1568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001570 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 }
1572 }
1573
1574 /**
1575 * Convenience method for deleting rows in the database.
1576 *
1577 * @param table the table to delete from
1578 * @param whereClause the optional WHERE clause to apply when deleting.
1579 * Passing null will delete all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001580 * @param whereArgs You may include ?s in the where clause, which
1581 * will be replaced by the values from whereArgs. The values
1582 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001583 * @return the number of rows affected if a whereClause is passed in, 0
1584 * otherwise. To remove all rows and get a count pass "1" as the
1585 * whereClause.
1586 */
1587 public int delete(String table, String whereClause, String[] whereArgs) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001588 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001590 SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table +
1591 (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
1592 try {
1593 return statement.executeUpdateDelete();
1594 } finally {
1595 statement.close();
1596 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001598 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 }
1600 }
1601
1602 /**
1603 * Convenience method for updating rows in the database.
1604 *
1605 * @param table the table to update in
1606 * @param values a map from column names to new column values. null is a
1607 * valid value that will be translated to NULL.
1608 * @param whereClause the optional WHERE clause to apply when updating.
1609 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001610 * @param whereArgs You may include ?s in the where clause, which
1611 * will be replaced by the values from whereArgs. The values
1612 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 * @return the number of rows affected
1614 */
1615 public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001616 return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 /**
1620 * Convenience method for updating rows in the database.
1621 *
1622 * @param table the table to update in
1623 * @param values a map from column names to new column values. null is a
1624 * valid value that will be translated to NULL.
1625 * @param whereClause the optional WHERE clause to apply when updating.
1626 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001627 * @param whereArgs You may include ?s in the where clause, which
1628 * will be replaced by the values from whereArgs. The values
1629 * will be bound as Strings.
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001630 * @param conflictAlgorithm for update conflict resolver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 * @return the number of rows affected
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 */
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001633 public int updateWithOnConflict(String table, ContentValues values,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001634 String whereClause, String[] whereArgs, int conflictAlgorithm) {
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001635 if (values == null || values.isEmpty()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 throw new IllegalArgumentException("Empty values");
1637 }
1638
Jeff Brown03bd3022012-03-06 13:48:56 -08001639 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001641 StringBuilder sql = new StringBuilder(120);
1642 sql.append("UPDATE ");
1643 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1644 sql.append(table);
1645 sql.append(" SET ");
1646
1647 // move all bind args to one array
1648 int setValuesSize = values.size();
1649 int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
1650 Object[] bindArgs = new Object[bindArgsSize];
1651 int i = 0;
1652 for (String colName : values.keySet()) {
1653 sql.append((i > 0) ? "," : "");
1654 sql.append(colName);
1655 bindArgs[i++] = values.get(colName);
1656 sql.append("=?");
1657 }
1658 if (whereArgs != null) {
1659 for (i = setValuesSize; i < bindArgsSize; i++) {
1660 bindArgs[i] = whereArgs[i - setValuesSize];
1661 }
1662 }
1663 if (!TextUtils.isEmpty(whereClause)) {
1664 sql.append(" WHERE ");
1665 sql.append(whereClause);
1666 }
1667
1668 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1669 try {
1670 return statement.executeUpdateDelete();
1671 } finally {
1672 statement.close();
1673 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001675 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 }
1677 }
1678
1679 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001680 * Execute a single SQL statement that is NOT a SELECT
1681 * or any other SQL statement that returns data.
1682 * <p>
Vasu Norice38b982010-07-22 13:57:13 -07001683 * It has no means to return any data (such as the number of affected rows).
Vasu Noriccd95442010-05-28 17:04:16 -07001684 * Instead, you're encouraged to use {@link #insert(String, String, ContentValues)},
1685 * {@link #update(String, ContentValues, String, String[])}, et al, when possible.
1686 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001687 * <p>
1688 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1689 * automatically managed by this class. So, do not set journal_mode
1690 * using "PRAGMA journal_mode'<value>" statement if your app is using
1691 * {@link #enableWriteAheadLogging()}
1692 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 *
Vasu Noriccd95442010-05-28 17:04:16 -07001694 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1695 * not supported.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001696 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001698 public void execSQL(String sql) throws SQLException {
Vasu Nori16057fa2011-03-18 11:40:37 -07001699 executeSql(sql, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 }
1701
1702 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001703 * Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE.
1704 * <p>
1705 * For INSERT statements, use any of the following instead.
1706 * <ul>
1707 * <li>{@link #insert(String, String, ContentValues)}</li>
1708 * <li>{@link #insertOrThrow(String, String, ContentValues)}</li>
1709 * <li>{@link #insertWithOnConflict(String, String, ContentValues, int)}</li>
1710 * </ul>
1711 * <p>
1712 * For UPDATE statements, use any of the following instead.
1713 * <ul>
1714 * <li>{@link #update(String, ContentValues, String, String[])}</li>
1715 * <li>{@link #updateWithOnConflict(String, ContentValues, String, String[], int)}</li>
1716 * </ul>
1717 * <p>
1718 * For DELETE statements, use any of the following instead.
1719 * <ul>
1720 * <li>{@link #delete(String, String, String[])}</li>
1721 * </ul>
1722 * <p>
1723 * For example, the following are good candidates for using this method:
1724 * <ul>
1725 * <li>ALTER TABLE</li>
1726 * <li>CREATE or DROP table / trigger / view / index / virtual table</li>
1727 * <li>REINDEX</li>
1728 * <li>RELEASE</li>
1729 * <li>SAVEPOINT</li>
1730 * <li>PRAGMA that returns no data</li>
1731 * </ul>
1732 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001733 * <p>
1734 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1735 * automatically managed by this class. So, do not set journal_mode
1736 * using "PRAGMA journal_mode'<value>" statement if your app is using
1737 * {@link #enableWriteAheadLogging()}
1738 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 *
Vasu Noriccd95442010-05-28 17:04:16 -07001740 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1741 * not supported.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001742 * @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001743 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001745 public void execSQL(String sql, Object[] bindArgs) throws SQLException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 if (bindArgs == null) {
1747 throw new IllegalArgumentException("Empty bindArgs");
1748 }
Vasu Norib83cb7c2010-09-14 13:36:01 -07001749 executeSql(sql, bindArgs);
Vasu Norice38b982010-07-22 13:57:13 -07001750 }
1751
Jeff Sharkey6adc98c2018-07-12 19:47:49 -06001752 /** {@hide} */
1753 public int executeSql(String sql, Object[] bindArgs) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001754 acquireReference();
1755 try {
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001756 final int statementType = DatabaseUtils.getSqlStatementType(sql);
1757 if (statementType == DatabaseUtils.STATEMENT_ATTACH) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001758 boolean disableWal = false;
1759 synchronized (mLock) {
1760 if (!mHasAttachedDbsLocked) {
1761 mHasAttachedDbsLocked = true;
1762 disableWal = true;
Fyodor Kupolovfd9c4a52017-07-13 15:36:57 -07001763 mConnectionPoolLocked.disableIdleConnectionHandler();
Jeff Brown03bd3022012-03-06 13:48:56 -08001764 }
1765 }
1766 if (disableWal) {
1767 disableWriteAheadLogging();
Jeff Browne5360fb2011-10-31 17:48:13 -07001768 }
1769 }
Jeff Browne5360fb2011-10-31 17:48:13 -07001770
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001771 try (SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs)) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001772 return statement.executeUpdateDelete();
1773 } finally {
Fyodor Kupolov25095c02017-11-17 14:02:10 -08001774 // If schema was updated, close non-primary connections, otherwise they might
1775 // have outdated schema information
1776 if (statementType == DatabaseUtils.STATEMENT_DDL) {
1777 mConnectionPoolLocked.closeAvailableNonPrimaryConnectionsAndLogExceptions();
1778 }
Jeff Brown03bd3022012-03-06 13:48:56 -08001779 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001781 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001783 }
1784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785 /**
Makoto Onuki17aa1b72015-12-16 14:02:01 -08001786 * Verifies that a SQL SELECT statement is valid by compiling it.
1787 * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
1788 *
1789 * @param sql SQL to be validated
1790 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
1791 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1792 * when the query is executed.
1793 * @throws SQLiteException if {@code sql} is invalid
1794 */
1795 public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal) {
1796 getThreadSession().prepare(sql,
1797 getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null);
1798 }
1799
1800 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001801 * Returns true if the database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001803 * @return True if database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 */
1805 public boolean isReadOnly() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001806 synchronized (mLock) {
1807 return isReadOnlyLocked();
1808 }
1809 }
1810
1811 private boolean isReadOnlyLocked() {
1812 return (mConfigurationLocked.openFlags & OPEN_READ_MASK) == OPEN_READONLY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001813 }
1814
1815 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001816 * Returns true if the database is in-memory db.
1817 *
1818 * @return True if the database is in-memory.
1819 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 */
Jeff Browne5360fb2011-10-31 17:48:13 -07001821 public boolean isInMemoryDatabase() {
1822 synchronized (mLock) {
1823 return mConfigurationLocked.isInMemoryDb();
1824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 }
1826
Jeff Browne5360fb2011-10-31 17:48:13 -07001827 /**
1828 * Returns true if the database is currently open.
1829 *
1830 * @return True if the database is currently open (has not been closed).
1831 */
1832 public boolean isOpen() {
1833 synchronized (mLock) {
1834 return mConnectionPoolLocked != null;
1835 }
1836 }
1837
1838 /**
1839 * Returns true if the new version code is greater than the current database version.
1840 *
1841 * @param newVersion The new version code.
Mark Lu1e202082016-08-30 17:41:25 -07001842 * @return True if the new version code is greater than the current database version.
Jeff Browne5360fb2011-10-31 17:48:13 -07001843 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 public boolean needUpgrade(int newVersion) {
1845 return newVersion > getVersion();
1846 }
1847
1848 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001849 * Gets the path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001850 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001851 * @return The path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 */
1853 public final String getPath() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001854 synchronized (mLock) {
1855 return mConfigurationLocked.path;
Christopher Tatead9e8b12011-10-05 17:49:26 -07001856 }
Brad Fitzpatrick722802e2010-03-23 22:22:16 -07001857 }
1858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001859 /**
1860 * Sets the locale for this database. Does nothing if this database has
Jeff Brown1d9f7422012-03-15 14:32:32 -07001861 * the {@link #NO_LOCALIZED_COLLATORS} flag set or was opened read only.
Jeff Browne5360fb2011-10-31 17:48:13 -07001862 *
1863 * @param locale The new locale.
1864 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001865 * @throws SQLException if the locale could not be set. The most common reason
1866 * for this is that there is no collator available for the locale you requested.
1867 * In this case the database remains unchanged.
1868 */
1869 public void setLocale(Locale locale) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001870 if (locale == null) {
1871 throw new IllegalArgumentException("locale must not be null.");
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001872 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001873
Jeff Browne5360fb2011-10-31 17:48:13 -07001874 synchronized (mLock) {
1875 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001876
1877 final Locale oldLocale = mConfigurationLocked.locale;
Jeff Browne5360fb2011-10-31 17:48:13 -07001878 mConfigurationLocked.locale = locale;
Jeff Browne67ca422012-03-21 17:24:05 -07001879 try {
1880 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1881 } catch (RuntimeException ex) {
1882 mConfigurationLocked.locale = oldLocale;
1883 throw ex;
1884 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001885 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001886 }
1887
Vasu Norie495d1f2010-01-06 16:34:19 -08001888 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001889 * Sets the maximum size of the prepared-statement cache for this database.
Vasu Norie495d1f2010-01-06 16:34:19 -08001890 * (size of the cache = number of compiled-sql-statements stored in the cache).
Vasu Noriccd95442010-05-28 17:04:16 -07001891 *<p>
Vasu Norib729dcc2010-09-14 11:35:49 -07001892 * Maximum cache size can ONLY be increased from its current size (default = 10).
Vasu Noriccd95442010-05-28 17:04:16 -07001893 * If this method is called with smaller size than the current maximum value,
1894 * then IllegalStateException is thrown.
Vasu Norib729dcc2010-09-14 11:35:49 -07001895 *<p>
1896 * This method is thread-safe.
Vasu Norie495d1f2010-01-06 16:34:19 -08001897 *
Vasu Nori90a367262010-04-12 12:49:09 -07001898 * @param cacheSize the size of the cache. can be (0 to {@link #MAX_SQL_CACHE_SIZE})
Jeff Browne5360fb2011-10-31 17:48:13 -07001899 * @throws IllegalStateException if input cacheSize > {@link #MAX_SQL_CACHE_SIZE}.
Vasu Norie495d1f2010-01-06 16:34:19 -08001900 */
Vasu Nori54025902010-09-14 12:14:26 -07001901 public void setMaxSqlCacheSize(int cacheSize) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001902 if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) {
1903 throw new IllegalStateException(
1904 "expected value between 0 and " + MAX_SQL_CACHE_SIZE);
Vasu Nori587423a2010-09-27 18:18:34 -07001905 }
Vasu Nori587423a2010-09-27 18:18:34 -07001906
Jeff Browne5360fb2011-10-31 17:48:13 -07001907 synchronized (mLock) {
1908 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001909
1910 final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize;
Jeff Browne5360fb2011-10-31 17:48:13 -07001911 mConfigurationLocked.maxSqlCacheSize = cacheSize;
Jeff Browne67ca422012-03-21 17:24:05 -07001912 try {
1913 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1914 } catch (RuntimeException ex) {
1915 mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize;
1916 throw ex;
1917 }
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001918 }
1919 }
1920
Vasu Nori6c354da2010-04-26 23:33:39 -07001921 /**
Jeff Brown96496ad2012-03-23 14:38:06 -07001922 * Sets whether foreign key constraints are enabled for the database.
1923 * <p>
1924 * By default, foreign key constraints are not enforced by the database.
1925 * This method allows an application to enable foreign key constraints.
1926 * It must be called each time the database is opened to ensure that foreign
1927 * key constraints are enabled for the session.
1928 * </p><p>
1929 * A good time to call this method is right after calling {@link #openOrCreateDatabase}
1930 * or in the {@link SQLiteOpenHelper#onConfigure} callback.
1931 * </p><p>
1932 * When foreign key constraints are disabled, the database does not check whether
1933 * changes to the database will violate foreign key constraints. Likewise, when
1934 * foreign key constraints are disabled, the database will not execute cascade
1935 * delete or update triggers. As a result, it is possible for the database
1936 * state to become inconsistent. To perform a database integrity check,
1937 * call {@link #isDatabaseIntegrityOk}.
1938 * </p><p>
1939 * This method must not be called while a transaction is in progress.
1940 * </p><p>
1941 * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a>
1942 * for more details about foreign key constraint support.
1943 * </p>
1944 *
1945 * @param enable True to enable foreign key constraints, false to disable them.
1946 *
1947 * @throws IllegalStateException if the are transactions is in progress
1948 * when this method is called.
1949 */
1950 public void setForeignKeyConstraintsEnabled(boolean enable) {
1951 synchronized (mLock) {
1952 throwIfNotOpenLocked();
1953
1954 if (mConfigurationLocked.foreignKeyConstraintsEnabled == enable) {
1955 return;
1956 }
1957
1958 mConfigurationLocked.foreignKeyConstraintsEnabled = enable;
1959 try {
1960 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1961 } catch (RuntimeException ex) {
1962 mConfigurationLocked.foreignKeyConstraintsEnabled = !enable;
1963 throw ex;
1964 }
1965 }
1966 }
1967
1968 /**
Jeff Brown47847f32012-03-22 19:13:11 -07001969 * This method enables parallel execution of queries from multiple threads on the
1970 * same database. It does this by opening multiple connections to the database
1971 * and using a different database connection for each query. The database
1972 * journal mode is also changed to enable writes to proceed concurrently with reads.
Vasu Nori6c354da2010-04-26 23:33:39 -07001973 * <p>
Jeff Brown47847f32012-03-22 19:13:11 -07001974 * When write-ahead logging is not enabled (the default), it is not possible for
1975 * reads and writes to occur on the database at the same time. Before modifying the
1976 * database, the writer implicitly acquires an exclusive lock on the database which
1977 * prevents readers from accessing the database until the write is completed.
1978 * </p><p>
1979 * In contrast, when write-ahead logging is enabled (by calling this method), write
1980 * operations occur in a separate log file which allows reads to proceed concurrently.
1981 * While a write is in progress, readers on other threads will perceive the state
1982 * of the database as it was before the write began. When the write completes, readers
1983 * on other threads will then perceive the new state of the database.
1984 * </p><p>
1985 * It is a good idea to enable write-ahead logging whenever a database will be
1986 * concurrently accessed and modified by multiple threads at the same time.
1987 * However, write-ahead logging uses significantly more memory than ordinary
1988 * journaling because there are multiple connections to the same database.
1989 * So if a database will only be used by a single thread, or if optimizing
1990 * concurrency is not very important, then write-ahead logging should be disabled.
1991 * </p><p>
1992 * After calling this method, execution of queries in parallel is enabled as long as
1993 * the database remains open. To disable execution of queries in parallel, either
1994 * call {@link #disableWriteAheadLogging} or close the database and reopen it.
1995 * </p><p>
1996 * The maximum number of connections used to execute queries in parallel is
Vasu Nori6c354da2010-04-26 23:33:39 -07001997 * dependent upon the device memory and possibly other properties.
Jeff Brown47847f32012-03-22 19:13:11 -07001998 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07001999 * If a query is part of a transaction, then it is executed on the same database handle the
2000 * transaction was begun.
Jeff Brown47847f32012-03-22 19:13:11 -07002001 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07002002 * Writers should use {@link #beginTransactionNonExclusive()} or
2003 * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
Jeff Brown47847f32012-03-22 19:13:11 -07002004 * to start a transaction. Non-exclusive mode allows database file to be in readable
2005 * by other threads executing queries.
2006 * </p><p>
2007 * If the database has any attached databases, then execution of queries in parallel is NOT
2008 * possible. Likewise, write-ahead logging is not supported for read-only databases
2009 * or memory databases. In such cases, {@link #enableWriteAheadLogging} returns false.
2010 * </p><p>
2011 * The best way to enable write-ahead logging is to pass the
2012 * {@link #ENABLE_WRITE_AHEAD_LOGGING} flag to {@link #openDatabase}. This is
2013 * more efficient than calling {@link #enableWriteAheadLogging}.
2014 * <code><pre>
2015 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2016 * SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
2017 * myDatabaseErrorHandler);
Jeff Brown47847f32012-03-22 19:13:11 -07002018 * </pre></code>
2019 * </p><p>
2020 * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging}
2021 * after opening the database.
2022 * <code><pre>
2023 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2024 * SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
2025 * db.enableWriteAheadLogging();
2026 * </pre></code>
2027 * </p><p>
2028 * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for
2029 * more details about how write-ahead logging works.
Vasu Nori6c354da2010-04-26 23:33:39 -07002030 * </p>
2031 *
Jeff Brown47847f32012-03-22 19:13:11 -07002032 * @return True if write-ahead logging is enabled.
Jeff Browne67ca422012-03-21 17:24:05 -07002033 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002034 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002035 * time this method is called. WAL mode can only be changed when there are no
2036 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002037 *
2038 * @see #ENABLE_WRITE_AHEAD_LOGGING
2039 * @see #disableWriteAheadLogging
Vasu Nori6c354da2010-04-26 23:33:39 -07002040 */
Vasu Noriffe06122010-09-27 12:32:57 -07002041 public boolean enableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002042 synchronized (mLock) {
2043 throwIfNotOpenLocked();
2044
Jeff Brown47847f32012-03-22 19:13:11 -07002045 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002046 return true;
2047 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002048
2049 if (isReadOnlyLocked()) {
2050 // WAL doesn't make sense for readonly-databases.
2051 // TODO: True, but connection pooling does still make sense...
2052 return false;
2053 }
2054
2055 if (mConfigurationLocked.isInMemoryDb()) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002056 Log.i(TAG, "can't enable WAL for memory databases.");
2057 return false;
2058 }
2059
2060 // make sure this database has NO attached databases because sqlite's write-ahead-logging
2061 // doesn't work for databases with attached databases
Jeff Browne5360fb2011-10-31 17:48:13 -07002062 if (mHasAttachedDbsLocked) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002063 if (Log.isLoggable(TAG, Log.DEBUG)) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002064 Log.d(TAG, "this database: " + mConfigurationLocked.label
2065 + " has attached databases. can't enable WAL.");
Paul Westbrookdae6d372011-02-17 10:59:56 -08002066 }
2067 return false;
2068 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002069
Jeff Brown47847f32012-03-22 19:13:11 -07002070 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002071 try {
2072 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2073 } catch (RuntimeException ex) {
Jeff Brown47847f32012-03-22 19:13:11 -07002074 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002075 throw ex;
2076 }
Paul Westbrookdae6d372011-02-17 10:59:56 -08002077 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002078 return true;
Vasu Nori6c354da2010-04-26 23:33:39 -07002079 }
2080
Vasu Nori2827d6d2010-07-04 00:26:18 -07002081 /**
Vasu Nori7b04c412010-07-20 10:31:21 -07002082 * This method disables the features enabled by {@link #enableWriteAheadLogging()}.
Jeff Browne67ca422012-03-21 17:24:05 -07002083 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002084 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002085 * time this method is called. WAL mode can only be changed when there are no
2086 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002087 *
2088 * @see #enableWriteAheadLogging
Vasu Nori2827d6d2010-07-04 00:26:18 -07002089 */
Vasu Nori7b04c412010-07-20 10:31:21 -07002090 public void disableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002091 synchronized (mLock) {
2092 throwIfNotOpenLocked();
2093
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002094 final int oldFlags = mConfigurationLocked.openFlags;
Fyodor Kupolov692573b2018-03-06 12:34:36 -08002095 final boolean walDisabled = (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0;
2096 final boolean compatibilityWalDisabled = (oldFlags & DISABLE_COMPATIBILITY_WAL) != 0;
2097 if (walDisabled && compatibilityWalDisabled) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002098 return;
Paul Westbrookdae6d372011-02-17 10:59:56 -08002099 }
Vasu Nori8d111032010-06-22 18:34:21 -07002100
Jeff Brown47847f32012-03-22 19:13:11 -07002101 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Fyodor Kupolov692573b2018-03-06 12:34:36 -08002102 // If an app explicitly disables WAL, compatibility mode should be disabled too
2103 mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002104
Jeff Browne67ca422012-03-21 17:24:05 -07002105 try {
2106 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2107 } catch (RuntimeException ex) {
Fyodor Kupolov5bd43ad2017-10-25 16:09:35 -07002108 mConfigurationLocked.openFlags = oldFlags;
Jeff Browne67ca422012-03-21 17:24:05 -07002109 throw ex;
2110 }
Vasu Nori65a88832010-07-16 15:14:08 -07002111 }
Vasu Nori6c354da2010-04-26 23:33:39 -07002112 }
2113
Vasu Norif3cf8a42010-03-23 11:41:44 -07002114 /**
Jeff Brown47847f32012-03-22 19:13:11 -07002115 * Returns true if write-ahead logging has been enabled for this database.
2116 *
2117 * @return True if write-ahead logging has been enabled for this database.
2118 *
2119 * @see #enableWriteAheadLogging
2120 * @see #ENABLE_WRITE_AHEAD_LOGGING
2121 */
2122 public boolean isWriteAheadLoggingEnabled() {
2123 synchronized (mLock) {
2124 throwIfNotOpenLocked();
2125
2126 return (mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2127 }
2128 }
2129
2130 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002131 * Collect statistics about all open databases in the current process.
2132 * Used by bug report.
Vasu Norif3cf8a42010-03-23 11:41:44 -07002133 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002134 static ArrayList<DbStats> getDbStats() {
Vasu Noric3849202010-03-09 10:47:25 -08002135 ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002136 for (SQLiteDatabase db : getActiveDatabases()) {
2137 db.collectDbStats(dbStatsList);
Vasu Nori24675612010-09-27 14:54:19 -07002138 }
Vasu Noric3849202010-03-09 10:47:25 -08002139 return dbStatsList;
2140 }
2141
Jeff Browne5360fb2011-10-31 17:48:13 -07002142 private void collectDbStats(ArrayList<DbStats> dbStatsList) {
2143 synchronized (mLock) {
2144 if (mConnectionPoolLocked != null) {
2145 mConnectionPoolLocked.collectDbStats(dbStatsList);
2146 }
2147 }
2148 }
2149
2150 private static ArrayList<SQLiteDatabase> getActiveDatabases() {
2151 ArrayList<SQLiteDatabase> databases = new ArrayList<SQLiteDatabase>();
2152 synchronized (sActiveDatabases) {
2153 databases.addAll(sActiveDatabases.keySet());
2154 }
2155 return databases;
2156 }
2157
2158 /**
2159 * Dump detailed information about all open databases in the current process.
2160 * Used by bug report.
2161 */
Jeff Browna9be4152012-01-18 15:29:57 -08002162 static void dumpAll(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002163 for (SQLiteDatabase db : getActiveDatabases()) {
Jeff Browna9be4152012-01-18 15:29:57 -08002164 db.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002165 }
2166 }
2167
Jeff Browna9be4152012-01-18 15:29:57 -08002168 private void dump(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002169 synchronized (mLock) {
2170 if (mConnectionPoolLocked != null) {
2171 printer.println("");
Jeff Browna9be4152012-01-18 15:29:57 -08002172 mConnectionPoolLocked.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002173 }
2174 }
2175 }
2176
Vasu Noric3849202010-03-09 10:47:25 -08002177 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002178 * Returns list of full pathnames of all attached databases including the main database
2179 * by executing 'pragma database_list' on the database.
2180 *
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002181 * @return ArrayList of pairs of (database name, database file path) or null if the database
2182 * is not open.
Vasu Noric3849202010-03-09 10:47:25 -08002183 */
Vasu Noria017eda2011-01-27 10:52:55 -08002184 public List<Pair<String, String>> getAttachedDbs() {
Vasu Noric3849202010-03-09 10:47:25 -08002185 ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002186 synchronized (mLock) {
2187 if (mConnectionPoolLocked == null) {
2188 return null; // not open
2189 }
2190
2191 if (!mHasAttachedDbsLocked) {
2192 // No attached databases.
2193 // There is a small window where attached databases exist but this flag is not
2194 // set yet. This can occur when this thread is in a race condition with another
2195 // thread that is executing the SQL statement: "attach database <blah> as <foo>"
2196 // If this thread is NOT ok with such a race condition (and thus possibly not
2197 // receivethe entire list of attached databases), then the caller should ensure
2198 // that no thread is executing any SQL statements while a thread is calling this
2199 // method. Typically, this method is called when 'adb bugreport' is done or the
2200 // caller wants to collect stats on the database and all its attached databases.
2201 attachedDbs.add(new Pair<String, String>("main", mConfigurationLocked.path));
2202 return attachedDbs;
2203 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002204
2205 acquireReference();
Vasu Nori24675612010-09-27 14:54:19 -07002206 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002207
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002208 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002209 // has attached databases. query sqlite to get the list of attached databases.
2210 Cursor c = null;
2211 try {
2212 c = rawQuery("pragma database_list;", null);
2213 while (c.moveToNext()) {
2214 // sqlite returns a row for each database in the returned list of databases.
2215 // in each row,
2216 // 1st column is the database name such as main, or the database
2217 // name specified on the "ATTACH" command
2218 // 2nd column is the database file path.
2219 attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2)));
2220 }
2221 } finally {
2222 if (c != null) {
2223 c.close();
2224 }
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002225 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002226 return attachedDbs;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002227 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08002228 releaseReference();
Vasu Noric3849202010-03-09 10:47:25 -08002229 }
Vasu Noric3849202010-03-09 10:47:25 -08002230 }
2231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002232 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002233 * Runs 'pragma integrity_check' on the given database (and all the attached databases)
2234 * and returns true if the given database (and all its attached databases) pass integrity_check,
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002235 * false otherwise.
Vasu Noriccd95442010-05-28 17:04:16 -07002236 *<p>
2237 * If the result is false, then this method logs the errors reported by the integrity_check
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002238 * command execution.
Vasu Noriccd95442010-05-28 17:04:16 -07002239 *<p>
2240 * Note that 'pragma integrity_check' on a database can take a long time.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002241 *
2242 * @return true if the given database (and all its attached databases) pass integrity_check,
Vasu Noriccd95442010-05-28 17:04:16 -07002243 * false otherwise.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002244 */
2245 public boolean isDatabaseIntegrityOk() {
Jeff Brown03bd3022012-03-06 13:48:56 -08002246 acquireReference();
Vasu Noribfe1dc22010-08-25 16:29:02 -07002247 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002248 List<Pair<String, String>> attachedDbs = null;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002249 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002250 attachedDbs = getAttachedDbs();
2251 if (attachedDbs == null) {
2252 throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " +
2253 "be retrieved. probably because the database is closed");
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002254 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002255 } catch (SQLiteException e) {
2256 // can't get attachedDb list. do integrity check on the main database
2257 attachedDbs = new ArrayList<Pair<String, String>>();
2258 attachedDbs.add(new Pair<String, String>("main", getPath()));
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002259 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002260
2261 for (int i = 0; i < attachedDbs.size(); i++) {
2262 Pair<String, String> p = attachedDbs.get(i);
2263 SQLiteStatement prog = null;
2264 try {
2265 prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);");
2266 String rslt = prog.simpleQueryForString();
2267 if (!rslt.equalsIgnoreCase("ok")) {
2268 // integrity_checker failed on main or attached databases
2269 Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt);
2270 return false;
2271 }
2272 } finally {
2273 if (prog != null) prog.close();
2274 }
2275 }
2276 } finally {
2277 releaseReference();
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002278 }
Vasu Noribfe1dc22010-08-25 16:29:02 -07002279 return true;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002280 }
2281
Jeff Browne5360fb2011-10-31 17:48:13 -07002282 @Override
2283 public String toString() {
2284 return "SQLiteDatabase: " + getPath();
2285 }
2286
Jeff Browne5360fb2011-10-31 17:48:13 -07002287 private void throwIfNotOpenLocked() {
2288 if (mConnectionPoolLocked == null) {
2289 throw new IllegalStateException("The database '" + mConfigurationLocked.label
2290 + "' is not open.");
2291 }
2292 }
Vasu Nori3ef94e22010-02-05 14:49:04 -08002293
2294 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002295 * Used to allow returning sub-classes of {@link Cursor} when calling query.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002296 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002297 public interface CursorFactory {
2298 /**
2299 * See {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}.
2300 */
2301 public Cursor newCursor(SQLiteDatabase db,
2302 SQLiteCursorDriver masterQuery, String editTable,
2303 SQLiteQuery query);
2304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002305
2306 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002307 * A callback interface for a custom sqlite3 function.
2308 * This can be used to create a function that can be called from
2309 * sqlite3 database triggers.
2310 * @hide
Vasu Noric3849202010-03-09 10:47:25 -08002311 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002312 public interface CustomFunction {
2313 public void callback(String[] args);
2314 }
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002315
2316 /**
2317 * Wrapper for configuration parameters that are used for opening {@link SQLiteDatabase}
2318 */
2319 public static final class OpenParams {
2320 private final int mOpenFlags;
2321 private final CursorFactory mCursorFactory;
2322 private final DatabaseErrorHandler mErrorHandler;
2323 private final int mLookasideSlotSize;
2324 private final int mLookasideSlotCount;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002325 private final long mIdleConnectionTimeout;
2326 private final String mJournalMode;
2327 private final String mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002328
2329 private OpenParams(int openFlags, CursorFactory cursorFactory,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002330 DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002331 long idleConnectionTimeout, String journalMode, String syncMode) {
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002332 mOpenFlags = openFlags;
2333 mCursorFactory = cursorFactory;
2334 mErrorHandler = errorHandler;
2335 mLookasideSlotSize = lookasideSlotSize;
2336 mLookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002337 mIdleConnectionTimeout = idleConnectionTimeout;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002338 mJournalMode = journalMode;
2339 mSyncMode = syncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002340 }
2341
2342 /**
2343 * Returns size in bytes of each lookaside slot or -1 if not set.
2344 *
2345 * @see Builder#setLookasideConfig(int, int)
2346 */
2347 @IntRange(from = -1)
2348 public int getLookasideSlotSize() {
2349 return mLookasideSlotSize;
2350 }
2351
2352 /**
2353 * Returns total number of lookaside memory slots per database connection or -1 if not
2354 * set.
2355 *
2356 * @see Builder#setLookasideConfig(int, int)
2357 */
2358 @IntRange(from = -1)
2359 public int getLookasideSlotCount() {
2360 return mLookasideSlotCount;
2361 }
2362
2363 /**
Fyodor Kupolov76436c02017-08-03 17:56:44 -07002364 * Returns flags to control database access mode. Default value is 0.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002365 *
2366 * @see Builder#setOpenFlags(int)
2367 */
2368 @DatabaseOpenFlags
2369 public int getOpenFlags() {
2370 return mOpenFlags;
2371 }
2372
2373 /**
2374 * Returns an optional factory class that is called to instantiate a cursor when query
2375 * is called
2376 *
2377 * @see Builder#setCursorFactory(CursorFactory)
2378 */
2379 @Nullable
2380 public CursorFactory getCursorFactory() {
2381 return mCursorFactory;
2382 }
2383
2384 /**
2385 * Returns handler for database corruption errors
2386 *
2387 * @see Builder#setErrorHandler(DatabaseErrorHandler)
2388 */
2389 @Nullable
2390 public DatabaseErrorHandler getErrorHandler() {
2391 return mErrorHandler;
2392 }
2393
2394 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002395 * Returns maximum number of milliseconds that SQLite connection is allowed to be idle
2396 * before it is closed and removed from the pool.
2397 * <p>If the value isn't set, the timeout defaults to the system wide timeout
2398 *
2399 * @return timeout in milliseconds or -1 if the value wasn't set.
2400 */
2401 public long getIdleConnectionTimeout() {
2402 return mIdleConnectionTimeout;
2403 }
2404
2405 /**
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002406 * Returns <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>.
2407 * This journal mode will only be used if {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING}
2408 * flag is not set, otherwise a platform will use "WAL" journal mode.
2409 * @see Builder#setJournalMode(String)
2410 */
2411 @Nullable
2412 public String getJournalMode() {
2413 return mJournalMode;
2414 }
2415
2416 /**
2417 * Returns <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>.
Fyodor Kupolov8ba20892018-06-01 12:11:42 -07002418 * If not set, a system wide default will be used.
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002419 * @see Builder#setSynchronousMode(String)
2420 */
2421 @Nullable
2422 public String getSynchronousMode() {
2423 return mSyncMode;
2424 }
2425
2426 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002427 * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with
2428 * {@code this} parameters.
2429 * @hide
2430 */
2431 @NonNull
2432 public Builder toBuilder() {
2433 return new Builder(this);
2434 }
2435
2436 /**
2437 * Builder for {@link OpenParams}.
2438 */
2439 public static final class Builder {
2440 private int mLookasideSlotSize = -1;
2441 private int mLookasideSlotCount = -1;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002442 private long mIdleConnectionTimeout = -1;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002443 private int mOpenFlags;
2444 private CursorFactory mCursorFactory;
2445 private DatabaseErrorHandler mErrorHandler;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002446 private String mJournalMode;
2447 private String mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002448
2449 public Builder() {
2450 }
2451
2452 public Builder(OpenParams params) {
2453 mLookasideSlotSize = params.mLookasideSlotSize;
2454 mLookasideSlotCount = params.mLookasideSlotCount;
2455 mOpenFlags = params.mOpenFlags;
2456 mCursorFactory = params.mCursorFactory;
2457 mErrorHandler = params.mErrorHandler;
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002458 mJournalMode = params.mJournalMode;
2459 mSyncMode = params.mSyncMode;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002460 }
2461
2462 /**
2463 * Configures
2464 * <a href="https://sqlite.org/malloc.html#lookaside">lookaside memory allocator</a>
2465 *
2466 * <p>SQLite default settings will be used, if this method isn't called.
2467 * Use {@code setLookasideConfig(0,0)} to disable lookaside
2468 *
Fyodor Kupolov05a0f0f2017-06-30 19:00:00 -07002469 * <p><strong>Note:</strong> Provided slotSize/slotCount configuration is just a
2470 * recommendation. The system may choose different values depending on a device, e.g.
2471 * lookaside allocations can be disabled on low-RAM devices
2472 *
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002473 * @param slotSize The size in bytes of each lookaside slot.
2474 * @param slotCount The total number of lookaside memory slots per database connection.
2475 */
2476 public Builder setLookasideConfig(@IntRange(from = 0) final int slotSize,
2477 @IntRange(from = 0) final int slotCount) {
2478 Preconditions.checkArgument(slotSize >= 0,
2479 "lookasideSlotCount cannot be negative");
2480 Preconditions.checkArgument(slotCount >= 0,
2481 "lookasideSlotSize cannot be negative");
2482 Preconditions.checkArgument(
2483 (slotSize > 0 && slotCount > 0) || (slotCount == 0 && slotSize == 0),
2484 "Invalid configuration: " + slotSize + ", " + slotCount);
2485
2486 mLookasideSlotSize = slotSize;
2487 mLookasideSlotCount = slotCount;
2488 return this;
2489 }
2490
2491 /**
2492 * Returns true if {@link #ENABLE_WRITE_AHEAD_LOGGING} flag is set
2493 * @hide
2494 */
2495 public boolean isWriteAheadLoggingEnabled() {
2496 return (mOpenFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2497 }
2498
2499 /**
2500 * Sets flags to control database access mode
2501 * @param openFlags The new flags to set
2502 * @see #OPEN_READWRITE
2503 * @see #OPEN_READONLY
2504 * @see #CREATE_IF_NECESSARY
2505 * @see #NO_LOCALIZED_COLLATORS
2506 * @see #ENABLE_WRITE_AHEAD_LOGGING
2507 * @return same builder instance for chaining multiple calls into a single statement
2508 */
2509 @NonNull
2510 public Builder setOpenFlags(@DatabaseOpenFlags int openFlags) {
2511 mOpenFlags = openFlags;
2512 return this;
2513 }
2514
2515 /**
2516 * Adds flags to control database access mode
2517 *
2518 * @param openFlags The new flags to add
2519 * @return same builder instance for chaining multiple calls into a single statement
2520 */
2521 @NonNull
2522 public Builder addOpenFlags(@DatabaseOpenFlags int openFlags) {
2523 mOpenFlags |= openFlags;
2524 return this;
2525 }
2526
2527 /**
2528 * Removes database access mode flags
2529 *
2530 * @param openFlags Flags to remove
2531 * @return same builder instance for chaining multiple calls into a single statement
2532 */
2533 @NonNull
2534 public Builder removeOpenFlags(@DatabaseOpenFlags int openFlags) {
2535 mOpenFlags &= ~openFlags;
2536 return this;
2537 }
2538
2539 /**
2540 * Sets {@link #ENABLE_WRITE_AHEAD_LOGGING} flag if {@code enabled} is {@code true},
2541 * unsets otherwise
2542 * @hide
2543 */
2544 public void setWriteAheadLoggingEnabled(boolean enabled) {
2545 if (enabled) {
2546 addOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2547 } else {
2548 removeOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2549 }
2550 }
2551
2552 /**
2553 * Set an optional factory class that is called to instantiate a cursor when query
2554 * is called.
2555 *
2556 * @param cursorFactory instance
2557 * @return same builder instance for chaining multiple calls into a single statement
2558 */
2559 @NonNull
2560 public Builder setCursorFactory(@Nullable CursorFactory cursorFactory) {
2561 mCursorFactory = cursorFactory;
2562 return this;
2563 }
2564
2565
2566 /**
2567 * Sets {@link DatabaseErrorHandler} object to handle db corruption errors
2568 */
2569 @NonNull
2570 public Builder setErrorHandler(@Nullable DatabaseErrorHandler errorHandler) {
2571 mErrorHandler = errorHandler;
2572 return this;
2573 }
2574
2575 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002576 * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle
2577 * before it is closed and removed from the pool.
2578 *
2579 * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE}
2580 * to allow unlimited idle connections.
2581 */
2582 @NonNull
2583 public Builder setIdleConnectionTimeout(
2584 @IntRange(from = 0) long idleConnectionTimeoutMs) {
2585 Preconditions.checkArgument(idleConnectionTimeoutMs >= 0,
2586 "idle connection timeout cannot be negative");
2587 mIdleConnectionTimeout = idleConnectionTimeoutMs;
2588 return this;
2589 }
2590
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002591
2592 /**
2593 * Sets <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>
2594 * to use when {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag is not set.
2595 */
2596 @NonNull
2597 public Builder setJournalMode(@NonNull String journalMode) {
2598 Preconditions.checkNotNull(journalMode);
2599 mJournalMode = journalMode;
2600 return this;
2601 }
2602
2603 /**
2604 * Sets <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>
Fyodor Kupolov8ba20892018-06-01 12:11:42 -07002605 * .
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002606 * @return
2607 */
2608 @NonNull
2609 public Builder setSynchronousMode(@NonNull String syncMode) {
2610 Preconditions.checkNotNull(syncMode);
2611 mSyncMode = syncMode;
2612 return this;
2613 }
2614
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002615 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002616 * Creates an instance of {@link OpenParams} with the options that were previously set
2617 * on this builder
2618 */
2619 @NonNull
2620 public OpenParams build() {
2621 return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize,
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002622 mLookasideSlotCount, mIdleConnectionTimeout, mJournalMode, mSyncMode);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002623 }
2624 }
2625 }
2626
2627 /** @hide */
2628 @IntDef(flag = true, prefix = {"OPEN_", "CREATE_", "NO_", "ENABLE_"}, value = {
2629 OPEN_READWRITE,
2630 OPEN_READONLY,
2631 CREATE_IF_NECESSARY,
2632 NO_LOCALIZED_COLLATORS,
2633 ENABLE_WRITE_AHEAD_LOGGING
2634 })
2635 @Retention(RetentionPolicy.SOURCE)
2636 public @interface DatabaseOpenFlags {}
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002638}
Fyodor Kupolov13a4b372017-11-07 18:45:35 -08002639