Question

I'm trying to create a Cursor from a table, constrained to a certain set of ID's, passed into the selection arguments as follows: (simplified for readability)

String[] ids; //The id's to constrain the cursor to
StringBuilder selection;

//for each id, add to the selection
for(int i = 0; i < ids.length(); i++) {
    selection = Table.column._ID + " = " + ids[i];
        if(i < ids.length -1) {
            selection.append( "OR" ) //Add an "OR" after each selection (except the last)
        }
}    

Cursor cursor = query(uri, projection, selection.toString(), null, null);

The idea is that this Cursor will be filled with any item whose id matches an item in the list.

This works ok, except for a huge list, I get an SQLiteException, as the argument is too large:

android.database.sqlite.SQLiteException: Expression tree is too large (maximum depth 1000)

I understand why this is happening. The query is built as:

 selection = Table.column._ID = id[1] OR Table.column._ID = id[2] ... 

And can get pretty massive.

The question is, how can I make this query work? Surely there is a more efficient way to populate a Cursor with a huge list of constraints / selection criteria, right?

Should I be passing the ids into selectionArgs and dealing with it that way?

Was it helpful?

Solution

Thanks to pskink for his input. The answer is to use the 'IN' operator.

String[] ids; //The id's to constrain the cursor to
StringBuilder selection;

selection = Table.column._ID + " IN (";
for(int i = 0; i < ids.length(); i++) {
    selection.append(ids[i]);
        if(i < ids.length -1) {
            selection.append( "," ) //Add an "," after each selection (except the last)
        }
}
selection.append(")");   

This is the equivalent of:

Selection = "Table.column._ID IN (ids[1], ids[2], ids[3], ...);

Which is much better than:

Selection = "Table.column._ID = ids[1] OR Table.column._ID = ids[2] OR Table.column._ID = ids[3] ...";
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top