@@ -9,6 +9,61 @@ module PostgreSQL
9
9
# @private
10
10
OID = ::ActiveRecord ::ConnectionAdapters ::PostgreSQL ::OID
11
11
12
+ # this version makes sure to register the types by name as well
13
+ # we still need to version with OID since it's used from SchemaStatements as well
14
+ class ArjdbcTypeMapInitializer < OID ::TypeMapInitializer
15
+ private
16
+
17
+ def name_with_ns ( row )
18
+ if row [ 'in_ns' ]
19
+ row [ 'typname' ]
20
+ else
21
+ %Q("#{ row [ 'nspname' ] } "."#{ row [ 'typname' ] } ")
22
+ end
23
+ end
24
+
25
+ def register_enum_type ( row )
26
+ super
27
+ register name_with_ns ( row ) , OID ::Enum . new
28
+ end
29
+
30
+ def register_array_type ( row )
31
+ super
32
+ register_with_subtype ( name_with_ns ( row ) , row [ 'typelem' ] . to_i ) do |subtype |
33
+ OID ::Array . new ( subtype , row [ 'typdelim' ] )
34
+ end
35
+ end
36
+
37
+ def register_range_type ( row )
38
+ super
39
+ name = name_with_ns ( row )
40
+ register_with_subtype ( name , row [ 'rngsubtype' ] . to_i ) do |subtype |
41
+ OID ::Range . new ( subtype , name . to_sym )
42
+ end
43
+ end
44
+
45
+ def register_domain_type ( row )
46
+ if base_type = @store . lookup ( row [ 'typbasetype' ] . to_i )
47
+ register row [ 'oid' ] , base_type
48
+ register name_with_ns ( row ) , base_type
49
+ else
50
+ warn "unknown base type (OID: #{ row [ 'typbasetype' ] } ) for domain #{ row [ 'typname' ] } ."
51
+ end
52
+ end
53
+
54
+ def register_composite_type ( row )
55
+ if subtype = @store . lookup ( row [ 'typelem' ] . to_i )
56
+ register row [ 'oid' ] , OID ::Vector . new ( row [ 'typdelim' ] , subtype )
57
+ register name_with_ns ( row ) , OID ::Vector . new ( row [ 'typdelim' ] , subtype )
58
+ end
59
+ end
60
+
61
+ def assert_valid_registration ( oid , oid_type )
62
+ ret = super
63
+ ret == 0 ? oid : ret
64
+ end
65
+ end
66
+
12
67
# @private
13
68
module OIDTypes
14
69
@@ -41,7 +96,7 @@ def lookup_cast_type(sql_type)
41
96
42
97
def get_oid_type ( oid , fmod , column_name , sql_type = '' ) # :nodoc:
43
98
if !type_map . key? ( oid )
44
- load_additional_types ( type_map , [ oid ] )
99
+ load_additional_types ( type_map , oid )
45
100
end
46
101
47
102
type_map . fetch ( oid , fmod , sql_type ) {
@@ -138,26 +193,45 @@ def initialize_type_map(m)
138
193
end
139
194
140
195
load_additional_types ( m )
196
+
197
+ # pgjdbc returns these if the column is auto-incrmenting
198
+ m . alias_type 'serial' , 'int4'
199
+ m . alias_type 'bigserial' , 'int8'
141
200
end
142
201
143
- def load_additional_types ( type_map , oids = nil ) # :nodoc:
144
- initializer = OID :: TypeMapInitializer . new ( type_map )
202
+ def load_additional_types ( type_map , oid = nil ) # :nodoc:
203
+ initializer = ArjdbcTypeMapInitializer . new ( type_map )
145
204
146
205
if supports_ranges?
147
206
query = <<-SQL
148
- SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
207
+ SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype,
208
+ ns.nspname, ns.nspname = ANY(current_schemas(true)) in_ns
149
209
FROM pg_type as t
150
210
LEFT JOIN pg_range as r ON oid = rngtypid
211
+ JOIN pg_namespace AS ns ON t.typnamespace = ns.oid
151
212
SQL
152
213
else
153
214
query = <<-SQL
154
- SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype
215
+ SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype,
216
+ ns.nspname, ns.nspname = ANY(current_schemas(true)) in_ns
155
217
FROM pg_type as t
218
+ JOIN pg_namespace AS ns ON t.typnamespace = ns.oid
156
219
SQL
157
220
end
158
221
159
- if oids
160
- query += "WHERE t.oid::integer IN (%s)" % oids . join ( ", " )
222
+ if oid
223
+ if oid . is_a? Numeric || oid . match ( /^\d +$/ )
224
+ # numeric OID
225
+ query += "WHERE t.oid::integer = %s" % oid
226
+
227
+ elsif m = oid . match ( /"?(\w +)"?\. "?(\w +)"?/ )
228
+ # namespace and type name
229
+ query += "WHERE ns.nspname = '%s' AND t.typname = '%s'" % [ m [ 1 ] , m [ 2 ] ]
230
+
231
+ else
232
+ # only type name
233
+ query += "WHERE t.typname = '%s' AND ns.nspname = ANY(current_schemas(true))" % oid
234
+ end
161
235
else
162
236
query += initializer . query_conditions_for_initial_load ( type_map )
163
237
end
0 commit comments