【问题标题】:Cannot query for a long string in ActiveRecord无法在 ActiveRecord 中查询长字符串
【发布时间】:2012-01-15 20:43:18
【问题描述】:

我有一个活动记录 Song 模型,其 songhash 字段 (string(255)) 包含 Sha2 哈希。当我尝试通过以下代码查找歌曲时,没有返回任何内容:

song = Song.all.first
song2 = Song.where(songhash: song.songhash).first
# song is a valid object with a songhash set, but song2 is nil!

如果我用“like”查询做同样的事情,它会起作用:

song = Song.all.first
song2 = Song.where("songhash like ?", song.songhash).first
# song2 is a valid object now
song2.songhash == song.songhash
# the equation is true

我担心它与字符串编码有关,但我不知道为什么这个字符串可能存在编码问题:61a9761b9ebd543b72c5ccf2ab6db198b067f7cf7f8412ee6e9c14b19611bc80

我正在使用带有 sqlite db 的 rails 3.1。

有什么想法吗?

【问题讨论】:

  • Song.find_by_songhash(song.songhash) 返回什么?
  • 不幸的是它返回 nil :-(
  • 你是如何生成哈希的?哈希中没有空格吗?您是否尝试过直接使用哈希,而不是作为变量?
  • 我尝试直接使用它,但即使这样也没有找到。生成哈希的代码是:songhash = Digest::SHA2.hexdigest("#{self.title}#{self.album}#{self.artist}#{self.year}").to_s,所以没什么好激动的。
  • 不确定是否重要,但 to_s 可能会抛出错误,因为 Digest::SHA2.hexdigest 返回一个字符串,并且在搅拌上没有 to_s 方法。

标签: ruby-on-rails sqlite activerecord ruby-on-rails-3.1


【解决方案1】:

总结

生成的 SQL 语句

 # With = / It doesn't work
 SELECT "songs".* FROM "songs" WHERE "songs"."type" 
 IN ('PlaylistSong') AND "songs"."songhash" =
 '61a9761b9ebd543b72c5ccf2ab6db198b067f7cf7f8412ee6e9c14b19611bc80'

 # With like / It works
 SELECT "songs".* FROM "songs" WHERE "songs"."type" 
 IN ('PlaylistSong') AND (songhash like 
 '61a9761b9ebd543b72c5ccf2ab6db198b067f7cf7f8412ee6e9c14b19611bc80')

 # With upper / It works
 SELECT "songs".* FROM "songs" WHERE "songs"."type" 
 IN ('PlaylistSong') AND (UPPER(songhash) = 
 '61A9761B9EBD543B72C5CCF2AB6DB198B067F7CF7F8412EE6E9C14B19611BC80')

以下语句有效:

 Song.where(['UPPER(songhash) = ?', song.songhash.upcase]).first
 Song.where(['songhash like ?', song.songhash]).first

UPPERLIKE 都不区分大小写

SQLite 文档

LIKE 运算符进行模式匹配比较。 (一个错误:默认情况下,SQLite 只理解 ASCII 字符的大小写。默认情况下,LIKE 运算符对 超出 ASCII 范围的 unicode 字符区分大小写。例如,表达式 'a' LIKE 'A' 是 TRUE,但 'æ' LIKE 'Æ' 是 FALSE。)See more

调查

  1. 字符集等于? (Rails - SQLite)
  2. 存储的字符串可能是脏的(回车,...)

【讨论】:

    【解决方案2】:

    感谢@gazler 和@basgys 的帮助,我得以找到问题所在:

    其实是Digest::Sha2#hexdigest函数导致的编码问题。它返回一个编码为 ASCII-8BIT 的字符串。将其存储在数据库中时,它似乎会自动转换为 UTF-8 字符串(我通过运行select hex(songhash) from songs 查询来检查)。但是,在查询中使用字符串时,它似乎没有进行这种转换。

    在内部,ruby 似乎可以自动处理不同的编码转换。这就是为什么"abc"=="abc" 尽管它们可能有不同的编码。

    我确信这不是预期的行为,但是我不知道这是否是一个错误 - 以及它是否是 ActiveRecord、SQLite 驱动程序或 SQLite 本身中的某个地方是否是一个错误。

    我现在的解决方案是将.encode("UTF-8") 附加到摘要函数的结果中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多