2222package io .requery .android .database .sqlite ;
2323
2424import android .annotation .SuppressLint ;
25+ import android .annotation .TargetApi ;
2526import android .database .Cursor ;
26- import android .database .DatabaseUtils ;
2727import android .database .sqlite .SQLiteBindOrColumnIndexOutOfRangeException ;
2828import android .database .sqlite .SQLiteDatabaseLockedException ;
2929import android .database .sqlite .SQLiteException ;
30+ import android .os .Build ;
31+ import android .os .Looper ;
3032import android .os .ParcelFileDescriptor ;
3133import android .support .v4 .os .CancellationSignal ;
3234import android .support .v4 .os .OperationCanceledException ;
35+ import android .support .v4 .util .LruCache ;
3336import android .util .Log ;
34- import android .util .LruCache ;
3537import android .util .Printer ;
3638import io .requery .android .database .CursorWindow ;
3739
8991 *
9092 * @hide
9193 */
92- @ SuppressWarnings ({ "unused" , "ForLoopReplaceableByForEach" , " TryFinallyCanBeTryWithResources"} )
94+ @ SuppressWarnings (" TryFinallyCanBeTryWithResources" )
9395public final class SQLiteConnection implements CancellationSignal .OnCancelListener {
9496 private static final String TAG = "SQLiteConnection" ;
9597 private static final boolean DEBUG = false ;
@@ -325,12 +327,13 @@ private void setSyncMode(String newValue) {
325327 }
326328
327329 private static String canonicalizeSyncMode (String value ) {
328- if (value .equals ("0" )) {
329- return "OFF" ;
330- } else if (value .equals ("1" )) {
331- return "NORMAL" ;
332- } else if (value .equals ("2" )) {
333- return "FULL" ;
330+ switch (value ) {
331+ case "0" :
332+ return "OFF" ;
333+ case "1" :
334+ return "NORMAL" ;
335+ case "2" :
336+ return "FULL" ;
334337 }
335338 return value ;
336339 }
@@ -345,10 +348,14 @@ private void setJournalMode(String newValue) {
345348 }
346349 // PRAGMA journal_mode silently fails and returns the original journal
347350 // mode in some cases if the journal mode could not be changed.
348- } catch (SQLiteDatabaseLockedException ex ) {
351+ } catch (SQLiteException ex ) {
349352 // This error (SQLITE_BUSY) occurs if one connection has the database
350353 // open in WAL mode and another tries to change it to non-WAL.
354+ if (!(ex instanceof SQLiteDatabaseLockedException )) {
355+ throw ex ;
356+ }
351357 }
358+
352359 // Because we always disable WAL mode when a database is first opened
353360 // (even if we intend to re-enable it), we can encounter problems if
354361 // there is another open connection to the database somewhere.
@@ -475,14 +482,6 @@ boolean isPreparedStatementInCache(String sql) {
475482 return mPreparedStatementCache .get (sql ) != null ;
476483 }
477484
478- /**
479- * Gets the unique id of this connection.
480- * @return The connection id.
481- */
482- public int getConnectionId () {
483- return mConnectionId ;
484- }
485-
486485 /**
487486 * Returns true if this is the primary database connection.
488487 * @return True if this is the primary database connection.
@@ -711,7 +710,11 @@ public ParcelFileDescriptor executeForBlobFileDescriptor(String sql, Object[] bi
711710 try {
712711 int fd = nativeExecuteForBlobFileDescriptor (
713712 mConnectionPtr , statement .mStatementPtr );
714- return fd >= 0 ? ParcelFileDescriptor .adoptFd (fd ) : null ;
713+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .HONEYCOMB_MR2 ) {
714+ return fd >= 0 ? ParcelFileDescriptor .adoptFd (fd ) : null ;
715+ } else {
716+ throw new UnsupportedOperationException ();
717+ }
715718 } finally {
716719 detachCancellationSignal (cancellationSignal );
717720 }
@@ -918,7 +921,7 @@ private PreparedStatement acquirePreparedStatement(String sql) {
918921 final long statementPtr = nativePrepareStatement (mConnectionPtr , sql );
919922 try {
920923 final int numParameters = nativeGetParameterCount (mConnectionPtr , statementPtr );
921- final int type = DatabaseUtils .getSqlStatementType (sql );
924+ final int type = SQLiteStatementType .getSqlStatementType (sql );
922925 final boolean readOnly = nativeIsReadOnly (mConnectionPtr , statementPtr );
923926 statement = obtainPreparedStatement (sql , statementPtr , numParameters , type , readOnly );
924927 if (!skipCache && isCacheable (type )) {
@@ -1009,9 +1012,13 @@ public void onCancel() {
10091012 private void bindArguments (PreparedStatement statement , Object [] bindArgs ) {
10101013 final int count = bindArgs != null ? bindArgs .length : 0 ;
10111014 if (count != statement .mNumParameters ) {
1012- throw new SQLiteBindOrColumnIndexOutOfRangeException (
1013- "Expected " + statement .mNumParameters + " bind arguments but "
1014- + count + " were provided." );
1015+ String message = "Expected " + statement .mNumParameters + " bind arguments but "
1016+ + count + " were provided." ;
1017+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .HONEYCOMB ) {
1018+ throw new SQLiteBindOrColumnIndexOutOfRangeException (message );
1019+ } else {
1020+ throw new SQLiteException (message );
1021+ }
10151022 }
10161023 if (count == 0 ) {
10171024 return ;
@@ -1065,6 +1072,7 @@ private void bindArguments(PreparedStatement statement, Object[] bindArgs) {
10651072 * @param obj the object whose value type is to be returned
10661073 * @return object value type
10671074 */
1075+ @ TargetApi (Build .VERSION_CODES .HONEYCOMB )
10681076 private static int getTypeOfObject (Object obj ) {
10691077 if (obj == null ) {
10701078 return Cursor .FIELD_TYPE_NULL ;
@@ -1088,15 +1096,21 @@ private void throwIfStatementForbidden(PreparedStatement statement) {
10881096 }
10891097
10901098 private static boolean isCacheable (int statementType ) {
1091- if (statementType == DatabaseUtils .STATEMENT_UPDATE
1092- || statementType == DatabaseUtils .STATEMENT_SELECT ) {
1093- return true ;
1094- }
1095- return false ;
1099+ return statementType == SQLiteStatementType .STATEMENT_UPDATE
1100+ || statementType == SQLiteStatementType .STATEMENT_SELECT ;
10961101 }
10971102
10981103 private void applyBlockGuardPolicy (PreparedStatement statement ) {
1099-
1104+ if (!mConfiguration .isInMemoryDb () && SQLiteDebug .DEBUG_SQL_LOG ) {
1105+ // don't have access to the policy, so just log
1106+ if (Looper .myLooper () == Looper .getMainLooper ()) {
1107+ if (statement .mReadOnly ) {
1108+ Log .w (TAG , "Reading from disk on main thread" );
1109+ } else {
1110+ Log .w (TAG , "Writing to disk on main thread" );
1111+ }
1112+ }
1113+ }
11001114 }
11011115
11021116 /**
@@ -1369,8 +1383,7 @@ public int beginOperation(String kind, String sql, Object[] bindArgs) {
13691383 } else {
13701384 operation .mBindArgs .clear ();
13711385 }
1372- for (int i = 0 ; i < bindArgs .length ; i ++) {
1373- final Object arg = bindArgs [i ];
1386+ for (final Object arg : bindArgs ) {
13741387 if (arg != null && arg instanceof byte []) {
13751388 // Don't hold onto the real byte array longer than necessary.
13761389 operation .mBindArgs .add (EMPTY_BYTE_ARRAY );
@@ -1427,6 +1440,9 @@ private boolean endOperationDeferLogLocked(int cookie) {
14271440
14281441 private void logOperationLocked (int cookie , String detail ) {
14291442 final Operation operation = getOperationLocked (cookie );
1443+ if (operation == null ) {
1444+ return ;
1445+ }
14301446 StringBuilder msg = new StringBuilder ();
14311447 operation .describe (msg , false );
14321448 if (detail != null ) {
0 commit comments