Search code examples
androidandroid-sqliteandroid-contentproviderandroid-contentresolverandroid-context

Android: Invalid column count(*) in ContentResolver query()


I am developing an Android application and I want to read the call log. I have found tons of ways to do it but I want to use more complex queries such as COUNT, SUM combined with GROUP BY.

The following works:

Uri allCalls = Uri.parse("content://call_log/calls");
Cursor cursor = context.getContentResolver().query(allCalls, null, null, null, null);

If I want to use more advanced syntax, like the following

Uri allCalls = Uri.parse("content://call_log/calls");
String[] columns = new String[] { CallLog.Calls.NUMBER, CallLog.Calls.CACHED_NAME, "count(" + CallLog.Calls.NUMBER + ") as total" };
String selection = " 0 == 0) (GROUP BY (" + CallLog.Calls.NUMBER + "), (" + CallLog.Calls.CACHED_NAME + ")";
Cursor cursor = context.getContentResolver().query(allCalls, columns, selection, null, "count("+ CallLog.Calls.NUMBER +") DESC");

the application crashes with the following error:

java.lang.IllegalArgumentException: Invalid column count(number) as total

I have tried different variants like count(*) as total, count(*) without the "as total", but still nothing.

Do you have any ideas what am I doing wrong?

I am developing in Android API level 19 (4.4.2)

Thanks


Solution

  • It is crashing because your use of count(" + CallLog.Calls.NUMBER + ") as total in the columns variable is illegal. You can only put Strings representing column names into that argument to contentResolver.query(), such as CallLog.Calls.NUMBER, nothing else. You can retrieve a count by running a query and then getting the count from the cursor returned, but the content provider/resolver model really does not support a group by clause. I've never tried but maybe someone else knows a workaround for that. But your group by clause is being interpreted as part of an SQL where clause. It does support an order by clause so replacing your query call with the following may be helpful :

    Cursor cursor = context.getContentResolver().query(allCalls, columns, selection, null, CallLog.Calls.NUMBER + "," + CallLog.Calls.CACHED_NAME);