Skip to content

Commit 0f16478

Browse files
committed
1 parent d46dd18 commit 0f16478

File tree

1 file changed

+77
-128
lines changed
  • lib/arjdbc/postgresql/base

1 file changed

+77
-128
lines changed

lib/arjdbc/postgresql/base/oid.rb

Lines changed: 77 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,6 @@ module PostgreSQL
66
module OID
77
class Type
88
def type; end
9-
def simplified_type(sql_type); type end
10-
11-
def infinity(options = {})
12-
::Float::INFINITY * (options[:negative] ? -1 : 1)
13-
end
149
end
1510

1611
class Identity < Type
@@ -19,29 +14,9 @@ def type_cast(value)
1914
end
2015
end
2116

22-
# String, Text types do not exist in AR 4.0/4.1
23-
# AR reports Identity for them - make it similar
24-
class String < Identity
25-
def type; :string end
26-
end
27-
28-
class SpecializedString < OID::String
29-
def type; @type end
30-
31-
def initialize(type)
32-
@type = type
33-
end
34-
end
35-
36-
class Text < OID::String
37-
def type; :text end
38-
end
39-
4017
class Bit < Type
41-
def type; :string end
42-
4318
def type_cast(value)
44-
if ::String === value
19+
if String === value
4520
ConnectionAdapters::PostgreSQLColumn.string_to_bit value
4621
else
4722
value
@@ -50,20 +25,16 @@ def type_cast(value)
5025
end
5126

5227
class Bytea < Type
53-
def type; :binary end
54-
5528
def type_cast(value)
5629
return if value.nil?
5730
PGconn.unescape_bytea value
5831
end
5932
end
6033

6134
class Money < Type
62-
def type; :decimal end
63-
6435
def type_cast(value)
6536
return if value.nil?
66-
return value unless ::String === value
37+
return value unless String === value
6738

6839
# Because money output is formatted according to the locale, there are two
6940
# cases to consider (note the decimal separators):
@@ -105,8 +76,6 @@ def type_cast(value)
10576
end
10677

10778
class Point < Type
108-
def type; :string end
109-
11079
def type_cast(value)
11180
if ::String === value
11281
ConnectionAdapters::PostgreSQLColumn.string_to_point value
@@ -117,8 +86,6 @@ def type_cast(value)
11786
end
11887

11988
class Array < Type
120-
def type; @subtype.type end
121-
12289
attr_reader :subtype
12390
def initialize(subtype)
12491
@subtype = subtype
@@ -135,56 +102,63 @@ def type_cast(value)
135102

136103
class Range < Type
137104
attr_reader :subtype
138-
def simplified_type(sql_type); sql_type.to_sym end
139-
140105
def initialize(subtype)
141106
@subtype = subtype
142107
end
143108

144109
def extract_bounds(value)
145110
from, to = value[1..-2].split(',')
146111
{
147-
from: (value[1] == ',' || from == '-infinity') ? @subtype.infinity(negative: true) : from,
148-
to: (value[-2] == ',' || to == 'infinity') ? @subtype.infinity : to,
112+
from: (value[1] == ',' || from == '-infinity') ? infinity(:negative => true) : from,
113+
to: (value[-2] == ',' || to == 'infinity') ? infinity : to,
149114
exclude_start: (value[0] == '('),
150115
exclude_end: (value[-1] == ')')
151116
}
152117
end
153118

119+
def infinity(options = {})
120+
::Float::INFINITY * (options[:negative] ? -1 : 1)
121+
end
122+
154123
def infinity?(value)
155124
value.respond_to?(:infinite?) && value.infinite?
156125
end
157126

158-
def type_cast_single(value)
159-
infinity?(value) ? value : @subtype.type_cast(value)
127+
def to_integer(value)
128+
infinity?(value) ? value : value.to_i
160129
end
161130

162131
def type_cast(value)
163132
return if value.nil? || value == 'empty'
164133
return value if value.is_a?(::Range)
165134

166135
extracted = extract_bounds(value)
167-
from = type_cast_single extracted[:from]
168-
to = type_cast_single extracted[:to]
169-
170-
if !infinity?(from) && extracted[:exclude_start]
171-
if from.respond_to?(:succ)
172-
from = from.succ
173-
ActiveSupport::Deprecation.warn <<-MESSAGE
174-
Excluding the beginning of a Range is only partialy supported through `#succ`.
175-
This is not reliable and will be removed in the future.
176-
MESSAGE
177-
else
178-
raise ArgumentError, "The Ruby Range object does not support excluding the beginning of a Range. (unsupported value: '#{value}')"
179-
end
136+
137+
case @subtype
138+
when :date
139+
from = ConnectionAdapters::Column.value_to_date(extracted[:from])
140+
from += 1.day if extracted[:exclude_start]
141+
to = ConnectionAdapters::Column.value_to_date(extracted[:to])
142+
when :decimal
143+
from = BigDecimal.new(extracted[:from].to_s)
144+
# FIXME: add exclude start for ::Range, same for timestamp ranges
145+
to = BigDecimal.new(extracted[:to].to_s)
146+
when :time
147+
from = ConnectionAdapters::Column.string_to_time(extracted[:from])
148+
to = ConnectionAdapters::Column.string_to_time(extracted[:to])
149+
when :integer
150+
from = to_integer(extracted[:from]) rescue value ? 1 : 0
151+
from += 1 if extracted[:exclude_start]
152+
to = to_integer(extracted[:to]) rescue value ? 1 : 0
153+
else
154+
return value
180155
end
156+
181157
::Range.new(from, to, extracted[:exclude_end])
182158
end
183159
end
184160

185161
class Integer < Type
186-
def type; :integer end
187-
188162
def type_cast(value)
189163
return if value.nil?
190164

@@ -193,8 +167,6 @@ def type_cast(value)
193167
end
194168

195169
class Boolean < Type
196-
def type; :boolean end
197-
198170
def type_cast(value)
199171
return if value.nil?
200172

@@ -204,9 +176,6 @@ def type_cast(value)
204176

205177
class Timestamp < Type
206178
def type; :timestamp; end
207-
def simplified_type(sql_type)
208-
:datetime
209-
end
210179

211180
def type_cast(value)
212181
return if value.nil?
@@ -218,7 +187,7 @@ def type_cast(value)
218187
end
219188

220189
class Date < Type
221-
def type; :date; end
190+
def type; :datetime; end
222191

223192
def type_cast(value)
224193
return if value.nil?
@@ -230,8 +199,6 @@ def type_cast(value)
230199
end
231200

232201
class Time < Type
233-
def type; :time end
234-
235202
def type_cast(value)
236203
return if value.nil?
237204

@@ -242,8 +209,6 @@ def type_cast(value)
242209
end
243210

244211
class Float < Type
245-
def type; :float end
246-
247212
def type_cast(value)
248213
case value
249214
when nil; nil
@@ -257,32 +222,19 @@ def type_cast(value)
257222
end
258223

259224
class Decimal < Type
260-
def type; :decimal end
261-
262225
def type_cast(value)
263226
return if value.nil?
264227

265228
ConnectionAdapters::Column.value_to_decimal value
266229
end
267-
268-
def infinity(options = {})
269-
BigDecimal.new("Infinity") * (options[:negative] ? -1 : 1)
270-
end
271-
end
272-
273-
class Enum < Type
274-
def type; :enum end
275-
276-
def type_cast(value)
277-
value.to_s
278-
end
279230
end
280231

281232
class Hstore < Type
282-
def type; :hstore end
283-
284233
def type_cast_for_write(value)
285-
ConnectionAdapters::PostgreSQLColumn.hstore_to_string value
234+
# roundtrip to ensure uniform uniform types
235+
# TODO: This is not an efficient solution.
236+
stringified = ConnectionAdapters::PostgreSQLColumn.hstore_to_string(value)
237+
type_cast(stringified)
286238
end
287239

288240
def type_cast(value)
@@ -297,22 +249,19 @@ def accessor
297249
end
298250

299251
class Cidr < Type
300-
def type; :cidr end
301252
def type_cast(value)
302253
return if value.nil?
303254

304255
ConnectionAdapters::PostgreSQLColumn.string_to_cidr value
305256
end
306257
end
307-
class Inet < Cidr
308-
def type; :inet end
309-
end
310258

311259
class Json < Type
312-
def type; :json end
313-
314260
def type_cast_for_write(value)
315-
ConnectionAdapters::PostgreSQLColumn.json_to_string value
261+
# roundtrip to ensure uniform uniform types
262+
# TODO: This is not an efficient solution.
263+
stringified = ConnectionAdapters::PostgreSQLColumn.json_to_string(value)
264+
type_cast(stringified)
316265
end
317266

318267
def type_cast(value)
@@ -326,13 +275,6 @@ def accessor
326275
end
327276
end
328277

329-
class Uuid < Type
330-
def type; :uuid end
331-
def type_cast(value)
332-
value.presence
333-
end
334-
end
335-
336278
class TypeMap
337279
def initialize
338280
@mapping = {}
@@ -379,7 +321,7 @@ def fetch(ftype, fmod)
379321
}
380322

381323
# Register an OID type named +name+ with a typecasting object in
382-
# +type+. +name+ should correspond to the `typname` column in
324+
# +type+. +name+ should correspond to the `typname` column in
383325
# the `pg_type` table.
384326
def self.register_type(name, type)
385327
NAMES[name] = type
@@ -396,47 +338,54 @@ def self.registered_type?(name)
396338
end
397339

398340
register_type 'int2', OID::Integer.new
399-
alias_type 'int4', 'int2'
400-
alias_type 'int8', 'int2'
401-
alias_type 'oid', 'int2'
341+
alias_type 'int4', 'int2'
342+
alias_type 'int8', 'int2'
343+
alias_type 'oid', 'int2'
344+
345+
register_type 'daterange', OID::Range.new(:date)
346+
register_type 'numrange', OID::Range.new(:decimal)
347+
register_type 'tsrange', OID::Range.new(:time)
348+
register_type 'int4range', OID::Range.new(:integer)
349+
alias_type 'tstzrange', 'tsrange'
350+
alias_type 'int8range', 'int4range'
351+
402352
register_type 'numeric', OID::Decimal.new
403-
register_type 'float4', OID::Float.new
404-
alias_type 'float8', 'float4'
405-
register_type 'text', OID::Text.new
406-
register_type 'varchar', OID::String.new
407-
alias_type 'char', 'varchar'
408-
alias_type 'name', 'varchar'
409-
alias_type 'bpchar', 'varchar'
353+
register_type 'text', OID::Identity.new
354+
alias_type 'varchar', 'text'
355+
alias_type 'char', 'text'
356+
alias_type 'bpchar', 'text'
357+
alias_type 'xml', 'text'
358+
359+
# FIXME: why are we keeping these types as strings?
360+
alias_type 'tsvector', 'text'
361+
alias_type 'interval', 'text'
362+
alias_type 'macaddr', 'text'
363+
alias_type 'uuid', 'text'
364+
365+
register_type 'money', OID::Money.new
366+
register_type 'bytea', OID::Bytea.new
410367
register_type 'bool', OID::Boolean.new
411368
register_type 'bit', OID::Bit.new
412-
alias_type 'varbit', 'bit'
369+
register_type 'varbit', OID::Bit.new
370+
371+
register_type 'float4', OID::Float.new
372+
alias_type 'float8', 'float4'
373+
413374
register_type 'timestamp', OID::Timestamp.new
414-
alias_type 'timestamptz', 'timestamp'
375+
register_type 'timestamptz', OID::Timestamp.new
415376
register_type 'date', OID::Date.new
416377
register_type 'time', OID::Time.new
417378

418-
register_type 'money', OID::Money.new
419-
register_type 'bytea', OID::Bytea.new
379+
register_type 'path', OID::Identity.new
420380
register_type 'point', OID::Point.new
381+
register_type 'polygon', OID::Identity.new
382+
register_type 'circle', OID::Identity.new
421383
register_type 'hstore', OID::Hstore.new
422384
register_type 'json', OID::Json.new
423-
register_type 'cidr', OID::Cidr.new
424-
register_type 'inet', OID::Inet.new
425-
register_type 'uuid', OID::Uuid.new
426-
register_type 'xml', SpecializedString.new(:xml)
427-
register_type 'tsvector', SpecializedString.new(:tsvector)
428-
register_type 'macaddr', SpecializedString.new(:macaddr)
429-
register_type 'citext', SpecializedString.new(:citext)
430-
register_type 'ltree', SpecializedString.new(:ltree)
385+
register_type 'ltree', OID::Identity.new
431386

432-
# FIXME: why are we keeping these types as strings?
433-
alias_type 'interval', 'varchar'
434-
alias_type 'path', 'varchar'
435-
alias_type 'line', 'varchar'
436-
alias_type 'polygon', 'varchar'
437-
alias_type 'circle', 'varchar'
438-
alias_type 'lseg', 'varchar'
439-
alias_type 'box', 'varchar'
387+
register_type 'cidr', OID::Cidr.new
388+
alias_type 'inet', 'cidr'
440389
end
441390
end
442391
end

0 commit comments

Comments
 (0)