Sqlite where子句不起作用(这是一个bug吗?)

时间:2012-03-15 12:24:59

标签: ruby-on-rails sqlite

我正在调试Ruby on Rails引擎,当在Sqlite上运行时遇到问题,它在查找应用程序本身创建的记录时遇到问题。在MySQL上运行时,一切正常,但SQLite上的相同查询失败。

我已经跟踪了这个问题,我发现问题出在一个简单的WHERE查询中,该查询无法找到创建的记录。本质上,表结构有一个名为key的列,用于存储一些md5哈希值。失败的规范插入具有给定散列的记录然后在下面的指令上对相同的散列执行SELECT查询,但SQLite不返回相同键的记录。我从应用程序中提取了生成的数据库和失败的查询,这是应用程序数据库的副本:

http://dl.dropbox.com/u/2289657/combustion_test.sqlite

以下是软件执行的查询的记录(使用命令行实用程序):

# Here I'm selecting all the records from the table
# there is a single record  in it, the key is the third field
$ sqlite3 combustion_test.sqlite 'SELECT * FROM tr8n_translation_keys'
1||b56c67d10759f8012aff28fc03f26cbf|Hello World|We must start with this sentence!||||en-US|0|2012-03-14 11:49:50.335322|2012-03-14 11:49:50.335322|

# Here I'm selecting the record with that key and it doesn't return anything
$ sqlite3 combustion_test.sqlite "SELECT * FROM tr8n_translation_keys WHERE key = 'b56c67d10759f8012aff28fc03f26cbf'"

# Here I'selecting the record with a LIKE clause and it finds the record
$ sqlite3 combustion_test.sqlite "SELECT * FROM tr8n_translation_keys WHERE key LIKE 'b56c67d10759f8012aff28fc03f26cbf'"
1||b56c67d10759f8012aff28fc03f26cbf|Hello World|We must start with this sentence!||||en-US|0|2012-03-14 11:49:50.335322|2012-03-14 11:49:50.335322|

我应该将此报告为SQLite网站的错误吗?

P.S。我也尝试过使用不同SQLite版本的不同系统,但结果是一样的。

更新

这是表格架构

sqlite> .schema tr8n_translation_keys
CREATE TABLE "tr8n_translation_keys" (
   "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
   "type" varchar(255), "key" varchar(255) NOT NULL,
   "label" text NOT NULL, 
   "description" text, 
   "verified_at" datetime, 
   "translation_count" integer, 
   "admin" boolean, 
   "locale" varchar(255), 
   "level" integer DEFAULT 0, 
   "created_at" datetime, 
   "updated_at" datetime, 
   "synced_at" datetime
);
CREATE UNIQUE INDEX "index_tr8n_translation_keys_on_key" ON "tr8n_translation_keys" ("key");
CREATE INDEX "index_tr8n_translation_keys_on_synced_at" ON "tr8n_translation_keys" ("synced_at");

更新2

以下是计算插入表中的键值的rails代码(我删除了一些代码,完整方法is here

def self.find_or_create(label, desc = "", options = {})
  key = generate_key(label, desc).to_s
  # IF I UNCOMMENT THIS LINE EVERYTHING WORKS
  #key = 'b56c67d10759f8012aff28fc03f26cbf'

  tkey = Tr8n::Cache.fetch("translation_key_#{key}") do
    existing_key = where(:key => key).first ### THIS IS THE FAILING WHERE

    existing_key ||= begin
      new_tkey = create(:key => key.to_s, 
                        :label => label, 
                        :description => desc, 
                        :locale => locale,
                        :level => level,
                        :admin => Tr8n::Config.block_options[:admin])
# rest of method...

这里是generate_key方法,关于sqlite的评论来自作者,而非我的)

def self.generate_key(label, desc = "")
  # TODO: there is something iffy going on with the strings from the hash
  # without the extra ~ = the strings are not seen in the sqlite database - wtf?
  "#{Digest::MD5.hexdigest("#{label};;;#{desc}")}"
end

2 个答案:

答案 0 :(得分:1)

这有效:

SELECT * FROM tr8n_translation_keys WHERE LOWER(key)='b56c67d10759f8012aff28fc03f26cbf';

但这不是:

SELECT * FROM tr8n_translation_keys WHERE key='b56c67d10759f8012aff28fc03f26cbf' COLLATE NOCASE;

当我在SQLiteManager中检查数据库时,它会显示key

X'6235366336376431303735396638303132616666323866633033663236636266'

这意味着它将key视为BLOB(原始二进制数据)而不是TEXT。这就是比较失败的原因。但是LOWER(key)会导致字段转换为文本,因此比较成功。

因此,我们需要找出条目存储为BLOB而不是TEXT的原因。这些值是如何插入数据库的?


关注更新2 :我不是Ruby专家,但是generate_key返回的值没有按照您期望的方式转换为字符串。在致电to_str时,请尝试to_s而不是generate_key

答案 1 :(得分:1)

基于以下Stack Overflow答案...

https://stackoverflow.com/a/6591427/18064

...您可能希望更新密钥的生成,如下所示:

def self.generate_key(label, desc = "")
   # TODO: there is something iffy going on with the strings from the hash
   # without the extra ~ = the strings are not seen in the sqlite database - wtf?
   "#{Digest::MD5.hexdigest("#{label};;;#{desc}").encode('UTF-8')}"
end

请注意添加.encode('UTF-8')

当我遇到与你相同的问题时,这对我有用。