diff options
author | Aaron Patterson <aaron.patterson@gmail.com> | 2011-04-22 15:31:03 -0500 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2011-04-22 15:41:13 -0500 |
commit | 3d19b356d7ccb37b23afcab0b0b698bfd3d668d7 (patch) | |
tree | 4781b80c42488b53a880e00d8a6f1396b10c62a2 | |
parent | 3eae734012fadd641a4ec95715480b962861294c (diff) | |
download | rails-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:
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb | 67 |
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 |