activerecord-oracle_enhanced-adapter 6.0.5 → 6.1.2
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.
- checksums.yaml +4 -4
- data/History.md +109 -4
- data/README.md +12 -1
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +3 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +0 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +0 -9
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +9 -7
- data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +8 -9
- data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +0 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +3 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/lob.rb +1 -2
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +2 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +0 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +2 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +2 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +15 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +43 -40
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +19 -19
- data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +2 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +52 -33
- data/lib/active_record/type/oracle_enhanced/boolean.rb +0 -1
- data/lib/active_record/type/oracle_enhanced/integer.rb +0 -1
- data/lib/arel/visitors/oracle.rb +217 -0
- data/lib/arel/visitors/oracle12.rb +124 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +9 -3
- data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +5 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +0 -1
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +27 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +2 -2
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +122 -0
- data/spec/active_record/oracle_enhanced/type/national_character_string_spec.rb +4 -2
- data/spec/spec_config.yaml.template +2 -2
- data/spec/spec_helper.rb +13 -2
- metadata +22 -20
@@ -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, "
|
14
|
+
select_values(<<~SQL.squish, "SCHEMA")
|
15
15
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
|
16
16
|
DECODE(table_name, UPPER(table_name), LOWER(table_name), table_name)
|
17
17
|
FROM all_tables
|
@@ -44,7 +44,7 @@ module ActiveRecord
|
|
44
44
|
table_owner, table_name = default_owner, real_name
|
45
45
|
end
|
46
46
|
|
47
|
-
select_values(<<~SQL.squish, "
|
47
|
+
select_values(<<~SQL.squish, "SCHEMA", [bind_string("owner", table_owner), bind_string("table_name", table_name)]).any?
|
48
48
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ owner, table_name
|
49
49
|
FROM all_tables
|
50
50
|
WHERE owner = :owner
|
@@ -60,14 +60,14 @@ module ActiveRecord
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def views # :nodoc:
|
63
|
-
select_values(<<~SQL.squish, "
|
63
|
+
select_values(<<~SQL.squish, "SCHEMA")
|
64
64
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
|
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
|
-
select_values(<<~SQL.squish, "
|
70
|
+
select_values(<<~SQL.squish, "SCHEMA")
|
71
71
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
|
72
72
|
LOWER(mview_name) FROM all_mviews WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
73
73
|
SQL
|
@@ -75,8 +75,8 @@ module ActiveRecord
|
|
75
75
|
|
76
76
|
# get synonyms for schema dump
|
77
77
|
def synonyms
|
78
|
-
result = select_all(<<~SQL.squish, "
|
79
|
-
SELECT
|
78
|
+
result = select_all(<<~SQL.squish, "SCHEMA")
|
79
|
+
SELECT synonym_name, table_owner, table_name
|
80
80
|
FROM all_synonyms where owner = SYS_CONTEXT('userenv', 'current_schema')
|
81
81
|
SQL
|
82
82
|
|
@@ -90,7 +90,7 @@ module ActiveRecord
|
|
90
90
|
(_owner, table_name) = @connection.describe(table_name)
|
91
91
|
default_tablespace_name = default_tablespace
|
92
92
|
|
93
|
-
result = select_all(<<~SQL.squish, "
|
93
|
+
result = select_all(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
|
94
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,
|
95
95
|
i.index_type, i.ityp_owner, i.ityp_name, i.parameters,
|
96
96
|
LOWER(i.tablespace_name) AS tablespace_name,
|
@@ -120,7 +120,7 @@ module ActiveRecord
|
|
120
120
|
statement_parameters = nil
|
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
|
-
source = select_values(<<~SQL.squish, "
|
123
|
+
source = select_values(<<~SQL.squish, "SCHEMA", [bind_string("procedure_name", procedure_name.upcase)]).join
|
124
124
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ text
|
125
125
|
FROM all_source
|
126
126
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
@@ -199,19 +199,19 @@ module ActiveRecord
|
|
199
199
|
# t.string :last_name, :comment => “Surname”
|
200
200
|
# end
|
201
201
|
|
202
|
-
def create_table(table_name, **options)
|
203
|
-
create_sequence =
|
204
|
-
td = create_table_definition
|
202
|
+
def create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **options)
|
203
|
+
create_sequence = id != false
|
204
|
+
td = create_table_definition(
|
205
|
+
table_name, **options.extract!(:temporary, :options, :as, :comment, :tablespace, :organization)
|
206
|
+
)
|
205
207
|
|
206
|
-
if
|
207
|
-
pk =
|
208
|
-
Base.get_primary_key table_name.to_s.singularize
|
209
|
-
end
|
208
|
+
if id && !td.as
|
209
|
+
pk = primary_key || Base.get_primary_key(table_name.to_s.singularize)
|
210
210
|
|
211
211
|
if pk.is_a?(Array)
|
212
212
|
td.primary_keys pk
|
213
213
|
else
|
214
|
-
td.primary_key pk,
|
214
|
+
td.primary_key pk, id, **options
|
215
215
|
end
|
216
216
|
end
|
217
217
|
|
@@ -229,8 +229,10 @@ module ActiveRecord
|
|
229
229
|
yield td if block_given?
|
230
230
|
create_sequence = create_sequence || td.create_sequence
|
231
231
|
|
232
|
-
if
|
233
|
-
drop_table(table_name,
|
232
|
+
if force && data_source_exists?(table_name)
|
233
|
+
drop_table(table_name, force: force, if_exists: true)
|
234
|
+
else
|
235
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
234
236
|
end
|
235
237
|
|
236
238
|
execute schema_creation.accept td
|
@@ -238,14 +240,14 @@ module ActiveRecord
|
|
238
240
|
create_sequence_and_trigger(table_name, options) if create_sequence
|
239
241
|
|
240
242
|
if supports_comments? && !supports_comments_in_create?
|
241
|
-
if table_comment =
|
243
|
+
if table_comment = td.comment.presence
|
242
244
|
change_table_comment(table_name, table_comment)
|
243
245
|
end
|
244
246
|
td.columns.each do |column|
|
245
247
|
change_column_comment(table_name, column.name, column.comment) if column.comment.present?
|
246
248
|
end
|
247
249
|
end
|
248
|
-
td.indexes.each { |c, o| add_index table_name, c, o }
|
250
|
+
td.indexes.each { |c, o| add_index table_name, c, **o }
|
249
251
|
|
250
252
|
rebuild_primary_key_index_to_default_tablespace(table_name, options)
|
251
253
|
end
|
@@ -254,13 +256,16 @@ module ActiveRecord
|
|
254
256
|
if new_name.to_s.length > DatabaseLimits::IDENTIFIER_MAX_LENGTH
|
255
257
|
raise ArgumentError, "New table name '#{new_name}' is too long; the limit is #{DatabaseLimits::IDENTIFIER_MAX_LENGTH} characters"
|
256
258
|
end
|
259
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
260
|
+
schema_cache.clear_data_source_cache!(new_name.to_s)
|
257
261
|
execute "RENAME #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
|
258
262
|
execute "RENAME #{quote_table_name("#{table_name}_seq")} TO #{default_sequence_name(new_name)}" rescue nil
|
259
263
|
|
260
264
|
rename_table_indexes(table_name, new_name)
|
261
265
|
end
|
262
266
|
|
263
|
-
def drop_table(table_name, options
|
267
|
+
def drop_table(table_name, **options) #:nodoc:
|
268
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
264
269
|
execute "DROP TABLE #{quote_table_name(table_name)}#{' CASCADE CONSTRAINTS' if options[:force] == :cascade}"
|
265
270
|
seq_name = options[:sequence_name] || default_sequence_name(table_name)
|
266
271
|
execute "DROP SEQUENCE #{quote_table_name(seq_name)}" rescue nil
|
@@ -290,7 +295,7 @@ module ActiveRecord
|
|
290
295
|
end
|
291
296
|
end
|
292
297
|
|
293
|
-
def add_index(table_name, column_name, options
|
298
|
+
def add_index(table_name, column_name, **options) #:nodoc:
|
294
299
|
index_name, index_type, quoted_column_names, tablespace, index_options = add_index_options(table_name, column_name, **options)
|
295
300
|
execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})#{tablespace} #{index_options}"
|
296
301
|
if index_type == "UNIQUE"
|
@@ -309,13 +314,11 @@ module ActiveRecord
|
|
309
314
|
index_type = options[:unique] ? "UNIQUE" : ""
|
310
315
|
index_name = options[:name].to_s if options.key?(:name)
|
311
316
|
tablespace = tablespace_for(:index, options[:tablespace])
|
312
|
-
|
313
|
-
# TODO: This option is used for NOLOGGING, needs better argumetn name
|
317
|
+
# TODO: This option is used for NOLOGGING, needs better argument name
|
314
318
|
index_options = options[:options]
|
315
319
|
|
316
|
-
|
317
|
-
|
318
|
-
end
|
320
|
+
validate_index_length!(table_name, index_name, options.fetch(:internal, false))
|
321
|
+
|
319
322
|
if table_exists?(table_name) && index_name_exists?(table_name, index_name)
|
320
323
|
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
|
321
324
|
end
|
@@ -326,8 +329,8 @@ module ActiveRecord
|
|
326
329
|
|
327
330
|
# Remove the given index from the table.
|
328
331
|
# Gives warning if index does not exist
|
329
|
-
def remove_index(table_name,
|
330
|
-
index_name = index_name_for_remove(table_name, options)
|
332
|
+
def remove_index(table_name, column_name = nil, **options) #:nodoc:
|
333
|
+
index_name = index_name_for_remove(table_name, column_name, options)
|
331
334
|
# TODO: It should execute only when index_type == "UNIQUE"
|
332
335
|
execute "ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{quote_column_name(index_name)}" rescue nil
|
333
336
|
execute "DROP INDEX #{quote_column_name(index_name)}"
|
@@ -364,7 +367,7 @@ module ActiveRecord
|
|
364
367
|
# Will always query database and not index cache.
|
365
368
|
def index_name_exists?(table_name, index_name)
|
366
369
|
(_owner, table_name) = @connection.describe(table_name)
|
367
|
-
result = select_value(<<~SQL.squish, "
|
370
|
+
result = select_value(<<~SQL.squish, "SCHEMA")
|
368
371
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ 1 FROM all_indexes i
|
369
372
|
WHERE i.owner = SYS_CONTEXT('userenv', 'current_schema')
|
370
373
|
AND i.table_owner = SYS_CONTEXT('userenv', 'current_schema')
|
@@ -443,7 +446,7 @@ module ActiveRecord
|
|
443
446
|
change_column table_name, column_name, column.sql_type, null: null
|
444
447
|
end
|
445
448
|
|
446
|
-
def change_column(table_name, column_name, type, options
|
449
|
+
def change_column(table_name, column_name, type, **options) #:nodoc:
|
447
450
|
column = column_for(table_name, column_name)
|
448
451
|
|
449
452
|
# remove :null option if its value is the same as current column definition
|
@@ -497,8 +500,9 @@ module ActiveRecord
|
|
497
500
|
end
|
498
501
|
|
499
502
|
def table_comment(table_name) #:nodoc:
|
503
|
+
# TODO
|
500
504
|
(_owner, table_name) = @connection.describe(table_name)
|
501
|
-
select_value(<<~SQL.squish, "
|
505
|
+
select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
|
502
506
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ comments FROM all_tab_comments
|
503
507
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
504
508
|
AND table_name = :table_name
|
@@ -514,7 +518,7 @@ module ActiveRecord
|
|
514
518
|
def column_comment(table_name, column_name) #:nodoc:
|
515
519
|
# TODO: it does not exist in Abstract adapter
|
516
520
|
(_owner, table_name) = @connection.describe(table_name)
|
517
|
-
select_value(<<~SQL.squish, "
|
521
|
+
select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name), bind_string("column_name", column_name.upcase)])
|
518
522
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ comments FROM all_col_comments
|
519
523
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
520
524
|
AND table_name = :table_name
|
@@ -531,7 +535,7 @@ module ActiveRecord
|
|
531
535
|
end
|
532
536
|
|
533
537
|
def tablespace(table_name)
|
534
|
-
select_value(<<~SQL.squish, "
|
538
|
+
select_value(<<~SQL.squish, "SCHEMA")
|
535
539
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ tablespace_name
|
536
540
|
FROM all_tables
|
537
541
|
WHERE table_name='#{table_name.to_s.upcase}'
|
@@ -543,7 +547,7 @@ module ActiveRecord
|
|
543
547
|
def foreign_keys(table_name) #:nodoc:
|
544
548
|
(_owner, desc_table_name) = @connection.describe(table_name)
|
545
549
|
|
546
|
-
fk_info = select_all(<<~SQL.squish, "
|
550
|
+
fk_info = select_all(<<~SQL.squish, "SCHEMA", [bind_string("desc_table_name", desc_table_name)])
|
547
551
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ r.table_name to_table
|
548
552
|
,rc.column_name references_column
|
549
553
|
,cc.column_name
|
@@ -585,7 +589,7 @@ module ActiveRecord
|
|
585
589
|
# REFERENTIAL INTEGRITY ====================================
|
586
590
|
|
587
591
|
def disable_referential_integrity(&block) #:nodoc:
|
588
|
-
old_constraints = select_all(<<~SQL.squish, "
|
592
|
+
old_constraints = select_all(<<~SQL.squish, "SCHEMA")
|
589
593
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ constraint_name, owner, table_name
|
590
594
|
FROM all_constraints
|
591
595
|
WHERE constraint_type = 'R'
|
@@ -617,13 +621,12 @@ module ActiveRecord
|
|
617
621
|
end
|
618
622
|
|
619
623
|
private
|
620
|
-
|
621
624
|
def schema_creation
|
622
625
|
OracleEnhanced::SchemaCreation.new self
|
623
626
|
end
|
624
627
|
|
625
|
-
def create_table_definition(
|
626
|
-
OracleEnhanced::TableDefinition.new(self,
|
628
|
+
def create_table_definition(name, **options)
|
629
|
+
OracleEnhanced::TableDefinition.new(self, name, **options)
|
627
630
|
end
|
628
631
|
|
629
632
|
def new_column_from_field(table_name, field)
|
@@ -645,7 +648,7 @@ module ActiveRecord
|
|
645
648
|
# If a default contains a newline these cleanup regexes need to
|
646
649
|
# match newlines.
|
647
650
|
field["data_default"].sub!(/^'(.*)'$/m, '\1')
|
648
|
-
field["data_default"] = nil if
|
651
|
+
field["data_default"] = nil if /^(null|empty_[bc]lob\(\))$/i.match?(field["data_default"])
|
649
652
|
# TODO: Needs better fix to fallback "N" to false
|
650
653
|
field["data_default"] = false if field["data_default"] == "N" && OracleEnhancedAdapter.emulate_booleans_from_strings
|
651
654
|
end
|
@@ -8,7 +8,7 @@ module ActiveRecord #:nodoc:
|
|
8
8
|
STATEMENT_TOKEN = "\n\n/\n\n"
|
9
9
|
|
10
10
|
def structure_dump #:nodoc:
|
11
|
-
sequences = select(<<~SQL.squish, "
|
11
|
+
sequences = select(<<~SQL.squish, "SCHEMA")
|
12
12
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
|
13
13
|
sequence_name, min_value, max_value, increment_by, order_flag, cycle_flag
|
14
14
|
FROM all_sequences
|
@@ -18,7 +18,7 @@ module ActiveRecord #:nodoc:
|
|
18
18
|
structure = sequences.map do |result|
|
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
|
-
tables = select_values(<<~SQL.squish, "
|
21
|
+
tables = select_values(<<~SQL.squish, "SCHEMA")
|
22
22
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ 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
|
@@ -30,7 +30,7 @@ module ActiveRecord #:nodoc:
|
|
30
30
|
tables.each do |table_name|
|
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
|
-
columns = select_all(<<~SQL.squish, "
|
33
|
+
columns = select_all(<<~SQL.squish, "SCHEMA")
|
34
34
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ 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
|
@@ -55,8 +55,9 @@ module ActiveRecord #:nodoc:
|
|
55
55
|
structure << structure_dump_column_comments(table_name)
|
56
56
|
end
|
57
57
|
|
58
|
-
join_with_statement_token(structure) <<
|
59
|
-
|
58
|
+
join_with_statement_token(structure) <<
|
59
|
+
structure_dump_fk_constraints <<
|
60
|
+
structure_dump_views
|
60
61
|
end
|
61
62
|
|
62
63
|
def structure_dump_column(column) #:nodoc:
|
@@ -90,7 +91,7 @@ module ActiveRecord #:nodoc:
|
|
90
91
|
|
91
92
|
def structure_dump_primary_key(table) #:nodoc:
|
92
93
|
opts = { name: "", cols: [] }
|
93
|
-
pks = select_all(<<~SQL.squish, "
|
94
|
+
pks = select_all(<<~SQL.squish, "SCHEMA")
|
94
95
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ a.constraint_name, a.column_name, a.position
|
95
96
|
FROM all_cons_columns a
|
96
97
|
JOIN all_constraints c
|
@@ -109,7 +110,7 @@ module ActiveRecord #:nodoc:
|
|
109
110
|
|
110
111
|
def structure_dump_unique_keys(table) #:nodoc:
|
111
112
|
keys = {}
|
112
|
-
uks = select_all(<<~SQL.squish, "
|
113
|
+
uks = select_all(<<~SQL.squish, "SCHEMA")
|
113
114
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ a.constraint_name, a.column_name, a.position
|
114
115
|
FROM all_cons_columns a
|
115
116
|
JOIN all_constraints c
|
@@ -145,7 +146,7 @@ module ActiveRecord #:nodoc:
|
|
145
146
|
end
|
146
147
|
|
147
148
|
def structure_dump_fk_constraints #:nodoc:
|
148
|
-
foreign_keys = select_all(<<~SQL.squish, "
|
149
|
+
foreign_keys = select_all(<<~SQL.squish, "SCHEMA")
|
149
150
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ table_name FROM all_tables
|
150
151
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY 1
|
151
152
|
SQL
|
@@ -173,7 +174,7 @@ module ActiveRecord #:nodoc:
|
|
173
174
|
|
174
175
|
def structure_dump_column_comments(table_name)
|
175
176
|
comments = []
|
176
|
-
columns = select_values(<<~SQL.squish, "
|
177
|
+
columns = select_values(<<~SQL.squish, "SCHEMA")
|
177
178
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ column_name FROM user_tab_columns
|
178
179
|
WHERE table_name = '#{table_name}' ORDER BY column_id
|
179
180
|
SQL
|
@@ -207,7 +208,7 @@ module ActiveRecord #:nodoc:
|
|
207
208
|
# Extract all stored procedures, packages, synonyms.
|
208
209
|
def structure_dump_db_stored_code #:nodoc:
|
209
210
|
structure = []
|
210
|
-
all_source = select_all(<<~SQL.squish, "
|
211
|
+
all_source = select_all(<<~SQL.squish, "SCHEMA")
|
211
212
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ DISTINCT name, type
|
212
213
|
FROM all_source
|
213
214
|
WHERE type IN ('PROCEDURE', 'PACKAGE', 'PACKAGE BODY', 'FUNCTION', 'TRIGGER', 'TYPE')
|
@@ -239,7 +240,7 @@ module ActiveRecord #:nodoc:
|
|
239
240
|
|
240
241
|
def structure_dump_views #:nodoc:
|
241
242
|
structure = []
|
242
|
-
views = select_all(<<~SQL.squish, "
|
243
|
+
views = select_all(<<~SQL.squish, "SCHEMA")
|
243
244
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ view_name, text FROM all_views
|
244
245
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY view_name ASC
|
245
246
|
SQL
|
@@ -251,7 +252,7 @@ module ActiveRecord #:nodoc:
|
|
251
252
|
|
252
253
|
def structure_dump_synonyms #:nodoc:
|
253
254
|
structure = []
|
254
|
-
synonyms = select_all(<<~SQL.squish, "
|
255
|
+
synonyms = select_all(<<~SQL.squish, "SCHEMA")
|
255
256
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ owner, synonym_name, table_name, table_owner
|
256
257
|
FROM all_synonyms
|
257
258
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
@@ -264,14 +265,14 @@ module ActiveRecord #:nodoc:
|
|
264
265
|
end
|
265
266
|
|
266
267
|
def structure_drop #:nodoc:
|
267
|
-
sequences = select_values(<<~SQL.squish, "
|
268
|
+
sequences = select_values(<<~SQL.squish, "SCHEMA")
|
268
269
|
SELECT/*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
|
269
270
|
sequence_name FROM all_sequences where sequence_owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY 1
|
270
271
|
SQL
|
271
272
|
statements = sequences.map do |seq|
|
272
273
|
"DROP SEQUENCE \"#{seq}\""
|
273
274
|
end
|
274
|
-
tables = select_values(<<~SQL.squish, "
|
275
|
+
tables = select_values(<<~SQL.squish, "SCHEMA")
|
275
276
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ table_name from all_tables t
|
276
277
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema') AND secondary = 'N'
|
277
278
|
AND NOT EXISTS (SELECT mv.mview_name FROM all_mviews mv
|
@@ -287,7 +288,7 @@ module ActiveRecord #:nodoc:
|
|
287
288
|
end
|
288
289
|
|
289
290
|
def temp_table_drop #:nodoc:
|
290
|
-
temporary_tables = select_values(<<~SQL.squish, "
|
291
|
+
temporary_tables = select_values(<<~SQL.squish, "SCHEMA")
|
291
292
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ table_name FROM all_tables
|
292
293
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
293
294
|
AND secondary = 'N' AND temporary = 'Y' ORDER BY 1
|
@@ -318,11 +319,10 @@ module ActiveRecord #:nodoc:
|
|
318
319
|
end
|
319
320
|
|
320
321
|
private
|
321
|
-
|
322
322
|
# Called only if `supports_virtual_columns?` returns true
|
323
323
|
# return [{'column_name' => 'FOOS', 'data_default' => '...'}, ...]
|
324
324
|
def virtual_columns_for(table)
|
325
|
-
select_all(<<~SQL.squish, "
|
325
|
+
select_all(<<~SQL.squish, "SCHEMA")
|
326
326
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ column_name, data_default
|
327
327
|
FROM all_tab_cols
|
328
328
|
WHERE virtual_column = 'YES'
|
@@ -333,7 +333,7 @@ module ActiveRecord #:nodoc:
|
|
333
333
|
|
334
334
|
def drop_sql_for_feature(type)
|
335
335
|
short_type = type == "materialized view" ? "mview" : type
|
336
|
-
features = select_values(<<~SQL.squish, "
|
336
|
+
features = select_values(<<~SQL.squish, "SCHEMA")
|
337
337
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ #{short_type}_name FROM all_#{short_type.tableize}
|
338
338
|
where owner = SYS_CONTEXT('userenv', 'current_schema')
|
339
339
|
SQL
|
@@ -344,7 +344,7 @@ module ActiveRecord #:nodoc:
|
|
344
344
|
end
|
345
345
|
|
346
346
|
def drop_sql_for_object(type)
|
347
|
-
objects = select_values(<<~SQL.squish, "
|
347
|
+
objects = select_values(<<~SQL.squish, "SCHEMA")
|
348
348
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ object_name FROM all_objects
|
349
349
|
WHERE object_type = '#{type.upcase}' and owner = SYS_CONTEXT('userenv', 'current_schema')
|
350
350
|
SQL
|
@@ -4,6 +4,8 @@ module ActiveRecord
|
|
4
4
|
module ConnectionAdapters #:nodoc:
|
5
5
|
module OracleEnhanced
|
6
6
|
class TypeMetadata < DelegateClass(ActiveRecord::ConnectionAdapters::SqlTypeMetadata) # :nodoc:
|
7
|
+
include Deduplicable
|
8
|
+
|
7
9
|
attr_reader :virtual
|
8
10
|
|
9
11
|
def initialize(type_metadata, virtual: nil)
|
@@ -23,7 +25,6 @@ module ActiveRecord
|
|
23
25
|
end
|
24
26
|
|
25
27
|
protected
|
26
|
-
|
27
28
|
def attributes_for_hash
|
28
29
|
[self.class, @type_metadata, virtual]
|
29
30
|
end
|
@@ -30,6 +30,9 @@
|
|
30
30
|
# contribution.
|
31
31
|
# portions Copyright 2005 Graham Jenkins
|
32
32
|
|
33
|
+
require "arel/visitors/oracle"
|
34
|
+
require "arel/visitors/oracle12"
|
35
|
+
require "active_record/connection_adapters"
|
33
36
|
require "active_record/connection_adapters/abstract_adapter"
|
34
37
|
require "active_record/connection_adapters/statement_pool"
|
35
38
|
require "active_record/connection_adapters/oracle_enhanced/connection"
|
@@ -213,13 +216,24 @@ module ActiveRecord
|
|
213
216
|
cattr_accessor :use_shorter_identifier
|
214
217
|
self.use_shorter_identifier = false
|
215
218
|
|
219
|
+
##
|
220
|
+
# :singleton-method:
|
221
|
+
# By default, OracleEnhanced adapter will grant unlimited tablespace, create session, create table, create view,
|
222
|
+
# and create sequence when running the rake task db:create.
|
223
|
+
#
|
224
|
+
# If you wish to change these permissions you can add the following line to your initializer file:
|
225
|
+
#
|
226
|
+
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.permissions =
|
227
|
+
# ["create session", "create table", "create view", "create sequence", "create trigger", "ctxapp"]
|
228
|
+
cattr_accessor :permissions
|
229
|
+
self.permissions = ["create session", "create table", "create view", "create sequence"]
|
230
|
+
|
216
231
|
##
|
217
232
|
# :singleton-method:
|
218
233
|
# Specify default sequence start with value (by default 1 if not explicitly set), e.g.:
|
219
234
|
|
220
235
|
class StatementPool < ConnectionAdapters::StatementPool
|
221
236
|
private
|
222
|
-
|
223
237
|
def dealloc(stmt)
|
224
238
|
stmt.close
|
225
239
|
end
|
@@ -238,6 +252,14 @@ module ActiveRecord
|
|
238
252
|
ADAPTER_NAME
|
239
253
|
end
|
240
254
|
|
255
|
+
# Oracle enhanced adapter has no implementation because
|
256
|
+
# Oracle Database cannot detect `NoDatabaseError`.
|
257
|
+
# Please refer to the following discussion for details.
|
258
|
+
# https://github.com/rsim/oracle-enhanced/pull/1900
|
259
|
+
def self.database_exists?(config)
|
260
|
+
raise NotImplementedError
|
261
|
+
end
|
262
|
+
|
241
263
|
def arel_visitor # :nodoc:
|
242
264
|
if supports_fetch_first_n_rows_and_offset?
|
243
265
|
Arel::Visitors::Oracle12.new(self)
|
@@ -266,6 +288,10 @@ module ActiveRecord
|
|
266
288
|
true
|
267
289
|
end
|
268
290
|
|
291
|
+
def supports_common_table_expressions?
|
292
|
+
true
|
293
|
+
end
|
294
|
+
|
269
295
|
def supports_views?
|
270
296
|
true
|
271
297
|
end
|
@@ -438,6 +464,7 @@ module ActiveRecord
|
|
438
464
|
end
|
439
465
|
|
440
466
|
def discard!
|
467
|
+
super
|
441
468
|
@connection = nil
|
442
469
|
end
|
443
470
|
|
@@ -451,7 +478,7 @@ module ActiveRecord
|
|
451
478
|
# if sequence_name is set to :autogenerated then it means that primary key will be populated by trigger
|
452
479
|
raise ArgumentError.new "Trigger based primary key is not supported" if sequence_name == AUTOGENERATED_SEQUENCE_NAME
|
453
480
|
# call directly connection method to avoid prepared statement which causes fetching of next sequence value twice
|
454
|
-
select_value(<<~SQL.squish, "
|
481
|
+
select_value(<<~SQL.squish, "SCHEMA")
|
455
482
|
SELECT #{quote_table_name(sequence_name)}.NEXTVAL FROM dual
|
456
483
|
SQL
|
457
484
|
end
|
@@ -489,7 +516,7 @@ module ActiveRecord
|
|
489
516
|
end
|
490
517
|
|
491
518
|
if primary_key && sequence_name
|
492
|
-
new_start_value = select_value(<<~SQL.squish, "
|
519
|
+
new_start_value = select_value(<<~SQL.squish, "SCHEMA")
|
493
520
|
select NVL(max(#{quote_column_name(primary_key)}),0) + 1 from #{quote_table_name(table_name)}
|
494
521
|
SQL
|
495
522
|
|
@@ -500,32 +527,32 @@ module ActiveRecord
|
|
500
527
|
|
501
528
|
# Current database name
|
502
529
|
def current_database
|
503
|
-
select_value(<<~SQL.squish, "
|
530
|
+
select_value(<<~SQL.squish, "SCHEMA")
|
504
531
|
SELECT SYS_CONTEXT('userenv', 'con_name') FROM dual
|
505
532
|
SQL
|
506
533
|
rescue ActiveRecord::StatementInvalid
|
507
|
-
select_value(<<~SQL.squish, "
|
534
|
+
select_value(<<~SQL.squish, "SCHEMA")
|
508
535
|
SELECT SYS_CONTEXT('userenv', 'db_name') FROM dual
|
509
536
|
SQL
|
510
537
|
end
|
511
538
|
|
512
539
|
# Current database session user
|
513
540
|
def current_user
|
514
|
-
select_value(<<~SQL.squish, "
|
541
|
+
select_value(<<~SQL.squish, "SCHEMA")
|
515
542
|
SELECT SYS_CONTEXT('userenv', 'session_user') FROM dual
|
516
543
|
SQL
|
517
544
|
end
|
518
545
|
|
519
546
|
# Current database session schema
|
520
547
|
def current_schema
|
521
|
-
select_value(<<~SQL.squish, "
|
548
|
+
select_value(<<~SQL.squish, "SCHEMA")
|
522
549
|
SELECT SYS_CONTEXT('userenv', 'current_schema') FROM dual
|
523
550
|
SQL
|
524
551
|
end
|
525
552
|
|
526
553
|
# Default tablespace name of current user
|
527
554
|
def default_tablespace
|
528
|
-
select_value(<<~SQL.squish, "
|
555
|
+
select_value(<<~SQL.squish, "SCHEMA")
|
529
556
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ LOWER(default_tablespace) FROM user_users
|
530
557
|
WHERE username = SYS_CONTEXT('userenv', 'current_schema')
|
531
558
|
SQL
|
@@ -534,7 +561,7 @@ module ActiveRecord
|
|
534
561
|
def column_definitions(table_name)
|
535
562
|
(owner, desc_table_name) = @connection.describe(table_name)
|
536
563
|
|
537
|
-
select_all(<<~SQL.squish, "
|
564
|
+
select_all(<<~SQL.squish, "SCHEMA")
|
538
565
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ cols.column_name AS name, cols.data_type AS sql_type,
|
539
566
|
cols.data_default, cols.nullable, cols.virtual_column, cols.hidden_column,
|
540
567
|
cols.data_type_owner AS sql_type_owner,
|
@@ -566,7 +593,7 @@ module ActiveRecord
|
|
566
593
|
def pk_and_sequence_for(table_name, owner = nil, desc_table_name = nil) #:nodoc:
|
567
594
|
(owner, desc_table_name) = @connection.describe(table_name)
|
568
595
|
|
569
|
-
seqs = select_values(<<~SQL.squish, "
|
596
|
+
seqs = select_values(<<~SQL.squish, "SCHEMA")
|
570
597
|
select /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ us.sequence_name
|
571
598
|
from all_sequences us
|
572
599
|
where us.sequence_owner = '#{owner}'
|
@@ -574,7 +601,7 @@ module ActiveRecord
|
|
574
601
|
SQL
|
575
602
|
|
576
603
|
# changed back from user_constraints to all_constraints for consistency
|
577
|
-
pks = select_values(<<~SQL.squish, "
|
604
|
+
pks = select_values(<<~SQL.squish, "SCHEMA")
|
578
605
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ cc.column_name
|
579
606
|
FROM all_constraints c, all_cons_columns cc
|
580
607
|
WHERE c.owner = '#{owner}'
|
@@ -608,7 +635,7 @@ module ActiveRecord
|
|
608
635
|
def primary_keys(table_name) # :nodoc:
|
609
636
|
(_owner, desc_table_name) = @connection.describe(table_name)
|
610
637
|
|
611
|
-
pks = select_values(<<~SQL.squish, "
|
638
|
+
pks = select_values(<<~SQL.squish, "SCHEMA", [bind_string("table_name", desc_table_name)])
|
612
639
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ cc.column_name
|
613
640
|
FROM all_constraints c, all_cons_columns cc
|
614
641
|
WHERE c.owner = SYS_CONTEXT('userenv', 'current_schema')
|
@@ -628,7 +655,7 @@ module ActiveRecord
|
|
628
655
|
#
|
629
656
|
# It does not construct DISTINCT clause. Just return column names for distinct.
|
630
657
|
order_columns = orders.reject(&:blank?).map { |s|
|
631
|
-
s = s
|
658
|
+
s = visitor.compile(s) unless s.is_a?(String)
|
632
659
|
# remove any ASC/DESC modifiers
|
633
660
|
s.gsub(/\s+(ASC|DESC)\s*?/i, "")
|
634
661
|
}.reject(&:blank?).map.with_index { |column, i|
|
@@ -638,7 +665,7 @@ module ActiveRecord
|
|
638
665
|
end
|
639
666
|
|
640
667
|
def temporary_table?(table_name) #:nodoc:
|
641
|
-
select_value(<<~SQL.squish, "
|
668
|
+
select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name.upcase)]) == "Y"
|
642
669
|
SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
|
643
670
|
temporary FROM all_tables WHERE table_name = :table_name and owner = SYS_CONTEXT('userenv', 'current_schema')
|
644
671
|
SQL
|
@@ -748,25 +775,17 @@ module ActiveRecord
|
|
748
775
|
autoload :OracleEnhancedProcedures, "active_record/connection_adapters/oracle_enhanced/procedures"
|
749
776
|
end
|
750
777
|
|
751
|
-
#
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
end
|
763
|
-
class Oracle12 < Arel::Visitors::ToSql
|
764
|
-
private
|
765
|
-
def build_subselect(key, o)
|
766
|
-
stmt = super
|
767
|
-
stmt.orders = [] # `orders` will never be set to prevent `ORA-00907`.
|
768
|
-
stmt
|
769
|
-
end
|
778
|
+
# Workaround for https://github.com/jruby/jruby/issues/6267
|
779
|
+
if RUBY_ENGINE == "jruby"
|
780
|
+
require "jruby"
|
781
|
+
|
782
|
+
class org.jruby::RubyObjectSpace::WeakMap
|
783
|
+
field_reader :map
|
784
|
+
end
|
785
|
+
|
786
|
+
class ObjectSpace::WeakMap
|
787
|
+
def values
|
788
|
+
JRuby.ref(self).map.values.reject(&:nil?)
|
770
789
|
end
|
771
790
|
end
|
772
791
|
end
|