【问题标题】:ActiveRecord :select is messing with my data typesActiveRecord :select 弄乱了我的数据类型
【发布时间】:2010-12-24 16:59:10
【问题描述】:

所以我有这个非常简单的 sn-p。

Topic.all(:select => 'count(*) as cnt')[0].cnt   # behaves the same on all models
"500"  # What, a string? 

似乎出于某种原因 ActiveRecord 将计数强制为字符串。事实上,我注意到它将选择列表中从原始对象中丢失的所有内容强制转换为字符串。

为什么会这样?

什么是修复此问题的猴子补丁,使其按预期工作?

:我不想使用 Topic.count,我需要做一些棘手的分组和选择。

仅供参考,使用 ActiveRecord 2.3.5

证明信息在原始连接中:

ree-1.8.7-2009.10 > r = ActiveRecord::Base::connection.raw_connection.query(
     "select 1").fetch_field.type == Mysql::Field::TYPE_LONGLONG
 => true
ree-1.8.7-2009.10 > r = ActiveRecord::Base::connection.raw_connection.query(
    "select 'a'").fetch_field.type == Mysql::Field::TYPE_VAR_STRING
 => true

当使用 Stmt API 时,您会自动获得正确类型的东西

ree-1.8.7-2009.10 > s = ActiveRecord::Base::connection.raw_connection.stmt_init
 => #<Mysql::Stmt:0xbd083dc>
ree-1.8.7-2009.10 > s.prepare("select 1, 'hello'")
 => #<Mysql::Stmt:0xbd083dc>
ree-1.8.7-2009.10 > s.execute
 => #<Mysql::Stmt:0xbd083dc>
ree-1.8.7-2009.10 > s.fetch
 => [1, "hello"]
ree-1.8.7-2009.10 >

但是……Active Record MySql 适配器使用返回字符串的查询 API。

ree-1.8.7-2009.10 > cnn.query("select 1,2,3 union all select 1,2,3").each{|r| p r}
["1", "2", "3"]
["1", "2", "3"]

【问题讨论】:

  • 你一定有一些理由不简单地在最后加上'.to_i',对吧?
  • 我可以解决这个问题,但我试图找到根本原因,我的直觉告诉我它的原因抽象适配器定义没有办法做这些事情
  • "请:我不想使用 Topic.count,我需要做一些棘手的分组和选择。"这就是为什么他们发明了 count_by_sql ...
  • count_by_sql 只返回一个值,我需要每行多个计数一个

标签: ruby-on-rails ruby activerecord


【解决方案1】:

这实际上可能是因为没有简单的方法来假设值是什么,所以 String 是“安全的”。选择中未映射到列的任何内容都不能自省为类型。

【讨论】:

  • 它在 MySql::Result 对象中可用...只是当它自动生成动态方法时,它不会将其拉出那里...可能导致它未在接口中定义...
【解决方案2】:

问题在于 MySQL。当 MySQL 返回结果集时,结果集没有关于列是什么类型的信息。 ActiveRecord 只能做到最好:将所有内容都视为字符串。

ActiveRecord 可以将从“正常”查询(SELECT id FROM 主题)返回的列视为正确的类型,因为 ActiveRecord 向数据库询问了列的类型。

【讨论】:

  • 这不是真的。在 AS/400 上查询 DB2 时,您会遇到同样类型的问题。进行连接,从连接的表中选择,您会收到一个字符串。破坏数据的是 ActiveRecord。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
  • 2014-12-21
  • 1970-01-01
  • 1970-01-01
  • 2015-04-19
相关资源
最近更新 更多