summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorVasu Nori <vnori@google.com>2010-08-03 10:50:56 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2010-08-03 10:50:56 -0700
commit6cd0cc46061e682b14447477147b2dd6969df155 (patch)
tree106ee4d61c982c77a2f0835cde852e03f65a0ab5 /core
parent5515b54d92945985b71a4ef9b8f507be152b5a50 (diff)
parent0732f7912ccec9a1cc379b535ac0b56ae50972b3 (diff)
downloadframeworks_base-6cd0cc46061e682b14447477147b2dd6969df155.zip
frameworks_base-6cd0cc46061e682b14447477147b2dd6969df155.tar.gz
frameworks_base-6cd0cc46061e682b14447477147b2dd6969df155.tar.bz2
Merge "random but useful stuff"
Diffstat (limited to 'core')
-rw-r--r--core/java/android/database/DatabaseUtils.java20
-rw-r--r--core/java/android/database/sqlite/SQLiteCompiledSql.java3
-rw-r--r--core/java/android/database/sqlite/SQLiteCursorDriver.java2
-rw-r--r--core/java/android/database/sqlite/SQLiteDatabase.java290
-rw-r--r--core/java/android/database/sqlite/SQLiteDirectCursorDriver.java10
-rw-r--r--core/java/android/database/sqlite/SQLiteProgram.java191
-rw-r--r--core/java/android/database/sqlite/SQLiteQuery.java62
-rw-r--r--core/java/android/database/sqlite/SQLiteStatement.java20
8 files changed, 233 insertions, 365 deletions
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 0687659..9ac45d8 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -678,14 +678,8 @@ public class DatabaseUtils {
* first column of the first row.
*/
public static long longForQuery(SQLiteStatement prog, String[] selectionArgs) {
- if (selectionArgs != null) {
- int size = selectionArgs.length;
- for (int i = 0; i < size; i++) {
- bindObjectToProgram(prog, i + 1, selectionArgs[i]);
- }
- }
- long value = prog.simpleQueryForLong();
- return value;
+ prog.bindAllArgsAsStrings(selectionArgs);
+ return prog.simpleQueryForLong();
}
/**
@@ -706,14 +700,8 @@ public class DatabaseUtils {
* first column of the first row.
*/
public static String stringForQuery(SQLiteStatement prog, String[] selectionArgs) {
- if (selectionArgs != null) {
- int size = selectionArgs.length;
- for (int i = 0; i < size; i++) {
- bindObjectToProgram(prog, i + 1, selectionArgs[i]);
- }
- }
- String value = prog.simpleQueryForString();
- return value;
+ prog.bindAllArgsAsStrings(selectionArgs);
+ return prog.simpleQueryForString();
}
/**
diff --git a/core/java/android/database/sqlite/SQLiteCompiledSql.java b/core/java/android/database/sqlite/SQLiteCompiledSql.java
index 9889a21..aa0a57d 100644
--- a/core/java/android/database/sqlite/SQLiteCompiledSql.java
+++ b/core/java/android/database/sqlite/SQLiteCompiledSql.java
@@ -134,9 +134,6 @@ import android.util.Log;
try {
if (nStatement == 0) return;
// finalizer should NEVER get called
- if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) {
- Log.v(TAG, "** warning ** Finalized DbObj (id#" + nStatement + ")");
- }
int len = mSqlStmt.length();
Log.w(TAG, "Releasing statement in a finalizer. Please ensure " +
"that you explicitly call close() on your cursor: " +
diff --git a/core/java/android/database/sqlite/SQLiteCursorDriver.java b/core/java/android/database/sqlite/SQLiteCursorDriver.java
index eda1b78..b3963f9 100644
--- a/core/java/android/database/sqlite/SQLiteCursorDriver.java
+++ b/core/java/android/database/sqlite/SQLiteCursorDriver.java
@@ -40,8 +40,6 @@ public interface SQLiteCursorDriver {
/**
* Called by a SQLiteCursor when it is requeryed.
- *
- * @return The new count value.
*/
void cursorRequeried(Cursor cursor);
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index a2fff73..dc3b469 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -39,14 +39,13 @@ import dalvik.system.BlockGuard;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
-import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Pattern;
@@ -351,6 +350,10 @@ public class SQLiteDatabase extends SQLiteClosable {
private static final String MEMORY_DB_PATH = ":memory:";
+ /** stores reference to all databases opened in the current process. */
+ private static ArrayList<WeakReference<SQLiteDatabase>> mActiveDatabases =
+ new ArrayList<WeakReference<SQLiteDatabase>>();
+
synchronized void addSQLiteClosable(SQLiteClosable closable) {
// mPrograms is per instance of SQLiteDatabase and it doesn't actually touch the database
// itself. so, there is no need to lock().
@@ -966,7 +969,9 @@ public class SQLiteDatabase extends SQLiteClosable {
// END STOPSHIP
// add this database to the list of databases opened in this process
- ActiveDatabases.addActiveDatabase(sqliteDatabase);
+ synchronized(mActiveDatabases) {
+ mActiveDatabases.add(new WeakReference<SQLiteDatabase>(sqliteDatabase));
+ }
return sqliteDatabase;
}
@@ -1284,7 +1289,7 @@ public class SQLiteDatabase extends SQLiteClosable {
*/
public SQLiteStatement compileStatement(String sql) throws SQLException {
verifyDbIsOpen();
- return new SQLiteStatement(this, sql);
+ return new SQLiteStatement(this, sql, null);
}
/**
@@ -1634,68 +1639,41 @@ public class SQLiteDatabase extends SQLiteClosable {
*/
public long insertWithOnConflict(String table, String nullColumnHack,
ContentValues initialValues, int conflictAlgorithm) {
- verifyDbIsOpen();
-
- // Measurements show most sql lengths <= 152
- StringBuilder sql = new StringBuilder(152);
+ StringBuilder sql = new StringBuilder();
sql.append("INSERT");
sql.append(CONFLICT_VALUES[conflictAlgorithm]);
sql.append(" INTO ");
sql.append(table);
- // Measurements show most values lengths < 40
- StringBuilder values = new StringBuilder(40);
-
- Set<Map.Entry<String, Object>> entrySet = null;
- if (initialValues != null && initialValues.size() > 0) {
- entrySet = initialValues.valueSet();
- Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator();
- sql.append('(');
-
- boolean needSeparator = false;
- while (entriesIter.hasNext()) {
- if (needSeparator) {
- sql.append(", ");
- values.append(", ");
- }
- needSeparator = true;
- Map.Entry<String, Object> entry = entriesIter.next();
- sql.append(entry.getKey());
- values.append('?');
+ sql.append('(');
+
+ Object[] bindArgs = null;
+ int size = (initialValues != null && initialValues.size() > 0) ? initialValues.size() : 0;
+ if (size > 0) {
+ bindArgs = new Object[size];
+ int i = 0;
+ for (String colName : initialValues.keySet()) {
+ sql.append((i > 0) ? "," : "");
+ sql.append(colName);
+ bindArgs[i++] = initialValues.get(colName);
}
-
sql.append(')');
+ sql.append(" VALUES (");
+ for (i = 0; i < size; i++) {
+ sql.append((i > 0) ? ",?" : "?");
+ }
} else {
- sql.append("(" + nullColumnHack + ") ");
- values.append("NULL");
+ sql.append(nullColumnHack + ") VALUES (NULL");
}
+ sql.append(')');
- sql.append(" VALUES(");
- sql.append(values);
- sql.append(");");
-
- SQLiteStatement statement = null;
+ SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
try {
- statement = compileStatement(sql.toString());
-
- // Bind the values
- if (entrySet != null) {
- int size = entrySet.size();
- Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator();
- for (int i = 0; i < size; i++) {
- Map.Entry<String, Object> entry = entriesIter.next();
- DatabaseUtils.bindObjectToProgram(statement, i + 1, entry.getValue());
- }
- }
-
- // Run the program and then cleanup
return statement.executeInsert();
} catch (SQLiteDatabaseCorruptException e) {
onCorruption();
throw e;
} finally {
- if (statement != null) {
- statement.close();
- }
+ statement.close();
}
}
@@ -1710,26 +1688,15 @@ public class SQLiteDatabase extends SQLiteClosable {
* whereClause.
*/
public int delete(String table, String whereClause, String[] whereArgs) {
- verifyDbIsOpen();
- SQLiteStatement statement = null;
+ SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table +
+ (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
try {
- statement = compileStatement("DELETE FROM " + table
- + (!TextUtils.isEmpty(whereClause)
- ? " WHERE " + whereClause : ""));
- if (whereArgs != null) {
- int numArgs = whereArgs.length;
- for (int i = 0; i < numArgs; i++) {
- DatabaseUtils.bindObjectToProgram(statement, i + 1, whereArgs[i]);
- }
- }
return statement.executeUpdateDelete();
} catch (SQLiteDatabaseCorruptException e) {
onCorruption();
throw e;
} finally {
- if (statement != null) {
- statement.close();
- }
+ statement.close();
}
}
@@ -1760,7 +1727,8 @@ public class SQLiteDatabase extends SQLiteClosable {
*/
public int updateWithOnConflict(String table, ContentValues values,
String whereClause, String[] whereArgs, int conflictAlgorithm) {
- if (values == null || values.size() == 0) {
+ int setValuesSize = values.size();
+ if (values == null || setValuesSize == 0) {
throw new IllegalArgumentException("Empty values");
}
@@ -1770,58 +1738,34 @@ public class SQLiteDatabase extends SQLiteClosable {
sql.append(table);
sql.append(" SET ");
- Set<Map.Entry<String, Object>> entrySet = values.valueSet();
- Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator();
-
- while (entriesIter.hasNext()) {
- Map.Entry<String, Object> entry = entriesIter.next();
- sql.append(entry.getKey());
+ // move all bind args to one array
+ int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
+ Object[] bindArgs = new Object[bindArgsSize];
+ int i = 0;
+ for (String colName : values.keySet()) {
+ sql.append((i > 0) ? "," : "");
+ sql.append(colName);
+ bindArgs[i++] = values.get(colName);
sql.append("=?");
- if (entriesIter.hasNext()) {
- sql.append(", ");
+ }
+ if (whereArgs != null) {
+ for (i = setValuesSize; i < bindArgsSize; i++) {
+ bindArgs[i] = whereArgs[i - setValuesSize];
}
}
-
if (!TextUtils.isEmpty(whereClause)) {
sql.append(" WHERE ");
sql.append(whereClause);
}
- verifyDbIsOpen();
- SQLiteStatement statement = null;
+ SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
try {
- statement = compileStatement(sql.toString());
-
- // Bind the values
- int size = entrySet.size();
- entriesIter = entrySet.iterator();
- int bindArg = 1;
- for (int i = 0; i < size; i++) {
- Map.Entry<String, Object> entry = entriesIter.next();
- DatabaseUtils.bindObjectToProgram(statement, bindArg, entry.getValue());
- bindArg++;
- }
-
- if (whereArgs != null) {
- size = whereArgs.length;
- for (int i = 0; i < size; i++) {
- statement.bindString(bindArg, whereArgs[i]);
- bindArg++;
- }
- }
-
- // Run the program and then cleanup
return statement.executeUpdateDelete();
} catch (SQLiteDatabaseCorruptException e) {
onCorruption();
throw e;
- } catch (SQLException e) {
- Log.e(TAG, "Error updating " + values + " using " + sql);
- throw e;
} finally {
- if (statement != null) {
- statement.close();
- }
+ statement.close();
}
}
@@ -1913,25 +1857,15 @@ public class SQLiteDatabase extends SQLiteClosable {
}
private void executeSql(String sql, Object[] bindArgs) throws SQLException {
- verifyDbIsOpen();
long timeStart = SystemClock.uptimeMillis();
- SQLiteStatement statement = null;
+ SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs);
try {
- statement = compileStatement(sql);
- if (bindArgs != null) {
- int numArgs = bindArgs.length;
- for (int i = 0; i < numArgs; i++) {
- DatabaseUtils.bindObjectToProgram(statement, i + 1, bindArgs[i]);
- }
- }
- statement.execute();
+ statement.executeUpdateDelete();
} catch (SQLiteDatabaseCorruptException e) {
onCorruption();
throw e;
} finally {
- if (statement != null) {
- statement.close();
- }
+ statement.close();
}
logTimeStat(sql, timeStart);
}
@@ -2450,82 +2384,78 @@ public class SQLiteDatabase extends SQLiteClosable {
mConnectionPool.release(db);
}
- static class ActiveDatabases {
- private static final ActiveDatabases activeDatabases = new ActiveDatabases();
- private HashSet<WeakReference<SQLiteDatabase>> mActiveDatabases =
- new HashSet<WeakReference<SQLiteDatabase>>();
- private ActiveDatabases() {} // disable instantiation of this class
- static ActiveDatabases getInstance() {
- return activeDatabases;
- }
- private static void addActiveDatabase(SQLiteDatabase sqliteDatabase) {
- activeDatabases.mActiveDatabases.add(new WeakReference<SQLiteDatabase>(sqliteDatabase));
- }
- }
-
/**
* this method is used to collect data about ALL open databases in the current process.
- * bugreport is a user of this data.
+ * bugreport is a user of this data.
*/
/* package */ static ArrayList<DbStats> getDbStats() {
ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
- for (WeakReference<SQLiteDatabase> w : ActiveDatabases.getInstance().mActiveDatabases) {
+ // make a local copy of mActiveDatabases - so that this method is not competing
+ // for synchronization lock on mActiveDatabases
+ ArrayList<WeakReference<SQLiteDatabase>> tempList =
+ new ArrayList<WeakReference<SQLiteDatabase>>();
+ synchronized(mActiveDatabases) {
+ Collections.copy(tempList, mActiveDatabases);
+ }
+ for (WeakReference<SQLiteDatabase> w : tempList) {
SQLiteDatabase db = w.get();
if (db == null || !db.isOpen()) {
continue;
}
- try {
- // get SQLITE_DBSTATUS_LOOKASIDE_USED for the db
- int lookasideUsed = db.native_getDbLookaside();
-
- // get the lastnode of the dbname
- String path = db.getPath();
- int indx = path.lastIndexOf("/");
- String lastnode = path.substring((indx != -1) ? ++indx : 0);
-
- // get list of attached dbs and for each db, get its size and pagesize
- ArrayList<Pair<String, String>> attachedDbs = db.getAttachedDbs();
- if (attachedDbs == null) {
- continue;
- }
- for (int i = 0; i < attachedDbs.size(); i++) {
- Pair<String, String> p = attachedDbs.get(i);
- long pageCount = DatabaseUtils.longForQuery(db, "PRAGMA " + p.first
- + ".page_count;", null);
-
- // first entry in the attached db list is always the main database
- // don't worry about prefixing the dbname with "main"
- String dbName;
- if (i == 0) {
- dbName = lastnode;
- } else {
- // lookaside is only relevant for the main db
- lookasideUsed = 0;
- dbName = " (attached) " + p.first;
- // if the attached db has a path, attach the lastnode from the path to above
- if (p.second.trim().length() > 0) {
- int idx = p.second.lastIndexOf("/");
- dbName += " : " + p.second.substring((idx != -1) ? ++idx : 0);
- }
+ synchronized (db) {
+ try {
+ // get SQLITE_DBSTATUS_LOOKASIDE_USED for the db
+ int lookasideUsed = db.native_getDbLookaside();
+
+ // get the lastnode of the dbname
+ String path = db.getPath();
+ int indx = path.lastIndexOf("/");
+ String lastnode = path.substring((indx != -1) ? ++indx : 0);
+
+ // get list of attached dbs and for each db, get its size and pagesize
+ ArrayList<Pair<String, String>> attachedDbs = db.getAttachedDbs();
+ if (attachedDbs == null) {
+ continue;
}
- if (pageCount > 0) {
- dbStatsList.add(new DbStats(dbName, pageCount, db.getPageSize(),
- lookasideUsed, db.mNumCacheHits, db.mNumCacheMisses,
- db.mCompiledQueries.size()));
+ for (int i = 0; i < attachedDbs.size(); i++) {
+ Pair<String, String> p = attachedDbs.get(i);
+ long pageCount = DatabaseUtils.longForQuery(db, "PRAGMA " + p.first
+ + ".page_count;", null);
+
+ // first entry in the attached db list is always the main database
+ // don't worry about prefixing the dbname with "main"
+ String dbName;
+ if (i == 0) {
+ dbName = lastnode;
+ } else {
+ // lookaside is only relevant for the main db
+ lookasideUsed = 0;
+ dbName = " (attached) " + p.first;
+ // if the attached db has a path, attach the lastnode from the path to above
+ if (p.second.trim().length() > 0) {
+ int idx = p.second.lastIndexOf("/");
+ dbName += " : " + p.second.substring((idx != -1) ? ++idx : 0);
+ }
+ }
+ if (pageCount > 0) {
+ dbStatsList.add(new DbStats(dbName, pageCount, db.getPageSize(),
+ lookasideUsed, db.mNumCacheHits, db.mNumCacheMisses,
+ db.mCompiledQueries.size()));
+ }
}
- }
- // if there are pooled connections, return the cache stats for them also.
- if (db.mConnectionPool != null) {
- for (SQLiteDatabase pDb : db.mConnectionPool.getConnectionList()) {
- dbStatsList.add(new DbStats("(pooled # " + pDb.mConnectionNum + ") "
- + lastnode, 0, 0, 0, pDb.mNumCacheHits, pDb.mNumCacheMisses,
- pDb.mCompiledQueries.size()));
+ // if there are pooled connections, return the cache stats for them also.
+ if (db.mConnectionPool != null) {
+ for (SQLiteDatabase pDb : db.mConnectionPool.getConnectionList()) {
+ dbStatsList.add(new DbStats("(pooled # " + pDb.mConnectionNum + ") "
+ + lastnode, 0, 0, 0, pDb.mNumCacheHits, pDb.mNumCacheMisses,
+ pDb.mCompiledQueries.size()));
+ }
}
+ } catch (SQLiteException e) {
+ // ignore. we don't care about exceptions when we are taking adb
+ // bugreport!
}
- } catch (SQLiteException e) {
- // ignore. we don't care about exceptions when we are taking adb
- // bugreport!
}
}
return dbStatsList;
@@ -2636,7 +2566,7 @@ public class SQLiteDatabase extends SQLiteClosable {
* this method.
* @throws SQLException
*/
- /* package */ native void native_setLocale(String loc, int flags);
+ private native void native_setLocale(String loc, int flags);
/**
* return the SQLITE_DBSTATUS_LOOKASIDE_USED documented here
diff --git a/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java b/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java
index 6cdfa69..de2fca9 100644
--- a/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java
+++ b/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java
@@ -45,11 +45,6 @@ public class SQLiteDirectCursorDriver implements SQLiteCursorDriver {
mDatabase.lock();
mDatabase.closePendingStatements();
query = new SQLiteQuery(mDatabase, mSql, 0, selectionArgs);
- // Arg binding
- int numArgs = selectionArgs == null ? 0 : selectionArgs.length;
- for (int i = 0; i < numArgs; i++) {
- query.bindString(i + 1, selectionArgs[i]);
- }
// Create the cursor
if (factory == null) {
@@ -73,10 +68,7 @@ public class SQLiteDirectCursorDriver implements SQLiteCursorDriver {
}
public void setBindArguments(String[] bindArgs) {
- final int numArgs = bindArgs.length;
- for (int i = 0; i < numArgs; i++) {
- mQuery.bindString(i + 1, bindArgs[i]);
- }
+ mQuery.bindAllArgsAsStrings(bindArgs);
}
public void cursorDeactivated() {
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index a4ebe5a..231d8e6 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -17,10 +17,10 @@
package android.database.sqlite;
import android.database.DatabaseUtils;
+import android.database.Cursor;
import android.util.Log;
-import android.util.Pair;
-import java.util.ArrayList;
+import java.util.HashMap;
/**
* A base class for compiled SQLite programs.
@@ -47,7 +47,7 @@ public abstract class SQLiteProgram extends SQLiteClosable {
* @deprecated do not use this
*/
@Deprecated
- protected int nHandle = 0;
+ protected int nHandle;
/**
* the SQLiteCompiledSql object for the given sql statement.
@@ -60,7 +60,7 @@ public abstract class SQLiteProgram extends SQLiteClosable {
* @deprecated do not use this
*/
@Deprecated
- protected int nStatement = 0;
+ protected int nStatement;
/**
* In the case of {@link SQLiteStatement}, this member stores the bindargs passed
@@ -84,23 +84,29 @@ public abstract class SQLiteProgram extends SQLiteClosable {
* <p>
* It is protected (in multi-threaded environment) by {@link SQLiteProgram}.this
*/
- private ArrayList<Pair<Integer, Object>> mBindArgs = null;
-
+ /* package */ HashMap<Integer, Object> mBindArgs = null;
/* package */ final int mStatementType;
/* package */ SQLiteProgram(SQLiteDatabase db, String sql) {
- this(db, sql, true);
+ this(db, sql, null, true);
}
- /* package */ SQLiteProgram(SQLiteDatabase db, String sql, boolean compileFlag) {
+ /* package */ SQLiteProgram(SQLiteDatabase db, String sql, Object[] bindArgs,
+ boolean compileFlag) {
mSql = sql.trim();
mStatementType = DatabaseUtils.getSqlStatementType(mSql);
db.acquireReference();
db.addSQLiteClosable(this);
mDatabase = db;
nHandle = db.mNativeHandle;
+ if (bindArgs != null) {
+ int size = bindArgs.length;
+ for (int i = 0; i < size; i++) {
+ this.addToBindArgs(i + 1, bindArgs[i]);
+ }
+ }
if (compileFlag) {
- compileSql();
+ compileAndbindAllArgs();
}
}
@@ -218,6 +224,39 @@ public abstract class SQLiteProgram extends SQLiteClosable {
// TODO is there a need for this?
}
+ private void bind(int type, int index, Object value) {
+ mDatabase.verifyDbIsOpen();
+ synchronized (this) {
+ addToBindArgs(index, (type == Cursor.FIELD_TYPE_NULL) ? null : value);
+ if (nStatement > 0) {
+ // bind only if the SQL statement is compiled
+ acquireReference();
+ try {
+ switch (type) {
+ case Cursor.FIELD_TYPE_NULL:
+ native_bind_null(index);
+ break;
+ case Cursor.FIELD_TYPE_BLOB:
+ native_bind_blob(index, (byte[]) value);
+ break;
+ case Cursor.FIELD_TYPE_FLOAT:
+ native_bind_double(index, (Double) value);
+ break;
+ case Cursor.FIELD_TYPE_INTEGER:
+ native_bind_long(index, (Long) value);
+ break;
+ case Cursor.FIELD_TYPE_STRING:
+ default:
+ native_bind_string(index, (String) value);
+ break;
+ }
+ } finally {
+ releaseReference();
+ }
+ }
+ }
+ }
+
/**
* Bind a NULL value to this statement. The value remains bound until
* {@link #clearBindings} is called.
@@ -225,44 +264,18 @@ public abstract class SQLiteProgram extends SQLiteClosable {
* @param index The 1-based index to the parameter to bind null to
*/
public void bindNull(int index) {
- mDatabase.verifyDbIsOpen();
- synchronized (this) {
- acquireReference();
- try {
- if (this.nStatement == 0) {
- // since the SQL statement is not compiled, don't do the binding yet.
- // can be done before executing the SQL statement
- addToBindArgs(index, null);
- } else {
- native_bind_null(index);
- }
- } finally {
- releaseReference();
- }
- }
+ bind(Cursor.FIELD_TYPE_NULL, index, null);
}
/**
* Bind a long value to this statement. The value remains bound until
* {@link #clearBindings} is called.
- *
+ *addToBindArgs
* @param index The 1-based index to the parameter to bind
* @param value The value to bind
*/
public void bindLong(int index, long value) {
- mDatabase.verifyDbIsOpen();
- synchronized (this) {
- acquireReference();
- try {
- if (this.nStatement == 0) {
- addToBindArgs(index, value);
- } else {
- native_bind_long(index, value);
- }
- } finally {
- releaseReference();
- }
- }
+ bind(Cursor.FIELD_TYPE_INTEGER, index, value);
}
/**
@@ -273,19 +286,7 @@ public abstract class SQLiteProgram extends SQLiteClosable {
* @param value The value to bind
*/
public void bindDouble(int index, double value) {
- mDatabase.verifyDbIsOpen();
- synchronized (this) {
- acquireReference();
- try {
- if (this.nStatement == 0) {
- addToBindArgs(index, value);
- } else {
- native_bind_double(index, value);
- }
- } finally {
- releaseReference();
- }
- }
+ bind(Cursor.FIELD_TYPE_FLOAT, index, value);
}
/**
@@ -299,19 +300,7 @@ public abstract class SQLiteProgram extends SQLiteClosable {
if (value == null) {
throw new IllegalArgumentException("the bind value at index " + index + " is null");
}
- mDatabase.verifyDbIsOpen();
- synchronized (this) {
- acquireReference();
- try {
- if (this.nStatement == 0) {
- addToBindArgs(index, value);
- } else {
- native_bind_string(index, value);
- }
- } finally {
- releaseReference();
- }
- }
+ bind(Cursor.FIELD_TYPE_STRING, index, value);
}
/**
@@ -325,19 +314,7 @@ public abstract class SQLiteProgram extends SQLiteClosable {
if (value == null) {
throw new IllegalArgumentException("the bind value at index " + index + " is null");
}
- mDatabase.verifyDbIsOpen();
- synchronized (this) {
- acquireReference();
- try {
- if (this.nStatement == 0) {
- addToBindArgs(index, value);
- } else {
- native_bind_blob(index, value);
- }
- } finally {
- releaseReference();
- }
- }
+ bind(Cursor.FIELD_TYPE_BLOB, index, value);
}
/**
@@ -374,28 +351,56 @@ public abstract class SQLiteProgram extends SQLiteClosable {
private synchronized void addToBindArgs(int index, Object value) {
if (mBindArgs == null) {
- mBindArgs = new ArrayList<Pair<Integer, Object>>();
+ mBindArgs = new HashMap<Integer, Object>();
}
- mBindArgs.add(new Pair<Integer, Object>(index, value));
+ mBindArgs.put(index, value);
}
/* package */ synchronized void compileAndbindAllArgs() {
- assert nStatement == 0;
- compileSql();
+ if (nStatement == 0) {
+ // SQL statement is not compiled yet. compile it now.
+ compileSql();
+ }
if (mBindArgs == null) {
return;
}
- for (Pair<Integer, Object> p : mBindArgs) {
- if (p.second == null) {
- native_bind_null(p.first);
- } else if (p.second instanceof Long) {
- native_bind_long(p.first, (Long)p.second);
- } else if (p.second instanceof Double) {
- native_bind_double(p.first, (Double)p.second);
- } else if (p.second instanceof byte[]) {
- native_bind_blob(p.first, (byte[])p.second);
- } else {
- native_bind_string(p.first, (String)p.second);
+ for (int index : mBindArgs.keySet()) {
+ Object value = mBindArgs.get(index);
+ if (value == null) {
+ native_bind_null(index);
+ } else if (value instanceof Double || value instanceof Float) {
+ native_bind_double(index, ((Number) value).doubleValue());
+ } else if (value instanceof Number) {
+ native_bind_long(index, ((Number) value).longValue());
+ } else if (value instanceof Boolean) {
+ Boolean bool = (Boolean)value;
+ native_bind_long(index, (bool) ? 1 : 0);
+ if (bool) {
+ native_bind_long(index, 1);
+ } else {
+ native_bind_long(index, 0);
+ }
+ } else if (value instanceof byte[]){
+ native_bind_blob(index, (byte[]) value);
+ } else {
+ native_bind_string(index, value.toString());
+ }
+ }
+ }
+
+ /**
+ * Given an array of String bindArgs, this method binds all of them in one single call.
+ *
+ * @param bindArgs the String array of bind args.
+ */
+ public void bindAllArgsAsStrings(String[] bindArgs) {
+ if (bindArgs == null) {
+ return;
+ }
+ int size = bindArgs.length;
+ synchronized(this) {
+ for (int i = 0; i < size; i++) {
+ bindString(i + 1, bindArgs[i]);
}
}
}
@@ -421,6 +426,6 @@ public abstract class SQLiteProgram extends SQLiteClosable {
protected final native void native_bind_double(int index, double value);
protected final native void native_bind_string(int index, String value);
protected final native void native_bind_blob(int index, byte[] value);
- /* package */ final native void native_clear_bindings();
+ private final native void native_clear_bindings();
}
diff --git a/core/java/android/database/sqlite/SQLiteQuery.java b/core/java/android/database/sqlite/SQLiteQuery.java
index 1732971..63a8ce9 100644
--- a/core/java/android/database/sqlite/SQLiteQuery.java
+++ b/core/java/android/database/sqlite/SQLiteQuery.java
@@ -18,7 +18,6 @@ package android.database.sqlite;
import android.database.CursorWindow;
import android.os.SystemClock;
-import android.util.Log;
/**
* A SQLite program that represents a query that reads the resulting rows into a CursorWindow.
@@ -28,28 +27,24 @@ import android.util.Log;
* threads should perform its own synchronization when using the SQLiteQuery.
*/
public class SQLiteQuery extends SQLiteProgram {
- private static final String TAG = "Cursor";
+ private static final String TAG = "SQLiteQuery";
/** The index of the unbound OFFSET parameter */
- private int mOffsetIndex;
-
- /** Args to bind on requery */
- private String[] mBindArgs;
+ private int mOffsetIndex = 0;
private boolean mClosed = false;
/**
* Create a persistent query object.
- *
+ *
* @param db The database that this query object is associated with
* @param query The SQL string for this query.
* @param offsetIndex The 1-based index to the OFFSET parameter,
*/
/* package */ SQLiteQuery(SQLiteDatabase db, String query, int offsetIndex, String[] bindArgs) {
super(db, query);
-
mOffsetIndex = offsetIndex;
- mBindArgs = bindArgs;
+ bindAllArgsAsStrings(bindArgs);
}
/**
@@ -61,7 +56,8 @@ public class SQLiteQuery extends SQLiteProgram {
* @param query the instance of {@link SQLiteQuery} to be replaced
*/
/* package */ SQLiteQuery(SQLiteDatabase db, SQLiteQuery query) {
- this(db, query.mSql, 0, query.mBindArgs);
+ super(db, query.mSql);
+ this.mBindArgs = query.mBindArgs;
}
/**
@@ -148,51 +144,13 @@ public class SQLiteQuery extends SQLiteProgram {
* Called by SQLiteCursor when it is requeried.
*/
/* package */ void requery() {
- if (mBindArgs != null) {
- int len = mBindArgs.length;
- try {
- for (int i = 0; i < len; i++) {
- super.bindString(i + 1, mBindArgs[i]);
- }
- } catch (SQLiteMisuseException e) {
- StringBuilder errMsg = new StringBuilder("mSql " + mSql);
- for (int i = 0; i < len; i++) {
- errMsg.append(" ");
- errMsg.append(mBindArgs[i]);
- }
- errMsg.append(" ");
- IllegalStateException leakProgram = new IllegalStateException(
- errMsg.toString(), e);
- throw leakProgram;
- }
+ if (mClosed) {
+ throw new IllegalStateException("requerying a closed cursor");
}
+ compileAndbindAllArgs();
}
- @Override
- public void bindNull(int index) {
- mBindArgs[index - 1] = null;
- if (!mClosed) super.bindNull(index);
- }
-
- @Override
- public void bindLong(int index, long value) {
- mBindArgs[index - 1] = Long.toString(value);
- if (!mClosed) super.bindLong(index, value);
- }
-
- @Override
- public void bindDouble(int index, double value) {
- mBindArgs[index - 1] = Double.toString(value);
- if (!mClosed) super.bindDouble(index, value);
- }
-
- @Override
- public void bindString(int index, String value) {
- mBindArgs[index - 1] = value;
- if (!mClosed) super.bindString(index, value);
- }
-
- private final native int native_fill_window(CursorWindow window,
+ private final native int native_fill_window(CursorWindow window,
int startPos, int offsetParam, int maxRead, int lastPos);
private final native int native_column_count();
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index 619764a..97e39d6 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -37,10 +37,10 @@ public class SQLiteStatement extends SQLiteProgram
private static final boolean WRITE = false;
private SQLiteDatabase mOrigDb;
- private int state;
- /** possible value for {@link #state}. indicates that a transaction is started.} */
+ private int mState;
+ /** possible value for {@link #mState}. indicates that a transaction is started.} */
private static final int TRANS_STARTED = 1;
- /** possible value for {@link #state}. indicates that a lock is acquired.} */
+ /** possible value for {@link #mState}. indicates that a lock is acquired.} */
private static final int LOCK_ACQUIRED = 2;
/**
@@ -49,8 +49,8 @@ public class SQLiteStatement extends SQLiteProgram
* @param db
* @param sql
*/
- /* package */ SQLiteStatement(SQLiteDatabase db, String sql) {
- super(db, sql, false /* don't compile sql statement */);
+ /* package */ SQLiteStatement(SQLiteDatabase db, String sql, Object[] bindArgs) {
+ super(db, sql, bindArgs, false /* don't compile sql statement */);
}
/**
@@ -166,7 +166,7 @@ public class SQLiteStatement extends SQLiteProgram
* methods in this class.
*/
private long acquireAndLock(boolean rwFlag) {
- state = 0;
+ mState = 0;
// use pooled database connection handles for SELECT SQL statements
mDatabase.verifyDbIsOpen();
SQLiteDatabase db = (mStatementType != DatabaseUtils.STATEMENT_SELECT) ? mDatabase
@@ -197,13 +197,13 @@ public class SQLiteStatement extends SQLiteProgram
// got update SQL statement. if there is NO pending transaction, start one
if (!mDatabase.inTransaction()) {
mDatabase.beginTransactionNonExclusive();
- state = TRANS_STARTED;
+ mState = TRANS_STARTED;
}
}
// do I have database lock? if not, grab it.
if (!mDatabase.isDbLockedByCurrentThread()) {
mDatabase.lock();
- state = LOCK_ACQUIRED;
+ mState = LOCK_ACQUIRED;
}
acquireReference();
@@ -218,13 +218,13 @@ public class SQLiteStatement extends SQLiteProgram
*/
private void releaseAndUnlock() {
releaseReference();
- if (state == TRANS_STARTED) {
+ if (mState == TRANS_STARTED) {
try {
mDatabase.setTransactionSuccessful();
} finally {
mDatabase.endTransaction();
}
- } else if (state == LOCK_ACQUIRED) {
+ } else if (mState == LOCK_ACQUIRED) {
mDatabase.unlock();
}
if (mStatementType == DatabaseUtils.STATEMENT_COMMIT ||