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