aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2011-04-22 15:31:03 -0500
committerAaron Patterson <aaron.patterson@gmail.com>2011-04-22 15:41:13 -0500
commit3d19b356d7ccb37b23afcab0b0b698bfd3d668d7 (patch)
tree4781b80c42488b53a880e00d8a6f1396b10c62a2 /activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
parent3eae734012fadd641a4ec95715480b962861294c (diff)
downloadrails-3d19b356d7ccb37b23afcab0b0b698bfd3d668d7.tar.gz
rails-3d19b356d7ccb37b23afcab0b0b698bfd3d668d7.tar.bz2
rails-3d19b356d7ccb37b23afcab0b0b698bfd3d668d7.zip
fetch result row arrays from pg in C and return early if there are no money or binary columns. :heart:
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb')
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb67
1 files changed, 36 insertions, 31 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 203ecd2f03..8763074121 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -1,6 +1,9 @@
require 'active_record/connection_adapters/abstract_adapter'
require 'active_support/core_ext/kernel/requires'
require 'active_support/core_ext/object/blank'
+
+# Make sure we're using pg high enough for PGResult#values
+gem 'pg', '~> 0.11'
require 'pg'
module ActiveRecord
@@ -460,42 +463,44 @@ module ActiveRecord
# create a 2D array representing the result set
def result_as_array(res) #:nodoc:
# check if we have any binary column and if they need escaping
- unescape_col = []
- res.nfields.times do |j|
- unescape_col << res.ftype(j)
+ ftypes = Array.new(res.nfields) do |i|
+ [i, res.ftype(i)]
end
- ary = []
- res.ntuples.times do |i|
- ary << []
- res.nfields.times do |j|
- data = res.getvalue(i,j)
- case unescape_col[j]
-
- # unescape string passed BYTEA field (OID == 17)
- when BYTEA_COLUMN_TYPE_OID
- data = unescape_bytea(data) if String === data
-
- # If this is a money type column and there are any currency symbols,
- # then strip them off. Indeed it would be prettier to do this in
- # PostgreSQLColumn.string_to_decimal but would break form input
- # fields that call value_before_type_cast.
- when MONEY_COLUMN_TYPE_OID
- # Because money output is formatted according to the locale, there are two
- # cases to consider (note the decimal separators):
- # (1) $12,345,678.12
- # (2) $12.345.678,12
- case data
- when /^-?\D+[\d,]+\.\d{2}$/ # (1)
- data.gsub!(/[^-\d.]/, '')
- when /^-?\D+[\d.]+,\d{2}$/ # (2)
- data.gsub!(/[^-\d,]/, '').sub!(/,/, '.')
- end
+ rows = res.values
+ return rows unless ftypes.any? { |_, x|
+ x == BYTEA_COLUMN_TYPE_OID || x == MONEY_COLUMN_TYPE_OID
+ }
+
+ typehash = ftypes.group_by { |_, type| type }
+ binaries = (typehash[BYTEA_COLUMN_TYPE_OID] || []).map { |x| x.first }
+ monies = (typehash[MONEY_COLUMN_TYPE_OID] || []).map { |x| x.first }
+
+ rows.each do |row|
+ # unescape string passed BYTEA field (OID == 17)
+ binaries.each do |index|
+ data = row[index]
+ row[index] = unescape_bytea(data)
+ end
+
+ # If this is a money type column and there are any currency symbols,
+ # then strip them off. Indeed it would be prettier to do this in
+ # PostgreSQLColumn.string_to_decimal but would break form input
+ # fields that call value_before_type_cast.
+ monies.each do |index|
+ data = row[index]
+ # Because money output is formatted according to the locale, there are two
+ # cases to consider (note the decimal separators):
+ # (1) $12,345,678.12
+ # (2) $12.345.678,12
+ case data
+ when /^-?\D+[\d,]+\.\d{2}$/ # (1)
+ data.gsub!(/[^-\d.]/, '')
+ when /^-?\D+[\d.]+,\d{2}$/ # (2)
+ data.gsub!(/[^-\d,]/, '').sub!(/,/, '.')
end
- ary[i] << data
end
end
- return ary
end