IllegalArgumentException:无效列

发布于 2024-10-12 08:27:47 字数 4452 浏览 4 评论 0原文

这是 logcat:

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]);
}

在 LogCat 中:

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

所以该列确实存在。

Here is the logcat:

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)

The line that's associated with it is:

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);
} 
...

What could be the problem? The database is created just fine. Is there any other code you'd need to see?

UPDATE:
I am VERY sure this column exists. I queried the database with this:

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]);
}

And in LogCat:

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

So the column DOES exist.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

荒人说梦 2024-10-19 08:27:47

毫无疑问,该列确实存在于您的数据库中,但如果您尚未将该列添加到称为投影图的事物中,您将收到所看到的“无效列”错误。您可以通过查询生成器对象添加投影图,如下所示:

// 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”列别名 - 我认为这解释了您发现的“奇怪的修复”。

希望这有帮助。

The column undoubtedly does exist in your database, but if you haven't added the column to a thing called the projection map, you'll get the "invalid column" error you're seeing. You can add the projection map via a query builder object, like this:

// 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, ...)

To understand what happens, look in the source for the SQLiteQueryBuilder class, and you'll see the following:

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]);
          }
      }
[...]

Basically it's checking the columns you requested in your projection against a list of "allowed" columns, and you can see that if the map does not contain the column from your projection, it will throw an IllegalArgumentException, just as you saw. (I imagine this checking against the map is a security feature to prevent SQL-based attacks from people abusing your content provider, but that's just a guess.)

Note also that if you set "strict" projection maps in your query builder:

qb.setStrictProjectionMap(true);

Then in that case it expects you to know the exact column names... If you don't set it, it checks for the "AS" column alias -- I think that explains the "weird fix" you discovered.

Hope this helps.

你在我安 2024-10-19 08:27:47

我发现了一个奇怪的解决办法。在String[] PROJECTION中。你必须这样做:

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
};

I found a weird fix to this. In String[] PROJECTION. You have to do:

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
};
本宫微胖 2024-10-19 08:27:47

您是否已将此列添加到内容提供商的投影图中(相对于包含此列的表)?我希望这有帮助。

Have you add this column in the content provider's projection map, relative to the table with this column? I hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文