SQLiteDatabase.java revision f8a7ceaef2e7d5cd530c9426bde91b6fa9a40b75
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.database.sqlite; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentValues; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.DatabaseUtils; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.SQLException; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Debug; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Config; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.EventLog; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Iterator; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Locale; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.WeakHashMap; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.concurrent.locks.ReentrantLock; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Exposes methods to manage a SQLite database. 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>SQLiteDatabase has methods to create, delete, execute SQL commands, and 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * perform other common database management tasks. 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>See the Notepad sample application in the SDK for an example of creating 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and managing a database. 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> Database names must be unique within an application, not across all 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * applications. 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Localized Collation - ORDER BY</h3> 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>In addition to SQLite's default <code>BINARY</code> collator, Android supplies 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * two more, <code>LOCALIZED</code>, which changes with the system's current locale 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if you wire it up correctly (XXX a link needed!), and <code>UNICODE</code>, which 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is the Unicode Collation Algorithm and not tailored to the current locale. 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SQLiteDatabase extends SQLiteClosable { 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "Database"; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int DB_OPERATION_EVENT = 52000; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Algorithms used in ON CONFLICT clause 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.sqlite.org/lang_conflict.html 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public enum ConflictAlgorithm { 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When a constraint violation occurs, an immediate ROLLBACK occurs, 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * thus ending the current transaction, and the command aborts with a 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * return code of SQLITE_CONSTRAINT. If no transaction is active 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (other than the implied transaction that is created on every command) 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * then this algorithm works the same as ABORT. 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ROLLBACK("ROLLBACK"), 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When a constraint violation occurs,no ROLLBACK is executed 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * so changes from prior commands within the same transaction 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * are preserved. This is the default behavior. 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ABORT("ABORT"), 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When a constraint violation occurs, the command aborts with a return 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * code SQLITE_CONSTRAINT. But any changes to the database that 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the command made prior to encountering the constraint violation 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * are preserved and are not backed out. 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FAIL("FAIL"), 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When a constraint violation occurs, the one row that contains 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the constraint violation is not inserted or changed. 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * But the command continues executing normally. Other rows before and 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * after the row that contained the constraint violation continue to be 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * inserted or updated normally. No error is returned. 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IGNORE("IGNORE"), 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When a UNIQUE constraint violation occurs, the pre-existing rows that 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * are causing the constraint violation are removed prior to inserting 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or updating the current row. Thus the insert or update always occurs. 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The command continues executing normally. No error is returned. 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If a NOT NULL constraint violation occurs, the NULL value is replaced 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by the default value for that column. If the column has no default 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value, then the ABORT algorithm is used. If a CHECK constraint 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * violation occurs then the IGNORE algorithm is used. When this conflict 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * resolution strategy deletes rows in order to satisfy a constraint, 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it does not invoke delete triggers on those rows. 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This behavior might change in a future release. 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project REPLACE("REPLACE"); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final String mValue; 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ConflictAlgorithm(String value) { 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mValue = value; 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String value() { 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mValue; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Maximum Length Of A LIKE Or GLOB Pattern 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The pattern matching algorithm used in the default LIKE and GLOB implementation 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of SQLite can exhibit O(N^2) performance (where N is the number of characters in 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the pattern) for certain pathological cases. To avoid denial-of-service attacks 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes. 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The default value of this limit is 50000. A modern workstation can evaluate 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly. 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The denial of service problem only comes into play when the pattern length gets 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * are at most a few dozen bytes in length, paranoid application developers may 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * want to reduce this parameter to something in the range of a few hundred 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if they know that external users are able to generate arbitrary patterns. 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Flag for {@link #openDatabase} to open the database for reading and writing. 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If the disk is full, this may fail even before you actually write anything. 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@more} Note that the value of this flag is 0, so it is the default. 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int OPEN_READWRITE = 0x00000000; // update native code if changing 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Flag for {@link #openDatabase} to open the database for reading only. 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is the only reliable way to open a database if the disk may be full. 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int OPEN_READONLY = 0x00000001; // update native code if changing 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Flag for {@link #openDatabase} to open the database without support for localized collators. 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@more} This causes the collator <code>LOCALIZED</code> not to be created. 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You must be consistent when using this flag to use the setting the database was 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * created with. If this is set, {@link #setLocale} will do nothing. 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Flag for {@link #openDatabase} to create the database file if it does not already exist. 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Indicates whether the most-recently started transaction has been marked as successful. 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mInnerTransactionIsSuccessful; 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Valid during the life of a transaction, and indicates whether the entire transaction (the 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * outer one and all of the inner ones) so far has been successful. 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mTransactionIsSuccessful; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Synchronize on this when accessing the database */ 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final ReentrantLock mLock = new ReentrantLock(true); 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private long mLockAcquiredWallTime = 0L; 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private long mLockAcquiredThreadTime = 0L; 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // limit the frequency of complaints about each database to one within 20 sec 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // unless run command adb shell setprop log.tag.Database VERBOSE 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LOCK_WARNING_WINDOW_IN_MS = 20000; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If the lock is held this long then a warning will be printed when it is released. */ 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS = 300; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS = 100; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT = 2000; 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private long mLastLockMessageTime = 0L; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Used by native code, do not rename */ 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ int mNativeHandle = 0; 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Used to make temp table names unique */ 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ int mTempTableSequence = 0; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The path for the database file */ 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mPath; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The flags passed to open/create */ 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mFlags; 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The optional factory to use when creating new Cursors */ 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private CursorFactory mFactory; 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private WeakHashMap<SQLiteClosable, Object> mPrograms; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final RuntimeException mLeakedException; 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // package visible, since callers will access directly to minimize overhead in the case 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // that logging is not enabled. 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ final boolean mLogStats; 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param closable 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void addSQLiteClosable(SQLiteClosable closable) { 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPrograms.put(closable, null); 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void removeSQLiteClosable(SQLiteClosable closable) { 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPrograms.remove(closable); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onAllReferencesReleased() { 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isOpen()) { 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dbclose(); 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Attempts to release memory that SQLite holds but does not require to 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * operate properly. Typically this memory will come from the page cache. 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the number of bytes actually released 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static public native int releaseMemory(); 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Control whether or not the SQLiteDatabase is made thread-safe by using locks 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * around critical sections. This is pretty expensive, so if you know that your 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * DB will only be used by a single thread then you should set this to false. 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The default is true. 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param lockingEnabled set to true to enable locks, false otherwise 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setLockingEnabled(boolean lockingEnabled) { 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLockingEnabled = lockingEnabled; 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If set then the SQLiteDatabase is made thread-safe by using locks 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * around critical sections 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mLockingEnabled = true; 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ void onCorruption() { 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Close the database (if we can), which will cause subsequent operations to fail. 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(); 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Removing corrupt database: " + mPath); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Delete the corrupt file. Don't re-create it now -- that would just confuse people 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // -- but the next time someone tries to open it, they can set it up from scratch. 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new File(mPath).delete(); 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Locks the database for exclusive access. The database lock must be held when 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * touch the native sqlite3* object since it is single threaded and uses 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a polling lock contention algorithm. The lock is recursive, and may be acquired 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * multiple times by the same thread. This is a no-op if mLockingEnabled is false. 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #unlock() 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ void lock() { 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mLockingEnabled) return; 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLock.lock(); 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) { 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mLock.getHoldCount() == 1) { 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Use elapsed real-time since the CPU may sleep when waiting for IO 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLockAcquiredWallTime = SystemClock.elapsedRealtime(); 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLockAcquiredThreadTime = Debug.threadCpuTimeNanos(); 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Locks the database for exclusive access. The database lock must be held when 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * touch the native sqlite3* object since it is single threaded and uses 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a polling lock contention algorithm. The lock is recursive, and may be acquired 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * multiple times by the same thread. 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #unlockForced() 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void lockForced() { 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLock.lock(); 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) { 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mLock.getHoldCount() == 1) { 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Use elapsed real-time since the CPU may sleep when waiting for IO 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLockAcquiredWallTime = SystemClock.elapsedRealtime(); 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLockAcquiredThreadTime = Debug.threadCpuTimeNanos(); 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Releases the database lock. This is a no-op if mLockingEnabled is false. 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #unlock() 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ void unlock() { 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mLockingEnabled) return; 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) { 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mLock.getHoldCount() == 1) { 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkLockHoldTime(); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLock.unlock(); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Releases the database lock. 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #unlockForced() 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void unlockForced() { 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mLock.getHoldCount() == 1) { 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkLockHoldTime(); 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLock.unlock(); 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void checkLockHoldTime() { 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Use elapsed real-time since the CPU may sleep when waiting for IO 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long elapsedTime = SystemClock.elapsedRealtime(); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long lockedTime = elapsedTime - mLockAcquiredWallTime; 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lockedTime < LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT && 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project !Log.isLoggable(TAG, Log.VERBOSE) && 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (elapsedTime - mLastLockMessageTime) < LOCK_WARNING_WINDOW_IN_MS) { 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lockedTime > LOCK_ACQUIRED_WARNING_TIME_IN_MS) { 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int threadTime = (int) 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((Debug.threadCpuTimeNanos() - mLockAcquiredThreadTime) / 1000000); 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (threadTime > LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS || 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lockedTime > LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT) { 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLastLockMessageTime = elapsedTime; 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String msg = "lock held on " + mPath + " for " + lockedTime + "ms. Thread time was " 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + threadTime + "ms"; 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING_STACK_TRACE) { 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, msg, new Exception()); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, msg); 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Begins a transaction. Transactions can be nested. When the outer transaction is ended all of 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the work done in that transaction and all of the nested transactions will be committed or 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * rolled back. The changes will be rolled back if any transaction is ended without being 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed. 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Here is the standard idiom for transactions: 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * db.beginTransaction(); 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * try { 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ... 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * db.setTransactionSuccessful(); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * } finally { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * db.endTransaction(); 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * } 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void beginTransaction() { 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lockForced(); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean ok = false; 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If this thread already had the lock then get out 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mLock.getHoldCount() > 1) { 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mInnerTransactionIsSuccessful) { 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String msg = "Cannot call beginTransaction between " 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + "calling setTransactionSuccessful and endTransaction"; 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IllegalStateException e = new IllegalStateException(msg); 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "beginTransaction() failed", e); 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw e; 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ok = true; 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This thread didn't already have the lock, so begin a database 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // transaction now. 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project execSQL("BEGIN EXCLUSIVE;"); 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTransactionIsSuccessful = true; 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInnerTransactionIsSuccessful = false; 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ok = true; 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!ok) { 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // beginTransaction is called before the try block so we must release the lock in 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the case of failure. 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlockForced(); 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * End a transaction. See beginTransaction for notes about how to use this and when transactions 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * are committed and rolled back. 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void endTransaction() { 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mLock.isHeldByCurrentThread()) { 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("no transaction pending"); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mInnerTransactionIsSuccessful) { 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInnerTransactionIsSuccessful = false; 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTransactionIsSuccessful = false; 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mLock.getHoldCount() != 1) { 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mTransactionIsSuccessful) { 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project execSQL("COMMIT;"); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project execSQL("ROLLBACK;"); 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SQLException e) { 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGD) { 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, "exception during rollback, maybe the DB previously " 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + "performed an auto-rollback"); 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlockForced(); 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGV) { 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, "unlocked " + Thread.currentThread() 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", holdCount is " + mLock.getHoldCount()); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Marks the current transaction as successful. Do not do any more database work between 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * calling this and calling endTransaction. Do as little non-database work as possible in that 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * situation too. If any errors are encountered between this and endTransaction the transaction 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will still be committed. 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IllegalStateException if the current thread is not in a transaction or the 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * transaction is already marked as successful. 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setTransactionSuccessful() { 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mLock.isHeldByCurrentThread()) { 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("no transaction pending"); 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mInnerTransactionIsSuccessful) { 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException( 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "setTransactionSuccessful may only be called once per call to beginTransaction"); 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInnerTransactionIsSuccessful = true; 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * return true if there is a transaction pending 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean inTransaction() { 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mLock.getHoldCount() > 0; 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Checks if the database lock is held by this thread. 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true, if this thread is holding the database lock. 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isDbLockedByCurrentThread() { 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mLock.isHeldByCurrentThread(); 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Checks if the database is locked by another thread. This is 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * just an estimate, since this status can change at any time, 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * including after the call is made but before the result has 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * been acted upon. 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true, if the database is locked by another thread 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isDbLockedByOtherThreads() { 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return !mLock.isHeldByCurrentThread() && mLock.isLocked(); 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Temporarily end the transaction to let other threads run. The transaction is assumed to be 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * successful so far. Do not call setTransactionSuccessful before calling this. When this 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * returns a new transaction will have been created but not marked as successful. 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the transaction was yielded 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @deprecated if the db is locked more than once (becuase of nested transactions) then the lock 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will not be yielded. Use yieldIfContendedSafely instead. 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean yieldIfContended() { 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return yieldIfContendedHelper(false /* do not check yielding */); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Temporarily end the transaction to let other threads run. The transaction is assumed to be 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * successful so far. Do not call setTransactionSuccessful before calling this. When this 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * returns a new transaction will have been created but not marked as successful. This assumes 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that there are no nested transactions (beginTransaction has only been called once) and will 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * through an exception if that is not the case. 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the transaction was yielded 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean yieldIfContendedSafely() { 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return yieldIfContendedHelper(true /* check yielding */); 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean yieldIfContendedHelper(boolean checkFullyYielded) { 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mLock.getQueueLength() == 0) { 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Reset the lock acquire time since we know that the thread was willing to yield 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the lock at this time. 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLockAcquiredWallTime = SystemClock.elapsedRealtime(); 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLockAcquiredThreadTime = Debug.threadCpuTimeNanos(); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTransactionSuccessful(); 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project endTransaction(); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (checkFullyYielded) { 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (this.isDbLockedByCurrentThread()) { 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException( 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Db locked more than once. yielfIfContended cannot yield"); 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project beginTransaction(); 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Maps table names to info about what to which _sync_time column to set 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to NULL on an update. This is used to support syncing. */ 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Map<String, SyncUpdateInfo> mSyncUpdateInfo = 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new HashMap<String, SyncUpdateInfo>(); 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Map<String, String> getSyncedTables() { 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(mSyncUpdateInfo) { 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HashMap<String, String> tables = new HashMap<String, String>(); 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String table : mSyncUpdateInfo.keySet()) { 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SyncUpdateInfo info = mSyncUpdateInfo.get(table); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (info.deletedTable != null) { 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tables.put(table, info.deletedTable); 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return tables; 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Internal class used to keep track what needs to be marked as changed 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when an update occurs. This is used for syncing, so the sync engine 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * knows what data has been updated locally. 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static private class SyncUpdateInfo { 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates the SyncUpdateInfo class. 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param masterTable The table to set _sync_time to NULL in 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param deletedTable The deleted table that corresponds to the 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * master table 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param foreignKey The key that refers to the primary key in table 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SyncUpdateInfo(String masterTable, String deletedTable, 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String foreignKey) { 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.masterTable = masterTable; 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.deletedTable = deletedTable; 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.foreignKey = foreignKey; 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The table containing the _sync_time column */ 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String masterTable; 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The deleted table that corresponds to the master table */ 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String deletedTable; 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The key in the local table the row in table. It may be _id, if table 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is the local table. */ 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String foreignKey; 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Used to allow returning sub-classes of {@link Cursor} when calling query. 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface CursorFactory { 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link SQLiteCursor#SQLiteCursor(SQLiteDatabase, SQLiteCursorDriver, 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * String, SQLiteQuery)}. 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Cursor newCursor(SQLiteDatabase db, 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteCursorDriver masterQuery, String editTable, 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteQuery query); 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open the database according to the flags {@link #OPEN_READWRITE} 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}. 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Sets the locale of the database to the the system's current locale. 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Call {@link #setLocale} if you would like something else.</p> 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param path to database file to open and/or create 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param factory an optional factory class that is called to instantiate a 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * cursor when query is called, or null for default 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param flags to control database access mode 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the newly opened database 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws SQLiteException if the database cannot be opened 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags) { 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteDatabase db = null; 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Open the database. 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SQLiteDatabase(path, factory, flags); 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SQLiteDatabaseCorruptException e) { 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Try to recover from this, if we can. 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: should we do this for other open failures? 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Deleting and re-creating corrupt database " + path, e); 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new File(path).delete(); 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SQLiteDatabase(path, factory, flags); 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY). 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static SQLiteDatabase openOrCreateDatabase(File file, CursorFactory factory) { 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return openOrCreateDatabase(file.getPath(), factory); 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY). 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory) { 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return openDatabase(path, factory, CREATE_IF_NECESSARY); 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a memory backed SQLite database. Its contents will be destroyed 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when the database is closed. 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Sets the locale of the database to the the system's current locale. 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Call {@link #setLocale} if you would like something else.</p> 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param factory an optional factory class that is called to instantiate a 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * cursor when query is called 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return a SQLiteDatabase object, or null if the database can't be created 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static SQLiteDatabase create(CursorFactory factory) { 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is a magic string with special meaning for SQLite. 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return openDatabase(":memory:", factory, CREATE_IF_NECESSARY); 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Close the database. 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void close() { 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project closeClosable(); 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project releaseReference(); 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void closeClosable() { 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Map.Entry<SQLiteClosable, Object>> iter = mPrograms.entrySet().iterator(); 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (iter.hasNext()) { 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Map.Entry<SQLiteClosable, Object> entry = iter.next(); 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteClosable program = entry.getKey(); 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (program != null) { 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project program.onAllReferencesReleasedFromContainer(); 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Native call to close the database. 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native void dbclose(); 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the database version. 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the database version 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getVersion() { 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteStatement prog = null; 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project prog = new SQLiteStatement(this, "PRAGMA user_version;"); 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long version = prog.simpleQueryForLong(); 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (int) version; 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prog != null) prog.close(); 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the database version. 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param version the new database version 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setVersion(int version) { 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project execSQL("PRAGMA user_version = " + version); 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the maximum size the database may grow to. 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the new maximum database size 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long getMaximumSize() { 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteStatement prog = null; 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project prog = new SQLiteStatement(this, 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "PRAGMA max_page_count;"); 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long pageCount = prog.simpleQueryForLong(); 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return pageCount * getPageSize(); 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prog != null) prog.close(); 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the maximum size the database will grow to. The maximum size cannot 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be set below the current size. 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param numBytes the maximum database size, in bytes 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the new maximum database size 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long setMaximumSize(long numBytes) { 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteStatement prog = null; 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long pageSize = getPageSize(); 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long numPages = numBytes / pageSize; 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If numBytes isn't a multiple of pageSize, bump up a page 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((numBytes % pageSize) != 0) { 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numPages++; 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project prog = new SQLiteStatement(this, 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "PRAGMA max_page_count = " + numPages); 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long newPageCount = prog.simpleQueryForLong(); 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return newPageCount * pageSize; 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prog != null) prog.close(); 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the current database page size, in bytes. 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the database page size, in bytes 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long getPageSize() { 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteStatement prog = null; 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project prog = new SQLiteStatement(this, 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "PRAGMA page_size;"); 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long size = prog.simpleQueryForLong(); 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return size; 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prog != null) prog.close(); 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the database page size. The page size must be a power of two. This 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * method does not work if any data has been written to the database file, 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and must be called right after the database has been created. 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param numBytes the database page size, in bytes 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setPageSize(long numBytes) { 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project execSQL("PRAGMA page_size = " + numBytes); 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Mark this table as syncable. When an update occurs in this table the 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * _sync_dirty field will be set to ensure proper syncing operation. 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table the table to mark as syncable 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param deletedTable The deleted table that corresponds to the 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * syncable table 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void markTableSyncable(String table, String deletedTable) { 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project markTableSyncable(table, "_id", table, deletedTable); 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Mark this table as syncable, with the _sync_dirty residing in another 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * table. When an update occurs in this table the _sync_dirty field of the 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * row in updateTable with the _id in foreignKey will be set to 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ensure proper syncing operation. 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table an update on this table will trigger a sync time removal 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param foreignKey this is the column in table whose value is an _id in 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * updateTable 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param updateTable this is the table that will have its _sync_dirty 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void markTableSyncable(String table, String foreignKey, 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String updateTable) { 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project markTableSyncable(table, foreignKey, updateTable, null); 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Mark this table as syncable, with the _sync_dirty residing in another 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * table. When an update occurs in this table the _sync_dirty field of the 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * row in updateTable with the _id in foreignKey will be set to 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ensure proper syncing operation. 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table an update on this table will trigger a sync time removal 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param foreignKey this is the column in table whose value is an _id in 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * updateTable 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param updateTable this is the table that will have its _sync_dirty 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param deletedTable The deleted table that corresponds to the 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * updateTable 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void markTableSyncable(String table, String foreignKey, 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String updateTable, String deletedTable) { 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_execSQL("SELECT _sync_dirty FROM " + updateTable 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " LIMIT 0"); 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_execSQL("SELECT " + foreignKey + " FROM " + table 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " LIMIT 0"); 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SyncUpdateInfo info = new SyncUpdateInfo(updateTable, deletedTable, 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project foreignKey); 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mSyncUpdateInfo) { 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSyncUpdateInfo.put(table, info); 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Call for each row that is updated in a cursor. 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table the table the row is in 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param rowId the row ID of the updated row 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ void rowUpdated(String table, long rowId) { 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SyncUpdateInfo info; 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mSyncUpdateInfo) { 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project info = mSyncUpdateInfo.get(table); 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (info != null) { 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project execSQL("UPDATE " + info.masterTable 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " SET _sync_dirty=1 WHERE _id=(SELECT " + info.foreignKey 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " FROM " + table + " WHERE _id=" + rowId + ")"); 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Finds the name of the first table, which is editable. 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param tables a list of tables 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the first table listed 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String findEditTable(String tables) { 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!TextUtils.isEmpty(tables)) { 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // find the first word terminated by either a space or a comma 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spacepos = tables.indexOf(' '); 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int commapos = tables.indexOf(','); 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spacepos > 0 && (spacepos < commapos || commapos < 0)) { 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return tables.substring(0, spacepos); 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) { 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return tables.substring(0, commapos); 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return tables; 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("Invalid tables"); 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Compiles an SQL statement into a reusable pre-compiled statement object. 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * statement and fill in those values with {@link SQLiteProgram#bindString} 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and {@link SQLiteProgram#bindLong} each time you want to run the 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * statement. Statements may not return result sets larger than 1x1. 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param sql The raw SQL statement, may contain ? for unknown values to be 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * bound later. 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return a pre-compiled statement object. 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SQLiteStatement compileStatement(String sql) throws SQLException { 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SQLiteStatement(this, sql); 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Query the given URL, returning a {@link Cursor} over the result set. 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param distinct true if you want each row to be unique, false otherwise. 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table The table name to compile the query against. 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param columns A list of which columns to return. Passing null will 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * return all columns, which is discouraged to prevent reading 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * data from storage that isn't going to be used. 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selection A filter declaring which rows to return, formatted as an 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * SQL WHERE clause (excluding the WHERE itself). Passing null 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will return all rows for the given table. 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selectionArgs You may include ?s in selection, which will be 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * replaced by the values from selectionArgs, in order that they 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * appear in the selection. The values will be bound as Strings. 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupBy A filter declaring how to group rows, formatted as an SQL 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * GROUP BY clause (excluding the GROUP BY itself). Passing null 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will cause the rows to not be grouped. 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param having A filter declare which row groups to include in the cursor, 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if row grouping is being used, formatted as an SQL HAVING 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * clause (excluding the HAVING itself). Passing null will cause 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * all row groups to be included, and is required when row 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * grouping is not being used. 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (excluding the ORDER BY itself). Passing null will use the 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * default sort order, which may be unordered. 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param limit Limits the number of rows returned by the query, 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * formatted as LIMIT clause. Passing null denotes no LIMIT clause. 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A Cursor object, which is positioned before the first entry 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see Cursor 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Cursor query(boolean distinct, String table, String[] columns, 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String selection, String[] selectionArgs, String groupBy, 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String having, String orderBy, String limit) { 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return queryWithFactory(null, distinct, table, columns, selection, selectionArgs, 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project groupBy, having, orderBy, limit); 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Query the given URL, returning a {@link Cursor} over the result set. 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cursorFactory the cursor factory to use, or null for the default factory 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param distinct true if you want each row to be unique, false otherwise. 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table The table name to compile the query against. 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param columns A list of which columns to return. Passing null will 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * return all columns, which is discouraged to prevent reading 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * data from storage that isn't going to be used. 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selection A filter declaring which rows to return, formatted as an 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * SQL WHERE clause (excluding the WHERE itself). Passing null 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will return all rows for the given table. 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selectionArgs You may include ?s in selection, which will be 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * replaced by the values from selectionArgs, in order that they 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * appear in the selection. The values will be bound as Strings. 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupBy A filter declaring how to group rows, formatted as an SQL 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * GROUP BY clause (excluding the GROUP BY itself). Passing null 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will cause the rows to not be grouped. 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param having A filter declare which row groups to include in the cursor, 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if row grouping is being used, formatted as an SQL HAVING 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * clause (excluding the HAVING itself). Passing null will cause 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * all row groups to be included, and is required when row 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * grouping is not being used. 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (excluding the ORDER BY itself). Passing null will use the 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * default sort order, which may be unordered. 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param limit Limits the number of rows returned by the query, 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * formatted as LIMIT clause. Passing null denotes no LIMIT clause. 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A Cursor object, which is positioned before the first entry 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see Cursor 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Cursor queryWithFactory(CursorFactory cursorFactory, 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean distinct, String table, String[] columns, 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String selection, String[] selectionArgs, String groupBy, 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String having, String orderBy, String limit) { 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String sql = SQLiteQueryBuilder.buildQueryString( 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project distinct, table, columns, selection, groupBy, having, orderBy, limit); 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return rawQueryWithFactory( 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cursorFactory, sql, selectionArgs, findEditTable(table)); 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Query the given table, returning a {@link Cursor} over the result set. 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table The table name to compile the query against. 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param columns A list of which columns to return. Passing null will 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * return all columns, which is discouraged to prevent reading 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * data from storage that isn't going to be used. 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selection A filter declaring which rows to return, formatted as an 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * SQL WHERE clause (excluding the WHERE itself). Passing null 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will return all rows for the given table. 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selectionArgs You may include ?s in selection, which will be 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * replaced by the values from selectionArgs, in order that they 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * appear in the selection. The values will be bound as Strings. 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupBy A filter declaring how to group rows, formatted as an SQL 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * GROUP BY clause (excluding the GROUP BY itself). Passing null 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will cause the rows to not be grouped. 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param having A filter declare which row groups to include in the cursor, 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if row grouping is being used, formatted as an SQL HAVING 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * clause (excluding the HAVING itself). Passing null will cause 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * all row groups to be included, and is required when row 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * grouping is not being used. 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (excluding the ORDER BY itself). Passing null will use the 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * default sort order, which may be unordered. 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A {@link Cursor} object, which is positioned before the first entry 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see Cursor 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Cursor query(String table, String[] columns, String selection, 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] selectionArgs, String groupBy, String having, 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String orderBy) { 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return query(false, table, columns, selection, selectionArgs, groupBy, 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project having, orderBy, null /* limit */); 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Query the given table, returning a {@link Cursor} over the result set. 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table The table name to compile the query against. 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param columns A list of which columns to return. Passing null will 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * return all columns, which is discouraged to prevent reading 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * data from storage that isn't going to be used. 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selection A filter declaring which rows to return, formatted as an 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * SQL WHERE clause (excluding the WHERE itself). Passing null 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will return all rows for the given table. 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selectionArgs You may include ?s in selection, which will be 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * replaced by the values from selectionArgs, in order that they 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * appear in the selection. The values will be bound as Strings. 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupBy A filter declaring how to group rows, formatted as an SQL 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * GROUP BY clause (excluding the GROUP BY itself). Passing null 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will cause the rows to not be grouped. 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param having A filter declare which row groups to include in the cursor, 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if row grouping is being used, formatted as an SQL HAVING 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * clause (excluding the HAVING itself). Passing null will cause 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * all row groups to be included, and is required when row 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * grouping is not being used. 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (excluding the ORDER BY itself). Passing null will use the 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * default sort order, which may be unordered. 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param limit Limits the number of rows returned by the query, 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * formatted as LIMIT clause. Passing null denotes no LIMIT clause. 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A {@link Cursor} object, which is positioned before the first entry 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see Cursor 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Cursor query(String table, String[] columns, String selection, 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] selectionArgs, String groupBy, String having, 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String orderBy, String limit) { 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return query(false, table, columns, selection, selectionArgs, groupBy, 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project having, orderBy, limit); 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Runs the provided SQL and returns a {@link Cursor} over the result set. 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param sql the SQL query. The SQL string must not be ; terminated 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selectionArgs You may include ?s in where clause in the query, 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * which will be replaced by the values from selectionArgs. The 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * values will be bound as Strings. 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A {@link Cursor} object, which is positioned before the first entry 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Cursor rawQuery(String sql, String[] selectionArgs) { 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return rawQueryWithFactory(null, sql, selectionArgs, null); 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Runs the provided SQL and returns a cursor over the result set. 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cursorFactory the cursor factory to use, or null for the default factory 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param sql the SQL query. The SQL string must not be ; terminated 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selectionArgs You may include ?s in where clause in the query, 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * which will be replaced by the values from selectionArgs. The 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * values will be bound as Strings. 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param editTable the name of the first table, which is editable 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A {@link Cursor} object, which is positioned before the first entry 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Cursor rawQueryWithFactory( 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CursorFactory cursorFactory, String sql, String[] selectionArgs, 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String editTable) { 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long timeStart = 0; 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGV) { 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project timeStart = System.currentTimeMillis(); 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable); 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return driver.query( 11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cursorFactory != null ? cursorFactory : mFactory, 11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectionArgs); 11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGV) { 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long duration = System.currentTimeMillis() - timeStart; 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(SQLiteCursor.TAG, 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "query (" + duration + " ms): " + driver.toString() + ", args are " 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + (selectionArgs != null 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ? TextUtils.join(",", selectionArgs) 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : "<null>")); 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Runs the provided SQL and returns a cursor over the result set. 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The cursor will read an initial set of rows and the return to the caller. 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * It will continue to read in batches and send data changed notifications 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when the later batches are ready. 11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param sql the SQL query. The SQL string must not be ; terminated 11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selectionArgs You may include ?s in where clause in the query, 11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * which will be replaced by the values from selectionArgs. The 11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * values will be bound as Strings. 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param initialRead set the initial count of items to read from the cursor 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param maxRead set the count of items to read on each iteration after the first 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A {@link Cursor} object, which is positioned before the first entry 1146f8a7ceaef2e7d5cd530c9426bde91b6fa9a40b75Andy Stadler * 1147f8a7ceaef2e7d5cd530c9426bde91b6fa9a40b75Andy Stadler * This work is incomplete and not fully tested or reviewed, so currently 1148f8a7ceaef2e7d5cd530c9426bde91b6fa9a40b75Andy Stadler * hidden. 1149f8a7ceaef2e7d5cd530c9426bde91b6fa9a40b75Andy Stadler * @hide 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Cursor rawQuery(String sql, String[] selectionArgs, 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int initialRead, int maxRead) { 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteCursor c = (SQLiteCursor)rawQueryWithFactory( 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project null, sql, selectionArgs, null); 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.setLoadStyle(initialRead, maxRead); 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return c; 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Convenience method for inserting a row into the database. 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table the table to insert the row into 11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param nullColumnHack SQL doesn't allow inserting a completely empty row, 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * so if initialValues is empty this column will explicitly be 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * assigned a NULL value 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values this map contains the initial column values for the 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * row. The keys should be the column names and the values the 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * column values 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the row ID of the newly inserted row, or -1 if an error occurred 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long insert(String table, String nullColumnHack, ContentValues values) { 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return insertWithOnConflict(table, nullColumnHack, values, null); 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SQLException e) { 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Error inserting " + values, e); 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Convenience method for inserting a row into the database. 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table the table to insert the row into 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param nullColumnHack SQL doesn't allow inserting a completely empty row, 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * so if initialValues is empty this column will explicitly be 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * assigned a NULL value 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values this map contains the initial column values for the 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * row. The keys should be the column names and the values the 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * column values 11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws SQLException 11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the row ID of the newly inserted row, or -1 if an error occurred 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long insertOrThrow(String table, String nullColumnHack, ContentValues values) 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws SQLException { 11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return insertWithOnConflict(table, nullColumnHack, values, null); 11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Convenience method for replacing a row in the database. 12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table the table in which to replace the row 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param nullColumnHack SQL doesn't allow inserting a completely empty row, 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * so if initialValues is empty this row will explicitly be 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * assigned a NULL value 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param initialValues this map contains the initial column values for 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the row. The key 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the row ID of the newly inserted row, or -1 if an error occurred 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long replace(String table, String nullColumnHack, ContentValues initialValues) { 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return insertWithOnConflict(table, nullColumnHack, initialValues, 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ConflictAlgorithm.REPLACE); 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SQLException e) { 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Error inserting " + initialValues, e); 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Convenience method for replacing a row in the database. 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table the table in which to replace the row 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param nullColumnHack SQL doesn't allow inserting a completely empty row, 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * so if initialValues is empty this row will explicitly be 12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * assigned a NULL value 12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param initialValues this map contains the initial column values for 12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the row. The key 12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws SQLException 12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the row ID of the newly inserted row, or -1 if an error occurred 12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long replaceOrThrow(String table, String nullColumnHack, 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentValues initialValues) throws SQLException { 12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return insertWithOnConflict(table, nullColumnHack, initialValues, 12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ConflictAlgorithm.REPLACE); 12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * General method for inserting a row into the database. 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table the table to insert the row into 12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param nullColumnHack SQL doesn't allow inserting a completely empty row, 12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * so if initialValues is empty this column will explicitly be 12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * assigned a NULL value 12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param initialValues this map contains the initial column values for the 12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * row. The keys should be the column names and the values the 12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * column values 12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param algorithm {@link ConflictAlgorithm} for insert conflict resolver 12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the row ID of the newly inserted row, or -1 if an error occurred 12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long insertWithOnConflict(String table, String nullColumnHack, 12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentValues initialValues, ConflictAlgorithm algorithm) { 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isOpen()) { 12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("database not open"); 12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Measurements show most sql lengths <= 152 12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sql = new StringBuilder(152); 12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append("INSERT"); 12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (algorithm != null) { 12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(" OR "); 12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(algorithm.value()); 12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(" INTO "); 12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(table); 12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Measurements show most values lengths < 40 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder values = new StringBuilder(40); 12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Set<Map.Entry<String, Object>> entrySet = null; 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (initialValues != null && initialValues.size() > 0) { 12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entrySet = initialValues.valueSet(); 12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator(); 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append('('); 12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean needSeparator = false; 12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (entriesIter.hasNext()) { 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (needSeparator) { 12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(", "); 12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project values.append(", "); 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project needSeparator = true; 12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Map.Entry<String, Object> entry = entriesIter.next(); 12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(entry.getKey()); 12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project values.append('?'); 12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(')'); 12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append("(" + nullColumnHack + ") "); 12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project values.append("NULL"); 12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(" VALUES("); 12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(values); 12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(");"); 12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteStatement statement = null; 12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement = compileStatement(sql.toString()); 13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Bind the values 13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (entrySet != null) { 13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = entrySet.size(); 13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator(); 13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Map.Entry<String, Object> entry = entriesIter.next(); 13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DatabaseUtils.bindObjectToProgram(statement, i + 1, entry.getValue()); 13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Run the program and then cleanup 13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement.execute(); 13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long insertedRowId = lastInsertRow(); 13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (insertedRowId == -1) { 13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Error inserting " + initialValues + " using " + sql); 13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGD && Log.isLoggable(TAG, Log.VERBOSE)) { 13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, "Inserting row " + insertedRowId + " from " 13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + initialValues + " using " + sql); 13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return insertedRowId; 13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SQLiteDatabaseCorruptException e) { 13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onCorruption(); 13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw e; 13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (statement != null) { 13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement.close(); 13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Convenience method for deleting rows in the database. 13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table the table to delete from 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param whereClause the optional WHERE clause to apply when deleting. 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Passing null will delete all rows. 13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the number of rows affected if a whereClause is passed in, 0 13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * otherwise. To remove all rows and get a count pass "1" as the 13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * whereClause. 13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int delete(String table, String whereClause, String[] whereArgs) { 13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isOpen()) { 13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("database not open"); 13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteStatement statement = null; 13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement = compileStatement("DELETE FROM " + table 13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + (!TextUtils.isEmpty(whereClause) 13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ? " WHERE " + whereClause : "")); 13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (whereArgs != null) { 13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numArgs = whereArgs.length; 13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numArgs; i++) { 13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DatabaseUtils.bindObjectToProgram(statement, i + 1, whereArgs[i]); 13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement.execute(); 13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement.close(); 13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return lastChangeCount(); 13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SQLiteDatabaseCorruptException e) { 13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onCorruption(); 13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw e; 13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (statement != null) { 13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement.close(); 13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Convenience method for updating rows in the database. 13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table the table to update in 13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values a map from column names to new column values. null is a 13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * valid value that will be translated to NULL. 13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param whereClause the optional WHERE clause to apply when updating. 13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Passing null will update all rows. 13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the number of rows affected 13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int update(String table, ContentValues values, String whereClause, String[] whereArgs) { 13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return updateWithOnConflict(table, values, whereClause, whereArgs, null); 13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Convenience method for updating rows in the database. 13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param table the table to update in 13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values a map from column names to new column values. null is a 13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * valid value that will be translated to NULL. 13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param whereClause the optional WHERE clause to apply when updating. 13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Passing null will update all rows. 13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param algorithm {@link ConflictAlgorithm} for update conflict resolver 13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the number of rows affected 14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int updateWithOnConflict(String table, ContentValues values, 14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String whereClause, String[] whereArgs, ConflictAlgorithm algorithm) { 14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isOpen()) { 14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("database not open"); 14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (values == null || values.size() == 0) { 14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Empty values"); 14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sql = new StringBuilder(120); 14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append("UPDATE "); 14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (algorithm != null) { 14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(" OR "); 14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(algorithm.value()); 14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(table); 14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(" SET "); 14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Set<Map.Entry<String, Object>> entrySet = values.valueSet(); 14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator(); 14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (entriesIter.hasNext()) { 14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Map.Entry<String, Object> entry = entriesIter.next(); 14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(entry.getKey()); 14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append("=?"); 14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (entriesIter.hasNext()) { 14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(", "); 14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!TextUtils.isEmpty(whereClause)) { 14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(" WHERE "); 14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(whereClause); 14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteStatement statement = null; 14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement = compileStatement(sql.toString()); 14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Bind the values 14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = entrySet.size(); 14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entriesIter = entrySet.iterator(); 14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int bindArg = 1; 14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Map.Entry<String, Object> entry = entriesIter.next(); 14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DatabaseUtils.bindObjectToProgram(statement, bindArg, entry.getValue()); 14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bindArg++; 14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (whereArgs != null) { 14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size = whereArgs.length; 14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement.bindString(bindArg, whereArgs[i]); 14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bindArg++; 14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Run the program and then cleanup 14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement.execute(); 14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement.close(); 14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numChangedRows = lastChangeCount(); 14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGD && Log.isLoggable(TAG, Log.VERBOSE)) { 14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, "Updated " + numChangedRows + " using " + values + " and " + sql); 14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return numChangedRows; 14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SQLiteDatabaseCorruptException e) { 14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onCorruption(); 14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw e; 14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SQLException e) { 14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Error updating " + values + " using " + sql); 14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw e; 14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (statement != null) { 14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement.close(); 14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Execute a single SQL statement that is not a query. For example, CREATE 14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TABLE, DELETE, INSERT, etc. Multiple statements separated by ;s are not 14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * supported. it takes a write lock 14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws SQLException If the SQL string is invalid for some reason 14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void execSQL(String sql) throws SQLException { 14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean logStats = mLogStats; 14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long timeStart = logStats ? SystemClock.elapsedRealtime() : 0; 14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_execSQL(sql); 14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SQLiteDatabaseCorruptException e) { 14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onCorruption(); 14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw e; 15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (logStats) { 15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project logTimeStat(false /* not a read */, timeStart, SystemClock.elapsedRealtime()); 15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Execute a single SQL statement that is not a query. For example, CREATE 15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TABLE, DELETE, INSERT, etc. Multiple statements separated by ;s are not 15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * supported. it takes a write lock, 15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param sql 15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param bindArgs only byte[], String, Long and Double are supported in bindArgs. 15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws SQLException If the SQL string is invalid for some reason 15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void execSQL(String sql, Object[] bindArgs) throws SQLException { 15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bindArgs == null) { 15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Empty bindArgs"); 15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean logStats = mLogStats; 15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long timeStart = logStats ? SystemClock.elapsedRealtime() : 0; 15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteStatement statement = null; 15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement = compileStatement(sql); 15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bindArgs != null) { 15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numArgs = bindArgs.length; 15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numArgs; i++) { 15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DatabaseUtils.bindObjectToProgram(statement, i + 1, bindArgs[i]); 15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement.execute(); 15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SQLiteDatabaseCorruptException e) { 15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onCorruption(); 15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw e; 15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (statement != null) { 15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statement.close(); 15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (logStats) { 15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project logTimeStat(false /* not a read */, timeStart, SystemClock.elapsedRealtime()); 15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() { 15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isOpen()) { 15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mPrograms.isEmpty()) { 15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Leak found", mLeakedException); 15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IllegalStateException leakProgram = new IllegalStateException( 15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "mPrograms size " + mPrograms.size(), mLeakedException); 15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Leak found", leakProgram); 15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project closeClosable(); 15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onAllReferencesReleased(); 15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Private constructor. See {@link #create} and {@link #openDatabase}. 15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param path The full path to the database 15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param factory The factory to use when creating cursors, may be NULL. 15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param flags 0 or {@link #NO_LOCALIZED_COLLATORS}. If the database file already 15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * exists, mFlags will be updated appropriately. 15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SQLiteDatabase(String path, CursorFactory factory, int flags) { 15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (path == null) { 15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("path should not be null"); 15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFlags = flags; 15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPath = path; 15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLogStats = "1".equals(android.os.SystemProperties.get("db.logstats")); 15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLeakedException = new IllegalStateException(path + 15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " SQLiteDatabase created and never closed"); 15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFactory = factory; 15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dbopen(mPath, mFlags); 15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPrograms = new WeakHashMap<SQLiteClosable,Object>(); 15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setLocale(Locale.getDefault()); 15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RuntimeException e) { 15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Failed to setLocale() when constructing, closing the database", e); 15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dbclose(); 15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw e; 15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * return whether the DB is opened as read only. 15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if DB is opened as read only 15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isReadOnly() { 15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (mFlags & OPEN_READ_MASK) == OPEN_READONLY; 16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the DB is currently open (has not been closed) 16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isOpen() { 16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mNativeHandle != 0; 16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean needUpgrade(int newVersion) { 16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return newVersion > getVersion(); 16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Getter for the path to the database file. 16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the path to our database file. 16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final String getPath() { 16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mPath; 16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ void logTimeStat(boolean read, long begin, long end) { 16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EventLog.writeEvent(DB_OPERATION_EVENT, mPath, read ? 0 : 1, end - begin); 16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the locale for this database. Does nothing if this database has 16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the NO_LOCALIZED_COLLATORS flag set or was opened read only. 16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws SQLException if the locale could not be set. The most common reason 16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for this is that there is no collator available for the locale you requested. 16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In this case the database remains unchanged. 16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setLocale(Locale locale) { 16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lock(); 16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_setLocale(locale.toString(), mFlags); 16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlock(); 16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Native call to open the database. 16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param path The full path to the database 16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native void dbopen(String path, int flags); 16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Native call to execute a raw SQL statement. {@link #lock} must be held 16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when calling this method. 16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param sql The raw SQL string 16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws SQLException 16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ native void native_execSQL(String sql) throws SQLException; 16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Native call to set the locale. {@link #lock} must be held when calling 16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this method. 16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws SQLException 16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ native void native_setLocale(String loc, int flags); 16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the row ID of the last row inserted into the database. 16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the row ID of the last row inserted into the database. 16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ native long lastInsertRow(); 16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the number of changes made in the last statement executed. 16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the number of changes made in the last statement executed. 16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ native int lastChangeCount(); 16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1679