1 /* 2 * Copyright (C) 2016 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 17 package androidx.sqlite.db; 18 19 import android.content.ContentValues; 20 import android.database.Cursor; 21 import android.database.SQLException; 22 import android.database.sqlite.SQLiteDatabase; 23 import android.database.sqlite.SQLiteTransactionListener; 24 import android.os.Build; 25 import android.os.CancellationSignal; 26 import android.os.OperationCanceledException; 27 import android.util.Pair; 28 29 import androidx.annotation.RequiresApi; 30 31 import java.io.Closeable; 32 import java.util.List; 33 import java.util.Locale; 34 35 /** 36 * A database abstraction which removes the framework dependency and allows swapping underlying 37 * sql versions. It mimics the behavior of {@link android.database.sqlite.SQLiteDatabase} 38 */ 39 @SuppressWarnings("unused") 40 public interface SupportSQLiteDatabase extends Closeable { 41 /** 42 * Compiles the given SQL statement. 43 * 44 * @param sql The sql query. 45 * @return Compiled statement. 46 */ compileStatement(String sql)47 SupportSQLiteStatement compileStatement(String sql); 48 49 /** 50 * Begins a transaction in EXCLUSIVE mode. 51 * <p> 52 * Transactions can be nested. 53 * When the outer transaction is ended all of 54 * the work done in that transaction and all of the nested transactions will be committed or 55 * rolled back. The changes will be rolled back if any transaction is ended without being 56 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed. 57 * </p> 58 * <p>Here is the standard idiom for transactions: 59 * 60 * <pre> 61 * db.beginTransaction(); 62 * try { 63 * ... 64 * db.setTransactionSuccessful(); 65 * } finally { 66 * db.endTransaction(); 67 * } 68 * </pre> 69 */ beginTransaction()70 void beginTransaction(); 71 72 /** 73 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When 74 * the outer transaction is ended all of the work done in that transaction 75 * and all of the nested transactions will be committed or rolled back. The 76 * changes will be rolled back if any transaction is ended without being 77 * marked as clean (by calling setTransactionSuccessful). Otherwise they 78 * will be committed. 79 * <p> 80 * Here is the standard idiom for transactions: 81 * 82 * <pre> 83 * db.beginTransactionNonExclusive(); 84 * try { 85 * ... 86 * db.setTransactionSuccessful(); 87 * } finally { 88 * db.endTransaction(); 89 * } 90 * </pre> 91 */ beginTransactionNonExclusive()92 void beginTransactionNonExclusive(); 93 94 /** 95 * Begins a transaction in EXCLUSIVE mode. 96 * <p> 97 * Transactions can be nested. 98 * When the outer transaction is ended all of 99 * the work done in that transaction and all of the nested transactions will be committed or 100 * rolled back. The changes will be rolled back if any transaction is ended without being 101 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed. 102 * </p> 103 * <p>Here is the standard idiom for transactions: 104 * 105 * <pre> 106 * db.beginTransactionWithListener(listener); 107 * try { 108 * ... 109 * db.setTransactionSuccessful(); 110 * } finally { 111 * db.endTransaction(); 112 * } 113 * </pre> 114 * 115 * @param transactionListener listener that should be notified when the transaction begins, 116 * commits, or is rolled back, either explicitly or by a call to 117 * {@link #yieldIfContendedSafely}. 118 */ beginTransactionWithListener(SQLiteTransactionListener transactionListener)119 void beginTransactionWithListener(SQLiteTransactionListener transactionListener); 120 121 /** 122 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When 123 * the outer transaction is ended all of the work done in that transaction 124 * and all of the nested transactions will be committed or rolled back. The 125 * changes will be rolled back if any transaction is ended without being 126 * marked as clean (by calling setTransactionSuccessful). Otherwise they 127 * will be committed. 128 * <p> 129 * Here is the standard idiom for transactions: 130 * 131 * <pre> 132 * db.beginTransactionWithListenerNonExclusive(listener); 133 * try { 134 * ... 135 * db.setTransactionSuccessful(); 136 * } finally { 137 * db.endTransaction(); 138 * } 139 * </pre> 140 * 141 * @param transactionListener listener that should be notified when the 142 * transaction begins, commits, or is rolled back, either 143 * explicitly or by a call to {@link #yieldIfContendedSafely}. 144 */ beginTransactionWithListenerNonExclusive(SQLiteTransactionListener transactionListener)145 void beginTransactionWithListenerNonExclusive(SQLiteTransactionListener transactionListener); 146 147 /** 148 * End a transaction. See beginTransaction for notes about how to use this and when transactions 149 * are committed and rolled back. 150 */ endTransaction()151 void endTransaction(); 152 153 /** 154 * Marks the current transaction as successful. Do not do any more database work between 155 * calling this and calling endTransaction. Do as little non-database work as possible in that 156 * situation too. If any errors are encountered between this and endTransaction the transaction 157 * will still be committed. 158 * 159 * @throws IllegalStateException if the current thread is not in a transaction or the 160 * transaction is already marked as successful. 161 */ setTransactionSuccessful()162 void setTransactionSuccessful(); 163 164 /** 165 * Returns true if the current thread has a transaction pending. 166 * 167 * @return True if the current thread is in a transaction. 168 */ inTransaction()169 boolean inTransaction(); 170 171 /** 172 * Returns true if the current thread is holding an active connection to the database. 173 * <p> 174 * The name of this method comes from a time when having an active connection 175 * to the database meant that the thread was holding an actual lock on the 176 * database. Nowadays, there is no longer a true "database lock" although threads 177 * may block if they cannot acquire a database connection to perform a 178 * particular operation. 179 * </p> 180 * 181 * @return True if the current thread is holding an active connection to the database. 182 */ isDbLockedByCurrentThread()183 boolean isDbLockedByCurrentThread(); 184 185 /** 186 * Temporarily end the transaction to let other threads run. The transaction is assumed to be 187 * successful so far. Do not call setTransactionSuccessful before calling this. When this 188 * returns a new transaction will have been created but not marked as successful. This assumes 189 * that there are no nested transactions (beginTransaction has only been called once) and will 190 * throw an exception if that is not the case. 191 * 192 * @return true if the transaction was yielded 193 */ yieldIfContendedSafely()194 boolean yieldIfContendedSafely(); 195 196 /** 197 * Temporarily end the transaction to let other threads run. The transaction is assumed to be 198 * successful so far. Do not call setTransactionSuccessful before calling this. When this 199 * returns a new transaction will have been created but not marked as successful. This assumes 200 * that there are no nested transactions (beginTransaction has only been called once) and will 201 * throw an exception if that is not the case. 202 * 203 * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if 204 * the lock was actually yielded. This will allow other background 205 * threads to make some 206 * more progress than they would if we started the transaction 207 * immediately. 208 * @return true if the transaction was yielded 209 */ yieldIfContendedSafely(long sleepAfterYieldDelay)210 boolean yieldIfContendedSafely(long sleepAfterYieldDelay); 211 212 /** 213 * Gets the database version. 214 * 215 * @return the database version 216 */ getVersion()217 int getVersion(); 218 219 /** 220 * Sets the database version. 221 * 222 * @param version the new database version 223 */ setVersion(int version)224 void setVersion(int version); 225 226 /** 227 * Returns the maximum size the database may grow to. 228 * 229 * @return the new maximum database size 230 */ getMaximumSize()231 long getMaximumSize(); 232 233 /** 234 * Sets the maximum size the database will grow to. The maximum size cannot 235 * be set below the current size. 236 * 237 * @param numBytes the maximum database size, in bytes 238 * @return the new maximum database size 239 */ setMaximumSize(long numBytes)240 long setMaximumSize(long numBytes); 241 242 /** 243 * Returns the current database page size, in bytes. 244 * 245 * @return the database page size, in bytes 246 */ getPageSize()247 long getPageSize(); 248 249 /** 250 * Sets the database page size. The page size must be a power of two. This 251 * method does not work if any data has been written to the database file, 252 * and must be called right after the database has been created. 253 * 254 * @param numBytes the database page size, in bytes 255 */ setPageSize(long numBytes)256 void setPageSize(long numBytes); 257 258 /** 259 * Runs the given query on the database. If you would like to have typed bind arguments, 260 * use {@link #query(SupportSQLiteQuery)}. 261 * 262 * @param query The SQL query that includes the query and can bind into a given compiled 263 * program. 264 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 265 * {@link Cursor}s are not synchronized, see the documentation for more details. 266 * @see #query(SupportSQLiteQuery) 267 */ query(String query)268 Cursor query(String query); 269 270 /** 271 * Runs the given query on the database. If you would like to have bind arguments, 272 * use {@link #query(SupportSQLiteQuery)}. 273 * 274 * @param query The SQL query that includes the query and can bind into a given compiled 275 * program. 276 * @param bindArgs The query arguments to bind. 277 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 278 * {@link Cursor}s are not synchronized, see the documentation for more details. 279 * @see #query(SupportSQLiteQuery) 280 */ query(String query, Object[] bindArgs)281 Cursor query(String query, Object[] bindArgs); 282 283 /** 284 * Runs the given query on the database. 285 * <p> 286 * This class allows using type safe sql program bindings while running queries. 287 * 288 * @param query The SQL query that includes the query and can bind into a given compiled 289 * program. 290 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 291 * {@link Cursor}s are not synchronized, see the documentation for more details. 292 * @see SimpleSQLiteQuery 293 */ query(SupportSQLiteQuery query)294 Cursor query(SupportSQLiteQuery query); 295 296 /** 297 * Runs the given query on the database. 298 * <p> 299 * This class allows using type safe sql program bindings while running queries. 300 * 301 * @param query The SQL query that includes the query and can bind into a given compiled 302 * program. 303 * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 304 * If the operation is canceled, then {@link OperationCanceledException} will be thrown 305 * when the query is executed. 306 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 307 * {@link Cursor}s are not synchronized, see the documentation for more details. 308 */ 309 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) query(SupportSQLiteQuery query, CancellationSignal cancellationSignal)310 Cursor query(SupportSQLiteQuery query, CancellationSignal cancellationSignal); 311 312 /** 313 * Convenience method for inserting a row into the database. 314 * 315 * @param table the table to insert the row into 316 * @param values this map contains the initial column values for the 317 * row. The keys should be the column names and the values the 318 * column values 319 * @param conflictAlgorithm for insert conflict resolver. One of 320 * {@link SQLiteDatabase#CONFLICT_NONE}, {@link SQLiteDatabase#CONFLICT_ROLLBACK}, 321 * {@link SQLiteDatabase#CONFLICT_ABORT}, {@link SQLiteDatabase#CONFLICT_FAIL}, 322 * {@link SQLiteDatabase#CONFLICT_IGNORE}, {@link SQLiteDatabase#CONFLICT_REPLACE}. 323 * @return the row ID of the newly inserted row, or -1 if an error occurred 324 * @throws SQLException If the insert fails 325 */ insert(String table, int conflictAlgorithm, ContentValues values)326 long insert(String table, int conflictAlgorithm, ContentValues values) throws SQLException; 327 328 /** 329 * Convenience method for deleting rows in the database. 330 * 331 * @param table the table to delete from 332 * @param whereClause the optional WHERE clause to apply when deleting. 333 * Passing null will delete all rows. 334 * @param whereArgs You may include ?s in the where clause, which 335 * will be replaced by the values from whereArgs. The values 336 * will be bound as Strings. 337 * @return the number of rows affected if a whereClause is passed in, 0 338 * otherwise. To remove all rows and get a count pass "1" as the 339 * whereClause. 340 */ delete(String table, String whereClause, Object[] whereArgs)341 int delete(String table, String whereClause, Object[] whereArgs); 342 343 /** 344 * Convenience method for updating rows in the database. 345 * 346 * @param table the table to update in 347 * @param conflictAlgorithm for update conflict resolver. One of 348 * {@link SQLiteDatabase#CONFLICT_NONE}, {@link SQLiteDatabase#CONFLICT_ROLLBACK}, 349 * {@link SQLiteDatabase#CONFLICT_ABORT}, {@link SQLiteDatabase#CONFLICT_FAIL}, 350 * {@link SQLiteDatabase#CONFLICT_IGNORE}, {@link SQLiteDatabase#CONFLICT_REPLACE}. 351 * @param values a map from column names to new column values. null is a 352 * valid value that will be translated to NULL. 353 * @param whereClause the optional WHERE clause to apply when updating. 354 * Passing null will update all rows. 355 * @param whereArgs You may include ?s in the where clause, which 356 * will be replaced by the values from whereArgs. The values 357 * will be bound as Strings. 358 * @return the number of rows affected 359 */ update(String table, int conflictAlgorithm, ContentValues values, String whereClause, Object[] whereArgs)360 int update(String table, int conflictAlgorithm, 361 ContentValues values, String whereClause, Object[] whereArgs); 362 363 /** 364 * Execute a single SQL statement that does not return any data. 365 * <p> 366 * When using {@link #enableWriteAheadLogging()}, journal_mode is 367 * automatically managed by this class. So, do not set journal_mode 368 * using "PRAGMA journal_mode'<value>" statement if your app is using 369 * {@link #enableWriteAheadLogging()} 370 * </p> 371 * 372 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are 373 * not supported. 374 * @throws SQLException if the SQL string is invalid 375 * @see #query(SupportSQLiteQuery) 376 */ execSQL(String sql)377 void execSQL(String sql) throws SQLException; 378 379 /** 380 * Execute a single SQL statement that does not return any data. 381 * <p> 382 * When using {@link #enableWriteAheadLogging()}, journal_mode is 383 * automatically managed by this class. So, do not set journal_mode 384 * using "PRAGMA journal_mode'<value>" statement if your app is using 385 * {@link #enableWriteAheadLogging()} 386 * </p> 387 * 388 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons 389 * are 390 * not supported. 391 * @param bindArgs only byte[], String, Long and Double are supported in selectionArgs. 392 * @throws SQLException if the SQL string is invalid 393 * @see #query(SupportSQLiteQuery) 394 */ execSQL(String sql, Object[] bindArgs)395 void execSQL(String sql, Object[] bindArgs) throws SQLException; 396 397 /** 398 * Returns true if the database is opened as read only. 399 * 400 * @return True if database is opened as read only. 401 */ isReadOnly()402 boolean isReadOnly(); 403 404 /** 405 * Returns true if the database is currently open. 406 * 407 * @return True if the database is currently open (has not been closed). 408 */ isOpen()409 boolean isOpen(); 410 411 /** 412 * Returns true if the new version code is greater than the current database version. 413 * 414 * @param newVersion The new version code. 415 * @return True if the new version code is greater than the current database version. 416 */ needUpgrade(int newVersion)417 boolean needUpgrade(int newVersion); 418 419 /** 420 * Gets the path to the database file. 421 * 422 * @return The path to the database file. 423 */ getPath()424 String getPath(); 425 426 /** 427 * Sets the locale for this database. Does nothing if this database has 428 * the {@link SQLiteDatabase#NO_LOCALIZED_COLLATORS} flag set or was opened read only. 429 * 430 * @param locale The new locale. 431 * @throws SQLException if the locale could not be set. The most common reason 432 * for this is that there is no collator available for the locale you 433 * requested. 434 * In this case the database remains unchanged. 435 */ setLocale(Locale locale)436 void setLocale(Locale locale); 437 438 /** 439 * Sets the maximum size of the prepared-statement cache for this database. 440 * (size of the cache = number of compiled-sql-statements stored in the cache). 441 * <p> 442 * Maximum cache size can ONLY be increased from its current size (default = 10). 443 * If this method is called with smaller size than the current maximum value, 444 * then IllegalStateException is thrown. 445 * <p> 446 * This method is thread-safe. 447 * 448 * @param cacheSize the size of the cache. can be (0 to 449 * {@link SQLiteDatabase#MAX_SQL_CACHE_SIZE}) 450 * @throws IllegalStateException if input cacheSize gt; 451 * {@link SQLiteDatabase#MAX_SQL_CACHE_SIZE}. 452 */ setMaxSqlCacheSize(int cacheSize)453 void setMaxSqlCacheSize(int cacheSize); 454 455 /** 456 * Sets whether foreign key constraints are enabled for the database. 457 * <p> 458 * By default, foreign key constraints are not enforced by the database. 459 * This method allows an application to enable foreign key constraints. 460 * It must be called each time the database is opened to ensure that foreign 461 * key constraints are enabled for the session. 462 * </p><p> 463 * A good time to call this method is right after calling {@code #openOrCreateDatabase} 464 * or in the {@link SupportSQLiteOpenHelper.Callback#onConfigure} callback. 465 * </p><p> 466 * When foreign key constraints are disabled, the database does not check whether 467 * changes to the database will violate foreign key constraints. Likewise, when 468 * foreign key constraints are disabled, the database will not execute cascade 469 * delete or update triggers. As a result, it is possible for the database 470 * state to become inconsistent. To perform a database integrity check, 471 * call {@link #isDatabaseIntegrityOk}. 472 * </p><p> 473 * This method must not be called while a transaction is in progress. 474 * </p><p> 475 * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a> 476 * for more details about foreign key constraint support. 477 * </p> 478 * 479 * @param enable True to enable foreign key constraints, false to disable them. 480 * @throws IllegalStateException if the are transactions is in progress 481 * when this method is called. 482 */ 483 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) setForeignKeyConstraintsEnabled(boolean enable)484 void setForeignKeyConstraintsEnabled(boolean enable); 485 486 /** 487 * This method enables parallel execution of queries from multiple threads on the 488 * same database. It does this by opening multiple connections to the database 489 * and using a different database connection for each query. The database 490 * journal mode is also changed to enable writes to proceed concurrently with reads. 491 * <p> 492 * When write-ahead logging is not enabled (the default), it is not possible for 493 * reads and writes to occur on the database at the same time. Before modifying the 494 * database, the writer implicitly acquires an exclusive lock on the database which 495 * prevents readers from accessing the database until the write is completed. 496 * </p><p> 497 * In contrast, when write-ahead logging is enabled (by calling this method), write 498 * operations occur in a separate log file which allows reads to proceed concurrently. 499 * While a write is in progress, readers on other threads will perceive the state 500 * of the database as it was before the write began. When the write completes, readers 501 * on other threads will then perceive the new state of the database. 502 * </p><p> 503 * It is a good idea to enable write-ahead logging whenever a database will be 504 * concurrently accessed and modified by multiple threads at the same time. 505 * However, write-ahead logging uses significantly more memory than ordinary 506 * journaling because there are multiple connections to the same database. 507 * So if a database will only be used by a single thread, or if optimizing 508 * concurrency is not very important, then write-ahead logging should be disabled. 509 * </p><p> 510 * After calling this method, execution of queries in parallel is enabled as long as 511 * the database remains open. To disable execution of queries in parallel, either 512 * call {@link #disableWriteAheadLogging} or close the database and reopen it. 513 * </p><p> 514 * The maximum number of connections used to execute queries in parallel is 515 * dependent upon the device memory and possibly other properties. 516 * </p><p> 517 * If a query is part of a transaction, then it is executed on the same database handle the 518 * transaction was begun. 519 * </p><p> 520 * Writers should use {@link #beginTransactionNonExclusive()} or 521 * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)} 522 * to start a transaction. Non-exclusive mode allows database file to be in readable 523 * by other threads executing queries. 524 * </p><p> 525 * If the database has any attached databases, then execution of queries in parallel is NOT 526 * possible. Likewise, write-ahead logging is not supported for read-only databases 527 * or memory databases. In such cases, {@code enableWriteAheadLogging} returns false. 528 * </p><p> 529 * The best way to enable write-ahead logging is to pass the 530 * {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag to 531 * {@link SQLiteDatabase#openDatabase}. This is more efficient than calling 532 * <code><pre> 533 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory, 534 * SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING, 535 * myDatabaseErrorHandler); 536 * db.enableWriteAheadLogging(); 537 * </pre></code> 538 * </p><p> 539 * Another way to enable write-ahead logging is to call {@code enableWriteAheadLogging} 540 * after opening the database. 541 * <code><pre> 542 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory, 543 * SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler); 544 * db.enableWriteAheadLogging(); 545 * </pre></code> 546 * </p><p> 547 * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for 548 * more details about how write-ahead logging works. 549 * </p> 550 * 551 * @return True if write-ahead logging is enabled. 552 * @throws IllegalStateException if there are transactions in progress at the 553 * time this method is called. WAL mode can only be changed when 554 * there are no 555 * transactions in progress. 556 * @see SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING 557 * @see #disableWriteAheadLogging 558 */ enableWriteAheadLogging()559 boolean enableWriteAheadLogging(); 560 561 /** 562 * This method disables the features enabled by {@link #enableWriteAheadLogging()}. 563 * 564 * @throws IllegalStateException if there are transactions in progress at the 565 * time this method is called. WAL mode can only be changed when 566 * there are no 567 * transactions in progress. 568 * @see #enableWriteAheadLogging 569 */ 570 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) disableWriteAheadLogging()571 void disableWriteAheadLogging(); 572 573 /** 574 * Returns true if write-ahead logging has been enabled for this database. 575 * 576 * @return True if write-ahead logging has been enabled for this database. 577 * @see #enableWriteAheadLogging 578 * @see SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING 579 */ 580 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) isWriteAheadLoggingEnabled()581 boolean isWriteAheadLoggingEnabled(); 582 583 /** 584 * Returns list of full path names of all attached databases including the main database 585 * by executing 'pragma database_list' on the database. 586 * 587 * @return ArrayList of pairs of (database name, database file path) or null if the database 588 * is not open. 589 */ getAttachedDbs()590 List<Pair<String, String>> getAttachedDbs(); 591 592 /** 593 * Runs 'pragma integrity_check' on the given database (and all the attached databases) 594 * and returns true if the given database (and all its attached databases) pass integrity_check, 595 * false otherwise. 596 * <p> 597 * If the result is false, then this method logs the errors reported by the integrity_check 598 * command execution. 599 * <p> 600 * Note that 'pragma integrity_check' on a database can take a long time. 601 * 602 * @return true if the given database (and all its attached databases) pass integrity_check, 603 * false otherwise. 604 */ isDatabaseIntegrityOk()605 boolean isDatabaseIntegrityOk(); 606 } 607