activerecord-oracle_enhanced-adapter 6.0.0.rc3 → 6.1.0.rc1

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +126 -0
  3. data/README.md +13 -2
  4. data/VERSION +1 -1
  5. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +2 -3
  6. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +0 -1
  7. data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +0 -9
  8. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +64 -47
  9. data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +4 -5
  10. data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +0 -1
  11. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +3 -4
  12. data/lib/active_record/connection_adapters/oracle_enhanced/lob.rb +1 -2
  13. data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +12 -7
  14. data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +0 -1
  15. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +38 -3
  16. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +3 -4
  17. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +1 -1
  18. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +15 -3
  19. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +48 -45
  20. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +16 -17
  21. data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +2 -1
  22. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +57 -15
  23. data/lib/active_record/type/oracle_enhanced/boolean.rb +0 -1
  24. data/lib/active_record/type/oracle_enhanced/integer.rb +0 -1
  25. data/lib/arel/visitors/oracle.rb +253 -0
  26. data/lib/arel/visitors/oracle12.rb +160 -0
  27. data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +35 -3
  28. data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +6 -1
  29. data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +0 -1
  30. data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +28 -1
  31. data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +2 -1
  32. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +48 -0
  33. data/spec/active_record/oracle_enhanced/type/national_character_string_spec.rb +4 -2
  34. data/spec/spec_config.yaml.template +2 -2
  35. data/spec/spec_helper.rb +13 -4
  36. data/spec/support/stats.sql +3 -0
  37. metadata +30 -26
@@ -18,13 +18,12 @@ module ActiveRecord #:nodoc:
18
18
  module ClassMethods
19
19
  def lob_columns
20
20
  columns.select do |column|
21
- column.sql_type_metadata.sql_type =~ /LOB$/
21
+ column.sql_type_metadata.sql_type.end_with?("LOB")
22
22
  end
23
23
  end
24
24
  end
25
25
 
26
26
  private
27
-
28
27
  def enhanced_write_lobs
29
28
  if self.class.connection.is_a?(ConnectionAdapters::OracleEnhancedAdapter) &&
30
29
  !(self.class.custom_create_method || self.class.custom_update_method)
@@ -97,6 +97,10 @@ module ActiveRecord
97
97
  @raw_connection.exec(sql, *bindvars, &block)
98
98
  end
99
99
 
100
+ def with_retry(&block)
101
+ @raw_connection.with_retry(&block)
102
+ end
103
+
100
104
  def prepare(sql)
101
105
  Cursor.new(self, @raw_connection.parse(sql))
102
106
  end
@@ -265,7 +269,6 @@ module ActiveRecord
265
269
  end
266
270
 
267
271
  private
268
-
269
272
  def date_without_time?(value)
270
273
  case value
271
274
  when OraDate
@@ -319,9 +322,9 @@ module ActiveRecord
319
322
  # connection using host, port and database name
320
323
  elsif host || port
321
324
  host ||= "localhost"
322
- host = "[#{host}]" if host =~ /^[^\[].*:/ # IPv6
325
+ host = "[#{host}]" if /^[^\[].*:/.match?(host) # IPv6
323
326
  port ||= 1521
324
- database = "/#{database}" unless database.match(/^\//)
327
+ database = "/#{database}" unless database.start_with?("/")
325
328
  "//#{host}:#{port}#{database}"
326
329
  # if no host is specified then assume that
327
330
  # database parameter is TNS alias or TNS connection string
@@ -423,13 +426,11 @@ class OCI8EnhancedAutoRecover < DelegateClass(OCI8) #:nodoc:
423
426
  LOST_CONNECTION_ERROR_CODES = [ 28, 1012, 3113, 3114, 3135 ] #:nodoc:
424
427
 
425
428
  # Adds auto-recovery functionality.
426
- #
427
- # See: http://www.jiubao.org/ruby-oci8/api.en.html#label-11
428
- def exec(sql, *bindvars, &block) #:nodoc:
429
+ def with_retry #:nodoc:
429
430
  should_retry = self.class.auto_retry? && autocommit?
430
431
 
431
432
  begin
432
- @connection.exec(sql, *bindvars, &block)
433
+ yield
433
434
  rescue OCIException => e
434
435
  raise unless e.is_a?(OCIError) && LOST_CONNECTION_ERROR_CODES.include?(e.code)
435
436
  @active = false
@@ -439,5 +440,9 @@ class OCI8EnhancedAutoRecover < DelegateClass(OCI8) #:nodoc:
439
440
  retry
440
441
  end
441
442
  end
443
+
444
+ def exec(sql, *bindvars, &block) #:nodoc:
445
+ with_retry { @connection.exec(sql, *bindvars, &block) }
446
+ end
442
447
  end
443
448
  #:startdoc:
@@ -97,7 +97,6 @@ module ActiveRecord #:nodoc:
97
97
  end
98
98
 
99
99
  private
100
-
101
100
  # Creates a record with custom create method
102
101
  # and returns its id.
103
102
  def _create_record
@@ -132,8 +132,43 @@ module ActiveRecord
132
132
  end
133
133
  end
134
134
 
135
- private
135
+ def column_name_matcher
136
+ COLUMN_NAME
137
+ end
138
+
139
+ def column_name_with_order_matcher
140
+ COLUMN_NAME_WITH_ORDER
141
+ end
142
+
143
+ COLUMN_NAME = /
144
+ \A
145
+ (
146
+ (?:
147
+ # "table_name"."column_name" | function(one or no argument)
148
+ ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")) | \w+\((?:|\g<2>)\)
149
+ )
150
+ (?:(?:\s+AS)?\s+(?:\w+|"\w+"))?
151
+ )
152
+ (?:\s*,\s*\g<1>)*
153
+ \z
154
+ /ix
155
+
156
+ COLUMN_NAME_WITH_ORDER = /
157
+ \A
158
+ (
159
+ (?:
160
+ # "table_name"."column_name" | function(one or no argument)
161
+ ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")) | \w+\((?:|\g<2>)\)
162
+ )
163
+ (?:\s+ASC|\s+DESC)?
164
+ (?:\s+NULLS\s+(?:FIRST|LAST))?
165
+ )
166
+ (?:\s*,\s*\g<1>)*
167
+ \z
168
+ /ix
169
+ private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
136
170
 
171
+ private
137
172
  def oracle_downcase(column_name)
138
173
  return nil if column_name.nil?
139
174
  /[a-z]/.match?(column_name) ? column_name : column_name.downcase
@@ -143,8 +178,8 @@ module ActiveRecord
143
178
  end
144
179
  end
145
180
 
146
- # if MRI or YARV
147
- if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby"
181
+ # if MRI or YARV or TruffleRuby
182
+ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby" || RUBY_ENGINE == "truffleruby"
148
183
  require "active_record/connection_adapters/oracle_enhanced/oci_quoting"
149
184
  # if JRuby
150
185
  elsif RUBY_ENGINE == "jruby"
@@ -3,11 +3,10 @@
3
3
  module ActiveRecord
4
4
  module ConnectionAdapters
5
5
  module OracleEnhanced
6
- class SchemaCreation < AbstractAdapter::SchemaCreation
6
+ class SchemaCreation < SchemaCreation
7
7
  private
8
-
9
8
  def visit_ColumnDefinition(o)
10
- if [:blob, :clob, :nclob].include?(sql_type = type_to_sql(o.type, o.options).downcase.to_sym)
9
+ if [:blob, :clob, :nclob].include?(sql_type = type_to_sql(o.type, **o.options).downcase.to_sym)
11
10
  if (tablespace = default_tablespace_for(sql_type))
12
11
  @lob_tablespaces ||= {}
13
12
  @lob_tablespaces[o.name] = tablespace
@@ -36,7 +35,7 @@ module ActiveRecord
36
35
  create_sql << " TABLESPACE #{tablespace}"
37
36
  end
38
37
  end
39
- add_table_options!(create_sql, table_options(o))
38
+ add_table_options!(create_sql, o)
40
39
  create_sql << " AS #{to_sql(o.as)}" if o.as
41
40
  create_sql
42
41
  end
@@ -17,7 +17,7 @@ module ActiveRecord
17
17
  ].each do |column_type|
18
18
  module_eval <<-CODE, __FILE__, __LINE__ + 1
19
19
  def #{column_type}(*args, **options)
20
- args.each { |name| column(name, :#{column_type}, options) }
20
+ args.each { |name| column(name, :#{column_type}, **options) }
21
21
  end
22
22
  CODE
23
23
  end
@@ -4,7 +4,15 @@ module ActiveRecord #:nodoc:
4
4
  module ConnectionAdapters #:nodoc:
5
5
  module OracleEnhanced #:nodoc:
6
6
  class SchemaDumper < ConnectionAdapters::SchemaDumper #:nodoc:
7
+ DEFAULT_PRIMARY_KEY_COLUMN_SPEC = { precision: "38", null: "false" }.freeze
8
+ private_constant :DEFAULT_PRIMARY_KEY_COLUMN_SPEC
9
+
7
10
  private
11
+ def column_spec_for_primary_key(column)
12
+ spec = super
13
+ spec.except!(:precision) if prepare_column_options(column) == DEFAULT_PRIMARY_KEY_COLUMN_SPEC
14
+ spec
15
+ end
8
16
 
9
17
  def tables(stream)
10
18
  # do not include materialized views in schema dump - they should be created separately after schema creation
@@ -51,6 +59,7 @@ module ActiveRecord #:nodoc:
51
59
  else
52
60
  statement_parts = [ ("add_context_index " + remove_prefix_and_suffix(table).inspect) ]
53
61
  statement_parts << index.columns.inspect
62
+ statement_parts << ("sync: " + $1.inspect) if index.parameters =~ /SYNC\((.*?)\)/
54
63
  statement_parts << ("name: " + index.name.inspect)
55
64
  end
56
65
  else
@@ -72,7 +81,7 @@ module ActiveRecord #:nodoc:
72
81
  index_statements = indexes.map do |index|
73
82
  " t.index #{index_parts(index).join(', ')}" unless index.type == "CTXSYS.CONTEXT"
74
83
  end
75
- stream.puts index_statements.sort.join("\n")
84
+ stream.puts index_statements.compact.sort.join("\n")
76
85
  end
77
86
  end
78
87
 
@@ -107,7 +116,10 @@ module ActiveRecord #:nodoc:
107
116
  tbl.print ", primary_key: #{pk.inspect}" unless pk == "id"
108
117
  pkcol = columns.detect { |c| c.name == pk }
109
118
  pkcolspec = column_spec_for_primary_key(pkcol)
110
- if pkcolspec.present?
119
+ unless pkcolspec.empty?
120
+ if pkcolspec != pkcolspec.slice(:id, :default)
121
+ pkcolspec = { id: { type: pkcolspec.delete(:id), **pkcolspec }.compact }
122
+ end
111
123
  tbl.print ", #{format_colspec(pkcolspec)}"
112
124
  end
113
125
  when Array
@@ -168,7 +180,7 @@ module ActiveRecord #:nodoc:
168
180
 
169
181
  def extract_expression_for_virtual_column(column)
170
182
  column_name = column.name
171
- @connection.select_value(<<~SQL.squish, "Table comment", [bind_string("table_name", table_name.upcase), bind_string("column_name", column_name.upcase)]).inspect
183
+ @connection.select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name.upcase), bind_string("column_name", column_name.upcase)]).inspect
172
184
  select data_default from all_tab_columns
173
185
  where owner = SYS_CONTEXT('userenv', 'current_schema')
174
186
  and table_name = :table_name
@@ -11,7 +11,7 @@ module ActiveRecord
11
11
  # see: abstract/schema_statements.rb
12
12
 
13
13
  def tables #:nodoc:
14
- select_values(<<~SQL.squish, "tables")
14
+ select_values(<<~SQL.squish, "SCHEMA")
15
15
  SELECT DECODE(table_name, UPPER(table_name), LOWER(table_name), table_name)
16
16
  FROM all_tables
17
17
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
@@ -43,7 +43,7 @@ module ActiveRecord
43
43
  table_owner, table_name = default_owner, real_name
44
44
  end
45
45
 
46
- select_values(<<~SQL.squish, "table exists", [bind_string("owner", table_owner), bind_string("table_name", table_name)]).any?
46
+ select_values(<<~SQL.squish, "SCHEMA", [bind_string("owner", table_owner), bind_string("table_name", table_name)]).any?
47
47
  SELECT owner, table_name
48
48
  FROM all_tables
49
49
  WHERE owner = :owner
@@ -59,20 +59,20 @@ module ActiveRecord
59
59
  end
60
60
 
61
61
  def views # :nodoc:
62
- select_values(<<~SQL.squish, "views")
62
+ select_values(<<~SQL.squish, "SCHEMA")
63
63
  SELECT LOWER(view_name) FROM all_views WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
64
64
  SQL
65
65
  end
66
66
 
67
67
  def materialized_views #:nodoc:
68
- select_values(<<~SQL.squish, "materialized views")
68
+ select_values(<<~SQL.squish, "SCHEMA")
69
69
  SELECT LOWER(mview_name) FROM all_mviews WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
70
70
  SQL
71
71
  end
72
72
 
73
73
  # get synonyms for schema dump
74
74
  def synonyms
75
- result = select_all(<<~SQL.squish, "synonyms")
75
+ result = select_all(<<~SQL.squish, "SCHEMA")
76
76
  SELECT synonym_name, table_owner, table_name
77
77
  FROM all_synonyms where owner = SYS_CONTEXT('userenv', 'current_schema')
78
78
  SQL
@@ -87,7 +87,7 @@ module ActiveRecord
87
87
  (_owner, table_name) = @connection.describe(table_name)
88
88
  default_tablespace_name = default_tablespace
89
89
 
90
- result = select_all(<<~SQL.squish, "indexes", [bind_string("table_name", table_name)])
90
+ result = select_all(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
91
91
  SELECT LOWER(i.table_name) AS table_name, LOWER(i.index_name) AS index_name, i.uniqueness,
92
92
  i.index_type, i.ityp_owner, i.ityp_name, i.parameters,
93
93
  LOWER(i.tablespace_name) AS tablespace_name,
@@ -117,7 +117,7 @@ module ActiveRecord
117
117
  statement_parameters = nil
118
118
  if row["index_type"] == "DOMAIN" && row["ityp_owner"] == "CTXSYS" && row["ityp_name"] == "CONTEXT"
119
119
  procedure_name = default_datastore_procedure(row["index_name"])
120
- source = select_values(<<~SQL.squish, "procedure", [bind_string("procedure_name", procedure_name.upcase)]).join
120
+ source = select_values(<<~SQL.squish, "SCHEMA", [bind_string("procedure_name", procedure_name.upcase)]).join
121
121
  SELECT text
122
122
  FROM all_source
123
123
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
@@ -196,19 +196,19 @@ module ActiveRecord
196
196
  # t.string :last_name, :comment => “Surname”
197
197
  # end
198
198
 
199
- def create_table(table_name, **options)
200
- create_sequence = options[:id] != false
201
- td = create_table_definition table_name, options
199
+ def create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **options)
200
+ create_sequence = id != false
201
+ td = create_table_definition(
202
+ table_name, **options.extract!(:temporary, :options, :as, :comment, :tablespace, :organization)
203
+ )
202
204
 
203
- if options[:id] != false && !options[:as]
204
- pk = options.fetch(:primary_key) do
205
- Base.get_primary_key table_name.to_s.singularize
206
- end
205
+ if id && !td.as
206
+ pk = primary_key || Base.get_primary_key(table_name.to_s.singularize)
207
207
 
208
208
  if pk.is_a?(Array)
209
209
  td.primary_keys pk
210
210
  else
211
- td.primary_key pk, options.fetch(:id, :primary_key), options
211
+ td.primary_key pk, id, **options
212
212
  end
213
213
  end
214
214
 
@@ -226,8 +226,10 @@ module ActiveRecord
226
226
  yield td if block_given?
227
227
  create_sequence = create_sequence || td.create_sequence
228
228
 
229
- if options[:force] && data_source_exists?(table_name)
230
- drop_table(table_name, options)
229
+ if force && data_source_exists?(table_name)
230
+ drop_table(table_name, force: force, if_exists: true)
231
+ else
232
+ schema_cache.clear_data_source_cache!(table_name.to_s)
231
233
  end
232
234
 
233
235
  execute schema_creation.accept td
@@ -235,14 +237,14 @@ module ActiveRecord
235
237
  create_sequence_and_trigger(table_name, options) if create_sequence
236
238
 
237
239
  if supports_comments? && !supports_comments_in_create?
238
- if table_comment = options[:comment].presence
240
+ if table_comment = td.comment.presence
239
241
  change_table_comment(table_name, table_comment)
240
242
  end
241
243
  td.columns.each do |column|
242
244
  change_column_comment(table_name, column.name, column.comment) if column.comment.present?
243
245
  end
244
246
  end
245
- td.indexes.each { |c, o| add_index table_name, c, o }
247
+ td.indexes.each { |c, o| add_index table_name, c, **o }
246
248
 
247
249
  rebuild_primary_key_index_to_default_tablespace(table_name, options)
248
250
  end
@@ -251,13 +253,16 @@ module ActiveRecord
251
253
  if new_name.to_s.length > DatabaseLimits::IDENTIFIER_MAX_LENGTH
252
254
  raise ArgumentError, "New table name '#{new_name}' is too long; the limit is #{DatabaseLimits::IDENTIFIER_MAX_LENGTH} characters"
253
255
  end
256
+ schema_cache.clear_data_source_cache!(table_name.to_s)
257
+ schema_cache.clear_data_source_cache!(new_name.to_s)
254
258
  execute "RENAME #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
255
259
  execute "RENAME #{quote_table_name("#{table_name}_seq")} TO #{default_sequence_name(new_name)}" rescue nil
256
260
 
257
261
  rename_table_indexes(table_name, new_name)
258
262
  end
259
263
 
260
- def drop_table(table_name, options = {}) #:nodoc:
264
+ def drop_table(table_name, **options) #:nodoc:
265
+ schema_cache.clear_data_source_cache!(table_name.to_s)
261
266
  execute "DROP TABLE #{quote_table_name(table_name)}#{' CASCADE CONSTRAINTS' if options[:force] == :cascade}"
262
267
  seq_name = options[:sequence_name] || default_sequence_name(table_name)
263
268
  execute "DROP SEQUENCE #{quote_table_name(seq_name)}" rescue nil
@@ -287,8 +292,8 @@ module ActiveRecord
287
292
  end
288
293
  end
289
294
 
290
- def add_index(table_name, column_name, options = {}) #:nodoc:
291
- index_name, index_type, quoted_column_names, tablespace, index_options = add_index_options(table_name, column_name, options)
295
+ def add_index(table_name, column_name, **options) #:nodoc:
296
+ index_name, index_type, quoted_column_names, tablespace, index_options = add_index_options(table_name, column_name, **options)
292
297
  execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})#{tablespace} #{index_options}"
293
298
  if index_type == "UNIQUE"
294
299
  unless /\(.*\)/.match?(quoted_column_names)
@@ -306,13 +311,11 @@ module ActiveRecord
306
311
  index_type = options[:unique] ? "UNIQUE" : ""
307
312
  index_name = options[:name].to_s if options.key?(:name)
308
313
  tablespace = tablespace_for(:index, options[:tablespace])
309
- max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length
310
- # TODO: This option is used for NOLOGGING, needs better argumetn name
314
+ # TODO: This option is used for NOLOGGING, needs better argument name
311
315
  index_options = options[:options]
312
316
 
313
- if index_name.to_s.length > max_index_length
314
- raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{max_index_length} characters"
315
- end
317
+ validate_index_length!(table_name, index_name, options.fetch(:internal, false))
318
+
316
319
  if table_exists?(table_name) && index_name_exists?(table_name, index_name)
317
320
  raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
318
321
  end
@@ -323,8 +326,8 @@ module ActiveRecord
323
326
 
324
327
  # Remove the given index from the table.
325
328
  # Gives warning if index does not exist
326
- def remove_index(table_name, options = {}) #:nodoc:
327
- index_name = index_name_for_remove(table_name, options)
329
+ def remove_index(table_name, column_name = nil, **options) #:nodoc:
330
+ index_name = index_name_for_remove(table_name, column_name, options)
328
331
  # TODO: It should execute only when index_type == "UNIQUE"
329
332
  execute "ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{quote_column_name(index_name)}" rescue nil
330
333
  execute "DROP INDEX #{quote_column_name(index_name)}"
@@ -361,7 +364,7 @@ module ActiveRecord
361
364
  # Will always query database and not index cache.
362
365
  def index_name_exists?(table_name, index_name)
363
366
  (_owner, table_name) = @connection.describe(table_name)
364
- result = select_value(<<~SQL.squish, "index name exists")
367
+ result = select_value(<<~SQL.squish, "SCHEMA")
365
368
  SELECT 1 FROM all_indexes i
366
369
  WHERE i.owner = SYS_CONTEXT('userenv', 'current_schema')
367
370
  AND i.table_owner = SYS_CONTEXT('userenv', 'current_schema')
@@ -402,14 +405,14 @@ module ActiveRecord
402
405
  execute "DROP SYNONYM #{quote_table_name(name)}"
403
406
  end
404
407
 
405
- def add_reference(table_name, *args)
406
- OracleEnhanced::ReferenceDefinition.new(*args).add_to(update_table_definition(table_name, self))
408
+ def add_reference(table_name, ref_name, **options)
409
+ OracleEnhanced::ReferenceDefinition.new(ref_name, **options).add_to(update_table_definition(table_name, self))
407
410
  end
408
411
 
409
- def add_column(table_name, column_name, type, options = {}) #:nodoc:
412
+ def add_column(table_name, column_name, type, **options) #:nodoc:
410
413
  type = aliased_types(type.to_s, type)
411
414
  at = create_alter_table table_name
412
- at.add_column(column_name, type, options)
415
+ at.add_column(column_name, type, **options)
413
416
  add_column_sql = schema_creation.accept at
414
417
  add_column_sql << tablespace_for((type_to_sql(type).downcase.to_sym), nil, table_name, column_name)
415
418
  execute add_column_sql
@@ -440,7 +443,7 @@ module ActiveRecord
440
443
  change_column table_name, column_name, column.sql_type, null: null
441
444
  end
442
445
 
443
- def change_column(table_name, column_name, type, options = {}) #:nodoc:
446
+ def change_column(table_name, column_name, type, **options) #:nodoc:
444
447
  column = column_for(table_name, column_name)
445
448
 
446
449
  # remove :null option if its value is the same as current column definition
@@ -453,7 +456,7 @@ module ActiveRecord
453
456
  end
454
457
 
455
458
  td = create_table_definition(table_name)
456
- cd = td.new_column_definition(column.name, type, options)
459
+ cd = td.new_column_definition(column.name, type, **options)
457
460
  change_column_stmt = schema_creation.accept cd
458
461
  change_column_stmt << tablespace_for((type_to_sql(type).downcase.to_sym), nil, options[:table_name], options[:column_name]) if type
459
462
  change_column_sql = "ALTER TABLE #{quote_table_name(table_name)} MODIFY #{change_column_stmt}"
@@ -494,8 +497,9 @@ module ActiveRecord
494
497
  end
495
498
 
496
499
  def table_comment(table_name) #:nodoc:
500
+ # TODO
497
501
  (_owner, table_name) = @connection.describe(table_name)
498
- select_value(<<~SQL.squish, "Table comment", [bind_string("table_name", table_name)])
502
+ select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
499
503
  SELECT comments FROM all_tab_comments
500
504
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
501
505
  AND table_name = :table_name
@@ -511,7 +515,7 @@ module ActiveRecord
511
515
  def column_comment(table_name, column_name) #:nodoc:
512
516
  # TODO: it does not exist in Abstract adapter
513
517
  (_owner, table_name) = @connection.describe(table_name)
514
- select_value(<<~SQL.squish, "Column comment", [bind_string("table_name", table_name), bind_string("column_name", column_name.upcase)])
518
+ select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name), bind_string("column_name", column_name.upcase)])
515
519
  SELECT comments FROM all_col_comments
516
520
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
517
521
  AND table_name = :table_name
@@ -528,7 +532,7 @@ module ActiveRecord
528
532
  end
529
533
 
530
534
  def tablespace(table_name)
531
- select_value(<<~SQL.squish, "tablespace")
535
+ select_value(<<~SQL.squish, "SCHEMA")
532
536
  SELECT tablespace_name
533
537
  FROM all_tables
534
538
  WHERE table_name='#{table_name.to_s.upcase}'
@@ -540,7 +544,7 @@ module ActiveRecord
540
544
  def foreign_keys(table_name) #:nodoc:
541
545
  (_owner, desc_table_name) = @connection.describe(table_name)
542
546
 
543
- fk_info = select_all(<<~SQL.squish, "Foreign Keys", [bind_string("desc_table_name", desc_table_name)])
547
+ fk_info = select_all(<<~SQL.squish, "SCHEMA", [bind_string("desc_table_name", desc_table_name)])
544
548
  SELECT r.table_name to_table
545
549
  ,rc.column_name references_column
546
550
  ,cc.column_name
@@ -582,7 +586,7 @@ module ActiveRecord
582
586
  # REFERENTIAL INTEGRITY ====================================
583
587
 
584
588
  def disable_referential_integrity(&block) #:nodoc:
585
- old_constraints = select_all(<<~SQL.squish, "Foreign Keys to disable and enable")
589
+ old_constraints = select_all(<<~SQL.squish, "SCHEMA")
586
590
  SELECT constraint_name, owner, table_name
587
591
  FROM all_constraints
588
592
  WHERE constraint_type = 'R'
@@ -614,13 +618,12 @@ module ActiveRecord
614
618
  end
615
619
 
616
620
  private
617
-
618
621
  def schema_creation
619
622
  OracleEnhanced::SchemaCreation.new self
620
623
  end
621
624
 
622
- def create_table_definition(*args)
623
- OracleEnhanced::TableDefinition.new(self, *args)
625
+ def create_table_definition(name, **options)
626
+ OracleEnhanced::TableDefinition.new(self, name, **options)
624
627
  end
625
628
 
626
629
  def new_column_from_field(table_name, field)
@@ -642,7 +645,7 @@ module ActiveRecord
642
645
  # If a default contains a newline these cleanup regexes need to
643
646
  # match newlines.
644
647
  field["data_default"].sub!(/^'(.*)'$/m, '\1')
645
- field["data_default"] = nil if field["data_default"] =~ /^(null|empty_[bc]lob\(\))$/i
648
+ field["data_default"] = nil if /^(null|empty_[bc]lob\(\))$/i.match?(field["data_default"])
646
649
  # TODO: Needs better fix to fallback "N" to false
647
650
  field["data_default"] = false if field["data_default"] == "N" && OracleEnhancedAdapter.emulate_booleans_from_strings
648
651
  end