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