2012-09-24 25 views
9

Tôi đang chuyển đổi một ứng dụng đường ray từ sử dụng mysql (mysql2 gem) thành postgres (pg gem).connection.select_value chỉ trả về chuỗi trong postgres với pg gem

Với mysql, ActiveRecord::Base.connection.select_value cuộc gọi trở về giá trị gõ theo các dữ liệu, ví dụ:

> 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 

Tuy nhiên, với postgres, connection.select_value luôn trả về một chuỗi:

> 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" 

này đã phá vỡ một vài đơn vị thử nghiệm, và trong khi chúng có thể sửa chữa được, tôi chắc chắn chúng ta có mã khác dựa trên các giá trị trả về này. Có cách nào để nhận giá trị trả lại đúng cách từ connection.select_value khi sử dụng postgres không?

Trả lời

4

Câu trả lời ngắn gọn là không. Trình điều khiển 'pg' cố ý cung cấp lớp mỏng nhất có thể trên trình điều khiển gốc 'libpq'. Nó không làm typecasting, vì đó là trách nhiệm của các thư viện cấp cao hơn có một số hiểu biết sâu sắc về miền mà kết quả sẽ được sử dụng. Lý do cho quyết định này được ghi nhận là on the PostgreSQL Wiki và tôi sẵn lòng thảo luận với bạn thêm on the mailing list.

+4

Câu trả lời hay nhất chưa từng có! ;) Cảm ơn. –

+0

"mỏng một lớp càng tốt trên trình điều khiển gốc 'libpq'." Vấn đề là, phân bổ chuỗi trong ruby ​​thực sự khá tốn kém, có vẻ như lãng phí –

+0

Tôi nghĩ rằng đó là vấn đề của hoàn cảnh cho dù đó là lãng phí hơn để phân bổ chuỗi cho mỗi cột hoặc cố gắng ánh xạ các loại PostgreSQL vào Ruby theo mặc định. Nếu tất cả các kiểu cột của bạn đều có các số tương đương có nguồn gốc chính xác (không phải BigNum) trong Ruby, có thể là lãng phí khi đại diện cho tất cả chúng như là các chuỗi. Tuy nhiên, dường như tôi vô trách nhiệm thực hiện những gì chỉ có thể là một hệ thống lập bản đồ kiểu hoàn chỉnh một phần dựa trên chất thải bộ nhớ tiềm ẩn trong hoàn cảnh tương đối hiếm hoi đó. –

0

Đối với những người hạ cánh ở đây tìm kiếm một thuộc tính activerecord (Rails) câu trả lời cụ thể: tôi đã thực hiện một số xét nghiệm (https://gist.github.com/gamov/8fe38733012931eb3360) và phát hiện ra rằng:

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

trả về một String với Rails < 4 và một Fixnum with Rails> = 4.

Bộ điều hợp Postgres sẽ chuyển tiếp các kiểu từ DB sang mô-đun Persistence để việc truyền có thể được thực hiện một cách minh bạch.