我有一个ContentProvider
,它在调试中使用自定义CursorFacory
来打印SQL查询(用于调试)。
一个特定的查询返回0行,而我知道有应该包含的行。所以我从我的日志中复制了查询,替换了绑定值,并在设备上的sqlite3 shell中运行它,得到了正确的结果。
查询代码
cr.query (contentUri,
Projection.columns,
FeedColumns.FEED_TYPE + "=? AND " +
FeedColumns.SUB_TYPE + "=? AND " +
ProfileUpdateFeedItem.UPDATED_FIELD + "=? AND " +
FeedColumns.IS_NOTIFIED + "=?",
new String[] {FeedType.USER, // 2
WallPostData.WallPostType.PROFILE_UPDATE, // 1
ProfileUpdateData.ProfileField.STATUS, // 0
SQLBoolean.FALSE // 0
},
FeedColumns.CREATED + " ASC");
来自日志:
07-04 12:48:51.339 4067-4314/com.redacted.android D/DATABASE﹕ QUERY: SQLiteQuery: SELECT DISTINCT id, sender, data_1, data_2, photo, feed_type, sub_type, created, expiry, updated, comment_count, comment_unread, reaction_count, reaction_unread, sender_name, sender_photo, _id FROM wall WHERE feed_type=? AND sub_type=? AND data_1=? AND is_notified=? ORDER BY created ASC LIMIT 100
在设备:
Enter SQL statements terminated with a ";"
sqlite> SELECT DISTINCT id, sender, data_1, data_2, photo, feed_type, sub_type, created, expiry, updated, comment_count, comment_unread, reaction_count, reaction_unread, sender_name, sender_photo, _id FROM wall WHERE feed_type=2 AND sub_type=1 AND data_1=0 AND is_notified=0 ORDER BY created ASC LIMIT 100;
53b702b827d7482062f52b03|a7e759d78abe4bfa97045ce49a24ab57|0|Educ||2|1|1404502712279|1404761912325|1404502712279|||||Luke Skywalker|pr/e5c2c0398b267f93683c80dc5009722e|49
ContentProvider不同意,cursor.getCount()
返回0。
知道为什么会这样吗?
feed_type , sub_type ,和 is_notified INTEGER
列。
data_1是BLOB
,它为符合此查询条件的任何行存储整数,但为其他类型的数据存储字符串
当你在shell中运行时,我很惊讶你得到任何行。blob数据类型可能无法为您正确地转换键值。通常,数据库API需要一个特殊的函数来设置blob值并检索它。
这里的问题是BLOB列。它在查询中被正确地评估(表中的数据在ListView
中使用,并且根据data_1
和data_2
列的内容显示不同)。feed
类别中的所有内容都被解析为植根于anstractfedobject的类层次结构的成员。
大多数同时使用data_1
和data_2
的字段都存储文本,但有些字段(对应于上述类层次结构的子集)使用data_1
作为类型枚举,UI使用它来解释存储在data_2
中的值。例如,0类型表示data_2
是图片id(构建url并下载),而类型1表示它是实际的文本内容。
我最终做的是用一个名为type_enumeration
的整数列替换data_1
,并将data_2
重命名为data_1
。现在我知道BLOB
可能会导致这些问题,我将把data_2
也更改为TEXT
列。
如果将来我需要在DB中存储二进制数据,我将在列中添加一个bin_data
。
现在通常在适当的规范化模式中,您会使用链接表来表示这种层次结构,但在移动环境中,您希望最小化连接,以便在性能方面节省一些额外的列(至少这是我的经验)。