1

我使用 SQLite3 并有一个名为 blobs 的表来存储内容和 *hash_value*。

这是架构:

CREATE TABLE "blobs" (
  "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
  "content" blob,
  "hash_value" text,
  "created_at" datetime NOT NULL,
  "updated_at" datetime NOT NULL
);

现在我插入了一些数据。看起来像这样:

1|--- foo
...
|34dc86f45b3dc92b352fd45f525192c0|2012-04-09 17:02:54.219504|2012-04-09 17:02:54.219504

我尝试了以下两个查询:

  • select * from blobs where hash_value = '34dc86f45b3dc92b352fd45f525192c0';
  • select * from blobs where hash_value LIKE '34dc86f45b3dc92b352fd45f525192c0';

第一个不起作用,但第二个起作用。我不明白为什么=操作员不工作。

我试图将其分解为一个简单的示例,其中我的哈希只是'abc'并且 = 有效。我的意思是这个字符串几乎不会太长。

编辑

好的,我实际上将其范围缩小到:

  • 我正在使用 Ruby 生成这样的哈希Digest::MD5.hexdigest("foobar")
  • 这会生成一个这样的字符串:'3858f62230ac3c915f300c664312c63f'
  • 我的测试看起来有点像这样:b = Blob.new(...);b.save!;Blob.find_by_hash(b.hash)
  • find_hash 是Blob.find(:all, :conditions => ["hash_value = ?", hash_value])
  • 如果我将哈希手动设置为'3858f62230ac3c915f300c664312c63f'(硬编码字符串),它会起作用。
  • 但是如果生成了这个字符串,我会收到以下错误:

    Failure/Error: Blob.find_by_hash(b.hash_value)[0].load.should == txt
     ArgumentError: wrong number of arguments (0 for 1)
    

而且我无法如上所述查询 SQLite3。

解决方案

解决方案是:

  • 而不是使用 Digest::MD5.hexdigest("foobar") 使用 Digest::MD5.base64digest("foobar")

我不知道为什么 sqlite3 与 hexdigest 有问题,但肯定有一些可疑之处。

4

2 回答 2

2

两者的区别在于编码:

Digest::MD5.hexdigest("foobar").encoding #=>  #<Encoding:ASCII-8BIT> 
Digest::MD5.base64digest("foobar").encoding #=> #<Encoding:US-ASCII> 

我不认为 hexdigest 具有 8 位编码的特殊原因(这实际上意味着“这是原始数据”,但 ruby​​ 似乎就是这样做的。当 ruby​​ sqlite3 驱动程序看到带有 ascii-8bit 编码的东西时,它会绑定查询的值作为 blob,而不是文本。这反过来会影响 sqlite3 进行比较的方式(尽管我不完全了解如何进行比较)。

另请参阅此问题

于 2012-04-10T12:12:29.663 回答
0

解决方案是:

而不是使用 Digest::MD5.hexdigest("foobar") 使用 Digest::MD5.base64digest("foobar")。我不知道为什么 sqlite3 与 hexdigest 有问题,但肯定有一些可疑之处。

于 2012-04-10T09:56:55.720 回答