activerecord-oracle_enhanced-adapter 7.0.0 → 7.1.0
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 +56 -0
- data/README.md +0 -1
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +5 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +2 -2
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +35 -27
- data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +15 -2
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +9 -2
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +3 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +24 -15
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +3 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +7 -5
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +5 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +24 -22
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +17 -17
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +72 -29
- data/lib/activerecord-oracle_enhanced-adapter.rb +8 -0
- data/lib/arel/visitors/oracle.rb +6 -3
- data/lib/arel/visitors/oracle12.rb +6 -5
- data/lib/arel/visitors/oracle_common.rb +46 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +24 -5
- data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +7 -2
- data/spec/active_record/connection_adapters/oracle_enhanced/dbms_output_spec.rb +2 -2
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +3 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +25 -15
- data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +15 -18
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +14 -10
- data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +2 -2
- data/spec/active_record/oracle_enhanced/type/character_string_spec.rb +24 -0
- data/spec/active_record/oracle_enhanced/type/custom_spec.rb +90 -0
- data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +4 -2
- data/spec/active_record/oracle_enhanced/type/integer_spec.rb +8 -0
- data/spec/active_record/oracle_enhanced/type/national_character_text_spec.rb +3 -3
- data/spec/active_record/oracle_enhanced/type/raw_spec.rb +15 -0
- data/spec/active_record/oracle_enhanced/type/text_spec.rb +18 -3
- data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +5 -1
- data/spec/spec_config.yaml.template +2 -2
- data/spec/spec_helper.rb +14 -3
- metadata +27 -9
@@ -12,7 +12,7 @@ module ActiveRecord
|
|
12
12
|
|
13
13
|
def tables # :nodoc:
|
14
14
|
select_values(<<~SQL.squish, "SCHEMA")
|
15
|
-
SELECT
|
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
|
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) =
|
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
|
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
|
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) =
|
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
|
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
|
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::
|
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
|
@@ -330,6 +330,8 @@ module ActiveRecord
|
|
330
330
|
# Remove the given index from the table.
|
331
331
|
# Gives warning if index does not exist
|
332
332
|
def remove_index(table_name, column_name = nil, **options) # :nodoc:
|
333
|
+
return if options[:if_exists] && !index_exists?(table_name, column_name, **options)
|
334
|
+
|
333
335
|
index_name = index_name_for_remove(table_name, column_name, options)
|
334
336
|
# TODO: It should execute only when index_type == "UNIQUE"
|
335
337
|
execute "ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{quote_column_name(index_name)}" rescue nil
|
@@ -366,9 +368,9 @@ module ActiveRecord
|
|
366
368
|
#
|
367
369
|
# Will always query database and not index cache.
|
368
370
|
def index_name_exists?(table_name, index_name)
|
369
|
-
(_owner, table_name) =
|
371
|
+
(_owner, table_name) = _connection.describe(table_name)
|
370
372
|
result = select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name), bind_string("index_name", index_name.to_s.upcase)])
|
371
|
-
SELECT
|
373
|
+
SELECT 1 FROM all_indexes i
|
372
374
|
WHERE i.owner = SYS_CONTEXT('userenv', 'current_schema')
|
373
375
|
AND i.table_owner = SYS_CONTEXT('userenv', 'current_schema')
|
374
376
|
AND i.table_name = :table_name
|
@@ -509,9 +511,9 @@ module ActiveRecord
|
|
509
511
|
|
510
512
|
def table_comment(table_name) # :nodoc:
|
511
513
|
# TODO
|
512
|
-
(_owner, table_name) =
|
514
|
+
(_owner, table_name) = _connection.describe(table_name)
|
513
515
|
select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
|
514
|
-
SELECT
|
516
|
+
SELECT comments FROM all_tab_comments
|
515
517
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
516
518
|
AND table_name = :table_name
|
517
519
|
SQL
|
@@ -525,9 +527,9 @@ module ActiveRecord
|
|
525
527
|
|
526
528
|
def column_comment(table_name, column_name) # :nodoc:
|
527
529
|
# TODO: it does not exist in Abstract adapter
|
528
|
-
(_owner, table_name) =
|
530
|
+
(_owner, table_name) = _connection.describe(table_name)
|
529
531
|
select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name), bind_string("column_name", column_name.upcase)])
|
530
|
-
SELECT
|
532
|
+
SELECT comments FROM all_col_comments
|
531
533
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
532
534
|
AND table_name = :table_name
|
533
535
|
AND column_name = :column_name
|
@@ -544,7 +546,7 @@ module ActiveRecord
|
|
544
546
|
|
545
547
|
def tablespace(table_name)
|
546
548
|
select_value(<<~SQL.squish, "SCHEMA")
|
547
|
-
SELECT
|
549
|
+
SELECT tablespace_name
|
548
550
|
FROM all_tables
|
549
551
|
WHERE table_name='#{table_name.to_s.upcase}'
|
550
552
|
AND owner = SYS_CONTEXT('userenv', 'current_schema')
|
@@ -553,10 +555,10 @@ module ActiveRecord
|
|
553
555
|
|
554
556
|
# get table foreign keys for schema dump
|
555
557
|
def foreign_keys(table_name) # :nodoc:
|
556
|
-
(_owner, desc_table_name) =
|
558
|
+
(_owner, desc_table_name) = _connection.describe(table_name)
|
557
559
|
|
558
560
|
fk_info = select_all(<<~SQL.squish, "SCHEMA", [bind_string("desc_table_name", desc_table_name)])
|
559
|
-
SELECT
|
561
|
+
SELECT r.table_name to_table
|
560
562
|
,rc.column_name references_column
|
561
563
|
,cc.column_name
|
562
564
|
,c.constraint_name name
|
@@ -598,7 +600,7 @@ module ActiveRecord
|
|
598
600
|
|
599
601
|
def disable_referential_integrity(&block) # :nodoc:
|
600
602
|
old_constraints = select_all(<<~SQL.squish, "SCHEMA")
|
601
|
-
SELECT
|
603
|
+
SELECT constraint_name, owner, table_name
|
602
604
|
FROM all_constraints
|
603
605
|
WHERE constraint_type = 'R'
|
604
606
|
AND status = 'ENABLED'
|
@@ -637,7 +639,7 @@ module ActiveRecord
|
|
637
639
|
OracleEnhanced::TableDefinition.new(self, name, **options)
|
638
640
|
end
|
639
641
|
|
640
|
-
def new_column_from_field(table_name, field)
|
642
|
+
def new_column_from_field(table_name, field, definitions)
|
641
643
|
limit, scale = field["limit"], field["scale"]
|
642
644
|
if limit || scale
|
643
645
|
field["sql_type"] += "(#{(limit || 38).to_i}" + ((scale = scale.to_i) > 0 ? ",#{scale})" : ")")
|
@@ -713,7 +715,7 @@ module ActiveRecord
|
|
713
715
|
return unless tablespace
|
714
716
|
|
715
717
|
index_name = select_value(<<~SQL.squish, "Index name for primary key", [bind_string("table_name", table_name.upcase)])
|
716
|
-
SELECT
|
718
|
+
SELECT index_name FROM all_constraints
|
717
719
|
WHERE table_name = :table_name
|
718
720
|
AND constraint_type = 'P'
|
719
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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(
|
244
|
-
super(
|
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
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
490
|
+
_connection.logoff rescue nil
|
465
491
|
end
|
466
492
|
|
467
493
|
def discard!
|
468
494
|
super
|
469
|
-
|
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 =
|
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
|
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) =
|
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
|
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) =
|
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
|
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
|
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) =
|
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
|
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
|
@@ -662,12 +688,12 @@ module ActiveRecord
|
|
662
688
|
}.reject(&:blank?).map.with_index { |column, i|
|
663
689
|
"FIRST_VALUE(#{column}) OVER (PARTITION BY #{columns} ORDER BY #{column}) AS alias_#{i}__"
|
664
690
|
}
|
665
|
-
|
691
|
+
(order_columns << super).join(", ")
|
666
692
|
end
|
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
|
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
|
-
|
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
|
-
|
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
|
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
|
data/lib/arel/visitors/oracle.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
129
|
+
visit o.left, collector
|
127
130
|
collector << operator
|
128
131
|
collector << valuez.join(",")
|
129
132
|
collector << ")"
|