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