在使用pg gem连接postgres数据库时,connection.select_value仅返回字符串。

9
我将一个使用mysql(mysql2 gem)的rails应用程序转换为使用postgres(pg gem)。
使用mysql时,ActiveRecord::Base.connection.select_value调用返回根据数据类型分配类型的值,例如:
> ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM errors")
=> 86
> ActiveRecord::Base.connection.select_value("SELECT exception FROM errors where id=565")
=> "TechTalk.Genome.SqlExecutionException"
> ActiveRecord::Base.connection.select_value("SELECT id FROM errors where id=565")
=> 565

然而,使用PostgreSQL时,connection.select_value总是返回一个字符串:
> ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM errors")
=> "1"
> ActiveRecord::Base.connection.select_value("SELECT id FROM errors")
=> "1"
> ActiveRecord::Base.connection.select_value("SELECT source FROM errors limit 1")
=> "webapp"

这破坏了一些单元测试,虽然这些可以修复,但我确定我们有其他代码依赖这些返回值。在使用postgres时,有没有办法从connection.select_value获取正确类型的返回值?

2个回答

4
简短回答是不行。'pg'驱动器故意提供尽可能薄的一层,位于本机'libpq'驱动器之上。它不进行类型转换,因为这是高级库的责任,这些库对结果将要使用的领域有一定的了解。这个决定的基础记录在PostgreSQL Wiki上,并且我很乐意与您进一步讨论,可以通过邮件列表进行

5
最差的最佳答案!;) 谢谢。 - Monica Woods
尽可能地在本机“libpq”驱动程序之上使用薄层。问题是,Ruby中的字符串分配实际上非常昂贵,似乎很浪费。 - Sam Saffron
我认为这取决于情况,是更浪费为每个列分配字符串,还是默认尝试将PostgreSQL类型映射到Ruby中。如果您的列类型在Ruby中都有确切的Numeric衍生(非BigNum)等价物,则将它们全部表示为字符串可能是浪费的。然而,在我看来,基于相对罕见的内存浪费潜在风险实施仅能是部分完整的类型映射系统似乎是不负责任的。 - Michael Granger
我同意Michael所表达的想法,但在Rails的上下文中,我觉得驱动程序应该根据其“native_database_types”表派生数据类型。 - gamov

0
对于那些寻找activerecord属性(Rails)特定答案的人: 我进行了一些测试(https://gist.github.com/gamov/8fe38733012931eb3360),发现:
RequestedItem.where(id: 1).select(*, 10 AS tq).first.tq.class

在 Rails < 4 中返回一个字符串,而在 Rails >= 4 中返回一个 Fixnum。

Postgres 适配器将从数据库中转发类型到 Persistence 模块,因此可以透明地进行强制转换。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接