1 /* 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 17 package android.database.sqlite; 18 19 import android.app.AppGlobals; 20 import android.content.ContentValues; 21 import android.content.res.Resources; 22 import android.database.Cursor; 23 import android.database.DatabaseErrorHandler; 24 import android.database.DatabaseUtils; 25 import android.database.DefaultDatabaseErrorHandler; 26 import android.database.SQLException; 27 import android.database.sqlite.SQLiteDebug.DbStats; 28 import android.os.Debug; 29 import android.os.StatFs; 30 import android.os.SystemClock; 31 import android.os.SystemProperties; 32 import android.text.TextUtils; 33 import android.util.EventLog; 34 import android.util.Log; 35 import android.util.LruCache; 36 import android.util.Pair; 37 import dalvik.system.BlockGuard; 38 import java.io.File; 39 import java.lang.ref.WeakReference; 40 import java.util.ArrayList; 41 import java.util.HashMap; 42 import java.util.Iterator; 43 import java.util.List; 44 import java.util.Locale; 45 import java.util.Map; 46 import java.util.Random; 47 import java.util.WeakHashMap; 48 import java.util.concurrent.TimeUnit; 49 import java.util.concurrent.locks.ReentrantLock; 50 import java.util.regex.Pattern; 51 52 /** 53 * Exposes methods to manage a SQLite database. 54 * <p>SQLiteDatabase has methods to create, delete, execute SQL commands, and 55 * perform other common database management tasks. 56 * <p>See the Notepad sample application in the SDK for an example of creating 57 * and managing a database. 58 * <p> Database names must be unique within an application, not across all 59 * applications. 60 * 61 * <h3>Localized Collation - ORDER BY</h3> 62 * <p>In addition to SQLite's default <code>BINARY</code> collator, Android supplies 63 * two more, <code>LOCALIZED</code>, which changes with the system's current locale 64 * if you wire it up correctly (XXX a link needed!), and <code>UNICODE</code>, which 65 * is the Unicode Collation Algorithm and not tailored to the current locale. 66 */ 67 public class SQLiteDatabase extends SQLiteClosable { 68 private static final String TAG = "SQLiteDatabase"; 69 private static final boolean ENABLE_DB_SAMPLE = false; // true to enable stats in event log 70 private static final int EVENT_DB_OPERATION = 52000; 71 private static final int EVENT_DB_CORRUPT = 75004; 72 73 /** 74 * Algorithms used in ON CONFLICT clause 75 * http://www.sqlite.org/lang_conflict.html 76 */ 77 /** 78 * When a constraint violation occurs, an immediate ROLLBACK occurs, 79 * thus ending the current transaction, and the command aborts with a 80 * return code of SQLITE_CONSTRAINT. If no transaction is active 81 * (other than the implied transaction that is created on every command) 82 * then this algorithm works the same as ABORT. 83 */ 84 public static final int CONFLICT_ROLLBACK = 1; 85 86 /** 87 * When a constraint violation occurs,no ROLLBACK is executed 88 * so changes from prior commands within the same transaction 89 * are preserved. This is the default behavior. 90 */ 91 public static final int CONFLICT_ABORT = 2; 92 93 /** 94 * When a constraint violation occurs, the command aborts with a return 95 * code SQLITE_CONSTRAINT. But any changes to the database that 96 * the command made prior to encountering the constraint violation 97 * are preserved and are not backed out. 98 */ 99 public static final int CONFLICT_FAIL = 3; 100 101 /** 102 * When a constraint violation occurs, the one row that contains 103 * the constraint violation is not inserted or changed. 104 * But the command continues executing normally. Other rows before and 105 * after the row that contained the constraint violation continue to be 106 * inserted or updated normally. No error is returned. 107 */ 108 public static final int CONFLICT_IGNORE = 4; 109 110 /** 111 * When a UNIQUE constraint violation occurs, the pre-existing rows that 112 * are causing the constraint violation are removed prior to inserting 113 * or updating the current row. Thus the insert or update always occurs. 114 * The command continues executing normally. No error is returned. 115 * If a NOT NULL constraint violation occurs, the NULL value is replaced 116 * by the default value for that column. If the column has no default 117 * value, then the ABORT algorithm is used. If a CHECK constraint 118 * violation occurs then the IGNORE algorithm is used. When this conflict 119 * resolution strategy deletes rows in order to satisfy a constraint, 120 * it does not invoke delete triggers on those rows. 121 * This behavior might change in a future release. 122 */ 123 public static final int CONFLICT_REPLACE = 5; 124 125 /** 126 * use the following when no conflict action is specified. 127 */ 128 public static final int CONFLICT_NONE = 0; 129 private static final String[] CONFLICT_VALUES = new String[] 130 {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "}; 131 132 /** 133 * Maximum Length Of A LIKE Or GLOB Pattern 134 * The pattern matching algorithm used in the default LIKE and GLOB implementation 135 * of SQLite can exhibit O(N^2) performance (where N is the number of characters in 136 * the pattern) for certain pathological cases. To avoid denial-of-service attacks 137 * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes. 138 * The default value of this limit is 50000. A modern workstation can evaluate 139 * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly. 140 * The denial of service problem only comes into play when the pattern length gets 141 * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns 142 * are at most a few dozen bytes in length, paranoid application developers may 143 * want to reduce this parameter to something in the range of a few hundred 144 * if they know that external users are able to generate arbitrary patterns. 145 */ 146 public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000; 147 148 /** 149 * Flag for {@link #openDatabase} to open the database for reading and writing. 150 * If the disk is full, this may fail even before you actually write anything. 151 * 152 * {@more} Note that the value of this flag is 0, so it is the default. 153 */ 154 public static final int OPEN_READWRITE = 0x00000000; // update native code if changing 155 156 /** 157 * Flag for {@link #openDatabase} to open the database for reading only. 158 * This is the only reliable way to open a database if the disk may be full. 159 */ 160 public static final int OPEN_READONLY = 0x00000001; // update native code if changing 161 162 private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing 163 164 /** 165 * Flag for {@link #openDatabase} to open the database without support for localized collators. 166 * 167 * {@more} This causes the collator <code>LOCALIZED</code> not to be created. 168 * You must be consistent when using this flag to use the setting the database was 169 * created with. If this is set, {@link #setLocale} will do nothing. 170 */ 171 public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing 172 173 /** 174 * Flag for {@link #openDatabase} to create the database file if it does not already exist. 175 */ 176 public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing 177 178 /** 179 * Indicates whether the most-recently started transaction has been marked as successful. 180 */ 181 private boolean mInnerTransactionIsSuccessful; 182 183 /** 184 * Valid during the life of a transaction, and indicates whether the entire transaction (the 185 * outer one and all of the inner ones) so far has been successful. 186 */ 187 private boolean mTransactionIsSuccessful; 188 189 /** 190 * Valid during the life of a transaction. 191 */ 192 private SQLiteTransactionListener mTransactionListener; 193 194 /** 195 * this member is set if {@link #execSQL(String)} is used to begin and end transactions. 196 */ 197 private boolean mTransactionUsingExecSql; 198 199 /** Synchronize on this when accessing the database */ 200 private final DatabaseReentrantLock mLock = new DatabaseReentrantLock(true); 201 202 private long mLockAcquiredWallTime = 0L; 203 private long mLockAcquiredThreadTime = 0L; 204 205 // limit the frequency of complaints about each database to one within 20 sec 206 // unless run command adb shell setprop log.tag.Database VERBOSE 207 private static final int LOCK_WARNING_WINDOW_IN_MS = 20000; 208 /** If the lock is held this long then a warning will be printed when it is released. */ 209 private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS = 300; 210 private static final int LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS = 100; 211 private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT = 2000; 212 213 private static final int SLEEP_AFTER_YIELD_QUANTUM = 1000; 214 215 // The pattern we remove from database filenames before 216 // potentially logging them. 217 private static final Pattern EMAIL_IN_DB_PATTERN = Pattern.compile("[\\w\\.\\-]+@[\\w\\.\\-]+"); 218 219 private long mLastLockMessageTime = 0L; 220 221 // Things related to query logging/sampling for debugging 222 // slow/frequent queries during development. Always log queries 223 // which take (by default) 500ms+; shorter queries are sampled 224 // accordingly. Commit statements, which are typically slow, are 225 // logged together with the most recently executed SQL statement, 226 // for disambiguation. The 500ms value is configurable via a 227 // SystemProperty, but developers actively debugging database I/O 228 // should probably use the regular log tunable, 229 // LOG_SLOW_QUERIES_PROPERTY, defined below. 230 private static int sQueryLogTimeInMillis = 0; // lazily initialized 231 private static final int QUERY_LOG_SQL_LENGTH = 64; 232 private static final String COMMIT_SQL = "COMMIT;"; 233 private static final String BEGIN_SQL = "BEGIN;"; 234 private final Random mRandom = new Random(); 235 /** the last non-commit/rollback sql statement in a transaction */ 236 // guarded by 'this' 237 private String mLastSqlStatement = null; 238 getLastSqlStatement()239 synchronized String getLastSqlStatement() { 240 return mLastSqlStatement; 241 } 242 setLastSqlStatement(String sql)243 synchronized void setLastSqlStatement(String sql) { 244 mLastSqlStatement = sql; 245 } 246 247 /** guarded by {@link #mLock} */ 248 private long mTransStartTime; 249 250 // String prefix for slow database query EventLog records that show 251 // lock acquistions of the database. 252 /* package */ static final String GET_LOCK_LOG_PREFIX = "GETLOCK:"; 253 254 /** Used by native code, do not rename. make it volatile, so it is thread-safe. */ 255 /* package */ volatile int mNativeHandle = 0; 256 257 /** 258 * The size, in bytes, of a block on "/data". This corresponds to the Unix 259 * statfs.f_bsize field. note that this field is lazily initialized. 260 */ 261 private static int sBlockSize = 0; 262 263 /** The path for the database file */ 264 private final String mPath; 265 266 /** The anonymized path for the database file for logging purposes */ 267 private String mPathForLogs = null; // lazily populated 268 269 /** The flags passed to open/create */ 270 private final int mFlags; 271 272 /** The optional factory to use when creating new Cursors */ 273 private final CursorFactory mFactory; 274 275 private final WeakHashMap<SQLiteClosable, Object> mPrograms; 276 277 /** Default statement-cache size per database connection ( = instance of this class) */ 278 private static final int DEFAULT_SQL_CACHE_SIZE = 25; 279 280 /** 281 * for each instance of this class, a LRU cache is maintained to store 282 * the compiled query statement ids returned by sqlite database. 283 * key = SQL statement with "?" for bind args 284 * value = {@link SQLiteCompiledSql} 285 * If an application opens the database and keeps it open during its entire life, then 286 * there will not be an overhead of compilation of SQL statements by sqlite. 287 * 288 * why is this cache NOT static? because sqlite attaches compiledsql statements to the 289 * struct created when {@link SQLiteDatabase#openDatabase(String, CursorFactory, int)} is 290 * invoked. 291 * 292 * this cache's max size is settable by calling the method 293 * (@link #setMaxSqlCacheSize(int)}. 294 */ 295 // guarded by this 296 private LruCache<String, SQLiteCompiledSql> mCompiledQueries; 297 298 /** 299 * absolute max value that can be set by {@link #setMaxSqlCacheSize(int)} 300 * size of each prepared-statement is between 1K - 6K, depending on the complexity of the 301 * SQL statement & schema. 302 */ 303 public static final int MAX_SQL_CACHE_SIZE = 100; 304 private boolean mCacheFullWarning; 305 306 /** Used to find out where this object was created in case it never got closed. */ 307 private final Throwable mStackTrace; 308 309 // System property that enables logging of slow queries. Specify the threshold in ms. 310 private static final String LOG_SLOW_QUERIES_PROPERTY = "db.log.slow_query_threshold"; 311 private final int mSlowQueryThreshold; 312 313 /** stores the list of statement ids that need to be finalized by sqlite */ 314 private final ArrayList<Integer> mClosedStatementIds = new ArrayList<Integer>(); 315 316 /** {@link DatabaseErrorHandler} to be used when SQLite returns any of the following errors 317 * Corruption 318 * */ 319 private final DatabaseErrorHandler mErrorHandler; 320 321 /** The Database connection pool {@link DatabaseConnectionPool}. 322 * Visibility is package-private for testing purposes. otherwise, private visibility is enough. 323 */ 324 /* package */ volatile DatabaseConnectionPool mConnectionPool = null; 325 326 /** Each database connection handle in the pool is assigned a number 1..N, where N is the 327 * size of the connection pool. 328 * The main connection handle to which the pool is attached is assigned a value of 0. 329 */ 330 /* package */ final short mConnectionNum; 331 332 /** on pooled database connections, this member points to the parent ( = main) 333 * database connection handle. 334 * package visibility only for testing purposes 335 */ 336 /* package */ SQLiteDatabase mParentConnObj = null; 337 338 private static final String MEMORY_DB_PATH = ":memory:"; 339 340 /** set to true if the database has attached databases */ 341 private volatile boolean mHasAttachedDbs = false; 342 343 /** stores reference to all databases opened in the current process. */ 344 private static ArrayList<WeakReference<SQLiteDatabase>> mActiveDatabases = 345 new ArrayList<WeakReference<SQLiteDatabase>>(); 346 addSQLiteClosable(SQLiteClosable closable)347 synchronized void addSQLiteClosable(SQLiteClosable closable) { 348 // mPrograms is per instance of SQLiteDatabase and it doesn't actually touch the database 349 // itself. so, there is no need to lock(). 350 mPrograms.put(closable, null); 351 } 352 removeSQLiteClosable(SQLiteClosable closable)353 synchronized void removeSQLiteClosable(SQLiteClosable closable) { 354 mPrograms.remove(closable); 355 } 356 357 @Override onAllReferencesReleased()358 protected void onAllReferencesReleased() { 359 if (isOpen()) { 360 // close the database which will close all pending statements to be finalized also 361 close(); 362 } 363 } 364 365 /** 366 * Attempts to release memory that SQLite holds but does not require to 367 * operate properly. Typically this memory will come from the page cache. 368 * 369 * @return the number of bytes actually released 370 */ releaseMemory()371 static public native int releaseMemory(); 372 373 /** 374 * Control whether or not the SQLiteDatabase is made thread-safe by using locks 375 * around critical sections. This is pretty expensive, so if you know that your 376 * DB will only be used by a single thread then you should set this to false. 377 * The default is true. 378 * @param lockingEnabled set to true to enable locks, false otherwise 379 */ setLockingEnabled(boolean lockingEnabled)380 public void setLockingEnabled(boolean lockingEnabled) { 381 mLockingEnabled = lockingEnabled; 382 } 383 384 /** 385 * If set then the SQLiteDatabase is made thread-safe by using locks 386 * around critical sections 387 */ 388 private boolean mLockingEnabled = true; 389 onCorruption()390 /* package */ void onCorruption() { 391 EventLog.writeEvent(EVENT_DB_CORRUPT, mPath); 392 mErrorHandler.onCorruption(this); 393 } 394 395 /** 396 * Locks the database for exclusive access. The database lock must be held when 397 * touch the native sqlite3* object since it is single threaded and uses 398 * a polling lock contention algorithm. The lock is recursive, and may be acquired 399 * multiple times by the same thread. This is a no-op if mLockingEnabled is false. 400 * 401 * @see #unlock() 402 */ lock(String sql)403 /* package */ void lock(String sql) { 404 lock(sql, false); 405 } 406 lock()407 /* pachage */ void lock() { 408 lock(null, false); 409 } 410 411 private static final long LOCK_WAIT_PERIOD = 30L; lock(String sql, boolean forced)412 private void lock(String sql, boolean forced) { 413 // make sure this method is NOT being called from a 'synchronized' method 414 if (Thread.holdsLock(this)) { 415 Log.w(TAG, "don't lock() while in a synchronized method"); 416 } 417 verifyDbIsOpen(); 418 if (!forced && !mLockingEnabled) return; 419 boolean done = false; 420 long timeStart = SystemClock.uptimeMillis(); 421 while (!done) { 422 try { 423 // wait for 30sec to acquire the lock 424 done = mLock.tryLock(LOCK_WAIT_PERIOD, TimeUnit.SECONDS); 425 if (!done) { 426 // lock not acquired in NSec. print a message and stacktrace saying the lock 427 // has not been available for 30sec. 428 Log.w(TAG, "database lock has not been available for " + LOCK_WAIT_PERIOD + 429 " sec. Current Owner of the lock is " + mLock.getOwnerDescription() + 430 ". Continuing to wait in thread: " + Thread.currentThread().getId()); 431 } 432 } catch (InterruptedException e) { 433 // ignore the interruption 434 } 435 } 436 if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) { 437 if (mLock.getHoldCount() == 1) { 438 // Use elapsed real-time since the CPU may sleep when waiting for IO 439 mLockAcquiredWallTime = SystemClock.elapsedRealtime(); 440 mLockAcquiredThreadTime = Debug.threadCpuTimeNanos(); 441 } 442 } 443 if (sql != null) { 444 if (ENABLE_DB_SAMPLE) { 445 logTimeStat(sql, timeStart, GET_LOCK_LOG_PREFIX); 446 } 447 } 448 } 449 private static class DatabaseReentrantLock extends ReentrantLock { DatabaseReentrantLock(boolean fair)450 DatabaseReentrantLock(boolean fair) { 451 super(fair); 452 } 453 @Override getOwner()454 public Thread getOwner() { 455 return super.getOwner(); 456 } getOwnerDescription()457 public String getOwnerDescription() { 458 Thread t = getOwner(); 459 return (t== null) ? "none" : String.valueOf(t.getId()); 460 } 461 } 462 463 /** 464 * Locks the database for exclusive access. The database lock must be held when 465 * touch the native sqlite3* object since it is single threaded and uses 466 * a polling lock contention algorithm. The lock is recursive, and may be acquired 467 * multiple times by the same thread. 468 * 469 * @see #unlockForced() 470 */ lockForced()471 private void lockForced() { 472 lock(null, true); 473 } 474 lockForced(String sql)475 private void lockForced(String sql) { 476 lock(sql, true); 477 } 478 479 /** 480 * Releases the database lock. This is a no-op if mLockingEnabled is false. 481 * 482 * @see #unlock() 483 */ unlock()484 /* package */ void unlock() { 485 if (!mLockingEnabled) return; 486 if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) { 487 if (mLock.getHoldCount() == 1) { 488 checkLockHoldTime(); 489 } 490 } 491 mLock.unlock(); 492 } 493 494 /** 495 * Releases the database lock. 496 * 497 * @see #unlockForced() 498 */ unlockForced()499 private void unlockForced() { 500 if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) { 501 if (mLock.getHoldCount() == 1) { 502 checkLockHoldTime(); 503 } 504 } 505 mLock.unlock(); 506 } 507 checkLockHoldTime()508 private void checkLockHoldTime() { 509 // Use elapsed real-time since the CPU may sleep when waiting for IO 510 long elapsedTime = SystemClock.elapsedRealtime(); 511 long lockedTime = elapsedTime - mLockAcquiredWallTime; 512 if (lockedTime < LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT && 513 !Log.isLoggable(TAG, Log.VERBOSE) && 514 (elapsedTime - mLastLockMessageTime) < LOCK_WARNING_WINDOW_IN_MS) { 515 return; 516 } 517 if (lockedTime > LOCK_ACQUIRED_WARNING_TIME_IN_MS) { 518 int threadTime = (int) 519 ((Debug.threadCpuTimeNanos() - mLockAcquiredThreadTime) / 1000000); 520 if (threadTime > LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS || 521 lockedTime > LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT) { 522 mLastLockMessageTime = elapsedTime; 523 String msg = "lock held on " + mPath + " for " + lockedTime + "ms. Thread time was " 524 + threadTime + "ms"; 525 if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING_STACK_TRACE) { 526 Log.d(TAG, msg, new Exception()); 527 } else { 528 Log.d(TAG, msg); 529 } 530 } 531 } 532 } 533 534 /** 535 * Begins a transaction in EXCLUSIVE mode. 536 * <p> 537 * Transactions can be nested. 538 * When the outer transaction is ended all of 539 * the work done in that transaction and all of the nested transactions will be committed or 540 * rolled back. The changes will be rolled back if any transaction is ended without being 541 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed. 542 * </p> 543 * <p>Here is the standard idiom for transactions: 544 * 545 * <pre> 546 * db.beginTransaction(); 547 * try { 548 * ... 549 * db.setTransactionSuccessful(); 550 * } finally { 551 * db.endTransaction(); 552 * } 553 * </pre> 554 */ beginTransaction()555 public void beginTransaction() { 556 beginTransaction(null /* transactionStatusCallback */, true); 557 } 558 559 /** 560 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When 561 * the outer transaction is ended all of the work done in that transaction 562 * and all of the nested transactions will be committed or rolled back. The 563 * changes will be rolled back if any transaction is ended without being 564 * marked as clean (by calling setTransactionSuccessful). Otherwise they 565 * will be committed. 566 * <p> 567 * Here is the standard idiom for transactions: 568 * 569 * <pre> 570 * db.beginTransactionNonExclusive(); 571 * try { 572 * ... 573 * db.setTransactionSuccessful(); 574 * } finally { 575 * db.endTransaction(); 576 * } 577 * </pre> 578 */ beginTransactionNonExclusive()579 public void beginTransactionNonExclusive() { 580 beginTransaction(null /* transactionStatusCallback */, false); 581 } 582 583 /** 584 * Begins a transaction in EXCLUSIVE mode. 585 * <p> 586 * Transactions can be nested. 587 * When the outer transaction is ended all of 588 * the work done in that transaction and all of the nested transactions will be committed or 589 * rolled back. The changes will be rolled back if any transaction is ended without being 590 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed. 591 * </p> 592 * <p>Here is the standard idiom for transactions: 593 * 594 * <pre> 595 * db.beginTransactionWithListener(listener); 596 * try { 597 * ... 598 * db.setTransactionSuccessful(); 599 * } finally { 600 * db.endTransaction(); 601 * } 602 * </pre> 603 * 604 * @param transactionListener listener that should be notified when the transaction begins, 605 * commits, or is rolled back, either explicitly or by a call to 606 * {@link #yieldIfContendedSafely}. 607 */ beginTransactionWithListener(SQLiteTransactionListener transactionListener)608 public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) { 609 beginTransaction(transactionListener, true); 610 } 611 612 /** 613 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When 614 * the outer transaction is ended all of the work done in that transaction 615 * and all of the nested transactions will be committed or rolled back. The 616 * changes will be rolled back if any transaction is ended without being 617 * marked as clean (by calling setTransactionSuccessful). Otherwise they 618 * will be committed. 619 * <p> 620 * Here is the standard idiom for transactions: 621 * 622 * <pre> 623 * db.beginTransactionWithListenerNonExclusive(listener); 624 * try { 625 * ... 626 * db.setTransactionSuccessful(); 627 * } finally { 628 * db.endTransaction(); 629 * } 630 * </pre> 631 * 632 * @param transactionListener listener that should be notified when the 633 * transaction begins, commits, or is rolled back, either 634 * explicitly or by a call to {@link #yieldIfContendedSafely}. 635 */ beginTransactionWithListenerNonExclusive( SQLiteTransactionListener transactionListener)636 public void beginTransactionWithListenerNonExclusive( 637 SQLiteTransactionListener transactionListener) { 638 beginTransaction(transactionListener, false); 639 } 640 beginTransaction(SQLiteTransactionListener transactionListener, boolean exclusive)641 private void beginTransaction(SQLiteTransactionListener transactionListener, 642 boolean exclusive) { 643 verifyDbIsOpen(); 644 lockForced(BEGIN_SQL); 645 boolean ok = false; 646 try { 647 // If this thread already had the lock then get out 648 if (mLock.getHoldCount() > 1) { 649 if (mInnerTransactionIsSuccessful) { 650 String msg = "Cannot call beginTransaction between " 651 + "calling setTransactionSuccessful and endTransaction"; 652 IllegalStateException e = new IllegalStateException(msg); 653 Log.e(TAG, "beginTransaction() failed", e); 654 throw e; 655 } 656 ok = true; 657 return; 658 } 659 660 // This thread didn't already have the lock, so begin a database 661 // transaction now. 662 if (exclusive && mConnectionPool == null) { 663 execSQL("BEGIN EXCLUSIVE;"); 664 } else { 665 execSQL("BEGIN IMMEDIATE;"); 666 } 667 mTransStartTime = SystemClock.uptimeMillis(); 668 mTransactionListener = transactionListener; 669 mTransactionIsSuccessful = true; 670 mInnerTransactionIsSuccessful = false; 671 if (transactionListener != null) { 672 try { 673 transactionListener.onBegin(); 674 } catch (RuntimeException e) { 675 execSQL("ROLLBACK;"); 676 throw e; 677 } 678 } 679 ok = true; 680 } finally { 681 if (!ok) { 682 // beginTransaction is called before the try block so we must release the lock in 683 // the case of failure. 684 unlockForced(); 685 } 686 } 687 } 688 689 /** 690 * End a transaction. See beginTransaction for notes about how to use this and when transactions 691 * are committed and rolled back. 692 */ endTransaction()693 public void endTransaction() { 694 verifyLockOwner(); 695 try { 696 if (mInnerTransactionIsSuccessful) { 697 mInnerTransactionIsSuccessful = false; 698 } else { 699 mTransactionIsSuccessful = false; 700 } 701 if (mLock.getHoldCount() != 1) { 702 return; 703 } 704 RuntimeException savedException = null; 705 if (mTransactionListener != null) { 706 try { 707 if (mTransactionIsSuccessful) { 708 mTransactionListener.onCommit(); 709 } else { 710 mTransactionListener.onRollback(); 711 } 712 } catch (RuntimeException e) { 713 savedException = e; 714 mTransactionIsSuccessful = false; 715 } 716 } 717 if (mTransactionIsSuccessful) { 718 execSQL(COMMIT_SQL); 719 // if write-ahead logging is used, we have to take care of checkpoint. 720 // TODO: should applications be given the flexibility of choosing when to 721 // trigger checkpoint? 722 // for now, do checkpoint after every COMMIT because that is the fastest 723 // way to guarantee that readers will see latest data. 724 // but this is the slowest way to run sqlite with in write-ahead logging mode. 725 if (this.mConnectionPool != null) { 726 execSQL("PRAGMA wal_checkpoint;"); 727 if (SQLiteDebug.DEBUG_SQL_STATEMENTS) { 728 Log.i(TAG, "PRAGMA wal_Checkpoint done"); 729 } 730 } 731 // log the transaction time to the Eventlog. 732 if (ENABLE_DB_SAMPLE) { 733 logTimeStat(getLastSqlStatement(), mTransStartTime, COMMIT_SQL); 734 } 735 } else { 736 try { 737 execSQL("ROLLBACK;"); 738 if (savedException != null) { 739 throw savedException; 740 } 741 } catch (SQLException e) { 742 if (false) { 743 Log.d(TAG, "exception during rollback, maybe the DB previously " 744 + "performed an auto-rollback"); 745 } 746 } 747 } 748 } finally { 749 mTransactionListener = null; 750 unlockForced(); 751 if (false) { 752 Log.v(TAG, "unlocked " + Thread.currentThread() 753 + ", holdCount is " + mLock.getHoldCount()); 754 } 755 } 756 } 757 758 /** 759 * Marks the current transaction as successful. Do not do any more database work between 760 * calling this and calling endTransaction. Do as little non-database work as possible in that 761 * situation too. If any errors are encountered between this and endTransaction the transaction 762 * will still be committed. 763 * 764 * @throws IllegalStateException if the current thread is not in a transaction or the 765 * transaction is already marked as successful. 766 */ setTransactionSuccessful()767 public void setTransactionSuccessful() { 768 verifyDbIsOpen(); 769 if (!mLock.isHeldByCurrentThread()) { 770 throw new IllegalStateException("no transaction pending"); 771 } 772 if (mInnerTransactionIsSuccessful) { 773 throw new IllegalStateException( 774 "setTransactionSuccessful may only be called once per call to beginTransaction"); 775 } 776 mInnerTransactionIsSuccessful = true; 777 } 778 779 /** 780 * return true if there is a transaction pending 781 */ inTransaction()782 public boolean inTransaction() { 783 return mLock.getHoldCount() > 0 || mTransactionUsingExecSql; 784 } 785 setTransactionUsingExecSqlFlag()786 /* package */ synchronized void setTransactionUsingExecSqlFlag() { 787 if (Log.isLoggable(TAG, Log.DEBUG)) { 788 Log.i(TAG, "found execSQL('begin transaction')"); 789 } 790 mTransactionUsingExecSql = true; 791 } 792 resetTransactionUsingExecSqlFlag()793 /* package */ synchronized void resetTransactionUsingExecSqlFlag() { 794 if (Log.isLoggable(TAG, Log.DEBUG)) { 795 if (mTransactionUsingExecSql) { 796 Log.i(TAG, "found execSQL('commit or end or rollback')"); 797 } 798 } 799 mTransactionUsingExecSql = false; 800 } 801 802 /** 803 * Returns true if the caller is considered part of the current transaction, if any. 804 * <p> 805 * Caller is part of the current transaction if either of the following is true 806 * <ol> 807 * <li>If transaction is started by calling beginTransaction() methods AND if the caller is 808 * in the same thread as the thread that started the transaction. 809 * </li> 810 * <li>If the transaction is started by calling {@link #execSQL(String)} like this: 811 * execSQL("BEGIN transaction"). In this case, every thread in the process is considered 812 * part of the current transaction.</li> 813 * </ol> 814 * 815 * @return true if the caller is considered part of the current transaction, if any. 816 */ amIInTransaction()817 /* package */ synchronized boolean amIInTransaction() { 818 // always do this test on the main database connection - NOT on pooled database connection 819 // since transactions always occur on the main database connections only. 820 SQLiteDatabase db = (isPooledConnection()) ? mParentConnObj : this; 821 boolean b = (!db.inTransaction()) ? false : 822 db.mTransactionUsingExecSql || db.mLock.isHeldByCurrentThread(); 823 if (Log.isLoggable(TAG, Log.DEBUG)) { 824 Log.i(TAG, "amIinTransaction: " + b); 825 } 826 return b; 827 } 828 829 /** 830 * Checks if the database lock is held by this thread. 831 * 832 * @return true, if this thread is holding the database lock. 833 */ isDbLockedByCurrentThread()834 public boolean isDbLockedByCurrentThread() { 835 return mLock.isHeldByCurrentThread(); 836 } 837 838 /** 839 * Checks if the database is locked by another thread. This is 840 * just an estimate, since this status can change at any time, 841 * including after the call is made but before the result has 842 * been acted upon. 843 * 844 * @return true, if the database is locked by another thread 845 */ isDbLockedByOtherThreads()846 public boolean isDbLockedByOtherThreads() { 847 return !mLock.isHeldByCurrentThread() && mLock.isLocked(); 848 } 849 850 /** 851 * Temporarily end the transaction to let other threads run. The transaction is assumed to be 852 * successful so far. Do not call setTransactionSuccessful before calling this. When this 853 * returns a new transaction will have been created but not marked as successful. 854 * @return true if the transaction was yielded 855 * @deprecated if the db is locked more than once (becuase of nested transactions) then the lock 856 * will not be yielded. Use yieldIfContendedSafely instead. 857 */ 858 @Deprecated yieldIfContended()859 public boolean yieldIfContended() { 860 return yieldIfContendedHelper(false /* do not check yielding */, 861 -1 /* sleepAfterYieldDelay */); 862 } 863 864 /** 865 * Temporarily end the transaction to let other threads run. The transaction is assumed to be 866 * successful so far. Do not call setTransactionSuccessful before calling this. When this 867 * returns a new transaction will have been created but not marked as successful. This assumes 868 * that there are no nested transactions (beginTransaction has only been called once) and will 869 * throw an exception if that is not the case. 870 * @return true if the transaction was yielded 871 */ yieldIfContendedSafely()872 public boolean yieldIfContendedSafely() { 873 return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/); 874 } 875 876 /** 877 * Temporarily end the transaction to let other threads run. The transaction is assumed to be 878 * successful so far. Do not call setTransactionSuccessful before calling this. When this 879 * returns a new transaction will have been created but not marked as successful. This assumes 880 * that there are no nested transactions (beginTransaction has only been called once) and will 881 * throw an exception if that is not the case. 882 * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if 883 * the lock was actually yielded. This will allow other background threads to make some 884 * more progress than they would if we started the transaction immediately. 885 * @return true if the transaction was yielded 886 */ yieldIfContendedSafely(long sleepAfterYieldDelay)887 public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) { 888 return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay); 889 } 890 yieldIfContendedHelper(boolean checkFullyYielded, long sleepAfterYieldDelay)891 private boolean yieldIfContendedHelper(boolean checkFullyYielded, long sleepAfterYieldDelay) { 892 if (mLock.getQueueLength() == 0) { 893 // Reset the lock acquire time since we know that the thread was willing to yield 894 // the lock at this time. 895 mLockAcquiredWallTime = SystemClock.elapsedRealtime(); 896 mLockAcquiredThreadTime = Debug.threadCpuTimeNanos(); 897 return false; 898 } 899 setTransactionSuccessful(); 900 SQLiteTransactionListener transactionListener = mTransactionListener; 901 endTransaction(); 902 if (checkFullyYielded) { 903 if (this.isDbLockedByCurrentThread()) { 904 throw new IllegalStateException( 905 "Db locked more than once. yielfIfContended cannot yield"); 906 } 907 } 908 if (sleepAfterYieldDelay > 0) { 909 // Sleep for up to sleepAfterYieldDelay milliseconds, waking up periodically to 910 // check if anyone is using the database. If the database is not contended, 911 // retake the lock and return. 912 long remainingDelay = sleepAfterYieldDelay; 913 while (remainingDelay > 0) { 914 try { 915 Thread.sleep(remainingDelay < SLEEP_AFTER_YIELD_QUANTUM ? 916 remainingDelay : SLEEP_AFTER_YIELD_QUANTUM); 917 } catch (InterruptedException e) { 918 Thread.interrupted(); 919 } 920 remainingDelay -= SLEEP_AFTER_YIELD_QUANTUM; 921 if (mLock.getQueueLength() == 0) { 922 break; 923 } 924 } 925 } 926 beginTransactionWithListener(transactionListener); 927 return true; 928 } 929 930 /** 931 * @deprecated This method no longer serves any useful purpose and has been deprecated. 932 */ 933 @Deprecated 934 public Map<String, String> getSyncedTables() { 935 return new HashMap<String, String>(0); 936 } 937 938 /** 939 * Used to allow returning sub-classes of {@link Cursor} when calling query. 940 */ 941 public interface CursorFactory { 942 /** 943 * See 944 * {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}. 945 */ 946 public Cursor newCursor(SQLiteDatabase db, 947 SQLiteCursorDriver masterQuery, String editTable, 948 SQLiteQuery query); 949 } 950 951 /** 952 * Open the database according to the flags {@link #OPEN_READWRITE} 953 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}. 954 * 955 * <p>Sets the locale of the database to the the system's current locale. 956 * Call {@link #setLocale} if you would like something else.</p> 957 * 958 * @param path to database file to open and/or create 959 * @param factory an optional factory class that is called to instantiate a 960 * cursor when query is called, or null for default 961 * @param flags to control database access mode 962 * @return the newly opened database 963 * @throws SQLiteException if the database cannot be opened 964 */ 965 public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags) { 966 return openDatabase(path, factory, flags, new DefaultDatabaseErrorHandler()); 967 } 968 969 /** 970 * Open the database according to the flags {@link #OPEN_READWRITE} 971 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}. 972 * 973 * <p>Sets the locale of the database to the the system's current locale. 974 * Call {@link #setLocale} if you would like something else.</p> 975 * 976 * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be 977 * used to handle corruption when sqlite reports database corruption.</p> 978 * 979 * @param path to database file to open and/or create 980 * @param factory an optional factory class that is called to instantiate a 981 * cursor when query is called, or null for default 982 * @param flags to control database access mode 983 * @param errorHandler the {@link DatabaseErrorHandler} obj to be used to handle corruption 984 * when sqlite reports database corruption 985 * @return the newly opened database 986 * @throws SQLiteException if the database cannot be opened 987 */ 988 public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags, 989 DatabaseErrorHandler errorHandler) { 990 SQLiteDatabase sqliteDatabase = openDatabase(path, factory, flags, errorHandler, 991 (short) 0 /* the main connection handle */); 992 993 // set sqlite pagesize to mBlockSize 994 if (sBlockSize == 0) { 995 // TODO: "/data" should be a static final String constant somewhere. it is hardcoded 996 // in several places right now. 997 sBlockSize = new StatFs("/data").getBlockSize(); 998 } 999 sqliteDatabase.setPageSize(sBlockSize); 1000 sqliteDatabase.setJournalMode(path, "TRUNCATE"); 1001 1002 // add this database to the list of databases opened in this process 1003 synchronized(mActiveDatabases) { 1004 mActiveDatabases.add(new WeakReference<SQLiteDatabase>(sqliteDatabase)); 1005 } 1006 return sqliteDatabase; 1007 } 1008 1009 private static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags, 1010 DatabaseErrorHandler errorHandler, short connectionNum) { 1011 SQLiteDatabase db = new SQLiteDatabase(path, factory, flags, errorHandler, connectionNum); 1012 try { 1013 if (Log.isLoggable(TAG, Log.DEBUG)) { 1014 Log.i(TAG, "opening the db : " + path); 1015 } 1016 // Open the database. 1017 db.dbopen(path, flags); 1018 db.setLocale(Locale.getDefault()); 1019 if (SQLiteDebug.DEBUG_SQL_STATEMENTS) { 1020 db.enableSqlTracing(path, connectionNum); 1021 } 1022 if (SQLiteDebug.DEBUG_SQL_TIME) { 1023 db.enableSqlProfiling(path, connectionNum); 1024 } 1025 return db; 1026 } catch (SQLiteDatabaseCorruptException e) { 1027 db.mErrorHandler.onCorruption(db); 1028 return SQLiteDatabase.openDatabase(path, factory, flags, errorHandler); 1029 } catch (SQLiteException e) { 1030 Log.e(TAG, "Failed to open the database. closing it.", e); 1031 db.close(); 1032 throw e; 1033 } 1034 } 1035 1036 /** 1037 * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY). 1038 */ 1039 public static SQLiteDatabase openOrCreateDatabase(File file, CursorFactory factory) { 1040 return openOrCreateDatabase(file.getPath(), factory); 1041 } 1042 1043 /** 1044 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY). 1045 */ 1046 public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory) { 1047 return openDatabase(path, factory, CREATE_IF_NECESSARY); 1048 } 1049 1050 /** 1051 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler). 1052 */ 1053 public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory, 1054 DatabaseErrorHandler errorHandler) { 1055 return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler); 1056 } 1057 1058 private void setJournalMode(final String dbPath, final String mode) { 1059 // journal mode can be set only for non-memory databases 1060 // AND can't be set for readonly databases 1061 if (dbPath.equalsIgnoreCase(MEMORY_DB_PATH) || isReadOnly()) { 1062 return; 1063 } 1064 String s = DatabaseUtils.stringForQuery(this, "PRAGMA journal_mode=" + mode, null); 1065 if (!s.equalsIgnoreCase(mode)) { 1066 Log.e(TAG, "setting journal_mode to " + mode + " failed for db: " + dbPath + 1067 " (on pragma set journal_mode, sqlite returned:" + s); 1068 } 1069 } 1070 1071 /** 1072 * Create a memory backed SQLite database. Its contents will be destroyed 1073 * when the database is closed. 1074 * 1075 * <p>Sets the locale of the database to the the system's current locale. 1076 * Call {@link #setLocale} if you would like something else.</p> 1077 * 1078 * @param factory an optional factory class that is called to instantiate a 1079 * cursor when query is called 1080 * @return a SQLiteDatabase object, or null if the database can't be created 1081 */ 1082 public static SQLiteDatabase create(CursorFactory factory) { 1083 // This is a magic string with special meaning for SQLite. 1084 return openDatabase(MEMORY_DB_PATH, factory, CREATE_IF_NECESSARY); 1085 } 1086 1087 /** 1088 * Close the database. 1089 */ 1090 public void close() { 1091 if (!isOpen()) { 1092 return; 1093 } 1094 if (Log.isLoggable(TAG, Log.DEBUG)) { 1095 Log.i(TAG, "closing db: " + mPath + " (connection # " + mConnectionNum); 1096 } 1097 lock(); 1098 try { 1099 // some other thread could have closed this database while I was waiting for lock. 1100 // check the database state 1101 if (!isOpen()) { 1102 return; 1103 } 1104 closeClosable(); 1105 // finalize ALL statements queued up so far 1106 closePendingStatements(); 1107 releaseCustomFunctions(); 1108 // close this database instance - regardless of its reference count value 1109 closeDatabase(); 1110 if (mConnectionPool != null) { 1111 if (Log.isLoggable(TAG, Log.DEBUG)) { 1112 assert mConnectionPool != null; 1113 Log.i(TAG, mConnectionPool.toString()); 1114 } 1115 mConnectionPool.close(); 1116 } 1117 } finally { 1118 unlock(); 1119 } 1120 } 1121 1122 private void closeClosable() { 1123 /* deallocate all compiled SQL statement objects from mCompiledQueries cache. 1124 * this should be done before de-referencing all {@link SQLiteClosable} objects 1125 * from this database object because calling 1126 * {@link SQLiteClosable#onAllReferencesReleasedFromContainer()} could cause the database 1127 * to be closed. sqlite doesn't let a database close if there are 1128 * any unfinalized statements - such as the compiled-sql objects in mCompiledQueries. 1129 */ 1130 deallocCachedSqlStatements(); 1131 1132 Iterator<Map.Entry<SQLiteClosable, Object>> iter = mPrograms.entrySet().iterator(); 1133 while (iter.hasNext()) { 1134 Map.Entry<SQLiteClosable, Object> entry = iter.next(); 1135 SQLiteClosable program = entry.getKey(); 1136 if (program != null) { 1137 program.onAllReferencesReleasedFromContainer(); 1138 } 1139 } 1140 } 1141 1142 /** 1143 * package level access for testing purposes 1144 */ 1145 /* package */ void closeDatabase() throws SQLiteException { 1146 try { 1147 dbclose(); 1148 } catch (SQLiteUnfinalizedObjectsException e) { 1149 String msg = e.getMessage(); 1150 String[] tokens = msg.split(",", 2); 1151 int stmtId = Integer.parseInt(tokens[0]); 1152 // get extra info about this statement, if it is still to be released by closeClosable() 1153 Iterator<Map.Entry<SQLiteClosable, Object>> iter = mPrograms.entrySet().iterator(); 1154 boolean found = false; 1155 while (iter.hasNext()) { 1156 Map.Entry<SQLiteClosable, Object> entry = iter.next(); 1157 SQLiteClosable program = entry.getKey(); 1158 if (program != null && program instanceof SQLiteProgram) { 1159 SQLiteCompiledSql compiledSql = ((SQLiteProgram)program).mCompiledSql; 1160 if (compiledSql.nStatement == stmtId) { 1161 msg = compiledSql.toString(); 1162 found = true; 1163 } 1164 } 1165 } 1166 if (!found) { 1167 // the statement is already released by closeClosable(). is it waiting to be 1168 // finalized? 1169 if (mClosedStatementIds.contains(stmtId)) { 1170 Log.w(TAG, "this shouldn't happen. finalizing the statement now: "); 1171 closePendingStatements(); 1172 // try to close the database again 1173 closeDatabase(); 1174 } 1175 } else { 1176 // the statement is not yet closed. most probably programming error in the app. 1177 throw new SQLiteUnfinalizedObjectsException( 1178 "close() on database: " + getPath() + 1179 " failed due to un-close()d SQL statements: " + msg); 1180 } 1181 } 1182 } 1183 1184 /** 1185 * Native call to close the database. 1186 */ 1187 private native void dbclose(); 1188 1189 /** 1190 * A callback interface for a custom sqlite3 function. 1191 * This can be used to create a function that can be called from 1192 * sqlite3 database triggers. 1193 * @hide 1194 */ 1195 public interface CustomFunction { 1196 public void callback(String[] args); 1197 } 1198 1199 /** 1200 * Registers a CustomFunction callback as a function that can be called from 1201 * sqlite3 database triggers. 1202 * @param name the name of the sqlite3 function 1203 * @param numArgs the number of arguments for the function 1204 * @param function callback to call when the function is executed 1205 * @hide 1206 */ 1207 public void addCustomFunction(String name, int numArgs, CustomFunction function) { 1208 verifyDbIsOpen(); 1209 synchronized (mCustomFunctions) { 1210 int ref = native_addCustomFunction(name, numArgs, function); 1211 if (ref != 0) { 1212 // save a reference to the function for cleanup later 1213 mCustomFunctions.add(new Integer(ref)); 1214 } else { 1215 throw new SQLiteException("failed to add custom function " + name); 1216 } 1217 } 1218 } 1219 1220 private void releaseCustomFunctions() { 1221 synchronized (mCustomFunctions) { 1222 for (int i = 0; i < mCustomFunctions.size(); i++) { 1223 Integer function = mCustomFunctions.get(i); 1224 native_releaseCustomFunction(function.intValue()); 1225 } 1226 mCustomFunctions.clear(); 1227 } 1228 } 1229 1230 // list of CustomFunction references so we can clean up when the database closes 1231 private final ArrayList<Integer> mCustomFunctions = 1232 new ArrayList<Integer>(); 1233 1234 private native int native_addCustomFunction(String name, int numArgs, CustomFunction function); 1235 private native void native_releaseCustomFunction(int function); 1236 1237 /** 1238 * Gets the database version. 1239 * 1240 * @return the database version 1241 */ 1242 public int getVersion() { 1243 return ((Long) DatabaseUtils.longForQuery(this, "PRAGMA user_version;", null)).intValue(); 1244 } 1245 1246 /** 1247 * Sets the database version. 1248 * 1249 * @param version the new database version 1250 */ 1251 public void setVersion(int version) { 1252 execSQL("PRAGMA user_version = " + version); 1253 } 1254 1255 /** 1256 * Returns the maximum size the database may grow to. 1257 * 1258 * @return the new maximum database size 1259 */ 1260 public long getMaximumSize() { 1261 long pageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count;", null); 1262 return pageCount * getPageSize(); 1263 } 1264 1265 /** 1266 * Sets the maximum size the database will grow to. The maximum size cannot 1267 * be set below the current size. 1268 * 1269 * @param numBytes the maximum database size, in bytes 1270 * @return the new maximum database size 1271 */ 1272 public long setMaximumSize(long numBytes) { 1273 long pageSize = getPageSize(); 1274 long numPages = numBytes / pageSize; 1275 // If numBytes isn't a multiple of pageSize, bump up a page 1276 if ((numBytes % pageSize) != 0) { 1277 numPages++; 1278 } 1279 long newPageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count = " + numPages, 1280 null); 1281 return newPageCount * pageSize; 1282 } 1283 1284 /** 1285 * Returns the current database page size, in bytes. 1286 * 1287 * @return the database page size, in bytes 1288 */ 1289 public long getPageSize() { 1290 return DatabaseUtils.longForQuery(this, "PRAGMA page_size;", null); 1291 } 1292 1293 /** 1294 * Sets the database page size. The page size must be a power of two. This 1295 * method does not work if any data has been written to the database file, 1296 * and must be called right after the database has been created. 1297 * 1298 * @param numBytes the database page size, in bytes 1299 */ 1300 public void setPageSize(long numBytes) { 1301 execSQL("PRAGMA page_size = " + numBytes); 1302 } 1303 1304 /** 1305 * Mark this table as syncable. When an update occurs in this table the 1306 * _sync_dirty field will be set to ensure proper syncing operation. 1307 * 1308 * @param table the table to mark as syncable 1309 * @param deletedTable The deleted table that corresponds to the 1310 * syncable table 1311 * @deprecated This method no longer serves any useful purpose and has been deprecated. 1312 */ 1313 @Deprecated 1314 public void markTableSyncable(String table, String deletedTable) { 1315 } 1316 1317 /** 1318 * Mark this table as syncable, with the _sync_dirty residing in another 1319 * table. When an update occurs in this table the _sync_dirty field of the 1320 * row in updateTable with the _id in foreignKey will be set to 1321 * ensure proper syncing operation. 1322 * 1323 * @param table an update on this table will trigger a sync time removal 1324 * @param foreignKey this is the column in table whose value is an _id in 1325 * updateTable 1326 * @param updateTable this is the table that will have its _sync_dirty 1327 * @deprecated This method no longer serves any useful purpose and has been deprecated. 1328 */ 1329 @Deprecated 1330 public void markTableSyncable(String table, String foreignKey, String updateTable) { 1331 } 1332 1333 /** 1334 * Finds the name of the first table, which is editable. 1335 * 1336 * @param tables a list of tables 1337 * @return the first table listed 1338 */ 1339 public static String findEditTable(String tables) { 1340 if (!TextUtils.isEmpty(tables)) { 1341 // find the first word terminated by either a space or a comma 1342 int spacepos = tables.indexOf(' '); 1343 int commapos = tables.indexOf(','); 1344 1345 if (spacepos > 0 && (spacepos < commapos || commapos < 0)) { 1346 return tables.substring(0, spacepos); 1347 } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) { 1348 return tables.substring(0, commapos); 1349 } 1350 return tables; 1351 } else { 1352 throw new IllegalStateException("Invalid tables"); 1353 } 1354 } 1355 1356 /** 1357 * Compiles an SQL statement into a reusable pre-compiled statement object. 1358 * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the 1359 * statement and fill in those values with {@link SQLiteProgram#bindString} 1360 * and {@link SQLiteProgram#bindLong} each time you want to run the 1361 * statement. Statements may not return result sets larger than 1x1. 1362 *<p> 1363 * No two threads should be using the same {@link SQLiteStatement} at the same time. 1364 * 1365 * @param sql The raw SQL statement, may contain ? for unknown values to be 1366 * bound later. 1367 * @return A pre-compiled {@link SQLiteStatement} object. Note that 1368 * {@link SQLiteStatement}s are not synchronized, see the documentation for more details. 1369 */ 1370 public SQLiteStatement compileStatement(String sql) throws SQLException { 1371 verifyDbIsOpen(); 1372 return new SQLiteStatement(this, sql, null); 1373 } 1374 1375 /** 1376 * Query the given URL, returning a {@link Cursor} over the result set. 1377 * 1378 * @param distinct true if you want each row to be unique, false otherwise. 1379 * @param table The table name to compile the query against. 1380 * @param columns A list of which columns to return. Passing null will 1381 * return all columns, which is discouraged to prevent reading 1382 * data from storage that isn't going to be used. 1383 * @param selection A filter declaring which rows to return, formatted as an 1384 * SQL WHERE clause (excluding the WHERE itself). Passing null 1385 * will return all rows for the given table. 1386 * @param selectionArgs You may include ?s in selection, which will be 1387 * replaced by the values from selectionArgs, in order that they 1388 * appear in the selection. The values will be bound as Strings. 1389 * @param groupBy A filter declaring how to group rows, formatted as an SQL 1390 * GROUP BY clause (excluding the GROUP BY itself). Passing null 1391 * will cause the rows to not be grouped. 1392 * @param having A filter declare which row groups to include in the cursor, 1393 * if row grouping is being used, formatted as an SQL HAVING 1394 * clause (excluding the HAVING itself). Passing null will cause 1395 * all row groups to be included, and is required when row 1396 * grouping is not being used. 1397 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 1398 * (excluding the ORDER BY itself). Passing null will use the 1399 * default sort order, which may be unordered. 1400 * @param limit Limits the number of rows returned by the query, 1401 * formatted as LIMIT clause. Passing null denotes no LIMIT clause. 1402 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1403 * {@link Cursor}s are not synchronized, see the documentation for more details. 1404 * @see Cursor 1405 */ 1406 public Cursor query(boolean distinct, String table, String[] columns, 1407 String selection, String[] selectionArgs, String groupBy, 1408 String having, String orderBy, String limit) { 1409 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs, 1410 groupBy, having, orderBy, limit); 1411 } 1412 1413 /** 1414 * Query the given URL, returning a {@link Cursor} over the result set. 1415 * 1416 * @param cursorFactory the cursor factory to use, or null for the default factory 1417 * @param distinct true if you want each row to be unique, false otherwise. 1418 * @param table The table name to compile the query against. 1419 * @param columns A list of which columns to return. Passing null will 1420 * return all columns, which is discouraged to prevent reading 1421 * data from storage that isn't going to be used. 1422 * @param selection A filter declaring which rows to return, formatted as an 1423 * SQL WHERE clause (excluding the WHERE itself). Passing null 1424 * will return all rows for the given table. 1425 * @param selectionArgs You may include ?s in selection, which will be 1426 * replaced by the values from selectionArgs, in order that they 1427 * appear in the selection. The values will be bound as Strings. 1428 * @param groupBy A filter declaring how to group rows, formatted as an SQL 1429 * GROUP BY clause (excluding the GROUP BY itself). Passing null 1430 * will cause the rows to not be grouped. 1431 * @param having A filter declare which row groups to include in the cursor, 1432 * if row grouping is being used, formatted as an SQL HAVING 1433 * clause (excluding the HAVING itself). Passing null will cause 1434 * all row groups to be included, and is required when row 1435 * grouping is not being used. 1436 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 1437 * (excluding the ORDER BY itself). Passing null will use the 1438 * default sort order, which may be unordered. 1439 * @param limit Limits the number of rows returned by the query, 1440 * formatted as LIMIT clause. Passing null denotes no LIMIT clause. 1441 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1442 * {@link Cursor}s are not synchronized, see the documentation for more details. 1443 * @see Cursor 1444 */ 1445 public Cursor queryWithFactory(CursorFactory cursorFactory, 1446 boolean distinct, String table, String[] columns, 1447 String selection, String[] selectionArgs, String groupBy, 1448 String having, String orderBy, String limit) { 1449 verifyDbIsOpen(); 1450 String sql = SQLiteQueryBuilder.buildQueryString( 1451 distinct, table, columns, selection, groupBy, having, orderBy, limit); 1452 1453 return rawQueryWithFactory( 1454 cursorFactory, sql, selectionArgs, findEditTable(table)); 1455 } 1456 1457 /** 1458 * Query the given table, returning a {@link Cursor} over the result set. 1459 * 1460 * @param table The table name to compile the query against. 1461 * @param columns A list of which columns to return. Passing null will 1462 * return all columns, which is discouraged to prevent reading 1463 * data from storage that isn't going to be used. 1464 * @param selection A filter declaring which rows to return, formatted as an 1465 * SQL WHERE clause (excluding the WHERE itself). Passing null 1466 * will return all rows for the given table. 1467 * @param selectionArgs You may include ?s in selection, which will be 1468 * replaced by the values from selectionArgs, in order that they 1469 * appear in the selection. The values will be bound as Strings. 1470 * @param groupBy A filter declaring how to group rows, formatted as an SQL 1471 * GROUP BY clause (excluding the GROUP BY itself). Passing null 1472 * will cause the rows to not be grouped. 1473 * @param having A filter declare which row groups to include in the cursor, 1474 * if row grouping is being used, formatted as an SQL HAVING 1475 * clause (excluding the HAVING itself). Passing null will cause 1476 * all row groups to be included, and is required when row 1477 * grouping is not being used. 1478 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 1479 * (excluding the ORDER BY itself). Passing null will use the 1480 * default sort order, which may be unordered. 1481 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1482 * {@link Cursor}s are not synchronized, see the documentation for more details. 1483 * @see Cursor 1484 */ 1485 public Cursor query(String table, String[] columns, String selection, 1486 String[] selectionArgs, String groupBy, String having, 1487 String orderBy) { 1488 1489 return query(false, table, columns, selection, selectionArgs, groupBy, 1490 having, orderBy, null /* limit */); 1491 } 1492 1493 /** 1494 * Query the given table, returning a {@link Cursor} over the result set. 1495 * 1496 * @param table The table name to compile the query against. 1497 * @param columns A list of which columns to return. Passing null will 1498 * return all columns, which is discouraged to prevent reading 1499 * data from storage that isn't going to be used. 1500 * @param selection A filter declaring which rows to return, formatted as an 1501 * SQL WHERE clause (excluding the WHERE itself). Passing null 1502 * will return all rows for the given table. 1503 * @param selectionArgs You may include ?s in selection, which will be 1504 * replaced by the values from selectionArgs, in order that they 1505 * appear in the selection. The values will be bound as Strings. 1506 * @param groupBy A filter declaring how to group rows, formatted as an SQL 1507 * GROUP BY clause (excluding the GROUP BY itself). Passing null 1508 * will cause the rows to not be grouped. 1509 * @param having A filter declare which row groups to include in the cursor, 1510 * if row grouping is being used, formatted as an SQL HAVING 1511 * clause (excluding the HAVING itself). Passing null will cause 1512 * all row groups to be included, and is required when row 1513 * grouping is not being used. 1514 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 1515 * (excluding the ORDER BY itself). Passing null will use the 1516 * default sort order, which may be unordered. 1517 * @param limit Limits the number of rows returned by the query, 1518 * formatted as LIMIT clause. Passing null denotes no LIMIT clause. 1519 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1520 * {@link Cursor}s are not synchronized, see the documentation for more details. 1521 * @see Cursor 1522 */ 1523 public Cursor query(String table, String[] columns, String selection, 1524 String[] selectionArgs, String groupBy, String having, 1525 String orderBy, String limit) { 1526 1527 return query(false, table, columns, selection, selectionArgs, groupBy, 1528 having, orderBy, limit); 1529 } 1530 1531 /** 1532 * Runs the provided SQL and returns a {@link Cursor} over the result set. 1533 * 1534 * @param sql the SQL query. The SQL string must not be ; terminated 1535 * @param selectionArgs You may include ?s in where clause in the query, 1536 * which will be replaced by the values from selectionArgs. The 1537 * values will be bound as Strings. 1538 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1539 * {@link Cursor}s are not synchronized, see the documentation for more details. 1540 */ 1541 public Cursor rawQuery(String sql, String[] selectionArgs) { 1542 return rawQueryWithFactory(null, sql, selectionArgs, null); 1543 } 1544 1545 /** 1546 * Runs the provided SQL and returns a cursor over the result set. 1547 * 1548 * @param cursorFactory the cursor factory to use, or null for the default factory 1549 * @param sql the SQL query. The SQL string must not be ; terminated 1550 * @param selectionArgs You may include ?s in where clause in the query, 1551 * which will be replaced by the values from selectionArgs. The 1552 * values will be bound as Strings. 1553 * @param editTable the name of the first table, which is editable 1554 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1555 * {@link Cursor}s are not synchronized, see the documentation for more details. 1556 */ 1557 public Cursor rawQueryWithFactory( 1558 CursorFactory cursorFactory, String sql, String[] selectionArgs, 1559 String editTable) { 1560 verifyDbIsOpen(); 1561 BlockGuard.getThreadPolicy().onReadFromDisk(); 1562 long timeStart = 0; 1563 1564 if (false || mSlowQueryThreshold != -1) { 1565 timeStart = System.currentTimeMillis(); 1566 } 1567 1568 SQLiteDatabase db = getDbConnection(sql); 1569 SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(db, sql, editTable); 1570 1571 Cursor cursor = null; 1572 try { 1573 cursor = driver.query( 1574 cursorFactory != null ? cursorFactory : mFactory, 1575 selectionArgs); 1576 } finally { 1577 if (false || mSlowQueryThreshold != -1) { 1578 1579 // Force query execution 1580 int count = -1; 1581 if (cursor != null) { 1582 count = cursor.getCount(); 1583 } 1584 1585 long duration = System.currentTimeMillis() - timeStart; 1586 1587 if (false || duration >= mSlowQueryThreshold) { 1588 Log.v(SQLiteCursor.TAG, 1589 "query (" + duration + " ms): " + driver.toString() + ", args are " 1590 + (selectionArgs != null 1591 ? TextUtils.join(",", selectionArgs) 1592 : "<null>") + ", count is " + count); 1593 } 1594 } 1595 releaseDbConnection(db); 1596 } 1597 return cursor; 1598 } 1599 1600 /** 1601 * Convenience method for inserting a row into the database. 1602 * 1603 * @param table the table to insert the row into 1604 * @param nullColumnHack optional; may be <code>null</code>. 1605 * SQL doesn't allow inserting a completely empty row without 1606 * naming at least one column name. If your provided <code>values</code> is 1607 * empty, no column names are known and an empty row can't be inserted. 1608 * If not set to null, the <code>nullColumnHack</code> parameter 1609 * provides the name of nullable column name to explicitly insert a NULL into 1610 * in the case where your <code>values</code> is empty. 1611 * @param values this map contains the initial column values for the 1612 * row. The keys should be the column names and the values the 1613 * column values 1614 * @return the row ID of the newly inserted row, or -1 if an error occurred 1615 */ 1616 public long insert(String table, String nullColumnHack, ContentValues values) { 1617 try { 1618 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE); 1619 } catch (SQLException e) { 1620 Log.e(TAG, "Error inserting " + values, e); 1621 return -1; 1622 } 1623 } 1624 1625 /** 1626 * Convenience method for inserting a row into the database. 1627 * 1628 * @param table the table to insert the row into 1629 * @param nullColumnHack optional; may be <code>null</code>. 1630 * SQL doesn't allow inserting a completely empty row without 1631 * naming at least one column name. If your provided <code>values</code> is 1632 * empty, no column names are known and an empty row can't be inserted. 1633 * If not set to null, the <code>nullColumnHack</code> parameter 1634 * provides the name of nullable column name to explicitly insert a NULL into 1635 * in the case where your <code>values</code> is empty. 1636 * @param values this map contains the initial column values for the 1637 * row. The keys should be the column names and the values the 1638 * column values 1639 * @throws SQLException 1640 * @return the row ID of the newly inserted row, or -1 if an error occurred 1641 */ 1642 public long insertOrThrow(String table, String nullColumnHack, ContentValues values) 1643 throws SQLException { 1644 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE); 1645 } 1646 1647 /** 1648 * Convenience method for replacing a row in the database. 1649 * 1650 * @param table the table in which to replace the row 1651 * @param nullColumnHack optional; may be <code>null</code>. 1652 * SQL doesn't allow inserting a completely empty row without 1653 * naming at least one column name. If your provided <code>initialValues</code> is 1654 * empty, no column names are known and an empty row can't be inserted. 1655 * If not set to null, the <code>nullColumnHack</code> parameter 1656 * provides the name of nullable column name to explicitly insert a NULL into 1657 * in the case where your <code>initialValues</code> is empty. 1658 * @param initialValues this map contains the initial column values for 1659 * the row. 1660 * @return the row ID of the newly inserted row, or -1 if an error occurred 1661 */ 1662 public long replace(String table, String nullColumnHack, ContentValues initialValues) { 1663 try { 1664 return insertWithOnConflict(table, nullColumnHack, initialValues, 1665 CONFLICT_REPLACE); 1666 } catch (SQLException e) { 1667 Log.e(TAG, "Error inserting " + initialValues, e); 1668 return -1; 1669 } 1670 } 1671 1672 /** 1673 * Convenience method for replacing a row in the database. 1674 * 1675 * @param table the table in which to replace the row 1676 * @param nullColumnHack optional; may be <code>null</code>. 1677 * SQL doesn't allow inserting a completely empty row without 1678 * naming at least one column name. If your provided <code>initialValues</code> is 1679 * empty, no column names are known and an empty row can't be inserted. 1680 * If not set to null, the <code>nullColumnHack</code> parameter 1681 * provides the name of nullable column name to explicitly insert a NULL into 1682 * in the case where your <code>initialValues</code> is empty. 1683 * @param initialValues this map contains the initial column values for 1684 * the row. The key 1685 * @throws SQLException 1686 * @return the row ID of the newly inserted row, or -1 if an error occurred 1687 */ 1688 public long replaceOrThrow(String table, String nullColumnHack, 1689 ContentValues initialValues) throws SQLException { 1690 return insertWithOnConflict(table, nullColumnHack, initialValues, 1691 CONFLICT_REPLACE); 1692 } 1693 1694 /** 1695 * General method for inserting a row into the database. 1696 * 1697 * @param table the table to insert the row into 1698 * @param nullColumnHack optional; may be <code>null</code>. 1699 * SQL doesn't allow inserting a completely empty row without 1700 * naming at least one column name. If your provided <code>initialValues</code> is 1701 * empty, no column names are known and an empty row can't be inserted. 1702 * If not set to null, the <code>nullColumnHack</code> parameter 1703 * provides the name of nullable column name to explicitly insert a NULL into 1704 * in the case where your <code>initialValues</code> is empty. 1705 * @param initialValues this map contains the initial column values for the 1706 * row. The keys should be the column names and the values the 1707 * column values 1708 * @param conflictAlgorithm for insert conflict resolver 1709 * @return the row ID of the newly inserted row 1710 * OR the primary key of the existing row if the input param 'conflictAlgorithm' = 1711 * {@link #CONFLICT_IGNORE} 1712 * OR -1 if any error 1713 */ 1714 public long insertWithOnConflict(String table, String nullColumnHack, 1715 ContentValues initialValues, int conflictAlgorithm) { 1716 StringBuilder sql = new StringBuilder(); 1717 sql.append("INSERT"); 1718 sql.append(CONFLICT_VALUES[conflictAlgorithm]); 1719 sql.append(" INTO "); 1720 sql.append(table); 1721 sql.append('('); 1722 1723 Object[] bindArgs = null; 1724 int size = (initialValues != null && initialValues.size() > 0) ? initialValues.size() : 0; 1725 if (size > 0) { 1726 bindArgs = new Object[size]; 1727 int i = 0; 1728 for (String colName : initialValues.keySet()) { 1729 sql.append((i > 0) ? "," : ""); 1730 sql.append(colName); 1731 bindArgs[i++] = initialValues.get(colName); 1732 } 1733 sql.append(')'); 1734 sql.append(" VALUES ("); 1735 for (i = 0; i < size; i++) { 1736 sql.append((i > 0) ? ",?" : "?"); 1737 } 1738 } else { 1739 sql.append(nullColumnHack + ") VALUES (NULL"); 1740 } 1741 sql.append(')'); 1742 1743 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs); 1744 try { 1745 return statement.executeInsert(); 1746 } catch (SQLiteDatabaseCorruptException e) { 1747 onCorruption(); 1748 throw e; 1749 } finally { 1750 statement.close(); 1751 } 1752 } 1753 1754 /** 1755 * Convenience method for deleting rows in the database. 1756 * 1757 * @param table the table to delete from 1758 * @param whereClause the optional WHERE clause to apply when deleting. 1759 * Passing null will delete all rows. 1760 * @return the number of rows affected if a whereClause is passed in, 0 1761 * otherwise. To remove all rows and get a count pass "1" as the 1762 * whereClause. 1763 */ delete(String table, String whereClause, String[] whereArgs)1764 public int delete(String table, String whereClause, String[] whereArgs) { 1765 SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table + 1766 (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs); 1767 try { 1768 return statement.executeUpdateDelete(); 1769 } catch (SQLiteDatabaseCorruptException e) { 1770 onCorruption(); 1771 throw e; 1772 } finally { 1773 statement.close(); 1774 } 1775 } 1776 1777 /** 1778 * Convenience method for updating rows in the database. 1779 * 1780 * @param table the table to update in 1781 * @param values a map from column names to new column values. null is a 1782 * valid value that will be translated to NULL. 1783 * @param whereClause the optional WHERE clause to apply when updating. 1784 * Passing null will update all rows. 1785 * @return the number of rows affected 1786 */ update(String table, ContentValues values, String whereClause, String[] whereArgs)1787 public int update(String table, ContentValues values, String whereClause, String[] whereArgs) { 1788 return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE); 1789 } 1790 1791 /** 1792 * Convenience method for updating rows in the database. 1793 * 1794 * @param table the table to update in 1795 * @param values a map from column names to new column values. null is a 1796 * valid value that will be translated to NULL. 1797 * @param whereClause the optional WHERE clause to apply when updating. 1798 * Passing null will update all rows. 1799 * @param conflictAlgorithm for update conflict resolver 1800 * @return the number of rows affected 1801 */ updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, int conflictAlgorithm)1802 public int updateWithOnConflict(String table, ContentValues values, 1803 String whereClause, String[] whereArgs, int conflictAlgorithm) { 1804 if (values == null || values.size() == 0) { 1805 throw new IllegalArgumentException("Empty values"); 1806 } 1807 1808 StringBuilder sql = new StringBuilder(120); 1809 sql.append("UPDATE "); 1810 sql.append(CONFLICT_VALUES[conflictAlgorithm]); 1811 sql.append(table); 1812 sql.append(" SET "); 1813 1814 // move all bind args to one array 1815 int setValuesSize = values.size(); 1816 int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length); 1817 Object[] bindArgs = new Object[bindArgsSize]; 1818 int i = 0; 1819 for (String colName : values.keySet()) { 1820 sql.append((i > 0) ? "," : ""); 1821 sql.append(colName); 1822 bindArgs[i++] = values.get(colName); 1823 sql.append("=?"); 1824 } 1825 if (whereArgs != null) { 1826 for (i = setValuesSize; i < bindArgsSize; i++) { 1827 bindArgs[i] = whereArgs[i - setValuesSize]; 1828 } 1829 } 1830 if (!TextUtils.isEmpty(whereClause)) { 1831 sql.append(" WHERE "); 1832 sql.append(whereClause); 1833 } 1834 1835 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs); 1836 try { 1837 return statement.executeUpdateDelete(); 1838 } catch (SQLiteDatabaseCorruptException e) { 1839 onCorruption(); 1840 throw e; 1841 } finally { 1842 statement.close(); 1843 } 1844 } 1845 1846 /** 1847 * Execute a single SQL statement that is NOT a SELECT 1848 * or any other SQL statement that returns data. 1849 * <p> 1850 * It has no means to return any data (such as the number of affected rows). 1851 * Instead, you're encouraged to use {@link #insert(String, String, ContentValues)}, 1852 * {@link #update(String, ContentValues, String, String[])}, et al, when possible. 1853 * </p> 1854 * <p> 1855 * When using {@link #enableWriteAheadLogging()}, journal_mode is 1856 * automatically managed by this class. So, do not set journal_mode 1857 * using "PRAGMA journal_mode'<value>" statement if your app is using 1858 * {@link #enableWriteAheadLogging()} 1859 * </p> 1860 * 1861 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are 1862 * not supported. 1863 * @throws SQLException if the SQL string is invalid 1864 */ execSQL(String sql)1865 public void execSQL(String sql) throws SQLException { 1866 executeSql(sql, null); 1867 } 1868 1869 /** 1870 * Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE. 1871 * <p> 1872 * For INSERT statements, use any of the following instead. 1873 * <ul> 1874 * <li>{@link #insert(String, String, ContentValues)}</li> 1875 * <li>{@link #insertOrThrow(String, String, ContentValues)}</li> 1876 * <li>{@link #insertWithOnConflict(String, String, ContentValues, int)}</li> 1877 * </ul> 1878 * <p> 1879 * For UPDATE statements, use any of the following instead. 1880 * <ul> 1881 * <li>{@link #update(String, ContentValues, String, String[])}</li> 1882 * <li>{@link #updateWithOnConflict(String, ContentValues, String, String[], int)}</li> 1883 * </ul> 1884 * <p> 1885 * For DELETE statements, use any of the following instead. 1886 * <ul> 1887 * <li>{@link #delete(String, String, String[])}</li> 1888 * </ul> 1889 * <p> 1890 * For example, the following are good candidates for using this method: 1891 * <ul> 1892 * <li>ALTER TABLE</li> 1893 * <li>CREATE or DROP table / trigger / view / index / virtual table</li> 1894 * <li>REINDEX</li> 1895 * <li>RELEASE</li> 1896 * <li>SAVEPOINT</li> 1897 * <li>PRAGMA that returns no data</li> 1898 * </ul> 1899 * </p> 1900 * <p> 1901 * When using {@link #enableWriteAheadLogging()}, journal_mode is 1902 * automatically managed by this class. So, do not set journal_mode 1903 * using "PRAGMA journal_mode'<value>" statement if your app is using 1904 * {@link #enableWriteAheadLogging()} 1905 * </p> 1906 * 1907 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are 1908 * not supported. 1909 * @param bindArgs only byte[], String, Long and Double are supported in bindArgs. 1910 * @throws SQLException if the SQL string is invalid 1911 */ execSQL(String sql, Object[] bindArgs)1912 public void execSQL(String sql, Object[] bindArgs) throws SQLException { 1913 if (bindArgs == null) { 1914 throw new IllegalArgumentException("Empty bindArgs"); 1915 } 1916 executeSql(sql, bindArgs); 1917 } 1918 executeSql(String sql, Object[] bindArgs)1919 private int executeSql(String sql, Object[] bindArgs) throws SQLException { 1920 if (DatabaseUtils.getSqlStatementType(sql) == DatabaseUtils.STATEMENT_ATTACH) { 1921 disableWriteAheadLogging(); 1922 mHasAttachedDbs = true; 1923 } 1924 SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs); 1925 try { 1926 return statement.executeUpdateDelete(); 1927 } catch (SQLiteDatabaseCorruptException e) { 1928 onCorruption(); 1929 throw e; 1930 } finally { 1931 statement.close(); 1932 } 1933 } 1934 1935 @Override finalize()1936 protected void finalize() throws Throwable { 1937 try { 1938 if (isOpen()) { 1939 Log.e(TAG, "close() was never explicitly called on database '" + 1940 mPath + "' ", mStackTrace); 1941 closeClosable(); 1942 onAllReferencesReleased(); 1943 releaseCustomFunctions(); 1944 } 1945 } finally { 1946 super.finalize(); 1947 } 1948 } 1949 1950 /** 1951 * Private constructor. 1952 * 1953 * @param path The full path to the database 1954 * @param factory The factory to use when creating cursors, may be NULL. 1955 * @param flags 0 or {@link #NO_LOCALIZED_COLLATORS}. If the database file already 1956 * exists, mFlags will be updated appropriately. 1957 * @param errorHandler The {@link DatabaseErrorHandler} to be used when sqlite reports database 1958 * corruption. may be NULL. 1959 * @param connectionNum 0 for main database connection handle. 1..N for pooled database 1960 * connection handles. 1961 */ SQLiteDatabase(String path, CursorFactory factory, int flags, DatabaseErrorHandler errorHandler, short connectionNum)1962 private SQLiteDatabase(String path, CursorFactory factory, int flags, 1963 DatabaseErrorHandler errorHandler, short connectionNum) { 1964 if (path == null) { 1965 throw new IllegalArgumentException("path should not be null"); 1966 } 1967 setMaxSqlCacheSize(DEFAULT_SQL_CACHE_SIZE); 1968 mFlags = flags; 1969 mPath = path; 1970 mSlowQueryThreshold = SystemProperties.getInt(LOG_SLOW_QUERIES_PROPERTY, -1); 1971 mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace(); 1972 mFactory = factory; 1973 mPrograms = new WeakHashMap<SQLiteClosable,Object>(); 1974 // Set the DatabaseErrorHandler to be used when SQLite reports corruption. 1975 // If the caller sets errorHandler = null, then use default errorhandler. 1976 mErrorHandler = (errorHandler == null) ? new DefaultDatabaseErrorHandler() : errorHandler; 1977 mConnectionNum = connectionNum; 1978 /* sqlite soft heap limit http://www.sqlite.org/c3ref/soft_heap_limit64.html 1979 * set it to 4 times the default cursor window size. 1980 * TODO what is an appropriate value, considering the WAL feature which could burn 1981 * a lot of memory with many connections to the database. needs testing to figure out 1982 * optimal value for this. 1983 */ 1984 int limit = Resources.getSystem().getInteger( 1985 com.android.internal.R.integer.config_cursorWindowSize) * 1024 * 4; 1986 native_setSqliteSoftHeapLimit(limit); 1987 } 1988 1989 /** 1990 * return whether the DB is opened as read only. 1991 * @return true if DB is opened as read only 1992 */ isReadOnly()1993 public boolean isReadOnly() { 1994 return (mFlags & OPEN_READ_MASK) == OPEN_READONLY; 1995 } 1996 1997 /** 1998 * @return true if the DB is currently open (has not been closed) 1999 */ isOpen()2000 public boolean isOpen() { 2001 return mNativeHandle != 0; 2002 } 2003 needUpgrade(int newVersion)2004 public boolean needUpgrade(int newVersion) { 2005 return newVersion > getVersion(); 2006 } 2007 2008 /** 2009 * Getter for the path to the database file. 2010 * 2011 * @return the path to our database file. 2012 */ getPath()2013 public final String getPath() { 2014 return mPath; 2015 } 2016 logTimeStat(String sql, long beginMillis)2017 /* package */ void logTimeStat(String sql, long beginMillis) { 2018 if (ENABLE_DB_SAMPLE) { 2019 logTimeStat(sql, beginMillis, null); 2020 } 2021 } 2022 logTimeStat(String sql, long beginMillis, String prefix)2023 private void logTimeStat(String sql, long beginMillis, String prefix) { 2024 // Sample fast queries in proportion to the time taken. 2025 // Quantize the % first, so the logged sampling probability 2026 // exactly equals the actual sampling rate for this query. 2027 2028 int samplePercent; 2029 long durationMillis = SystemClock.uptimeMillis() - beginMillis; 2030 if (durationMillis == 0 && prefix == GET_LOCK_LOG_PREFIX) { 2031 // The common case is locks being uncontended. Don't log those, 2032 // even at 1%, which is our default below. 2033 return; 2034 } 2035 if (sQueryLogTimeInMillis == 0) { 2036 sQueryLogTimeInMillis = SystemProperties.getInt("db.db_operation.threshold_ms", 500); 2037 } 2038 if (durationMillis >= sQueryLogTimeInMillis) { 2039 samplePercent = 100; 2040 } else { 2041 samplePercent = (int) (100 * durationMillis / sQueryLogTimeInMillis) + 1; 2042 if (mRandom.nextInt(100) >= samplePercent) return; 2043 } 2044 2045 // Note: the prefix will be "COMMIT;" or "GETLOCK:" when non-null. We wait to do 2046 // it here so we avoid allocating in the common case. 2047 if (prefix != null) { 2048 sql = prefix + sql; 2049 } 2050 if (sql.length() > QUERY_LOG_SQL_LENGTH) sql = sql.substring(0, QUERY_LOG_SQL_LENGTH); 2051 2052 // ActivityThread.currentPackageName() only returns non-null if the 2053 // current thread is an application main thread. This parameter tells 2054 // us whether an event loop is blocked, and if so, which app it is. 2055 // 2056 // Sadly, there's no fast way to determine app name if this is *not* a 2057 // main thread, or when we are invoked via Binder (e.g. ContentProvider). 2058 // Hopefully the full path to the database will be informative enough. 2059 2060 String blockingPackage = AppGlobals.getInitialPackage(); 2061 if (blockingPackage == null) blockingPackage = ""; 2062 2063 EventLog.writeEvent( 2064 EVENT_DB_OPERATION, 2065 getPathForLogs(), 2066 sql, 2067 durationMillis, 2068 blockingPackage, 2069 samplePercent); 2070 } 2071 2072 /** 2073 * Removes email addresses from database filenames before they're 2074 * logged to the EventLog where otherwise apps could potentially 2075 * read them. 2076 */ getPathForLogs()2077 private String getPathForLogs() { 2078 if (mPathForLogs != null) { 2079 return mPathForLogs; 2080 } 2081 if (mPath == null) { 2082 return null; 2083 } 2084 if (mPath.indexOf('@') == -1) { 2085 mPathForLogs = mPath; 2086 } else { 2087 mPathForLogs = EMAIL_IN_DB_PATTERN.matcher(mPath).replaceAll("XX@YY"); 2088 } 2089 return mPathForLogs; 2090 } 2091 2092 /** 2093 * Sets the locale for this database. Does nothing if this database has 2094 * the NO_LOCALIZED_COLLATORS flag set or was opened read only. 2095 * @throws SQLException if the locale could not be set. The most common reason 2096 * for this is that there is no collator available for the locale you requested. 2097 * In this case the database remains unchanged. 2098 */ setLocale(Locale locale)2099 public void setLocale(Locale locale) { 2100 lock(); 2101 try { 2102 native_setLocale(locale.toString(), mFlags); 2103 } finally { 2104 unlock(); 2105 } 2106 } 2107 verifyDbIsOpen()2108 /* package */ void verifyDbIsOpen() { 2109 if (!isOpen()) { 2110 throw new IllegalStateException("database " + getPath() + " (conn# " + 2111 mConnectionNum + ") already closed"); 2112 } 2113 } 2114 verifyLockOwner()2115 /* package */ void verifyLockOwner() { 2116 verifyDbIsOpen(); 2117 if (mLockingEnabled && !isDbLockedByCurrentThread()) { 2118 throw new IllegalStateException("Don't have database lock!"); 2119 } 2120 } 2121 2122 /** 2123 * Adds the given SQL and its compiled-statement-id-returned-by-sqlite to the 2124 * cache of compiledQueries attached to 'this'. 2125 * <p> 2126 * If there is already a {@link SQLiteCompiledSql} in compiledQueries for the given SQL, 2127 * the new {@link SQLiteCompiledSql} object is NOT inserted into the cache (i.e.,the current 2128 * mapping is NOT replaced with the new mapping). 2129 */ addToCompiledQueries( String sql, SQLiteCompiledSql compiledStatement)2130 /* package */ synchronized void addToCompiledQueries( 2131 String sql, SQLiteCompiledSql compiledStatement) { 2132 // don't insert the new mapping if a mapping already exists 2133 if (mCompiledQueries.get(sql) != null) { 2134 return; 2135 } 2136 2137 int maxCacheSz = (mConnectionNum == 0) ? mCompiledQueries.maxSize() : 2138 mParentConnObj.mCompiledQueries.maxSize(); 2139 2140 if (SQLiteDebug.DEBUG_SQL_CACHE) { 2141 boolean printWarning = (mConnectionNum == 0) 2142 ? (!mCacheFullWarning && mCompiledQueries.size() == maxCacheSz) 2143 : (!mParentConnObj.mCacheFullWarning && 2144 mParentConnObj.mCompiledQueries.size() == maxCacheSz); 2145 if (printWarning) { 2146 /* 2147 * cache size is not enough for this app. log a warning. 2148 * chances are it is NOT using ? for bindargs - or cachesize is too small. 2149 */ 2150 Log.w(TAG, "Reached MAX size for compiled-sql statement cache for database " + 2151 getPath() + ". Use setMaxSqlCacheSize() to increase cachesize. "); 2152 mCacheFullWarning = true; 2153 Log.d(TAG, "Here are the SQL statements in Cache of database: " + mPath); 2154 for (String s : mCompiledQueries.snapshot().keySet()) { 2155 Log.d(TAG, "Sql statement in Cache: " + s); 2156 } 2157 } 2158 } 2159 /* add the given SQLiteCompiledSql compiledStatement to cache. 2160 * no need to worry about the cache size - because {@link #mCompiledQueries} 2161 * self-limits its size. 2162 */ 2163 mCompiledQueries.put(sql, compiledStatement); 2164 } 2165 2166 /** package-level access for testing purposes */ deallocCachedSqlStatements()2167 /* package */ synchronized void deallocCachedSqlStatements() { 2168 for (SQLiteCompiledSql compiledSql : mCompiledQueries.snapshot().values()) { 2169 compiledSql.releaseSqlStatement(); 2170 } 2171 mCompiledQueries.evictAll(); 2172 } 2173 2174 /** 2175 * From the compiledQueries cache, returns the compiled-statement-id for the given SQL. 2176 * Returns null, if not found in the cache. 2177 */ getCompiledStatementForSql(String sql)2178 /* package */ synchronized SQLiteCompiledSql getCompiledStatementForSql(String sql) { 2179 return mCompiledQueries.get(sql); 2180 } 2181 2182 /** 2183 * Sets the maximum size of the prepared-statement cache for this database. 2184 * (size of the cache = number of compiled-sql-statements stored in the cache). 2185 *<p> 2186 * Maximum cache size can ONLY be increased from its current size (default = 10). 2187 * If this method is called with smaller size than the current maximum value, 2188 * then IllegalStateException is thrown. 2189 *<p> 2190 * This method is thread-safe. 2191 * 2192 * @param cacheSize the size of the cache. can be (0 to {@link #MAX_SQL_CACHE_SIZE}) 2193 * @throws IllegalStateException if input cacheSize > {@link #MAX_SQL_CACHE_SIZE} or 2194 * the value set with previous setMaxSqlCacheSize() call. 2195 */ setMaxSqlCacheSize(int cacheSize)2196 public void setMaxSqlCacheSize(int cacheSize) { 2197 synchronized (this) { 2198 LruCache<String, SQLiteCompiledSql> oldCompiledQueries = mCompiledQueries; 2199 if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) { 2200 throw new IllegalStateException( 2201 "expected value between 0 and " + MAX_SQL_CACHE_SIZE); 2202 } else if (oldCompiledQueries != null && cacheSize < oldCompiledQueries.maxSize()) { 2203 throw new IllegalStateException("cannot set cacheSize to a value less than the " 2204 + "value set with previous setMaxSqlCacheSize() call."); 2205 } 2206 mCompiledQueries = new LruCache<String, SQLiteCompiledSql>(cacheSize) { 2207 @Override 2208 protected void entryRemoved(boolean evicted, String key, SQLiteCompiledSql oldValue, 2209 SQLiteCompiledSql newValue) { 2210 verifyLockOwner(); 2211 oldValue.releaseIfNotInUse(); 2212 } 2213 }; 2214 if (oldCompiledQueries != null) { 2215 for (Map.Entry<String, SQLiteCompiledSql> entry 2216 : oldCompiledQueries.snapshot().entrySet()) { 2217 mCompiledQueries.put(entry.getKey(), entry.getValue()); 2218 } 2219 } 2220 } 2221 } 2222 isInStatementCache(String sql)2223 /* package */ synchronized boolean isInStatementCache(String sql) { 2224 return mCompiledQueries.get(sql) != null; 2225 } 2226 releaseCompiledSqlObj( String sql, SQLiteCompiledSql compiledSql)2227 /* package */ synchronized void releaseCompiledSqlObj( 2228 String sql, SQLiteCompiledSql compiledSql) { 2229 if (mCompiledQueries.get(sql) == compiledSql) { 2230 // it is in cache - reset its inUse flag 2231 compiledSql.release(); 2232 } else { 2233 // it is NOT in cache. finalize it. 2234 compiledSql.releaseSqlStatement(); 2235 } 2236 } 2237 getCacheHitNum()2238 private synchronized int getCacheHitNum() { 2239 return mCompiledQueries.hitCount(); 2240 } 2241 getCacheMissNum()2242 private synchronized int getCacheMissNum() { 2243 return mCompiledQueries.missCount(); 2244 } 2245 getCachesize()2246 private synchronized int getCachesize() { 2247 return mCompiledQueries.size(); 2248 } 2249 finalizeStatementLater(int id)2250 /* package */ void finalizeStatementLater(int id) { 2251 if (!isOpen()) { 2252 // database already closed. this statement will already have been finalized. 2253 return; 2254 } 2255 synchronized(mClosedStatementIds) { 2256 if (mClosedStatementIds.contains(id)) { 2257 // this statement id is already queued up for finalization. 2258 return; 2259 } 2260 mClosedStatementIds.add(id); 2261 } 2262 } 2263 isInQueueOfStatementsToBeFinalized(int id)2264 /* package */ boolean isInQueueOfStatementsToBeFinalized(int id) { 2265 if (!isOpen()) { 2266 // database already closed. this statement will already have been finalized. 2267 // return true so that the caller doesn't have to worry about finalizing this statement. 2268 return true; 2269 } 2270 synchronized(mClosedStatementIds) { 2271 return mClosedStatementIds.contains(id); 2272 } 2273 } 2274 closePendingStatements()2275 /* package */ void closePendingStatements() { 2276 if (!isOpen()) { 2277 // since this database is already closed, no need to finalize anything. 2278 mClosedStatementIds.clear(); 2279 return; 2280 } 2281 verifyLockOwner(); 2282 /* to minimize synchronization on mClosedStatementIds, make a copy of the list */ 2283 ArrayList<Integer> list = new ArrayList<Integer>(mClosedStatementIds.size()); 2284 synchronized(mClosedStatementIds) { 2285 list.addAll(mClosedStatementIds); 2286 mClosedStatementIds.clear(); 2287 } 2288 // finalize all the statements from the copied list 2289 int size = list.size(); 2290 for (int i = 0; i < size; i++) { 2291 native_finalize(list.get(i)); 2292 } 2293 } 2294 2295 /** 2296 * for testing only 2297 */ getQueuedUpStmtList()2298 /* package */ ArrayList<Integer> getQueuedUpStmtList() { 2299 return mClosedStatementIds; 2300 } 2301 2302 /** 2303 * This method enables parallel execution of queries from multiple threads on the same database. 2304 * It does this by opening multiple handles to the database and using a different 2305 * database handle for each query. 2306 * <p> 2307 * If a transaction is in progress on one connection handle and say, a table is updated in the 2308 * transaction, then query on the same table on another connection handle will block for the 2309 * transaction to complete. But this method enables such queries to execute by having them 2310 * return old version of the data from the table. Most often it is the data that existed in the 2311 * table prior to the above transaction updates on that table. 2312 * <p> 2313 * Maximum number of simultaneous handles used to execute queries in parallel is 2314 * dependent upon the device memory and possibly other properties. 2315 * <p> 2316 * After calling this method, execution of queries in parallel is enabled as long as this 2317 * database handle is open. To disable execution of queries in parallel, database should 2318 * be closed and reopened. 2319 * <p> 2320 * If a query is part of a transaction, then it is executed on the same database handle the 2321 * transaction was begun. 2322 * <p> 2323 * If the database has any attached databases, then execution of queries in paralel is NOT 2324 * possible. In such cases, a message is printed to logcat and false is returned. 2325 * <p> 2326 * This feature is not available for :memory: databases. In such cases, 2327 * a message is printed to logcat and false is returned. 2328 * <p> 2329 * A typical way to use this method is the following: 2330 * <pre> 2331 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory, 2332 * CREATE_IF_NECESSARY, myDatabaseErrorHandler); 2333 * db.enableWriteAheadLogging(); 2334 * </pre> 2335 * <p> 2336 * Writers should use {@link #beginTransactionNonExclusive()} or 2337 * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)} 2338 * to start a trsnsaction. 2339 * Non-exclusive mode allows database file to be in readable by threads executing queries. 2340 * </p> 2341 * 2342 * @return true if write-ahead-logging is set. false otherwise 2343 */ enableWriteAheadLogging()2344 public boolean enableWriteAheadLogging() { 2345 // make sure the database is not READONLY. WAL doesn't make sense for readonly-databases. 2346 if (isReadOnly()) { 2347 return false; 2348 } 2349 // acquire lock - no that no other thread is enabling WAL at the same time 2350 lock(); 2351 try { 2352 if (mConnectionPool != null) { 2353 // already enabled 2354 return true; 2355 } 2356 if (mPath.equalsIgnoreCase(MEMORY_DB_PATH)) { 2357 Log.i(TAG, "can't enable WAL for memory databases."); 2358 return false; 2359 } 2360 2361 // make sure this database has NO attached databases because sqlite's write-ahead-logging 2362 // doesn't work for databases with attached databases 2363 if (mHasAttachedDbs) { 2364 if (Log.isLoggable(TAG, Log.DEBUG)) { 2365 Log.d(TAG, 2366 "this database: " + mPath + " has attached databases. can't enable WAL."); 2367 } 2368 return false; 2369 } 2370 mConnectionPool = new DatabaseConnectionPool(this); 2371 setJournalMode(mPath, "WAL"); 2372 return true; 2373 } finally { 2374 unlock(); 2375 } 2376 } 2377 2378 /** 2379 * This method disables the features enabled by {@link #enableWriteAheadLogging()}. 2380 * @hide 2381 */ disableWriteAheadLogging()2382 public void disableWriteAheadLogging() { 2383 // grab database lock so that writeAheadLogging is not disabled from 2 different threads 2384 // at the same time 2385 lock(); 2386 try { 2387 if (mConnectionPool == null) { 2388 return; // already disabled 2389 } 2390 mConnectionPool.close(); 2391 setJournalMode(mPath, "TRUNCATE"); 2392 mConnectionPool = null; 2393 } finally { 2394 unlock(); 2395 } 2396 } 2397 getDatabaseHandle(String sql)2398 /* package */ SQLiteDatabase getDatabaseHandle(String sql) { 2399 if (isPooledConnection()) { 2400 // this is a pooled database connection 2401 // use it if it is open AND if I am not currently part of a transaction 2402 if (isOpen() && !amIInTransaction()) { 2403 // TODO: use another connection from the pool 2404 // if this connection is currently in use by some other thread 2405 // AND if there are free connections in the pool 2406 return this; 2407 } else { 2408 // the pooled connection is not open! could have been closed either due 2409 // to corruption on this or some other connection to the database 2410 // OR, maybe the connection pool is disabled after this connection has been 2411 // allocated to me. try to get some other pooled or main database connection 2412 return getParentDbConnObj().getDbConnection(sql); 2413 } 2414 } else { 2415 // this is NOT a pooled connection. can we get one? 2416 return getDbConnection(sql); 2417 } 2418 } 2419 createPoolConnection(short connectionNum)2420 /* package */ SQLiteDatabase createPoolConnection(short connectionNum) { 2421 SQLiteDatabase db = openDatabase(mPath, mFactory, mFlags, mErrorHandler, connectionNum); 2422 db.mParentConnObj = this; 2423 return db; 2424 } 2425 getParentDbConnObj()2426 private synchronized SQLiteDatabase getParentDbConnObj() { 2427 return mParentConnObj; 2428 } 2429 isPooledConnection()2430 private boolean isPooledConnection() { 2431 return this.mConnectionNum > 0; 2432 } 2433 getDbConnection(String sql)2434 /* package */ SQLiteDatabase getDbConnection(String sql) { 2435 verifyDbIsOpen(); 2436 // this method should always be called with main database connection handle. 2437 // the only time when it is called with pooled database connection handle is 2438 // corruption occurs while trying to open a pooled database connection handle. 2439 // in that case, simply return 'this' handle 2440 if (isPooledConnection()) { 2441 return this; 2442 } 2443 2444 // use the current connection handle if 2445 // 1. if the caller is part of the ongoing transaction, if any 2446 // 2. OR, if there is NO connection handle pool setup 2447 if (amIInTransaction() || mConnectionPool == null) { 2448 return this; 2449 } else { 2450 // get a connection handle from the pool 2451 if (Log.isLoggable(TAG, Log.DEBUG)) { 2452 assert mConnectionPool != null; 2453 Log.i(TAG, mConnectionPool.toString()); 2454 } 2455 return mConnectionPool.get(sql); 2456 } 2457 } 2458 releaseDbConnection(SQLiteDatabase db)2459 private void releaseDbConnection(SQLiteDatabase db) { 2460 // ignore this release call if 2461 // 1. the database is closed 2462 // 2. OR, if db is NOT a pooled connection handle 2463 // 3. OR, if the database being released is same as 'this' (this condition means 2464 // that we should always be releasing a pooled connection handle by calling this method 2465 // from the 'main' connection handle 2466 if (!isOpen() || !db.isPooledConnection() || (db == this)) { 2467 return; 2468 } 2469 if (Log.isLoggable(TAG, Log.DEBUG)) { 2470 assert isPooledConnection(); 2471 assert mConnectionPool != null; 2472 Log.d(TAG, "releaseDbConnection threadid = " + Thread.currentThread().getId() + 2473 ", releasing # " + db.mConnectionNum + ", " + getPath()); 2474 } 2475 mConnectionPool.release(db); 2476 } 2477 2478 /** 2479 * this method is used to collect data about ALL open databases in the current process. 2480 * bugreport is a user of this data. 2481 */ getDbStats()2482 /* package */ static ArrayList<DbStats> getDbStats() { 2483 ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>(); 2484 // make a local copy of mActiveDatabases - so that this method is not competing 2485 // for synchronization lock on mActiveDatabases 2486 ArrayList<WeakReference<SQLiteDatabase>> tempList; 2487 synchronized(mActiveDatabases) { 2488 tempList = (ArrayList<WeakReference<SQLiteDatabase>>)mActiveDatabases.clone(); 2489 } 2490 for (WeakReference<SQLiteDatabase> w : tempList) { 2491 SQLiteDatabase db = w.get(); 2492 if (db == null || !db.isOpen()) { 2493 continue; 2494 } 2495 2496 try { 2497 // get SQLITE_DBSTATUS_LOOKASIDE_USED for the db 2498 int lookasideUsed = db.native_getDbLookaside(); 2499 2500 // get the lastnode of the dbname 2501 String path = db.getPath(); 2502 int indx = path.lastIndexOf("/"); 2503 String lastnode = path.substring((indx != -1) ? ++indx : 0); 2504 2505 // get list of attached dbs and for each db, get its size and pagesize 2506 List<Pair<String, String>> attachedDbs = db.getAttachedDbs(); 2507 if (attachedDbs == null) { 2508 continue; 2509 } 2510 for (int i = 0; i < attachedDbs.size(); i++) { 2511 Pair<String, String> p = attachedDbs.get(i); 2512 long pageCount = DatabaseUtils.longForQuery(db, "PRAGMA " + p.first 2513 + ".page_count;", null); 2514 2515 // first entry in the attached db list is always the main database 2516 // don't worry about prefixing the dbname with "main" 2517 String dbName; 2518 if (i == 0) { 2519 dbName = lastnode; 2520 } else { 2521 // lookaside is only relevant for the main db 2522 lookasideUsed = 0; 2523 dbName = " (attached) " + p.first; 2524 // if the attached db has a path, attach the lastnode from the path to above 2525 if (p.second.trim().length() > 0) { 2526 int idx = p.second.lastIndexOf("/"); 2527 dbName += " : " + p.second.substring((idx != -1) ? ++idx : 0); 2528 } 2529 } 2530 if (pageCount > 0) { 2531 dbStatsList.add(new DbStats(dbName, pageCount, db.getPageSize(), 2532 lookasideUsed, db.getCacheHitNum(), db.getCacheMissNum(), 2533 db.getCachesize())); 2534 } 2535 } 2536 // if there are pooled connections, return the cache stats for them also. 2537 // while we are trying to query the pooled connections for stats, some other thread 2538 // could be disabling conneciton pool. so, grab a reference to the connection pool. 2539 DatabaseConnectionPool connPool = db.mConnectionPool; 2540 if (connPool != null) { 2541 for (SQLiteDatabase pDb : connPool.getConnectionList()) { 2542 dbStatsList.add(new DbStats("(pooled # " + pDb.mConnectionNum + ") " 2543 + lastnode, 0, 0, 0, pDb.getCacheHitNum(), 2544 pDb.getCacheMissNum(), pDb.getCachesize())); 2545 } 2546 } 2547 } catch (SQLiteException e) { 2548 // ignore. we don't care about exceptions when we are taking adb 2549 // bugreport! 2550 } 2551 } 2552 return dbStatsList; 2553 } 2554 2555 /** 2556 * Returns list of full pathnames of all attached databases including the main database 2557 * by executing 'pragma database_list' on the database. 2558 * 2559 * @return ArrayList of pairs of (database name, database file path) or null if the database 2560 * is not open. 2561 */ getAttachedDbs()2562 public List<Pair<String, String>> getAttachedDbs() { 2563 if (!isOpen()) { 2564 return null; 2565 } 2566 ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>(); 2567 if (!mHasAttachedDbs) { 2568 // No attached databases. 2569 // There is a small window where attached databases exist but this flag is not set yet. 2570 // This can occur when this thread is in a race condition with another thread 2571 // that is executing the SQL statement: "attach database <blah> as <foo>" 2572 // If this thread is NOT ok with such a race condition (and thus possibly not receive 2573 // the entire list of attached databases), then the caller should ensure that no thread 2574 // is executing any SQL statements while a thread is calling this method. 2575 // Typically, this method is called when 'adb bugreport' is done or the caller wants to 2576 // collect stats on the database and all its attached databases. 2577 attachedDbs.add(new Pair<String, String>("main", mPath)); 2578 return attachedDbs; 2579 } 2580 // has attached databases. query sqlite to get the list of attached databases. 2581 Cursor c = null; 2582 try { 2583 c = rawQuery("pragma database_list;", null); 2584 while (c.moveToNext()) { 2585 // sqlite returns a row for each database in the returned list of databases. 2586 // in each row, 2587 // 1st column is the database name such as main, or the database 2588 // name specified on the "ATTACH" command 2589 // 2nd column is the database file path. 2590 attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2))); 2591 } 2592 } finally { 2593 if (c != null) { 2594 c.close(); 2595 } 2596 } 2597 return attachedDbs; 2598 } 2599 2600 /** 2601 * Runs 'pragma integrity_check' on the given database (and all the attached databases) 2602 * and returns true if the given database (and all its attached databases) pass integrity_check, 2603 * false otherwise. 2604 *<p> 2605 * If the result is false, then this method logs the errors reported by the integrity_check 2606 * command execution. 2607 *<p> 2608 * Note that 'pragma integrity_check' on a database can take a long time. 2609 * 2610 * @return true if the given database (and all its attached databases) pass integrity_check, 2611 * false otherwise. 2612 */ isDatabaseIntegrityOk()2613 public boolean isDatabaseIntegrityOk() { 2614 verifyDbIsOpen(); 2615 List<Pair<String, String>> attachedDbs = null; 2616 try { 2617 attachedDbs = getAttachedDbs(); 2618 if (attachedDbs == null) { 2619 throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " + 2620 "be retrieved. probably because the database is closed"); 2621 } 2622 } catch (SQLiteException e) { 2623 // can't get attachedDb list. do integrity check on the main database 2624 attachedDbs = new ArrayList<Pair<String, String>>(); 2625 attachedDbs.add(new Pair<String, String>("main", this.mPath)); 2626 } 2627 for (int i = 0; i < attachedDbs.size(); i++) { 2628 Pair<String, String> p = attachedDbs.get(i); 2629 SQLiteStatement prog = null; 2630 try { 2631 prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);"); 2632 String rslt = prog.simpleQueryForString(); 2633 if (!rslt.equalsIgnoreCase("ok")) { 2634 // integrity_checker failed on main or attached databases 2635 Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt); 2636 return false; 2637 } 2638 } finally { 2639 if (prog != null) prog.close(); 2640 } 2641 } 2642 return true; 2643 } 2644 2645 /** 2646 * Native call to open the database. 2647 * 2648 * @param path The full path to the database 2649 */ 2650 private native void dbopen(String path, int flags); 2651 2652 /** 2653 * Native call to setup tracing of all SQL statements 2654 * 2655 * @param path the full path to the database 2656 * @param connectionNum connection number: 0 - N, where the main database 2657 * connection handle is numbered 0 and the connection handles in the connection 2658 * pool are numbered 1..N. 2659 */ 2660 private native void enableSqlTracing(String path, short connectionNum); 2661 2662 /** 2663 * Native call to setup profiling of all SQL statements. 2664 * currently, sqlite's profiling = printing of execution-time 2665 * (wall-clock time) of each of the SQL statements, as they 2666 * are executed. 2667 * 2668 * @param path the full path to the database 2669 * @param connectionNum connection number: 0 - N, where the main database 2670 * connection handle is numbered 0 and the connection handles in the connection 2671 * pool are numbered 1..N. 2672 */ 2673 private native void enableSqlProfiling(String path, short connectionNum); 2674 2675 /** 2676 * Native call to set the locale. {@link #lock} must be held when calling 2677 * this method. 2678 * @throws SQLException 2679 */ 2680 private native void native_setLocale(String loc, int flags); 2681 2682 /** 2683 * return the SQLITE_DBSTATUS_LOOKASIDE_USED documented here 2684 * http://www.sqlite.org/c3ref/c_dbstatus_lookaside_used.html 2685 * @return int value of SQLITE_DBSTATUS_LOOKASIDE_USED 2686 */ 2687 private native int native_getDbLookaside(); 2688 2689 /** 2690 * finalizes the given statement id. 2691 * 2692 * @param statementId statement to be finzlied by sqlite 2693 */ 2694 private final native void native_finalize(int statementId); 2695 2696 /** 2697 * set sqlite soft heap limit 2698 * http://www.sqlite.org/c3ref/soft_heap_limit64.html 2699 */ 2700 private native void native_setSqliteSoftHeapLimit(int softHeapLimit); 2701 } 2702