connection.select_value 仅使用 pg gem 在 postgres 中返回字符串

Posted

技术标签:

【中文标题】connection.select_value 仅使用 pg gem 在 postgres 中返回字符串【英文标题】:connection.select_value only returns strings in postgres with pg gem 【发布时间】:2012-09-16 06:40:04 【问题描述】:

我正在将一个 Rails 应用程序从使用 mysql (mysql2 gem) 转换为 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

但是,对于 postgres,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 获取正确类型的返回值?

【问题讨论】:

【参考方案1】:

对于那些在这里寻找 activerecord 属性 (Rails) 特定答案的人: 我做了一些测试 (https://gist.github.com/gamov/8fe38733012931eb3360) 并发现:

RequestedItem.where(id: 1).select(*, 10 AS tq).first.tq.class

返回 Rails = 4 的 Fixnum。

Postgres 适配器会将类型从 DB 转发到 Persistence 模块,因此可以透明地进行转换。

【讨论】:

【参考方案2】:

简短的回答是否定的。 'pg' 驱动程序有意在本机 'libpq' 驱动程序之上提供尽可能薄的一层。它不进行类型转换,因为这是对使用结果的领域有一定了解的高级库的职责。此决定的理由已记录在 on the PostgreSQL Wiki,我很乐意与您进一步讨论 on the mailing list。

【讨论】:

有史以来最糟糕的最佳答案! ;) 谢谢。 "在本地 'libpq' 驱动程序之上尽可能薄一层。"问题是,ruby 中的字符串分配实际上非常昂贵,看起来很浪费 我认为是为每列分配字符串更浪费还是尝试将PostgreSQL类型默认映射到Ruby中更浪费,这是一个环境问题。如果您的列类型在 Ruby 中都具有精确的数字派生(非 BigNum)等价物,那么将它们全部表示为字符串可能是一种浪费。但是,在这种相对罕见的情况下,基于潜在的内存浪费来实现只能是部分完整的类型映射系统,这对我来说似乎是不负责任的。 我同意 Michael 表达的想法,但是在 Rails 的上下文中,我觉得驱动程序应该根据它的 'native_database_types' 表导出数据类型。

以上是关于connection.select_value 仅使用 pg gem 在 postgres 中返回字符串的主要内容,如果未能解决你的问题,请参考以下文章

仅 ftping 仅今天的文件

为啥我的 charFormat 样式仅适用于选择,并且仅适用于特定方向的选择?

在oracle中仅选择且仅选择特定记录[关闭]

仅 32 位 MacOS 应用程序可以使用仅 64 位框架吗?

MatFile 对象仅支持 '()' 索引

如何仅在 ASP.NET MVC 中仅显示当前登录用户创建的项目