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