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