module Postgres::Conversion

Public Instance Methods

decode_array(str, delim=',', &conv_proc) click to toggle source
# File lib/postgres-pr/typeconv/array.rb, line 5
def decode_array(str, delim=',', &conv_proc)
  delim = Regexp.escape(delim)
  buf = StringScanner.new(str)
  return parse_arr(buf, delim, &conv_proc)
ensure
  raise ConversionError, "end of string expected (#{buf.rest})" unless buf.empty?
end
decode_bytea(str) click to toggle source

Decodes a bytea encoded string.

For decoding rules see:

http://www.postgresql.org/docs/7.4/static/datatype-binary.html

Supports both the historical escape format and the new 9.0+ hex format.

# File lib/postgres-pr/typeconv/bytea.rb, line 19
def decode_bytea(str)
  if str =~ /\A\\x/
    # PostgreSQL 9.0+ bytea hex format
    str[2..-1].gsub(/(..)/){|s| s.to_i(16).chr}
  else
    # Historical PostgreSQL bytea escape format
    str.gsub(/\\(\\|'|[0-3][0-7][0-7])/) {|s|
      if s.size == 2 then s[1,1] else s[1,3].oct.chr end
    }
  end
end
Also aliased as: unescape_bytea
encode_bytea(str) click to toggle source

Encodes a string as bytea value.

For encoding rules see:

http://www.postgresql.org/docs/7.4/static/datatype-binary.html

The historical bytea escape format is always used, for maximum compatibility.

# File lib/postgres-pr/typeconv/bytea.rb, line 8
def encode_bytea(str)
  # each_byte used instead of [] for 1.9 compatibility
  str.gsub(/[\000-\037\047\134\177-\377]/){|b| "\\#{sprintf('%o', b.each_byte{|x| break x}).rjust(3, '0')}"}
end
unescape_bytea(str)
Alias for: decode_bytea

Private Instance Methods

parse_arr(buf, delim, &conv_proc) click to toggle source
# File lib/postgres-pr/typeconv/array.rb, line 15
def parse_arr(buf, delim, &conv_proc)
  # skip whitespace
  buf.skip(/\s*/)       

  raise ConversionError, "'{' expected" unless buf.get_byte == '{'

  elems = []
  unless buf.scan(/\}/) # array is not empty
    loop do
      # skip whitespace
      buf.skip(/\s+/)   

      elems <<
      if buf.check(/\{/)
        parse_arr(buf, delim, &conv_proc)
      else
        e = buf.scan(/("((\\.)|[^"])*"|\\.|[^\}#{ delim }])*/) || raise(ConversionError)
        if conv_proc then conv_proc.call(e) else e end
      end

      break if buf.scan(/\}/)
      break unless buf.scan(/#{ delim }/)
    end
  end

  # skip whitespace
  buf.skip(/\s*/)

  elems
end