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