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