blob: df0e262b712f18b488cc6124cb070d6b42d83787 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.database.sqlite;
18
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070019import android.annotation.IntDef;
20import android.annotation.IntRange;
Makoto Onuki17aa1b72015-12-16 14:02:01 -080021import android.annotation.NonNull;
22import android.annotation.Nullable;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070023import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.ContentValues;
25import android.database.Cursor;
Vasu Nori062fc7ce2010-03-31 16:13:05 -070026import android.database.DatabaseErrorHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.database.DatabaseUtils;
Vasu Nori062fc7ce2010-03-31 16:13:05 -070028import android.database.DefaultDatabaseErrorHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.database.SQLException;
Vasu Noric3849202010-03-09 10:47:25 -080030import android.database.sqlite.SQLiteDebug.DbStats;
Jeff Browna7771df2012-05-07 20:06:46 -070031import android.os.CancellationSignal;
Jeff Browne5360fb2011-10-31 17:48:13 -070032import android.os.Looper;
Jeff Browna7771df2012-05-07 20:06:46 -070033import android.os.OperationCanceledException;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070034import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.util.EventLog;
Dmitri Plotnikov90142c92009-09-15 10:52:17 -070037import android.util.Log;
Vasu Noric3849202010-03-09 10:47:25 -080038import android.util.Pair;
Jeff Browne5360fb2011-10-31 17:48:13 -070039import android.util.Printer;
40
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070041import com.android.internal.util.Preconditions;
42
Jeff Browne5360fb2011-10-31 17:48:13 -070043import dalvik.system.CloseGuard;
44
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import java.io.File;
Jeff Brown79087e42012-03-01 19:52:44 -080046import java.io.FileFilter;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -070047import java.lang.annotation.Retention;
48import java.lang.annotation.RetentionPolicy;
Vasu Noric3849202010-03-09 10:47:25 -080049import java.util.ArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import java.util.HashMap;
Jesse Wilson9b5a9352011-02-10 11:19:09 -080051import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import java.util.Locale;
53import java.util.Map;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import java.util.WeakHashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055
56/**
57 * Exposes methods to manage a SQLite database.
Jeff Browne5360fb2011-10-31 17:48:13 -070058 *
59 * <p>
60 * SQLiteDatabase has methods to create, delete, execute SQL commands, and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 * perform other common database management tasks.
Jeff Browne5360fb2011-10-31 17:48:13 -070062 * </p><p>
63 * See the Notepad sample application in the SDK for an example of creating
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 * and managing a database.
Jeff Browne5360fb2011-10-31 17:48:13 -070065 * </p><p>
66 * Database names must be unique within an application, not across all applications.
67 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 *
69 * <h3>Localized Collation - ORDER BY</h3>
Jeff Browne5360fb2011-10-31 17:48:13 -070070 * <p>
71 * In addition to SQLite's default <code>BINARY</code> collator, Android supplies
72 * two more, <code>LOCALIZED</code>, which changes with the system's current locale,
73 * and <code>UNICODE</code>, which is the Unicode Collation Algorithm and not tailored
74 * to the current locale.
75 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 */
Jeff Brownbaefdfa2012-03-05 10:33:13 -080077public final class SQLiteDatabase extends SQLiteClosable {
Vasu Norifb16cbd2010-07-25 16:38:48 -070078 private static final String TAG = "SQLiteDatabase";
Jeff Browne5360fb2011-10-31 17:48:13 -070079
Jeff Hamilton082c2af2009-09-29 11:49:51 -070080 private static final int EVENT_DB_CORRUPT = 75004;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081
Fyodor Kupolov535672992017-08-30 18:16:31 -070082 // By default idle connections are not closed
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070083 private static final boolean DEBUG_CLOSE_IDLE_CONNECTIONS = SystemProperties
Fyodor Kupolov535672992017-08-30 18:16:31 -070084 .getBoolean("persist.debug.sqlite.close_idle_connections", false);
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070085
Jeff Browne5360fb2011-10-31 17:48:13 -070086 // Stores reference to all databases opened in the current process.
87 // (The referent Object is not used at this time.)
88 // INVARIANT: Guarded by sActiveDatabases.
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070089 private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases = new WeakHashMap<>();
Jeff Browne5360fb2011-10-31 17:48:13 -070090
91 // Thread-local for database sessions that belong to this database.
92 // Each thread has its own database session.
93 // INVARIANT: Immutable.
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070094 private final ThreadLocal<SQLiteSession> mThreadSession = ThreadLocal
95 .withInitial(this::createSession);
Jeff Browne5360fb2011-10-31 17:48:13 -070096
97 // The optional factory to use when creating new Cursors. May be null.
98 // INVARIANT: Immutable.
99 private final CursorFactory mCursorFactory;
100
101 // Error handler to be used when SQLite returns corruption errors.
102 // INVARIANT: Immutable.
103 private final DatabaseErrorHandler mErrorHandler;
104
105 // Shared database state lock.
106 // This lock guards all of the shared state of the database, such as its
107 // configuration, whether it is open or closed, and so on. This lock should
108 // be held for as little time as possible.
109 //
110 // The lock MUST NOT be held while attempting to acquire database connections or
111 // while executing SQL statements on behalf of the client as it can lead to deadlock.
112 //
113 // It is ok to hold the lock while reconfiguring the connection pool or dumping
114 // statistics because those operations are non-reentrant and do not try to acquire
115 // connections that might be held by other threads.
116 //
117 // Basic rule: grab the lock, access or modify global state, release the lock, then
118 // do the required SQL work.
119 private final Object mLock = new Object();
120
121 // Warns if the database is finalized without being closed properly.
122 // INVARIANT: Guarded by mLock.
123 private final CloseGuard mCloseGuardLocked = CloseGuard.get();
124
125 // The database configuration.
126 // INVARIANT: Guarded by mLock.
127 private final SQLiteDatabaseConfiguration mConfigurationLocked;
128
129 // The connection pool for the database, null when closed.
130 // The pool itself is thread-safe, but the reference to it can only be acquired
131 // when the lock is held.
132 // INVARIANT: Guarded by mLock.
133 private SQLiteConnectionPool mConnectionPoolLocked;
134
135 // True if the database has attached databases.
136 // INVARIANT: Guarded by mLock.
137 private boolean mHasAttachedDbsLocked;
138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700140 * When a constraint violation occurs, an immediate ROLLBACK occurs,
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800141 * thus ending the current transaction, and the command aborts with a
142 * return code of SQLITE_CONSTRAINT. If no transaction is active
143 * (other than the implied transaction that is created on every command)
Jeff Browne5360fb2011-10-31 17:48:13 -0700144 * then this algorithm works the same as ABORT.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800145 */
146 public static final int CONFLICT_ROLLBACK = 1;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700147
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800148 /**
149 * When a constraint violation occurs,no ROLLBACK is executed
150 * so changes from prior commands within the same transaction
151 * are preserved. This is the default behavior.
152 */
153 public static final int CONFLICT_ABORT = 2;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700154
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800155 /**
156 * When a constraint violation occurs, the command aborts with a return
157 * code SQLITE_CONSTRAINT. But any changes to the database that
158 * the command made prior to encountering the constraint violation
159 * are preserved and are not backed out.
160 */
161 public static final int CONFLICT_FAIL = 3;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700162
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800163 /**
164 * When a constraint violation occurs, the one row that contains
165 * the constraint violation is not inserted or changed.
166 * But the command continues executing normally. Other rows before and
167 * after the row that contained the constraint violation continue to be
168 * inserted or updated normally. No error is returned.
169 */
170 public static final int CONFLICT_IGNORE = 4;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700171
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800172 /**
173 * When a UNIQUE constraint violation occurs, the pre-existing rows that
174 * are causing the constraint violation are removed prior to inserting
175 * or updating the current row. Thus the insert or update always occurs.
176 * The command continues executing normally. No error is returned.
177 * If a NOT NULL constraint violation occurs, the NULL value is replaced
178 * by the default value for that column. If the column has no default
179 * value, then the ABORT algorithm is used. If a CHECK constraint
180 * violation occurs then the IGNORE algorithm is used. When this conflict
181 * resolution strategy deletes rows in order to satisfy a constraint,
182 * it does not invoke delete triggers on those rows.
Jeff Browne5360fb2011-10-31 17:48:13 -0700183 * This behavior might change in a future release.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800184 */
185 public static final int CONFLICT_REPLACE = 5;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700186
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800187 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700188 * Use the following when no conflict action is specified.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800189 */
190 public static final int CONFLICT_NONE = 0;
Jeff Browne5360fb2011-10-31 17:48:13 -0700191
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800192 private static final String[] CONFLICT_VALUES = new String[]
193 {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 /**
196 * Maximum Length Of A LIKE Or GLOB Pattern
197 * The pattern matching algorithm used in the default LIKE and GLOB implementation
198 * of SQLite can exhibit O(N^2) performance (where N is the number of characters in
199 * the pattern) for certain pathological cases. To avoid denial-of-service attacks
200 * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes.
201 * The default value of this limit is 50000. A modern workstation can evaluate
202 * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly.
203 * The denial of service problem only comes into play when the pattern length gets
204 * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns
205 * are at most a few dozen bytes in length, paranoid application developers may
206 * want to reduce this parameter to something in the range of a few hundred
207 * if they know that external users are able to generate arbitrary patterns.
208 */
209 public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000;
210
211 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700212 * Open flag: Flag for {@link #openDatabase} to open the database for reading and writing.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 * If the disk is full, this may fail even before you actually write anything.
214 *
215 * {@more} Note that the value of this flag is 0, so it is the default.
216 */
217 public static final int OPEN_READWRITE = 0x00000000; // update native code if changing
218
219 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700220 * Open flag: Flag for {@link #openDatabase} to open the database for reading only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 * This is the only reliable way to open a database if the disk may be full.
222 */
223 public static final int OPEN_READONLY = 0x00000001; // update native code if changing
224
225 private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing
226
227 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700228 * Open flag: Flag for {@link #openDatabase} to open the database without support for
229 * localized collators.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 *
231 * {@more} This causes the collator <code>LOCALIZED</code> not to be created.
232 * You must be consistent when using this flag to use the setting the database was
233 * created with. If this is set, {@link #setLocale} will do nothing.
234 */
235 public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing
236
237 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700238 * Open flag: Flag for {@link #openDatabase} to create the database file if it does not
239 * already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 */
241 public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing
242
243 /**
Jeff Brown47847f32012-03-22 19:13:11 -0700244 * Open flag: Flag for {@link #openDatabase} to open the database file with
245 * write-ahead logging enabled by default. Using this flag is more efficient
246 * than calling {@link #enableWriteAheadLogging}.
247 *
248 * Write-ahead logging cannot be used with read-only databases so the value of
249 * this flag is ignored if the database is opened read-only.
250 *
251 * @see #enableWriteAheadLogging
252 */
253 public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;
254
255 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700256 * Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}.
Vasu Norib729dcc2010-09-14 11:35:49 -0700257 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700258 * Each prepared-statement is between 1K - 6K, depending on the complexity of the
259 * SQL statement & schema. A large SQL cache may use a significant amount of memory.
Vasu Norie495d1f2010-01-06 16:34:19 -0800260 */
Vasu Nori90a367262010-04-12 12:49:09 -0700261 public static final int MAX_SQL_CACHE_SIZE = 100;
Vasu Norib729dcc2010-09-14 11:35:49 -0700262
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700263 private SQLiteDatabase(final String path, final int openFlags,
264 CursorFactory cursorFactory, DatabaseErrorHandler errorHandler,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700265 int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700266 mCursorFactory = cursorFactory;
267 mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler();
268 mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700269 mConfigurationLocked.lookasideSlotSize = lookasideSlotSize;
270 mConfigurationLocked.lookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700271 // Disable lookaside allocator on low-RAM devices
272 if (ActivityManager.isLowRamDeviceStatic()) {
273 mConfigurationLocked.lookasideSlotCount = 0;
274 mConfigurationLocked.lookasideSlotSize = 0;
275 }
276 long effectiveTimeoutMs = Long.MAX_VALUE;
277 // Never close idle connections for in-memory databases
278 if (!mConfigurationLocked.isInMemoryDb()) {
279 // First, check app-specific value. Otherwise use defaults
280 // -1 in idleConnectionTimeoutMs indicates unset value
281 if (idleConnectionTimeoutMs >= 0) {
282 effectiveTimeoutMs = idleConnectionTimeoutMs;
283 } else if (DEBUG_CLOSE_IDLE_CONNECTIONS) {
284 effectiveTimeoutMs = SQLiteGlobal.getIdleConnectionTimeout();
285 }
286 }
287 mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700289
Jeff Browne5360fb2011-10-31 17:48:13 -0700290 @Override
291 protected void finalize() throws Throwable {
292 try {
293 dispose(true);
294 } finally {
295 super.finalize();
296 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700297 }
298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 @Override
300 protected void onAllReferencesReleased() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700301 dispose(false);
302 }
303
304 private void dispose(boolean finalized) {
305 final SQLiteConnectionPool pool;
306 synchronized (mLock) {
307 if (mCloseGuardLocked != null) {
308 if (finalized) {
309 mCloseGuardLocked.warnIfOpen();
310 }
311 mCloseGuardLocked.close();
312 }
313
314 pool = mConnectionPoolLocked;
315 mConnectionPoolLocked = null;
316 }
317
318 if (!finalized) {
319 synchronized (sActiveDatabases) {
320 sActiveDatabases.remove(this);
321 }
322
323 if (pool != null) {
324 pool.close();
325 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326 }
327 }
328
329 /**
330 * Attempts to release memory that SQLite holds but does not require to
331 * operate properly. Typically this memory will come from the page cache.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700332 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 * @return the number of bytes actually released
334 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700335 public static int releaseMemory() {
336 return SQLiteGlobal.releaseMemory();
337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338
339 /**
340 * Control whether or not the SQLiteDatabase is made thread-safe by using locks
341 * around critical sections. This is pretty expensive, so if you know that your
342 * DB will only be used by a single thread then you should set this to false.
343 * The default is true.
344 * @param lockingEnabled set to true to enable locks, false otherwise
Jeff Browne5360fb2011-10-31 17:48:13 -0700345 *
346 * @deprecated This method now does nothing. Do not use.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700348 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 public void setLockingEnabled(boolean lockingEnabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 }
351
352 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700353 * Gets a label to use when describing the database in log messages.
354 * @return The label.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700356 String getLabel() {
357 synchronized (mLock) {
358 return mConfigurationLocked.label;
359 }
360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361
Jeff Browne5360fb2011-10-31 17:48:13 -0700362 /**
363 * Sends a corruption message to the database error handler.
364 */
365 void onCorruption() {
366 EventLog.writeEvent(EVENT_DB_CORRUPT, getLabel());
Vasu Noriccd95442010-05-28 17:04:16 -0700367 mErrorHandler.onCorruption(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 }
369
370 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700371 * Gets the {@link SQLiteSession} that belongs to this thread for this database.
372 * Once a thread has obtained a session, it will continue to obtain the same
373 * session even after the database has been closed (although the session will not
374 * be usable). However, a thread that does not already have a session cannot
375 * obtain one after the database has been closed.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700376 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700377 * The idea is that threads that have active connections to the database may still
378 * have work to complete even after the call to {@link #close}. Active database
379 * connections are not actually disposed until they are released by the threads
380 * that own them.
381 *
382 * @return The session, never null.
383 *
384 * @throws IllegalStateException if the thread does not yet have a session and
385 * the database is not open.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700387 SQLiteSession getThreadSession() {
388 return mThreadSession.get(); // initialValue() throws if database closed
Vasu Nori6d970252010-10-05 10:48:49 -0700389 }
Vasu Nori16057fa2011-03-18 11:40:37 -0700390
Jeff Browne5360fb2011-10-31 17:48:13 -0700391 SQLiteSession createSession() {
392 final SQLiteConnectionPool pool;
393 synchronized (mLock) {
394 throwIfNotOpenLocked();
395 pool = mConnectionPoolLocked;
Vasu Nori6d970252010-10-05 10:48:49 -0700396 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700397 return new SQLiteSession(pool);
Vasu Norid4608a32011-02-03 16:24:06 -0800398 }
399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700401 * Gets default connection flags that are appropriate for this thread, taking into
402 * account whether the thread is acting on behalf of the UI.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700404 * @param readOnly True if the connection should be read-only.
405 * @return The connection flags.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700407 int getThreadDefaultConnectionFlags(boolean readOnly) {
408 int flags = readOnly ? SQLiteConnectionPool.CONNECTION_FLAG_READ_ONLY :
409 SQLiteConnectionPool.CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY;
410 if (isMainThread()) {
411 flags |= SQLiteConnectionPool.CONNECTION_FLAG_INTERACTIVE;
412 }
413 return flags;
Vasu Nori16057fa2011-03-18 11:40:37 -0700414 }
415
Jeff Browne5360fb2011-10-31 17:48:13 -0700416 private static boolean isMainThread() {
417 // FIXME: There should be a better way to do this.
418 // Would also be nice to have something that would work across Binder calls.
419 Looper looper = Looper.myLooper();
420 return looper != null && looper == Looper.getMainLooper();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 }
422
423 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700424 * Begins a transaction in EXCLUSIVE mode.
425 * <p>
426 * Transactions can be nested.
427 * When the outer transaction is ended all of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 * the work done in that transaction and all of the nested transactions will be committed or
429 * rolled back. The changes will be rolled back if any transaction is ended without being
430 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700431 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 * <p>Here is the standard idiom for transactions:
433 *
434 * <pre>
435 * db.beginTransaction();
436 * try {
437 * ...
438 * db.setTransactionSuccessful();
439 * } finally {
440 * db.endTransaction();
441 * }
442 * </pre>
443 */
444 public void beginTransaction() {
Vasu Nori6c354da2010-04-26 23:33:39 -0700445 beginTransaction(null /* transactionStatusCallback */, true);
446 }
447
448 /**
449 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
450 * the outer transaction is ended all of the work done in that transaction
451 * and all of the nested transactions will be committed or rolled back. The
452 * changes will be rolled back if any transaction is ended without being
453 * marked as clean (by calling setTransactionSuccessful). Otherwise they
454 * will be committed.
455 * <p>
456 * Here is the standard idiom for transactions:
457 *
458 * <pre>
459 * db.beginTransactionNonExclusive();
460 * try {
461 * ...
462 * db.setTransactionSuccessful();
463 * } finally {
464 * db.endTransaction();
465 * }
466 * </pre>
467 */
468 public void beginTransactionNonExclusive() {
469 beginTransaction(null /* transactionStatusCallback */, false);
Fred Quintanac4516a72009-09-03 12:14:06 -0700470 }
471
472 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700473 * Begins a transaction in EXCLUSIVE mode.
474 * <p>
475 * Transactions can be nested.
476 * When the outer transaction is ended all of
Fred Quintanac4516a72009-09-03 12:14:06 -0700477 * the work done in that transaction and all of the nested transactions will be committed or
478 * rolled back. The changes will be rolled back if any transaction is ended without being
479 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700480 * </p>
Fred Quintanac4516a72009-09-03 12:14:06 -0700481 * <p>Here is the standard idiom for transactions:
482 *
483 * <pre>
484 * db.beginTransactionWithListener(listener);
485 * try {
486 * ...
487 * db.setTransactionSuccessful();
488 * } finally {
489 * db.endTransaction();
490 * }
491 * </pre>
Vasu Noriccd95442010-05-28 17:04:16 -0700492 *
Fred Quintanac4516a72009-09-03 12:14:06 -0700493 * @param transactionListener listener that should be notified when the transaction begins,
494 * commits, or is rolled back, either explicitly or by a call to
495 * {@link #yieldIfContendedSafely}.
496 */
497 public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
Vasu Nori6c354da2010-04-26 23:33:39 -0700498 beginTransaction(transactionListener, true);
499 }
500
501 /**
502 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
503 * the outer transaction is ended all of the work done in that transaction
504 * and all of the nested transactions will be committed or rolled back. The
505 * changes will be rolled back if any transaction is ended without being
506 * marked as clean (by calling setTransactionSuccessful). Otherwise they
507 * will be committed.
508 * <p>
509 * Here is the standard idiom for transactions:
510 *
511 * <pre>
512 * db.beginTransactionWithListenerNonExclusive(listener);
513 * try {
514 * ...
515 * db.setTransactionSuccessful();
516 * } finally {
517 * db.endTransaction();
518 * }
519 * </pre>
520 *
521 * @param transactionListener listener that should be notified when the
522 * transaction begins, commits, or is rolled back, either
523 * explicitly or by a call to {@link #yieldIfContendedSafely}.
524 */
525 public void beginTransactionWithListenerNonExclusive(
526 SQLiteTransactionListener transactionListener) {
527 beginTransaction(transactionListener, false);
528 }
529
530 private void beginTransaction(SQLiteTransactionListener transactionListener,
531 boolean exclusive) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800532 acquireReference();
533 try {
534 getThreadSession().beginTransaction(
535 exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
536 SQLiteSession.TRANSACTION_MODE_IMMEDIATE,
537 transactionListener,
538 getThreadDefaultConnectionFlags(false /*readOnly*/), null);
539 } finally {
540 releaseReference();
541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 }
543
544 /**
545 * End a transaction. See beginTransaction for notes about how to use this and when transactions
546 * are committed and rolled back.
547 */
548 public void endTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800549 acquireReference();
550 try {
551 getThreadSession().endTransaction(null);
552 } finally {
553 releaseReference();
554 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 }
556
557 /**
558 * Marks the current transaction as successful. Do not do any more database work between
559 * calling this and calling endTransaction. Do as little non-database work as possible in that
560 * situation too. If any errors are encountered between this and endTransaction the transaction
561 * will still be committed.
562 *
563 * @throws IllegalStateException if the current thread is not in a transaction or the
564 * transaction is already marked as successful.
565 */
566 public void setTransactionSuccessful() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800567 acquireReference();
568 try {
569 getThreadSession().setTransactionSuccessful();
570 } finally {
571 releaseReference();
572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800573 }
574
575 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700576 * Returns true if the current thread has a transaction pending.
577 *
578 * @return True if the current thread is in a transaction.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800579 */
580 public boolean inTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800581 acquireReference();
582 try {
583 return getThreadSession().hasTransaction();
584 } finally {
585 releaseReference();
586 }
Vasu Norice38b982010-07-22 13:57:13 -0700587 }
588
589 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700590 * Returns true if the current thread is holding an active connection to the database.
Vasu Norice38b982010-07-22 13:57:13 -0700591 * <p>
Jeff Browne5360fb2011-10-31 17:48:13 -0700592 * The name of this method comes from a time when having an active connection
593 * to the database meant that the thread was holding an actual lock on the
594 * database. Nowadays, there is no longer a true "database lock" although threads
595 * may block if they cannot acquire a database connection to perform a
596 * particular operation.
597 * </p>
Vasu Norice38b982010-07-22 13:57:13 -0700598 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700599 * @return True if the current thread is holding an active connection to the database.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 */
601 public boolean isDbLockedByCurrentThread() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800602 acquireReference();
603 try {
604 return getThreadSession().hasConnection();
605 } finally {
606 releaseReference();
607 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 }
609
610 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700611 * Always returns false.
612 * <p>
613 * There is no longer the concept of a database lock, so this method always returns false.
614 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700616 * @return False.
617 * @deprecated Always returns false. Do not use this method.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700619 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800620 public boolean isDbLockedByOtherThreads() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700621 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800622 }
623
624 /**
625 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
626 * successful so far. Do not call setTransactionSuccessful before calling this. When this
627 * returns a new transaction will have been created but not marked as successful.
628 * @return true if the transaction was yielded
629 * @deprecated if the db is locked more than once (becuase of nested transactions) then the lock
630 * will not be yielded. Use yieldIfContendedSafely instead.
631 */
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700632 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 public boolean yieldIfContended() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700634 return yieldIfContendedHelper(false /* do not check yielding */,
635 -1 /* sleepAfterYieldDelay */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 }
637
638 /**
639 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
640 * successful so far. Do not call setTransactionSuccessful before calling this. When this
641 * returns a new transaction will have been created but not marked as successful. This assumes
642 * that there are no nested transactions (beginTransaction has only been called once) and will
Fred Quintana5c7aede2009-08-27 21:41:27 -0700643 * throw an exception if that is not the case.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644 * @return true if the transaction was yielded
645 */
646 public boolean yieldIfContendedSafely() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700647 return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648 }
649
Fred Quintana5c7aede2009-08-27 21:41:27 -0700650 /**
651 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
652 * successful so far. Do not call setTransactionSuccessful before calling this. When this
653 * returns a new transaction will have been created but not marked as successful. This assumes
654 * that there are no nested transactions (beginTransaction has only been called once) and will
655 * throw an exception if that is not the case.
656 * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if
657 * the lock was actually yielded. This will allow other background threads to make some
658 * more progress than they would if we started the transaction immediately.
659 * @return true if the transaction was yielded
660 */
661 public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
662 return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay);
663 }
664
Jeff Browne5360fb2011-10-31 17:48:13 -0700665 private boolean yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800666 acquireReference();
667 try {
668 return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null);
669 } finally {
670 releaseReference();
671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672 }
673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700675 * Deprecated.
Vasu Nori95675132010-07-21 16:24:40 -0700676 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800677 */
Vasu Nori95675132010-07-21 16:24:40 -0700678 @Deprecated
679 public Map<String, String> getSyncedTables() {
680 return new HashMap<String, String>(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 }
682
683 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 * Open the database according to the flags {@link #OPEN_READWRITE}
685 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
686 *
687 * <p>Sets the locale of the database to the the system's current locale.
688 * Call {@link #setLocale} if you would like something else.</p>
689 *
690 * @param path to database file to open and/or create
691 * @param factory an optional factory class that is called to instantiate a
692 * cursor when query is called, or null for default
693 * @param flags to control database access mode
694 * @return the newly opened database
695 * @throws SQLiteException if the database cannot be opened
696 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700697 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
698 @DatabaseOpenFlags int flags) {
Jeff Brown47847f32012-03-22 19:13:11 -0700699 return openDatabase(path, factory, flags, null);
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700700 }
701
702 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700703 * Open the database according to the specified {@link OpenParams parameters}
704 *
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700705 * @param path path to database file to open and/or create.
706 * <p><strong>Important:</strong> The file should be constructed either from an absolute path or
707 * by using {@link android.content.Context#getDatabasePath(String)}.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700708 * @param openParams configuration parameters that are used for opening {@link SQLiteDatabase}
709 * @return the newly opened database
710 * @throws SQLiteException if the database cannot be opened
711 */
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700712 public static SQLiteDatabase openDatabase(@NonNull File path,
713 @NonNull OpenParams openParams) {
714 return openDatabase(path.getPath(), openParams);
715 }
716
717 private static SQLiteDatabase openDatabase(@NonNull String path,
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700718 @NonNull OpenParams openParams) {
719 Preconditions.checkArgument(openParams != null, "OpenParams cannot be null");
720 SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags,
721 openParams.mCursorFactory, openParams.mErrorHandler,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700722 openParams.mLookasideSlotSize, openParams.mLookasideSlotCount,
723 openParams.mIdleConnectionTimeout);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700724 db.open();
725 return db;
726 }
727
728 /**
Vasu Nori74f170f2010-06-01 18:06:18 -0700729 * Open the database according to the flags {@link #OPEN_READWRITE}
730 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
731 *
732 * <p>Sets the locale of the database to the the system's current locale.
733 * Call {@link #setLocale} if you would like something else.</p>
734 *
735 * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be
736 * used to handle corruption when sqlite reports database corruption.</p>
737 *
738 * @param path to database file to open and/or create
739 * @param factory an optional factory class that is called to instantiate a
740 * cursor when query is called, or null for default
741 * @param flags to control database access mode
742 * @param errorHandler the {@link DatabaseErrorHandler} obj to be used to handle corruption
743 * when sqlite reports database corruption
744 * @return the newly opened database
745 * @throws SQLiteException if the database cannot be opened
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700746 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700747 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
748 @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler) {
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700749 SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1, -1);
Jeff Browne5360fb2011-10-31 17:48:13 -0700750 db.open();
751 return db;
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700752 }
753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754 /**
755 * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
756 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700757 public static SQLiteDatabase openOrCreateDatabase(@NonNull File file,
758 @Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 return openOrCreateDatabase(file.getPath(), factory);
760 }
761
762 /**
763 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
764 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700765 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
766 @Nullable CursorFactory factory) {
Jeff Brown47847f32012-03-22 19:13:11 -0700767 return openDatabase(path, factory, CREATE_IF_NECESSARY, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768 }
769
770 /**
Vasu Nori6c354da2010-04-26 23:33:39 -0700771 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler).
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700772 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700773 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
774 @Nullable CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler) {
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700775 return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler);
776 }
777
Jeff Brown559d0642012-02-29 10:19:12 -0800778 /**
Jeff Brown79087e42012-03-01 19:52:44 -0800779 * Deletes a database including its journal file and other auxiliary files
780 * that may have been created by the database engine.
781 *
782 * @param file The database file path.
783 * @return True if the database was successfully deleted.
784 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700785 public static boolean deleteDatabase(@NonNull File file) {
Jeff Brown79087e42012-03-01 19:52:44 -0800786 if (file == null) {
787 throw new IllegalArgumentException("file must not be null");
788 }
789
790 boolean deleted = false;
791 deleted |= file.delete();
792 deleted |= new File(file.getPath() + "-journal").delete();
793 deleted |= new File(file.getPath() + "-shm").delete();
794 deleted |= new File(file.getPath() + "-wal").delete();
795
796 File dir = file.getParentFile();
797 if (dir != null) {
798 final String prefix = file.getName() + "-mj";
Jeff Brownfce58902014-01-24 13:20:57 -0800799 File[] files = dir.listFiles(new FileFilter() {
Jeff Brown79087e42012-03-01 19:52:44 -0800800 @Override
801 public boolean accept(File candidate) {
802 return candidate.getName().startsWith(prefix);
803 }
Jeff Brownfce58902014-01-24 13:20:57 -0800804 });
805 if (files != null) {
806 for (File masterJournal : files) {
807 deleted |= masterJournal.delete();
808 }
Jeff Brown79087e42012-03-01 19:52:44 -0800809 }
810 }
811 return deleted;
812 }
813
814 /**
Jeff Brown559d0642012-02-29 10:19:12 -0800815 * Reopens the database in read-write mode.
816 * If the database is already read-write, does nothing.
817 *
818 * @throws SQLiteException if the database could not be reopened as requested, in which
819 * case it remains open in read only mode.
820 * @throws IllegalStateException if the database is not open.
821 *
822 * @see #isReadOnly()
823 * @hide
824 */
825 public void reopenReadWrite() {
826 synchronized (mLock) {
827 throwIfNotOpenLocked();
828
829 if (!isReadOnlyLocked()) {
830 return; // nothing to do
831 }
832
833 // Reopen the database in read-write mode.
834 final int oldOpenFlags = mConfigurationLocked.openFlags;
835 mConfigurationLocked.openFlags = (mConfigurationLocked.openFlags & ~OPEN_READ_MASK)
836 | OPEN_READWRITE;
837 try {
838 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
839 } catch (RuntimeException ex) {
840 mConfigurationLocked.openFlags = oldOpenFlags;
841 throw ex;
842 }
843 }
844 }
845
Jeff Browne5360fb2011-10-31 17:48:13 -0700846 private void open() {
847 try {
848 try {
849 openInner();
850 } catch (SQLiteDatabaseCorruptException ex) {
851 onCorruption();
852 openInner();
853 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700854 } catch (SQLiteException ex) {
855 Log.e(TAG, "Failed to open database '" + getLabel() + "'.", ex);
856 close();
857 throw ex;
858 }
859 }
860
861 private void openInner() {
862 synchronized (mLock) {
863 assert mConnectionPoolLocked == null;
864 mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked);
865 mCloseGuardLocked.open("close");
866 }
867
868 synchronized (sActiveDatabases) {
869 sActiveDatabases.put(this, null);
870 }
871 }
872
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700873 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 * Create a memory backed SQLite database. Its contents will be destroyed
875 * when the database is closed.
876 *
877 * <p>Sets the locale of the database to the the system's current locale.
878 * Call {@link #setLocale} if you would like something else.</p>
879 *
880 * @param factory an optional factory class that is called to instantiate a
881 * cursor when query is called
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700882 * @return a SQLiteDatabase instance
883 * @throws SQLiteException if the database cannot be created
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800884 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700885 @NonNull
886 public static SQLiteDatabase create(@Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887 // This is a magic string with special meaning for SQLite.
Jeff Browne5360fb2011-10-31 17:48:13 -0700888 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
889 factory, CREATE_IF_NECESSARY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 }
891
892 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700893 * Create a memory backed SQLite database. Its contents will be destroyed
894 * when the database is closed.
895 *
896 * <p>Sets the locale of the database to the the system's current locale.
897 * Call {@link #setLocale} if you would like something else.</p>
898 * @param openParams configuration parameters that are used for opening SQLiteDatabase
Fyodor Kupolov76436c02017-08-03 17:56:44 -0700899 * @return a SQLiteDatabase instance
900 * @throws SQLException if the database cannot be created
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700901 */
902 @NonNull
903 public static SQLiteDatabase createInMemory(@NonNull OpenParams openParams) {
904 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
905 openParams.toBuilder().addOpenFlags(CREATE_IF_NECESSARY).build());
906 }
907
908 /**
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400909 * Registers a CustomFunction callback as a function that can be called from
Jeff Browne5360fb2011-10-31 17:48:13 -0700910 * SQLite database triggers.
911 *
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400912 * @param name the name of the sqlite3 function
913 * @param numArgs the number of arguments for the function
914 * @param function callback to call when the function is executed
915 * @hide
916 */
917 public void addCustomFunction(String name, int numArgs, CustomFunction function) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700918 // Create wrapper (also validates arguments).
919 SQLiteCustomFunction wrapper = new SQLiteCustomFunction(name, numArgs, function);
920
921 synchronized (mLock) {
922 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -0700923
Jeff Browne5360fb2011-10-31 17:48:13 -0700924 mConfigurationLocked.customFunctions.add(wrapper);
Jeff Browne67ca422012-03-21 17:24:05 -0700925 try {
926 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
927 } catch (RuntimeException ex) {
928 mConfigurationLocked.customFunctions.remove(wrapper);
929 throw ex;
930 }
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400931 }
932 }
933
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400934 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 * Gets the database version.
936 *
937 * @return the database version
938 */
939 public int getVersion() {
Vasu Noriccd95442010-05-28 17:04:16 -0700940 return ((Long) DatabaseUtils.longForQuery(this, "PRAGMA user_version;", null)).intValue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 }
942
943 /**
944 * Sets the database version.
945 *
946 * @param version the new database version
947 */
948 public void setVersion(int version) {
949 execSQL("PRAGMA user_version = " + version);
950 }
951
952 /**
953 * Returns the maximum size the database may grow to.
954 *
955 * @return the new maximum database size
956 */
957 public long getMaximumSize() {
Vasu Noriccd95442010-05-28 17:04:16 -0700958 long pageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count;", null);
959 return pageCount * getPageSize();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 }
961
962 /**
963 * Sets the maximum size the database will grow to. The maximum size cannot
964 * be set below the current size.
965 *
966 * @param numBytes the maximum database size, in bytes
967 * @return the new maximum database size
968 */
969 public long setMaximumSize(long numBytes) {
Vasu Noriccd95442010-05-28 17:04:16 -0700970 long pageSize = getPageSize();
971 long numPages = numBytes / pageSize;
972 // If numBytes isn't a multiple of pageSize, bump up a page
973 if ((numBytes % pageSize) != 0) {
974 numPages++;
Vasu Norif3cf8a42010-03-23 11:41:44 -0700975 }
Vasu Noriccd95442010-05-28 17:04:16 -0700976 long newPageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count = " + numPages,
977 null);
978 return newPageCount * pageSize;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 }
980
981 /**
982 * Returns the current database page size, in bytes.
983 *
984 * @return the database page size, in bytes
985 */
986 public long getPageSize() {
Vasu Noriccd95442010-05-28 17:04:16 -0700987 return DatabaseUtils.longForQuery(this, "PRAGMA page_size;", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 }
989
990 /**
991 * Sets the database page size. The page size must be a power of two. This
992 * method does not work if any data has been written to the database file,
993 * and must be called right after the database has been created.
994 *
995 * @param numBytes the database page size, in bytes
996 */
997 public void setPageSize(long numBytes) {
998 execSQL("PRAGMA page_size = " + numBytes);
999 }
1000
1001 /**
1002 * Mark this table as syncable. When an update occurs in this table the
1003 * _sync_dirty field will be set to ensure proper syncing operation.
1004 *
1005 * @param table the table to mark as syncable
1006 * @param deletedTable The deleted table that corresponds to the
1007 * syncable table
Vasu Nori95675132010-07-21 16:24:40 -07001008 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 */
Vasu Nori95675132010-07-21 16:24:40 -07001010 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 public void markTableSyncable(String table, String deletedTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 }
1013
1014 /**
1015 * Mark this table as syncable, with the _sync_dirty residing in another
1016 * table. When an update occurs in this table the _sync_dirty field of the
1017 * row in updateTable with the _id in foreignKey will be set to
1018 * ensure proper syncing operation.
1019 *
1020 * @param table an update on this table will trigger a sync time removal
1021 * @param foreignKey this is the column in table whose value is an _id in
1022 * updateTable
1023 * @param updateTable this is the table that will have its _sync_dirty
Vasu Nori95675132010-07-21 16:24:40 -07001024 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 */
Vasu Nori95675132010-07-21 16:24:40 -07001026 @Deprecated
1027 public void markTableSyncable(String table, String foreignKey, String updateTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001028 }
1029
1030 /**
1031 * Finds the name of the first table, which is editable.
1032 *
1033 * @param tables a list of tables
1034 * @return the first table listed
1035 */
1036 public static String findEditTable(String tables) {
1037 if (!TextUtils.isEmpty(tables)) {
1038 // find the first word terminated by either a space or a comma
1039 int spacepos = tables.indexOf(' ');
1040 int commapos = tables.indexOf(',');
1041
1042 if (spacepos > 0 && (spacepos < commapos || commapos < 0)) {
1043 return tables.substring(0, spacepos);
1044 } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) {
1045 return tables.substring(0, commapos);
1046 }
1047 return tables;
1048 } else {
1049 throw new IllegalStateException("Invalid tables");
1050 }
1051 }
1052
1053 /**
1054 * Compiles an SQL statement into a reusable pre-compiled statement object.
1055 * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the
1056 * statement and fill in those values with {@link SQLiteProgram#bindString}
1057 * and {@link SQLiteProgram#bindLong} each time you want to run the
1058 * statement. Statements may not return result sets larger than 1x1.
Vasu Nori2827d6d2010-07-04 00:26:18 -07001059 *<p>
1060 * No two threads should be using the same {@link SQLiteStatement} at the same time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061 *
1062 * @param sql The raw SQL statement, may contain ? for unknown values to be
1063 * bound later.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001064 * @return A pre-compiled {@link SQLiteStatement} object. Note that
1065 * {@link SQLiteStatement}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 */
1067 public SQLiteStatement compileStatement(String sql) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001068 acquireReference();
1069 try {
1070 return new SQLiteStatement(this, sql, null);
1071 } finally {
1072 releaseReference();
1073 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 }
1075
1076 /**
1077 * Query the given URL, returning a {@link Cursor} over the result set.
1078 *
1079 * @param distinct true if you want each row to be unique, false otherwise.
1080 * @param table The table name to compile the query against.
1081 * @param columns A list of which columns to return. Passing null will
1082 * return all columns, which is discouraged to prevent reading
1083 * data from storage that isn't going to be used.
1084 * @param selection A filter declaring which rows to return, formatted as an
1085 * SQL WHERE clause (excluding the WHERE itself). Passing null
1086 * will return all rows for the given table.
1087 * @param selectionArgs You may include ?s in selection, which will be
1088 * replaced by the values from selectionArgs, in order that they
1089 * appear in the selection. The values will be bound as Strings.
1090 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1091 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1092 * will cause the rows to not be grouped.
1093 * @param having A filter declare which row groups to include in the cursor,
1094 * if row grouping is being used, formatted as an SQL HAVING
1095 * clause (excluding the HAVING itself). Passing null will cause
1096 * all row groups to be included, and is required when row
1097 * grouping is not being used.
1098 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1099 * (excluding the ORDER BY itself). Passing null will use the
1100 * default sort order, which may be unordered.
1101 * @param limit Limits the number of rows returned by the query,
1102 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001103 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1104 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 * @see Cursor
1106 */
1107 public Cursor query(boolean distinct, String table, String[] columns,
1108 String selection, String[] selectionArgs, String groupBy,
1109 String having, String orderBy, String limit) {
1110 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown75ea64f2012-01-25 19:37:13 -08001111 groupBy, having, orderBy, limit, null);
1112 }
1113
1114 /**
1115 * Query the given URL, returning a {@link Cursor} over the result set.
1116 *
1117 * @param distinct true if you want each row to be unique, false otherwise.
1118 * @param table The table name to compile the query against.
1119 * @param columns A list of which columns to return. Passing null will
1120 * return all columns, which is discouraged to prevent reading
1121 * data from storage that isn't going to be used.
1122 * @param selection A filter declaring which rows to return, formatted as an
1123 * SQL WHERE clause (excluding the WHERE itself). Passing null
1124 * will return all rows for the given table.
1125 * @param selectionArgs You may include ?s in selection, which will be
1126 * replaced by the values from selectionArgs, in order that they
1127 * appear in the selection. The values will be bound as Strings.
1128 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1129 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1130 * will cause the rows to not be grouped.
1131 * @param having A filter declare which row groups to include in the cursor,
1132 * if row grouping is being used, formatted as an SQL HAVING
1133 * clause (excluding the HAVING itself). Passing null will cause
1134 * all row groups to be included, and is required when row
1135 * grouping is not being used.
1136 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1137 * (excluding the ORDER BY itself). Passing null will use the
1138 * default sort order, which may be unordered.
1139 * @param limit Limits the number of rows returned by the query,
1140 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001141 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001142 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1143 * when the query is executed.
1144 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1145 * {@link Cursor}s are not synchronized, see the documentation for more details.
1146 * @see Cursor
1147 */
1148 public Cursor query(boolean distinct, String table, String[] columns,
1149 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001150 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001151 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001152 groupBy, having, orderBy, limit, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 }
1154
1155 /**
1156 * Query the given URL, returning a {@link Cursor} over the result set.
1157 *
1158 * @param cursorFactory the cursor factory to use, or null for the default factory
1159 * @param distinct true if you want each row to be unique, false otherwise.
1160 * @param table The table name to compile the query against.
1161 * @param columns A list of which columns to return. Passing null will
1162 * return all columns, which is discouraged to prevent reading
1163 * data from storage that isn't going to be used.
1164 * @param selection A filter declaring which rows to return, formatted as an
1165 * SQL WHERE clause (excluding the WHERE itself). Passing null
1166 * will return all rows for the given table.
1167 * @param selectionArgs You may include ?s in selection, which will be
1168 * replaced by the values from selectionArgs, in order that they
1169 * appear in the selection. The values will be bound as Strings.
1170 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1171 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1172 * will cause the rows to not be grouped.
1173 * @param having A filter declare which row groups to include in the cursor,
1174 * if row grouping is being used, formatted as an SQL HAVING
1175 * clause (excluding the HAVING itself). Passing null will cause
1176 * all row groups to be included, and is required when row
1177 * grouping is not being used.
1178 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1179 * (excluding the ORDER BY itself). Passing null will use the
1180 * default sort order, which may be unordered.
1181 * @param limit Limits the number of rows returned by the query,
1182 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001183 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1184 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185 * @see Cursor
1186 */
1187 public Cursor queryWithFactory(CursorFactory cursorFactory,
1188 boolean distinct, String table, String[] columns,
1189 String selection, String[] selectionArgs, String groupBy,
1190 String having, String orderBy, String limit) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001191 return queryWithFactory(cursorFactory, distinct, table, columns, selection,
1192 selectionArgs, groupBy, having, orderBy, limit, null);
1193 }
1194
1195 /**
1196 * Query the given URL, returning a {@link Cursor} over the result set.
1197 *
1198 * @param cursorFactory the cursor factory to use, or null for the default factory
1199 * @param distinct true if you want each row to be unique, false otherwise.
1200 * @param table The table name to compile the query against.
1201 * @param columns A list of which columns to return. Passing null will
1202 * return all columns, which is discouraged to prevent reading
1203 * data from storage that isn't going to be used.
1204 * @param selection A filter declaring which rows to return, formatted as an
1205 * SQL WHERE clause (excluding the WHERE itself). Passing null
1206 * will return all rows for the given table.
1207 * @param selectionArgs You may include ?s in selection, which will be
1208 * replaced by the values from selectionArgs, in order that they
1209 * appear in the selection. The values will be bound as Strings.
1210 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1211 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1212 * will cause the rows to not be grouped.
1213 * @param having A filter declare which row groups to include in the cursor,
1214 * if row grouping is being used, formatted as an SQL HAVING
1215 * clause (excluding the HAVING itself). Passing null will cause
1216 * all row groups to be included, and is required when row
1217 * grouping is not being used.
1218 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1219 * (excluding the ORDER BY itself). Passing null will use the
1220 * default sort order, which may be unordered.
1221 * @param limit Limits the number of rows returned by the query,
1222 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001223 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001224 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1225 * when the query is executed.
1226 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1227 * {@link Cursor}s are not synchronized, see the documentation for more details.
1228 * @see Cursor
1229 */
1230 public Cursor queryWithFactory(CursorFactory cursorFactory,
1231 boolean distinct, String table, String[] columns,
1232 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001233 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001234 acquireReference();
1235 try {
1236 String sql = SQLiteQueryBuilder.buildQueryString(
1237 distinct, table, columns, selection, groupBy, having, orderBy, limit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238
Jeff Brown03bd3022012-03-06 13:48:56 -08001239 return rawQueryWithFactory(cursorFactory, sql, selectionArgs,
1240 findEditTable(table), cancellationSignal);
1241 } finally {
1242 releaseReference();
1243 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001244 }
1245
1246 /**
1247 * Query the given table, returning a {@link Cursor} over the result set.
1248 *
1249 * @param table The table name to compile the query against.
1250 * @param columns A list of which columns to return. Passing null will
1251 * return all columns, which is discouraged to prevent reading
1252 * data from storage that isn't going to be used.
1253 * @param selection A filter declaring which rows to return, formatted as an
1254 * SQL WHERE clause (excluding the WHERE itself). Passing null
1255 * will return all rows for the given table.
1256 * @param selectionArgs You may include ?s in selection, which will be
1257 * replaced by the values from selectionArgs, in order that they
1258 * appear in the selection. The values will be bound as Strings.
1259 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1260 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1261 * will cause the rows to not be grouped.
1262 * @param having A filter declare which row groups to include in the cursor,
1263 * if row grouping is being used, formatted as an SQL HAVING
1264 * clause (excluding the HAVING itself). Passing null will cause
1265 * all row groups to be included, and is required when row
1266 * grouping is not being used.
1267 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1268 * (excluding the ORDER BY itself). Passing null will use the
1269 * default sort order, which may be unordered.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001270 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1271 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001272 * @see Cursor
1273 */
1274 public Cursor query(String table, String[] columns, String selection,
1275 String[] selectionArgs, String groupBy, String having,
1276 String orderBy) {
1277
1278 return query(false, table, columns, selection, selectionArgs, groupBy,
1279 having, orderBy, null /* limit */);
1280 }
1281
1282 /**
1283 * Query the given table, returning a {@link Cursor} over the result set.
1284 *
1285 * @param table The table name to compile the query against.
1286 * @param columns A list of which columns to return. Passing null will
1287 * return all columns, which is discouraged to prevent reading
1288 * data from storage that isn't going to be used.
1289 * @param selection A filter declaring which rows to return, formatted as an
1290 * SQL WHERE clause (excluding the WHERE itself). Passing null
1291 * will return all rows for the given table.
1292 * @param selectionArgs You may include ?s in selection, which will be
1293 * replaced by the values from selectionArgs, in order that they
1294 * appear in the selection. The values will be bound as Strings.
1295 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1296 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1297 * will cause the rows to not be grouped.
1298 * @param having A filter declare which row groups to include in the cursor,
1299 * if row grouping is being used, formatted as an SQL HAVING
1300 * clause (excluding the HAVING itself). Passing null will cause
1301 * all row groups to be included, and is required when row
1302 * grouping is not being used.
1303 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1304 * (excluding the ORDER BY itself). Passing null will use the
1305 * default sort order, which may be unordered.
1306 * @param limit Limits the number of rows returned by the query,
1307 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001308 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1309 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001310 * @see Cursor
1311 */
1312 public Cursor query(String table, String[] columns, String selection,
1313 String[] selectionArgs, String groupBy, String having,
1314 String orderBy, String limit) {
1315
1316 return query(false, table, columns, selection, selectionArgs, groupBy,
1317 having, orderBy, limit);
1318 }
1319
1320 /**
1321 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1322 *
1323 * @param sql the SQL query. The SQL string must not be ; terminated
1324 * @param selectionArgs You may include ?s in where clause in the query,
1325 * which will be replaced by the values from selectionArgs. The
1326 * values will be bound as Strings.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001327 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1328 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 */
1330 public Cursor rawQuery(String sql, String[] selectionArgs) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001331 return rawQueryWithFactory(null, sql, selectionArgs, null, null);
1332 }
1333
1334 /**
1335 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1336 *
1337 * @param sql the SQL query. The SQL string must not be ; terminated
1338 * @param selectionArgs You may include ?s in where clause in the query,
1339 * which will be replaced by the values from selectionArgs. The
1340 * values will be bound as Strings.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001341 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001342 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1343 * when the query is executed.
1344 * @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.
1346 */
1347 public Cursor rawQuery(String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001348 CancellationSignal cancellationSignal) {
1349 return rawQueryWithFactory(null, sql, selectionArgs, null, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001350 }
1351
1352 /**
1353 * Runs the provided SQL and returns a cursor over the result set.
1354 *
1355 * @param cursorFactory the cursor factory to use, or null for the default factory
1356 * @param sql the SQL query. The SQL string must not be ; terminated
1357 * @param selectionArgs You may include ?s in where clause in the query,
1358 * which will be replaced by the values from selectionArgs. The
1359 * values will be bound as Strings.
1360 * @param editTable the name of the first table, which is editable
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001361 * @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.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 */
1364 public Cursor rawQueryWithFactory(
1365 CursorFactory cursorFactory, String sql, String[] selectionArgs,
1366 String editTable) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001367 return rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable, null);
1368 }
1369
1370 /**
1371 * Runs the provided SQL and returns a cursor over the result set.
1372 *
1373 * @param cursorFactory the cursor factory to use, or null for the default factory
1374 * @param sql the SQL query. The SQL string must not be ; terminated
1375 * @param selectionArgs You may include ?s in where clause in the query,
1376 * which will be replaced by the values from selectionArgs. The
1377 * values will be bound as Strings.
1378 * @param editTable the name of the first table, which is editable
Jeff Brown4c1241d2012-02-02 17:05:00 -08001379 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001380 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1381 * when the query is executed.
1382 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1383 * {@link Cursor}s are not synchronized, see the documentation for more details.
1384 */
1385 public Cursor rawQueryWithFactory(
1386 CursorFactory cursorFactory, String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001387 String editTable, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001388 acquireReference();
1389 try {
1390 SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
1391 cancellationSignal);
1392 return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
1393 selectionArgs);
1394 } finally {
1395 releaseReference();
1396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 }
1398
1399 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400 * Convenience method for inserting a row into the database.
1401 *
1402 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001403 * @param nullColumnHack optional; may be <code>null</code>.
1404 * SQL doesn't allow inserting a completely empty row without
1405 * naming at least one column name. If your provided <code>values</code> is
1406 * empty, no column names are known and an empty row can't be inserted.
1407 * If not set to null, the <code>nullColumnHack</code> parameter
1408 * provides the name of nullable column name to explicitly insert a NULL into
1409 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001410 * @param values this map contains the initial column values for the
1411 * row. The keys should be the column names and the values the
1412 * column values
1413 * @return the row ID of the newly inserted row, or -1 if an error occurred
1414 */
1415 public long insert(String table, String nullColumnHack, ContentValues values) {
1416 try {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001417 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418 } catch (SQLException e) {
1419 Log.e(TAG, "Error inserting " + values, e);
1420 return -1;
1421 }
1422 }
1423
1424 /**
1425 * Convenience method for inserting a row into the database.
1426 *
1427 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001428 * @param nullColumnHack optional; may be <code>null</code>.
1429 * SQL doesn't allow inserting a completely empty row without
1430 * naming at least one column name. If your provided <code>values</code> is
1431 * empty, no column names are known and an empty row can't be inserted.
1432 * If not set to null, the <code>nullColumnHack</code> parameter
1433 * provides the name of nullable column name to explicitly insert a NULL into
1434 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 * @param values this map contains the initial column values for the
1436 * row. The keys should be the column names and the values the
1437 * column values
1438 * @throws SQLException
1439 * @return the row ID of the newly inserted row, or -1 if an error occurred
1440 */
1441 public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
1442 throws SQLException {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001443 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 }
1445
1446 /**
1447 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001448 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 *
1450 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001451 * @param nullColumnHack optional; may be <code>null</code>.
1452 * SQL doesn't allow inserting a completely empty row without
1453 * naming at least one column name. If your provided <code>initialValues</code> is
1454 * empty, no column names are known and an empty row can't be inserted.
1455 * If not set to null, the <code>nullColumnHack</code> parameter
1456 * provides the name of nullable column name to explicitly insert a NULL into
1457 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001459 * 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 -08001460 * @return the row ID of the newly inserted row, or -1 if an error occurred
1461 */
1462 public long replace(String table, String nullColumnHack, ContentValues initialValues) {
1463 try {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001464 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001465 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 } catch (SQLException e) {
1467 Log.e(TAG, "Error inserting " + initialValues, e);
1468 return -1;
1469 }
1470 }
1471
1472 /**
1473 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001474 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 *
1476 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001477 * @param nullColumnHack optional; may be <code>null</code>.
1478 * SQL doesn't allow inserting a completely empty row without
1479 * naming at least one column name. If your provided <code>initialValues</code> is
1480 * empty, no column names are known and an empty row can't be inserted.
1481 * If not set to null, the <code>nullColumnHack</code> parameter
1482 * provides the name of nullable column name to explicitly insert a NULL into
1483 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001485 * the row. The keys should be the column names and the values the column values.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 * @throws SQLException
1487 * @return the row ID of the newly inserted row, or -1 if an error occurred
1488 */
1489 public long replaceOrThrow(String table, String nullColumnHack,
1490 ContentValues initialValues) throws SQLException {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001491 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001492 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 }
1494
1495 /**
1496 * General method for inserting a row into the database.
1497 *
1498 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001499 * @param nullColumnHack optional; may be <code>null</code>.
1500 * SQL doesn't allow inserting a completely empty row without
1501 * naming at least one column name. If your provided <code>initialValues</code> is
1502 * empty, no column names are known and an empty row can't be inserted.
1503 * If not set to null, the <code>nullColumnHack</code> parameter
1504 * provides the name of nullable column name to explicitly insert a NULL into
1505 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 * @param initialValues this map contains the initial column values for the
1507 * row. The keys should be the column names and the values the
1508 * column values
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001509 * @param conflictAlgorithm for insert conflict resolver
Steve Pomeroyc240b602013-03-14 00:42:10 -04001510 * @return the row ID of the newly inserted row OR <code>-1</code> if either the
1511 * input parameter <code>conflictAlgorithm</code> = {@link #CONFLICT_IGNORE}
1512 * or an error occurred.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 */
1514 public long insertWithOnConflict(String table, String nullColumnHack,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001515 ContentValues initialValues, int conflictAlgorithm) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001516 acquireReference();
1517 try {
1518 StringBuilder sql = new StringBuilder();
1519 sql.append("INSERT");
1520 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1521 sql.append(" INTO ");
1522 sql.append(table);
1523 sql.append('(');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524
Jeff Brown03bd3022012-03-06 13:48:56 -08001525 Object[] bindArgs = null;
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001526 int size = (initialValues != null && !initialValues.isEmpty())
Jeff Brown03bd3022012-03-06 13:48:56 -08001527 ? initialValues.size() : 0;
1528 if (size > 0) {
1529 bindArgs = new Object[size];
1530 int i = 0;
1531 for (String colName : initialValues.keySet()) {
1532 sql.append((i > 0) ? "," : "");
1533 sql.append(colName);
1534 bindArgs[i++] = initialValues.get(colName);
1535 }
1536 sql.append(')');
1537 sql.append(" VALUES (");
1538 for (i = 0; i < size; i++) {
1539 sql.append((i > 0) ? ",?" : "?");
1540 }
1541 } else {
1542 sql.append(nullColumnHack + ") VALUES (NULL");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001544 sql.append(')');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545
Jeff Brown03bd3022012-03-06 13:48:56 -08001546 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1547 try {
1548 return statement.executeInsert();
1549 } finally {
1550 statement.close();
1551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001553 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 }
1555 }
1556
1557 /**
1558 * Convenience method for deleting rows in the database.
1559 *
1560 * @param table the table to delete from
1561 * @param whereClause the optional WHERE clause to apply when deleting.
1562 * Passing null will delete all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001563 * @param whereArgs You may include ?s in the where clause, which
1564 * will be replaced by the values from whereArgs. The values
1565 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001566 * @return the number of rows affected if a whereClause is passed in, 0
1567 * otherwise. To remove all rows and get a count pass "1" as the
1568 * whereClause.
1569 */
1570 public int delete(String table, String whereClause, String[] whereArgs) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001571 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001573 SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table +
1574 (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
1575 try {
1576 return statement.executeUpdateDelete();
1577 } finally {
1578 statement.close();
1579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001581 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 }
1583 }
1584
1585 /**
1586 * Convenience method for updating rows in the database.
1587 *
1588 * @param table the table to update in
1589 * @param values a map from column names to new column values. null is a
1590 * valid value that will be translated to NULL.
1591 * @param whereClause the optional WHERE clause to apply when updating.
1592 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001593 * @param whereArgs You may include ?s in the where clause, which
1594 * will be replaced by the values from whereArgs. The values
1595 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 * @return the number of rows affected
1597 */
1598 public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001599 return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 /**
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.
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001613 * @param conflictAlgorithm for update conflict resolver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 * @return the number of rows affected
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 */
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001616 public int updateWithOnConflict(String table, ContentValues values,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001617 String whereClause, String[] whereArgs, int conflictAlgorithm) {
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001618 if (values == null || values.isEmpty()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 throw new IllegalArgumentException("Empty values");
1620 }
1621
Jeff Brown03bd3022012-03-06 13:48:56 -08001622 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001624 StringBuilder sql = new StringBuilder(120);
1625 sql.append("UPDATE ");
1626 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1627 sql.append(table);
1628 sql.append(" SET ");
1629
1630 // move all bind args to one array
1631 int setValuesSize = values.size();
1632 int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
1633 Object[] bindArgs = new Object[bindArgsSize];
1634 int i = 0;
1635 for (String colName : values.keySet()) {
1636 sql.append((i > 0) ? "," : "");
1637 sql.append(colName);
1638 bindArgs[i++] = values.get(colName);
1639 sql.append("=?");
1640 }
1641 if (whereArgs != null) {
1642 for (i = setValuesSize; i < bindArgsSize; i++) {
1643 bindArgs[i] = whereArgs[i - setValuesSize];
1644 }
1645 }
1646 if (!TextUtils.isEmpty(whereClause)) {
1647 sql.append(" WHERE ");
1648 sql.append(whereClause);
1649 }
1650
1651 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1652 try {
1653 return statement.executeUpdateDelete();
1654 } finally {
1655 statement.close();
1656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001658 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 }
1660 }
1661
1662 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001663 * Execute a single SQL statement that is NOT a SELECT
1664 * or any other SQL statement that returns data.
1665 * <p>
Vasu Norice38b982010-07-22 13:57:13 -07001666 * It has no means to return any data (such as the number of affected rows).
Vasu Noriccd95442010-05-28 17:04:16 -07001667 * Instead, you're encouraged to use {@link #insert(String, String, ContentValues)},
1668 * {@link #update(String, ContentValues, String, String[])}, et al, when possible.
1669 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001670 * <p>
1671 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1672 * automatically managed by this class. So, do not set journal_mode
1673 * using "PRAGMA journal_mode'<value>" statement if your app is using
1674 * {@link #enableWriteAheadLogging()}
1675 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 *
Vasu Noriccd95442010-05-28 17:04:16 -07001677 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1678 * not supported.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001679 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001680 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001681 public void execSQL(String sql) throws SQLException {
Vasu Nori16057fa2011-03-18 11:40:37 -07001682 executeSql(sql, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 }
1684
1685 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001686 * Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE.
1687 * <p>
1688 * For INSERT statements, use any of the following instead.
1689 * <ul>
1690 * <li>{@link #insert(String, String, ContentValues)}</li>
1691 * <li>{@link #insertOrThrow(String, String, ContentValues)}</li>
1692 * <li>{@link #insertWithOnConflict(String, String, ContentValues, int)}</li>
1693 * </ul>
1694 * <p>
1695 * For UPDATE statements, use any of the following instead.
1696 * <ul>
1697 * <li>{@link #update(String, ContentValues, String, String[])}</li>
1698 * <li>{@link #updateWithOnConflict(String, ContentValues, String, String[], int)}</li>
1699 * </ul>
1700 * <p>
1701 * For DELETE statements, use any of the following instead.
1702 * <ul>
1703 * <li>{@link #delete(String, String, String[])}</li>
1704 * </ul>
1705 * <p>
1706 * For example, the following are good candidates for using this method:
1707 * <ul>
1708 * <li>ALTER TABLE</li>
1709 * <li>CREATE or DROP table / trigger / view / index / virtual table</li>
1710 * <li>REINDEX</li>
1711 * <li>RELEASE</li>
1712 * <li>SAVEPOINT</li>
1713 * <li>PRAGMA that returns no data</li>
1714 * </ul>
1715 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001716 * <p>
1717 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1718 * automatically managed by this class. So, do not set journal_mode
1719 * using "PRAGMA journal_mode'<value>" statement if your app is using
1720 * {@link #enableWriteAheadLogging()}
1721 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001722 *
Vasu Noriccd95442010-05-28 17:04:16 -07001723 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1724 * not supported.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001725 * @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001726 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001728 public void execSQL(String sql, Object[] bindArgs) throws SQLException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 if (bindArgs == null) {
1730 throw new IllegalArgumentException("Empty bindArgs");
1731 }
Vasu Norib83cb7c2010-09-14 13:36:01 -07001732 executeSql(sql, bindArgs);
Vasu Norice38b982010-07-22 13:57:13 -07001733 }
1734
Vasu Nori54025902010-09-14 12:14:26 -07001735 private int executeSql(String sql, Object[] bindArgs) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001736 acquireReference();
1737 try {
1738 if (DatabaseUtils.getSqlStatementType(sql) == DatabaseUtils.STATEMENT_ATTACH) {
1739 boolean disableWal = false;
1740 synchronized (mLock) {
1741 if (!mHasAttachedDbsLocked) {
1742 mHasAttachedDbsLocked = true;
1743 disableWal = true;
Fyodor Kupolovfd9c4a52017-07-13 15:36:57 -07001744 mConnectionPoolLocked.disableIdleConnectionHandler();
Jeff Brown03bd3022012-03-06 13:48:56 -08001745 }
1746 }
1747 if (disableWal) {
1748 disableWriteAheadLogging();
Jeff Browne5360fb2011-10-31 17:48:13 -07001749 }
1750 }
Jeff Browne5360fb2011-10-31 17:48:13 -07001751
Jeff Brown03bd3022012-03-06 13:48:56 -08001752 SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs);
1753 try {
1754 return statement.executeUpdateDelete();
1755 } finally {
1756 statement.close();
1757 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001759 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 }
1762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 /**
Makoto Onuki17aa1b72015-12-16 14:02:01 -08001764 * Verifies that a SQL SELECT statement is valid by compiling it.
1765 * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
1766 *
1767 * @param sql SQL to be validated
1768 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
1769 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1770 * when the query is executed.
1771 * @throws SQLiteException if {@code sql} is invalid
1772 */
1773 public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal) {
1774 getThreadSession().prepare(sql,
1775 getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null);
1776 }
1777
1778 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001779 * Returns true if the database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001781 * @return True if database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 */
1783 public boolean isReadOnly() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001784 synchronized (mLock) {
1785 return isReadOnlyLocked();
1786 }
1787 }
1788
1789 private boolean isReadOnlyLocked() {
1790 return (mConfigurationLocked.openFlags & OPEN_READ_MASK) == OPEN_READONLY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791 }
1792
1793 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001794 * Returns true if the database is in-memory db.
1795 *
1796 * @return True if the database is in-memory.
1797 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798 */
Jeff Browne5360fb2011-10-31 17:48:13 -07001799 public boolean isInMemoryDatabase() {
1800 synchronized (mLock) {
1801 return mConfigurationLocked.isInMemoryDb();
1802 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 }
1804
Jeff Browne5360fb2011-10-31 17:48:13 -07001805 /**
1806 * Returns true if the database is currently open.
1807 *
1808 * @return True if the database is currently open (has not been closed).
1809 */
1810 public boolean isOpen() {
1811 synchronized (mLock) {
1812 return mConnectionPoolLocked != null;
1813 }
1814 }
1815
1816 /**
1817 * Returns true if the new version code is greater than the current database version.
1818 *
1819 * @param newVersion The new version code.
Mark Lu1e202082016-08-30 17:41:25 -07001820 * @return True if the new version code is greater than the current database version.
Jeff Browne5360fb2011-10-31 17:48:13 -07001821 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001822 public boolean needUpgrade(int newVersion) {
1823 return newVersion > getVersion();
1824 }
1825
1826 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001827 * Gets the path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001828 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001829 * @return The path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 */
1831 public final String getPath() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001832 synchronized (mLock) {
1833 return mConfigurationLocked.path;
Christopher Tatead9e8b12011-10-05 17:49:26 -07001834 }
Brad Fitzpatrick722802e2010-03-23 22:22:16 -07001835 }
1836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837 /**
1838 * Sets the locale for this database. Does nothing if this database has
Jeff Brown1d9f7422012-03-15 14:32:32 -07001839 * the {@link #NO_LOCALIZED_COLLATORS} flag set or was opened read only.
Jeff Browne5360fb2011-10-31 17:48:13 -07001840 *
1841 * @param locale The new locale.
1842 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 * @throws SQLException if the locale could not be set. The most common reason
1844 * for this is that there is no collator available for the locale you requested.
1845 * In this case the database remains unchanged.
1846 */
1847 public void setLocale(Locale locale) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001848 if (locale == null) {
1849 throw new IllegalArgumentException("locale must not be null.");
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001850 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001851
Jeff Browne5360fb2011-10-31 17:48:13 -07001852 synchronized (mLock) {
1853 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001854
1855 final Locale oldLocale = mConfigurationLocked.locale;
Jeff Browne5360fb2011-10-31 17:48:13 -07001856 mConfigurationLocked.locale = locale;
Jeff Browne67ca422012-03-21 17:24:05 -07001857 try {
1858 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1859 } catch (RuntimeException ex) {
1860 mConfigurationLocked.locale = oldLocale;
1861 throw ex;
1862 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001863 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001864 }
1865
Vasu Norie495d1f2010-01-06 16:34:19 -08001866 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001867 * Sets the maximum size of the prepared-statement cache for this database.
Vasu Norie495d1f2010-01-06 16:34:19 -08001868 * (size of the cache = number of compiled-sql-statements stored in the cache).
Vasu Noriccd95442010-05-28 17:04:16 -07001869 *<p>
Vasu Norib729dcc2010-09-14 11:35:49 -07001870 * Maximum cache size can ONLY be increased from its current size (default = 10).
Vasu Noriccd95442010-05-28 17:04:16 -07001871 * If this method is called with smaller size than the current maximum value,
1872 * then IllegalStateException is thrown.
Vasu Norib729dcc2010-09-14 11:35:49 -07001873 *<p>
1874 * This method is thread-safe.
Vasu Norie495d1f2010-01-06 16:34:19 -08001875 *
Vasu Nori90a367262010-04-12 12:49:09 -07001876 * @param cacheSize the size of the cache. can be (0 to {@link #MAX_SQL_CACHE_SIZE})
Jeff Browne5360fb2011-10-31 17:48:13 -07001877 * @throws IllegalStateException if input cacheSize > {@link #MAX_SQL_CACHE_SIZE}.
Vasu Norie495d1f2010-01-06 16:34:19 -08001878 */
Vasu Nori54025902010-09-14 12:14:26 -07001879 public void setMaxSqlCacheSize(int cacheSize) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001880 if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) {
1881 throw new IllegalStateException(
1882 "expected value between 0 and " + MAX_SQL_CACHE_SIZE);
Vasu Nori587423a2010-09-27 18:18:34 -07001883 }
Vasu Nori587423a2010-09-27 18:18:34 -07001884
Jeff Browne5360fb2011-10-31 17:48:13 -07001885 synchronized (mLock) {
1886 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001887
1888 final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize;
Jeff Browne5360fb2011-10-31 17:48:13 -07001889 mConfigurationLocked.maxSqlCacheSize = cacheSize;
Jeff Browne67ca422012-03-21 17:24:05 -07001890 try {
1891 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1892 } catch (RuntimeException ex) {
1893 mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize;
1894 throw ex;
1895 }
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001896 }
1897 }
1898
Vasu Nori6c354da2010-04-26 23:33:39 -07001899 /**
Jeff Brown96496ad2012-03-23 14:38:06 -07001900 * Sets whether foreign key constraints are enabled for the database.
1901 * <p>
1902 * By default, foreign key constraints are not enforced by the database.
1903 * This method allows an application to enable foreign key constraints.
1904 * It must be called each time the database is opened to ensure that foreign
1905 * key constraints are enabled for the session.
1906 * </p><p>
1907 * A good time to call this method is right after calling {@link #openOrCreateDatabase}
1908 * or in the {@link SQLiteOpenHelper#onConfigure} callback.
1909 * </p><p>
1910 * When foreign key constraints are disabled, the database does not check whether
1911 * changes to the database will violate foreign key constraints. Likewise, when
1912 * foreign key constraints are disabled, the database will not execute cascade
1913 * delete or update triggers. As a result, it is possible for the database
1914 * state to become inconsistent. To perform a database integrity check,
1915 * call {@link #isDatabaseIntegrityOk}.
1916 * </p><p>
1917 * This method must not be called while a transaction is in progress.
1918 * </p><p>
1919 * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a>
1920 * for more details about foreign key constraint support.
1921 * </p>
1922 *
1923 * @param enable True to enable foreign key constraints, false to disable them.
1924 *
1925 * @throws IllegalStateException if the are transactions is in progress
1926 * when this method is called.
1927 */
1928 public void setForeignKeyConstraintsEnabled(boolean enable) {
1929 synchronized (mLock) {
1930 throwIfNotOpenLocked();
1931
1932 if (mConfigurationLocked.foreignKeyConstraintsEnabled == enable) {
1933 return;
1934 }
1935
1936 mConfigurationLocked.foreignKeyConstraintsEnabled = enable;
1937 try {
1938 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1939 } catch (RuntimeException ex) {
1940 mConfigurationLocked.foreignKeyConstraintsEnabled = !enable;
1941 throw ex;
1942 }
1943 }
1944 }
1945
1946 /**
Jeff Brown47847f32012-03-22 19:13:11 -07001947 * This method enables parallel execution of queries from multiple threads on the
1948 * same database. It does this by opening multiple connections to the database
1949 * and using a different database connection for each query. The database
1950 * journal mode is also changed to enable writes to proceed concurrently with reads.
Vasu Nori6c354da2010-04-26 23:33:39 -07001951 * <p>
Jeff Brown47847f32012-03-22 19:13:11 -07001952 * When write-ahead logging is not enabled (the default), it is not possible for
1953 * reads and writes to occur on the database at the same time. Before modifying the
1954 * database, the writer implicitly acquires an exclusive lock on the database which
1955 * prevents readers from accessing the database until the write is completed.
1956 * </p><p>
1957 * In contrast, when write-ahead logging is enabled (by calling this method), write
1958 * operations occur in a separate log file which allows reads to proceed concurrently.
1959 * While a write is in progress, readers on other threads will perceive the state
1960 * of the database as it was before the write began. When the write completes, readers
1961 * on other threads will then perceive the new state of the database.
1962 * </p><p>
1963 * It is a good idea to enable write-ahead logging whenever a database will be
1964 * concurrently accessed and modified by multiple threads at the same time.
1965 * However, write-ahead logging uses significantly more memory than ordinary
1966 * journaling because there are multiple connections to the same database.
1967 * So if a database will only be used by a single thread, or if optimizing
1968 * concurrency is not very important, then write-ahead logging should be disabled.
1969 * </p><p>
1970 * After calling this method, execution of queries in parallel is enabled as long as
1971 * the database remains open. To disable execution of queries in parallel, either
1972 * call {@link #disableWriteAheadLogging} or close the database and reopen it.
1973 * </p><p>
1974 * The maximum number of connections used to execute queries in parallel is
Vasu Nori6c354da2010-04-26 23:33:39 -07001975 * dependent upon the device memory and possibly other properties.
Jeff Brown47847f32012-03-22 19:13:11 -07001976 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07001977 * If a query is part of a transaction, then it is executed on the same database handle the
1978 * transaction was begun.
Jeff Brown47847f32012-03-22 19:13:11 -07001979 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07001980 * Writers should use {@link #beginTransactionNonExclusive()} or
1981 * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
Jeff Brown47847f32012-03-22 19:13:11 -07001982 * to start a transaction. Non-exclusive mode allows database file to be in readable
1983 * by other threads executing queries.
1984 * </p><p>
1985 * If the database has any attached databases, then execution of queries in parallel is NOT
1986 * possible. Likewise, write-ahead logging is not supported for read-only databases
1987 * or memory databases. In such cases, {@link #enableWriteAheadLogging} returns false.
1988 * </p><p>
1989 * The best way to enable write-ahead logging is to pass the
1990 * {@link #ENABLE_WRITE_AHEAD_LOGGING} flag to {@link #openDatabase}. This is
1991 * more efficient than calling {@link #enableWriteAheadLogging}.
1992 * <code><pre>
1993 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
1994 * SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
1995 * myDatabaseErrorHandler);
1996 * db.enableWriteAheadLogging();
1997 * </pre></code>
1998 * </p><p>
1999 * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging}
2000 * after opening the database.
2001 * <code><pre>
2002 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
2003 * SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
2004 * db.enableWriteAheadLogging();
2005 * </pre></code>
2006 * </p><p>
2007 * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for
2008 * more details about how write-ahead logging works.
Vasu Nori6c354da2010-04-26 23:33:39 -07002009 * </p>
2010 *
Jeff Brown47847f32012-03-22 19:13:11 -07002011 * @return True if write-ahead logging is enabled.
Jeff Browne67ca422012-03-21 17:24:05 -07002012 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002013 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002014 * time this method is called. WAL mode can only be changed when there are no
2015 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002016 *
2017 * @see #ENABLE_WRITE_AHEAD_LOGGING
2018 * @see #disableWriteAheadLogging
Vasu Nori6c354da2010-04-26 23:33:39 -07002019 */
Vasu Noriffe06122010-09-27 12:32:57 -07002020 public boolean enableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002021 synchronized (mLock) {
2022 throwIfNotOpenLocked();
2023
Jeff Brown47847f32012-03-22 19:13:11 -07002024 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002025 return true;
2026 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002027
2028 if (isReadOnlyLocked()) {
2029 // WAL doesn't make sense for readonly-databases.
2030 // TODO: True, but connection pooling does still make sense...
2031 return false;
2032 }
2033
2034 if (mConfigurationLocked.isInMemoryDb()) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002035 Log.i(TAG, "can't enable WAL for memory databases.");
2036 return false;
2037 }
2038
2039 // make sure this database has NO attached databases because sqlite's write-ahead-logging
2040 // doesn't work for databases with attached databases
Jeff Browne5360fb2011-10-31 17:48:13 -07002041 if (mHasAttachedDbsLocked) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002042 if (Log.isLoggable(TAG, Log.DEBUG)) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002043 Log.d(TAG, "this database: " + mConfigurationLocked.label
2044 + " has attached databases. can't enable WAL.");
Paul Westbrookdae6d372011-02-17 10:59:56 -08002045 }
2046 return false;
2047 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002048
Jeff Brown47847f32012-03-22 19:13:11 -07002049 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002050 try {
2051 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2052 } catch (RuntimeException ex) {
Jeff Brown47847f32012-03-22 19:13:11 -07002053 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002054 throw ex;
2055 }
Paul Westbrookdae6d372011-02-17 10:59:56 -08002056 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002057 return true;
Vasu Nori6c354da2010-04-26 23:33:39 -07002058 }
2059
Vasu Nori2827d6d2010-07-04 00:26:18 -07002060 /**
Vasu Nori7b04c412010-07-20 10:31:21 -07002061 * This method disables the features enabled by {@link #enableWriteAheadLogging()}.
Jeff Browne67ca422012-03-21 17:24:05 -07002062 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002063 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002064 * time this method is called. WAL mode can only be changed when there are no
2065 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002066 *
2067 * @see #enableWriteAheadLogging
Vasu Nori2827d6d2010-07-04 00:26:18 -07002068 */
Vasu Nori7b04c412010-07-20 10:31:21 -07002069 public void disableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002070 synchronized (mLock) {
2071 throwIfNotOpenLocked();
2072
Jeff Brown47847f32012-03-22 19:13:11 -07002073 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002074 return;
Paul Westbrookdae6d372011-02-17 10:59:56 -08002075 }
Vasu Nori8d111032010-06-22 18:34:21 -07002076
Jeff Brown47847f32012-03-22 19:13:11 -07002077 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002078 try {
2079 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2080 } catch (RuntimeException ex) {
Jeff Brown47847f32012-03-22 19:13:11 -07002081 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002082 throw ex;
2083 }
Vasu Nori65a88832010-07-16 15:14:08 -07002084 }
Vasu Nori6c354da2010-04-26 23:33:39 -07002085 }
2086
Vasu Norif3cf8a42010-03-23 11:41:44 -07002087 /**
Jeff Brown47847f32012-03-22 19:13:11 -07002088 * Returns true if write-ahead logging has been enabled for this database.
2089 *
2090 * @return True if write-ahead logging has been enabled for this database.
2091 *
2092 * @see #enableWriteAheadLogging
2093 * @see #ENABLE_WRITE_AHEAD_LOGGING
2094 */
2095 public boolean isWriteAheadLoggingEnabled() {
2096 synchronized (mLock) {
2097 throwIfNotOpenLocked();
2098
2099 return (mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2100 }
2101 }
2102
2103 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002104 * Collect statistics about all open databases in the current process.
2105 * Used by bug report.
Vasu Norif3cf8a42010-03-23 11:41:44 -07002106 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002107 static ArrayList<DbStats> getDbStats() {
Vasu Noric3849202010-03-09 10:47:25 -08002108 ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002109 for (SQLiteDatabase db : getActiveDatabases()) {
2110 db.collectDbStats(dbStatsList);
Vasu Nori24675612010-09-27 14:54:19 -07002111 }
Vasu Noric3849202010-03-09 10:47:25 -08002112 return dbStatsList;
2113 }
2114
Jeff Browne5360fb2011-10-31 17:48:13 -07002115 private void collectDbStats(ArrayList<DbStats> dbStatsList) {
2116 synchronized (mLock) {
2117 if (mConnectionPoolLocked != null) {
2118 mConnectionPoolLocked.collectDbStats(dbStatsList);
2119 }
2120 }
2121 }
2122
2123 private static ArrayList<SQLiteDatabase> getActiveDatabases() {
2124 ArrayList<SQLiteDatabase> databases = new ArrayList<SQLiteDatabase>();
2125 synchronized (sActiveDatabases) {
2126 databases.addAll(sActiveDatabases.keySet());
2127 }
2128 return databases;
2129 }
2130
2131 /**
2132 * Dump detailed information about all open databases in the current process.
2133 * Used by bug report.
2134 */
Jeff Browna9be4152012-01-18 15:29:57 -08002135 static void dumpAll(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002136 for (SQLiteDatabase db : getActiveDatabases()) {
Jeff Browna9be4152012-01-18 15:29:57 -08002137 db.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002138 }
2139 }
2140
Jeff Browna9be4152012-01-18 15:29:57 -08002141 private void dump(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002142 synchronized (mLock) {
2143 if (mConnectionPoolLocked != null) {
2144 printer.println("");
Jeff Browna9be4152012-01-18 15:29:57 -08002145 mConnectionPoolLocked.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002146 }
2147 }
2148 }
2149
Vasu Noric3849202010-03-09 10:47:25 -08002150 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002151 * Returns list of full pathnames of all attached databases including the main database
2152 * by executing 'pragma database_list' on the database.
2153 *
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002154 * @return ArrayList of pairs of (database name, database file path) or null if the database
2155 * is not open.
Vasu Noric3849202010-03-09 10:47:25 -08002156 */
Vasu Noria017eda2011-01-27 10:52:55 -08002157 public List<Pair<String, String>> getAttachedDbs() {
Vasu Noric3849202010-03-09 10:47:25 -08002158 ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002159 synchronized (mLock) {
2160 if (mConnectionPoolLocked == null) {
2161 return null; // not open
2162 }
2163
2164 if (!mHasAttachedDbsLocked) {
2165 // No attached databases.
2166 // There is a small window where attached databases exist but this flag is not
2167 // set yet. This can occur when this thread is in a race condition with another
2168 // thread that is executing the SQL statement: "attach database <blah> as <foo>"
2169 // If this thread is NOT ok with such a race condition (and thus possibly not
2170 // receivethe entire list of attached databases), then the caller should ensure
2171 // that no thread is executing any SQL statements while a thread is calling this
2172 // method. Typically, this method is called when 'adb bugreport' is done or the
2173 // caller wants to collect stats on the database and all its attached databases.
2174 attachedDbs.add(new Pair<String, String>("main", mConfigurationLocked.path));
2175 return attachedDbs;
2176 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002177
2178 acquireReference();
Vasu Nori24675612010-09-27 14:54:19 -07002179 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002180
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002181 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002182 // has attached databases. query sqlite to get the list of attached databases.
2183 Cursor c = null;
2184 try {
2185 c = rawQuery("pragma database_list;", null);
2186 while (c.moveToNext()) {
2187 // sqlite returns a row for each database in the returned list of databases.
2188 // in each row,
2189 // 1st column is the database name such as main, or the database
2190 // name specified on the "ATTACH" command
2191 // 2nd column is the database file path.
2192 attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2)));
2193 }
2194 } finally {
2195 if (c != null) {
2196 c.close();
2197 }
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002198 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002199 return attachedDbs;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002200 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08002201 releaseReference();
Vasu Noric3849202010-03-09 10:47:25 -08002202 }
Vasu Noric3849202010-03-09 10:47:25 -08002203 }
2204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002205 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002206 * Runs 'pragma integrity_check' on the given database (and all the attached databases)
2207 * and returns true if the given database (and all its attached databases) pass integrity_check,
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002208 * false otherwise.
Vasu Noriccd95442010-05-28 17:04:16 -07002209 *<p>
2210 * If the result is false, then this method logs the errors reported by the integrity_check
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002211 * command execution.
Vasu Noriccd95442010-05-28 17:04:16 -07002212 *<p>
2213 * Note that 'pragma integrity_check' on a database can take a long time.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002214 *
2215 * @return true if the given database (and all its attached databases) pass integrity_check,
Vasu Noriccd95442010-05-28 17:04:16 -07002216 * false otherwise.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002217 */
2218 public boolean isDatabaseIntegrityOk() {
Jeff Brown03bd3022012-03-06 13:48:56 -08002219 acquireReference();
Vasu Noribfe1dc22010-08-25 16:29:02 -07002220 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002221 List<Pair<String, String>> attachedDbs = null;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002222 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002223 attachedDbs = getAttachedDbs();
2224 if (attachedDbs == null) {
2225 throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " +
2226 "be retrieved. probably because the database is closed");
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002227 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002228 } catch (SQLiteException e) {
2229 // can't get attachedDb list. do integrity check on the main database
2230 attachedDbs = new ArrayList<Pair<String, String>>();
2231 attachedDbs.add(new Pair<String, String>("main", getPath()));
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002232 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002233
2234 for (int i = 0; i < attachedDbs.size(); i++) {
2235 Pair<String, String> p = attachedDbs.get(i);
2236 SQLiteStatement prog = null;
2237 try {
2238 prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);");
2239 String rslt = prog.simpleQueryForString();
2240 if (!rslt.equalsIgnoreCase("ok")) {
2241 // integrity_checker failed on main or attached databases
2242 Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt);
2243 return false;
2244 }
2245 } finally {
2246 if (prog != null) prog.close();
2247 }
2248 }
2249 } finally {
2250 releaseReference();
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002251 }
Vasu Noribfe1dc22010-08-25 16:29:02 -07002252 return true;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002253 }
2254
Jeff Browne5360fb2011-10-31 17:48:13 -07002255 @Override
2256 public String toString() {
2257 return "SQLiteDatabase: " + getPath();
2258 }
2259
Jeff Browne5360fb2011-10-31 17:48:13 -07002260 private void throwIfNotOpenLocked() {
2261 if (mConnectionPoolLocked == null) {
2262 throw new IllegalStateException("The database '" + mConfigurationLocked.label
2263 + "' is not open.");
2264 }
2265 }
Vasu Nori3ef94e22010-02-05 14:49:04 -08002266
2267 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002268 * Used to allow returning sub-classes of {@link Cursor} when calling query.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002270 public interface CursorFactory {
2271 /**
2272 * See {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}.
2273 */
2274 public Cursor newCursor(SQLiteDatabase db,
2275 SQLiteCursorDriver masterQuery, String editTable,
2276 SQLiteQuery query);
2277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002278
2279 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002280 * A callback interface for a custom sqlite3 function.
2281 * This can be used to create a function that can be called from
2282 * sqlite3 database triggers.
2283 * @hide
Vasu Noric3849202010-03-09 10:47:25 -08002284 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002285 public interface CustomFunction {
2286 public void callback(String[] args);
2287 }
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002288
2289 /**
2290 * Wrapper for configuration parameters that are used for opening {@link SQLiteDatabase}
2291 */
2292 public static final class OpenParams {
2293 private final int mOpenFlags;
2294 private final CursorFactory mCursorFactory;
2295 private final DatabaseErrorHandler mErrorHandler;
2296 private final int mLookasideSlotSize;
2297 private final int mLookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002298 private long mIdleConnectionTimeout;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002299
2300 private OpenParams(int openFlags, CursorFactory cursorFactory,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002301 DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount,
2302 long idleConnectionTimeout) {
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002303 mOpenFlags = openFlags;
2304 mCursorFactory = cursorFactory;
2305 mErrorHandler = errorHandler;
2306 mLookasideSlotSize = lookasideSlotSize;
2307 mLookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002308 mIdleConnectionTimeout = idleConnectionTimeout;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002309 }
2310
2311 /**
2312 * Returns size in bytes of each lookaside slot or -1 if not set.
2313 *
2314 * @see Builder#setLookasideConfig(int, int)
2315 */
2316 @IntRange(from = -1)
2317 public int getLookasideSlotSize() {
2318 return mLookasideSlotSize;
2319 }
2320
2321 /**
2322 * Returns total number of lookaside memory slots per database connection or -1 if not
2323 * set.
2324 *
2325 * @see Builder#setLookasideConfig(int, int)
2326 */
2327 @IntRange(from = -1)
2328 public int getLookasideSlotCount() {
2329 return mLookasideSlotCount;
2330 }
2331
2332 /**
Fyodor Kupolov76436c02017-08-03 17:56:44 -07002333 * Returns flags to control database access mode. Default value is 0.
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002334 *
2335 * @see Builder#setOpenFlags(int)
2336 */
2337 @DatabaseOpenFlags
2338 public int getOpenFlags() {
2339 return mOpenFlags;
2340 }
2341
2342 /**
2343 * Returns an optional factory class that is called to instantiate a cursor when query
2344 * is called
2345 *
2346 * @see Builder#setCursorFactory(CursorFactory)
2347 */
2348 @Nullable
2349 public CursorFactory getCursorFactory() {
2350 return mCursorFactory;
2351 }
2352
2353 /**
2354 * Returns handler for database corruption errors
2355 *
2356 * @see Builder#setErrorHandler(DatabaseErrorHandler)
2357 */
2358 @Nullable
2359 public DatabaseErrorHandler getErrorHandler() {
2360 return mErrorHandler;
2361 }
2362
2363 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002364 * Returns maximum number of milliseconds that SQLite connection is allowed to be idle
2365 * before it is closed and removed from the pool.
2366 * <p>If the value isn't set, the timeout defaults to the system wide timeout
2367 *
2368 * @return timeout in milliseconds or -1 if the value wasn't set.
2369 */
2370 public long getIdleConnectionTimeout() {
2371 return mIdleConnectionTimeout;
2372 }
2373
2374 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002375 * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with
2376 * {@code this} parameters.
2377 * @hide
2378 */
2379 @NonNull
2380 public Builder toBuilder() {
2381 return new Builder(this);
2382 }
2383
2384 /**
2385 * Builder for {@link OpenParams}.
2386 */
2387 public static final class Builder {
2388 private int mLookasideSlotSize = -1;
2389 private int mLookasideSlotCount = -1;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002390 private long mIdleConnectionTimeout = -1;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002391 private int mOpenFlags;
2392 private CursorFactory mCursorFactory;
2393 private DatabaseErrorHandler mErrorHandler;
2394
2395 public Builder() {
2396 }
2397
2398 public Builder(OpenParams params) {
2399 mLookasideSlotSize = params.mLookasideSlotSize;
2400 mLookasideSlotCount = params.mLookasideSlotCount;
2401 mOpenFlags = params.mOpenFlags;
2402 mCursorFactory = params.mCursorFactory;
2403 mErrorHandler = params.mErrorHandler;
2404 }
2405
2406 /**
2407 * Configures
2408 * <a href="https://sqlite.org/malloc.html#lookaside">lookaside memory allocator</a>
2409 *
2410 * <p>SQLite default settings will be used, if this method isn't called.
2411 * Use {@code setLookasideConfig(0,0)} to disable lookaside
2412 *
Fyodor Kupolov05a0f0f2017-06-30 19:00:00 -07002413 * <p><strong>Note:</strong> Provided slotSize/slotCount configuration is just a
2414 * recommendation. The system may choose different values depending on a device, e.g.
2415 * lookaside allocations can be disabled on low-RAM devices
2416 *
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002417 * @param slotSize The size in bytes of each lookaside slot.
2418 * @param slotCount The total number of lookaside memory slots per database connection.
2419 */
2420 public Builder setLookasideConfig(@IntRange(from = 0) final int slotSize,
2421 @IntRange(from = 0) final int slotCount) {
2422 Preconditions.checkArgument(slotSize >= 0,
2423 "lookasideSlotCount cannot be negative");
2424 Preconditions.checkArgument(slotCount >= 0,
2425 "lookasideSlotSize cannot be negative");
2426 Preconditions.checkArgument(
2427 (slotSize > 0 && slotCount > 0) || (slotCount == 0 && slotSize == 0),
2428 "Invalid configuration: " + slotSize + ", " + slotCount);
2429
2430 mLookasideSlotSize = slotSize;
2431 mLookasideSlotCount = slotCount;
2432 return this;
2433 }
2434
2435 /**
2436 * Returns true if {@link #ENABLE_WRITE_AHEAD_LOGGING} flag is set
2437 * @hide
2438 */
2439 public boolean isWriteAheadLoggingEnabled() {
2440 return (mOpenFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2441 }
2442
2443 /**
2444 * Sets flags to control database access mode
2445 * @param openFlags The new flags to set
2446 * @see #OPEN_READWRITE
2447 * @see #OPEN_READONLY
2448 * @see #CREATE_IF_NECESSARY
2449 * @see #NO_LOCALIZED_COLLATORS
2450 * @see #ENABLE_WRITE_AHEAD_LOGGING
2451 * @return same builder instance for chaining multiple calls into a single statement
2452 */
2453 @NonNull
2454 public Builder setOpenFlags(@DatabaseOpenFlags int openFlags) {
2455 mOpenFlags = openFlags;
2456 return this;
2457 }
2458
2459 /**
2460 * Adds flags to control database access mode
2461 *
2462 * @param openFlags The new flags to add
2463 * @return same builder instance for chaining multiple calls into a single statement
2464 */
2465 @NonNull
2466 public Builder addOpenFlags(@DatabaseOpenFlags int openFlags) {
2467 mOpenFlags |= openFlags;
2468 return this;
2469 }
2470
2471 /**
2472 * Removes database access mode flags
2473 *
2474 * @param openFlags Flags to remove
2475 * @return same builder instance for chaining multiple calls into a single statement
2476 */
2477 @NonNull
2478 public Builder removeOpenFlags(@DatabaseOpenFlags int openFlags) {
2479 mOpenFlags &= ~openFlags;
2480 return this;
2481 }
2482
2483 /**
2484 * Sets {@link #ENABLE_WRITE_AHEAD_LOGGING} flag if {@code enabled} is {@code true},
2485 * unsets otherwise
2486 * @hide
2487 */
2488 public void setWriteAheadLoggingEnabled(boolean enabled) {
2489 if (enabled) {
2490 addOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2491 } else {
2492 removeOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2493 }
2494 }
2495
2496 /**
2497 * Set an optional factory class that is called to instantiate a cursor when query
2498 * is called.
2499 *
2500 * @param cursorFactory instance
2501 * @return same builder instance for chaining multiple calls into a single statement
2502 */
2503 @NonNull
2504 public Builder setCursorFactory(@Nullable CursorFactory cursorFactory) {
2505 mCursorFactory = cursorFactory;
2506 return this;
2507 }
2508
2509
2510 /**
2511 * Sets {@link DatabaseErrorHandler} object to handle db corruption errors
2512 */
2513 @NonNull
2514 public Builder setErrorHandler(@Nullable DatabaseErrorHandler errorHandler) {
2515 mErrorHandler = errorHandler;
2516 return this;
2517 }
2518
2519 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002520 * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle
2521 * before it is closed and removed from the pool.
2522 *
2523 * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE}
2524 * to allow unlimited idle connections.
2525 */
2526 @NonNull
2527 public Builder setIdleConnectionTimeout(
2528 @IntRange(from = 0) long idleConnectionTimeoutMs) {
2529 Preconditions.checkArgument(idleConnectionTimeoutMs >= 0,
2530 "idle connection timeout cannot be negative");
2531 mIdleConnectionTimeout = idleConnectionTimeoutMs;
2532 return this;
2533 }
2534
2535 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002536 * Creates an instance of {@link OpenParams} with the options that were previously set
2537 * on this builder
2538 */
2539 @NonNull
2540 public OpenParams build() {
2541 return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002542 mLookasideSlotCount, mIdleConnectionTimeout);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002543 }
2544 }
2545 }
2546
2547 /** @hide */
2548 @IntDef(flag = true, prefix = {"OPEN_", "CREATE_", "NO_", "ENABLE_"}, value = {
2549 OPEN_READWRITE,
2550 OPEN_READONLY,
2551 CREATE_IF_NECESSARY,
2552 NO_LOCALIZED_COLLATORS,
2553 ENABLE_WRITE_AHEAD_LOGGING
2554 })
2555 @Retention(RetentionPolicy.SOURCE)
2556 public @interface DatabaseOpenFlags {}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557}