【发布时间】:2015-01-05 03:34:29
【问题描述】:
在测试我的一个应用程序的 Android 5.0 兼容性时,我发现 一个 我的两个 SQL 查询 不 在 Lollipop 上不再按预期工作。与旧的 Android 版本相比,我的两个问题导致 Lollipop 的结果明显不同。
下面,我将更深入地描述这些问题及其解决方案,以防您遇到类似问题。
我的主要问题很简单:这些不向后兼容的更改是否记录在案?
问题一:匹配
以下查询似乎不再适用于 Lollipop:
SELECT title FROM ents JOIN ctt ON ctt.docid = ents.cttId WHERE (ctt MATCH '*ads*');
它不再返回任何结果,在棒棒糖之前它确实返回了(当然,使用相同的数据库和相同的数据)。
如this question 中所述,例如,MATCH 仅匹配字符串前缀。确实如此,搜索词前面的“*”在 Android
然而,Lollipop 的 SQLite 不喜欢第一个 '*' 并且不为此查询返回任何内容。我不得不将查询更改为以下内容以使其再次工作:
SELECT title FROM ents JOIN ctt ON ctt.docid = ents.cttId WHERE (ctt MATCH 'ads*');
(我正在使用 FTS3 进行全文搜索。)
问题二:整理本地化
简短的故事:使用 Android 特定的“COLLATE LOCALIZED”将原始名称引用的别名列与 ORDER BY 结合使用 GROUPing BY 会在 Lollipop 上引发错误,但适用于以前的版本。哇!? :-)
长篇大论:
故事从一个相当大的自动生成查询开始,所以我对其进行了修改、简化和缩短到导致问题的部分。我知道查询没有多大意义,如下所示,但它说明了问题。
SELECT
inner.title AS title,
ltrim(inner.title, '*') AS title2
FROM
(SELECT types.text AS title FROM types) AS inner
GROUP BY inner.title
UNION SELECT
inner.title AS title,
ltrim(inner.title, '*') AS title2
FROM
(SELECT types.text AS title FROM types) AS inner
GROUP BY inner.title
ORDER BY title2 COLLATE LOCALIZED ASC
上面的查询适用于
错误:没有这样的列:inner.title
好的,我将“inner.title”与“title”作为别名,所以我尝试将“GROUP BY inner.title”更改为“GROUP BY title”,这确实是 Lollipop 的 SQLite 的解决方案:
SELECT
inner.title AS title,
ltrim(inner.title, '*') AS title2
FROM
(SELECT types.text AS title FROM types) AS inner
GROUP BY title
UNION SELECT
inner.title AS title,
ltrim(inner.title, '*') AS title2
FROM
(SELECT types.text AS title FROM types) AS inner
GROUP BY title
ORDER BY title2 COLLATE LOCALIZED ASC
(顺便说一句,在this answer 你可以找到Android 中使用的SQLite 版本的一个很好的概述)
现在有趣的部分来了:如果在 ORDER BY 子句中删除了 Android 特定的“COLLATE LOCALIZED”,那么一切都会开始工作,即使是“GROUP BY inner.title”:
SELECT
inner.title AS title,
ltrim(inner.title, '*') AS title2
FROM
(SELECT indsntyps.text AS title FROM indsntyps) AS inner
GROUP BY inner.title
UNION SELECT
inner.title AS title,
ltrim(inner.title, '*') AS title2
FROM
(SELECT indsntyps.text AS title FROM indsntyps) AS inner
GROUP BY inner.title
ORDER BY title2 ASC
我的 Lollipop 体验基于使用 Android 5.0 - API Level 21 ARM 系统映像的 SDK 模拟器中的测试。
对我来说,这个问题似乎是 Android 特有的 SQLite 错误。或者有人可以向我解释这个(在我看来)奇怪的行为吗?或者,再一次,这甚至在某个地方有记录吗? :-)
提前致谢!
【问题讨论】:
-
还值得在 Android 5.1 和 6.0 上进行测试,它们都带有不同的 SQLite 版本stackoverflow.com/a/4377116/444761
标签: android sqlite backwards-compatibility android-5.0-lollipop