4

最近、次のようなコードが原因でいくつかのバグが発生しました。

Cursor myCursor = myDb.rawQuery(
        "SELECT ... " +
        "  FROM ...complicated join... " +
        " WHERE field1 = ? AND (field2 = ? OR field3 = ?) ",
        new String[] {myField1, myField2});   // Oops, forgot about field3

これが発生すると、クエリは欠落しているパラメータを黙って無視し、バグが見過ごされてしまいます。pedanticプレースホルダーの数とフィールドの数が一致しない場合にSQLiteを(実行時に)悲鳴を上げるために使用できる設定などはありますか?

自分でラッパーを作成できることは知っていますが、何かが組み込まれているのではないかと思います...

4

1 に答える 1

1

Androidは基本的に、チェックされていない引数をネイティブsqliteに渡すだけです。http: //www.sqlite.org/c3ref/bind_blob.htmlを参照してください。

何かがバインドされていない場合、それは単にNULLにバインドされていると見なされます。バインドしすぎるとエラーが発生するはずですが

私はその種のチェックのためのAndroidのソースのデバッグオプションを知りません/見たことがありませんが、おそらくあなたのSQL構文をチェックするいくつかのコードを書くことができます:

SQLiteChecker mDbChecked = new SQLiteChecker(mDb);
Cursor c = mDbChecked.rawQuery("select complicated from table where stuff=?",
        new String[] {"one", "two"});

ここで、SQLiteCheckerは次のようなものになります。

/**
 * Simple Delegate for SQLiteDatabase
 */
public class SQLiteChecker {
    private final SQLiteDatabase mDbDelegate;
    public SQLiteChecker(SQLiteDatabase db) {
        mDbDelegate = db;
    }
    // ------------ Delegate methods --------------------//
    public int delete(String table, String whereClause, String[] whereArgs) {
        checkSQL(whereClause, whereArgs);
        return mDbDelegate.delete(table, whereClause, whereArgs);
    }

    public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
        checkSQL(whereClause, whereArgs);
        return mDbDelegate.update(table, values, whereClause, whereArgs);
    }

    public void execSQL(String sql, Object[] bindArgs) throws SQLException {
        checkSQL(sql, bindArgs);
        mDbDelegate.execSQL(sql, bindArgs);
    }

    public Cursor rawQuery(String sql, String[] selectionArgs) {
        checkSQL(sql, selectionArgs);
        return mDbDelegate.rawQuery(sql, selectionArgs);
    }

    // add more if you need

    // -------------- checking logic -------------------//
    private static void checkSQL(String query, Object[] args) {
        // bit unreliable but simple:
        // just check if amount of ? matches args.length
        int expected = countChar(query, '?');
        int actual = args != null ? args.length : 0;
        if (expected != actual) {
            Log.e("CHECK", "You seem to have messed up [" + query + "]");
            Log.e("CHECK", "expected:" + expected + " actual:" + actual);
        }
    }

    private static int countChar(String string, char ch) {
        if (string == null) return 0;
        int count = 0;
        for (int i = 0; i < string.length(); i++) {
            if (string.charAt(i) == ch)
                count++;
        }
        return count;
    }
}
于 2012-11-12T15:07:01.050 に答える