activerecord-jdbc-adapter 5.0.pre1 → 51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +1 -2
- data/.travis.yml +15 -416
- data/Gemfile +35 -37
- data/README.md +23 -118
- data/RUNNING_TESTS.md +31 -26
- data/Rakefile +2 -3
- data/activerecord-jdbc-adapter.gemspec +1 -2
- data/lib/arjdbc/abstract/connection_management.rb +21 -0
- data/lib/arjdbc/abstract/core.rb +62 -0
- data/lib/arjdbc/abstract/database_statements.rb +46 -0
- data/lib/arjdbc/abstract/statement_cache.rb +58 -0
- data/lib/arjdbc/abstract/transaction_support.rb +86 -0
- data/lib/arjdbc/derby/adapter.rb +6 -1
- data/lib/arjdbc/discover.rb +0 -7
- data/lib/arjdbc/firebird/adapter.rb +2 -2
- data/lib/arjdbc/jdbc/adapter.rb +10 -252
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/connection.rb +6 -0
- data/lib/arjdbc/jdbc.rb +2 -2
- data/lib/arjdbc/mysql/adapter.rb +87 -944
- data/lib/arjdbc/mysql/connection_methods.rb +4 -2
- data/lib/arjdbc/postgresql/adapter.rb +288 -1023
- data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
- data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
- data/lib/arjdbc/postgresql/base/pgconn.rb +8 -5
- data/lib/arjdbc/postgresql/column.rb +10 -599
- data/lib/arjdbc/postgresql/connection_methods.rb +9 -0
- data/lib/arjdbc/postgresql/name.rb +24 -0
- data/lib/arjdbc/postgresql/oid_types.rb +25 -110
- data/lib/arjdbc/sqlite3/adapter.rb +171 -170
- data/lib/arjdbc/tasks/database_tasks.rb +1 -3
- data/lib/arjdbc/tasks/db2_database_tasks.rb +2 -2
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +3 -3
- data/rakelib/02-test.rake +0 -12
- data/rakelib/compile.rake +1 -1
- data/rakelib/db.rake +7 -5
- data/rakelib/rails.rake +63 -64
- data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +1 -17
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +518 -1260
- data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +53 -134
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +214 -240
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +0 -20
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +85 -10
- metadata +20 -34
- data/Appraisals +0 -41
- data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
- data/lib/arjdbc/common_jdbc_methods.rb +0 -89
- data/lib/arjdbc/mysql/bulk_change_table.rb +0 -150
- data/lib/arjdbc/mysql/column.rb +0 -162
- data/lib/arjdbc/mysql/explain_support.rb +0 -82
- data/lib/arjdbc/mysql/schema_creation.rb +0 -58
- data/lib/arjdbc/oracle/adapter.rb +0 -952
- data/lib/arjdbc/oracle/column.rb +0 -126
- data/lib/arjdbc/oracle/connection_methods.rb +0 -21
- data/lib/arjdbc/oracle.rb +0 -4
- data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +0 -21
- data/lib/arjdbc/postgresql/base/oid.rb +0 -412
- data/lib/arjdbc/postgresql/base/schema_definitions.rb +0 -131
- data/lib/arjdbc/postgresql/explain_support.rb +0 -53
- data/lib/arjdbc/postgresql/oid/bytea.rb +0 -2
- data/lib/arjdbc/postgresql/schema_creation.rb +0 -60
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +0 -297
- data/lib/arjdbc/tasks/oracle_database_tasks.rb +0 -65
- data/src/java/arjdbc/oracle/OracleModule.java +0 -75
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +0 -465
data/lib/arjdbc/oracle/column.rb
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
module ArJdbc
|
2
|
-
module Oracle
|
3
|
-
|
4
|
-
# @see ActiveRecord::ConnectionAdapters::JdbcColumn#column_types
|
5
|
-
def self.column_selector
|
6
|
-
[ /oracle/i, lambda { |config, column| column.extend(Column) } ]
|
7
|
-
end
|
8
|
-
|
9
|
-
# @see ActiveRecord::ConnectionAdapters::JdbcColumn
|
10
|
-
module Column
|
11
|
-
|
12
|
-
def self.included(base)
|
13
|
-
# NOTE: assumes a standalone OracleColumn class
|
14
|
-
class << base; include Cast; end # unless AR42
|
15
|
-
end
|
16
|
-
|
17
|
-
def primary=(value)
|
18
|
-
super
|
19
|
-
@type = :integer if value && @sql_type =~ /^NUMBER$/i
|
20
|
-
end unless AR42
|
21
|
-
|
22
|
-
def type_cast(value)
|
23
|
-
return nil if value.nil?
|
24
|
-
case type
|
25
|
-
when :datetime then self.class.string_to_time(value)
|
26
|
-
when :timestamp then self.class.string_to_time(value)
|
27
|
-
when :boolean then self.class.value_to_boolean(value)
|
28
|
-
else
|
29
|
-
super
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def type_cast_code(var_name)
|
34
|
-
case type
|
35
|
-
when :datetime then "#{self.class.name}.string_to_time(#{var_name})"
|
36
|
-
when :timestamp then "#{self.class.name}.string_to_time(#{var_name})"
|
37
|
-
when :boolean then "#{self.class.name}.value_to_boolean(#{var_name})"
|
38
|
-
else
|
39
|
-
super
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def sql_type
|
44
|
-
(@sql_type || '').start_with?('XMLTYPE') ? 'XMLTYPE' : @sql_type
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def extract_limit(sql_type)
|
50
|
-
case sql_type
|
51
|
-
when /^(clob|date)/i then nil
|
52
|
-
when /^xml/i then nil
|
53
|
-
else super
|
54
|
-
end
|
55
|
-
end unless AR42
|
56
|
-
|
57
|
-
def simplified_type(field_type)
|
58
|
-
case field_type
|
59
|
-
when /char/i then :string
|
60
|
-
when /float|double/i then :float
|
61
|
-
when /int/i then :integer
|
62
|
-
when /^number\(1\)$/i then Oracle.emulate_booleans? ? :boolean : :integer
|
63
|
-
when /^num|dec|real/i then extract_scale(field_type) == 0 ? :integer : :decimal
|
64
|
-
# Oracle TIMESTAMP stores the date and time to up to 9 digits of sub-second precision
|
65
|
-
when /TIMESTAMP/i then :timestamp
|
66
|
-
# Oracle DATE stores the date and time to the second
|
67
|
-
when /DATE|TIME/i then :datetime
|
68
|
-
when /CLOB/i then :text
|
69
|
-
when /BLOB/i then :binary
|
70
|
-
when /XML/i then :xml
|
71
|
-
else
|
72
|
-
super
|
73
|
-
end
|
74
|
-
end unless AR42
|
75
|
-
|
76
|
-
# Post process default value from JDBC into a Rails-friendly format (columns{-internal})
|
77
|
-
def default_value(value)
|
78
|
-
return nil unless value
|
79
|
-
value = value.strip # Not sure why we need this for Oracle?
|
80
|
-
upcase = value.upcase
|
81
|
-
|
82
|
-
return nil if upcase == "NULL"
|
83
|
-
# SYSDATE default should be treated like a NULL value
|
84
|
-
return nil if upcase == "SYSDATE"
|
85
|
-
# jdbc returns column default strings with actual single quotes around the value.
|
86
|
-
return $1 if value =~ /^'(.*)'$/
|
87
|
-
|
88
|
-
value
|
89
|
-
end
|
90
|
-
|
91
|
-
module Cast
|
92
|
-
|
93
|
-
# Convert a value to a boolean.
|
94
|
-
def value_to_boolean(value)
|
95
|
-
# NOTE: Oracle JDBC meta-data gets us DECIMAL for NUMBER(1) values
|
96
|
-
# thus we're likely to get a column back as BigDecimal (e.g. 1.0)
|
97
|
-
if value.is_a?(String)
|
98
|
-
value.blank? ? nil : value == '1'
|
99
|
-
elsif value.is_a?(Numeric)
|
100
|
-
value.to_i == 1 # <BigDecimal:7b5bfe,'0.1E1',1(4)>
|
101
|
-
else
|
102
|
-
!! value
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
# @override
|
107
|
-
def string_to_time(string)
|
108
|
-
return string unless string.is_a?(String)
|
109
|
-
return nil if string.empty?
|
110
|
-
return Time.now if string.index('CURRENT') == 0 # TODO seems very wrong
|
111
|
-
|
112
|
-
super(string)
|
113
|
-
end
|
114
|
-
|
115
|
-
# @private
|
116
|
-
def guess_date_or_time(value)
|
117
|
-
return value if value.is_a? Date
|
118
|
-
( value && value.hour == 0 && value.min == 0 && value.sec == 0 ) ?
|
119
|
-
Date.new(value.year, value.month, value.day) : value
|
120
|
-
end
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
ArJdbc::ConnectionMethods.module_eval do
|
2
|
-
# Unless a connection URL (`url: jdbc:oracle:...`) is specified we'll use the
|
3
|
-
# *thin* method to connect to the Oracle DB.
|
4
|
-
# @note Oracle's JDBC driver should be on the class-path.
|
5
|
-
def oracle_connection(config)
|
6
|
-
config[:adapter_spec] ||= ::ArJdbc::Oracle
|
7
|
-
config[:adapter_class] = ActiveRecord::ConnectionAdapters::OracleAdapter unless config.key?(:adapter_class)
|
8
|
-
|
9
|
-
return jndi_connection(config) if jndi_config?(config)
|
10
|
-
|
11
|
-
config[:port] ||= 1521
|
12
|
-
config[:url] ||= "jdbc:oracle:thin:@#{config[:host]}:#{config[:port]}:#{config[:database] || 'XE'}"
|
13
|
-
config[:driver] ||= "oracle.jdbc.driver.OracleDriver"
|
14
|
-
config[:connection_alive_sql] ||= 'SELECT 1 FROM DUAL'
|
15
|
-
unless config.key?(:statement_escape_processing)
|
16
|
-
config[:statement_escape_processing] = true
|
17
|
-
end
|
18
|
-
jdbc_connection(config)
|
19
|
-
end
|
20
|
-
alias_method :jdbcoracle_connection, :oracle_connection
|
21
|
-
end
|
data/lib/arjdbc/oracle.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
ActiveRecord::ConnectionAdapters::PostgreSQL::OID::DateTime.class_eval do
|
2
|
-
def cast_value(value)
|
3
|
-
if value.is_a?(::String)
|
4
|
-
case value
|
5
|
-
when 'infinity' then ::Float::INFINITY
|
6
|
-
when '-infinity' then -::Float::INFINITY
|
7
|
-
#when / BC$/
|
8
|
-
# astronomical_year = format("%04d", value[/^\d+/].to_i)
|
9
|
-
# super(value.sub(/ BC$/, "").sub(/^\d+/, astronomical_year))
|
10
|
-
else
|
11
|
-
if value.end_with?(' BC')
|
12
|
-
DateTime.parse("-#{value}"[0...-3])
|
13
|
-
else
|
14
|
-
super
|
15
|
-
end
|
16
|
-
end
|
17
|
-
else
|
18
|
-
value
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,412 +0,0 @@
|
|
1
|
-
# copied from active_record/connection_adapters/postgresql/oid.rb
|
2
|
-
# until it's some day shareable with Rails ... this is not public API !
|
3
|
-
module ActiveRecord
|
4
|
-
module ConnectionAdapters
|
5
|
-
module PostgreSQL
|
6
|
-
module OID
|
7
|
-
class Type
|
8
|
-
def type; end
|
9
|
-
end
|
10
|
-
|
11
|
-
class Identity < Type
|
12
|
-
def type_cast(value)
|
13
|
-
value
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class Bit < Type
|
18
|
-
def type_cast(value)
|
19
|
-
if String === value
|
20
|
-
ConnectionAdapters::PostgreSQLColumn.string_to_bit value
|
21
|
-
else
|
22
|
-
value
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
class Bytea < Type
|
28
|
-
def type_cast(value)
|
29
|
-
return if value.nil?
|
30
|
-
PGconn.unescape_bytea value
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
class Money < Type
|
35
|
-
def type_cast(value)
|
36
|
-
return if value.nil?
|
37
|
-
return value unless String === value
|
38
|
-
|
39
|
-
# Because money output is formatted according to the locale, there are two
|
40
|
-
# cases to consider (note the decimal separators):
|
41
|
-
# (1) $12,345,678.12
|
42
|
-
# (2) $12.345.678,12
|
43
|
-
# Negative values are represented as follows:
|
44
|
-
# (3) -$2.55
|
45
|
-
# (4) ($2.55)
|
46
|
-
|
47
|
-
value.sub!(/^\((.+)\)$/, '-\1') # (4)
|
48
|
-
case value
|
49
|
-
when /^-?\D+[\d,]+\.\d{2}$/ # (1)
|
50
|
-
value.gsub!(/[^-\d.]/, '')
|
51
|
-
when /^-?\D+[\d.]+,\d{2}$/ # (2)
|
52
|
-
value.gsub!(/[^-\d,]/, '').sub!(/,/, '.')
|
53
|
-
end
|
54
|
-
|
55
|
-
ConnectionAdapters::Column.value_to_decimal value
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
class Vector < Type
|
60
|
-
attr_reader :delim, :subtype
|
61
|
-
|
62
|
-
# +delim+ corresponds to the `typdelim` column in the pg_types
|
63
|
-
# table. +subtype+ is derived from the `typelem` column in the
|
64
|
-
# pg_types table.
|
65
|
-
def initialize(delim, subtype)
|
66
|
-
@delim = delim
|
67
|
-
@subtype = subtype
|
68
|
-
end
|
69
|
-
|
70
|
-
# FIXME: this should probably split on +delim+ and use +subtype+
|
71
|
-
# to cast the values. Unfortunately, the current Rails behavior
|
72
|
-
# is to just return the string.
|
73
|
-
def type_cast(value)
|
74
|
-
value
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
class Point < Type
|
79
|
-
def type_cast(value)
|
80
|
-
if ::String === value
|
81
|
-
ConnectionAdapters::PostgreSQLColumn.string_to_point value
|
82
|
-
else
|
83
|
-
value
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
class Array < Type
|
89
|
-
attr_reader :subtype
|
90
|
-
def initialize(subtype)
|
91
|
-
@subtype = subtype
|
92
|
-
end
|
93
|
-
|
94
|
-
def type_cast(value)
|
95
|
-
if ::String === value
|
96
|
-
ConnectionAdapters::PostgreSQLColumn.string_to_array value, @subtype
|
97
|
-
else
|
98
|
-
value
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
class Range < Type
|
104
|
-
attr_reader :subtype
|
105
|
-
def initialize(subtype)
|
106
|
-
@subtype = subtype
|
107
|
-
end
|
108
|
-
|
109
|
-
def extract_bounds(value)
|
110
|
-
from, to = value[1..-2].split(',')
|
111
|
-
{
|
112
|
-
from: (value[1] == ',' || from == '-infinity') ? infinity(:negative => true) : from,
|
113
|
-
to: (value[-2] == ',' || to == 'infinity') ? infinity : to,
|
114
|
-
exclude_start: (value[0] == '('),
|
115
|
-
exclude_end: (value[-1] == ')')
|
116
|
-
}
|
117
|
-
end
|
118
|
-
|
119
|
-
def infinity(options = {})
|
120
|
-
::Float::INFINITY * (options[:negative] ? -1 : 1)
|
121
|
-
end
|
122
|
-
|
123
|
-
def infinity?(value)
|
124
|
-
value.respond_to?(:infinite?) && value.infinite?
|
125
|
-
end
|
126
|
-
|
127
|
-
def to_integer(value)
|
128
|
-
infinity?(value) ? value : value.to_i
|
129
|
-
end
|
130
|
-
|
131
|
-
def type_cast(value)
|
132
|
-
return if value.nil? || value == 'empty'
|
133
|
-
return value if value.is_a?(::Range)
|
134
|
-
|
135
|
-
extracted = extract_bounds(value)
|
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
|
155
|
-
end
|
156
|
-
|
157
|
-
::Range.new(from, to, extracted[:exclude_end])
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
class Integer < Type
|
162
|
-
def type_cast(value)
|
163
|
-
return if value.nil?
|
164
|
-
|
165
|
-
ConnectionAdapters::Column.value_to_integer value
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
class Boolean < Type
|
170
|
-
def type_cast(value)
|
171
|
-
return if value.nil?
|
172
|
-
|
173
|
-
ConnectionAdapters::Column.value_to_boolean value
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
class Timestamp < Type
|
178
|
-
def type; :timestamp; end
|
179
|
-
|
180
|
-
def type_cast(value)
|
181
|
-
return if value.nil?
|
182
|
-
|
183
|
-
# FIXME: probably we can improve this since we know it is PG
|
184
|
-
# specific
|
185
|
-
ConnectionAdapters::PostgreSQLColumn.string_to_time value
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
class Date < Type
|
190
|
-
def type; :datetime; end
|
191
|
-
|
192
|
-
def type_cast(value)
|
193
|
-
return if value.nil?
|
194
|
-
|
195
|
-
# FIXME: probably we can improve this since we know it is PG
|
196
|
-
# specific
|
197
|
-
ConnectionAdapters::Column.value_to_date value
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
class Time < Type
|
202
|
-
def type_cast(value)
|
203
|
-
return if value.nil?
|
204
|
-
|
205
|
-
# FIXME: probably we can improve this since we know it is PG
|
206
|
-
# specific
|
207
|
-
ConnectionAdapters::Column.string_to_dummy_time value
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
class Float < Type
|
212
|
-
def type_cast(value)
|
213
|
-
case value
|
214
|
-
when nil; nil
|
215
|
-
when 'Infinity'; ::Float::INFINITY
|
216
|
-
when '-Infinity'; -::Float::INFINITY
|
217
|
-
when 'NaN'; ::Float::NAN
|
218
|
-
else
|
219
|
-
value.to_f
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
class Decimal < Type
|
225
|
-
def type_cast(value)
|
226
|
-
return if value.nil?
|
227
|
-
|
228
|
-
ConnectionAdapters::Column.value_to_decimal value
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
class Hstore < Type
|
233
|
-
def type_cast_for_write(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)
|
238
|
-
end
|
239
|
-
|
240
|
-
def type_cast(value)
|
241
|
-
return if value.nil?
|
242
|
-
|
243
|
-
ConnectionAdapters::PostgreSQLColumn.string_to_hstore value
|
244
|
-
end
|
245
|
-
|
246
|
-
def accessor
|
247
|
-
ActiveRecord::Store::StringKeyedHashAccessor
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
class Cidr < Type
|
252
|
-
def type_cast(value)
|
253
|
-
return if value.nil?
|
254
|
-
|
255
|
-
ConnectionAdapters::PostgreSQLColumn.string_to_cidr value
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
class Json < Type
|
260
|
-
def type_cast_for_write(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)
|
265
|
-
end
|
266
|
-
|
267
|
-
def type_cast(value)
|
268
|
-
return if value.nil?
|
269
|
-
|
270
|
-
ConnectionAdapters::PostgreSQLColumn.string_to_json value
|
271
|
-
end
|
272
|
-
|
273
|
-
def accessor
|
274
|
-
ActiveRecord::Store::StringKeyedHashAccessor
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
class Jsonb < Type
|
279
|
-
def type_cast_for_write(value)
|
280
|
-
# roundtrip to ensure uniform uniform types
|
281
|
-
# TODO: This is not an efficient solution.
|
282
|
-
stringified = ConnectionAdapters::PostgreSQLColumn.json_to_string(value)
|
283
|
-
type_cast(stringified)
|
284
|
-
end
|
285
|
-
|
286
|
-
def type_cast(value)
|
287
|
-
return if value.nil?
|
288
|
-
|
289
|
-
ConnectionAdapters::PostgreSQLColumn.string_to_json value
|
290
|
-
end
|
291
|
-
|
292
|
-
def accessor
|
293
|
-
ActiveRecord::Store::StringKeyedHashAccessor
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
|
-
class TypeMap
|
298
|
-
def initialize
|
299
|
-
@mapping = {}
|
300
|
-
end
|
301
|
-
|
302
|
-
def []=(oid, type)
|
303
|
-
@mapping[oid] = type
|
304
|
-
end
|
305
|
-
|
306
|
-
def [](oid)
|
307
|
-
@mapping[oid]
|
308
|
-
end
|
309
|
-
|
310
|
-
def clear
|
311
|
-
@mapping.clear
|
312
|
-
end
|
313
|
-
|
314
|
-
def key?(oid)
|
315
|
-
@mapping.key? oid
|
316
|
-
end
|
317
|
-
|
318
|
-
def fetch(ftype, fmod)
|
319
|
-
# The type for the numeric depends on the width of the field,
|
320
|
-
# so we'll do something special here.
|
321
|
-
#
|
322
|
-
# When dealing with decimal columns:
|
323
|
-
#
|
324
|
-
# places after decimal = fmod - 4 & 0xffff
|
325
|
-
# places before decimal = (fmod - 4) >> 16 & 0xffff
|
326
|
-
if ftype == 1700 && (fmod - 4 & 0xffff).zero?
|
327
|
-
ftype = 23
|
328
|
-
end
|
329
|
-
|
330
|
-
@mapping.fetch(ftype) { |oid| yield oid, fmod }
|
331
|
-
end
|
332
|
-
end
|
333
|
-
|
334
|
-
# When the PG adapter connects, the pg_type table is queried. The
|
335
|
-
# key of this hash maps to the `typname` column from the table.
|
336
|
-
# type_map is then dynamically built with oids as the key and type
|
337
|
-
# objects as values.
|
338
|
-
NAMES = Hash.new { |h,k| # :nodoc:
|
339
|
-
h[k] = OID::Identity.new
|
340
|
-
}
|
341
|
-
|
342
|
-
# Register an OID type named +name+ with a typecasting object in
|
343
|
-
# +type+. +name+ should correspond to the `typname` column in
|
344
|
-
# the `pg_type` table.
|
345
|
-
def self.register_type(name, type)
|
346
|
-
NAMES[name] = type
|
347
|
-
end
|
348
|
-
|
349
|
-
# Alias the +old+ type to the +new+ type.
|
350
|
-
def self.alias_type(new, old)
|
351
|
-
NAMES[new] = NAMES[old]
|
352
|
-
end
|
353
|
-
|
354
|
-
# Is +name+ a registered type?
|
355
|
-
def self.registered_type?(name)
|
356
|
-
NAMES.key? name
|
357
|
-
end
|
358
|
-
|
359
|
-
register_type 'int2', OID::Integer.new
|
360
|
-
alias_type 'int4', 'int2'
|
361
|
-
alias_type 'int8', 'int2'
|
362
|
-
alias_type 'oid', 'int2'
|
363
|
-
|
364
|
-
register_type 'daterange', OID::Range.new(:date)
|
365
|
-
register_type 'numrange', OID::Range.new(:decimal)
|
366
|
-
register_type 'tsrange', OID::Range.new(:time)
|
367
|
-
register_type 'int4range', OID::Range.new(:integer)
|
368
|
-
alias_type 'tstzrange', 'tsrange'
|
369
|
-
alias_type 'int8range', 'int4range'
|
370
|
-
|
371
|
-
register_type 'numeric', OID::Decimal.new
|
372
|
-
register_type 'text', OID::Identity.new
|
373
|
-
alias_type 'varchar', 'text'
|
374
|
-
alias_type 'char', 'text'
|
375
|
-
alias_type 'bpchar', 'text'
|
376
|
-
alias_type 'xml', 'text'
|
377
|
-
|
378
|
-
# FIXME: why are we keeping these types as strings?
|
379
|
-
alias_type 'tsvector', 'text'
|
380
|
-
alias_type 'interval', 'text'
|
381
|
-
alias_type 'macaddr', 'text'
|
382
|
-
alias_type 'uuid', 'text'
|
383
|
-
|
384
|
-
register_type 'money', OID::Money.new
|
385
|
-
register_type 'bytea', OID::Bytea.new
|
386
|
-
register_type 'bool', OID::Boolean.new
|
387
|
-
register_type 'bit', OID::Bit.new
|
388
|
-
register_type 'varbit', OID::Bit.new
|
389
|
-
|
390
|
-
register_type 'float4', OID::Float.new
|
391
|
-
alias_type 'float8', 'float4'
|
392
|
-
|
393
|
-
register_type 'timestamp', OID::Timestamp.new
|
394
|
-
register_type 'timestamptz', OID::Timestamp.new
|
395
|
-
register_type 'date', OID::Date.new
|
396
|
-
register_type 'time', OID::Time.new
|
397
|
-
|
398
|
-
register_type 'path', OID::Identity.new
|
399
|
-
register_type 'point', OID::Point.new
|
400
|
-
register_type 'polygon', OID::Identity.new
|
401
|
-
register_type 'circle', OID::Identity.new
|
402
|
-
register_type 'hstore', OID::Hstore.new
|
403
|
-
register_type 'json', OID::Json.new
|
404
|
-
register_type 'jsonb', OID::Jsonb.new
|
405
|
-
register_type 'ltree', OID::Identity.new
|
406
|
-
|
407
|
-
register_type 'cidr', OID::Cidr.new
|
408
|
-
alias_type 'inet', 'cidr'
|
409
|
-
end
|
410
|
-
end
|
411
|
-
end
|
412
|
-
end
|