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