activerecord-oracle_enhanced-adapter 7.0.3 → 7.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +24 -0
  3. data/README.md +0 -1
  4. data/VERSION +1 -1
  5. data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +5 -0
  6. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +1 -1
  7. data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +2 -2
  8. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +26 -21
  9. data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +15 -2
  10. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +9 -2
  11. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +3 -3
  12. data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +24 -15
  13. data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +3 -3
  14. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +2 -2
  15. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +1 -1
  16. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +5 -0
  17. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +1 -1
  18. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +22 -22
  19. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +17 -17
  20. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +71 -28
  21. data/lib/activerecord-oracle_enhanced-adapter.rb +8 -0
  22. data/lib/arel/visitors/oracle.rb +6 -3
  23. data/lib/arel/visitors/oracle12.rb +6 -5
  24. data/lib/arel/visitors/oracle_common.rb +46 -0
  25. data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +24 -5
  26. data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +7 -2
  27. data/spec/active_record/connection_adapters/oracle_enhanced/dbms_output_spec.rb +2 -2
  28. data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +3 -0
  29. data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +25 -15
  30. data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +15 -18
  31. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +14 -10
  32. data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +2 -2
  33. data/spec/active_record/oracle_enhanced/type/character_string_spec.rb +24 -0
  34. data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +4 -2
  35. data/spec/active_record/oracle_enhanced/type/integer_spec.rb +8 -0
  36. data/spec/active_record/oracle_enhanced/type/national_character_text_spec.rb +3 -3
  37. data/spec/active_record/oracle_enhanced/type/raw_spec.rb +15 -0
  38. data/spec/active_record/oracle_enhanced/type/text_spec.rb +18 -3
  39. data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +5 -1
  40. data/spec/spec_config.yaml.template +2 -2
  41. data/spec/spec_helper.rb +14 -3
  42. metadata +8 -6
@@ -12,7 +12,7 @@ module ActiveRecord
12
12
 
13
13
  def tables # :nodoc:
14
14
  select_values(<<~SQL.squish, "SCHEMA")
15
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
15
+ SELECT
16
16
  DECODE(table_name, UPPER(table_name), LOWER(table_name), table_name)
17
17
  FROM all_tables
18
18
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
@@ -45,7 +45,7 @@ module ActiveRecord
45
45
  end
46
46
 
47
47
  select_values(<<~SQL.squish, "SCHEMA", [bind_string("owner", table_owner), bind_string("table_name", table_name)]).any?
48
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ owner, table_name
48
+ SELECT owner, table_name
49
49
  FROM all_tables
50
50
  WHERE owner = :owner
51
51
  AND table_name = :table_name
@@ -53,7 +53,7 @@ module ActiveRecord
53
53
  end
54
54
 
55
55
  def data_source_exists?(table_name)
56
- (_owner, _table_name) = @connection.describe(table_name)
56
+ (_owner, _table_name) = _connection.describe(table_name)
57
57
  true
58
58
  rescue
59
59
  false
@@ -61,14 +61,14 @@ module ActiveRecord
61
61
 
62
62
  def views # :nodoc:
63
63
  select_values(<<~SQL.squish, "SCHEMA")
64
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
64
+ SELECT
65
65
  LOWER(view_name) FROM all_views WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
66
66
  SQL
67
67
  end
68
68
 
69
69
  def materialized_views # :nodoc:
70
70
  select_values(<<~SQL.squish, "SCHEMA")
71
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
71
+ SELECT
72
72
  LOWER(mview_name) FROM all_mviews WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
73
73
  SQL
74
74
  end
@@ -87,11 +87,11 @@ module ActiveRecord
87
87
  end
88
88
 
89
89
  def indexes(table_name) # :nodoc:
90
- (_owner, table_name) = @connection.describe(table_name)
90
+ (_owner, table_name) = _connection.describe(table_name)
91
91
  default_tablespace_name = default_tablespace
92
92
 
93
93
  result = select_all(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
94
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ LOWER(i.table_name) AS table_name, LOWER(i.index_name) AS index_name, i.uniqueness,
94
+ SELECT LOWER(i.table_name) AS table_name, LOWER(i.index_name) AS index_name, i.uniqueness,
95
95
  i.index_type, i.ityp_owner, i.ityp_name, i.parameters,
96
96
  LOWER(i.tablespace_name) AS tablespace_name,
97
97
  LOWER(c.column_name) AS column_name, e.column_expression,
@@ -121,7 +121,7 @@ module ActiveRecord
121
121
  if row["index_type"] == "DOMAIN" && row["ityp_owner"] == "CTXSYS" && row["ityp_name"] == "CONTEXT"
122
122
  procedure_name = default_datastore_procedure(row["index_name"])
123
123
  source = select_values(<<~SQL.squish, "SCHEMA", [bind_string("procedure_name", procedure_name.upcase)]).join
124
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ text
124
+ SELECT text
125
125
  FROM all_source
126
126
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
127
127
  AND name = :procedure_name
@@ -276,7 +276,7 @@ module ActiveRecord
276
276
  end
277
277
 
278
278
  def insert_versions_sql(versions) # :nodoc:
279
- sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
279
+ sm_table = quote_table_name(ActiveRecord::Base.connection.schema_migration.table_name)
280
280
 
281
281
  if supports_multi_insert?
282
282
  versions.inject(+"INSERT ALL\n") { |sql, version|
@@ -300,7 +300,7 @@ module ActiveRecord
300
300
  execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})#{tablespace} #{index_options}"
301
301
  if index_type == "UNIQUE"
302
302
  unless /\(.*\)/.match?(quoted_column_names)
303
- execute "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{quote_column_name(index_name)} #{index_type} (#{quoted_column_names})"
303
+ execute "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{quote_column_name(index_name)} #{index_type} (#{quoted_column_names}) USING INDEX #{quote_column_name(index_name)}"
304
304
  end
305
305
  end
306
306
  end
@@ -368,9 +368,9 @@ module ActiveRecord
368
368
  #
369
369
  # Will always query database and not index cache.
370
370
  def index_name_exists?(table_name, index_name)
371
- (_owner, table_name) = @connection.describe(table_name)
371
+ (_owner, table_name) = _connection.describe(table_name)
372
372
  result = select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name), bind_string("index_name", index_name.to_s.upcase)])
373
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ 1 FROM all_indexes i
373
+ SELECT 1 FROM all_indexes i
374
374
  WHERE i.owner = SYS_CONTEXT('userenv', 'current_schema')
375
375
  AND i.table_owner = SYS_CONTEXT('userenv', 'current_schema')
376
376
  AND i.table_name = :table_name
@@ -511,9 +511,9 @@ module ActiveRecord
511
511
 
512
512
  def table_comment(table_name) # :nodoc:
513
513
  # TODO
514
- (_owner, table_name) = @connection.describe(table_name)
514
+ (_owner, table_name) = _connection.describe(table_name)
515
515
  select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
516
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ comments FROM all_tab_comments
516
+ SELECT comments FROM all_tab_comments
517
517
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
518
518
  AND table_name = :table_name
519
519
  SQL
@@ -527,9 +527,9 @@ module ActiveRecord
527
527
 
528
528
  def column_comment(table_name, column_name) # :nodoc:
529
529
  # TODO: it does not exist in Abstract adapter
530
- (_owner, table_name) = @connection.describe(table_name)
530
+ (_owner, table_name) = _connection.describe(table_name)
531
531
  select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name), bind_string("column_name", column_name.upcase)])
532
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ comments FROM all_col_comments
532
+ SELECT comments FROM all_col_comments
533
533
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
534
534
  AND table_name = :table_name
535
535
  AND column_name = :column_name
@@ -546,7 +546,7 @@ module ActiveRecord
546
546
 
547
547
  def tablespace(table_name)
548
548
  select_value(<<~SQL.squish, "SCHEMA")
549
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ tablespace_name
549
+ SELECT tablespace_name
550
550
  FROM all_tables
551
551
  WHERE table_name='#{table_name.to_s.upcase}'
552
552
  AND owner = SYS_CONTEXT('userenv', 'current_schema')
@@ -555,10 +555,10 @@ module ActiveRecord
555
555
 
556
556
  # get table foreign keys for schema dump
557
557
  def foreign_keys(table_name) # :nodoc:
558
- (_owner, desc_table_name) = @connection.describe(table_name)
558
+ (_owner, desc_table_name) = _connection.describe(table_name)
559
559
 
560
560
  fk_info = select_all(<<~SQL.squish, "SCHEMA", [bind_string("desc_table_name", desc_table_name)])
561
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ r.table_name to_table
561
+ SELECT r.table_name to_table
562
562
  ,rc.column_name references_column
563
563
  ,cc.column_name
564
564
  ,c.constraint_name name
@@ -600,7 +600,7 @@ module ActiveRecord
600
600
 
601
601
  def disable_referential_integrity(&block) # :nodoc:
602
602
  old_constraints = select_all(<<~SQL.squish, "SCHEMA")
603
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ constraint_name, owner, table_name
603
+ SELECT constraint_name, owner, table_name
604
604
  FROM all_constraints
605
605
  WHERE constraint_type = 'R'
606
606
  AND status = 'ENABLED'
@@ -639,7 +639,7 @@ module ActiveRecord
639
639
  OracleEnhanced::TableDefinition.new(self, name, **options)
640
640
  end
641
641
 
642
- def new_column_from_field(table_name, field)
642
+ def new_column_from_field(table_name, field, definitions)
643
643
  limit, scale = field["limit"], field["scale"]
644
644
  if limit || scale
645
645
  field["sql_type"] += "(#{(limit || 38).to_i}" + ((scale = scale.to_i) > 0 ? ",#{scale})" : ")")
@@ -715,7 +715,7 @@ module ActiveRecord
715
715
  return unless tablespace
716
716
 
717
717
  index_name = select_value(<<~SQL.squish, "Index name for primary key", [bind_string("table_name", table_name.upcase)])
718
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ index_name FROM all_constraints
718
+ SELECT index_name FROM all_constraints
719
719
  WHERE table_name = :table_name
720
720
  AND constraint_type = 'P'
721
721
  AND owner = SYS_CONTEXT('userenv', 'current_schema')
@@ -9,7 +9,7 @@ module ActiveRecord # :nodoc:
9
9
 
10
10
  def structure_dump # :nodoc:
11
11
  sequences = select(<<~SQL.squish, "SCHEMA")
12
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
12
+ SELECT
13
13
  sequence_name, min_value, max_value, increment_by, order_flag, cycle_flag
14
14
  FROM all_sequences
15
15
  where sequence_owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY 1
@@ -19,7 +19,7 @@ module ActiveRecord # :nodoc:
19
19
  "CREATE SEQUENCE #{quote_table_name(result["sequence_name"])} MINVALUE #{result["min_value"]} MAXVALUE #{result["max_value"]} INCREMENT BY #{result["increment_by"]} #{result["order_flag"] == 'Y' ? "ORDER" : "NOORDER"} #{result["cycle_flag"] == 'Y' ? "CYCLE" : "NOCYCLE"}"
20
20
  end
21
21
  tables = select_values(<<~SQL.squish, "SCHEMA")
22
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ table_name FROM all_tables t
22
+ SELECT table_name FROM all_tables t
23
23
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema') AND secondary = 'N'
24
24
  AND NOT EXISTS (SELECT mv.mview_name FROM all_mviews mv
25
25
  WHERE mv.owner = t.owner AND mv.mview_name = t.table_name)
@@ -31,7 +31,7 @@ module ActiveRecord # :nodoc:
31
31
  virtual_columns = virtual_columns_for(table_name) if supports_virtual_columns?
32
32
  ddl = +"CREATE#{ ' GLOBAL TEMPORARY' if temporary_table?(table_name)} TABLE \"#{table_name}\" (\n"
33
33
  columns = select_all(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
34
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ column_name, data_type, data_length, char_used, char_length,
34
+ SELECT column_name, data_type, data_length, char_used, char_length,
35
35
  data_precision, data_scale, data_default, nullable
36
36
  FROM all_tab_columns
37
37
  WHERE table_name = :table_name
@@ -92,7 +92,7 @@ module ActiveRecord # :nodoc:
92
92
  def structure_dump_primary_key(table) # :nodoc:
93
93
  opts = { name: "", cols: [] }
94
94
  pks = select_all(<<~SQL.squish, "SCHEMA")
95
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ a.constraint_name, a.column_name, a.position
95
+ SELECT a.constraint_name, a.column_name, a.position
96
96
  FROM all_cons_columns a
97
97
  JOIN all_constraints c
98
98
  ON a.constraint_name = c.constraint_name
@@ -111,7 +111,7 @@ module ActiveRecord # :nodoc:
111
111
  def structure_dump_unique_keys(table) # :nodoc:
112
112
  keys = {}
113
113
  uks = select_all(<<~SQL.squish, "SCHEMA")
114
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ a.constraint_name, a.column_name, a.position
114
+ SELECT a.constraint_name, a.column_name, a.position
115
115
  FROM all_cons_columns a
116
116
  JOIN all_constraints c
117
117
  ON a.constraint_name = c.constraint_name
@@ -147,7 +147,7 @@ module ActiveRecord # :nodoc:
147
147
 
148
148
  def structure_dump_fk_constraints # :nodoc:
149
149
  foreign_keys = select_all(<<~SQL.squish, "SCHEMA")
150
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ table_name FROM all_tables
150
+ SELECT table_name FROM all_tables
151
151
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY 1
152
152
  SQL
153
153
  fks = foreign_keys.map do |table|
@@ -175,7 +175,7 @@ module ActiveRecord # :nodoc:
175
175
  def structure_dump_column_comments(table_name)
176
176
  comments = []
177
177
  columns = select_values(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
178
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ column_name FROM all_tab_columns
178
+ SELECT column_name FROM all_tab_columns
179
179
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
180
180
  AND table_name = :table_name ORDER BY column_id
181
181
  SQL
@@ -210,7 +210,7 @@ module ActiveRecord # :nodoc:
210
210
  def structure_dump_db_stored_code # :nodoc:
211
211
  structure = []
212
212
  all_source = select_all(<<~SQL.squish, "SCHEMA")
213
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ DISTINCT name, type
213
+ SELECT DISTINCT name, type
214
214
  FROM all_source
215
215
  WHERE type IN ('PROCEDURE', 'PACKAGE', 'PACKAGE BODY', 'FUNCTION', 'TRIGGER', 'TYPE')
216
216
  AND name NOT LIKE 'BIN$%'
@@ -219,7 +219,7 @@ module ActiveRecord # :nodoc:
219
219
  all_source.each do |source|
220
220
  ddl = +"CREATE OR REPLACE \n"
221
221
  texts = select_all(<<~SQL.squish, "all source at structure dump", [bind_string("source_name", source["name"]), bind_string("source_type", source["type"])])
222
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ text
222
+ SELECT text
223
223
  FROM all_source
224
224
  WHERE name = :source_name
225
225
  AND type = :source_type
@@ -242,7 +242,7 @@ module ActiveRecord # :nodoc:
242
242
  def structure_dump_views # :nodoc:
243
243
  structure = []
244
244
  views = select_all(<<~SQL.squish, "SCHEMA")
245
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ view_name, text FROM all_views
245
+ SELECT view_name, text FROM all_views
246
246
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY view_name ASC
247
247
  SQL
248
248
  views.each do |view|
@@ -254,7 +254,7 @@ module ActiveRecord # :nodoc:
254
254
  def structure_dump_synonyms # :nodoc:
255
255
  structure = []
256
256
  synonyms = select_all(<<~SQL.squish, "SCHEMA")
257
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ owner, synonym_name, table_name, table_owner
257
+ SELECT owner, synonym_name, table_name, table_owner
258
258
  FROM all_synonyms
259
259
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
260
260
  SQL
@@ -267,14 +267,14 @@ module ActiveRecord # :nodoc:
267
267
 
268
268
  def structure_drop # :nodoc:
269
269
  sequences = select_values(<<~SQL.squish, "SCHEMA")
270
- SELECT/*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
270
+ SELECT
271
271
  sequence_name FROM all_sequences where sequence_owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY 1
272
272
  SQL
273
273
  statements = sequences.map do |seq|
274
274
  "DROP SEQUENCE \"#{seq}\""
275
275
  end
276
276
  tables = select_values(<<~SQL.squish, "SCHEMA")
277
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ table_name from all_tables t
277
+ SELECT table_name from all_tables t
278
278
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema') AND secondary = 'N'
279
279
  AND NOT EXISTS (SELECT mv.mview_name FROM all_mviews mv
280
280
  WHERE mv.owner = t.owner AND mv.mview_name = t.table_name)
@@ -290,7 +290,7 @@ module ActiveRecord # :nodoc:
290
290
 
291
291
  def temp_table_drop # :nodoc:
292
292
  temporary_tables = select_values(<<~SQL.squish, "SCHEMA")
293
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ table_name FROM all_tables
293
+ SELECT table_name FROM all_tables
294
294
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
295
295
  AND secondary = 'N' AND temporary = 'Y' ORDER BY 1
296
296
  SQL
@@ -324,7 +324,7 @@ module ActiveRecord # :nodoc:
324
324
  # return [{'column_name' => 'FOOS', 'data_default' => '...'}, ...]
325
325
  def virtual_columns_for(table)
326
326
  select_all(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table.upcase)])
327
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ column_name, data_default
327
+ SELECT column_name, data_default
328
328
  FROM all_tab_cols
329
329
  WHERE virtual_column = 'YES'
330
330
  AND owner = SYS_CONTEXT('userenv', 'current_schema')
@@ -335,7 +335,7 @@ module ActiveRecord # :nodoc:
335
335
  def drop_sql_for_feature(type)
336
336
  short_type = type == "materialized view" ? "mview" : type
337
337
  features = select_values(<<~SQL.squish, "SCHEMA")
338
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ #{short_type}_name FROM all_#{short_type.tableize}
338
+ SELECT #{short_type}_name FROM all_#{short_type.tableize}
339
339
  where owner = SYS_CONTEXT('userenv', 'current_schema')
340
340
  SQL
341
341
  statements = features.map do |name|
@@ -346,7 +346,7 @@ module ActiveRecord # :nodoc:
346
346
 
347
347
  def drop_sql_for_object(type)
348
348
  objects = select_values(<<~SQL.squish, "SCHEMA")
349
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ object_name FROM all_objects
349
+ SELECT object_name FROM all_objects
350
350
  WHERE object_type = '#{type.upcase}' and owner = SYS_CONTEXT('userenv', 'current_schema')
351
351
  SQL
352
352
  statements = objects.map do |name|
@@ -121,6 +121,12 @@ module ActiveRecord
121
121
  # * <tt>:tcp_keepalive</tt> - TCP keepalive is enabled for OCI client, defaults to true
122
122
  # * <tt>:tcp_keepalive_time</tt> - TCP keepalive time for OCI client, defaults to 600
123
123
  # * <tt>:jdbc_statement_cache_size</tt> - number of cached SQL cursors to keep open, disabled per default (for unpooled JDBC only)
124
+ # * <tt>:jdbc_connect_properties</tt> - Additional properties for establishing Oracle JDBC connection (for unpooled JDBC only)
125
+ # example to require encryption and checksumming for network connection:
126
+ # adapter: oracle_enhanced
127
+ # jdbc_connect_properties:
128
+ # 'oracle.net.encryption_client': REQUIRED
129
+ # 'oracle.net.crypto_checksum_client': REQUIRED
124
130
  #
125
131
  # Optionals NLS parameters:
126
132
  #
@@ -240,8 +246,10 @@ module ActiveRecord
240
246
  end
241
247
  end
242
248
 
243
- def initialize(connection, logger = nil, config = {}) # :nodoc:
244
- super(connection, logger, config)
249
+ def initialize(config_or_deprecated_connection, deprecated_logger = nil, deprecated_connection_options = nil, deprecated_config = nil) # :nodoc:
250
+ super(config_or_deprecated_connection, deprecated_logger, deprecated_connection_options, deprecated_config)
251
+
252
+ @raw_connection = ConnectionAdapters::OracleEnhanced::Connection.create(@config)
245
253
  @enable_dbms_output = false
246
254
  @do_not_prefetch_primary_key = {}
247
255
  @columns_cache = {}
@@ -269,6 +277,11 @@ module ActiveRecord
269
277
  end
270
278
  end
271
279
 
280
+ def return_value_after_insert?(column) # :nodoc:
281
+ # TODO: Return true if there this column will be populated (e.g by a sequence)
282
+ super
283
+ end
284
+
272
285
  def build_statement_pool
273
286
  StatementPool.new(self.class.type_cast_config_to_integer(@config[:statement_limit]))
274
287
  end
@@ -298,11 +311,12 @@ module ActiveRecord
298
311
  end
299
312
 
300
313
  def supports_fetch_first_n_rows_and_offset?
301
- if !use_old_oracle_visitor && database_version.first >= 12
302
- true
303
- else
304
- false
305
- end
314
+ false
315
+
316
+ # TODO: At this point the connection is not initialized yet,
317
+ # so `database_version` raises an error
318
+ #
319
+ # !use_old_oracle_visitor && database_version.first >= 12
306
320
  end
307
321
 
308
322
  def supports_datetime_with_precision?
@@ -426,12 +440,13 @@ module ActiveRecord
426
440
 
427
441
  def auto_retry=(value) # :nodoc:
428
442
  @auto_retry = value
429
- @connection.auto_retry = value if @connection
443
+ _connection.auto_retry = value if _connection
430
444
  end
431
445
 
432
446
  # return raw OCI8 or JDBC connection
433
447
  def raw_connection
434
- @connection.raw_connection
448
+ verify!
449
+ _connection.raw_connection
435
450
  end
436
451
 
437
452
  # Returns true if the connection is active.
@@ -440,19 +455,30 @@ module ActiveRecord
440
455
  # #active? method is also available, but that simply returns the
441
456
  # last known state, which isn't good enough if the connection has
442
457
  # gone stale since the last use.
443
- @connection.ping
458
+ _connection.ping
444
459
  rescue OracleEnhanced::ConnectionException
445
460
  false
446
461
  end
447
462
 
463
+ def reconnect
464
+ _connection.reset # tentative
465
+ rescue OracleEnhanced::ConnectionException
466
+ connect
467
+ end
468
+
448
469
  # Reconnects to the database.
449
470
  def reconnect! # :nodoc:
450
471
  super
451
- @connection.reset!
472
+ _connection.reset!
452
473
  rescue OracleEnhanced::ConnectionException => e
453
474
  @logger.warn "#{adapter_name} automatic reconnection failed: #{e.message}" if @logger
454
475
  end
455
476
 
477
+ def clear_cache!(*args, **kwargs)
478
+ super
479
+ self.class.clear_type_map!
480
+ end
481
+
456
482
  def reset!
457
483
  clear_cache!
458
484
  super
@@ -461,12 +487,12 @@ module ActiveRecord
461
487
  # Disconnects from the database.
462
488
  def disconnect! # :nodoc:
463
489
  super
464
- @connection.logoff rescue nil
490
+ _connection.logoff rescue nil
465
491
  end
466
492
 
467
493
  def discard!
468
494
  super
469
- @connection = nil
495
+ _connection = nil
470
496
  end
471
497
 
472
498
  # use in set_sequence_name to avoid fetching primary key value from sequence
@@ -491,7 +517,7 @@ module ActiveRecord
491
517
  table_name = table_name.to_s
492
518
  do_not_prefetch = @do_not_prefetch_primary_key[table_name]
493
519
  if do_not_prefetch.nil?
494
- owner, desc_table_name = @connection.describe(table_name)
520
+ owner, desc_table_name = _connection.describe(table_name)
495
521
  @do_not_prefetch_primary_key[table_name] = do_not_prefetch = !has_primary_key?(table_name, owner, desc_table_name)
496
522
  end
497
523
  !do_not_prefetch
@@ -554,16 +580,16 @@ module ActiveRecord
554
580
  # Default tablespace name of current user
555
581
  def default_tablespace
556
582
  select_value(<<~SQL.squish, "SCHEMA")
557
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ LOWER(default_tablespace) FROM user_users
583
+ SELECT LOWER(default_tablespace) FROM user_users
558
584
  WHERE username = SYS_CONTEXT('userenv', 'current_schema')
559
585
  SQL
560
586
  end
561
587
 
562
588
  def column_definitions(table_name)
563
- (owner, desc_table_name) = @connection.describe(table_name)
589
+ (owner, desc_table_name) = _connection.describe(table_name)
564
590
 
565
591
  select_all(<<~SQL.squish, "SCHEMA", [bind_string("owner", owner), bind_string("table_name", desc_table_name)])
566
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ cols.column_name AS name, cols.data_type AS sql_type,
592
+ SELECT cols.column_name AS name, cols.data_type AS sql_type,
567
593
  cols.data_default, cols.nullable, cols.virtual_column, cols.hidden_column,
568
594
  cols.data_type_owner AS sql_type_owner,
569
595
  DECODE(cols.data_type, 'NUMBER', data_precision,
@@ -592,10 +618,10 @@ module ActiveRecord
592
618
  # Find a table's primary key and sequence.
593
619
  # *Note*: Only primary key is implemented - sequence will be nil.
594
620
  def pk_and_sequence_for(table_name, owner = nil, desc_table_name = nil) # :nodoc:
595
- (owner, desc_table_name) = @connection.describe(table_name)
621
+ (owner, desc_table_name) = _connection.describe(table_name)
596
622
 
597
623
  seqs = select_values_forcing_binds(<<~SQL.squish, "SCHEMA", [bind_string("owner", owner), bind_string("sequence_name", default_sequence_name(desc_table_name))])
598
- select /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ us.sequence_name
624
+ select us.sequence_name
599
625
  from all_sequences us
600
626
  where us.sequence_owner = :owner
601
627
  and us.sequence_name = upper(:sequence_name)
@@ -603,7 +629,7 @@ module ActiveRecord
603
629
 
604
630
  # changed back from user_constraints to all_constraints for consistency
605
631
  pks = select_values_forcing_binds(<<~SQL.squish, "SCHEMA", [bind_string("owner", owner), bind_string("table_name", desc_table_name)])
606
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ cc.column_name
632
+ SELECT cc.column_name
607
633
  FROM all_constraints c, all_cons_columns cc
608
634
  WHERE c.owner = :owner
609
635
  AND c.table_name = :table_name
@@ -634,10 +660,10 @@ module ActiveRecord
634
660
  end
635
661
 
636
662
  def primary_keys(table_name) # :nodoc:
637
- (_owner, desc_table_name) = @connection.describe(table_name)
663
+ (_owner, desc_table_name) = _connection.describe(table_name)
638
664
 
639
665
  pks = select_values_forcing_binds(<<~SQL.squish, "SCHEMA", [bind_string("table_name", desc_table_name)])
640
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ cc.column_name
666
+ SELECT cc.column_name
641
667
  FROM all_constraints c, all_cons_columns cc
642
668
  WHERE c.owner = SYS_CONTEXT('userenv', 'current_schema')
643
669
  AND c.table_name = :table_name
@@ -667,7 +693,7 @@ module ActiveRecord
667
693
 
668
694
  def temporary_table?(table_name) # :nodoc:
669
695
  select_value_forcing_binds(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name.upcase)]) == "Y"
670
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
696
+ SELECT
671
697
  temporary FROM all_tables WHERE table_name = :table_name and owner = SYS_CONTEXT('userenv', 'current_schema')
672
698
  SQL
673
699
  end
@@ -678,8 +704,14 @@ module ActiveRecord
678
704
  alias table_alias_length max_identifier_length
679
705
  alias index_name_length max_identifier_length
680
706
 
707
+ # This is to ensure rails is not shortening the index name,
708
+ # in order to preserve the local shortening behavior.
709
+ def max_index_name_size
710
+ 128
711
+ end
712
+
681
713
  def get_database_version
682
- @connection.database_version
714
+ _connection.database_version
683
715
  end
684
716
 
685
717
  def check_version
@@ -690,7 +722,20 @@ module ActiveRecord
690
722
  end
691
723
  end
692
724
 
725
+ private def _connection
726
+ @unconfigured_connection || @raw_connection
727
+ end
728
+
693
729
  class << self
730
+ def type_map
731
+ @type_map ||= Type::TypeMap.new.tap { |m| initialize_type_map(m) }
732
+ @type_map
733
+ end
734
+
735
+ def clear_type_map!
736
+ @type_map = nil
737
+ end
738
+
694
739
  private
695
740
  def initialize_type_map(m)
696
741
  super
@@ -724,10 +769,8 @@ module ActiveRecord
724
769
  end
725
770
  end
726
771
 
727
- TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
728
-
729
772
  def type_map
730
- TYPE_MAP
773
+ self.class.type_map
731
774
  end
732
775
 
733
776
  def extract_value_from_default(default)
@@ -749,7 +792,7 @@ module ActiveRecord
749
792
  end
750
793
 
751
794
  def translate_exception(exception, message:, sql:, binds:) # :nodoc:
752
- case @connection.error_code(exception)
795
+ case _connection.error_code(exception)
753
796
  when 1
754
797
  RecordNotUnique.new(message, sql: sql, binds: binds)
755
798
  when 60
@@ -10,6 +10,14 @@ if defined?(Rails)
10
10
 
11
11
  ActiveSupport.on_load(:active_record) do
12
12
  require "active_record/connection_adapters/oracle_enhanced_adapter"
13
+
14
+ if ActiveRecord::ConnectionAdapters.respond_to?(:register)
15
+ ActiveRecord::ConnectionAdapters.register(
16
+ "oracle_enhanced",
17
+ "ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter",
18
+ "active_record/connection_adapters/oracle_enhanced_adapter"
19
+ )
20
+ end
13
21
  end
14
22
  end
15
23
  end
@@ -1,8 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "oracle_common"
4
+
3
5
  module Arel # :nodoc: all
4
6
  module Visitors
5
7
  class Oracle < Arel::Visitors::ToSql
8
+ include OracleCommon
9
+
6
10
  private
7
11
  def visit_Arel_Nodes_SelectStatement(o, collector)
8
12
  o = order_hacks(o)
@@ -92,7 +96,6 @@ module Arel # :nodoc: all
92
96
  def visit_Arel_Nodes_HomogeneousIn(o, collector)
93
97
  in_clause_length = @connection.in_clause_length
94
98
  values = o.casted_values.map { |v| @connection.quote(v) }
95
- column_name = quote_table_name(o.table_name) + "." + quote_column_name(o.column_name)
96
99
  operator =
97
100
  if o.type == :in
98
101
  " IN ("
@@ -101,7 +104,7 @@ module Arel # :nodoc: all
101
104
  end
102
105
 
103
106
  if !Array === values || values.length <= in_clause_length
104
- collector << column_name
107
+ visit o.left, collector
105
108
  collector << operator
106
109
 
107
110
  expr =
@@ -123,7 +126,7 @@ module Arel # :nodoc: all
123
126
  collector << "("
124
127
  values.each_slice(in_clause_length).each_with_index do |valuez, i|
125
128
  collector << separator unless i == 0
126
- collector << column_name
129
+ visit o.left, collector
127
130
  collector << operator
128
131
  collector << valuez.join(",")
129
132
  collector << ")"
@@ -1,8 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "oracle_common"
4
+
3
5
  module Arel # :nodoc: all
4
6
  module Visitors
5
7
  class Oracle12 < Arel::Visitors::ToSql
8
+ include OracleCommon
9
+
6
10
  private
7
11
  def visit_Arel_Nodes_SelectStatement(o, collector)
8
12
  # Oracle does not allow LIMIT clause with select for update
@@ -45,7 +49,6 @@ module Arel # :nodoc: all
45
49
  def visit_Arel_Nodes_HomogeneousIn(o, collector)
46
50
  in_clause_length = @connection.in_clause_length
47
51
  values = o.casted_values.map { |v| @connection.quote(v) }
48
- column_name = quote_table_name(o.table_name) + "." + quote_column_name(o.column_name)
49
52
  operator =
50
53
  if o.type == :in
51
54
  " IN ("
@@ -54,7 +57,7 @@ module Arel # :nodoc: all
54
57
  end
55
58
 
56
59
  if !Array === values || values.length <= in_clause_length
57
- collector << column_name
60
+ visit o.left, collector
58
61
  collector << operator
59
62
 
60
63
  expr =
@@ -76,15 +79,13 @@ module Arel # :nodoc: all
76
79
  collector << "("
77
80
  values.each_slice(in_clause_length).each_with_index do |valuez, i|
78
81
  collector << separator unless i == 0
79
- collector << column_name
82
+ visit o.left, collector
80
83
  collector << operator
81
84
  collector << valuez.join(",")
82
85
  collector << ")"
83
86
  end
84
87
  collector << ")"
85
88
  end
86
-
87
- collector
88
89
  end
89
90
 
90
91
  def visit_Arel_Nodes_UpdateStatement(o, collector)