Android - Выберите максимум в контент-провайдере - PullRequest
5 голосов
/ 15 февраля 2011

Я пытаюсь выполнить этот запрос на моем пользовательском контент-провайдере.

cursor = activity.getContentResolver().query(
                GoalDescriptor.CONTENT_URI,
                "max(priority)", null,
                null, null);

для получения максимального значения приоритета int столбца.

я пробовал также:

cursor = activity.getContentResolver().query(
                GoalDescriptor.CONTENT_URI,
                null, "max(priority)",
                null, null);

безуспешно.

Этот код возвращает это исключение:

    java.lang.IllegalArgumentException: Invalid column MAX(priority)
E/DatabaseUtils(  688):     at android.database.sqlite.SQLiteQueryBuilder.computeProjection(SQLiteQueryBuilder.java:523)
E/DatabaseUtils(  688):     at android.database.sqlite.SQLiteQueryBuilder.buildQuery(SQLiteQueryBuilder.java:370)
E/DatabaseUtils(  688):     at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:323)
E/DatabaseUtils(  688):     at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:280)
E/DatabaseUtils(  688):     at nan.salsa.contentprovider.goal.GoalContentProvider.query(GoalContentProvider.java:118)
E/DatabaseUtils(  688):     at android.content.ContentProvider$Transport.bulkQuery(ContentProvider.java:150)
E/DatabaseUtils(  688):     at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:111)
E/DatabaseUtils(  688):     at android.os.Binder.execTransact(Binder.java:288)
E/DatabaseUtils(  688):     at dalvik.system.NativeStart.run(Native Method)
D/AndroidRuntime(  727): Shutting down VM

Реализация поставщика содержимого (стандарт- см. образец блокнота)

public Cursor query(Uri uri, String[] projection, String selection,
        String[] selectionArgs, String sortOrder) {
    SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
    qb.setTables(GoalDescriptor.TABLE_NAME);

    switch (sUriMatcher.match(uri)) {

    case GOAL:
        qb.setProjectionMap(sGoalProjectionMap);
        qb.appendWhere(GoalDescriptor._ID + "="
                + uri.getPathSegments().get(1));
        break;

    case GOALS:
        qb.setProjectionMap(sGoalProjectionMap);
        break;

    default:
        throw new IllegalArgumentException("Unknown URI " + uri);
    }

    // If no sort order is specified use the default
    String orderBy;
    if (TextUtils.isEmpty(sortOrder)) {
        orderBy = GoalInfo.GoalDescriptor.DEFAULT_SORT_ORDER;
    } else {
        orderBy = sortOrder;
    }

    // Get the database and run the query
    SQLiteDatabase db = mOpenHelper.getReadableDatabase();
    Cursor c = qb.query(db, projection, selection, selectionArgs, null,
            null, orderBy);

    // Tell the cursor what uri to watch, so it knows when its source data
    // changes
    c.setNotificationUri(getContext().getContentResolver(), uri);
    return c;
}

Вы можете мне помочь?

С уважением

Ответы [ 3 ]

16 голосов
/ 15 февраля 2011

Вы отправляете максимальный (приоритет) в качестве проекции, отправляете его как выбор, и он должен работать.

См. Этот вопрос: Android: получите наибольшее значение в столбце

Редактировать:

Похоже, это должно работать:

cursor = activity.getContentResolver().query(
         GoalDescriptor.CONTENT_URI,
          new String[] {"MAX(priority) AS max_priority"}, null,
         null, null);
1 голос
/ 15 марта 2012

К сожалению, ответ nEx (с использованием «AS» для предоставления псевдонима для столбца) работает только с поставщиками, которые не устанавливают флаг strictProjectionMap в своем SQLiteQueryBuilder. Например. поставщик контактов устанавливает этот флаг, поэтому, если вы попробуете использовать подход AS, вы все равно получите ошибку «Неправильный столбец».

И если кто-то может сказать мне, как указание агрегирующей функции, такой как MAX, должно работать, я был бы очень благодарен. Если я попробую это сделать, я получу исключение «неправильное использование агрегатной функции», чего я и ожидал от попытки поместить агрегатную функцию в предложение WHERE. Я знаю, что вы можете поместить подзапрос в предложение WHERE, но это предполагает, что вы знаете фактическую структуру таблицы и что она никогда не изменится на каком-либо конкретном уровне устройства или ОС, на что я бы не хотел делать ставку (в конце концов, поэтому прежде всего мы используем интерфейс провайдера, чтобы абстрагироваться от основного хранилища данных).

Итак ... Я не знаю ни одного способа сделать это для провайдеров, которые устанавливают флаг strictProjectionMap, кроме как для сортировки DESC по требуемому полю, и, предпочтительно, LIMIT до 1 строки, если провайдер поддерживает это (или если вы готовы рискнуть что-то сломать, включив LIMIT в строку сортировки). Я был бы очень рад, если бы кто-то знал другие подходы для этих случаев!

0 голосов
/ 06 марта 2016

В моем случае ответ nEx на самом деле работал, но я забыл также добавить "max _" + COLUMN_NAME в методе getColumnIndexByName () курсора.

После того, как я понял, это тоже нужно было изменить, наконец-то это сработало!

...