Question

I just encountered something strange. Say I have a table

_id | caption
 1  | foo

and I execute the following query on it directly in SQLite:

select _id, (caption != "bar") as caption from the_table;

I get the (expected) output:

_id | caption
 1  | 1

Executing this code however:

// This will execute the EXACT SAME query (checked via debugger)
Cursor affected = db.query(table, (String[]) projection.toArray(new String[0]), selection, selectionArgs, null, null, null); 
// ############ UPDATE ROW 1 TO CAPTION=bar #######
int result = db.update(table, values, selection, selectionArgs);

affected.moveToPosition(-1);        
while (affected.moveToNext()) {
    long id = affected.getLong(0); // We made the _id column the first in the projection
    for (int i = 1; i < affected.getColumnCount(); i++) {
        Log.d("xyz", affected.getInt(i) + "");
    }
}

gets me: "xyz 0" in LogCat.

Does the cursor execute the query lazily on the first cursor access?

It seems to work if I insert affected.getCount() right after the query.

Was it helpful?

Solution

Yes, there are leaky abstractions.

Query alone translates to a prepare call that compiles the SQL to a sqlite program (think bytecode). The program is not run.

To run a compiled sqlite program, one would use the step which either returns a result row, finihsed status code, or an error. In Android, you effectively run the program by calling one of the moveTo...() methods on the returned cursor.

Getting cursor count is not directly supported by the sqlite C API. Android implements it by running the query and storing the results in a "cursor window" buffer. The same buffer is used for accessing the cursor's data later.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top