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