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