activerecord-jdbc-adapter 5.0.pre1 → 51.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -2
  3. data/.travis.yml +15 -416
  4. data/Gemfile +35 -37
  5. data/README.md +23 -118
  6. data/RUNNING_TESTS.md +31 -26
  7. data/Rakefile +2 -3
  8. data/activerecord-jdbc-adapter.gemspec +1 -2
  9. data/lib/arjdbc/abstract/connection_management.rb +21 -0
  10. data/lib/arjdbc/abstract/core.rb +62 -0
  11. data/lib/arjdbc/abstract/database_statements.rb +46 -0
  12. data/lib/arjdbc/abstract/statement_cache.rb +58 -0
  13. data/lib/arjdbc/abstract/transaction_support.rb +86 -0
  14. data/lib/arjdbc/derby/adapter.rb +6 -1
  15. data/lib/arjdbc/discover.rb +0 -7
  16. data/lib/arjdbc/firebird/adapter.rb +2 -2
  17. data/lib/arjdbc/jdbc/adapter.rb +10 -252
  18. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  19. data/lib/arjdbc/jdbc/connection.rb +6 -0
  20. data/lib/arjdbc/jdbc.rb +2 -2
  21. data/lib/arjdbc/mysql/adapter.rb +87 -944
  22. data/lib/arjdbc/mysql/connection_methods.rb +4 -2
  23. data/lib/arjdbc/postgresql/adapter.rb +288 -1023
  24. data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
  25. data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
  26. data/lib/arjdbc/postgresql/base/pgconn.rb +8 -5
  27. data/lib/arjdbc/postgresql/column.rb +10 -599
  28. data/lib/arjdbc/postgresql/connection_methods.rb +9 -0
  29. data/lib/arjdbc/postgresql/name.rb +24 -0
  30. data/lib/arjdbc/postgresql/oid_types.rb +25 -110
  31. data/lib/arjdbc/sqlite3/adapter.rb +171 -170
  32. data/lib/arjdbc/tasks/database_tasks.rb +1 -3
  33. data/lib/arjdbc/tasks/db2_database_tasks.rb +2 -2
  34. data/lib/arjdbc/version.rb +1 -1
  35. data/pom.xml +3 -3
  36. data/rakelib/02-test.rake +0 -12
  37. data/rakelib/compile.rake +1 -1
  38. data/rakelib/db.rake +7 -5
  39. data/rakelib/rails.rake +63 -64
  40. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +1 -17
  41. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +518 -1260
  42. data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
  43. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +53 -134
  44. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +214 -240
  45. data/src/java/arjdbc/sqlite3/SQLite3Module.java +0 -20
  46. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +85 -10
  47. metadata +20 -34
  48. data/Appraisals +0 -41
  49. data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
  50. data/lib/arjdbc/common_jdbc_methods.rb +0 -89
  51. data/lib/arjdbc/mysql/bulk_change_table.rb +0 -150
  52. data/lib/arjdbc/mysql/column.rb +0 -162
  53. data/lib/arjdbc/mysql/explain_support.rb +0 -82
  54. data/lib/arjdbc/mysql/schema_creation.rb +0 -58
  55. data/lib/arjdbc/oracle/adapter.rb +0 -952
  56. data/lib/arjdbc/oracle/column.rb +0 -126
  57. data/lib/arjdbc/oracle/connection_methods.rb +0 -21
  58. data/lib/arjdbc/oracle.rb +0 -4
  59. data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +0 -21
  60. data/lib/arjdbc/postgresql/base/oid.rb +0 -412
  61. data/lib/arjdbc/postgresql/base/schema_definitions.rb +0 -131
  62. data/lib/arjdbc/postgresql/explain_support.rb +0 -53
  63. data/lib/arjdbc/postgresql/oid/bytea.rb +0 -2
  64. data/lib/arjdbc/postgresql/schema_creation.rb +0 -60
  65. data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +0 -297
  66. data/lib/arjdbc/tasks/oracle_database_tasks.rb +0 -65
  67. data/src/java/arjdbc/oracle/OracleModule.java +0 -75
  68. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +0 -465
@@ -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,4 +0,0 @@
1
- require 'arjdbc'
2
- require 'arjdbc/oracle/adapter'
3
- require 'arjdbc/oracle/connection_methods'
4
- ArJdbc.warn_unsupported_adapter 'oracle', [4, 2] # warns on AR >= 4.2
@@ -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