blob: 5b6efd4dcffe4f1c5bc09e10b294f5e84221aa0f [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 Kupolovcf97b6b2017-07-25 14:17:33 -070082 // TODO b/63398887 STOPSHIP.
83 // Temporarily enabled for testing across a broader set of dogfood devices.
84 private static final boolean DEBUG_CLOSE_IDLE_CONNECTIONS = SystemProperties
85 .getBoolean("persist.debug.sqlite.close_idle_connections", true);
86
Jeff Browne5360fb2011-10-31 17:48:13 -070087 // Stores reference to all databases opened in the current process.
88 // (The referent Object is not used at this time.)
89 // INVARIANT: Guarded by sActiveDatabases.
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070090 private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases = new WeakHashMap<>();
Jeff Browne5360fb2011-10-31 17:48:13 -070091
92 // Thread-local for database sessions that belong to this database.
93 // Each thread has its own database session.
94 // INVARIANT: Immutable.
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -070095 private final ThreadLocal<SQLiteSession> mThreadSession = ThreadLocal
96 .withInitial(this::createSession);
Jeff Browne5360fb2011-10-31 17:48:13 -070097
98 // The optional factory to use when creating new Cursors. May be null.
99 // INVARIANT: Immutable.
100 private final CursorFactory mCursorFactory;
101
102 // Error handler to be used when SQLite returns corruption errors.
103 // INVARIANT: Immutable.
104 private final DatabaseErrorHandler mErrorHandler;
105
106 // Shared database state lock.
107 // This lock guards all of the shared state of the database, such as its
108 // configuration, whether it is open or closed, and so on. This lock should
109 // be held for as little time as possible.
110 //
111 // The lock MUST NOT be held while attempting to acquire database connections or
112 // while executing SQL statements on behalf of the client as it can lead to deadlock.
113 //
114 // It is ok to hold the lock while reconfiguring the connection pool or dumping
115 // statistics because those operations are non-reentrant and do not try to acquire
116 // connections that might be held by other threads.
117 //
118 // Basic rule: grab the lock, access or modify global state, release the lock, then
119 // do the required SQL work.
120 private final Object mLock = new Object();
121
122 // Warns if the database is finalized without being closed properly.
123 // INVARIANT: Guarded by mLock.
124 private final CloseGuard mCloseGuardLocked = CloseGuard.get();
125
126 // The database configuration.
127 // INVARIANT: Guarded by mLock.
128 private final SQLiteDatabaseConfiguration mConfigurationLocked;
129
130 // The connection pool for the database, null when closed.
131 // The pool itself is thread-safe, but the reference to it can only be acquired
132 // when the lock is held.
133 // INVARIANT: Guarded by mLock.
134 private SQLiteConnectionPool mConnectionPoolLocked;
135
136 // True if the database has attached databases.
137 // INVARIANT: Guarded by mLock.
138 private boolean mHasAttachedDbsLocked;
139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700141 * When a constraint violation occurs, an immediate ROLLBACK occurs,
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800142 * thus ending the current transaction, and the command aborts with a
143 * return code of SQLITE_CONSTRAINT. If no transaction is active
144 * (other than the implied transaction that is created on every command)
Jeff Browne5360fb2011-10-31 17:48:13 -0700145 * then this algorithm works the same as ABORT.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800146 */
147 public static final int CONFLICT_ROLLBACK = 1;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700148
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800149 /**
150 * When a constraint violation occurs,no ROLLBACK is executed
151 * so changes from prior commands within the same transaction
152 * are preserved. This is the default behavior.
153 */
154 public static final int CONFLICT_ABORT = 2;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700155
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800156 /**
157 * When a constraint violation occurs, the command aborts with a return
158 * code SQLITE_CONSTRAINT. But any changes to the database that
159 * the command made prior to encountering the constraint violation
160 * are preserved and are not backed out.
161 */
162 public static final int CONFLICT_FAIL = 3;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700163
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800164 /**
165 * When a constraint violation occurs, the one row that contains
166 * the constraint violation is not inserted or changed.
167 * But the command continues executing normally. Other rows before and
168 * after the row that contained the constraint violation continue to be
169 * inserted or updated normally. No error is returned.
170 */
171 public static final int CONFLICT_IGNORE = 4;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700172
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800173 /**
174 * When a UNIQUE constraint violation occurs, the pre-existing rows that
175 * are causing the constraint violation are removed prior to inserting
176 * or updating the current row. Thus the insert or update always occurs.
177 * The command continues executing normally. No error is returned.
178 * If a NOT NULL constraint violation occurs, the NULL value is replaced
179 * by the default value for that column. If the column has no default
180 * value, then the ABORT algorithm is used. If a CHECK constraint
181 * violation occurs then the IGNORE algorithm is used. When this conflict
182 * resolution strategy deletes rows in order to satisfy a constraint,
183 * it does not invoke delete triggers on those rows.
Jeff Browne5360fb2011-10-31 17:48:13 -0700184 * This behavior might change in a future release.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800185 */
186 public static final int CONFLICT_REPLACE = 5;
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700187
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800188 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700189 * Use the following when no conflict action is specified.
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800190 */
191 public static final int CONFLICT_NONE = 0;
Jeff Browne5360fb2011-10-31 17:48:13 -0700192
Vasu Nori8d45e4e2010-02-05 22:35:47 -0800193 private static final String[] CONFLICT_VALUES = new String[]
194 {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 /**
197 * Maximum Length Of A LIKE Or GLOB Pattern
198 * The pattern matching algorithm used in the default LIKE and GLOB implementation
199 * of SQLite can exhibit O(N^2) performance (where N is the number of characters in
200 * the pattern) for certain pathological cases. To avoid denial-of-service attacks
201 * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes.
202 * The default value of this limit is 50000. A modern workstation can evaluate
203 * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly.
204 * The denial of service problem only comes into play when the pattern length gets
205 * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns
206 * are at most a few dozen bytes in length, paranoid application developers may
207 * want to reduce this parameter to something in the range of a few hundred
208 * if they know that external users are able to generate arbitrary patterns.
209 */
210 public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000;
211
212 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700213 * Open flag: Flag for {@link #openDatabase} to open the database for reading and writing.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 * If the disk is full, this may fail even before you actually write anything.
215 *
216 * {@more} Note that the value of this flag is 0, so it is the default.
217 */
218 public static final int OPEN_READWRITE = 0x00000000; // update native code if changing
219
220 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700221 * Open flag: Flag for {@link #openDatabase} to open the database for reading only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 * This is the only reliable way to open a database if the disk may be full.
223 */
224 public static final int OPEN_READONLY = 0x00000001; // update native code if changing
225
226 private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing
227
228 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700229 * Open flag: Flag for {@link #openDatabase} to open the database without support for
230 * localized collators.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 *
232 * {@more} This causes the collator <code>LOCALIZED</code> not to be created.
233 * You must be consistent when using this flag to use the setting the database was
234 * created with. If this is set, {@link #setLocale} will do nothing.
235 */
236 public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing
237
238 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700239 * Open flag: Flag for {@link #openDatabase} to create the database file if it does not
240 * already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 */
242 public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing
243
244 /**
Jeff Brown47847f32012-03-22 19:13:11 -0700245 * Open flag: Flag for {@link #openDatabase} to open the database file with
246 * write-ahead logging enabled by default. Using this flag is more efficient
247 * than calling {@link #enableWriteAheadLogging}.
248 *
249 * Write-ahead logging cannot be used with read-only databases so the value of
250 * this flag is ignored if the database is opened read-only.
251 *
252 * @see #enableWriteAheadLogging
253 */
254 public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;
255
256 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700257 * Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}.
Vasu Norib729dcc2010-09-14 11:35:49 -0700258 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700259 * Each prepared-statement is between 1K - 6K, depending on the complexity of the
260 * SQL statement & schema. A large SQL cache may use a significant amount of memory.
Vasu Norie495d1f2010-01-06 16:34:19 -0800261 */
Vasu Nori90a367262010-04-12 12:49:09 -0700262 public static final int MAX_SQL_CACHE_SIZE = 100;
Vasu Norib729dcc2010-09-14 11:35:49 -0700263
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700264 private SQLiteDatabase(final String path, final int openFlags,
265 CursorFactory cursorFactory, DatabaseErrorHandler errorHandler,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700266 int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700267 mCursorFactory = cursorFactory;
268 mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler();
269 mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700270 mConfigurationLocked.lookasideSlotSize = lookasideSlotSize;
271 mConfigurationLocked.lookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700272 // Disable lookaside allocator on low-RAM devices
273 if (ActivityManager.isLowRamDeviceStatic()) {
274 mConfigurationLocked.lookasideSlotCount = 0;
275 mConfigurationLocked.lookasideSlotSize = 0;
276 }
277 long effectiveTimeoutMs = Long.MAX_VALUE;
278 // Never close idle connections for in-memory databases
279 if (!mConfigurationLocked.isInMemoryDb()) {
280 // First, check app-specific value. Otherwise use defaults
281 // -1 in idleConnectionTimeoutMs indicates unset value
282 if (idleConnectionTimeoutMs >= 0) {
283 effectiveTimeoutMs = idleConnectionTimeoutMs;
284 } else if (DEBUG_CLOSE_IDLE_CONNECTIONS) {
285 effectiveTimeoutMs = SQLiteGlobal.getIdleConnectionTimeout();
286 }
287 }
288 mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700290
Jeff Browne5360fb2011-10-31 17:48:13 -0700291 @Override
292 protected void finalize() throws Throwable {
293 try {
294 dispose(true);
295 } finally {
296 super.finalize();
297 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700298 }
299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 @Override
301 protected void onAllReferencesReleased() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700302 dispose(false);
303 }
304
305 private void dispose(boolean finalized) {
306 final SQLiteConnectionPool pool;
307 synchronized (mLock) {
308 if (mCloseGuardLocked != null) {
309 if (finalized) {
310 mCloseGuardLocked.warnIfOpen();
311 }
312 mCloseGuardLocked.close();
313 }
314
315 pool = mConnectionPoolLocked;
316 mConnectionPoolLocked = null;
317 }
318
319 if (!finalized) {
320 synchronized (sActiveDatabases) {
321 sActiveDatabases.remove(this);
322 }
323
324 if (pool != null) {
325 pool.close();
326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327 }
328 }
329
330 /**
331 * Attempts to release memory that SQLite holds but does not require to
332 * operate properly. Typically this memory will come from the page cache.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700333 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 * @return the number of bytes actually released
335 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700336 public static int releaseMemory() {
337 return SQLiteGlobal.releaseMemory();
338 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339
340 /**
341 * Control whether or not the SQLiteDatabase is made thread-safe by using locks
342 * around critical sections. This is pretty expensive, so if you know that your
343 * DB will only be used by a single thread then you should set this to false.
344 * The default is true.
345 * @param lockingEnabled set to true to enable locks, false otherwise
Jeff Browne5360fb2011-10-31 17:48:13 -0700346 *
347 * @deprecated This method now does nothing. Do not use.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700349 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 public void setLockingEnabled(boolean lockingEnabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 }
352
353 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700354 * Gets a label to use when describing the database in log messages.
355 * @return The label.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700357 String getLabel() {
358 synchronized (mLock) {
359 return mConfigurationLocked.label;
360 }
361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362
Jeff Browne5360fb2011-10-31 17:48:13 -0700363 /**
364 * Sends a corruption message to the database error handler.
365 */
366 void onCorruption() {
367 EventLog.writeEvent(EVENT_DB_CORRUPT, getLabel());
Vasu Noriccd95442010-05-28 17:04:16 -0700368 mErrorHandler.onCorruption(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 }
370
371 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700372 * Gets the {@link SQLiteSession} that belongs to this thread for this database.
373 * Once a thread has obtained a session, it will continue to obtain the same
374 * session even after the database has been closed (although the session will not
375 * be usable). However, a thread that does not already have a session cannot
376 * obtain one after the database has been closed.
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -0700377 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700378 * The idea is that threads that have active connections to the database may still
379 * have work to complete even after the call to {@link #close}. Active database
380 * connections are not actually disposed until they are released by the threads
381 * that own them.
382 *
383 * @return The session, never null.
384 *
385 * @throws IllegalStateException if the thread does not yet have a session and
386 * the database is not open.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700388 SQLiteSession getThreadSession() {
389 return mThreadSession.get(); // initialValue() throws if database closed
Vasu Nori6d970252010-10-05 10:48:49 -0700390 }
Vasu Nori16057fa2011-03-18 11:40:37 -0700391
Jeff Browne5360fb2011-10-31 17:48:13 -0700392 SQLiteSession createSession() {
393 final SQLiteConnectionPool pool;
394 synchronized (mLock) {
395 throwIfNotOpenLocked();
396 pool = mConnectionPoolLocked;
Vasu Nori6d970252010-10-05 10:48:49 -0700397 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700398 return new SQLiteSession(pool);
Vasu Norid4608a32011-02-03 16:24:06 -0800399 }
400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700402 * Gets default connection flags that are appropriate for this thread, taking into
403 * account whether the thread is acting on behalf of the UI.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700405 * @param readOnly True if the connection should be read-only.
406 * @return The connection flags.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700408 int getThreadDefaultConnectionFlags(boolean readOnly) {
409 int flags = readOnly ? SQLiteConnectionPool.CONNECTION_FLAG_READ_ONLY :
410 SQLiteConnectionPool.CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY;
411 if (isMainThread()) {
412 flags |= SQLiteConnectionPool.CONNECTION_FLAG_INTERACTIVE;
413 }
414 return flags;
Vasu Nori16057fa2011-03-18 11:40:37 -0700415 }
416
Jeff Browne5360fb2011-10-31 17:48:13 -0700417 private static boolean isMainThread() {
418 // FIXME: There should be a better way to do this.
419 // Would also be nice to have something that would work across Binder calls.
420 Looper looper = Looper.myLooper();
421 return looper != null && looper == Looper.getMainLooper();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 }
423
424 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700425 * Begins a transaction in EXCLUSIVE mode.
426 * <p>
427 * Transactions can be nested.
428 * When the outer transaction is ended all of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 * the work done in that transaction and all of the nested transactions will be committed or
430 * rolled back. The changes will be rolled back if any transaction is ended without being
431 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700432 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 * <p>Here is the standard idiom for transactions:
434 *
435 * <pre>
436 * db.beginTransaction();
437 * try {
438 * ...
439 * db.setTransactionSuccessful();
440 * } finally {
441 * db.endTransaction();
442 * }
443 * </pre>
444 */
445 public void beginTransaction() {
Vasu Nori6c354da2010-04-26 23:33:39 -0700446 beginTransaction(null /* transactionStatusCallback */, true);
447 }
448
449 /**
450 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
451 * the outer transaction is ended all of the work done in that transaction
452 * and all of the nested transactions will be committed or rolled back. The
453 * changes will be rolled back if any transaction is ended without being
454 * marked as clean (by calling setTransactionSuccessful). Otherwise they
455 * will be committed.
456 * <p>
457 * Here is the standard idiom for transactions:
458 *
459 * <pre>
460 * db.beginTransactionNonExclusive();
461 * try {
462 * ...
463 * db.setTransactionSuccessful();
464 * } finally {
465 * db.endTransaction();
466 * }
467 * </pre>
468 */
469 public void beginTransactionNonExclusive() {
470 beginTransaction(null /* transactionStatusCallback */, false);
Fred Quintanac4516a72009-09-03 12:14:06 -0700471 }
472
473 /**
Vasu Noriccd95442010-05-28 17:04:16 -0700474 * Begins a transaction in EXCLUSIVE mode.
475 * <p>
476 * Transactions can be nested.
477 * When the outer transaction is ended all of
Fred Quintanac4516a72009-09-03 12:14:06 -0700478 * the work done in that transaction and all of the nested transactions will be committed or
479 * rolled back. The changes will be rolled back if any transaction is ended without being
480 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
Vasu Noriccd95442010-05-28 17:04:16 -0700481 * </p>
Fred Quintanac4516a72009-09-03 12:14:06 -0700482 * <p>Here is the standard idiom for transactions:
483 *
484 * <pre>
485 * db.beginTransactionWithListener(listener);
486 * try {
487 * ...
488 * db.setTransactionSuccessful();
489 * } finally {
490 * db.endTransaction();
491 * }
492 * </pre>
Vasu Noriccd95442010-05-28 17:04:16 -0700493 *
Fred Quintanac4516a72009-09-03 12:14:06 -0700494 * @param transactionListener listener that should be notified when the transaction begins,
495 * commits, or is rolled back, either explicitly or by a call to
496 * {@link #yieldIfContendedSafely}.
497 */
498 public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
Vasu Nori6c354da2010-04-26 23:33:39 -0700499 beginTransaction(transactionListener, true);
500 }
501
502 /**
503 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
504 * the outer transaction is ended all of the work done in that transaction
505 * and all of the nested transactions will be committed or rolled back. The
506 * changes will be rolled back if any transaction is ended without being
507 * marked as clean (by calling setTransactionSuccessful). Otherwise they
508 * will be committed.
509 * <p>
510 * Here is the standard idiom for transactions:
511 *
512 * <pre>
513 * db.beginTransactionWithListenerNonExclusive(listener);
514 * try {
515 * ...
516 * db.setTransactionSuccessful();
517 * } finally {
518 * db.endTransaction();
519 * }
520 * </pre>
521 *
522 * @param transactionListener listener that should be notified when the
523 * transaction begins, commits, or is rolled back, either
524 * explicitly or by a call to {@link #yieldIfContendedSafely}.
525 */
526 public void beginTransactionWithListenerNonExclusive(
527 SQLiteTransactionListener transactionListener) {
528 beginTransaction(transactionListener, false);
529 }
530
531 private void beginTransaction(SQLiteTransactionListener transactionListener,
532 boolean exclusive) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800533 acquireReference();
534 try {
535 getThreadSession().beginTransaction(
536 exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
537 SQLiteSession.TRANSACTION_MODE_IMMEDIATE,
538 transactionListener,
539 getThreadDefaultConnectionFlags(false /*readOnly*/), null);
540 } finally {
541 releaseReference();
542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 }
544
545 /**
546 * End a transaction. See beginTransaction for notes about how to use this and when transactions
547 * are committed and rolled back.
548 */
549 public void endTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800550 acquireReference();
551 try {
552 getThreadSession().endTransaction(null);
553 } finally {
554 releaseReference();
555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 }
557
558 /**
559 * Marks the current transaction as successful. Do not do any more database work between
560 * calling this and calling endTransaction. Do as little non-database work as possible in that
561 * situation too. If any errors are encountered between this and endTransaction the transaction
562 * will still be committed.
563 *
564 * @throws IllegalStateException if the current thread is not in a transaction or the
565 * transaction is already marked as successful.
566 */
567 public void setTransactionSuccessful() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800568 acquireReference();
569 try {
570 getThreadSession().setTransactionSuccessful();
571 } finally {
572 releaseReference();
573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800574 }
575
576 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700577 * Returns true if the current thread has a transaction pending.
578 *
579 * @return True if the current thread is in a transaction.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 */
581 public boolean inTransaction() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800582 acquireReference();
583 try {
584 return getThreadSession().hasTransaction();
585 } finally {
586 releaseReference();
587 }
Vasu Norice38b982010-07-22 13:57:13 -0700588 }
589
590 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700591 * Returns true if the current thread is holding an active connection to the database.
Vasu Norice38b982010-07-22 13:57:13 -0700592 * <p>
Jeff Browne5360fb2011-10-31 17:48:13 -0700593 * The name of this method comes from a time when having an active connection
594 * to the database meant that the thread was holding an actual lock on the
595 * database. Nowadays, there is no longer a true "database lock" although threads
596 * may block if they cannot acquire a database connection to perform a
597 * particular operation.
598 * </p>
Vasu Norice38b982010-07-22 13:57:13 -0700599 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700600 * @return True if the current thread is holding an active connection to the database.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 */
602 public boolean isDbLockedByCurrentThread() {
Jeff Brown03bd3022012-03-06 13:48:56 -0800603 acquireReference();
604 try {
605 return getThreadSession().hasConnection();
606 } finally {
607 releaseReference();
608 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800609 }
610
611 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700612 * Always returns false.
613 * <p>
614 * There is no longer the concept of a database lock, so this method always returns false.
615 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 *
Jeff Browne5360fb2011-10-31 17:48:13 -0700617 * @return False.
618 * @deprecated Always returns false. Do not use this method.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 */
Jeff Browne5360fb2011-10-31 17:48:13 -0700620 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 public boolean isDbLockedByOtherThreads() {
Jeff Browne5360fb2011-10-31 17:48:13 -0700622 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 }
624
625 /**
626 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
627 * successful so far. Do not call setTransactionSuccessful before calling this. When this
628 * returns a new transaction will have been created but not marked as successful.
629 * @return true if the transaction was yielded
630 * @deprecated if the db is locked more than once (becuase of nested transactions) then the lock
631 * will not be yielded. Use yieldIfContendedSafely instead.
632 */
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700633 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 public boolean yieldIfContended() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700635 return yieldIfContendedHelper(false /* do not check yielding */,
636 -1 /* sleepAfterYieldDelay */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637 }
638
639 /**
640 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
641 * successful so far. Do not call setTransactionSuccessful before calling this. When this
642 * returns a new transaction will have been created but not marked as successful. This assumes
643 * that there are no nested transactions (beginTransaction has only been called once) and will
Fred Quintana5c7aede2009-08-27 21:41:27 -0700644 * throw an exception if that is not the case.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 * @return true if the transaction was yielded
646 */
647 public boolean yieldIfContendedSafely() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700648 return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 }
650
Fred Quintana5c7aede2009-08-27 21:41:27 -0700651 /**
652 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
653 * successful so far. Do not call setTransactionSuccessful before calling this. When this
654 * returns a new transaction will have been created but not marked as successful. This assumes
655 * that there are no nested transactions (beginTransaction has only been called once) and will
656 * throw an exception if that is not the case.
657 * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if
658 * the lock was actually yielded. This will allow other background threads to make some
659 * more progress than they would if we started the transaction immediately.
660 * @return true if the transaction was yielded
661 */
662 public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
663 return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay);
664 }
665
Jeff Browne5360fb2011-10-31 17:48:13 -0700666 private boolean yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay) {
Jeff Brown03bd3022012-03-06 13:48:56 -0800667 acquireReference();
668 try {
669 return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null);
670 } finally {
671 releaseReference();
672 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800673 }
674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675 /**
Jeff Browne5360fb2011-10-31 17:48:13 -0700676 * Deprecated.
Vasu Nori95675132010-07-21 16:24:40 -0700677 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 */
Vasu Nori95675132010-07-21 16:24:40 -0700679 @Deprecated
680 public Map<String, String> getSyncedTables() {
681 return new HashMap<String, String>(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682 }
683
684 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685 * Open the database according to the flags {@link #OPEN_READWRITE}
686 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
687 *
688 * <p>Sets the locale of the database to the the system's current locale.
689 * Call {@link #setLocale} if you would like something else.</p>
690 *
691 * @param path to database file to open and/or create
692 * @param factory an optional factory class that is called to instantiate a
693 * cursor when query is called, or null for default
694 * @param flags to control database access mode
695 * @return the newly opened database
696 * @throws SQLiteException if the database cannot be opened
697 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700698 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
699 @DatabaseOpenFlags int flags) {
Jeff Brown47847f32012-03-22 19:13:11 -0700700 return openDatabase(path, factory, flags, null);
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700701 }
702
703 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700704 * Open the database according to the specified {@link OpenParams parameters}
705 *
706 * @param path to database file to open and/or create
707 * @param openParams configuration parameters that are used for opening {@link SQLiteDatabase}
708 * @return the newly opened database
709 * @throws SQLiteException if the database cannot be opened
710 */
711 public static SQLiteDatabase openDatabase(@NonNull String path,
712 @NonNull OpenParams openParams) {
713 Preconditions.checkArgument(openParams != null, "OpenParams cannot be null");
714 SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags,
715 openParams.mCursorFactory, openParams.mErrorHandler,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700716 openParams.mLookasideSlotSize, openParams.mLookasideSlotCount,
717 openParams.mIdleConnectionTimeout);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700718 db.open();
719 return db;
720 }
721
722 /**
Vasu Nori74f170f2010-06-01 18:06:18 -0700723 * Open the database according to the flags {@link #OPEN_READWRITE}
724 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
725 *
726 * <p>Sets the locale of the database to the the system's current locale.
727 * Call {@link #setLocale} if you would like something else.</p>
728 *
729 * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be
730 * used to handle corruption when sqlite reports database corruption.</p>
731 *
732 * @param path to database file to open and/or create
733 * @param factory an optional factory class that is called to instantiate a
734 * cursor when query is called, or null for default
735 * @param flags to control database access mode
736 * @param errorHandler the {@link DatabaseErrorHandler} obj to be used to handle corruption
737 * when sqlite reports database corruption
738 * @return the newly opened database
739 * @throws SQLiteException if the database cannot be opened
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700740 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700741 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
742 @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler) {
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -0700743 SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1, -1);
Jeff Browne5360fb2011-10-31 17:48:13 -0700744 db.open();
745 return db;
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700746 }
747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 /**
749 * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
750 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700751 public static SQLiteDatabase openOrCreateDatabase(@NonNull File file,
752 @Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800753 return openOrCreateDatabase(file.getPath(), factory);
754 }
755
756 /**
757 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
758 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700759 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
760 @Nullable CursorFactory factory) {
Jeff Brown47847f32012-03-22 19:13:11 -0700761 return openDatabase(path, factory, CREATE_IF_NECESSARY, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 }
763
764 /**
Vasu Nori6c354da2010-04-26 23:33:39 -0700765 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler).
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700766 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700767 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
768 @Nullable CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler) {
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700769 return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler);
770 }
771
Jeff Brown559d0642012-02-29 10:19:12 -0800772 /**
Jeff Brown79087e42012-03-01 19:52:44 -0800773 * Deletes a database including its journal file and other auxiliary files
774 * that may have been created by the database engine.
775 *
776 * @param file The database file path.
777 * @return True if the database was successfully deleted.
778 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700779 public static boolean deleteDatabase(@NonNull File file) {
Jeff Brown79087e42012-03-01 19:52:44 -0800780 if (file == null) {
781 throw new IllegalArgumentException("file must not be null");
782 }
783
784 boolean deleted = false;
785 deleted |= file.delete();
786 deleted |= new File(file.getPath() + "-journal").delete();
787 deleted |= new File(file.getPath() + "-shm").delete();
788 deleted |= new File(file.getPath() + "-wal").delete();
789
790 File dir = file.getParentFile();
791 if (dir != null) {
792 final String prefix = file.getName() + "-mj";
Jeff Brownfce58902014-01-24 13:20:57 -0800793 File[] files = dir.listFiles(new FileFilter() {
Jeff Brown79087e42012-03-01 19:52:44 -0800794 @Override
795 public boolean accept(File candidate) {
796 return candidate.getName().startsWith(prefix);
797 }
Jeff Brownfce58902014-01-24 13:20:57 -0800798 });
799 if (files != null) {
800 for (File masterJournal : files) {
801 deleted |= masterJournal.delete();
802 }
Jeff Brown79087e42012-03-01 19:52:44 -0800803 }
804 }
805 return deleted;
806 }
807
808 /**
Jeff Brown559d0642012-02-29 10:19:12 -0800809 * Reopens the database in read-write mode.
810 * If the database is already read-write, does nothing.
811 *
812 * @throws SQLiteException if the database could not be reopened as requested, in which
813 * case it remains open in read only mode.
814 * @throws IllegalStateException if the database is not open.
815 *
816 * @see #isReadOnly()
817 * @hide
818 */
819 public void reopenReadWrite() {
820 synchronized (mLock) {
821 throwIfNotOpenLocked();
822
823 if (!isReadOnlyLocked()) {
824 return; // nothing to do
825 }
826
827 // Reopen the database in read-write mode.
828 final int oldOpenFlags = mConfigurationLocked.openFlags;
829 mConfigurationLocked.openFlags = (mConfigurationLocked.openFlags & ~OPEN_READ_MASK)
830 | OPEN_READWRITE;
831 try {
832 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
833 } catch (RuntimeException ex) {
834 mConfigurationLocked.openFlags = oldOpenFlags;
835 throw ex;
836 }
837 }
838 }
839
Jeff Browne5360fb2011-10-31 17:48:13 -0700840 private void open() {
841 try {
842 try {
843 openInner();
844 } catch (SQLiteDatabaseCorruptException ex) {
845 onCorruption();
846 openInner();
847 }
Jeff Browne5360fb2011-10-31 17:48:13 -0700848 } catch (SQLiteException ex) {
849 Log.e(TAG, "Failed to open database '" + getLabel() + "'.", ex);
850 close();
851 throw ex;
852 }
853 }
854
855 private void openInner() {
856 synchronized (mLock) {
857 assert mConnectionPoolLocked == null;
858 mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked);
859 mCloseGuardLocked.open("close");
860 }
861
862 synchronized (sActiveDatabases) {
863 sActiveDatabases.put(this, null);
864 }
865 }
866
Vasu Nori062fc7ce2010-03-31 16:13:05 -0700867 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868 * Create a memory backed SQLite database. Its contents will be destroyed
869 * when the database is closed.
870 *
871 * <p>Sets the locale of the database to the the system's current locale.
872 * Call {@link #setLocale} if you would like something else.</p>
873 *
874 * @param factory an optional factory class that is called to instantiate a
875 * cursor when query is called
876 * @return a SQLiteDatabase object, or null if the database can't be created
877 */
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700878 @NonNull
879 public static SQLiteDatabase create(@Nullable CursorFactory factory) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880 // This is a magic string with special meaning for SQLite.
Jeff Browne5360fb2011-10-31 17:48:13 -0700881 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
882 factory, CREATE_IF_NECESSARY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 }
884
885 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -0700886 * Create a memory backed SQLite database. Its contents will be destroyed
887 * when the database is closed.
888 *
889 * <p>Sets the locale of the database to the the system's current locale.
890 * Call {@link #setLocale} if you would like something else.</p>
891 * @param openParams configuration parameters that are used for opening SQLiteDatabase
892 * @return a SQLiteDatabase object, or null if the database can't be created
893 */
894 @NonNull
895 public static SQLiteDatabase createInMemory(@NonNull OpenParams openParams) {
896 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
897 openParams.toBuilder().addOpenFlags(CREATE_IF_NECESSARY).build());
898 }
899
900 /**
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400901 * Registers a CustomFunction callback as a function that can be called from
Jeff Browne5360fb2011-10-31 17:48:13 -0700902 * SQLite database triggers.
903 *
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400904 * @param name the name of the sqlite3 function
905 * @param numArgs the number of arguments for the function
906 * @param function callback to call when the function is executed
907 * @hide
908 */
909 public void addCustomFunction(String name, int numArgs, CustomFunction function) {
Jeff Browne5360fb2011-10-31 17:48:13 -0700910 // Create wrapper (also validates arguments).
911 SQLiteCustomFunction wrapper = new SQLiteCustomFunction(name, numArgs, function);
912
913 synchronized (mLock) {
914 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -0700915
Jeff Browne5360fb2011-10-31 17:48:13 -0700916 mConfigurationLocked.customFunctions.add(wrapper);
Jeff Browne67ca422012-03-21 17:24:05 -0700917 try {
918 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
919 } catch (RuntimeException ex) {
920 mConfigurationLocked.customFunctions.remove(wrapper);
921 throw ex;
922 }
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400923 }
924 }
925
Mike Lockwood9d9c1be2010-07-13 19:27:52 -0400926 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927 * Gets the database version.
928 *
929 * @return the database version
930 */
931 public int getVersion() {
Vasu Noriccd95442010-05-28 17:04:16 -0700932 return ((Long) DatabaseUtils.longForQuery(this, "PRAGMA user_version;", null)).intValue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 }
934
935 /**
936 * Sets the database version.
937 *
938 * @param version the new database version
939 */
940 public void setVersion(int version) {
941 execSQL("PRAGMA user_version = " + version);
942 }
943
944 /**
945 * Returns the maximum size the database may grow to.
946 *
947 * @return the new maximum database size
948 */
949 public long getMaximumSize() {
Vasu Noriccd95442010-05-28 17:04:16 -0700950 long pageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count;", null);
951 return pageCount * getPageSize();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 }
953
954 /**
955 * Sets the maximum size the database will grow to. The maximum size cannot
956 * be set below the current size.
957 *
958 * @param numBytes the maximum database size, in bytes
959 * @return the new maximum database size
960 */
961 public long setMaximumSize(long numBytes) {
Vasu Noriccd95442010-05-28 17:04:16 -0700962 long pageSize = getPageSize();
963 long numPages = numBytes / pageSize;
964 // If numBytes isn't a multiple of pageSize, bump up a page
965 if ((numBytes % pageSize) != 0) {
966 numPages++;
Vasu Norif3cf8a42010-03-23 11:41:44 -0700967 }
Vasu Noriccd95442010-05-28 17:04:16 -0700968 long newPageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count = " + numPages,
969 null);
970 return newPageCount * pageSize;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971 }
972
973 /**
974 * Returns the current database page size, in bytes.
975 *
976 * @return the database page size, in bytes
977 */
978 public long getPageSize() {
Vasu Noriccd95442010-05-28 17:04:16 -0700979 return DatabaseUtils.longForQuery(this, "PRAGMA page_size;", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980 }
981
982 /**
983 * Sets the database page size. The page size must be a power of two. This
984 * method does not work if any data has been written to the database file,
985 * and must be called right after the database has been created.
986 *
987 * @param numBytes the database page size, in bytes
988 */
989 public void setPageSize(long numBytes) {
990 execSQL("PRAGMA page_size = " + numBytes);
991 }
992
993 /**
994 * Mark this table as syncable. When an update occurs in this table the
995 * _sync_dirty field will be set to ensure proper syncing operation.
996 *
997 * @param table the table to mark as syncable
998 * @param deletedTable The deleted table that corresponds to the
999 * syncable table
Vasu Nori95675132010-07-21 16:24:40 -07001000 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 */
Vasu Nori95675132010-07-21 16:24:40 -07001002 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 public void markTableSyncable(String table, String deletedTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 }
1005
1006 /**
1007 * Mark this table as syncable, with the _sync_dirty residing in another
1008 * table. When an update occurs in this table the _sync_dirty field of the
1009 * row in updateTable with the _id in foreignKey will be set to
1010 * ensure proper syncing operation.
1011 *
1012 * @param table an update on this table will trigger a sync time removal
1013 * @param foreignKey this is the column in table whose value is an _id in
1014 * updateTable
1015 * @param updateTable this is the table that will have its _sync_dirty
Vasu Nori95675132010-07-21 16:24:40 -07001016 * @deprecated This method no longer serves any useful purpose and has been deprecated.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 */
Vasu Nori95675132010-07-21 16:24:40 -07001018 @Deprecated
1019 public void markTableSyncable(String table, String foreignKey, String updateTable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 }
1021
1022 /**
1023 * Finds the name of the first table, which is editable.
1024 *
1025 * @param tables a list of tables
1026 * @return the first table listed
1027 */
1028 public static String findEditTable(String tables) {
1029 if (!TextUtils.isEmpty(tables)) {
1030 // find the first word terminated by either a space or a comma
1031 int spacepos = tables.indexOf(' ');
1032 int commapos = tables.indexOf(',');
1033
1034 if (spacepos > 0 && (spacepos < commapos || commapos < 0)) {
1035 return tables.substring(0, spacepos);
1036 } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) {
1037 return tables.substring(0, commapos);
1038 }
1039 return tables;
1040 } else {
1041 throw new IllegalStateException("Invalid tables");
1042 }
1043 }
1044
1045 /**
1046 * Compiles an SQL statement into a reusable pre-compiled statement object.
1047 * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the
1048 * statement and fill in those values with {@link SQLiteProgram#bindString}
1049 * and {@link SQLiteProgram#bindLong} each time you want to run the
1050 * statement. Statements may not return result sets larger than 1x1.
Vasu Nori2827d6d2010-07-04 00:26:18 -07001051 *<p>
1052 * No two threads should be using the same {@link SQLiteStatement} at the same time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053 *
1054 * @param sql The raw SQL statement, may contain ? for unknown values to be
1055 * bound later.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001056 * @return A pre-compiled {@link SQLiteStatement} object. Note that
1057 * {@link SQLiteStatement}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 */
1059 public SQLiteStatement compileStatement(String sql) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001060 acquireReference();
1061 try {
1062 return new SQLiteStatement(this, sql, null);
1063 } finally {
1064 releaseReference();
1065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 }
1067
1068 /**
1069 * Query the given URL, returning a {@link Cursor} over the result set.
1070 *
1071 * @param distinct true if you want each row to be unique, false otherwise.
1072 * @param table The table name to compile the query against.
1073 * @param columns A list of which columns to return. Passing null will
1074 * return all columns, which is discouraged to prevent reading
1075 * data from storage that isn't going to be used.
1076 * @param selection A filter declaring which rows to return, formatted as an
1077 * SQL WHERE clause (excluding the WHERE itself). Passing null
1078 * will return all rows for the given table.
1079 * @param selectionArgs You may include ?s in selection, which will be
1080 * replaced by the values from selectionArgs, in order that they
1081 * appear in the selection. The values will be bound as Strings.
1082 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1083 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1084 * will cause the rows to not be grouped.
1085 * @param having A filter declare which row groups to include in the cursor,
1086 * if row grouping is being used, formatted as an SQL HAVING
1087 * clause (excluding the HAVING itself). Passing null will cause
1088 * all row groups to be included, and is required when row
1089 * grouping is not being used.
1090 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1091 * (excluding the ORDER BY itself). Passing null will use the
1092 * default sort order, which may be unordered.
1093 * @param limit Limits the number of rows returned by the query,
1094 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001095 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1096 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 * @see Cursor
1098 */
1099 public Cursor query(boolean distinct, String table, String[] columns,
1100 String selection, String[] selectionArgs, String groupBy,
1101 String having, String orderBy, String limit) {
1102 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown75ea64f2012-01-25 19:37:13 -08001103 groupBy, having, orderBy, limit, null);
1104 }
1105
1106 /**
1107 * Query the given URL, returning a {@link Cursor} over the result set.
1108 *
1109 * @param distinct true if you want each row to be unique, false otherwise.
1110 * @param table The table name to compile the query against.
1111 * @param columns A list of which columns to return. Passing null will
1112 * return all columns, which is discouraged to prevent reading
1113 * data from storage that isn't going to be used.
1114 * @param selection A filter declaring which rows to return, formatted as an
1115 * SQL WHERE clause (excluding the WHERE itself). Passing null
1116 * will return all rows for the given table.
1117 * @param selectionArgs You may include ?s in selection, which will be
1118 * replaced by the values from selectionArgs, in order that they
1119 * appear in the selection. The values will be bound as Strings.
1120 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1121 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1122 * will cause the rows to not be grouped.
1123 * @param having A filter declare which row groups to include in the cursor,
1124 * if row grouping is being used, formatted as an SQL HAVING
1125 * clause (excluding the HAVING itself). Passing null will cause
1126 * all row groups to be included, and is required when row
1127 * grouping is not being used.
1128 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1129 * (excluding the ORDER BY itself). Passing null will use the
1130 * default sort order, which may be unordered.
1131 * @param limit Limits the number of rows returned by the query,
1132 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001133 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001134 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1135 * when the query is executed.
1136 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1137 * {@link Cursor}s are not synchronized, see the documentation for more details.
1138 * @see Cursor
1139 */
1140 public Cursor query(boolean distinct, String table, String[] columns,
1141 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001142 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001143 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001144 groupBy, having, orderBy, limit, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 }
1146
1147 /**
1148 * Query the given URL, returning a {@link Cursor} over the result set.
1149 *
1150 * @param cursorFactory the cursor factory to use, or null for the default factory
1151 * @param distinct true if you want each row to be unique, false otherwise.
1152 * @param table The table name to compile the query against.
1153 * @param columns A list of which columns to return. Passing null will
1154 * return all columns, which is discouraged to prevent reading
1155 * data from storage that isn't going to be used.
1156 * @param selection A filter declaring which rows to return, formatted as an
1157 * SQL WHERE clause (excluding the WHERE itself). Passing null
1158 * will return all rows for the given table.
1159 * @param selectionArgs You may include ?s in selection, which will be
1160 * replaced by the values from selectionArgs, in order that they
1161 * appear in the selection. The values will be bound as Strings.
1162 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1163 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1164 * will cause the rows to not be grouped.
1165 * @param having A filter declare which row groups to include in the cursor,
1166 * if row grouping is being used, formatted as an SQL HAVING
1167 * clause (excluding the HAVING itself). Passing null will cause
1168 * all row groups to be included, and is required when row
1169 * grouping is not being used.
1170 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1171 * (excluding the ORDER BY itself). Passing null will use the
1172 * default sort order, which may be unordered.
1173 * @param limit Limits the number of rows returned by the query,
1174 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001175 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1176 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 * @see Cursor
1178 */
1179 public Cursor queryWithFactory(CursorFactory cursorFactory,
1180 boolean distinct, String table, String[] columns,
1181 String selection, String[] selectionArgs, String groupBy,
1182 String having, String orderBy, String limit) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001183 return queryWithFactory(cursorFactory, distinct, table, columns, selection,
1184 selectionArgs, groupBy, having, orderBy, limit, null);
1185 }
1186
1187 /**
1188 * Query the given URL, returning a {@link Cursor} over the result set.
1189 *
1190 * @param cursorFactory the cursor factory to use, or null for the default factory
1191 * @param distinct true if you want each row to be unique, false otherwise.
1192 * @param table The table name to compile the query against.
1193 * @param columns A list of which columns to return. Passing null will
1194 * return all columns, which is discouraged to prevent reading
1195 * data from storage that isn't going to be used.
1196 * @param selection A filter declaring which rows to return, formatted as an
1197 * SQL WHERE clause (excluding the WHERE itself). Passing null
1198 * will return all rows for the given table.
1199 * @param selectionArgs You may include ?s in selection, which will be
1200 * replaced by the values from selectionArgs, in order that they
1201 * appear in the selection. The values will be bound as Strings.
1202 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1203 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1204 * will cause the rows to not be grouped.
1205 * @param having A filter declare which row groups to include in the cursor,
1206 * if row grouping is being used, formatted as an SQL HAVING
1207 * clause (excluding the HAVING itself). Passing null will cause
1208 * all row groups to be included, and is required when row
1209 * grouping is not being used.
1210 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1211 * (excluding the ORDER BY itself). Passing null will use the
1212 * default sort order, which may be unordered.
1213 * @param limit Limits the number of rows returned by the query,
1214 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001215 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001216 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1217 * when the query is executed.
1218 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1219 * {@link Cursor}s are not synchronized, see the documentation for more details.
1220 * @see Cursor
1221 */
1222 public Cursor queryWithFactory(CursorFactory cursorFactory,
1223 boolean distinct, String table, String[] columns,
1224 String selection, String[] selectionArgs, String groupBy,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001225 String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001226 acquireReference();
1227 try {
1228 String sql = SQLiteQueryBuilder.buildQueryString(
1229 distinct, table, columns, selection, groupBy, having, orderBy, limit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001230
Jeff Brown03bd3022012-03-06 13:48:56 -08001231 return rawQueryWithFactory(cursorFactory, sql, selectionArgs,
1232 findEditTable(table), cancellationSignal);
1233 } finally {
1234 releaseReference();
1235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 }
1237
1238 /**
1239 * Query the given table, returning a {@link Cursor} over the result set.
1240 *
1241 * @param table The table name to compile the query against.
1242 * @param columns A list of which columns to return. Passing null will
1243 * return all columns, which is discouraged to prevent reading
1244 * data from storage that isn't going to be used.
1245 * @param selection A filter declaring which rows to return, formatted as an
1246 * SQL WHERE clause (excluding the WHERE itself). Passing null
1247 * will return all rows for the given table.
1248 * @param selectionArgs You may include ?s in selection, which will be
1249 * replaced by the values from selectionArgs, in order that they
1250 * appear in the selection. The values will be bound as Strings.
1251 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1252 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1253 * will cause the rows to not be grouped.
1254 * @param having A filter declare which row groups to include in the cursor,
1255 * if row grouping is being used, formatted as an SQL HAVING
1256 * clause (excluding the HAVING itself). Passing null will cause
1257 * all row groups to be included, and is required when row
1258 * grouping is not being used.
1259 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1260 * (excluding the ORDER BY itself). Passing null will use the
1261 * default sort order, which may be unordered.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001262 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1263 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264 * @see Cursor
1265 */
1266 public Cursor query(String table, String[] columns, String selection,
1267 String[] selectionArgs, String groupBy, String having,
1268 String orderBy) {
1269
1270 return query(false, table, columns, selection, selectionArgs, groupBy,
1271 having, orderBy, null /* limit */);
1272 }
1273
1274 /**
1275 * Query the given table, returning a {@link Cursor} over the result set.
1276 *
1277 * @param table The table name to compile the query against.
1278 * @param columns A list of which columns to return. Passing null will
1279 * return all columns, which is discouraged to prevent reading
1280 * data from storage that isn't going to be used.
1281 * @param selection A filter declaring which rows to return, formatted as an
1282 * SQL WHERE clause (excluding the WHERE itself). Passing null
1283 * will return all rows for the given table.
1284 * @param selectionArgs You may include ?s in selection, which will be
1285 * replaced by the values from selectionArgs, in order that they
1286 * appear in the selection. The values will be bound as Strings.
1287 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1288 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1289 * will cause the rows to not be grouped.
1290 * @param having A filter declare which row groups to include in the cursor,
1291 * if row grouping is being used, formatted as an SQL HAVING
1292 * clause (excluding the HAVING itself). Passing null will cause
1293 * all row groups to be included, and is required when row
1294 * grouping is not being used.
1295 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1296 * (excluding the ORDER BY itself). Passing null will use the
1297 * default sort order, which may be unordered.
1298 * @param limit Limits the number of rows returned by the query,
1299 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001300 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1301 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001302 * @see Cursor
1303 */
1304 public Cursor query(String table, String[] columns, String selection,
1305 String[] selectionArgs, String groupBy, String having,
1306 String orderBy, String limit) {
1307
1308 return query(false, table, columns, selection, selectionArgs, groupBy,
1309 having, orderBy, limit);
1310 }
1311
1312 /**
1313 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1314 *
1315 * @param sql the SQL query. The SQL string must not be ; terminated
1316 * @param selectionArgs You may include ?s in where clause in the query,
1317 * which will be replaced by the values from selectionArgs. The
1318 * values will be bound as Strings.
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001319 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1320 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001321 */
1322 public Cursor rawQuery(String sql, String[] selectionArgs) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001323 return rawQueryWithFactory(null, sql, selectionArgs, null, null);
1324 }
1325
1326 /**
1327 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1328 *
1329 * @param sql the SQL query. The SQL string must not be ; terminated
1330 * @param selectionArgs You may include ?s in where clause in the query,
1331 * which will be replaced by the values from selectionArgs. The
1332 * values will be bound as Strings.
Jeff Brown4c1241d2012-02-02 17:05:00 -08001333 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001334 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1335 * when the query is executed.
1336 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1337 * {@link Cursor}s are not synchronized, see the documentation for more details.
1338 */
1339 public Cursor rawQuery(String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001340 CancellationSignal cancellationSignal) {
1341 return rawQueryWithFactory(null, sql, selectionArgs, null, cancellationSignal);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 }
1343
1344 /**
1345 * Runs the provided SQL and returns a cursor over the result set.
1346 *
1347 * @param cursorFactory the cursor factory to use, or null for the default factory
1348 * @param sql the SQL query. The SQL string must not be ; terminated
1349 * @param selectionArgs You may include ?s in where clause in the query,
1350 * which will be replaced by the values from selectionArgs. The
1351 * values will be bound as Strings.
1352 * @param editTable the name of the first table, which is editable
Jeff Hamiltonf3ca9a52010-05-12 15:04:33 -07001353 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1354 * {@link Cursor}s are not synchronized, see the documentation for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001355 */
1356 public Cursor rawQueryWithFactory(
1357 CursorFactory cursorFactory, String sql, String[] selectionArgs,
1358 String editTable) {
Jeff Brown75ea64f2012-01-25 19:37:13 -08001359 return rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable, null);
1360 }
1361
1362 /**
1363 * Runs the provided SQL and returns a cursor over the result set.
1364 *
1365 * @param cursorFactory the cursor factory to use, or null for the default factory
1366 * @param sql the SQL query. The SQL string must not be ; terminated
1367 * @param selectionArgs You may include ?s in where clause in the query,
1368 * which will be replaced by the values from selectionArgs. The
1369 * values will be bound as Strings.
1370 * @param editTable the name of the first table, which is editable
Jeff Brown4c1241d2012-02-02 17:05:00 -08001371 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -08001372 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1373 * when the query is executed.
1374 * @return A {@link Cursor} object, which is positioned before the first entry. Note that
1375 * {@link Cursor}s are not synchronized, see the documentation for more details.
1376 */
1377 public Cursor rawQueryWithFactory(
1378 CursorFactory cursorFactory, String sql, String[] selectionArgs,
Jeff Brown4c1241d2012-02-02 17:05:00 -08001379 String editTable, CancellationSignal cancellationSignal) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001380 acquireReference();
1381 try {
1382 SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
1383 cancellationSignal);
1384 return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
1385 selectionArgs);
1386 } finally {
1387 releaseReference();
1388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 }
1390
1391 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 * Convenience method for inserting a row into the database.
1393 *
1394 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001395 * @param nullColumnHack optional; may be <code>null</code>.
1396 * SQL doesn't allow inserting a completely empty row without
1397 * naming at least one column name. If your provided <code>values</code> is
1398 * empty, no column names are known and an empty row can't be inserted.
1399 * If not set to null, the <code>nullColumnHack</code> parameter
1400 * provides the name of nullable column name to explicitly insert a NULL into
1401 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 * @param values this map contains the initial column values for the
1403 * row. The keys should be the column names and the values the
1404 * column values
1405 * @return the row ID of the newly inserted row, or -1 if an error occurred
1406 */
1407 public long insert(String table, String nullColumnHack, ContentValues values) {
1408 try {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001409 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001410 } catch (SQLException e) {
1411 Log.e(TAG, "Error inserting " + values, e);
1412 return -1;
1413 }
1414 }
1415
1416 /**
1417 * Convenience method for inserting a row into the database.
1418 *
1419 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001420 * @param nullColumnHack optional; may be <code>null</code>.
1421 * SQL doesn't allow inserting a completely empty row without
1422 * naming at least one column name. If your provided <code>values</code> is
1423 * empty, no column names are known and an empty row can't be inserted.
1424 * If not set to null, the <code>nullColumnHack</code> parameter
1425 * provides the name of nullable column name to explicitly insert a NULL into
1426 * in the case where your <code>values</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 * @param values this map contains the initial column values for the
1428 * row. The keys should be the column names and the values the
1429 * column values
1430 * @throws SQLException
1431 * @return the row ID of the newly inserted row, or -1 if an error occurred
1432 */
1433 public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
1434 throws SQLException {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001435 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001436 }
1437
1438 /**
1439 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001440 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 *
1442 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001443 * @param nullColumnHack optional; may be <code>null</code>.
1444 * SQL doesn't allow inserting a completely empty row without
1445 * naming at least one column name. If your provided <code>initialValues</code> is
1446 * empty, no column names are known and an empty row can't be inserted.
1447 * If not set to null, the <code>nullColumnHack</code> parameter
1448 * provides the name of nullable column name to explicitly insert a NULL into
1449 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001450 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001451 * 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 -08001452 * @return the row ID of the newly inserted row, or -1 if an error occurred
1453 */
1454 public long replace(String table, String nullColumnHack, ContentValues initialValues) {
1455 try {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001456 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001457 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 } catch (SQLException e) {
1459 Log.e(TAG, "Error inserting " + initialValues, e);
1460 return -1;
1461 }
1462 }
1463
1464 /**
1465 * Convenience method for replacing a row in the database.
Mark Lu1e202082016-08-30 17:41:25 -07001466 * Inserts a new row if a row does not already exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 *
1468 * @param table the table in which to replace the row
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001469 * @param nullColumnHack optional; may be <code>null</code>.
1470 * SQL doesn't allow inserting a completely empty row without
1471 * naming at least one column name. If your provided <code>initialValues</code> is
1472 * empty, no column names are known and an empty row can't be inserted.
1473 * If not set to null, the <code>nullColumnHack</code> parameter
1474 * provides the name of nullable column name to explicitly insert a NULL into
1475 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 * @param initialValues this map contains the initial column values for
Mark Lu1e202082016-08-30 17:41:25 -07001477 * 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 -08001478 * @throws SQLException
1479 * @return the row ID of the newly inserted row, or -1 if an error occurred
1480 */
1481 public long replaceOrThrow(String table, String nullColumnHack,
1482 ContentValues initialValues) throws SQLException {
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001483 return insertWithOnConflict(table, nullColumnHack, initialValues,
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001484 CONFLICT_REPLACE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 }
1486
1487 /**
1488 * General method for inserting a row into the database.
1489 *
1490 * @param table the table to insert the row into
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001491 * @param nullColumnHack optional; may be <code>null</code>.
1492 * SQL doesn't allow inserting a completely empty row without
1493 * naming at least one column name. If your provided <code>initialValues</code> is
1494 * empty, no column names are known and an empty row can't be inserted.
1495 * If not set to null, the <code>nullColumnHack</code> parameter
1496 * provides the name of nullable column name to explicitly insert a NULL into
1497 * in the case where your <code>initialValues</code> is empty.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001498 * @param initialValues this map contains the initial column values for the
1499 * row. The keys should be the column names and the values the
1500 * column values
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001501 * @param conflictAlgorithm for insert conflict resolver
Steve Pomeroyc240b602013-03-14 00:42:10 -04001502 * @return the row ID of the newly inserted row OR <code>-1</code> if either the
1503 * input parameter <code>conflictAlgorithm</code> = {@link #CONFLICT_IGNORE}
1504 * or an error occurred.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 */
1506 public long insertWithOnConflict(String table, String nullColumnHack,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001507 ContentValues initialValues, int conflictAlgorithm) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001508 acquireReference();
1509 try {
1510 StringBuilder sql = new StringBuilder();
1511 sql.append("INSERT");
1512 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1513 sql.append(" INTO ");
1514 sql.append(table);
1515 sql.append('(');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516
Jeff Brown03bd3022012-03-06 13:48:56 -08001517 Object[] bindArgs = null;
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001518 int size = (initialValues != null && !initialValues.isEmpty())
Jeff Brown03bd3022012-03-06 13:48:56 -08001519 ? initialValues.size() : 0;
1520 if (size > 0) {
1521 bindArgs = new Object[size];
1522 int i = 0;
1523 for (String colName : initialValues.keySet()) {
1524 sql.append((i > 0) ? "," : "");
1525 sql.append(colName);
1526 bindArgs[i++] = initialValues.get(colName);
1527 }
1528 sql.append(')');
1529 sql.append(" VALUES (");
1530 for (i = 0; i < size; i++) {
1531 sql.append((i > 0) ? ",?" : "?");
1532 }
1533 } else {
1534 sql.append(nullColumnHack + ") VALUES (NULL");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 sql.append(')');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537
Jeff Brown03bd3022012-03-06 13:48:56 -08001538 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1539 try {
1540 return statement.executeInsert();
1541 } finally {
1542 statement.close();
1543 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001544 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001545 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 }
1547 }
1548
1549 /**
1550 * Convenience method for deleting rows in the database.
1551 *
1552 * @param table the table to delete from
1553 * @param whereClause the optional WHERE clause to apply when deleting.
1554 * Passing null will delete all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001555 * @param whereArgs You may include ?s in the where clause, which
1556 * will be replaced by the values from whereArgs. The values
1557 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 * @return the number of rows affected if a whereClause is passed in, 0
1559 * otherwise. To remove all rows and get a count pass "1" as the
1560 * whereClause.
1561 */
1562 public int delete(String table, String whereClause, String[] whereArgs) {
Jeff Brown03bd3022012-03-06 13:48:56 -08001563 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001564 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001565 SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table +
1566 (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
1567 try {
1568 return statement.executeUpdateDelete();
1569 } finally {
1570 statement.close();
1571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001573 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 }
1575 }
1576
1577 /**
1578 * Convenience method for updating rows in the database.
1579 *
1580 * @param table the table to update in
1581 * @param values a map from column names to new column values. null is a
1582 * valid value that will be translated to NULL.
1583 * @param whereClause the optional WHERE clause to apply when updating.
1584 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001585 * @param whereArgs You may include ?s in the where clause, which
1586 * will be replaced by the values from whereArgs. The values
1587 * will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588 * @return the number of rows affected
1589 */
1590 public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001591 return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 }
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 /**
1595 * Convenience method for updating rows in the database.
1596 *
1597 * @param table the table to update in
1598 * @param values a map from column names to new column values. null is a
1599 * valid value that will be translated to NULL.
1600 * @param whereClause the optional WHERE clause to apply when updating.
1601 * Passing null will update all rows.
Tim Roesfd020742013-01-22 23:12:11 +01001602 * @param whereArgs You may include ?s in the where clause, which
1603 * will be replaced by the values from whereArgs. The values
1604 * will be bound as Strings.
Vasu Nori8d45e4e2010-02-05 22:35:47 -08001605 * @param conflictAlgorithm for update conflict resolver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 * @return the number of rows affected
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 */
Dmitri Plotnikov600bdd82009-09-01 12:12:20 -07001608 public int updateWithOnConflict(String table, ContentValues values,
Vasu Nori6eb7c452010-01-27 14:31:24 -08001609 String whereClause, String[] whereArgs, int conflictAlgorithm) {
Mike Tsaoc74ee2f2017-03-24 14:56:34 -07001610 if (values == null || values.isEmpty()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 throw new IllegalArgumentException("Empty values");
1612 }
1613
Jeff Brown03bd3022012-03-06 13:48:56 -08001614 acquireReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08001616 StringBuilder sql = new StringBuilder(120);
1617 sql.append("UPDATE ");
1618 sql.append(CONFLICT_VALUES[conflictAlgorithm]);
1619 sql.append(table);
1620 sql.append(" SET ");
1621
1622 // move all bind args to one array
1623 int setValuesSize = values.size();
1624 int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
1625 Object[] bindArgs = new Object[bindArgsSize];
1626 int i = 0;
1627 for (String colName : values.keySet()) {
1628 sql.append((i > 0) ? "," : "");
1629 sql.append(colName);
1630 bindArgs[i++] = values.get(colName);
1631 sql.append("=?");
1632 }
1633 if (whereArgs != null) {
1634 for (i = setValuesSize; i < bindArgsSize; i++) {
1635 bindArgs[i] = whereArgs[i - setValuesSize];
1636 }
1637 }
1638 if (!TextUtils.isEmpty(whereClause)) {
1639 sql.append(" WHERE ");
1640 sql.append(whereClause);
1641 }
1642
1643 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
1644 try {
1645 return statement.executeUpdateDelete();
1646 } finally {
1647 statement.close();
1648 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001650 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 }
1652 }
1653
1654 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001655 * Execute a single SQL statement that is NOT a SELECT
1656 * or any other SQL statement that returns data.
1657 * <p>
Vasu Norice38b982010-07-22 13:57:13 -07001658 * It has no means to return any data (such as the number of affected rows).
Vasu Noriccd95442010-05-28 17:04:16 -07001659 * Instead, you're encouraged to use {@link #insert(String, String, ContentValues)},
1660 * {@link #update(String, ContentValues, String, String[])}, et al, when possible.
1661 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001662 * <p>
1663 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1664 * automatically managed by this class. So, do not set journal_mode
1665 * using "PRAGMA journal_mode'<value>" statement if your app is using
1666 * {@link #enableWriteAheadLogging()}
1667 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 *
Vasu Noriccd95442010-05-28 17:04:16 -07001669 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1670 * not supported.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001671 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001673 public void execSQL(String sql) throws SQLException {
Vasu Nori16057fa2011-03-18 11:40:37 -07001674 executeSql(sql, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 }
1676
1677 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001678 * Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE.
1679 * <p>
1680 * For INSERT statements, use any of the following instead.
1681 * <ul>
1682 * <li>{@link #insert(String, String, ContentValues)}</li>
1683 * <li>{@link #insertOrThrow(String, String, ContentValues)}</li>
1684 * <li>{@link #insertWithOnConflict(String, String, ContentValues, int)}</li>
1685 * </ul>
1686 * <p>
1687 * For UPDATE statements, use any of the following instead.
1688 * <ul>
1689 * <li>{@link #update(String, ContentValues, String, String[])}</li>
1690 * <li>{@link #updateWithOnConflict(String, ContentValues, String, String[], int)}</li>
1691 * </ul>
1692 * <p>
1693 * For DELETE statements, use any of the following instead.
1694 * <ul>
1695 * <li>{@link #delete(String, String, String[])}</li>
1696 * </ul>
1697 * <p>
1698 * For example, the following are good candidates for using this method:
1699 * <ul>
1700 * <li>ALTER TABLE</li>
1701 * <li>CREATE or DROP table / trigger / view / index / virtual table</li>
1702 * <li>REINDEX</li>
1703 * <li>RELEASE</li>
1704 * <li>SAVEPOINT</li>
1705 * <li>PRAGMA that returns no data</li>
1706 * </ul>
1707 * </p>
Vasu Nori9bf225e2010-07-07 16:38:28 -07001708 * <p>
1709 * When using {@link #enableWriteAheadLogging()}, journal_mode is
1710 * automatically managed by this class. So, do not set journal_mode
1711 * using "PRAGMA journal_mode'<value>" statement if your app is using
1712 * {@link #enableWriteAheadLogging()}
1713 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714 *
Vasu Noriccd95442010-05-28 17:04:16 -07001715 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
1716 * not supported.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717 * @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -08001718 * @throws SQLException if the SQL string is invalid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001719 */
Vasu Norib83cb7c2010-09-14 13:36:01 -07001720 public void execSQL(String sql, Object[] bindArgs) throws SQLException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001721 if (bindArgs == null) {
1722 throw new IllegalArgumentException("Empty bindArgs");
1723 }
Vasu Norib83cb7c2010-09-14 13:36:01 -07001724 executeSql(sql, bindArgs);
Vasu Norice38b982010-07-22 13:57:13 -07001725 }
1726
Vasu Nori54025902010-09-14 12:14:26 -07001727 private int executeSql(String sql, Object[] bindArgs) throws SQLException {
Jeff Brown03bd3022012-03-06 13:48:56 -08001728 acquireReference();
1729 try {
1730 if (DatabaseUtils.getSqlStatementType(sql) == DatabaseUtils.STATEMENT_ATTACH) {
1731 boolean disableWal = false;
1732 synchronized (mLock) {
1733 if (!mHasAttachedDbsLocked) {
1734 mHasAttachedDbsLocked = true;
1735 disableWal = true;
Fyodor Kupolovfd9c4a52017-07-13 15:36:57 -07001736 mConnectionPoolLocked.disableIdleConnectionHandler();
Jeff Brown03bd3022012-03-06 13:48:56 -08001737 }
1738 }
1739 if (disableWal) {
1740 disableWriteAheadLogging();
Jeff Browne5360fb2011-10-31 17:48:13 -07001741 }
1742 }
Jeff Browne5360fb2011-10-31 17:48:13 -07001743
Jeff Brown03bd3022012-03-06 13:48:56 -08001744 SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs);
1745 try {
1746 return statement.executeUpdateDelete();
1747 } finally {
1748 statement.close();
1749 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001750 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08001751 releaseReference();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001752 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 }
1754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 /**
Makoto Onuki17aa1b72015-12-16 14:02:01 -08001756 * Verifies that a SQL SELECT statement is valid by compiling it.
1757 * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
1758 *
1759 * @param sql SQL to be validated
1760 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
1761 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1762 * when the query is executed.
1763 * @throws SQLiteException if {@code sql} is invalid
1764 */
1765 public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal) {
1766 getThreadSession().prepare(sql,
1767 getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null);
1768 }
1769
1770 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001771 * Returns true if the database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001773 * @return True if database is opened as read only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 */
1775 public boolean isReadOnly() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001776 synchronized (mLock) {
1777 return isReadOnlyLocked();
1778 }
1779 }
1780
1781 private boolean isReadOnlyLocked() {
1782 return (mConfigurationLocked.openFlags & OPEN_READ_MASK) == OPEN_READONLY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001783 }
1784
1785 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001786 * Returns true if the database is in-memory db.
1787 *
1788 * @return True if the database is in-memory.
1789 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001790 */
Jeff Browne5360fb2011-10-31 17:48:13 -07001791 public boolean isInMemoryDatabase() {
1792 synchronized (mLock) {
1793 return mConfigurationLocked.isInMemoryDb();
1794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001795 }
1796
Jeff Browne5360fb2011-10-31 17:48:13 -07001797 /**
1798 * Returns true if the database is currently open.
1799 *
1800 * @return True if the database is currently open (has not been closed).
1801 */
1802 public boolean isOpen() {
1803 synchronized (mLock) {
1804 return mConnectionPoolLocked != null;
1805 }
1806 }
1807
1808 /**
1809 * Returns true if the new version code is greater than the current database version.
1810 *
1811 * @param newVersion The new version code.
Mark Lu1e202082016-08-30 17:41:25 -07001812 * @return True if the new version code is greater than the current database version.
Jeff Browne5360fb2011-10-31 17:48:13 -07001813 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 public boolean needUpgrade(int newVersion) {
1815 return newVersion > getVersion();
1816 }
1817
1818 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07001819 * Gets the path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 *
Jeff Browne5360fb2011-10-31 17:48:13 -07001821 * @return The path to the database file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001822 */
1823 public final String getPath() {
Jeff Browne5360fb2011-10-31 17:48:13 -07001824 synchronized (mLock) {
1825 return mConfigurationLocked.path;
Christopher Tatead9e8b12011-10-05 17:49:26 -07001826 }
Brad Fitzpatrick722802e2010-03-23 22:22:16 -07001827 }
1828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 /**
1830 * Sets the locale for this database. Does nothing if this database has
Jeff Brown1d9f7422012-03-15 14:32:32 -07001831 * the {@link #NO_LOCALIZED_COLLATORS} flag set or was opened read only.
Jeff Browne5360fb2011-10-31 17:48:13 -07001832 *
1833 * @param locale The new locale.
1834 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 * @throws SQLException if the locale could not be set. The most common reason
1836 * for this is that there is no collator available for the locale you requested.
1837 * In this case the database remains unchanged.
1838 */
1839 public void setLocale(Locale locale) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001840 if (locale == null) {
1841 throw new IllegalArgumentException("locale must not be null.");
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001842 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001843
Jeff Browne5360fb2011-10-31 17:48:13 -07001844 synchronized (mLock) {
1845 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001846
1847 final Locale oldLocale = mConfigurationLocked.locale;
Jeff Browne5360fb2011-10-31 17:48:13 -07001848 mConfigurationLocked.locale = locale;
Jeff Browne67ca422012-03-21 17:24:05 -07001849 try {
1850 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1851 } catch (RuntimeException ex) {
1852 mConfigurationLocked.locale = oldLocale;
1853 throw ex;
1854 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001855 }
Vasu Norib729dcc2010-09-14 11:35:49 -07001856 }
1857
Vasu Norie495d1f2010-01-06 16:34:19 -08001858 /**
Vasu Noriccd95442010-05-28 17:04:16 -07001859 * Sets the maximum size of the prepared-statement cache for this database.
Vasu Norie495d1f2010-01-06 16:34:19 -08001860 * (size of the cache = number of compiled-sql-statements stored in the cache).
Vasu Noriccd95442010-05-28 17:04:16 -07001861 *<p>
Vasu Norib729dcc2010-09-14 11:35:49 -07001862 * Maximum cache size can ONLY be increased from its current size (default = 10).
Vasu Noriccd95442010-05-28 17:04:16 -07001863 * If this method is called with smaller size than the current maximum value,
1864 * then IllegalStateException is thrown.
Vasu Norib729dcc2010-09-14 11:35:49 -07001865 *<p>
1866 * This method is thread-safe.
Vasu Norie495d1f2010-01-06 16:34:19 -08001867 *
Vasu Nori90a367262010-04-12 12:49:09 -07001868 * @param cacheSize the size of the cache. can be (0 to {@link #MAX_SQL_CACHE_SIZE})
Jeff Browne5360fb2011-10-31 17:48:13 -07001869 * @throws IllegalStateException if input cacheSize > {@link #MAX_SQL_CACHE_SIZE}.
Vasu Norie495d1f2010-01-06 16:34:19 -08001870 */
Vasu Nori54025902010-09-14 12:14:26 -07001871 public void setMaxSqlCacheSize(int cacheSize) {
Jeff Browne5360fb2011-10-31 17:48:13 -07001872 if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) {
1873 throw new IllegalStateException(
1874 "expected value between 0 and " + MAX_SQL_CACHE_SIZE);
Vasu Nori587423a2010-09-27 18:18:34 -07001875 }
Vasu Nori587423a2010-09-27 18:18:34 -07001876
Jeff Browne5360fb2011-10-31 17:48:13 -07001877 synchronized (mLock) {
1878 throwIfNotOpenLocked();
Jeff Browne67ca422012-03-21 17:24:05 -07001879
1880 final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize;
Jeff Browne5360fb2011-10-31 17:48:13 -07001881 mConfigurationLocked.maxSqlCacheSize = cacheSize;
Jeff Browne67ca422012-03-21 17:24:05 -07001882 try {
1883 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1884 } catch (RuntimeException ex) {
1885 mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize;
1886 throw ex;
1887 }
Jesse Wilsondfe515e2011-02-10 19:06:09 -08001888 }
1889 }
1890
Vasu Nori6c354da2010-04-26 23:33:39 -07001891 /**
Jeff Brown96496ad2012-03-23 14:38:06 -07001892 * Sets whether foreign key constraints are enabled for the database.
1893 * <p>
1894 * By default, foreign key constraints are not enforced by the database.
1895 * This method allows an application to enable foreign key constraints.
1896 * It must be called each time the database is opened to ensure that foreign
1897 * key constraints are enabled for the session.
1898 * </p><p>
1899 * A good time to call this method is right after calling {@link #openOrCreateDatabase}
1900 * or in the {@link SQLiteOpenHelper#onConfigure} callback.
1901 * </p><p>
1902 * When foreign key constraints are disabled, the database does not check whether
1903 * changes to the database will violate foreign key constraints. Likewise, when
1904 * foreign key constraints are disabled, the database will not execute cascade
1905 * delete or update triggers. As a result, it is possible for the database
1906 * state to become inconsistent. To perform a database integrity check,
1907 * call {@link #isDatabaseIntegrityOk}.
1908 * </p><p>
1909 * This method must not be called while a transaction is in progress.
1910 * </p><p>
1911 * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a>
1912 * for more details about foreign key constraint support.
1913 * </p>
1914 *
1915 * @param enable True to enable foreign key constraints, false to disable them.
1916 *
1917 * @throws IllegalStateException if the are transactions is in progress
1918 * when this method is called.
1919 */
1920 public void setForeignKeyConstraintsEnabled(boolean enable) {
1921 synchronized (mLock) {
1922 throwIfNotOpenLocked();
1923
1924 if (mConfigurationLocked.foreignKeyConstraintsEnabled == enable) {
1925 return;
1926 }
1927
1928 mConfigurationLocked.foreignKeyConstraintsEnabled = enable;
1929 try {
1930 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1931 } catch (RuntimeException ex) {
1932 mConfigurationLocked.foreignKeyConstraintsEnabled = !enable;
1933 throw ex;
1934 }
1935 }
1936 }
1937
1938 /**
Jeff Brown47847f32012-03-22 19:13:11 -07001939 * This method enables parallel execution of queries from multiple threads on the
1940 * same database. It does this by opening multiple connections to the database
1941 * and using a different database connection for each query. The database
1942 * journal mode is also changed to enable writes to proceed concurrently with reads.
Vasu Nori6c354da2010-04-26 23:33:39 -07001943 * <p>
Jeff Brown47847f32012-03-22 19:13:11 -07001944 * When write-ahead logging is not enabled (the default), it is not possible for
1945 * reads and writes to occur on the database at the same time. Before modifying the
1946 * database, the writer implicitly acquires an exclusive lock on the database which
1947 * prevents readers from accessing the database until the write is completed.
1948 * </p><p>
1949 * In contrast, when write-ahead logging is enabled (by calling this method), write
1950 * operations occur in a separate log file which allows reads to proceed concurrently.
1951 * While a write is in progress, readers on other threads will perceive the state
1952 * of the database as it was before the write began. When the write completes, readers
1953 * on other threads will then perceive the new state of the database.
1954 * </p><p>
1955 * It is a good idea to enable write-ahead logging whenever a database will be
1956 * concurrently accessed and modified by multiple threads at the same time.
1957 * However, write-ahead logging uses significantly more memory than ordinary
1958 * journaling because there are multiple connections to the same database.
1959 * So if a database will only be used by a single thread, or if optimizing
1960 * concurrency is not very important, then write-ahead logging should be disabled.
1961 * </p><p>
1962 * After calling this method, execution of queries in parallel is enabled as long as
1963 * the database remains open. To disable execution of queries in parallel, either
1964 * call {@link #disableWriteAheadLogging} or close the database and reopen it.
1965 * </p><p>
1966 * The maximum number of connections used to execute queries in parallel is
Vasu Nori6c354da2010-04-26 23:33:39 -07001967 * dependent upon the device memory and possibly other properties.
Jeff Brown47847f32012-03-22 19:13:11 -07001968 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07001969 * If a query is part of a transaction, then it is executed on the same database handle the
1970 * transaction was begun.
Jeff Brown47847f32012-03-22 19:13:11 -07001971 * </p><p>
Vasu Nori6c354da2010-04-26 23:33:39 -07001972 * Writers should use {@link #beginTransactionNonExclusive()} or
1973 * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
Jeff Brown47847f32012-03-22 19:13:11 -07001974 * to start a transaction. Non-exclusive mode allows database file to be in readable
1975 * by other threads executing queries.
1976 * </p><p>
1977 * If the database has any attached databases, then execution of queries in parallel is NOT
1978 * possible. Likewise, write-ahead logging is not supported for read-only databases
1979 * or memory databases. In such cases, {@link #enableWriteAheadLogging} returns false.
1980 * </p><p>
1981 * The best way to enable write-ahead logging is to pass the
1982 * {@link #ENABLE_WRITE_AHEAD_LOGGING} flag to {@link #openDatabase}. This is
1983 * more efficient than calling {@link #enableWriteAheadLogging}.
1984 * <code><pre>
1985 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
1986 * SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
1987 * myDatabaseErrorHandler);
1988 * db.enableWriteAheadLogging();
1989 * </pre></code>
1990 * </p><p>
1991 * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging}
1992 * after opening the database.
1993 * <code><pre>
1994 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
1995 * SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
1996 * db.enableWriteAheadLogging();
1997 * </pre></code>
1998 * </p><p>
1999 * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for
2000 * more details about how write-ahead logging works.
Vasu Nori6c354da2010-04-26 23:33:39 -07002001 * </p>
2002 *
Jeff Brown47847f32012-03-22 19:13:11 -07002003 * @return True if write-ahead logging is enabled.
Jeff Browne67ca422012-03-21 17:24:05 -07002004 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002005 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002006 * time this method is called. WAL mode can only be changed when there are no
2007 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002008 *
2009 * @see #ENABLE_WRITE_AHEAD_LOGGING
2010 * @see #disableWriteAheadLogging
Vasu Nori6c354da2010-04-26 23:33:39 -07002011 */
Vasu Noriffe06122010-09-27 12:32:57 -07002012 public boolean enableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002013 synchronized (mLock) {
2014 throwIfNotOpenLocked();
2015
Jeff Brown47847f32012-03-22 19:13:11 -07002016 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002017 return true;
2018 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002019
2020 if (isReadOnlyLocked()) {
2021 // WAL doesn't make sense for readonly-databases.
2022 // TODO: True, but connection pooling does still make sense...
2023 return false;
2024 }
2025
2026 if (mConfigurationLocked.isInMemoryDb()) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002027 Log.i(TAG, "can't enable WAL for memory databases.");
2028 return false;
2029 }
2030
2031 // make sure this database has NO attached databases because sqlite's write-ahead-logging
2032 // doesn't work for databases with attached databases
Jeff Browne5360fb2011-10-31 17:48:13 -07002033 if (mHasAttachedDbsLocked) {
Paul Westbrookdae6d372011-02-17 10:59:56 -08002034 if (Log.isLoggable(TAG, Log.DEBUG)) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002035 Log.d(TAG, "this database: " + mConfigurationLocked.label
2036 + " has attached databases. can't enable WAL.");
Paul Westbrookdae6d372011-02-17 10:59:56 -08002037 }
2038 return false;
2039 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002040
Jeff Brown47847f32012-03-22 19:13:11 -07002041 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002042 try {
2043 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2044 } catch (RuntimeException ex) {
Jeff Brown47847f32012-03-22 19:13:11 -07002045 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002046 throw ex;
2047 }
Paul Westbrookdae6d372011-02-17 10:59:56 -08002048 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002049 return true;
Vasu Nori6c354da2010-04-26 23:33:39 -07002050 }
2051
Vasu Nori2827d6d2010-07-04 00:26:18 -07002052 /**
Vasu Nori7b04c412010-07-20 10:31:21 -07002053 * This method disables the features enabled by {@link #enableWriteAheadLogging()}.
Jeff Browne67ca422012-03-21 17:24:05 -07002054 *
Jean-Baptiste Queru73644772012-03-21 19:24:32 -07002055 * @throws IllegalStateException if there are transactions in progress at the
Jeff Browne67ca422012-03-21 17:24:05 -07002056 * time this method is called. WAL mode can only be changed when there are no
2057 * transactions in progress.
Jeff Brown47847f32012-03-22 19:13:11 -07002058 *
2059 * @see #enableWriteAheadLogging
Vasu Nori2827d6d2010-07-04 00:26:18 -07002060 */
Vasu Nori7b04c412010-07-20 10:31:21 -07002061 public void disableWriteAheadLogging() {
Jeff Browne5360fb2011-10-31 17:48:13 -07002062 synchronized (mLock) {
2063 throwIfNotOpenLocked();
2064
Jeff Brown47847f32012-03-22 19:13:11 -07002065 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002066 return;
Paul Westbrookdae6d372011-02-17 10:59:56 -08002067 }
Vasu Nori8d111032010-06-22 18:34:21 -07002068
Jeff Brown47847f32012-03-22 19:13:11 -07002069 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002070 try {
2071 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
2072 } catch (RuntimeException ex) {
Jeff Brown47847f32012-03-22 19:13:11 -07002073 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
Jeff Browne67ca422012-03-21 17:24:05 -07002074 throw ex;
2075 }
Vasu Nori65a88832010-07-16 15:14:08 -07002076 }
Vasu Nori6c354da2010-04-26 23:33:39 -07002077 }
2078
Vasu Norif3cf8a42010-03-23 11:41:44 -07002079 /**
Jeff Brown47847f32012-03-22 19:13:11 -07002080 * Returns true if write-ahead logging has been enabled for this database.
2081 *
2082 * @return True if write-ahead logging has been enabled for this database.
2083 *
2084 * @see #enableWriteAheadLogging
2085 * @see #ENABLE_WRITE_AHEAD_LOGGING
2086 */
2087 public boolean isWriteAheadLoggingEnabled() {
2088 synchronized (mLock) {
2089 throwIfNotOpenLocked();
2090
2091 return (mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2092 }
2093 }
2094
2095 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002096 * Collect statistics about all open databases in the current process.
2097 * Used by bug report.
Vasu Norif3cf8a42010-03-23 11:41:44 -07002098 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002099 static ArrayList<DbStats> getDbStats() {
Vasu Noric3849202010-03-09 10:47:25 -08002100 ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002101 for (SQLiteDatabase db : getActiveDatabases()) {
2102 db.collectDbStats(dbStatsList);
Vasu Nori24675612010-09-27 14:54:19 -07002103 }
Vasu Noric3849202010-03-09 10:47:25 -08002104 return dbStatsList;
2105 }
2106
Jeff Browne5360fb2011-10-31 17:48:13 -07002107 private void collectDbStats(ArrayList<DbStats> dbStatsList) {
2108 synchronized (mLock) {
2109 if (mConnectionPoolLocked != null) {
2110 mConnectionPoolLocked.collectDbStats(dbStatsList);
2111 }
2112 }
2113 }
2114
2115 private static ArrayList<SQLiteDatabase> getActiveDatabases() {
2116 ArrayList<SQLiteDatabase> databases = new ArrayList<SQLiteDatabase>();
2117 synchronized (sActiveDatabases) {
2118 databases.addAll(sActiveDatabases.keySet());
2119 }
2120 return databases;
2121 }
2122
2123 /**
2124 * Dump detailed information about all open databases in the current process.
2125 * Used by bug report.
2126 */
Jeff Browna9be4152012-01-18 15:29:57 -08002127 static void dumpAll(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002128 for (SQLiteDatabase db : getActiveDatabases()) {
Jeff Browna9be4152012-01-18 15:29:57 -08002129 db.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002130 }
2131 }
2132
Jeff Browna9be4152012-01-18 15:29:57 -08002133 private void dump(Printer printer, boolean verbose) {
Jeff Browne5360fb2011-10-31 17:48:13 -07002134 synchronized (mLock) {
2135 if (mConnectionPoolLocked != null) {
2136 printer.println("");
Jeff Browna9be4152012-01-18 15:29:57 -08002137 mConnectionPoolLocked.dump(printer, verbose);
Jeff Browne5360fb2011-10-31 17:48:13 -07002138 }
2139 }
2140 }
2141
Vasu Noric3849202010-03-09 10:47:25 -08002142 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002143 * Returns list of full pathnames of all attached databases including the main database
2144 * by executing 'pragma database_list' on the database.
2145 *
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002146 * @return ArrayList of pairs of (database name, database file path) or null if the database
2147 * is not open.
Vasu Noric3849202010-03-09 10:47:25 -08002148 */
Vasu Noria017eda2011-01-27 10:52:55 -08002149 public List<Pair<String, String>> getAttachedDbs() {
Vasu Noric3849202010-03-09 10:47:25 -08002150 ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>();
Jeff Browne5360fb2011-10-31 17:48:13 -07002151 synchronized (mLock) {
2152 if (mConnectionPoolLocked == null) {
2153 return null; // not open
2154 }
2155
2156 if (!mHasAttachedDbsLocked) {
2157 // No attached databases.
2158 // There is a small window where attached databases exist but this flag is not
2159 // set yet. This can occur when this thread is in a race condition with another
2160 // thread that is executing the SQL statement: "attach database <blah> as <foo>"
2161 // If this thread is NOT ok with such a race condition (and thus possibly not
2162 // receivethe entire list of attached databases), then the caller should ensure
2163 // that no thread is executing any SQL statements while a thread is calling this
2164 // method. Typically, this method is called when 'adb bugreport' is done or the
2165 // caller wants to collect stats on the database and all its attached databases.
2166 attachedDbs.add(new Pair<String, String>("main", mConfigurationLocked.path));
2167 return attachedDbs;
2168 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002169
2170 acquireReference();
Vasu Nori24675612010-09-27 14:54:19 -07002171 }
Jeff Browne5360fb2011-10-31 17:48:13 -07002172
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002173 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002174 // has attached databases. query sqlite to get the list of attached databases.
2175 Cursor c = null;
2176 try {
2177 c = rawQuery("pragma database_list;", null);
2178 while (c.moveToNext()) {
2179 // sqlite returns a row for each database in the returned list of databases.
2180 // in each row,
2181 // 1st column is the database name such as main, or the database
2182 // name specified on the "ATTACH" command
2183 // 2nd column is the database file path.
2184 attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2)));
2185 }
2186 } finally {
2187 if (c != null) {
2188 c.close();
2189 }
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002190 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002191 return attachedDbs;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002192 } finally {
Jeff Brown03bd3022012-03-06 13:48:56 -08002193 releaseReference();
Vasu Noric3849202010-03-09 10:47:25 -08002194 }
Vasu Noric3849202010-03-09 10:47:25 -08002195 }
2196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002197 /**
Vasu Noriccd95442010-05-28 17:04:16 -07002198 * Runs 'pragma integrity_check' on the given database (and all the attached databases)
2199 * and returns true if the given database (and all its attached databases) pass integrity_check,
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002200 * false otherwise.
Vasu Noriccd95442010-05-28 17:04:16 -07002201 *<p>
2202 * If the result is false, then this method logs the errors reported by the integrity_check
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002203 * command execution.
Vasu Noriccd95442010-05-28 17:04:16 -07002204 *<p>
2205 * Note that 'pragma integrity_check' on a database can take a long time.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002206 *
2207 * @return true if the given database (and all its attached databases) pass integrity_check,
Vasu Noriccd95442010-05-28 17:04:16 -07002208 * false otherwise.
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002209 */
2210 public boolean isDatabaseIntegrityOk() {
Jeff Brown03bd3022012-03-06 13:48:56 -08002211 acquireReference();
Vasu Noribfe1dc22010-08-25 16:29:02 -07002212 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002213 List<Pair<String, String>> attachedDbs = null;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002214 try {
Jeff Brown03bd3022012-03-06 13:48:56 -08002215 attachedDbs = getAttachedDbs();
2216 if (attachedDbs == null) {
2217 throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " +
2218 "be retrieved. probably because the database is closed");
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002219 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002220 } catch (SQLiteException e) {
2221 // can't get attachedDb list. do integrity check on the main database
2222 attachedDbs = new ArrayList<Pair<String, String>>();
2223 attachedDbs.add(new Pair<String, String>("main", getPath()));
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002224 }
Jeff Brown03bd3022012-03-06 13:48:56 -08002225
2226 for (int i = 0; i < attachedDbs.size(); i++) {
2227 Pair<String, String> p = attachedDbs.get(i);
2228 SQLiteStatement prog = null;
2229 try {
2230 prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);");
2231 String rslt = prog.simpleQueryForString();
2232 if (!rslt.equalsIgnoreCase("ok")) {
2233 // integrity_checker failed on main or attached databases
2234 Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt);
2235 return false;
2236 }
2237 } finally {
2238 if (prog != null) prog.close();
2239 }
2240 }
2241 } finally {
2242 releaseReference();
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002243 }
Vasu Noribfe1dc22010-08-25 16:29:02 -07002244 return true;
Vasu Nori062fc7ce2010-03-31 16:13:05 -07002245 }
2246
Jeff Browne5360fb2011-10-31 17:48:13 -07002247 @Override
2248 public String toString() {
2249 return "SQLiteDatabase: " + getPath();
2250 }
2251
Jeff Browne5360fb2011-10-31 17:48:13 -07002252 private void throwIfNotOpenLocked() {
2253 if (mConnectionPoolLocked == null) {
2254 throw new IllegalStateException("The database '" + mConfigurationLocked.label
2255 + "' is not open.");
2256 }
2257 }
Vasu Nori3ef94e22010-02-05 14:49:04 -08002258
2259 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002260 * Used to allow returning sub-classes of {@link Cursor} when calling query.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002261 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002262 public interface CursorFactory {
2263 /**
2264 * See {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}.
2265 */
2266 public Cursor newCursor(SQLiteDatabase db,
2267 SQLiteCursorDriver masterQuery, String editTable,
2268 SQLiteQuery query);
2269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002270
2271 /**
Jeff Browne5360fb2011-10-31 17:48:13 -07002272 * A callback interface for a custom sqlite3 function.
2273 * This can be used to create a function that can be called from
2274 * sqlite3 database triggers.
2275 * @hide
Vasu Noric3849202010-03-09 10:47:25 -08002276 */
Jeff Browne5360fb2011-10-31 17:48:13 -07002277 public interface CustomFunction {
2278 public void callback(String[] args);
2279 }
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002280
2281 /**
2282 * Wrapper for configuration parameters that are used for opening {@link SQLiteDatabase}
2283 */
2284 public static final class OpenParams {
2285 private final int mOpenFlags;
2286 private final CursorFactory mCursorFactory;
2287 private final DatabaseErrorHandler mErrorHandler;
2288 private final int mLookasideSlotSize;
2289 private final int mLookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002290 private long mIdleConnectionTimeout;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002291
2292 private OpenParams(int openFlags, CursorFactory cursorFactory,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002293 DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount,
2294 long idleConnectionTimeout) {
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002295 mOpenFlags = openFlags;
2296 mCursorFactory = cursorFactory;
2297 mErrorHandler = errorHandler;
2298 mLookasideSlotSize = lookasideSlotSize;
2299 mLookasideSlotCount = lookasideSlotCount;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002300 mIdleConnectionTimeout = idleConnectionTimeout;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002301 }
2302
2303 /**
2304 * Returns size in bytes of each lookaside slot or -1 if not set.
2305 *
2306 * @see Builder#setLookasideConfig(int, int)
2307 */
2308 @IntRange(from = -1)
2309 public int getLookasideSlotSize() {
2310 return mLookasideSlotSize;
2311 }
2312
2313 /**
2314 * Returns total number of lookaside memory slots per database connection or -1 if not
2315 * set.
2316 *
2317 * @see Builder#setLookasideConfig(int, int)
2318 */
2319 @IntRange(from = -1)
2320 public int getLookasideSlotCount() {
2321 return mLookasideSlotCount;
2322 }
2323
2324 /**
2325 * Returns flags to control database access mode
2326 *
2327 * @see Builder#setOpenFlags(int)
2328 */
2329 @DatabaseOpenFlags
2330 public int getOpenFlags() {
2331 return mOpenFlags;
2332 }
2333
2334 /**
2335 * Returns an optional factory class that is called to instantiate a cursor when query
2336 * is called
2337 *
2338 * @see Builder#setCursorFactory(CursorFactory)
2339 */
2340 @Nullable
2341 public CursorFactory getCursorFactory() {
2342 return mCursorFactory;
2343 }
2344
2345 /**
2346 * Returns handler for database corruption errors
2347 *
2348 * @see Builder#setErrorHandler(DatabaseErrorHandler)
2349 */
2350 @Nullable
2351 public DatabaseErrorHandler getErrorHandler() {
2352 return mErrorHandler;
2353 }
2354
2355 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002356 * Returns maximum number of milliseconds that SQLite connection is allowed to be idle
2357 * before it is closed and removed from the pool.
2358 * <p>If the value isn't set, the timeout defaults to the system wide timeout
2359 *
2360 * @return timeout in milliseconds or -1 if the value wasn't set.
2361 */
2362 public long getIdleConnectionTimeout() {
2363 return mIdleConnectionTimeout;
2364 }
2365
2366 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002367 * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with
2368 * {@code this} parameters.
2369 * @hide
2370 */
2371 @NonNull
2372 public Builder toBuilder() {
2373 return new Builder(this);
2374 }
2375
2376 /**
2377 * Builder for {@link OpenParams}.
2378 */
2379 public static final class Builder {
2380 private int mLookasideSlotSize = -1;
2381 private int mLookasideSlotCount = -1;
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002382 private long mIdleConnectionTimeout = -1;
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002383 private int mOpenFlags;
2384 private CursorFactory mCursorFactory;
2385 private DatabaseErrorHandler mErrorHandler;
2386
2387 public Builder() {
2388 }
2389
2390 public Builder(OpenParams params) {
2391 mLookasideSlotSize = params.mLookasideSlotSize;
2392 mLookasideSlotCount = params.mLookasideSlotCount;
2393 mOpenFlags = params.mOpenFlags;
2394 mCursorFactory = params.mCursorFactory;
2395 mErrorHandler = params.mErrorHandler;
2396 }
2397
2398 /**
2399 * Configures
2400 * <a href="https://sqlite.org/malloc.html#lookaside">lookaside memory allocator</a>
2401 *
2402 * <p>SQLite default settings will be used, if this method isn't called.
2403 * Use {@code setLookasideConfig(0,0)} to disable lookaside
2404 *
Fyodor Kupolov05a0f0f2017-06-30 19:00:00 -07002405 * <p><strong>Note:</strong> Provided slotSize/slotCount configuration is just a
2406 * recommendation. The system may choose different values depending on a device, e.g.
2407 * lookaside allocations can be disabled on low-RAM devices
2408 *
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002409 * @param slotSize The size in bytes of each lookaside slot.
2410 * @param slotCount The total number of lookaside memory slots per database connection.
2411 */
2412 public Builder setLookasideConfig(@IntRange(from = 0) final int slotSize,
2413 @IntRange(from = 0) final int slotCount) {
2414 Preconditions.checkArgument(slotSize >= 0,
2415 "lookasideSlotCount cannot be negative");
2416 Preconditions.checkArgument(slotCount >= 0,
2417 "lookasideSlotSize cannot be negative");
2418 Preconditions.checkArgument(
2419 (slotSize > 0 && slotCount > 0) || (slotCount == 0 && slotSize == 0),
2420 "Invalid configuration: " + slotSize + ", " + slotCount);
2421
2422 mLookasideSlotSize = slotSize;
2423 mLookasideSlotCount = slotCount;
2424 return this;
2425 }
2426
2427 /**
2428 * Returns true if {@link #ENABLE_WRITE_AHEAD_LOGGING} flag is set
2429 * @hide
2430 */
2431 public boolean isWriteAheadLoggingEnabled() {
2432 return (mOpenFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
2433 }
2434
2435 /**
2436 * Sets flags to control database access mode
2437 * @param openFlags The new flags to set
2438 * @see #OPEN_READWRITE
2439 * @see #OPEN_READONLY
2440 * @see #CREATE_IF_NECESSARY
2441 * @see #NO_LOCALIZED_COLLATORS
2442 * @see #ENABLE_WRITE_AHEAD_LOGGING
2443 * @return same builder instance for chaining multiple calls into a single statement
2444 */
2445 @NonNull
2446 public Builder setOpenFlags(@DatabaseOpenFlags int openFlags) {
2447 mOpenFlags = openFlags;
2448 return this;
2449 }
2450
2451 /**
2452 * Adds flags to control database access mode
2453 *
2454 * @param openFlags The new flags to add
2455 * @return same builder instance for chaining multiple calls into a single statement
2456 */
2457 @NonNull
2458 public Builder addOpenFlags(@DatabaseOpenFlags int openFlags) {
2459 mOpenFlags |= openFlags;
2460 return this;
2461 }
2462
2463 /**
2464 * Removes database access mode flags
2465 *
2466 * @param openFlags Flags to remove
2467 * @return same builder instance for chaining multiple calls into a single statement
2468 */
2469 @NonNull
2470 public Builder removeOpenFlags(@DatabaseOpenFlags int openFlags) {
2471 mOpenFlags &= ~openFlags;
2472 return this;
2473 }
2474
2475 /**
2476 * Sets {@link #ENABLE_WRITE_AHEAD_LOGGING} flag if {@code enabled} is {@code true},
2477 * unsets otherwise
2478 * @hide
2479 */
2480 public void setWriteAheadLoggingEnabled(boolean enabled) {
2481 if (enabled) {
2482 addOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2483 } else {
2484 removeOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
2485 }
2486 }
2487
2488 /**
2489 * Set an optional factory class that is called to instantiate a cursor when query
2490 * is called.
2491 *
2492 * @param cursorFactory instance
2493 * @return same builder instance for chaining multiple calls into a single statement
2494 */
2495 @NonNull
2496 public Builder setCursorFactory(@Nullable CursorFactory cursorFactory) {
2497 mCursorFactory = cursorFactory;
2498 return this;
2499 }
2500
2501
2502 /**
2503 * Sets {@link DatabaseErrorHandler} object to handle db corruption errors
2504 */
2505 @NonNull
2506 public Builder setErrorHandler(@Nullable DatabaseErrorHandler errorHandler) {
2507 mErrorHandler = errorHandler;
2508 return this;
2509 }
2510
2511 /**
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002512 * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle
2513 * before it is closed and removed from the pool.
2514 *
2515 * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE}
2516 * to allow unlimited idle connections.
2517 */
2518 @NonNull
2519 public Builder setIdleConnectionTimeout(
2520 @IntRange(from = 0) long idleConnectionTimeoutMs) {
2521 Preconditions.checkArgument(idleConnectionTimeoutMs >= 0,
2522 "idle connection timeout cannot be negative");
2523 mIdleConnectionTimeout = idleConnectionTimeoutMs;
2524 return this;
2525 }
2526
2527 /**
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002528 * Creates an instance of {@link OpenParams} with the options that were previously set
2529 * on this builder
2530 */
2531 @NonNull
2532 public OpenParams build() {
2533 return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize,
Fyodor Kupolovcf97b6b2017-07-25 14:17:33 -07002534 mLookasideSlotCount, mIdleConnectionTimeout);
Fyodor Kupolovd3b0c7e2017-06-20 11:51:55 -07002535 }
2536 }
2537 }
2538
2539 /** @hide */
2540 @IntDef(flag = true, prefix = {"OPEN_", "CREATE_", "NO_", "ENABLE_"}, value = {
2541 OPEN_READWRITE,
2542 OPEN_READONLY,
2543 CREATE_IF_NECESSARY,
2544 NO_LOCALIZED_COLLATORS,
2545 ENABLE_WRITE_AHEAD_LOGGING
2546 })
2547 @Retention(RetentionPolicy.SOURCE)
2548 public @interface DatabaseOpenFlags {}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002549}