实践来源于下面的想法:
在调用
getContentResolver().query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
时,是否可以在系统构造的查询语句中,为等待查询的表使用一个别名。
通过Google查找后,发现下面两个web:
其中提供的方法是:在方法query的参数projection中,使用注释符,将系统拼凑的内容注释掉;而自己的语句全都放在了参数
projection中。下面是一段来自1)的例子:
select * from sms as a join threads as b where a._id = 1 order by a.date desc– from sms where () order by date desc
相应的query方法为 getContentResolver().query( Uri.parse("content://sms/") , new String[]{"* from sms as a join threads as b where a._id = 1 order by a.date desc--"}, null, null, null)
按照这个思路,首先测试了提供的例子,成功后在系统联系人数据库查询中使用此方法实现之前的想法,但是产生错误。日志信息类似下面:
Caused by: java.lang.IllegalArgumentException: Invalid column ......
原因在哪里?
下面这个web中,作者为‘DMH‘的回答,可以解释这个错误的原因。
IllegalArgumentException: Invalid column
回头查看logcat日志输出,依次查看了Android的源码:
com.android.providers.contacts.ContactsProvider2
android.database.sqlite.SQLiteQueryBuilder
之后明白了其中的原因。
在com.android.providers.contacts.ContactsProvider2中构建查询时,使用下面的代码:
qb.setStrictProjectionMap(true);
而在android.database.sqlite.SQLiteQueryBuilder的方法computeProjection中,有如下代码:
for (int i = 0; i < length; i++) {
String userColumn = projectionIn[i];
String column = mProjectionMap.get(userColumn);
if (column != null) {
projection[i] = column;
continue;
}
if (!mStrictProjectionMap &&
( userColumn.contains(" AS ") || userColumn.contains(" as "))) {
/* A column alias already exist */
projection[i] = userColumn;
continue;
}
throw new IllegalArgumentException("Invalid column "
+ projectionIn[i]);
}
变量mStrictProjectionMap的值是由第一段代码设置为了true,因而在构建查询语句时,想将待查的表名做个别名的机会也没有了。