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