@@ -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