Class: Sequel::Postgres::PGRange::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/sequel/extensions/pg_range.rb

Overview

Creates callable objects that convert strings into PGRange instances.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(db_type, converter = nil) ⇒ Parser

Set the db_type and converter on initialization.



85
86
87
88
# File 'lib/sequel/extensions/pg_range.rb', line 85

def initialize(db_type, converter=nil)
  @db_type = db_type.to_s.dup.freeze if db_type
  @converter = converter
end

Instance Attribute Details

#converterObject (readonly)

A callable object to convert the beginning and ending of the range into the appropriate ruby type.



82
83
84
# File 'lib/sequel/extensions/pg_range.rb', line 82

def converter
  @converter
end

#db_typeObject (readonly)

The database range type for this parser (e.g. ‘int4range’), automatically setting the db_type for the returned PGRange instances.



78
79
80
# File 'lib/sequel/extensions/pg_range.rb', line 78

def db_type
  @db_type
end

Instance Method Details

#call(string) ⇒ Object

Parse the range type input string into a PGRange value.

Raises:

  • (InvalidValue)


91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/sequel/extensions/pg_range.rb', line 91

def call(string)
  if string == 'empty'
    return PGRange.empty(db_type)
  end

  raise(InvalidValue, "invalid or unhandled range format: #{string.inspect}") unless matches = /\A(\[|\()("((?:\\"|[^"])*)"|[^"]*),("((?:\\"|[^"])*)"|[^"]*)(\]|\))\z/.match(string)

  exclude_begin = matches[1] == '('
  exclude_end = matches[6] == ')'

  # If the input is quoted, it needs to be unescaped.  Also, quoted input isn't
  # checked for emptiness, since the empty quoted string is considered an 
  # element that happens to be the empty string, while an unquoted empty string
  # is considered unbounded.
  #
  # While PostgreSQL allows pure escaping for input (without quoting), it appears
  # to always use the quoted output form when characters need to be escaped, so
  # there isn't a need to unescape unquoted output.
  if beg = matches[3]
    beg.gsub!(/\\(.)/, '\1')
  else
    beg = matches[2] unless matches[2].empty?
  end
  if en = matches[5]
    en.gsub!(/\\(.)/, '\1')
  else
    en = matches[4] unless matches[4].empty?
  end

  if c = converter
    beg = c.call(beg) if beg
    en = c.call(en) if en
  end

  PGRange.new(beg, en, :exclude_begin=>exclude_begin, :exclude_end=>exclude_end, :db_type=>db_type)
end