2012-12-09 103 views
1

我試圖執行具有各種條件查詢和我得到一個例外。複雜的SQLite查詢給

bind or column index out of range 

這是來自ContentProvider的查詢。

@Override 
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); 
    int uriType = sURIMatcher.match(uri); 
    switch (uriType) { 
    case RESPONSEVIEW2_SELECTION_10: 
     queryBuilder.setTables(RESPONSES_VIEW); 
     String activeUserKey = getActiveUserId();; 
     String outerSelection = 
       "(((" + PeerCreatedDataColumns.SHARED + "=" + "" + trueId + "" + ") OR " 
       + "(" + PeerCreatedDataColumns.AUTHORHASH + "=" + "'" + activeUserKey + "'" + ")) AND (" 
       + "(" + ResponsesColumns.PRIMARYMATCH + "= '*'" + ") OR " 
            // '*' is defined by the program, hopefully not in conflict with anything built-in 
       + "(" + ResponsesColumns.PRIMARYMATCH + " like '?') OR " 
       + "(" + ResponsesColumns.PRIMARYMATCH + " like '" + selectionArgs[0] + "%') OR " 
       + "(" + ResponsesColumns.PRIMARYMATCH + " like '%" + selectionArgs[0] + "') OR " 
       + "(" + ResponsesColumns.PRIMARYMATCH + " like '%" + selectionArgs[0] + "%'" + ")))"; 
     Log.d(DEBUG_TAG, "query " + outerSelection); 
     Cursor cursor10 = queryBuilder.query(mDB.getReadableDatabase(), projection, outerSelection, selectionArgs, 
       null, null, sortOrder); 
     cursor10.setNotificationUri(getContext().getContentResolver(), uri); 
     Log.e(DEBUG_TAG, "responses_view2 should have better search function"); 
     return cursor10; 
    case ROW_SELECTION_11: 
     queryBuilder.setTables(RESPONSES_VIEW); 
     Log.e(DEBUG_TAG, "responses_view2 should have better search function"); 
     queryBuilder.appendWhere(PeerDatabase._ID + "=" + uri.getLastPathSegment()); 
     Cursor cursor11 = queryBuilder.query(mDB.getReadableDatabase(), projection, selection, selectionArgs, null, 
       null, sortOrder); 
     cursor11.setNotificationUri(getContext().getContentResolver(), uri); 
     return cursor11; 
    ... 
    } 
} 

這裏是光標加載器,它似乎是錯誤的來源。

public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
    if (search == null) { 
     return null; 
    } else { 
     String[] selectArgs = { search }; 
     return new CursorLoader(getActivity(), table, createProjection, "?", selectArgs, null); 
    } 
} 

下面是完整的錯誤:

12-09 18:25:54.509: E/AndroidRuntime(12461): FATAL EXCEPTION: ModernAsyncTask #2 
12-09 18:25:54.509: E/AndroidRuntime(12461): java.lang.RuntimeException: An error occured while executing doInBackground() 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.support.v4.content.ModernAsyncTask$3.done(ModernAsyncTask.java:137) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.util.concurrent.FutureTask.setException(FutureTask.java:125) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.lang.Thread.run(Thread.java:1019) 
12-09 18:25:54.509: E/AndroidRuntime(12461): Caused by: android.database.sqlite.SQLiteException: bind or column index out of range: handle 0x28bd08 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.database.sqlite.SQLiteProgram.native_bind_string(Native Method) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.database.sqlite.SQLiteProgram.bindString(SQLiteProgram.java:244) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.database.sqlite.SQLiteQuery.bindString(SQLiteQuery.java:185) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:48) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1356) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:330) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:280) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at org.anuvar.plana.m.provider.PeerDataProvider.query(PeerDataProvider.java:285) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.content.ContentProvider$Transport.query(ContentProvider.java:187) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.content.ContentResolver.query(ContentResolver.java:262) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:49) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:35) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:240) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:51) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:40) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:123) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306) 
12-09 18:25:54.509: E/AndroidRuntime(12461): ... 4 more 

我試圖找出異常,但請讓我知道是否有更好的方式來查詢數據。

回答

4

selection參數中的?的數量必須與selectionArgs參數中的字符串數量相匹配。 LogCat表明這些計數不匹配,但我們很難分辨...

我發現了這個問題,請不要將?用引號括起來,否則你就會從字面上尋找一個問號。這是不正確的:

" like '?') OR " 

而是使用:

" like ?) OR " 

如果search是用戶輸入的,你應該保護自己免受SQL注入攻擊:

+ "(" + ResponsesColumns.PRIMARYMATCH + " like ?) OR " 
+ "(" + ResponsesColumns.PRIMARYMATCH + " like ?) OR " 
+ "(" + ResponsesColumns.PRIMARYMATCH + " like ?) OR " 
+ "(" + ResponsesColumns.PRIMARYMATCH + " like ?)))"; 

,並創建一個新的selectionArgs參數是這樣的:

String search = selectionArgs[0]; 
String[] matchArgs = { search, search + "%", "%" + search, "%" + search + "%" }; 
Cursor cursor10 = queryBuilder.query(mDB.getReadableDatabase(), projection, 
      outerSelection, matchArgs, null, null, sortOrder); 
+0

感謝。我把所有的東西放在一起時遇到了一些麻煩。這好多了。 – KrisC