activerecord-jdbc-adapter 5.0.pre1 → 50.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord-jdbc-adapter might be problematic. Click here for more details.

Files changed (66) 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/lib/arjdbc/abstract/connection_management.rb +21 -0
  9. data/lib/arjdbc/abstract/core.rb +62 -0
  10. data/lib/arjdbc/abstract/database_statements.rb +46 -0
  11. data/lib/arjdbc/abstract/statement_cache.rb +58 -0
  12. data/lib/arjdbc/abstract/transaction_support.rb +86 -0
  13. data/lib/arjdbc/derby/adapter.rb +6 -1
  14. data/lib/arjdbc/discover.rb +0 -7
  15. data/lib/arjdbc/firebird/adapter.rb +2 -2
  16. data/lib/arjdbc/jdbc.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/mysql/adapter.rb +82 -946
  21. data/lib/arjdbc/mysql/connection_methods.rb +4 -2
  22. data/lib/arjdbc/postgresql/adapter.rb +270 -970
  23. data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
  24. data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
  25. data/lib/arjdbc/postgresql/base/pgconn.rb +8 -5
  26. data/lib/arjdbc/postgresql/column.rb +10 -599
  27. data/lib/arjdbc/postgresql/connection_methods.rb +9 -0
  28. data/lib/arjdbc/postgresql/name.rb +24 -0
  29. data/lib/arjdbc/postgresql/oid_types.rb +28 -109
  30. data/lib/arjdbc/sqlite3/adapter.rb +18 -42
  31. data/lib/arjdbc/tasks/database_tasks.rb +1 -3
  32. data/lib/arjdbc/tasks/db2_database_tasks.rb +2 -2
  33. data/lib/arjdbc/version.rb +1 -1
  34. data/pom.xml +3 -3
  35. data/rakelib/02-test.rake +0 -12
  36. data/rakelib/compile.rake +1 -1
  37. data/rakelib/db.rake +7 -5
  38. data/rakelib/rails.rake +67 -64
  39. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +1 -17
  40. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +518 -1260
  41. data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
  42. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +53 -134
  43. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +214 -240
  44. data/src/java/arjdbc/sqlite3/SQLite3Module.java +0 -20
  45. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +85 -10
  46. metadata +16 -29
  47. data/Appraisals +0 -41
  48. data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
  49. data/lib/arjdbc/common_jdbc_methods.rb +0 -89
  50. data/lib/arjdbc/mysql/bulk_change_table.rb +0 -150
  51. data/lib/arjdbc/mysql/column.rb +0 -162
  52. data/lib/arjdbc/mysql/explain_support.rb +0 -82
  53. data/lib/arjdbc/mysql/schema_creation.rb +0 -58
  54. data/lib/arjdbc/oracle.rb +0 -4
  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/postgresql/base/oid.rb +0 -412
  59. data/lib/arjdbc/postgresql/base/schema_definitions.rb +0 -131
  60. data/lib/arjdbc/postgresql/explain_support.rb +0 -53
  61. data/lib/arjdbc/postgresql/oid/bytea.rb +0 -2
  62. data/lib/arjdbc/postgresql/schema_creation.rb +0 -60
  63. data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +0 -297
  64. data/lib/arjdbc/tasks/oracle_database_tasks.rb +0 -65
  65. data/src/java/arjdbc/oracle/OracleModule.java +0 -75
  66. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +0 -465
@@ -0,0 +1,26 @@
1
+ # This implements a basic decoder to work around ActiveRecord's dependence on the pg gem
2
+ module ActiveRecord::ConnectionAdapters::PostgreSQL::OID
3
+ class Array < ActiveModel::Type::Value
4
+ module PG
5
+ module TextDecoder
6
+ class Array
7
+ # Loads pg_array_parser if available. String parsing can be
8
+ # performed quicker by a native extension, which will not create
9
+ # a large amount of Ruby objects that will need to be garbage
10
+ # collected. pg_array_parser has a C and Java extension
11
+ begin
12
+ require 'pg_array_parser'
13
+ include PgArrayParser
14
+ rescue LoadError
15
+ require_relative 'array_parser'
16
+ include ActiveRecord::ConnectionAdapters::PostgreSQL::ArrayParser
17
+ end
18
+
19
+ def initialize(name:, delimiter:); end
20
+
21
+ alias_method :decode, :parse_pg_array
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ # This implements a basic encoder to work around ActiveRecord's dependence on the pg gem
2
+ module ActiveRecord::ConnectionAdapters::PostgreSQL::OID
3
+ class Array < ActiveModel::Type::Value
4
+ module PG
5
+ module TextEncoder
6
+ class Array
7
+
8
+ def initialize(name:, delimiter:)
9
+ @type = if name == 'string[]'.freeze
10
+ 'text'.freeze
11
+ else
12
+ base_type = name.chomp('[]'.freeze).to_sym
13
+ ActiveRecord::Base.connection.native_database_types[base_type][:name]
14
+ end
15
+ end
16
+
17
+ def encode(values)
18
+ ActiveRecord::Base.connection.jdbc_connection.create_array_of(@type, values.to_java).to_s
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,8 +1,11 @@
1
1
  module ActiveRecord::ConnectionAdapters::PostgreSQL::OID
2
- class PGconn # emulate PGconn#unescape_bytea due #652
3
- # NOTE: on pg gem ... PGconn = (class) PG::Connection
4
- def self.unescape_bytea(escaped)
5
- ArJdbc::PostgreSQL.unescape_bytea(escaped)
2
+ class Bytea < ActiveModel::Type::Binary
3
+ module PG
4
+ class Connection # emulate PG::Connection#unescape_bytea due #652
5
+ def self.unescape_bytea(escaped)
6
+ ArJdbc::PostgreSQL.unescape_bytea(escaped)
7
+ end
8
+ end
6
9
  end
7
10
  end
8
- end
11
+ end
@@ -1,11 +1,6 @@
1
1
  module ArJdbc
2
2
  module PostgreSQL
3
3
 
4
- # @see ActiveRecord::ConnectionAdapters::JdbcColumn#column_types
5
- def self.column_selector
6
- [ /postgre/i, lambda { |cfg, column| column.extend(Column) } ]
7
- end
8
-
9
4
  # @private these are defined on the Adapter class since 4.2
10
5
  module ColumnHelpers
11
6
 
@@ -20,13 +15,18 @@ module ArJdbc
20
15
  end
21
16
 
22
17
  # Extracts the value from a PostgreSQL column default definition.
23
- def extract_value_from_default(oid, default) # :nodoc:
18
+ def extract_value_from_default(default) # :nodoc:
24
19
  case default
25
20
  # Quoted types
26
- when /\A[\(B]?'(.*)'::/m
27
- $1.gsub(/''/, "'")
21
+ when /\A[\(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
22
+ # The default 'now'::date is CURRENT_DATE
23
+ if $1 == "now".freeze && $2 == "date".freeze
24
+ nil
25
+ else
26
+ $1.gsub("''".freeze, "'".freeze)
27
+ end
28
28
  # Boolean types
29
- when 'true', 'false'
29
+ when 'true'.freeze, 'false'.freeze
30
30
  default
31
31
  # Numeric types
32
32
  when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
@@ -42,599 +42,10 @@ module ArJdbc
42
42
  end
43
43
 
44
44
  def extract_default_function(default_value, default) # :nodoc:
45
- default if ! default_value && ( %r{\w+\(.*\)} === default )
45
+ default if ! default_value && ( %r{\w+\(.*\)|\(.*\)::\w+} === default )
46
46
  end
47
47
 
48
48
  end
49
49
 
50
- # Column behavior based on PostgreSQL adapter in Rails.
51
- # @see ActiveRecord::ConnectionAdapters::JdbcColumn
52
- module Column
53
-
54
- attr_accessor :array
55
- alias array? array
56
-
57
- def initialize(name, default, cast_type, sql_type = nil, null = true, default_function = nil,
58
- oid = nil, adapter = nil) # added arguments
59
- if sql_type.to_s[-2, 2] == '[]'
60
- @array = true
61
- super(name, default, cast_type, sql_type[0..-3], null)
62
- else
63
- @array = false
64
- super(name, default, cast_type, sql_type, null)
65
- end
66
-
67
- @oid = oid # used on Java side - expects @oid on Column instances
68
- #@adapter = adapter
69
-
70
- @default_function = default_function
71
- end
72
-
73
- end if AR42
74
-
75
- # @private (AR < 4.2 version) documented above
76
- module Column
77
-
78
- def initialize(name, default, oid_type = nil, sql_type = nil, null = true,
79
- fmod = nil, adapter = nil) # added due resolving #oid_type
80
- if oid_type.is_a?(Integer) # the "main" if branch (on AR 4.x)
81
- @oid = oid_type; @fmod = fmod; @adapter = adapter # see Column#oid_type
82
- elsif oid_type.respond_to?(:type_cast) # MRI compatibility
83
- @oid_type = oid_type; # @fmod = fmod; @adapter = adapter
84
- else # NOTE: AR <= 3.2 : (name, default, sql_type = nil, null = true)
85
- null, sql_type, oid_type = !! sql_type, oid_type, nil
86
- end
87
- if sql_type.to_s[-2, 2] == '[]' && AR40
88
- @array = true if respond_to?(:array)
89
- super(name, default, sql_type[0..-3], null)
90
- else
91
- @array = false if respond_to?(:array)
92
- super(name, default, sql_type, null)
93
- end
94
-
95
- @default_function = extract_default_function(@default, default)
96
- end
97
-
98
- def self.included(base)
99
- # NOTE: assumes a standalone PostgreSQLColumn class
100
- base_meta = class << base; self end
101
- base_meta.send :attr_accessor, :money_precision
102
-
103
- # Loads pg_array_parser if available. String parsing can be
104
- # performed quicker by a native extension, which will not create
105
- # a large amount of Ruby objects that will need to be garbage
106
- # collected. pg_array_parser has a C and Java extension
107
- begin
108
- require 'pg_array_parser'
109
- base_meta.send :include, PgArrayParser
110
- rescue LoadError
111
- if AR42
112
- require 'active_record/connection_adapters/postgresql/array_parser'
113
- else
114
- require 'arjdbc/postgresql/base/array_parser'
115
- end
116
- base_meta.send :include, ActiveRecord::ConnectionAdapters::PostgreSQL::ArrayParser
117
- end if AR40
118
-
119
- base_meta.send :include, Cast
120
-
121
- base.send :include, ColumnHelpers
122
- end
123
-
124
- if AR40 && ! AR42
125
-
126
- # @private
127
- def oid_type
128
- @oid_type ||= begin
129
- raise "oid not defined" unless oid = (@oid ||= nil)
130
- @adapter.get_oid_type(oid.to_i, @fmod.to_i, name)
131
- end
132
- end
133
-
134
- # @private
135
- def accessor; oid_type.accessor end
136
-
137
- end
138
-
139
- ( attr_accessor :array; def array?; array; end ) if AR40
140
-
141
- def number?; !array && super end if AR40
142
- def text?; !array && super end if AR40
143
-
144
- # Extracts the value from a PostgreSQL column default definition.
145
- #
146
- # @override JdbcColumn#default_value
147
- # NOTE: based on `self.extract_value_from_default(default)` code
148
- def default_value(default)
149
- # This is a performance optimization for Ruby 1.9.2 in development.
150
- # If the value is nil, we return nil straight away without checking
151
- # the regular expressions. If we check each regular expression,
152
- # Regexp#=== will call NilClass#to_str, which will trigger
153
- # method_missing (defined by whiny nil in ActiveSupport) which
154
- # makes this method very very slow.
155
- return default unless default
156
-
157
- case default
158
- when /\A'(.*)'::(num|date|tstz|ts|int4|int8)range\z/m
159
- $1
160
- # Numeric types
161
- when /\A\(?(-?\d+(\.\d*)?\)?(::bigint)?)\z/
162
- $1
163
- # Character types
164
- when /\A\(?'(.*)'::.*\b(?:character varying|bpchar|text)\z/m
165
- $1
166
- # Binary data types
167
- when /\A'(.*)'::bytea\z/m
168
- $1
169
- # Date/time types
170
- when /\A'(.+)'::(?:time(?:stamp)? with(?:out)? time zone|date)\z/
171
- $1
172
- when /\A'(.*)'::interval\z/
173
- $1
174
- # Boolean type
175
- when 'true'
176
- true
177
- when 'false'
178
- false
179
- # Geometric types
180
- when /\A'(.*)'::(?:point|line|lseg|box|"?path"?|polygon|circle)\z/
181
- $1
182
- # Network address types
183
- when /\A'(.*)'::(?:cidr|inet|macaddr)\z/
184
- $1
185
- # Bit string types
186
- when /\AB'(.*)'::"?bit(?: varying)?"?\z/
187
- $1
188
- # XML type
189
- when /\A'(.*)'::xml\z/m
190
- $1
191
- # Arrays
192
- when /\A'(.*)'::"?\D+"?\[\]\z/
193
- $1
194
- when /\AARRAY\[(.*)\](::\D+)?\z/
195
- "{#{$1.gsub(/'(.*?)'::[a-z]+(,)?\s?/, '\1\2')}}"
196
- # Hstore
197
- when /\A'(.*)'::hstore\z/
198
- $1
199
- # JSON
200
- when /\A'(.*)'::json\z/
201
- $1
202
- # JSONB
203
- when /\A'(.*)'::jsonb\z/
204
- $1
205
- # Object identifier types
206
- when /\A-?\d+\z/
207
- $1
208
- else
209
- # Anything else is blank, some user type, or some function
210
- # and we can't know the value of that, so return nil.
211
- nil
212
- end
213
- end
214
-
215
- # Casts value (which is a String) to an appropriate instance.
216
- # @private
217
- def type_cast(value) # AR < 4.0 version
218
- return if value.nil?
219
- return super if respond_to?(:encoded?) && encoded? # since AR-3.2
220
-
221
- case sql_type
222
- when 'money'
223
- self.class.string_to_money(value)
224
- else super
225
- end
226
- end
227
-
228
- # Casts value (which is a String) to an appropriate instance.
229
- def type_cast(value, type = false) # AR >= 4.0 version
230
- return if value.nil?
231
- return super(value) if encoded?
232
-
233
- # NOTE: we do not use OID::Type
234
- # @oid_type.type_cast value
235
-
236
- return self.class.string_to_array(value, self) if array? && type == false
237
-
238
- case type ||= self.type
239
- when :hstore then self.class.string_to_hstore value
240
- when :json then self.class.string_to_json value
241
- when :jsonb then self.class.string_to_json value
242
- when :cidr, :inet then self.class.string_to_cidr value
243
- when :macaddr then value
244
- when :tsvector then value
245
- when :datetime, :timestamp then self.class.string_to_time value
246
- else
247
- if ( sql_type = self.sql_type.to_s ) == 'money'
248
- self.class.string_to_money(value)
249
- elsif sql_type[0, 5] == 'point'
250
- value.is_a?(String) ? self.class.string_to_point(value) : value
251
- elsif sql_type[0, 3] == 'bit' || sql_type[0, 6] == 'varbit'
252
- value.is_a?(String) ? self.class.string_to_bit(value) : value
253
- elsif sql_type[-5, 5] == 'range'
254
- return if value.nil? || value == 'empty'
255
- return value if value.is_a?(::Range)
256
-
257
- extracted = extract_bounds(value)
258
-
259
- case sql_type[0...-5] # range sub-type
260
- when 'date' # :date
261
- from = self.class.value_to_date(extracted[:from])
262
- from += 1.day if extracted[:exclude_start]
263
- to = self.class.value_to_date(extracted[:to])
264
- when 'num' # :decimal
265
- from = ::BigDecimal.new(extracted[:from].to_s)
266
- # FIXME: add exclude start for ::Range, same for timestamp ranges
267
- to = ::BigDecimal.new(extracted[:to].to_s)
268
- when 'ts', 'tstz' # :time
269
- from = self.class.string_to_time(extracted[:from])
270
- to = self.class.string_to_time(extracted[:to])
271
- when 'int4', 'int8' # :integer
272
- from = extracted[:from]
273
- unless (from.respond_to?(:infinite?) && from.infinite?)
274
- from = from.respond_to?(:to_i) ? from.to_i : ( value ? 1 : 0 )
275
- end
276
- from += 1 if extracted[:exclude_start]
277
- to = extracted[:to]
278
- unless (to.respond_to?(:infinite?) && to.infinite?)
279
- to = to.respond_to?(:to_i) ? to.to_i : ( value ? 1 : 0 )
280
- end
281
- else
282
- return value
283
- end
284
-
285
- ::Range.new(from, to, extracted[:exclude_end])
286
- else
287
- super(value)
288
- end
289
- end
290
- end if AR40
291
-
292
- private
293
-
294
- # Extracts the scale from PostgreSQL-specific data types.
295
- def extract_scale(sql_type)
296
- # Money type has a fixed scale of 2.
297
- sql_type =~ /^money/ ? 2 : super
298
- end
299
-
300
- # Extracts the precision from PostgreSQL-specific data types.
301
- def extract_precision(sql_type)
302
- if sql_type == 'money'
303
- self.class.money_precision
304
- elsif sql_type =~ /timestamp/i
305
- $1.to_i if sql_type =~ /\((\d+)\)/
306
- else
307
- super
308
- end
309
- end
310
-
311
- # Maps PostgreSQL-specific data types to logical Rails types.
312
- def simplified_type(field_type)
313
- case field_type
314
- # Numeric and monetary types
315
- when /^(?:real|double precision)$/ then :float
316
- # Monetary types
317
- when 'money' then :decimal
318
- # Character types
319
- when /^(?:character varying|bpchar)(?:\(\d+\))?$/ then :string
320
- # Binary data types
321
- when 'bytea' then :binary
322
- # Date/time types
323
- when /^timestamp with(?:out)? time zone$/ then :datetime
324
- when 'interval' then :string
325
- # Geometric types
326
- when /^(?:point|line|lseg|box|"?path"?|polygon|circle)$/ then :string
327
- # Network address types
328
- when /^(?:cidr|inet|macaddr)$/ then :string
329
- # Bit strings
330
- when /^bit(?: varying)?(?:\(\d+\))?$/ then :string
331
- # XML type
332
- when 'xml' then :xml
333
- # tsvector type
334
- when 'tsvector' then :tsvector
335
- # Arrays
336
- when /^\D+\[\]$/ then :string
337
- # Object identifier types
338
- when 'oid' then :integer
339
- # UUID type
340
- when 'uuid' then :string
341
- # Small and big integer types
342
- when /^(?:small|big)int$/ then :integer
343
- # AR-JDBC added :
344
- when 'bool' then :boolean
345
- when 'char' then :string
346
- when 'serial' then :integer
347
- # Pass through all types that are not specific to PostgreSQL.
348
- else
349
- super
350
- end
351
- end
352
-
353
- # @private
354
- def simplified_type(field_type)
355
- case field_type
356
- # Numeric and monetary types
357
- when /^(?:real|double precision)$/ then :float
358
- # Monetary types
359
- when 'money' then :decimal
360
- when 'hstore' then :hstore
361
- when 'ltree' then :ltree
362
- # Network address types
363
- when 'inet' then :inet
364
- when 'cidr' then :cidr
365
- when 'macaddr' then :macaddr
366
- # Character types
367
- when /^(?:character varying|bpchar)(?:\(\d+\))?$/ then :string
368
- # Binary data types
369
- when 'bytea' then :binary
370
- # Date/time types
371
- when /^timestamp with(?:out)? time zone$/ then :datetime
372
- when /^interval(?:|\(\d+\))$/ then :string
373
- # Geometric types
374
- when /^(?:point|line|lseg|box|"?path"?|polygon|circle)$/ then :string
375
- # Bit strings
376
- when /^bit(?: varying)?(?:\(\d+\))?$/ then :string
377
- # XML type
378
- when 'xml' then :xml
379
- # tsvector type
380
- when 'tsvector' then :tsvector
381
- # Arrays
382
- when /^\D+\[\]$/ then :string
383
- # Object identifier types
384
- when 'oid' then :integer
385
- # UUID type
386
- when 'uuid' then :uuid
387
- # JSON type
388
- when 'json' then :json
389
- when 'jsonb' then :jsonb
390
- # Small and big integer types
391
- when /^(?:small|big)int$/ then :integer
392
- when /(num|date|tstz|ts|int4|int8)range$/
393
- field_type.to_sym
394
- # AR-JDBC added :
395
- when 'bool' then :boolean
396
- when 'char' then :string
397
- when 'serial' then :integer
398
- # Pass through all types that are not specific to PostgreSQL.
399
- else
400
- super
401
- end
402
- end if AR40
403
-
404
- # OID Type::Range helpers :
405
-
406
- def extract_bounds(value)
407
- f, t = value[1..-2].split(',')
408
- {
409
- :from => (value[1] == ',' || f == '-infinity') ? infinity(:negative => true) : f,
410
- :to => (value[-2] == ',' || t == 'infinity') ? infinity : t,
411
- :exclude_start => (value[0] == '('), :exclude_end => (value[-1] == ')')
412
- }
413
- end if AR40
414
-
415
- def infinity(options = {})
416
- ::Float::INFINITY * (options[:negative] ? -1 : 1)
417
- end if AR40
418
-
419
- private
420
-
421
- # TODO marshaling worked in 1.3.7 ,,, got broken in 1.3.8 (due @adapter)
422
- # but the fix introduced in 1.3.10 causes backwards (1.3) incompatibility
423
- # ... for now should be fine - there's likely more refactoring to happen!
424
-
425
- def marshal_dump
426
- # NOTE: disabled oid_type ... due range warnings (maybe they're fine) :
427
- # unknown OID 3904: failed to recognize type of 'int4_range'. It will be treated as String.
428
- #oid_type if respond_to?(:oid_type)
429
- @adapter = nil
430
- instance_variables.map { |var| [ var, instance_variable_get(var) ] }
431
- end
432
-
433
- def marshal_load(data)
434
- data.each { |pair| instance_variable_set( pair[0], pair[1] ) }
435
- end
436
-
437
- # @note Based on *active_record/connection_adapters/postgresql/cast.rb* (4.0).
438
- module Cast
439
-
440
- def string_to_money(string)
441
- return string unless String === string
442
-
443
- # Because money output is formatted according to the locale, there
444
- # are two cases to consider (note the decimal separators) :
445
- # (1) $12,345,678.12
446
- # (2) $12.345.678,12
447
- # Negative values are represented as follows:
448
- # (3) -$2.55
449
- # (4) ($2.55)
450
- string = string.sub(/^\((.+)\)$/, '-\1') # (4)
451
- case string
452
- when /^-?\D+[\d,]+\.\d{2}$/ # (1)
453
- string.gsub!(/[^-\d.]/, '')
454
- when /^-?\D+[\d.]+,\d{2}$/ # (2)
455
- string.gsub!(/[^-\d,]/, '')
456
- string.sub!(/,/, '.')
457
- end
458
- value_to_decimal string
459
- end
460
-
461
- def point_to_string(point)
462
- "(#{point[0]},#{point[1]})"
463
- end
464
-
465
- def string_to_point(string)
466
- if string[0] == '(' && string[-1] == ')'
467
- string = string[1...-1]
468
- end
469
- string.split(',').map { |v| Float(v) }
470
- end
471
-
472
- def string_to_time(string)
473
- return string unless String === string
474
-
475
- case string
476
- when 'infinity' then 1.0 / 0.0
477
- when '-infinity' then -1.0 / 0.0
478
- when / BC$/
479
- super("-#{string.sub(/ BC$/, "")}")
480
- else
481
- super
482
- end
483
- end
484
-
485
- def string_to_bit(value)
486
- case value
487
- when /^[01]*$/ then value # Bit-string notation
488
- when /^[0-9A-F]*$/i then value.hex.to_s(2) # Hexadecimal notation
489
- end
490
- end
491
-
492
- def string_to_bit(value)
493
- case value
494
- when /^0x/i
495
- value[2..-1].hex.to_s(2) # Hexadecimal notation
496
- else
497
- value # Bit-string notation
498
- end
499
- end if AR40
500
-
501
- def hstore_to_string(object, array_member = false)
502
- if Hash === object
503
- string = object.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(',')
504
- string = escape_hstore(string) if array_member
505
- string
506
- else
507
- object
508
- end
509
- end
510
-
511
- def string_to_hstore(string)
512
- if string.nil?
513
- nil
514
- elsif String === string
515
- Hash[string.scan(HstorePair).map { |k, v|
516
- v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
517
- k = k.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
518
- [k, v]
519
- }]
520
- else
521
- string
522
- end
523
- end
524
-
525
- def json_to_string(object)
526
- if Hash === object || Array === object
527
- ActiveSupport::JSON.encode(object)
528
- else
529
- object
530
- end
531
- end
532
-
533
- def array_to_string(value, column, adapter)
534
- casted_values = value.map do |val|
535
- if String === val
536
- if val == "NULL"
537
- "\"#{val}\""
538
- else
539
- quote_and_escape(adapter.type_cast(val, column, true))
540
- end
541
- else
542
- adapter.type_cast(val, column, true)
543
- end
544
- end
545
- "{#{casted_values.join(',')}}"
546
- end
547
-
548
- def range_to_string(object)
549
- from = object.begin.respond_to?(:infinite?) && object.begin.infinite? ? '' : object.begin
550
- to = object.end.respond_to?(:infinite?) && object.end.infinite? ? '' : object.end
551
- "[#{from},#{to}#{object.exclude_end? ? ')' : ']'}"
552
- end
553
-
554
- def string_to_json(string)
555
- if String === string
556
- ActiveSupport::JSON.decode(string)
557
- else
558
- string
559
- end
560
- end
561
-
562
- def string_to_cidr(string)
563
- if string.nil?
564
- nil
565
- elsif String === string
566
- begin
567
- IPAddr.new(string)
568
- rescue ArgumentError
569
- nil
570
- end
571
- else
572
- string
573
- end
574
- end
575
-
576
- def cidr_to_string(object)
577
- if IPAddr === object
578
- "#{object.to_s}/#{object.instance_variable_get(:@mask_addr).to_s(2).count('1')}"
579
- else
580
- object
581
- end
582
- end
583
-
584
- # @note Only used for default values - we get a "parsed" array from JDBC.
585
- def string_to_array(string, column_or_oid)
586
- return string unless String === string
587
- parse_pg_array(string).map { |val| type_cast_array(column_or_oid, val) }
588
- end
589
-
590
- private
591
-
592
- # @private
593
- HstorePair = begin
594
- quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/
595
- unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/
596
- /(#{quoted_string}|#{unquoted_string})\s*=>\s*(#{quoted_string}|#{unquoted_string})/
597
- end
598
-
599
- def escape_hstore(value)
600
- if value.nil?
601
- 'NULL'
602
- else
603
- if value == ""
604
- '""'
605
- else
606
- '"%s"' % value.to_s.gsub(/(["\\])/, '\\\\\1')
607
- end
608
- end
609
- end
610
-
611
- ARRAY_ESCAPE = "\\" * 2 * 2 # escape the backslash twice for PG arrays
612
-
613
- def quote_and_escape(value)
614
- case value
615
- when "NULL", Numeric
616
- value
617
- else
618
- value = value.gsub(/\\/, ARRAY_ESCAPE)
619
- value.gsub!(/"/,"\\\"")
620
- "\"#{value}\""
621
- end
622
- end
623
-
624
- def type_cast_array(oid, value)
625
- if ::Array === value
626
- value.map { |item| type_cast_array(oid, item) }
627
- else
628
- if oid.is_a?(Column)
629
- oid.type_cast value, oid.type # column.type
630
- else
631
- oid.type_cast value
632
- end
633
- end
634
- end
635
-
636
- end
637
-
638
- end unless AR42
639
50
  end
640
51
  end