Android棒棒糖 – 改变了SQLite的行为

当testing我的一个Android 5.0兼容性的应用程序时,我发现 两个我的SQL查询 不要再像棒棒糖那样工作了 我的两个问题导致棒棒糖显着不同的结果比较旧的Android版本。

下面,我会更深入地描述这些问题及其解决scheme,以防出现类似问题。

我的主要问题很简单:那些非向后兼容的变化在某个地方有logging吗?

问题一:匹配

看来以下查询不再适用于棒棒糖:

SELECT title FROM ents JOIN ctt ON ctt.docid = ents.cttId WHERE (ctt MATCH '*ads*'); 

它不会返回任何结果,在它做的前棒棒糖(当然有相同的数据库和相同的数据)。

正如在这个问题中所描述的,例如,MATCH只匹配string前缀。 实际上,search字词前面的“*”在Android <5.0上被忽略了。

棒棒糖的SQLite,但是,不喜欢第一个“*”,并不返回任何此查询。 我不得不改变查询以下,使其重新工作:

 SELECT title FROM ents JOIN ctt ON ctt.docid = ents.cttId WHERE (ctt MATCH 'ads*'); 

(我正在使用FTS3进行全文search。)

问题二:COLLATE LOCALIZED

小故事:使用特定于Android的“COLLATE LOCALIZED”对由原始名称引用的别名列与ORDER BY一起进行GROUPING,会在Lollipop上引发错误,但适用于以前的版本。 WTF!? 🙂

很长的故事:

故事从一个相当大的自动生成的查询开始,所以我修改,简化并缩短到导致问题的部分。 我知道这个查询没有太多的意义,但是它显示了这个问题。

 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 

上面的查询在Andriod <5.0上工作,但在棒棒糖中导致错误:

 错误:没有这样的列:inner.title 

好的,我用“title”replace了“inner.title”,所以我尝试将“GROUP BY inner.title”改为“GROUP BY title”,这真的是Lollipop的SQLite的解决scheme:

 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 

(顺便说一句,在这个答案中,你可以findAndroid中使用的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 

我的棒棒糖体验基于使用Android 5.0 – API Level 21 ARM系统映像的SDK模拟器中的testing。

这secon问题看起来像一个Android特定的SQLite错误对我来说。 或者可以有人解释我这(我的眼睛)奇怪的行为? 或者,这又是甚么地方logging的? 🙂

提前致谢!

Solutions Collecting From Web of "Android棒棒糖 – 改变了SQLite的行为"

我不是一个SQLite的专家,我假定你打算这个问题在很大程度上是修辞,但是让我提供一些想法。

比赛

正如您已经指出的, MATCH 只考虑前缀术语 。 意料之外的不可预知的行为可能会来自前缀前缀(如果您将)加上星号。

COLLATE LOCALIZED与一个别名

这似乎是一个有趣的错误。 不过,您可以尝试使用EXPLAIN QUERY PLAN来尝试诊断它。

文档

很明显,我没有告诉过你任何你不知道的事情。 然而,你的“问题”是关于文档的。 对于初学者来说, SQLite发行说明可以在这里find 。 他们通常对版本之间的变化相当详细。

你的第一个问题是一个编程错误。 文档已经在那里如何使用FTS前缀。 你不会解释为什么你的特定语法停止工作。 可以说,它从来不应该开始工作。

LOCALIZED问题可能是一个缺陷,因此它缺乏“文档”(我鼓励你把它报告给谷歌,虽然)。 另外请记住,SQLite是Android核心的一部分,不仅有自定义(如LOCALIZED ),而且还有本地Java绑定。 底层的SQLite核心实现和绑定都可能随着每个版本而改变。 这使我想到了我的主要观点:

考虑使用私有SQLite实现部署您的应用程序。 这样做的说明可以在这里find 。 这将使您能够控制您的应用程序使用的SQLite版本,并对您如何以及何时进行升级给予很好的控制。 但是,这样做是有代价的,因为你失去了LOCALIZED关键字,例如绑定只支持API 15或更高版本,我相信。

观察到的变化是因为棒棒糖附带SQLite 3.8(3.7.11版本的Android 4.x)。 这是更改列表http://www.sqlite.org/releaselog/3_8_0.html

例如,“GROUP BY inner.title”没有这样的列的错误是由于这个“GROUP BY子句中的标识符总是偏好输出列名”。

我看到OP有几个问题。

  1. FTS使用百分比不作为通配符的星号。

  2. FTSsearch字边界,所以有一个领先的通配符从来没有与FTS的工作,它会传递给sqlite读整个表极其缓慢,但OP导致我们相信它在过去的工作。 因此,如果这个查询确实运行的话,那么这个查询就会在以前运行缓慢。

  3. 联合查询在使用的资源总量上总是过多,特别是与某些组合在一起时。 因此,这个查询在可伸缩的业务应用程序中没有地位。