rawQuery returning 0 results when arrayOf() passed as parameter

Hello SQLcipher developers/users. I’ve been in Android development for now 13 years and I’ve never seen anything like this.

Yesterday I found out that we need to do the migration from original SQLCipher android lib to the new long-term remplaement. I did just that.

Replaced net.zetetic:android-database-sqlcipher:4.5.4 with net.zetetic:sqlcipher-android:4.7.2@aar
Also I already had androidx.sqlite:sqlite:2.3.1 in the codebase.

Project built correctly. Also, it ran correctly after a modification of passing password to the database unlocking (in SQLiteOpenHelper instead of passing it to in getWritableDatabase or getReadableDatabase).

Now, the only problem I have is with functionality of the app. Everything works fine with the app until you get to a screen needing to show one specific label.

I fetch it like this:

database.rawQuery(sql, arrayOf(testStringId, testIntegerId)).use { cursor →
hasRecords = c.moveToFirst()

hasRecords is always false even though the data is there (I downloaded the database locally, opened it with DB Browser for SQLite, unlocked it with the password and run the same query and it returned the needed results.

Now, the interesting part.
When I fetch it like this:

val sql = “SELECT * FROM TestTable WHERE testStringId = ‘2df6bfd8-9418-4e25-a7ca-29d0a08c6275’ AND testIntegerId = 0”

database.rawQuery(sql, null).use { cursor →
hasRecords = c.moveToFirst()

hasRecords is on true and cursor contains data.

How is that possible? What am I missing? I’ve been on this problem from this morning and I’ve ran out of ideas. Also I’m ready for some mental institution :sweat_smile:

If anyone experienced something similar I would appreciate the help.

Ok, I’ve found out a solution, but still have no idea why it’s working like that in the SQLiteDatabase implementation in sqlcipher lib.

This works:

database.rawQuery(sql, testStringId, testIntegerId).use { cursor →

I have to pass the arguments as varargs. If sent as arrayOf, it’s hitting another override of method passing arguments as Objects and it’s not working.

Anyone from development team to clear the confusion? Have I found some issue in the lib or I totally have no idea how it works?

Hi @tosulc,

I am happy to hear you were able to resolve the issue by passing your arguments for the query as varargs, sorry for the troubling behavior. I suspect when you are invoking the query with arrayOf(...), it may be dispatching to the other override for rawQuery which will accept a String[] as arguments. In that situation, each parameter will be bound as a String value using sqlite3_bind_text16, but if your column for testIntegerId has a column of type INTEGER, the query would not resolve properly to the record you are searching for. As you have observed, when you utilize rawQuery with varargs, each parameter type is inspected during the binding operation. In your case, the testIntegerId would be bound using sqlite3_bind_int64.

As an aside, since you are just updating to sqlcipher-android, you may wish to update to the latest release which is currently 4.9.0.

Ok, it makes sense. But that wasn’t specified anywhere in the documentation… that’s what troubles me.

btw. where can I track new releases? On GitHub - sqlcipher/sqlcipher-android: SQLCipher for Android provides an interface to SQLCipher databases on the Android platform. I can see 4.6.0 as the latest release. On Maven repo I can see the version you specified but I can’t see any changelog there.

Hi @tosulc,

SQLCipher for Android releases are made in tandem with SQLCipher core releases. We publish detailed announcements on our blog. For example, the latest 4.9.0 release may be found here [1]. Additionally, you may subscribe to SQLCipher release announcements on our Discuss site here [2].

[1] SQLCipher 4.9.0 Release - Security Update | Zetetic
[2] Updates - Zetetic Community Discussion

1 Like

I encountered the same issue when migrating from android-database-sqlcipher:4:3:0 to sqlcipher-android:4.9.0

but i have tons of instances where i am using cursor.rawQuery with arrayOf binds. what’s the best solution for me?

Can you tell me any version which I downgrade to? which has android 16kb support and where i dont have to change this rawQuery thing?

above snippet when i use cursor.rawQuery which gives moveToNext as false, below snippet on same when we use cursor.query gives moveToNext as true for the same SQL Statement

both methods executes the same method in the end which is

public Cursor rawQuery(String sql, Object... bindingArgs) {
        acquireReference();
        try {
            SQLiteDirectCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, null, null);
            return driver.query(mCursorFactory, bindingArgs);
        } finally {
            releaseReference();
        }
    }

Hi @Aurangzaib_Umer,

The solution [1] above was to invoke your method with varargs instead of arrayOf. The sqlcipher-android library already has support for 16 KB page sizes. Additionally, we have limited, post-end-of-life support for android-database-sqlcipher with 16 KB page support through Commercial licensing [2].


  1. rawQuery returning 0 results when arrayOf() passed as parameter - #3 by developernotes ↩︎

  2. SQLCipher for Android: 16KB Page Size Support | Zetetic ↩︎

but the snippet/screenshot i shared it with you, whats the logic in that? cursor.query calls the same method inside sqlitedatabase which is rawQuery having argument has Object …bindingArgs. Hence both cursor.rawQuery and cursor.query calls the same method inside but somehow cursor.query returns result while cursor.rawQuery not.

Well, I just published an article related to 16kb support specifically upgrading to sqlcipher-android from legacy androdi-database-sqlcipher. I can also add a new blog here helping in detail whoever face an issue with the migration.

here’s a medium article : Preparing for Android 15+: 16KB Page Size Compatibility and SQLCipher Migration | by Aurangzaib Umer | Jul, 2025 | Medium

Hi @Aurangzaib_Umer,

Can you share more specific details regarding which override of rawQuery and query you are invoking? Additionally, are you using arrayOf, or providing the arguments via varargs?