pmacs-activerecord-oracle_enhanced-adapter 1.4.2.rc1 → 1.5.5.1

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 (44) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +11 -40
  3. data/History.md +170 -0
  4. data/README.md +61 -5
  5. data/Rakefile +1 -0
  6. data/VERSION +1 -1
  7. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +330 -161
  8. data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +48 -8
  9. data/lib/active_record/connection_adapters/oracle_enhanced_column_dumper.rb +77 -0
  10. data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +8 -24
  11. data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +4 -13
  12. data/lib/active_record/connection_adapters/oracle_enhanced_database_tasks.rb +61 -0
  13. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +13 -12
  14. data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +42 -19
  15. data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +28 -74
  16. data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +165 -231
  17. data/lib/active_record/connection_adapters/oracle_enhanced_schema_creation.rb +89 -0
  18. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +16 -24
  19. data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +29 -38
  20. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +93 -42
  21. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +5 -3
  22. data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +7 -7
  23. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +1 -1
  24. data/lib/pmacs-activerecord-oracle_enhanced-adapter.rb +2 -2
  25. data/pmacs-activerecord-oracle_enhanced-adapter.gemspec +19 -17
  26. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +35 -99
  27. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +17 -3
  28. data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +105 -98
  29. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +74 -44
  30. data/spec/active_record/connection_adapters/oracle_enhanced_database_tasks_spec.rb +89 -0
  31. data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +3 -3
  32. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +13 -2
  33. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +11 -12
  34. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +252 -60
  35. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +170 -40
  36. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +14 -8
  37. data/spec/spec_helper.rb +25 -54
  38. metadata +41 -72
  39. data/lib/active_record/connection_adapters/oracle_enhanced.rake +0 -105
  40. data/lib/active_record/connection_adapters/oracle_enhanced_activerecord_patches.rb +0 -41
  41. data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +0 -118
  42. data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +0 -25
  43. data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +0 -17
  44. data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +0 -19
@@ -2,34 +2,63 @@ module ActiveRecord
2
2
  module ConnectionAdapters #:nodoc:
3
3
  class OracleEnhancedColumn < Column
4
4
 
5
- attr_reader :table_name, :forced_column_type, :nchar, :virtual_column_data_default #:nodoc:
5
+ attr_reader :table_name, :forced_column_type, :nchar, :virtual_column_data_default, :returning_id #:nodoc:
6
6
 
7
- def initialize(name, default, sql_type = nil, null = true, table_name = nil, forced_column_type = nil, virtual=false) #:nodoc:
7
+ def initialize(name, default, sql_type = nil, null = true, table_name = nil, forced_column_type = nil, virtual=false, returning_id=false) #:nodoc:
8
8
  @table_name = table_name
9
9
  @forced_column_type = forced_column_type
10
10
  @virtual = virtual
11
11
  @virtual_column_data_default = default.inspect if virtual
12
- default = nil if virtual
13
- super(name, default, sql_type, null)
12
+ @returning_id = returning_id
13
+ if virtual
14
+ default_value = nil
15
+ else
16
+ default_value = self.class.extract_value_from_default(default)
17
+ end
18
+ super(name, default_value, sql_type, null)
14
19
  # Is column NCHAR or NVARCHAR2 (will need to use N'...' value quoting for these data types)?
15
20
  # Define only when needed as adapter "quote" method will check at first if instance variable is defined.
16
21
  @nchar = true if @type == :string && sql_type[0,1] == 'N'
22
+ @object_type = sql_type.include? '.'
17
23
  end
18
24
 
19
25
  def type_cast(value) #:nodoc:
20
- return OracleEnhancedColumn::string_to_raw(value) if type == :raw
21
- return guess_date_or_time(value) if type == :datetime && OracleEnhancedAdapter.emulate_dates
22
- super
26
+ case type
27
+ when :raw
28
+ OracleEnhancedColumn.string_to_raw(value)
29
+ when :datetime
30
+ OracleEnhancedAdapter.emulate_dates ? guess_date_or_time(value) : super
31
+ when :float
32
+ !value.nil? ? self.class.value_to_decimal(value) : super
33
+ else
34
+ super
35
+ end
36
+ end
37
+
38
+ def type_cast_code(var_name)
39
+ type == :float ? "#{self.class.name}.value_to_decimal(#{var_name})" : super
40
+ end
41
+
42
+ def klass
43
+ type == :float ? BigDecimal : super
23
44
  end
24
45
 
25
46
  def virtual?
26
47
  @virtual
27
48
  end
28
49
 
50
+ def returning_id?
51
+ @returning_id
52
+ end
53
+
29
54
  def lob?
30
55
  self.sql_type =~ /LOB$/i
31
56
  end
32
57
 
58
+ def object_type?
59
+ @object_type
60
+ end
61
+
33
62
  # convert something to a boolean
34
63
  # added y as boolean value
35
64
  def self.value_to_boolean(value) #:nodoc:
@@ -71,12 +100,14 @@ module ActiveRecord
71
100
  forced_column_type ||
72
101
  case field_type
73
102
  when /decimal|numeric|number/i
74
- if OracleEnhancedAdapter.emulate_booleans && field_type == 'NUMBER(1)'
103
+ if OracleEnhancedAdapter.emulate_booleans && field_type.upcase == "NUMBER(1)"
75
104
  :boolean
76
105
  elsif extract_scale(field_type) == 0 ||
77
106
  # if column name is ID or ends with _ID
78
107
  OracleEnhancedAdapter.emulate_integers_by_column_name && OracleEnhancedAdapter.is_integer_column?(name, table_name)
79
108
  :integer
109
+ elsif field_type.upcase == "NUMBER"
110
+ OracleEnhancedAdapter.number_datatype_coercion
80
111
  else
81
112
  :decimal
82
113
  end
@@ -104,6 +135,15 @@ module ActiveRecord
104
135
  end
105
136
  end
106
137
 
138
+ def self.extract_value_from_default(default)
139
+ case default
140
+ when String
141
+ default.gsub(/''/, "'")
142
+ else
143
+ default
144
+ end
145
+ end
146
+
107
147
  def guess_date_or_time(value)
108
148
  value.respond_to?(:hour) && (value.hour == 0 and value.min == 0 and value.sec == 0) ?
109
149
  Date.new(value.year, value.month, value.day) : value
@@ -0,0 +1,77 @@
1
+ module ActiveRecord #:nodoc:
2
+ module ConnectionAdapters #:nodoc:
3
+ module OracleEnhancedColumnDumper #:nodoc:
4
+
5
+ def self.included(base) #:nodoc:
6
+ base.class_eval do
7
+ private
8
+ alias_method_chain :column_spec, :oracle_enhanced
9
+ alias_method_chain :prepare_column_options, :oracle_enhanced
10
+ alias_method_chain :migration_keys, :oracle_enhanced
11
+
12
+ def oracle_enhanced_adapter?
13
+ # return original method if not using 'OracleEnhanced'
14
+ if (rails_env = defined?(Rails.env) ? Rails.env : (defined?(RAILS_ENV) ? RAILS_ENV : nil)) &&
15
+ ActiveRecord::Base.configurations[rails_env] &&
16
+ ActiveRecord::Base.configurations[rails_env]['adapter'] != 'oracle_enhanced'
17
+ return false
18
+ else
19
+ return true
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ def column_spec_with_oracle_enhanced(column, types)
26
+ # return original method if not using 'OracleEnhanced'
27
+ return column_spec_without_oracle_enhanced(column, types) unless oracle_enhanced_adapter?
28
+
29
+ spec = prepare_column_options(column, types)
30
+ (spec.keys - [:name, :type]).each do |k|
31
+ key_s = (k == :virtual_type ? "type: " : "#{k.to_s}: ")
32
+ spec[k] = key_s + spec[k]
33
+ end
34
+ spec
35
+ end
36
+
37
+ def prepare_column_options_with_oracle_enhanced(column, types)
38
+ # return original method if not using 'OracleEnhanced'
39
+ return prepare_column_options_without_oracle_enhanced(column, types) unless oracle_enhanced_adapter?
40
+
41
+ spec = {}
42
+
43
+ spec[:name] = column.name.inspect
44
+ spec[:type] = column.virtual? ? 'virtual' : column.type.to_s
45
+ spec[:limit] = column.limit.inspect if column.limit != types[column.type][:limit] && column.type != :decimal
46
+ spec[:precision] = column.precision.inspect if !column.precision.nil?
47
+ spec[:scale] = column.scale.inspect if !column.scale.nil?
48
+ spec[:null] = 'false' if !column.null
49
+ spec[:as] = column.virtual_column_data_default if column.virtual?
50
+ spec[:default] = default_string(column.default) if column.has_default? && !column.virtual?
51
+
52
+ if column.virtual?
53
+ # Supports backwards compatibility with older OracleEnhancedAdapter versions where 'NUMBER' virtual column type is not included in dump
54
+ if column.sql_type != "NUMBER" || ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.number_datatype_coercion != :decimal
55
+ spec[:virtual_type] = column.type.inspect
56
+ end
57
+ end
58
+
59
+ spec
60
+ end
61
+
62
+ def migration_keys_with_oracle_enhanced
63
+ # TODO `& column_specs.map(&:keys).flatten` should be exetuted here
64
+ # return original method if not using 'OracleEnhanced'
65
+ return migration_keys_without_oracle_enhanced unless oracle_enhanced_adapter?
66
+
67
+ [:name, :limit, :precision, :scale, :default, :null, :as, :virtual_type]
68
+ end
69
+
70
+
71
+ end
72
+ end
73
+ end
74
+
75
+ ActiveRecord::ConnectionAdapters::ColumnDumper.class_eval do
76
+ include ActiveRecord::ConnectionAdapters::OracleEnhancedColumnDumper
77
+ end
@@ -4,18 +4,13 @@ module ActiveRecord
4
4
  class OracleEnhancedConnection #:nodoc:
5
5
 
6
6
  def self.create(config)
7
- connection = create_connection(config)
8
- unless connection.nil?
9
- connection.after_initialize(config)
10
- end
11
- connection
12
- end
13
-
14
- def after_initialize(config)
15
- schema = config[:schema]
16
- unless schema.blank?
17
- exec "alter session set current_schema = #{schema}"
18
- @owner = schema.upcase
7
+ case ORACLE_ENHANCED_CONNECTION
8
+ when :oci
9
+ OracleEnhancedOCIConnection.new(config)
10
+ when :jdbc
11
+ OracleEnhancedJDBCConnection.new(config)
12
+ else
13
+ nil
19
14
  end
20
15
  end
21
16
 
@@ -103,22 +98,11 @@ module ActiveRecord
103
98
  result.map { |r| r.values.first }
104
99
  end
105
100
 
106
-
107
- protected
108
- def self.create_connection(config)
109
- case ORACLE_ENHANCED_CONNECTION
110
- when :oci
111
- OracleEnhancedOCIConnection.new(config)
112
- when :jdbc
113
- OracleEnhancedJDBCConnection.new(config)
114
- else
115
- nil
116
- end
117
- end
118
101
  end
119
102
 
120
103
  class OracleEnhancedConnectionException < StandardError #:nodoc:
121
104
  end
105
+
122
106
  end
123
107
  end
124
108
 
@@ -329,19 +329,10 @@ module ActiveRecord
329
329
 
330
330
  module ContextIndexClassMethods
331
331
  # Add context index condition.
332
- case ::ActiveRecord::VERSION::MAJOR
333
- when 3
334
- def contains(column, query, options ={})
335
- score_label = options[:label].to_i || 1
336
- where("CONTAINS(#{connection.quote_column_name(column)}, ?, #{score_label}) > 0", query).
337
- order("SCORE(#{score_label}) DESC")
338
- end
339
- when 2
340
- def contains(column, query, options ={})
341
- score_label = options[:label].to_i || 1
342
- scoped(:conditions => ["CONTAINS(#{connection.quote_column_name(column)}, ?, #{score_label}) > 0", query],
343
- :order => "SCORE(#{score_label}) DESC")
344
- end
332
+ def contains(column, query, options ={})
333
+ score_label = options[:label].to_i || 1
334
+ where("CONTAINS(#{connection.quote_column_name(column)}, ?, #{score_label}) > 0", query).
335
+ order("SCORE(#{score_label}) DESC")
345
336
  end
346
337
  end
347
338
 
@@ -0,0 +1,61 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class OracleEnhancedAdapter
4
+ class DatabaseTasks
5
+ delegate :connection, :establish_connection, :to => ActiveRecord::Base
6
+
7
+ def initialize(config)
8
+ @config = config
9
+ end
10
+
11
+ def create
12
+ print "Please provide the SYSTEM password for your Oracle installation\n>"
13
+ system_password = $stdin.gets.strip
14
+ establish_connection(@config.merge('username' => 'SYSTEM', 'password' => system_password))
15
+ begin
16
+ connection.execute "CREATE USER #{@config['username']} IDENTIFIED BY #{@config['password']}"
17
+ rescue => e
18
+ if e.message =~ /ORA-01920/ # user name conflicts with another user or role name
19
+ connection.execute "ALTER USER #{@config['username']} IDENTIFIED BY #{@config['password']}"
20
+ else
21
+ raise e
22
+ end
23
+ end
24
+ connection.execute "GRANT unlimited tablespace TO #{@config['username']}"
25
+ connection.execute "GRANT create session TO #{@config['username']}"
26
+ connection.execute "GRANT create table TO #{@config['username']}"
27
+ connection.execute "GRANT create sequence TO #{@config['username']}"
28
+ end
29
+
30
+ def drop
31
+ establish_connection(@config)
32
+ connection.execute_structure_dump(connection.full_drop)
33
+ end
34
+
35
+ def purge
36
+ drop
37
+ connection.execute('PURGE RECYCLEBIN') rescue nil
38
+ end
39
+
40
+ def structure_dump(filename)
41
+ establish_connection(@config)
42
+ File.open(filename, 'w:utf-8') { |f| f << connection.structure_dump }
43
+ if connection.supports_migrations?
44
+ File.open(filename, 'a') { |f| f << connection.dump_schema_information }
45
+ end
46
+ if @config['structure_dump'] == 'db_stored_code'
47
+ File.open(filename, 'a') { |f| f << connection.structure_dump_db_stored_code }
48
+ end
49
+ end
50
+
51
+ def structure_load(filename)
52
+ establish_connection(@config)
53
+ connection.execute_structure_dump(File.read(filename))
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ ActiveRecord::Tasks::DatabaseTasks.register_task(/(oci|oracle)/, ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter::DatabaseTasks)
61
+
@@ -4,20 +4,22 @@ module ActiveRecord #:nodoc:
4
4
 
5
5
  module InstanceMethods #:nodoc:
6
6
  private
7
-
7
+
8
8
  def _field_changed?(attr, old, value)
9
9
  if column = column_for_attribute(attr)
10
10
  # Added also :decimal type
11
- if (column.type == :integer || column.type == :decimal) && column.null && (old.nil? || old == 0) && value.blank?
12
- # For nullable integer columns, NULL gets stored in database for blank (i.e. '') values.
11
+ if ([:integer, :decimal, :float].include? column.type) && column.null && (old.nil? || old == 0) && value.blank?
12
+ # For nullable integer/decimal/float columns, NULL gets stored in database for blank (i.e. '') values.
13
13
  # Hence we don't record it as a change if the value changes from nil to ''.
14
14
  # If an old value of 0 is set to '' we want this to get changed to nil as otherwise it'll
15
15
  # be typecast back to 0 (''.to_i => 0)
16
16
  value = nil
17
- # Oracle stores empty string '' as NULL
18
- # therefore need to convert empty string value to nil if old value is nil
19
17
  elsif column.type == :string && column.null && old.nil?
18
+ # Oracle stores empty string '' as NULL
19
+ # therefore need to convert empty string value to nil if old value is nil
20
20
  value = nil if value == ''
21
+ elsif old == 0 && value.is_a?(String) && value.present? && non_zero?(value)
22
+ value = nil
21
23
  else
22
24
  value = column.type_cast(value)
23
25
  end
@@ -25,7 +27,11 @@ module ActiveRecord #:nodoc:
25
27
 
26
28
  old != value
27
29
  end
28
-
30
+
31
+ def non_zero?(value)
32
+ value !~ /\A0+(\.0+)?\z/
33
+ end
34
+
29
35
  end
30
36
 
31
37
  end
@@ -35,10 +41,5 @@ end
35
41
  if ActiveRecord::Base.method_defined?(:changed?)
36
42
  ActiveRecord::Base.class_eval do
37
43
  include ActiveRecord::ConnectionAdapters::OracleEnhancedDirty::InstanceMethods
38
- # Starting with rails 3.2.9 the method #field_changed?
39
- # was renamed to #_field_changed?
40
- if private_method_defined?(:field_changed?)
41
- alias_method :field_changed?, :_field_changed?
42
- end
43
44
  end
44
- end
45
+ end
@@ -2,24 +2,36 @@ begin
2
2
  require "java"
3
3
  require "jruby"
4
4
 
5
- # ojdbc6.jar or ojdbc5.jar file should be in JRUBY_HOME/lib or should be in ENV['PATH'] or load path
5
+ # ojdbc7.jar, ojdbc6.jar or ojdbc5.jar file should be in application ./lib directory or in load path or in ENV['PATH']
6
6
 
7
7
  java_version = java.lang.System.getProperty("java.version")
8
- ojdbc_jar = if java_version =~ /^1.5/
9
- "ojdbc5.jar"
10
- elsif java_version >= '1.6'
11
- "ojdbc6.jar"
8
+ ojdbc_jars = if java_version =~ /^1.5/
9
+ %w(ojdbc5.jar)
10
+ elsif java_version =~ /^1.6/
11
+ %w(ojdbc6.jar)
12
+ elsif java_version >= '1.7'
13
+ # Oracle 11g client ojdbc6.jar is also compatible with Java 1.7
14
+ # Oracle 12c client provides new ojdbc7.jar
15
+ %w(ojdbc7.jar ojdbc6.jar)
12
16
  else
13
17
  nil
14
18
  end
15
19
 
16
- unless ojdbc_jar.nil? || ENV_JAVA['java.class.path'] =~ Regexp.new(ojdbc_jar)
20
+ if ojdbc_jars && ENV_JAVA['java.class.path'] !~ Regexp.new(ojdbc_jars.join('|'))
17
21
  # On Unix environment variable should be PATH, on Windows it is sometimes Path
18
- env_path = (ENV["PATH"] || ENV["Path"] || '').split(/[:;]/)
22
+ env_path = (ENV["PATH"] || ENV["Path"] || '').split(File::PATH_SEPARATOR)
19
23
  # Look for JDBC driver at first in lib subdirectory (application specific JDBC file version)
20
24
  # then in Ruby load path and finally in environment PATH
21
- if ojdbc_jar_path = ['./lib'].concat($LOAD_PATH).concat(env_path).find{|d| File.exists?(File.join(d,ojdbc_jar))}
22
- require File.join(ojdbc_jar_path,ojdbc_jar)
25
+ ['./lib'].concat($LOAD_PATH).concat(env_path).detect do |dir|
26
+ # check any compatible JDBC driver in the priority order
27
+ ojdbc_jars.any? do |ojdbc_jar|
28
+ if File.exists?(file_path = File.join(dir, ojdbc_jar))
29
+ puts "WARNING: JDK #{java_version} is not officially supported by #{ojdbc_jar}" if java_version >= '1.8'
30
+ puts "See http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#01_03 for supported versions"
31
+ require file_path
32
+ true
33
+ end
34
+ end
23
35
  end
24
36
  end
25
37
 
@@ -33,7 +45,7 @@ begin
33
45
 
34
46
  rescue LoadError, NameError
35
47
  # JDBC driver is unavailable.
36
- raise LoadError, "ERROR: ActiveRecord oracle_enhanced adapter could not load Oracle JDBC driver. Please install #{ojdbc_jar || "Oracle JDBC"} library."
48
+ raise LoadError, "ERROR: ActiveRecord oracle_enhanced adapter could not load Oracle JDBC driver. Please install #{ojdbc_jars ? ojdbc_jars.join(' or ') : "Oracle JDBC"} library."
37
49
  end
38
50
 
39
51
 
@@ -86,7 +98,7 @@ module ActiveRecord
86
98
  @raw_connection = @raw_connection.innermost_delegate
87
99
  elsif @raw_connection.respond_to?(:getUnderlyingConnection)
88
100
  @pooled_connection = @raw_connection
89
- @raw_connection = @raw_connection.underlying_connection
101
+ @raw_connection = @raw_connection.underlying_connection
90
102
  end
91
103
 
92
104
  config[:driver] ||= @raw_connection.meta_data.connection.java_class.name
@@ -149,8 +161,14 @@ module ActiveRecord
149
161
 
150
162
  self.autocommit = true
151
163
 
152
- # default schema owner
153
- @owner = username.upcase unless username.nil?
164
+ schema = config[:schema] && config[:schema].to_s
165
+ if schema.blank?
166
+ # default schema owner
167
+ @owner = username.upcase unless username.nil?
168
+ else
169
+ exec "alter session set current_schema = #{schema}"
170
+ @owner = schema
171
+ end
154
172
 
155
173
  @raw_connection
156
174
  end
@@ -285,7 +303,7 @@ module ActiveRecord
285
303
  # else
286
304
  # nil
287
305
  # end
288
-
306
+
289
307
  # Workaround with CallableStatement
290
308
  s = @raw_connection.prepareCall("BEGIN #{sql}; END;")
291
309
  s.registerOutParameter(1, java.sql.Types::BIGINT)
@@ -309,7 +327,8 @@ module ActiveRecord
309
327
  @raw_statement = raw_statement
310
328
  end
311
329
 
312
- def bind_param(position, value, col_type = nil)
330
+ def bind_param(position, value, column = nil)
331
+ col_type = column && column.type
313
332
  java_value = ruby_to_java_value(value, col_type)
314
333
  case value
315
334
  when Integer
@@ -336,10 +355,14 @@ module ActiveRecord
336
355
  when Time
337
356
  @raw_statement.setTimestamp(position, java_value)
338
357
  when NilClass
339
- # TODO: currently nil is always bound as NULL with VARCHAR type.
340
- # When nils will actually be used by ActiveRecord as bound parameters
341
- # then need to pass actual column type.
342
- @raw_statement.setNull(position, java.sql.Types::VARCHAR)
358
+ if column && column.object_type?
359
+ @raw_statement.setNull(position, java.sql.Types::STRUCT, column.sql_type)
360
+ else
361
+ # TODO: currently nil is always bound as NULL with VARCHAR type.
362
+ # When nils will actually be used by ActiveRecord as bound parameters
363
+ # then need to pass actual column type.
364
+ @raw_statement.setNull(position, java.sql.Types::VARCHAR)
365
+ end
343
366
  else
344
367
  raise ArgumentError, "Don't know how to bind variable with type #{value.class}"
345
368
  end