pushtorefresh / storio

Reactive API for SQLiteDatabase and ContentResolver.
Apache License 2.0
2.55k stars 182 forks source link

executeSQL(): crashes when executing no-args query #509

Closed vokilam closed 9 years ago

vokilam commented 9 years ago

Here is the setup:

db.executeSQL()
        .withQuery(RawQuery.builder()
                .query("DROP TABLE IF EXISTS items")
                .build())
        .prepare()
        .executeAsBlocking();

This fails with following exception:

 Caused by: java.lang.IllegalArgumentException: Empty bindArgs
        at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1651)
        at com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite$InternalImpl.executeSQL(DefaultStorIOSQLite.java:286)
        at com.pushtorefresh.storio.sqlite.operations.execute.PreparedExecuteSQL.executeAsBlocking(PreparedExecuteSQL.java:53)

This happens, because overloaded android.database.sqlite.SQLiteDatabase#execSQL(java.lang.String, java.lang.Object[]) does not accept null bindArgs (as per android-23 source), while DefaultStorIOSQLite implementation passes nullableArrayOfStrings(rawQuery.args()) as bindArgs.

I also tried a workaround:

db.executeSQL()
        .withQuery(RawQuery.builder()
                .query("DROP TABLE IF EXISTS ?")
                .args("items")
                .build())
        .prepare()
        .executeAsBlocking();

This fails with the following exception:

 Caused by: android.database.sqlite.SQLiteException: near "?": syntax error (code 1): , while compiling: DROP TABLE IF EXISTS ?
        at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
        at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
        at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
        at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
        at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
        at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
        at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1672)
        at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1653)
        at com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite$InternalImpl.executeSQL(DefaultStorIOSQLite.java:286)
        at com.pushtorefresh.storio.sqlite.operations.execute.PreparedExecuteSQL.executeAsBlocking(PreparedExecuteSQL.java:53)

I guess, binding is supported for values only (not for table or column names). So, I also doubt code in this README section works. Guys, please, take a look.

artem-zinnatullin commented 9 years ago

I'll take a look asap, sorry for this bug!

artem-zinnatullin commented 9 years ago

@vokilam prepared PR with fix, 1.3.1 will be released asap!

vokilam commented 9 years ago

Please, fix documentation also.

artem-zinnatullin commented 9 years ago

@vokilam just published v1.3.1 with fix to the Maven Central, should be available in 10-20 minutes!

Thanks for bug report!