IllegalArgumentException: неверный столбец

Вот логарифм:

01-15 16:06:03.622: ERROR/AndroidRuntime(22300): Uncaught handler: thread main exiting due to uncaught exception
01-15 16:06:03.657: ERROR/AndroidRuntime(22300): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mohit.geo2do/com.mohit.geo2do.activities.TaskEdit}: java.lang.IllegalArgumentException: Invalid column due_date
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.app.ActivityThread.access$2200(ActivityThread.java:119)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.os.Looper.loop(Looper.java:123)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.app.ActivityThread.main(ActivityThread.java:4363)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at java.lang.reflect.Method.invokeNative(Native Method)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at java.lang.reflect.Method.invoke(Method.java:521)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:862)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at dalvik.system.NativeStart.main(Native Method)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300): Caused by: java.lang.IllegalArgumentException: Invalid column due_date
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.database.sqlite.SQLiteQueryBuilder.computeProjection(SQLiteQueryBuilder.java:508)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.database.sqlite.SQLiteQueryBuilder.buildQuery(SQLiteQueryBuilder.java:356)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:309)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:266)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at com.mohit.geo2do.provider.TasksProvider.query(TasksProvider.java:174)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.content.ContentProvider$Transport.query(ContentProvider.java:130)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.content.ContentResolver.query(ContentResolver.java:202)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at com.mohit.geo2do.activities.TaskEdit.onCreate(TaskEdit.java:105)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
01-15 16:06:03.657: ERROR/AndroidRuntime(22300):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)

Связанная с ним строка:

private Cursor task;
private Uri uri;
private String[] PROJECTION { 
    Tasks._ID, Tasks.TITLE, Tasks.COMPLETED, Tasks.DUE_DATE, Tasks.IMPORTANCE, Tasks.NOTES
};
...
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.edit_task);
    ...
    uri = getIntent().getData();
    task = getContentResolver().query(uri, PROJECTION, null, null, null);
} 
...

В чем может быть проблема? База создается нормально. Есть ли какой-либо другой код, который вам нужно увидеть?

ОБНОВЛЕНИЕ:
Я ОЧЕНЬ уверен, что этот столбец существует. Я запросил базу данных следующим образом:

Cursor c = db.rawQuery("SELECT * FROM tasks LIMIT 1", null);
for (int i = 0; i < c.getColumnNames().length; i++) {
    Log.v(TAG, c.getColumnNames()[i]);
}

И в ЛогКэт:

01-15 16:52:07.857: VERBOSE/TasksProvider(24325): Creating database...
01-15 16:52:07.862: VERBOSE/TasksProvider(24325): _id
01-15 16:52:07.862: VERBOSE/TasksProvider(24325): title
01-15 16:52:07.862: VERBOSE/TasksProvider(24325): completed
01-15 16:52:07.862: VERBOSE/TasksProvider(24325): due_date
01-15 16:52:07.862: VERBOSE/TasksProvider(24325): notes
01-15 16:52:07.862: VERBOSE/TasksProvider(24325): importance

Так что столбец ДЕЙСТВИТЕЛЬНО существует.


person Mohit Deshpande    schedule 15.01.2011    source источник
comment
Какая строка: 105? task = getContentResolver().query(uri, PROJECTION, null, null, null);   -  person fiction    schedule 16.01.2011
comment
О - "Неверный столбец due_date". Вы на 100% уверены, что такая колонка есть?   -  person fiction    schedule 16.01.2011
comment
Проверьте обновление. Я совершенно уверен, и у меня есть доказательство LogCat, что «due_date» ДЕЙСТВИТЕЛЬНО существует.   -  person Mohit Deshpande    schedule 16.01.2011
comment
Почему последние три значения в проекции определяются как «как»? Может быть, потому что эти значения являются целыми/длинными?   -  person kacee    schedule 04.02.2011


Ответы (3)


Столбец, несомненно, существует в вашей базе данных, но если вы не добавили его в нечто, называемое картой проекции, вы получите сообщение об ошибке "недопустимый столбец", которое вы видите. Вы можете добавить карту проекции через объект построителя запросов, например:

// The projection map is a hashmap of strings
HashMap<String, String> MyProjectionMap;
MyProjectionMap = new HashMap<String, String>();

// Add column mappings to the projection map
MyProjectionMap.put(Tasks._ID, Tasks._ID);
MyProjectionMap.put(Tasks.TITLE, Tasks.TITLE);
[...]

SQLiteQueryBuilder qb;
qb.setTables("tasks");
qb.setProjectionMap(MyProjectionMap)

// Then do your query
Cursor c = qb.query(db, projection, ...)

Чтобы понять, что происходит, загляните в исходный код класса SQLiteQueryBuilder, и вы увидите следующее:

private String[] computeProjection(String[] projectionIn) {
    if (projectionIn != null && projectionIn.length > 0) {
       if (mProjectionMap != null) {
          [...]
          for (int i = 0; i < length; i++) {
             String userColumn = projectionIn[i];
             String column = mProjectionMap.get(userColumn);
             [...]
             if (!mStrictProjectionMap && ( userColumn.contains(" AS ") || userColumn.contains(" as "))) {
                /* A column alias already exist */
                projection[i] = userColumn;
                continue;
             }
             throw new IllegalArgumentException("Invalid column " + projectionIn[i]);
          }
      }
[...]

По сути, это проверка столбцов, которые вы запросили в своей проекции, по списку «разрешенных» столбцов, и вы можете видеть, что если карта не содержит столбца из вашей проекции, она выдаст исключение IllegalArgumentException, как вы видели. (Я предполагаю, что эта проверка по карте является функцией безопасности для предотвращения атак на основе SQL от людей, злоупотребляющих вашим контент-провайдером, но это всего лишь предположение.)

Также обратите внимание, что если вы установите «строгие» проекционные карты в своем построителе запросов:

qb.setStrictProjectionMap(true);

Затем в этом случае он ожидает, что вы знаете точные имена столбцов... Если вы не установите его, он проверит псевдоним столбца «AS» — я думаю, это объясняет «странное исправление», которое вы обнаружили.

Надеюсь это поможет.

person DMH    schedule 21.07.2011

Я нашел странное решение для этого. В 1_. Ты должен сделать:

private String[] PROJECTION { 
    Tasks._ID, 
    Tasks.TITLE, 
    Tasks.COMPLETED,
    Tasks.DUE_DATE + " as " + Tasks.DUE_DATE, 
    Tasks.IMPORTANCE + " as " + Tasks.DUE_DATE, 
    Tasks.NOTES + " as " + Tasks.NOTES
};
person Mohit Deshpande    schedule 15.01.2011

Вы добавили этот столбец в карту проекции поставщика контента относительно таблицы с этим столбцом? Надеюсь, это поможет.

person Paco    schedule 10.02.2011