activerecord-oracle_enhanced-adapter 6.0.0.rc3 → 6.1.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.md +126 -0
- data/README.md +13 -2
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +2 -3
- 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 +15 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +48 -45
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +16 -17
- data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +2 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +57 -15
- 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 +253 -0
- data/lib/arel/visitors/oracle12.rb +160 -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 +48 -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
- data/spec/support/stats.sql +3 -0
- metadata +30 -26
@@ -18,13 +18,12 @@ module ActiveRecord #:nodoc:
|
|
18
18
|
module ClassMethods
|
19
19
|
def lob_columns
|
20
20
|
columns.select do |column|
|
21
|
-
column.sql_type_metadata.sql_type
|
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,7 +180,7 @@ module ActiveRecord #:nodoc:
|
|
168
180
|
|
169
181
|
def extract_expression_for_virtual_column(column)
|
170
182
|
column_name = column.name
|
171
|
-
@connection.select_value(<<~SQL.squish, "
|
183
|
+
@connection.select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name.upcase), bind_string("column_name", column_name.upcase)]).inspect
|
172
184
|
select data_default from all_tab_columns
|
173
185
|
where owner = SYS_CONTEXT('userenv', 'current_schema')
|
174
186
|
and table_name = :table_name
|
@@ -11,7 +11,7 @@ module ActiveRecord
|
|
11
11
|
# see: abstract/schema_statements.rb
|
12
12
|
|
13
13
|
def tables #:nodoc:
|
14
|
-
select_values(<<~SQL.squish, "
|
14
|
+
select_values(<<~SQL.squish, "SCHEMA")
|
15
15
|
SELECT DECODE(table_name, UPPER(table_name), LOWER(table_name), table_name)
|
16
16
|
FROM all_tables
|
17
17
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
@@ -43,7 +43,7 @@ module ActiveRecord
|
|
43
43
|
table_owner, table_name = default_owner, real_name
|
44
44
|
end
|
45
45
|
|
46
|
-
select_values(<<~SQL.squish, "
|
46
|
+
select_values(<<~SQL.squish, "SCHEMA", [bind_string("owner", table_owner), bind_string("table_name", table_name)]).any?
|
47
47
|
SELECT owner, table_name
|
48
48
|
FROM all_tables
|
49
49
|
WHERE owner = :owner
|
@@ -59,20 +59,20 @@ module ActiveRecord
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def views # :nodoc:
|
62
|
-
select_values(<<~SQL.squish, "
|
62
|
+
select_values(<<~SQL.squish, "SCHEMA")
|
63
63
|
SELECT LOWER(view_name) FROM all_views WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
64
64
|
SQL
|
65
65
|
end
|
66
66
|
|
67
67
|
def materialized_views #:nodoc:
|
68
|
-
select_values(<<~SQL.squish, "
|
68
|
+
select_values(<<~SQL.squish, "SCHEMA")
|
69
69
|
SELECT LOWER(mview_name) FROM all_mviews WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
70
70
|
SQL
|
71
71
|
end
|
72
72
|
|
73
73
|
# get synonyms for schema dump
|
74
74
|
def synonyms
|
75
|
-
result = select_all(<<~SQL.squish, "
|
75
|
+
result = select_all(<<~SQL.squish, "SCHEMA")
|
76
76
|
SELECT synonym_name, table_owner, table_name
|
77
77
|
FROM all_synonyms where owner = SYS_CONTEXT('userenv', 'current_schema')
|
78
78
|
SQL
|
@@ -87,7 +87,7 @@ module ActiveRecord
|
|
87
87
|
(_owner, table_name) = @connection.describe(table_name)
|
88
88
|
default_tablespace_name = default_tablespace
|
89
89
|
|
90
|
-
result = select_all(<<~SQL.squish, "
|
90
|
+
result = select_all(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
|
91
91
|
SELECT LOWER(i.table_name) AS table_name, LOWER(i.index_name) AS index_name, i.uniqueness,
|
92
92
|
i.index_type, i.ityp_owner, i.ityp_name, i.parameters,
|
93
93
|
LOWER(i.tablespace_name) AS tablespace_name,
|
@@ -117,7 +117,7 @@ module ActiveRecord
|
|
117
117
|
statement_parameters = nil
|
118
118
|
if row["index_type"] == "DOMAIN" && row["ityp_owner"] == "CTXSYS" && row["ityp_name"] == "CONTEXT"
|
119
119
|
procedure_name = default_datastore_procedure(row["index_name"])
|
120
|
-
source = select_values(<<~SQL.squish, "
|
120
|
+
source = select_values(<<~SQL.squish, "SCHEMA", [bind_string("procedure_name", procedure_name.upcase)]).join
|
121
121
|
SELECT text
|
122
122
|
FROM all_source
|
123
123
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
@@ -196,19 +196,19 @@ module ActiveRecord
|
|
196
196
|
# t.string :last_name, :comment => “Surname”
|
197
197
|
# end
|
198
198
|
|
199
|
-
def create_table(table_name, **options)
|
200
|
-
create_sequence =
|
201
|
-
td = create_table_definition
|
199
|
+
def create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **options)
|
200
|
+
create_sequence = id != false
|
201
|
+
td = create_table_definition(
|
202
|
+
table_name, **options.extract!(:temporary, :options, :as, :comment, :tablespace, :organization)
|
203
|
+
)
|
202
204
|
|
203
|
-
if
|
204
|
-
pk =
|
205
|
-
Base.get_primary_key table_name.to_s.singularize
|
206
|
-
end
|
205
|
+
if id && !td.as
|
206
|
+
pk = primary_key || Base.get_primary_key(table_name.to_s.singularize)
|
207
207
|
|
208
208
|
if pk.is_a?(Array)
|
209
209
|
td.primary_keys pk
|
210
210
|
else
|
211
|
-
td.primary_key pk,
|
211
|
+
td.primary_key pk, id, **options
|
212
212
|
end
|
213
213
|
end
|
214
214
|
|
@@ -226,8 +226,10 @@ module ActiveRecord
|
|
226
226
|
yield td if block_given?
|
227
227
|
create_sequence = create_sequence || td.create_sequence
|
228
228
|
|
229
|
-
if
|
230
|
-
drop_table(table_name,
|
229
|
+
if force && data_source_exists?(table_name)
|
230
|
+
drop_table(table_name, force: force, if_exists: true)
|
231
|
+
else
|
232
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
231
233
|
end
|
232
234
|
|
233
235
|
execute schema_creation.accept td
|
@@ -235,14 +237,14 @@ module ActiveRecord
|
|
235
237
|
create_sequence_and_trigger(table_name, options) if create_sequence
|
236
238
|
|
237
239
|
if supports_comments? && !supports_comments_in_create?
|
238
|
-
if table_comment =
|
240
|
+
if table_comment = td.comment.presence
|
239
241
|
change_table_comment(table_name, table_comment)
|
240
242
|
end
|
241
243
|
td.columns.each do |column|
|
242
244
|
change_column_comment(table_name, column.name, column.comment) if column.comment.present?
|
243
245
|
end
|
244
246
|
end
|
245
|
-
td.indexes.each { |c, o| add_index table_name, c, o }
|
247
|
+
td.indexes.each { |c, o| add_index table_name, c, **o }
|
246
248
|
|
247
249
|
rebuild_primary_key_index_to_default_tablespace(table_name, options)
|
248
250
|
end
|
@@ -251,13 +253,16 @@ module ActiveRecord
|
|
251
253
|
if new_name.to_s.length > DatabaseLimits::IDENTIFIER_MAX_LENGTH
|
252
254
|
raise ArgumentError, "New table name '#{new_name}' is too long; the limit is #{DatabaseLimits::IDENTIFIER_MAX_LENGTH} characters"
|
253
255
|
end
|
256
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
257
|
+
schema_cache.clear_data_source_cache!(new_name.to_s)
|
254
258
|
execute "RENAME #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
|
255
259
|
execute "RENAME #{quote_table_name("#{table_name}_seq")} TO #{default_sequence_name(new_name)}" rescue nil
|
256
260
|
|
257
261
|
rename_table_indexes(table_name, new_name)
|
258
262
|
end
|
259
263
|
|
260
|
-
def drop_table(table_name, options
|
264
|
+
def drop_table(table_name, **options) #:nodoc:
|
265
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
261
266
|
execute "DROP TABLE #{quote_table_name(table_name)}#{' CASCADE CONSTRAINTS' if options[:force] == :cascade}"
|
262
267
|
seq_name = options[:sequence_name] || default_sequence_name(table_name)
|
263
268
|
execute "DROP SEQUENCE #{quote_table_name(seq_name)}" rescue nil
|
@@ -287,8 +292,8 @@ module ActiveRecord
|
|
287
292
|
end
|
288
293
|
end
|
289
294
|
|
290
|
-
def add_index(table_name, column_name, options
|
291
|
-
index_name, index_type, quoted_column_names, tablespace, index_options = add_index_options(table_name, column_name, options)
|
295
|
+
def add_index(table_name, column_name, **options) #:nodoc:
|
296
|
+
index_name, index_type, quoted_column_names, tablespace, index_options = add_index_options(table_name, column_name, **options)
|
292
297
|
execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})#{tablespace} #{index_options}"
|
293
298
|
if index_type == "UNIQUE"
|
294
299
|
unless /\(.*\)/.match?(quoted_column_names)
|
@@ -306,13 +311,11 @@ module ActiveRecord
|
|
306
311
|
index_type = options[:unique] ? "UNIQUE" : ""
|
307
312
|
index_name = options[:name].to_s if options.key?(:name)
|
308
313
|
tablespace = tablespace_for(:index, options[:tablespace])
|
309
|
-
|
310
|
-
# TODO: This option is used for NOLOGGING, needs better argumetn name
|
314
|
+
# TODO: This option is used for NOLOGGING, needs better argument name
|
311
315
|
index_options = options[:options]
|
312
316
|
|
313
|
-
|
314
|
-
|
315
|
-
end
|
317
|
+
validate_index_length!(table_name, index_name, options.fetch(:internal, false))
|
318
|
+
|
316
319
|
if table_exists?(table_name) && index_name_exists?(table_name, index_name)
|
317
320
|
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
|
318
321
|
end
|
@@ -323,8 +326,8 @@ module ActiveRecord
|
|
323
326
|
|
324
327
|
# Remove the given index from the table.
|
325
328
|
# Gives warning if index does not exist
|
326
|
-
def remove_index(table_name,
|
327
|
-
index_name = index_name_for_remove(table_name, options)
|
329
|
+
def remove_index(table_name, column_name = nil, **options) #:nodoc:
|
330
|
+
index_name = index_name_for_remove(table_name, column_name, options)
|
328
331
|
# TODO: It should execute only when index_type == "UNIQUE"
|
329
332
|
execute "ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{quote_column_name(index_name)}" rescue nil
|
330
333
|
execute "DROP INDEX #{quote_column_name(index_name)}"
|
@@ -361,7 +364,7 @@ module ActiveRecord
|
|
361
364
|
# Will always query database and not index cache.
|
362
365
|
def index_name_exists?(table_name, index_name)
|
363
366
|
(_owner, table_name) = @connection.describe(table_name)
|
364
|
-
result = select_value(<<~SQL.squish, "
|
367
|
+
result = select_value(<<~SQL.squish, "SCHEMA")
|
365
368
|
SELECT 1 FROM all_indexes i
|
366
369
|
WHERE i.owner = SYS_CONTEXT('userenv', 'current_schema')
|
367
370
|
AND i.table_owner = SYS_CONTEXT('userenv', 'current_schema')
|
@@ -402,14 +405,14 @@ module ActiveRecord
|
|
402
405
|
execute "DROP SYNONYM #{quote_table_name(name)}"
|
403
406
|
end
|
404
407
|
|
405
|
-
def add_reference(table_name,
|
406
|
-
OracleEnhanced::ReferenceDefinition.new(
|
408
|
+
def add_reference(table_name, ref_name, **options)
|
409
|
+
OracleEnhanced::ReferenceDefinition.new(ref_name, **options).add_to(update_table_definition(table_name, self))
|
407
410
|
end
|
408
411
|
|
409
|
-
def add_column(table_name, column_name, type, options
|
412
|
+
def add_column(table_name, column_name, type, **options) #:nodoc:
|
410
413
|
type = aliased_types(type.to_s, type)
|
411
414
|
at = create_alter_table table_name
|
412
|
-
at.add_column(column_name, type, options)
|
415
|
+
at.add_column(column_name, type, **options)
|
413
416
|
add_column_sql = schema_creation.accept at
|
414
417
|
add_column_sql << tablespace_for((type_to_sql(type).downcase.to_sym), nil, table_name, column_name)
|
415
418
|
execute add_column_sql
|
@@ -440,7 +443,7 @@ module ActiveRecord
|
|
440
443
|
change_column table_name, column_name, column.sql_type, null: null
|
441
444
|
end
|
442
445
|
|
443
|
-
def change_column(table_name, column_name, type, options
|
446
|
+
def change_column(table_name, column_name, type, **options) #:nodoc:
|
444
447
|
column = column_for(table_name, column_name)
|
445
448
|
|
446
449
|
# remove :null option if its value is the same as current column definition
|
@@ -453,7 +456,7 @@ module ActiveRecord
|
|
453
456
|
end
|
454
457
|
|
455
458
|
td = create_table_definition(table_name)
|
456
|
-
cd = td.new_column_definition(column.name, type, options)
|
459
|
+
cd = td.new_column_definition(column.name, type, **options)
|
457
460
|
change_column_stmt = schema_creation.accept cd
|
458
461
|
change_column_stmt << tablespace_for((type_to_sql(type).downcase.to_sym), nil, options[:table_name], options[:column_name]) if type
|
459
462
|
change_column_sql = "ALTER TABLE #{quote_table_name(table_name)} MODIFY #{change_column_stmt}"
|
@@ -494,8 +497,9 @@ module ActiveRecord
|
|
494
497
|
end
|
495
498
|
|
496
499
|
def table_comment(table_name) #:nodoc:
|
500
|
+
# TODO
|
497
501
|
(_owner, table_name) = @connection.describe(table_name)
|
498
|
-
select_value(<<~SQL.squish, "
|
502
|
+
select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
|
499
503
|
SELECT comments FROM all_tab_comments
|
500
504
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
501
505
|
AND table_name = :table_name
|
@@ -511,7 +515,7 @@ module ActiveRecord
|
|
511
515
|
def column_comment(table_name, column_name) #:nodoc:
|
512
516
|
# TODO: it does not exist in Abstract adapter
|
513
517
|
(_owner, table_name) = @connection.describe(table_name)
|
514
|
-
select_value(<<~SQL.squish, "
|
518
|
+
select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name), bind_string("column_name", column_name.upcase)])
|
515
519
|
SELECT comments FROM all_col_comments
|
516
520
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
517
521
|
AND table_name = :table_name
|
@@ -528,7 +532,7 @@ module ActiveRecord
|
|
528
532
|
end
|
529
533
|
|
530
534
|
def tablespace(table_name)
|
531
|
-
select_value(<<~SQL.squish, "
|
535
|
+
select_value(<<~SQL.squish, "SCHEMA")
|
532
536
|
SELECT tablespace_name
|
533
537
|
FROM all_tables
|
534
538
|
WHERE table_name='#{table_name.to_s.upcase}'
|
@@ -540,7 +544,7 @@ module ActiveRecord
|
|
540
544
|
def foreign_keys(table_name) #:nodoc:
|
541
545
|
(_owner, desc_table_name) = @connection.describe(table_name)
|
542
546
|
|
543
|
-
fk_info = select_all(<<~SQL.squish, "
|
547
|
+
fk_info = select_all(<<~SQL.squish, "SCHEMA", [bind_string("desc_table_name", desc_table_name)])
|
544
548
|
SELECT r.table_name to_table
|
545
549
|
,rc.column_name references_column
|
546
550
|
,cc.column_name
|
@@ -582,7 +586,7 @@ module ActiveRecord
|
|
582
586
|
# REFERENTIAL INTEGRITY ====================================
|
583
587
|
|
584
588
|
def disable_referential_integrity(&block) #:nodoc:
|
585
|
-
old_constraints = select_all(<<~SQL.squish, "
|
589
|
+
old_constraints = select_all(<<~SQL.squish, "SCHEMA")
|
586
590
|
SELECT constraint_name, owner, table_name
|
587
591
|
FROM all_constraints
|
588
592
|
WHERE constraint_type = 'R'
|
@@ -614,13 +618,12 @@ module ActiveRecord
|
|
614
618
|
end
|
615
619
|
|
616
620
|
private
|
617
|
-
|
618
621
|
def schema_creation
|
619
622
|
OracleEnhanced::SchemaCreation.new self
|
620
623
|
end
|
621
624
|
|
622
|
-
def create_table_definition(
|
623
|
-
OracleEnhanced::TableDefinition.new(self,
|
625
|
+
def create_table_definition(name, **options)
|
626
|
+
OracleEnhanced::TableDefinition.new(self, name, **options)
|
624
627
|
end
|
625
628
|
|
626
629
|
def new_column_from_field(table_name, field)
|
@@ -642,7 +645,7 @@ module ActiveRecord
|
|
642
645
|
# If a default contains a newline these cleanup regexes need to
|
643
646
|
# match newlines.
|
644
647
|
field["data_default"].sub!(/^'(.*)'$/m, '\1')
|
645
|
-
field["data_default"] = nil if
|
648
|
+
field["data_default"] = nil if /^(null|empty_[bc]lob\(\))$/i.match?(field["data_default"])
|
646
649
|
# TODO: Needs better fix to fallback "N" to false
|
647
650
|
field["data_default"] = false if field["data_default"] == "N" && OracleEnhancedAdapter.emulate_booleans_from_strings
|
648
651
|
end
|