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