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