From a5e2f6cd28710e4a81e850a77d5d0833cb1379de Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 26 Sep 2005 20:29:01 +0000 Subject: r3590@asus: jeremy | 2005-09-26 17:00:53 -0700 Correct and optimize PostgreSQL bytea escaping. This is a blend of four patches, each providing a bit to the solution. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@2347 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- .../connection_adapters/postgresql_adapter.rb | 50 +++++++++++++++++++--- 1 file changed, 43 insertions(+), 7 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 254b1a04a8..037f5f6869 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -79,7 +79,7 @@ module ActiveRecord def quote(value, column = nil) if value.class == String && column && column.type == :binary - quote_bytea(value) + "'#{escape_bytea(value)}'" else super end @@ -266,16 +266,52 @@ module ActiveRecord return rows end - def quote_bytea(s) - "'#{escape_bytea(s)}'" - end - def escape_bytea(s) - s.gsub(/\\/) { '\\\\\\\\' }.gsub(/[^\\]/) { |c| sprintf('\\\\%03o', c[0].to_i) } unless s.nil? + if PGconn.respond_to? :escape_bytea + self.class.send(:define_method, :escape_bytea) do |s| + PGconn.escape_bytea(s) if s + end + else + self.class.send(:define_method, :escape_bytea) do |s| + if s + result = '' + s.each_byte { |c| result << sprintf('\\\\%03o', c) } + result + end + end + end + escape_bytea(s) end def unescape_bytea(s) - s.gsub(/\\([0-9][0-9][0-9])/) { $1.oct.chr }.gsub(/\\\\/) { '\\' } unless s.nil? + if PGconn.respond_to? :unescape_bytea + self.class.send(:define_method, :unescape_bytea) do |s| + PGconn.unescape_bytea(s) if s + end + else + self.class.send(:define_method, :unescape_bytea) do |s| + if s + result = '' + i, max = 0, s.size + while i < max + char = s[i] + if char == ?\\ + if s[i+1] == ?\\ + char = ?\\ + i += 1 + else + char = s[i+1..i+3].oct + i += 3 + end + end + result << char + i += 1 + end + result + end + end + end + unescape_bytea(s) end # Query a table's column names, default values, and types. -- cgit v1.2.3