activerecord-jdbc-adapter 1.3.6 → 1.3.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +9 -5
  3. data/Gemfile +11 -3
  4. data/History.md +18 -0
  5. data/Rakefile +8 -0
  6. data/lib/arjdbc/db2/adapter.rb +23 -2
  7. data/lib/arjdbc/derby/adapter.rb +33 -3
  8. data/lib/arjdbc/firebird/adapter.rb +10 -2
  9. data/lib/arjdbc/jdbc.rb +35 -5
  10. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  11. data/lib/arjdbc/jdbc/connection.rb +10 -6
  12. data/lib/arjdbc/jdbc/connection_methods.rb +2 -2
  13. data/lib/arjdbc/jdbc/driver.rb +2 -2
  14. data/lib/arjdbc/jdbc/jdbc.rake +4 -3
  15. data/lib/arjdbc/jdbc/railtie.rb +1 -1
  16. data/lib/arjdbc/jdbc/rake_tasks.rb +3 -3
  17. data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -3
  18. data/lib/arjdbc/mssql/adapter.rb +25 -5
  19. data/lib/arjdbc/mssql/limit_helpers.rb +5 -2
  20. data/lib/arjdbc/mysql/adapter.rb +10 -3
  21. data/lib/arjdbc/mysql/connection_methods.rb +20 -0
  22. data/lib/arjdbc/oracle/adapter.rb +18 -1
  23. data/lib/arjdbc/tasks/databases.rake +1 -1
  24. data/lib/arjdbc/tasks/derby_database_tasks.rb +11 -11
  25. data/lib/arjdbc/tasks/h2_database_tasks.rb +9 -9
  26. data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +10 -10
  27. data/lib/arjdbc/tasks/jdbc_database_tasks.rb +69 -22
  28. data/lib/arjdbc/tasks/mssql_database_tasks.rb +14 -4
  29. data/lib/arjdbc/tasks/oracle_database_tasks.rb +7 -4
  30. data/lib/arjdbc/version.rb +1 -1
  31. data/lib/jdbc_adapter.rb +1 -1
  32. data/lib/jdbc_adapter/rake_tasks.rb +4 -3
  33. data/lib/jdbc_adapter/version.rb +4 -2
  34. data/rakelib/02-test.rake +10 -0
  35. data/rakelib/db.rake +5 -3
  36. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +35 -8
  37. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ebdc2f21df1a1fbe848c242a5a9c6e351a20056e
4
- data.tar.gz: 67e764365675757678fc29d3a2422faaa0b2920a
3
+ metadata.gz: 23a7dd04ff60809e25a4e3353934e7333eb95f85
4
+ data.tar.gz: 5e5f2405ab90b8162afb541ca07149b1c1905359
5
5
  SHA512:
6
- metadata.gz: 006bb63ddde830d1b02a26c5780349d1ad7e6204dbcd9195583fcf65b11f102a22e4e9dab43a6e242c344293503dd56140b6fa55f7b48e967289785b74bec88a
7
- data.tar.gz: e9e05577e5fb7965d0a5b38b64f1b7985d9412a31f5d0c7d414a4e8c1b865293ca8e77c120ee7402b7088c70c4a0b9c3f93a07c77868cde11a27ed9406b61e52
6
+ metadata.gz: 2f7e7f103b585be60afc053e89c60f4826409740b8a223380292ab57dd4d141a22e7ac2974b2c4c9b06e6ddb2f5971e32c5a01a20d73fc011f227adc5086322a
7
+ data.tar.gz: bd7e172e76bb7e2f492f4735124361060a5ddde25f036a67d80d9422e6b69d793ce270e19c33ddf74f659b820aa85eb4ea62c346ad9ddcbb104c4ac45cd84a34
data/Appraisals CHANGED
@@ -12,16 +12,20 @@ appraise "rails31" do
12
12
  end
13
13
 
14
14
  appraise "rails32" do
15
- gem "activerecord", "~> 3.2.16", :require => false
15
+ gem "activerecord", "~> 3.2.17", :require => false
16
16
  end
17
17
 
18
18
  appraise "rails40" do
19
19
  # NOTE: make sure you're using --1.9 with AR-4.0
20
- gem "activerecord", "~> 4.0.2", :require => false
20
+ gem "activerecord", "~> 4.0.4", :require => false
21
21
  end
22
22
 
23
23
  appraise "rails41" do
24
24
  # NOTE: make sure you're using --1.9 with AR-4.1
25
- gem "activerecord", :github => 'rails/rails', :branch => 'master', :require => false
26
- gem 'rails', :github => 'rails/rails', :branch => 'master'
27
- end
25
+ if branch = ENV['rails_branch']
26
+ gem "activerecord", :github => 'rails/rails', :branch => branch, :require => false
27
+ gem 'rails', :github => 'rails/rails', :branch => branch
28
+ else
29
+ gem "activerecord", '4.1.0.rc1', :require => false
30
+ end
31
+ end
data/Gemfile CHANGED
@@ -1,6 +1,10 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem 'activerecord', :require => nil
3
+ if version = ENV['AR_VERSION']
4
+ gem 'activerecord', version, :require => nil
5
+ else
6
+ gem 'activerecord', :require => nil
7
+ end
4
8
  gem 'thread_safe', :require => nil # "optional" - we can roll without it
5
9
  if defined?(JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
6
10
  gem 'jruby-openssl', :platform => :jruby
@@ -15,8 +19,12 @@ group :development do
15
19
  end
16
20
  end
17
21
 
18
- gem 'rake', :require => nil
19
- gem 'appraisal', :require => nil
22
+ if RUBY_VERSION < '1.9'
23
+ gem 'rake', '< 10.2.0', :require => nil
24
+ else
25
+ gem 'rake', :require => nil
26
+ end
27
+ gem 'appraisal', '~> 0.5.2', :require => nil
20
28
 
21
29
  # appraisal ignores group block declarations :
22
30
 
data/History.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## 1.3.7 (04/14/14)
2
+
3
+ - [postgres] set prepared values with array columns on AR < 4.0 correctly
4
+ - [postgres] handle null values in array columns with AR < 4.0 (fixes #548)
5
+ - [mysql] support for config[:reconnect] (might need some fine tuning to match mysql2)
6
+ - fix ordering on an aggregate in MSSQL (#532) (should fix #437 for good)
7
+ - introduce a deprecation (warn) method for AR-JDBC and start using it
8
+ - [mysql] do not set defaults for text/blob columns on rename/change (#543)
9
+ - try resolving config 'database' (if missing) from JDBC url: in rake tasks
10
+ - [mysql] needs to `reconnect!` when recreating database (fixes #539)
11
+ - remove_column compatibility with Rails 4.x for Oracle, Derby and MSSQL (#541)
12
+ - Fix connection without user and password (#542)
13
+ - fix db2 remove_column for ActiveRecord 4 (#537)
14
+ - FireBird's DB meta-identifier is 31 chars maximum, thanks @mariuz (#538)
15
+ - [derby] add emulate booleans option for derby adapter
16
+
17
+ Code Contributors (in no particular order): mark100net, Pierrick Rouxel, @iaddict
18
+
1
19
  ## 1.3.6 (02/04/14)
2
20
 
3
21
  - fix rails 4-0-stable compatibility (see #530)
data/Rakefile CHANGED
@@ -42,28 +42,36 @@ end
42
42
  # DRIVERS
43
43
 
44
44
  desc "Build drivers"
45
+ task "build:drivers" => DRIVERS.map { |name| "#{name}:build" }
45
46
  task "drivers:build" => DRIVERS.map { |name| "#{name}:build" }
46
47
 
47
48
  desc "Install drivers"
49
+ task "install:drivers" => DRIVERS.map { |name| "#{name}:install" }
48
50
  task "drivers:install" => DRIVERS.map { |name| "#{name}:install" }
49
51
 
50
52
  desc "Release drivers"
53
+ task "release:drivers" => DRIVERS.map { |name| "#{name}:release" }
51
54
  task "drivers:release" => DRIVERS.map { |name| "#{name}:release" }
52
55
 
53
56
  # ADAPTERS
54
57
 
55
58
  desc "Build adapters"
59
+ task "build:adapters" => [ 'build' ] + ADAPTERS.map { |name| "#{name}:build" }
56
60
  task "adapters:build" => [ 'build' ] + ADAPTERS.map { |name| "#{name}:build" }
57
61
 
58
62
  desc "Install adapters"
63
+ task "install:adapters" => [ 'install' ] + ADAPTERS.map { |name| "#{name}:install" }
59
64
  task "adapters:install" => [ 'install' ] + ADAPTERS.map { |name| "#{name}:install" }
60
65
 
61
66
  desc "Release adapters"
67
+ task "release:adapters" => [ 'release' ] + ADAPTERS.map { |name| "#{name}:release" }
62
68
  task "adapters:release" => [ 'release' ] + ADAPTERS.map { |name| "#{name}:release" }
63
69
 
64
70
  # ALL
65
71
 
72
+ task "build:all" => [ 'build' ] + TARGETS.map { |name| "#{name}:build" }
66
73
  task "all:build" => [ 'build' ] + TARGETS.map { |name| "#{name}:build" }
74
+ task "install:all" => [ 'install' ] + TARGETS.map { |name| "#{name}:install" }
67
75
  task "all:install" => [ 'install' ] + TARGETS.map { |name| "#{name}:install" }
68
76
 
69
77
  task :filelist do
@@ -350,6 +350,13 @@ module ArJdbc
350
350
  super(type, limit, precision, scale)
351
351
  end
352
352
 
353
+ def add_column(table_name, column_name, type, options = {})
354
+ # The keyword COLUMN allows to use reserved names for columns (ex: date)
355
+ add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
356
+ add_column_options!(add_column_sql, options)
357
+ execute(add_column_sql)
358
+ end
359
+
353
360
  def add_column_options!(sql, options)
354
361
  # handle case of defaults for CLOB columns,
355
362
  # which might get incorrect if we write LOBs in the after_save callback
@@ -498,17 +505,26 @@ module ArJdbc
498
505
  end
499
506
  end
500
507
 
508
+ if ActiveRecord::VERSION::MAJOR >= 4
509
+
510
+ def remove_column(table_name, column_name, type = nil, options = {})
511
+ db2_remove_column(table_name, column_name)
512
+ end
513
+
514
+ else
515
+
501
516
  def remove_column(table_name, *column_names)
502
517
  # http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.admin.dbobj.doc/doc/t0020132.html
503
518
  outcome = nil
504
519
  column_names = column_names.flatten
505
520
  for column_name in column_names
506
- sql = "ALTER TABLE #{table_name} DROP COLUMN #{column_name}"
507
- outcome = execute_table_change(sql, table_name, 'Remove Column')
521
+ outcome = db2_remove_column(table_name, column_name)
508
522
  end
509
523
  column_names.size == 1 ? outcome : nil
510
524
  end
511
525
 
526
+ end
527
+
512
528
  def rename_table(name, new_name)
513
529
  # http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0000980.html
514
530
  execute_table_change("RENAME TABLE #{name} TO #{new_name}", new_name, 'Rename Table')
@@ -646,6 +662,11 @@ module ArJdbc
646
662
  end
647
663
  end
648
664
 
665
+ def db2_remove_column(table_name, column_name)
666
+ sql = "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
667
+ execute_table_change(sql, table_name, 'Remove Column')
668
+ end
669
+
649
670
  end
650
671
  end
651
672
 
@@ -25,6 +25,19 @@ module ArJdbc
25
25
  [ /derby/i, lambda { |config, column| column.extend(Column) } ]
26
26
  end
27
27
 
28
+ # @private
29
+ @@emulate_booleans = true
30
+
31
+ # Boolean emulation can be disabled using :
32
+ #
33
+ # ArJdbc::Derby.emulate_booleans = false
34
+ #
35
+ def self.emulate_booleans?; @@emulate_booleans; end
36
+ # @deprecated Use {#emulate_booleans?} instead.
37
+ def self.emulate_booleans; @@emulate_booleans; end
38
+ # @see #emulate_booleans?
39
+ def self.emulate_booleans=(emulate); @@emulate_booleans = emulate; end
40
+
28
41
  # @note Part of this module is implemented in "native" Java.
29
42
  # @see ActiveRecord::ConnectionAdapters::JdbcColumn
30
43
  module Column
@@ -53,7 +66,7 @@ module ArJdbc
53
66
 
54
67
  def simplified_type(field_type)
55
68
  case field_type
56
- when /^smallint/i then :boolean
69
+ when /^smallint/i then Derby.emulate_booleans? ? :boolean : :integer
57
70
  when /^bigint|int/i then :integer
58
71
  when /^real|double/i then :float
59
72
  when /^dec/i then # DEC is a DECIMAL alias
@@ -282,12 +295,29 @@ module ArJdbc
282
295
  super
283
296
  end unless const_defined? :SchemaCreation
284
297
 
298
+ if ActiveRecord::VERSION::MAJOR >= 4
299
+
300
+ # @override
301
+ def remove_column(table_name, column_name, type = nil, options = {})
302
+ do_remove_column(table_name, column_name)
303
+ end
304
+
305
+ else
306
+
285
307
  # @override
286
308
  def remove_column(table_name, *column_names)
287
309
  for column_name in column_names.flatten
288
- execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)} RESTRICT"
310
+ do_remove_column(table_name, column_name)
289
311
  end
290
- end unless const_defined? :SchemaCreation
312
+ end
313
+ alias remove_columns remove_column
314
+
315
+ end
316
+
317
+ def do_remove_column(table_name, column_name)
318
+ execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)} RESTRICT"
319
+ end
320
+ private :do_remove_column
291
321
 
292
322
  # @override
293
323
  def change_column(table_name, column_name, type, options = {})
@@ -193,8 +193,16 @@ module ArJdbc
193
193
  columns(table_name).count { |column| column.primary } == 1
194
194
  end
195
195
 
196
- def default_sequence_name(table_name, column=nil)
197
- "#{table_name}_seq"
196
+ IDENTIFIER_LENGTH = 31 # usual DB meta-identifier: 31 chars maximum
197
+
198
+ def table_alias_length; IDENTIFIER_LENGTH; end
199
+ def table_name_length; IDENTIFIER_LENGTH; end
200
+ def index_name_length; IDENTIFIER_LENGTH; end
201
+ def column_name_length; IDENTIFIER_LENGTH; end
202
+
203
+ def default_sequence_name(table_name, column = nil)
204
+ # TODO: remove schema prefix if present (before truncating)
205
+ "#{table_name.to_s[0, IDENTIFIER_LENGTH - 4]}_seq"
198
206
  end
199
207
 
200
208
  # Set the sequence to the max value of the table's column.
data/lib/arjdbc/jdbc.rb CHANGED
@@ -1,6 +1,36 @@
1
- require 'arjdbc/jdbc/adapter'
2
- if Java::JavaLang::Boolean.getBoolean('arjdbc.extensions.discover')
3
- module ArJdbc; self.discover_extensions; end
4
- else
5
- require 'arjdbc/discover'
1
+ require 'set'
2
+ require 'active_support/deprecation'
3
+
4
+ module ArJdbc
5
+
6
+ class << self
7
+
8
+ def warn(message, once = nil)
9
+ super(message) || true if warn?(message, once)
10
+ end
11
+
12
+ def deprecate(message, once = nil)
13
+ ActiveSupport::Deprecation.warn(message, caller) || true if warn?(message, once)
14
+ end
15
+
16
+ private
17
+
18
+ @@warns = Set.new
19
+
20
+ def warn?(message, once)
21
+ return nil unless message
22
+ return false if @@warns.include?(message)
23
+ @@warns << message.dup if once
24
+ true
25
+ end
26
+
27
+ end
28
+
29
+ require 'arjdbc/jdbc/adapter'
30
+
31
+ if Java::JavaLang::Boolean.getBoolean('arjdbc.extensions.discover')
32
+ self.discover_extensions
33
+ else
34
+ require 'arjdbc/discover'
35
+ end
6
36
  end
Binary file
@@ -34,7 +34,9 @@ module ActiveRecord
34
34
  end
35
35
 
36
36
  # @deprecated no longer used - only kept for compatibility
37
- def set_native_database_types; end
37
+ def set_native_database_types
38
+ ArJdbc.deprecate "set_native_database_types is no longer used and does nothing override native_database_types instead"
39
+ end
38
40
 
39
41
  def self.jndi_config?(config)
40
42
  config[:jndi] || config[:data_source]
@@ -74,12 +76,13 @@ module ActiveRecord
74
76
 
75
77
  def setup_jdbc_factory
76
78
  if ! config[:url] || ( ! config[:driver] && ! config[:driver_instance] )
77
- raise ::ActiveRecord::ConnectionNotEstablished, "jdbc adapter requires :driver class and :url"
79
+ msg = config[:url] ? ":url = #{config[:url]}" : ":driver = #{config[:driver]}"
80
+ raise ::ActiveRecord::ConnectionNotEstablished, "jdbc adapter requires :driver and :url (got #{msg})"
78
81
  end
79
82
 
80
83
  url = jdbc_url
81
- username = config[:username].to_s
82
- password = config[:password].to_s
84
+ username = config[:username]
85
+ password = config[:password]
83
86
  jdbc_driver = ( config[:driver_instance] ||=
84
87
  JdbcDriver.new(config[:driver].to_s, config[:properties]) )
85
88
 
@@ -93,8 +96,9 @@ module ActiveRecord
93
96
 
94
97
  def jdbc_url
95
98
  url = config[:url].to_s
96
- if Hash === config[:options]
97
- options = config[:options].map { |key, val| "#{key}=#{val}" }.join('&')
99
+ if options = config[:options]
100
+ ArJdbc.deprecate "use config[:properties] to specify connection URL properties instead of config[:options]"
101
+ options = options.map { |key, val| "#{key}=#{val}" }.join('&') if Hash === options
98
102
  url = url['?'] ? "#{url}&#{options}" : "#{url}?#{options}" unless options.empty?
99
103
  config[:url] = url; config[:options] = nil
100
104
  end
@@ -1,5 +1,5 @@
1
1
  module ArJdbc
2
- if defined? ActiveRecord::ConnectionHandling # 4.0
2
+ if ActiveRecord.const_defined? :ConnectionHandling # 4.0
3
3
  ConnectionMethods = ActiveRecord::ConnectionHandling
4
4
  else # 3.x
5
5
  ConnectionMethods = (class << ActiveRecord::Base; self; end)
@@ -27,4 +27,4 @@ module ArJdbc
27
27
  end
28
28
 
29
29
  end
30
- end
30
+ end
@@ -34,8 +34,8 @@ module ActiveRecord
34
34
  def connection(url, user, pass)
35
35
  # bypass DriverManager to get around problem with dynamically loaded jdbc drivers
36
36
  properties = self.properties.clone
37
- properties.setProperty("user", user) if user
38
- properties.setProperty("password", pass) if pass
37
+ properties.setProperty("user", user.to_s) if user
38
+ properties.setProperty("password", pass.to_s) if pass
39
39
  @driver.connect(url, properties)
40
40
  end
41
41
  end
@@ -1,3 +1,4 @@
1
- # @deprecated
2
- warn "DEPRECATED: load 'arjdbc/tasks.rb' (or 'arjdbc/tasks/database.rake') instead of 'arjdbc/jdbc/jdbc.rake'"
3
- load 'arjdbc/tasks.rb'
1
+ load 'arjdbc/tasks.rb'
2
+
3
+ require 'arjdbc'
4
+ ArJdbc.deprecate "load 'arjdbc/tasks.rb' (or 'arjdbc/tasks/database.rake') instead of 'arjdbc/jdbc/jdbc.rake'"
@@ -1,2 +1,2 @@
1
- warn "DEPRECATED: require 'arjdbc/railtie' instead of 'arjdbc/jdbc/railtie' "
2
1
  require 'arjdbc/railtie'
2
+ ArJdbc.deprecate "require 'arjdbc/railtie' instead of 'arjdbc/jdbc/railtie'"
@@ -1,3 +1,3 @@
1
- # @deprecated
2
- warn "DEPRECATED: load 'arjdbc/tasks.rb' instead of 'arjdbc/jdbc/rake_tasks.rb'"
3
- load 'arjdbc/tasks.rb'
1
+ load 'arjdbc/tasks.rb'
2
+
3
+ ArJdbc.deprecate "load 'arjdbc/tasks.rb' instead of 'arjdbc/jdbc/rake_tasks.rb'"
@@ -1,3 +1,3 @@
1
- # @deprecated
2
- warn "DEPRECATED: require 'arjdbc/util/serialized_attributes' instead of 'arjdbc/jdbc/serialized_attributes_helper'"
3
- require 'arjdbc/util/serialized_attributes'
1
+ require 'arjdbc/util/serialized_attributes'
2
+
3
+ ArJdbc.deprecate "require 'arjdbc/util/serialized_attributes' instead of 'arjdbc/jdbc/serialized_attributes_helper'"
@@ -423,18 +423,38 @@ module ArJdbc
423
423
  end
424
424
  end
425
425
 
426
- def remove_column(table_name, *column_names)
426
+ def remove_columns(table_name, *column_names)
427
427
  raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.empty?
428
428
  # remove_columns(:posts, :foo, :bar) old syntax : remove_columns(:posts, [:foo, :bar])
429
429
  clear_cached_table(table_name)
430
+
431
+ return do_remove_column(table_name, column_names.first) if column_names.size == 1
430
432
  column_names.flatten.each do |column_name|
431
- remove_check_constraints(table_name, column_name)
432
- remove_default_constraint(table_name, column_name)
433
- remove_indexes(table_name, column_name) unless sqlserver_2000?
434
- execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
433
+ do_remove_column(table_name, column_name)
435
434
  end
436
435
  end
437
436
 
437
+ def do_remove_column(table_name, column_name)
438
+ remove_check_constraints(table_name, column_name)
439
+ remove_default_constraint(table_name, column_name)
440
+ remove_indexes(table_name, column_name) unless sqlserver_2000?
441
+ execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
442
+ end
443
+ private :do_remove_column
444
+
445
+ if ActiveRecord::VERSION::MAJOR >= 4
446
+
447
+ # @override
448
+ def remove_column(table_name, column_name, type = nil, options = {})
449
+ remove_columns(table_name, column_name)
450
+ end
451
+
452
+ else
453
+
454
+ def remove_column(table_name, *column_names); remove_columns(table_name, *column_names) end
455
+
456
+ end
457
+
438
458
  def remove_default_constraint(table_name, column_name)
439
459
  clear_cached_table(table_name)
440
460
  if sqlserver_2000?
@@ -4,6 +4,7 @@ module ArJdbc
4
4
 
5
5
  # @private
6
6
  FIND_SELECT = /\b(SELECT(\s+DISTINCT)?)\b(.*)/mi
7
+ FIND_AGGREGATE_FUNCTIONS = /AVG|COUNT|COUNT_BIG|MAX|MIN|SUM|STDDEV|STDEVP|VAR|VARP/
7
8
 
8
9
  module SqlServerReplaceLimitOffset
9
10
 
@@ -28,8 +29,10 @@ module ArJdbc
28
29
  # ActiveRecord::StatementInvalid: ActiveRecord::JDBCError: Column 'users.id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
29
30
  # SELECT t.* FROM ( SELECT ROW_NUMBER() OVER(ORDER BY users.id) AS _row_num, [users].[lft], COUNT([users].[lft]) FROM [users] GROUP BY [users].[lft] HAVING COUNT([users].[lft]) > 1 ) AS t WHERE t._row_num BETWEEN 1 AND 1
30
31
  if rest_of_query.downcase.include?('group by')
31
- if order.count(',') == 0
32
- order.gsub!(/ORDER BY (.*)/, 'ORDER BY MIN(\1)')
32
+ if order.match(/^ORDER +BY +(#{FIND_AGGREGATE_FUNCTIONS})\(/i)
33
+ # do nothing
34
+ elsif order.count(',') == 0
35
+ order.gsub!(/ORDER +BY +([^\s]+)(\s+ASC|\s+DESC)?/i, 'ORDER BY MIN(\1)\2')
33
36
  else
34
37
  raise('Only one order condition allowed.')
35
38
  end
@@ -341,6 +341,7 @@ module ArJdbc
341
341
  def recreate_database(name, options = {})
342
342
  drop_database(name)
343
343
  create_database(name, options)
344
+ reconnect!
344
345
  end
345
346
 
346
347
  # @override
@@ -406,7 +407,8 @@ module ArJdbc
406
407
  column = column_for(table_name, column_name)
407
408
 
408
409
  unless options_include_default?(options)
409
- options[:default] = column.default
410
+ # NOTE: no defaults for BLOB/TEXT columns with MySQL
411
+ options[:default] = column.default if type != :text && type != :binary
410
412
  end
411
413
 
412
414
  unless options.has_key?(:null)
@@ -422,17 +424,22 @@ module ArJdbc
422
424
  # @override
423
425
  def rename_column(table_name, column_name, new_column_name)
424
426
  options = {}
427
+
425
428
  if column = columns(table_name).find { |c| c.name == column_name.to_s }
426
- options[:default] = column.default; options[:null] = column.null
429
+ type = column.type
430
+ options[:default] = column.default if type != :text && type != :binary
431
+ options[:null] = column.null
427
432
  else
428
433
  raise ActiveRecord::ActiveRecordError, "No such column: #{table_name}.#{column_name}"
429
434
  end
435
+
430
436
  current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'")["Type"]
437
+
431
438
  rename_column_sql = "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{current_type}"
432
439
  add_column_options!(rename_column_sql, options)
433
440
  execute(rename_column_sql)
434
441
  rename_column_indexes(table_name, column_name, new_column_name) if respond_to?(:rename_column_indexes) # AR-4.0 SchemaStatements
435
- end # unless const_defined? :SchemaCreation
442
+ end
436
443
 
437
444
  def add_column_position!(sql, options)
438
445
  if options[:first]
@@ -31,6 +31,26 @@ ArJdbc::ConnectionMethods.module_eval do
31
31
  properties['useUnicode'] = 'true' unless properties.key?('useUnicode') # otherwise platform default
32
32
  encoding = config.key?(:encoding) ? config[:encoding] : 'utf8'
33
33
  properties['characterEncoding'] = encoding if encoding
34
+ if ! ( reconnect = config[:reconnect] ).nil?
35
+ properties['autoReconnect'] ||= reconnect.to_s
36
+ # properties['maxReconnects'] ||= '3'
37
+ # with reconnect fail-over sets connection read-only (by default)
38
+ # properties['failOverReadOnly'] ||= 'false'
39
+ end
40
+ if config[:sslkey] || sslcert = config[:sslcert] # || config[:use_ssl]
41
+ properties['useSSL'] ||= true
42
+ properties['requireSSL'] ||= true
43
+ properties['clientCertificateKeyStoreUrl'] ||= begin
44
+ java.io.File.new(sslcert).to_url.to_s
45
+ end if sslcert
46
+ if sslca = config[:sslca]
47
+ properties['trustCertificateKeyStoreUrl'] ||= begin
48
+ java.io.File.new(sslca).to_url.to_s
49
+ end
50
+ else
51
+ properties['verifyServerCertificate'] ||= false
52
+ end
53
+ end
34
54
 
35
55
  jdbc_connection(config)
36
56
  end
@@ -278,12 +278,29 @@ module ArJdbc
278
278
  "RENAME COLUMN #{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}"
279
279
  end
280
280
 
281
+ if ActiveRecord::VERSION::MAJOR >= 4
282
+
283
+ # @override
284
+ def remove_column(table_name, column_name, type = nil, options = {})
285
+ do_remove_column(table_name, column_name)
286
+ end
287
+
288
+ else
289
+
281
290
  # @override
282
291
  def remove_column(table_name, *column_names)
283
292
  for column_name in column_names.flatten
284
- execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
293
+ do_remove_column(table_name, column_name)
285
294
  end
286
295
  end
296
+ alias remove_columns remove_column
297
+
298
+ end
299
+
300
+ def do_remove_column(table_name, column_name)
301
+ execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
302
+ end
303
+ private :do_remove_column
287
304
 
288
305
  # SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
289
306
  #
@@ -42,7 +42,7 @@ namespace :db do
42
42
  end
43
43
 
44
44
  if defined? adapt_jdbc_config
45
- puts "ArJdbc: double loading #{__FILE__} please delete lib/tasks/jdbc.rake if present!"
45
+ ArJdbc.warn "double loading #{__FILE__} please delete lib/tasks/jdbc.rake if present!"
46
46
  end
47
47
 
48
48
  def adapt_jdbc_config(config)
@@ -8,28 +8,28 @@ module ArJdbc
8
8
  establish_connection(config)
9
9
  ActiveRecord::Base.connection
10
10
  end
11
-
11
+
12
12
  def drop
13
- db_dir = expand_path(config['database'])
13
+ db_dir = expand_path resolve_database(config, true)
14
14
  if File.exist?(db_dir)
15
15
  FileUtils.rm_r(db_dir)
16
16
  FileUtils.rmdir(db_dir) rescue nil
17
17
  end
18
18
  end
19
-
19
+
20
20
  SIZEABLE = %w( VARCHAR CLOB BLOB )
21
21
 
22
22
  def structure_dump(filename)
23
23
  establish_connection(config)
24
24
  dump = File.open(filename, "w:utf-8")
25
-
25
+
26
26
  meta_data = connection.jdbc_connection.meta_data
27
27
  tables_rs = meta_data.getTables(nil, nil, nil, ["TABLE"].to_java(:String))
28
-
28
+
29
29
  while tables_rs.next
30
30
  table_name = tables_rs.getString('TABLE_NAME') # getString(3)
31
31
  dump << "CREATE TABLE #{connection.quote_table_name(table_name)} (\n"
32
-
32
+
33
33
  columns_rs = meta_data.getColumns(nil, nil, table_name, nil)
34
34
  first_col = true
35
35
  while columns_rs.next
@@ -43,7 +43,7 @@ module ArJdbc
43
43
  type = columns_rs.getString(6)
44
44
  column_size = columns_rs.getString(7)
45
45
  nulling = ( columns_rs.getString(18) == 'NO' ? " NOT NULL" : nil )
46
-
46
+
47
47
  create_column = connection.quote_column_name(column_name)
48
48
  create_column << " #{type}"
49
49
  create_column << ( SIZEABLE.include?(type) ? "(#{column_size})" : "" )
@@ -57,15 +57,15 @@ module ArJdbc
57
57
  end
58
58
  dump << "\n);\n\n"
59
59
  end
60
-
60
+
61
61
  dump.close
62
62
  end
63
-
63
+
64
64
  def structure_load(filename)
65
65
  establish_connection(config)
66
66
  IO.read(filename).split(/;\n*/m).each { |ddl| connection.execute(ddl) }
67
67
  end
68
-
68
+
69
69
  private
70
70
 
71
71
  AUTO_INCREMENT_SQL = '' <<
@@ -89,7 +89,7 @@ module ArJdbc
89
89
  end
90
90
  ''
91
91
  end
92
-
92
+
93
93
  end
94
94
  end
95
95
  end
@@ -3,27 +3,27 @@ require 'arjdbc/tasks/hsqldb_database_tasks'
3
3
  module ArJdbc
4
4
  module Tasks
5
5
  class H2DatabaseTasks < HSQLDBDatabaseTasks
6
-
6
+
7
7
  protected
8
-
8
+
9
9
  # @override
10
10
  def do_drop_database(config)
11
- # ActiveRecord::JDBCError: org.h2.jdbc.JdbcSQLException:
12
- # Database is already closed (to disable automatic closing at VM
13
- # shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-170]:
11
+ # ActiveRecord::JDBCError: org.h2.jdbc.JdbcSQLException:
12
+ # Database is already closed (to disable automatic closing at VM
13
+ # shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-170]:
14
14
  # SHUTDOWN COMPACT
15
- #
15
+ #
16
16
  # connection.shutdown
17
- connection.drop_database config['database']
17
+ connection.drop_database resolve_database(config)
18
18
  end
19
-
19
+
20
20
  # @override
21
21
  def delete_database_files(config)
22
22
  return unless db_base = database_base_name(config)
23
23
  db_files = [ "#{db_base}.h2.db", "#{db_base}.lock.db", "#{db_base}.trace.db" ]
24
24
  db_files.each { |file| File.delete(file) if File.exist?(file) }
25
25
  end
26
-
26
+
27
27
  end
28
28
  end
29
29
  end
@@ -8,7 +8,7 @@ module ArJdbc
8
8
  establish_connection(config)
9
9
  ActiveRecord::Base.connection
10
10
  end
11
-
11
+
12
12
  def drop
13
13
  error = nil
14
14
  begin
@@ -27,14 +27,14 @@ module ArJdbc
27
27
  end
28
28
  end
29
29
  alias :purge :drop
30
-
30
+
31
31
  protected
32
-
32
+
33
33
  def do_drop_database(config)
34
- connection.drop_database config['database']
34
+ connection.drop_database resolve_database(config)
35
35
  connection.shutdown
36
36
  end
37
-
37
+
38
38
  def delete_database_files(config)
39
39
  return unless db_base = database_base_name(config)
40
40
  Dir.glob("#{db_base}.*").each do |file|
@@ -55,16 +55,16 @@ module ArJdbc
55
55
  FileUtils.rmdir(db_base)
56
56
  end
57
57
  end
58
-
58
+
59
59
  private
60
-
60
+
61
61
  def database_base_name(config)
62
- db = config['database']
62
+ db = resolve_database(config, true)
63
63
  db[0, 4] == 'mem:' ? nil : begin
64
- expand_path db[0, 4] == 'file:' ? db[4..-1] : db
64
+ expand_path db[0, 5] == 'file:' ? db[5..-1] : db
65
65
  end
66
66
  end
67
-
67
+
68
68
  end
69
69
  end
70
70
  end
@@ -1,18 +1,18 @@
1
1
  module ArJdbc
2
2
  module Tasks
3
3
  # Sharing task related code between AR 3.x and 4.x
4
- #
4
+ #
5
5
  # @note this class needs to conform to the API available since AR 4.0
6
6
  # mostly to be usable with ActiveRecord::Tasks::DatabaseTasks module
7
7
  class JdbcDatabaseTasks
8
-
8
+
9
9
  attr_reader :configuration
10
10
  alias_method :config, :configuration
11
-
11
+
12
12
  def initialize(configuration)
13
13
  @configuration = configuration
14
14
  end
15
-
15
+
16
16
  delegate :connection, :establish_connection, :to => ActiveRecord::Base
17
17
 
18
18
  def create
@@ -25,14 +25,14 @@ module ArJdbc
25
25
  rescue #=> error # database does not exists :
26
26
  url = config['url']
27
27
  url = $1 if url && url =~ /^(.*(?<!\/)\/)(?=\w)/
28
-
28
+
29
29
  establish_connection(config.merge('database' => nil, 'url' => url))
30
-
30
+
31
31
  unless connection.respond_to?(:create_database)
32
32
  raise "AR-JDBC adapter '#{adapter_with_spec}' does not support create_database"
33
33
  end
34
- connection.create_database(config['database'], config)
35
-
34
+ connection.create_database(resolve_database(config), config)
35
+
36
36
  establish_connection(config)
37
37
  end
38
38
  end
@@ -42,7 +42,7 @@ module ArJdbc
42
42
  unless ActiveRecord::Base.connection.respond_to?(:drop_database)
43
43
  raise "AR-JDBC adapter '#{adapter_with_spec}' does not support drop_database"
44
44
  end
45
- connection.drop_database config['database']
45
+ connection.drop_database resolve_database(config)
46
46
  end
47
47
 
48
48
  def purge
@@ -73,7 +73,7 @@ module ArJdbc
73
73
  raise "AR-JDBC adapter '#{adapter_with_spec}' does not support collation"
74
74
  end
75
75
  end
76
-
76
+
77
77
  def structure_dump(filename)
78
78
  establish_connection(config)
79
79
  if connection.respond_to?(:structure_dump)
@@ -94,29 +94,76 @@ module ArJdbc
94
94
  raise "AR-JDBC adapter '#{adapter_with_spec}' does not support structure_load"
95
95
  end
96
96
  end
97
-
98
- private
99
-
100
- def adapter_with_spec
101
- adapter, spec = config['adapter'], config['adapter_spec']
102
- spec ? "#{adapter} (#{spec})" : adapter
103
- end
104
-
97
+
105
98
  protected
106
-
99
+
107
100
  def expand_path(path)
108
101
  require 'pathname'
109
102
  path = Pathname.new path
110
103
  return path.to_s if path.absolute?
111
104
  rails_root ? File.join(rails_root, path) : File.expand_path(path)
112
105
  end
113
-
106
+
107
+ def resolve_database(config, file_paths = false)
108
+ config['database'] || resolve_database_from_url(config['url'] || '', file_paths)
109
+ end
110
+
111
+ def resolve_database_from_url(url, file_paths = false)
112
+ ( config = config_from_url(url, file_paths) ) ? config['database'] : nil
113
+ end
114
+
114
115
  private
115
-
116
+
117
+ def config_from_url(url, file_paths = false)
118
+ match = url.match %r{
119
+ ^ jdbc:
120
+ ( [\w]+ ): # $1 protocol
121
+ (?: ([\w]+) : )? # $2 (sub-protocol)
122
+ (?://)?
123
+ (?: ([\w\-]*) (?: [/:] ([\w\-]*) )? @ (?://)? )? # user[:password]@ or user[/password]@ ($3 $4)
124
+ ( [\w\.\-]+ )? # $5 host (or database if there's nothing left)
125
+ (?: : (\d+) )? # $6 port if any
126
+ (?: :? (/?[\w\-\./~]+) [\?;]? )? ([^/]*?) $
127
+ # $7 database part (ends with '?' or ';') and $8 query string - properties
128
+ }x
129
+
130
+ return nil unless match
131
+
132
+ config = {}
133
+ config['_protocol'] = match[1]
134
+ config['_sub_protocol'] = match[2] if match[2]
135
+ config['username'] = match[3] if match[3]
136
+ config['password'] = match[4] if match[4]
137
+ host = match[5]; port = match[6]
138
+ database = match[7]
139
+ if database.nil? && port.nil?
140
+ config['database'] = database = host
141
+ else
142
+ config['host'] = host if host
143
+ config['port'] = port if port
144
+ config['database'] = database
145
+ end
146
+ if database && ! file_paths && database[0...1] == '/'
147
+ config['database'] = database[1..-1]
148
+ end
149
+ if query_string = match[8]
150
+ properties = query_string.split('&').inject({}) do |memo, pair|
151
+ pair = pair.split("="); memo[ pair[0] ] = pair[1]; memo
152
+ end
153
+ config['properties'] = properties
154
+ end
155
+ config
156
+ end
157
+
158
+ def adapter_with_spec
159
+ adapter, spec = config['adapter'], config['adapter_spec']
160
+ spec ? "#{adapter} (#{spec})" : adapter
161
+ end
162
+
116
163
  def rails_root
117
164
  defined?(Rails.root) ? Rails.root : ( RAILS_ROOT )
118
165
  end
119
-
166
+
120
167
  end
121
168
  end
122
169
  end
@@ -6,22 +6,32 @@ module ArJdbc
6
6
 
7
7
  def purge
8
8
  test = deep_dup(configuration)
9
- test_database = test['database']
9
+ test_database = resolve_database(test)
10
10
  test['database'] = 'master'
11
11
  establish_connection(test)
12
12
  connection.recreate_database!(test_database)
13
13
  end
14
14
 
15
15
  def structure_dump(filename)
16
+ config = config_from_url_if_needed
16
17
  `smoscript -s #{config['host']} -d #{config['database']} -u #{config['username']} -p #{config['password']} -f #{filename} -A -U`
17
18
  end
18
19
 
19
20
  def structure_load(filename)
21
+ config = config_from_url_if_needed
20
22
  `sqlcmd -S #{config['host']} -d #{config['database']} -U #{config['username']} -P #{config['password']} -i #{filename}`
21
23
  end
22
-
24
+
23
25
  private
24
-
26
+
27
+ def config_from_url_if_needed
28
+ config = self.config
29
+ if config['url'] && ! config.key?('database')
30
+ config = config_from_url(config['url'])
31
+ end
32
+ config
33
+ end
34
+
25
35
  def deep_dup(hash)
26
36
  dup = hash.dup
27
37
  dup.each_pair do |k,v|
@@ -30,7 +40,7 @@ module ArJdbc
30
40
  end
31
41
  dup
32
42
  end
33
-
43
+
34
44
  end
35
45
  end
36
46
  end
@@ -8,6 +8,9 @@ module ArJdbc
8
8
  print "Please provide the SYSTEM password for your oracle installation\n>"
9
9
  system_password = $stdin.gets.strip
10
10
  establish_connection(config.merge('username' => 'SYSTEM', 'password' => system_password))
11
+ unless ( config = self.config ).key?('username')
12
+ config = config_from_url(config['url']) if config['url']
13
+ end
11
14
  begin
12
15
  connection.execute "CREATE USER #{config['username']} IDENTIFIED BY #{config['password']}"
13
16
  rescue => e
@@ -22,13 +25,13 @@ module ArJdbc
22
25
  connection.execute "GRANT create table TO #{config['username']}"
23
26
  connection.execute "GRANT create sequence TO #{config['username']}"
24
27
  end
25
-
28
+
26
29
  def drop
27
30
  self.class.load_enhanced_structure_dump
28
31
  establish_connection(config)
29
32
  connection.execute_structure_dump(connection.full_drop)
30
33
  end
31
-
34
+
32
35
  def purge
33
36
  self.class.load_enhanced_structure_dump
34
37
  establish_connection(:test)
@@ -47,7 +50,7 @@ module ArJdbc
47
50
  establish_connection(config)
48
51
  connection.execute_structure_dump(File.read(filename))
49
52
  end
50
-
53
+
51
54
  def self.load_enhanced_structure_dump
52
55
  unless defined? ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
53
56
  ActiveRecord::ConnectionAdapters.module_eval do
@@ -56,7 +59,7 @@ module ArJdbc
56
59
  end
57
60
  require 'arjdbc/tasks/oracle/enhanced_structure_dump'
58
61
  end
59
-
62
+
60
63
  end
61
64
  end
62
65
  end
@@ -1,5 +1,5 @@
1
1
  module ArJdbc
2
- VERSION = "1.3.6"
2
+ VERSION = "1.3.7"
3
3
  # @deprecated
4
4
  module Version
5
5
  # @private 1.2.x compatibility
data/lib/jdbc_adapter.rb CHANGED
@@ -1,2 +1,2 @@
1
- warn "DEPRECATED: require 'arjdbc' instead of 'jdbc_adapter'."
2
1
  require 'arjdbc'
2
+ ArJdbc.deprecate "require 'arjdbc' instead of 'jdbc_adapter'"
@@ -1,3 +1,4 @@
1
- # @deprecated
2
- warn "DEPRECATED: load 'arjdbc/tasks.rb' instead of 'jdbc_adapter/rake_tasks.rb'"
3
- require 'arjdbc/tasks.rb'
1
+ require 'arjdbc/tasks.rb'
2
+
3
+ require 'arjdbc'
4
+ ArJdbc.deprecate "load 'arjdbc/tasks.rb' instead of 'jdbc_adapter/rake_tasks.rb'"
@@ -1,2 +1,4 @@
1
- warn "DEPRECATED: require 'arjdbc/version' instead of 'jdbc_adapter/version'."
2
- require 'arjdbc/version'
1
+ require 'arjdbc/version'
2
+
3
+ require 'arjdbc'
4
+ ArJdbc.deprecate "require 'arjdbc/version' instead of 'jdbc_adapter/version'"
data/rakelib/02-test.rake CHANGED
@@ -47,6 +47,16 @@ task 'test_appraisal_hint' do
47
47
  end
48
48
  end
49
49
 
50
+ desc "Run unit tests (not connecting to a DB)."
51
+ Rake::TestTask.new(:test_unit) do |test_task|
52
+ test_task.test_files = FileList["test/unit*_test.rb"] + FileList["test/unit/*_test.rb"]
53
+ test_task.libs << 'lib' if defined?(JRUBY_VERSION)
54
+ test_task.libs << 'test'
55
+ test_task.verbose = true if $VERBOSE
56
+ set_test_task_compat_version test_task
57
+ end
58
+ task :test_units => :test_unit # alias
59
+
50
60
  Rake::TestTask.class_eval { attr_reader :test_files }
51
61
 
52
62
  def test_task_for(adapter, options = {})
data/rakelib/db.rake CHANGED
@@ -4,6 +4,7 @@ namespace :db do
4
4
 
5
5
  desc "Creates the test database for MySQL"
6
6
  task :mysql do
7
+ fail "could not create test database: mysql executable not found" unless mysql = which('mysql')
7
8
  load 'test/db/mysql_config.rb' # rescue nil
8
9
  script = sql_script <<-SQL, 'mysql'
9
10
  DROP DATABASE IF EXISTS `#{MYSQL_CONFIG[:database]}`;
@@ -19,12 +20,13 @@ SQL
19
20
  params['--password'] = password
20
21
  end
21
22
  puts "Creating MySQL (test) database: #{MYSQL_CONFIG[:database]}"
22
- sh "cat #{script.path} | mysql #{params.to_a.join(' ')}", :verbose => $VERBOSE # so password is not echoed
23
+ sh "cat #{script.path} | #{mysql} #{params.to_a.join(' ')}", :verbose => $VERBOSE # so password is not echoed
23
24
  end
24
25
 
25
26
  desc "Creates the test database for PostgreSQL"
26
27
  task :postgresql do
27
- fail unless PostgresHelper.have_postgres?
28
+ fail 'could not create test database: psql executable not found' unless psql = which('psql')
29
+ fail 'could not create test database: missing "postgres" role' unless PostgresHelper.postgres_role?
28
30
  load 'test/db/postgres_config.rb' # rescue nil
29
31
  script = sql_script <<-SQL, 'psql'
30
32
  DROP DATABASE IF EXISTS #{POSTGRES_CONFIG[:database]};
@@ -35,7 +37,7 @@ SQL
35
37
  params = { '-U' => ENV['PSQL_USER'] || 'postgres' }
36
38
  params['-q'] = nil unless $VERBOSE
37
39
  puts "Creating PostgreSQL (test) database: #{POSTGRES_CONFIG[:database]}"
38
- sh "cat #{script.path} | psql #{params.to_a.join(' ')}", :verbose => $VERBOSE
40
+ sh "cat #{script.path} | #{psql} #{params.to_a.join(' ')}", :verbose => $VERBOSE
39
41
  end
40
42
  task :postgres => :postgresql
41
43
 
@@ -35,7 +35,6 @@ import java.sql.SQLException;
35
35
  import java.sql.Statement;
36
36
  import java.sql.Timestamp;
37
37
  import java.sql.Types;
38
- import java.util.List;
39
38
  import java.util.Map;
40
39
  import java.util.UUID;
41
40
 
@@ -43,6 +42,7 @@ import org.jruby.Ruby;
43
42
  import org.jruby.RubyArray;
44
43
  import org.jruby.RubyBoolean;
45
44
  import org.jruby.RubyClass;
45
+ import org.jruby.RubyFixnum;
46
46
  import org.jruby.RubyFloat;
47
47
  import org.jruby.RubyHash;
48
48
  import org.jruby.RubyIO;
@@ -56,6 +56,8 @@ import org.jruby.util.ByteList;
56
56
 
57
57
  import org.postgresql.PGConnection;
58
58
  import org.postgresql.PGStatement;
59
+ import org.postgresql.core.BaseConnection;
60
+ import org.postgresql.jdbc4.Jdbc4Array;
59
61
  import org.postgresql.util.PGInterval;
60
62
  import org.postgresql.util.PGobject;
61
63
 
@@ -204,25 +206,50 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
204
206
  private static final ByteList INTERVAL =
205
207
  new ByteList( new byte[] { 'i','n','t','e','r','v','a','l' }, false );
206
208
 
209
+ private static final ByteList ARRAY_END = new ByteList( new byte[] { '[',']' }, false );
210
+
207
211
  @Override
208
212
  protected void setStringParameter(final ThreadContext context,
209
213
  final Connection connection, final PreparedStatement statement,
210
214
  final int index, final IRubyObject value,
211
215
  final IRubyObject column, final int type) throws SQLException {
212
- if ( value.isNil() ) statement.setNull(index, Types.VARCHAR);
216
+ final RubyString sqlType;
217
+ if ( column != null && ! column.isNil() ) {
218
+ sqlType = (RubyString) column.callMethod(context, "sql_type");
219
+ }
213
220
  else {
214
- if ( column != null && ! column.isNil() ) {
215
- final RubyString sqlType = column.callMethod(context, "sql_type").asString();
221
+ sqlType = null;
222
+ }
216
223
 
224
+ if ( value.isNil() ) {
225
+ if ( rawArrayType == Boolean.TRUE ) { // array's type is :string
226
+ if ( sqlType != null && sqlType.getByteList().endsWith( ARRAY_END ) ) {
227
+ statement.setNull(index, Types.ARRAY); return;
228
+ }
229
+ statement.setNull(index, type); return;
230
+ }
231
+ statement.setNull(index, Types.VARCHAR);
232
+ }
233
+ else {
234
+ final String valueStr = value.asString().toString();
235
+ if ( sqlType != null ) {
236
+ if ( rawArrayType == Boolean.TRUE && sqlType.getByteList().endsWith( ARRAY_END ) ) {
237
+ final Array valueArr = new Jdbc4Array(connection.unwrap(BaseConnection.class), oidType(column), valueStr);
238
+ statement.setArray(index, valueArr); return;
239
+ }
217
240
  if ( sqlType.getByteList().startsWith( INTERVAL ) ) {
218
- statement.setObject( index, new PGInterval( value.asString().toString() ) );
219
- return;
241
+ statement.setObject( index, new PGInterval( valueStr ) ); return;
220
242
  }
221
243
  }
222
- statement.setString( index, value.asString().toString() );
244
+ statement.setString( index, valueStr );
223
245
  }
224
246
  }
225
247
 
248
+ private static int oidType(final IRubyObject column) {
249
+ final IRubyObject oid_type = column.getInstanceVariables().getInstanceVariable("@oid_type");
250
+ return RubyFixnum.fix2int(oid_type);
251
+ }
252
+
226
253
  @Override
227
254
  protected void setObjectParameter(final ThreadContext context,
228
255
  final Connection connection, final PreparedStatement statement,
@@ -463,7 +490,7 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
463
490
  final Ruby runtime, final ResultSet resultSet, final int column)
464
491
  throws SQLException {
465
492
  if ( rawArrayType == Boolean.TRUE ) { // pre AR 4.0 compatibility
466
- return runtime.newString( resultSet.getString(column) );
493
+ return stringToRuby(context, runtime, resultSet, column);
467
494
  }
468
495
  // NOTE: avoid `finally { array.free(); }` on PostgreSQL due :
469
496
  // java.sql.SQLFeatureNotSupportedException:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-jdbc-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.6
4
+ version: 1.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sieger, Ola Bini, Karol Bucek and JRuby contributors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-04 00:00:00.000000000 Z
11
+ date: 2014-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -238,7 +238,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
238
238
  version: '0'
239
239
  requirements: []
240
240
  rubyforge_project: jruby-extras
241
- rubygems_version: 2.1.11
241
+ rubygems_version: 2.2.2
242
242
  signing_key:
243
243
  specification_version: 4
244
244
  summary: JDBC adapter for ActiveRecord, for use within JRuby on Rails.