activerecord-oracle_enhanced-adapter 5.2.8 → 6.0.0.beta1
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 +79 -13
- data/README.md +1 -7
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +10 -13
- data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +7 -7
- data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +4 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +7 -18
- data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +17 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +32 -32
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +17 -27
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +4 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +13 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +1 -13
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +55 -71
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +27 -17
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +87 -61
- data/lib/active_record/type/oracle_enhanced/character_string.rb +36 -0
- data/spec/active_record/connection_adapters/emulation/oracle_adapter_spec.rb +0 -2
- data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +25 -50
- data/spec/active_record/connection_adapters/oracle_enhanced/context_index_spec.rb +5 -13
- data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +0 -2
- data/spec/active_record/connection_adapters/oracle_enhanced/quoting_spec.rb +0 -15
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +1 -31
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +71 -253
- data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +2 -3
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +81 -81
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +0 -1
- data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +0 -2
- data/spec/active_record/oracle_enhanced/type/character_string_spec.rb +43 -0
- data/spec/active_record/oracle_enhanced/type/decimal_spec.rb +56 -0
- data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +1 -1
- data/spec/active_record/oracle_enhanced/type/json_spec.rb +0 -1
- data/spec/active_record/oracle_enhanced/type/national_character_string_spec.rb +1 -2
- data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +0 -2
- data/spec/spec_helper.rb +2 -0
- metadata +27 -23
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +0 -28
@@ -12,7 +12,7 @@ module ActiveRecord
|
|
12
12
|
name = name.to_s
|
13
13
|
@quoted_column_names[name] ||= begin
|
14
14
|
# if only valid lowercase column characters in name
|
15
|
-
if
|
15
|
+
if /\A[a-z][a-z_0-9\$#]*\Z/.match?(name)
|
16
16
|
"\"#{name.upcase}\""
|
17
17
|
else
|
18
18
|
# remove double quotes which cannot be used inside quoted identifier
|
@@ -38,18 +38,6 @@ module ActiveRecord
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
# Used only for quoting database links as the naming rules for links
|
42
|
-
# differ from the rules for column names. Specifically, link names may
|
43
|
-
# include periods.
|
44
|
-
def quote_database_link(name)
|
45
|
-
case name
|
46
|
-
when NONQUOTED_DATABASE_LINK
|
47
|
-
%Q("#{name.upcase}")
|
48
|
-
else
|
49
|
-
name
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
41
|
# Names must be from 1 to 30 bytes long with these exceptions:
|
54
42
|
# * Names of databases are limited to 8 bytes.
|
55
43
|
# * Names of database links can be as long as 128 bytes.
|
@@ -61,12 +49,10 @@ module ActiveRecord
|
|
61
49
|
#
|
62
50
|
# Nonquoted identifiers can contain only alphanumeric characters from
|
63
51
|
# your database character set and the underscore (_), dollar sign ($),
|
64
|
-
# and pound sign (#).
|
65
|
-
#
|
66
|
-
|
67
|
-
|
68
|
-
NONQUOTED_DATABASE_LINK = /[[:alpha:]][\w$#\.@]{0,127}/
|
69
|
-
VALID_TABLE_NAME = /\A(?:#{NONQUOTED_OBJECT_NAME}\.)?#{NONQUOTED_OBJECT_NAME}(?:@#{NONQUOTED_DATABASE_LINK})?\Z/
|
52
|
+
# and pound sign (#).
|
53
|
+
# Oracle strongly discourages you from using $ and # in nonquoted identifiers.
|
54
|
+
NONQUOTED_OBJECT_NAME = /[[:alpha:]][\w$#]{0,29}/
|
55
|
+
VALID_TABLE_NAME = /\A(?:#{NONQUOTED_OBJECT_NAME}\.)?#{NONQUOTED_OBJECT_NAME}?\Z/
|
70
56
|
|
71
57
|
# unescaped table name should start with letter and
|
72
58
|
# contain letters, digits, _, $ or #
|
@@ -83,8 +69,8 @@ module ActiveRecord
|
|
83
69
|
end
|
84
70
|
|
85
71
|
def quote_table_name(name) #:nodoc:
|
86
|
-
name,
|
87
|
-
@quoted_table_names[name] ||= [name.split(".").map { |n| quote_column_name(n) }.join(".")
|
72
|
+
name, _link = name.to_s.split("@")
|
73
|
+
@quoted_table_names[name] ||= [name.split(".").map { |n| quote_column_name(n) }].join(".")
|
88
74
|
end
|
89
75
|
|
90
76
|
def quote_string(s) #:nodoc:
|
@@ -93,8 +79,10 @@ module ActiveRecord
|
|
93
79
|
|
94
80
|
def _quote(value) #:nodoc:
|
95
81
|
case value
|
82
|
+
when Type::OracleEnhanced::CharacterString::Data then
|
83
|
+
"'#{quote_string(value.to_s)}'"
|
96
84
|
when Type::OracleEnhanced::NationalCharacterString::Data then
|
97
|
-
"N"
|
85
|
+
+"N" << "'#{quote_string(value.to_s)}'"
|
98
86
|
when ActiveModel::Type::Binary::Data then
|
99
87
|
"empty_blob()"
|
100
88
|
when Type::OracleEnhanced::Text::Data then
|
@@ -108,22 +96,22 @@ module ActiveRecord
|
|
108
96
|
|
109
97
|
def quoted_true #:nodoc:
|
110
98
|
return "'Y'" if emulate_booleans_from_strings
|
111
|
-
"1"
|
99
|
+
"1"
|
112
100
|
end
|
113
101
|
|
114
102
|
def unquoted_true #:nodoc:
|
115
103
|
return "Y" if emulate_booleans_from_strings
|
116
|
-
"1"
|
104
|
+
"1"
|
117
105
|
end
|
118
106
|
|
119
107
|
def quoted_false #:nodoc:
|
120
108
|
return "'N'" if emulate_booleans_from_strings
|
121
|
-
"0"
|
109
|
+
"0"
|
122
110
|
end
|
123
111
|
|
124
112
|
def unquoted_false #:nodoc:
|
125
113
|
return "N" if emulate_booleans_from_strings
|
126
|
-
"0"
|
114
|
+
"0"
|
127
115
|
end
|
128
116
|
|
129
117
|
def _type_cast(value)
|
@@ -137,6 +125,8 @@ module ActiveRecord
|
|
137
125
|
end
|
138
126
|
when Type::OracleEnhanced::NationalCharacterString::Data
|
139
127
|
value.to_s
|
128
|
+
when Type::OracleEnhanced::CharacterString::Data
|
129
|
+
value
|
140
130
|
else
|
141
131
|
super
|
142
132
|
end
|
@@ -146,7 +136,7 @@ module ActiveRecord
|
|
146
136
|
|
147
137
|
def oracle_downcase(column_name)
|
148
138
|
return nil if column_name.nil?
|
149
|
-
|
139
|
+
/[a-z]/.match?(column_name) ? column_name : column_name.downcase
|
150
140
|
end
|
151
141
|
end
|
152
142
|
end
|
@@ -17,11 +17,11 @@ module ActiveRecord
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def visit_TableDefinition(o)
|
20
|
-
create_sql = "CREATE#{' GLOBAL TEMPORARY' if o.temporary} TABLE #{quote_table_name(o.name)} "
|
20
|
+
create_sql = +"CREATE#{' GLOBAL TEMPORARY' if o.temporary} TABLE #{quote_table_name(o.name)} "
|
21
21
|
statements = o.columns.map { |c| accept c }
|
22
22
|
statements << accept(o.primary_keys) if o.primary_keys
|
23
23
|
|
24
|
-
if
|
24
|
+
if supports_foreign_keys?
|
25
25
|
statements.concat(o.foreign_keys.map { |to_table, options| foreign_key_in_create(o.name, to_table, options) })
|
26
26
|
end
|
27
27
|
|
@@ -75,7 +75,7 @@ module ActiveRecord
|
|
75
75
|
|
76
76
|
def action_sql(action, dependency)
|
77
77
|
if action == "UPDATE"
|
78
|
-
raise ArgumentError,
|
78
|
+
raise ArgumentError, <<~MSG
|
79
79
|
'#{action}' is not supported by Oracle
|
80
80
|
MSG
|
81
81
|
end
|
@@ -83,7 +83,7 @@ module ActiveRecord
|
|
83
83
|
when :nullify then "ON #{action} SET NULL"
|
84
84
|
when :cascade then "ON #{action} CASCADE"
|
85
85
|
else
|
86
|
-
raise ArgumentError,
|
86
|
+
raise ArgumentError, <<~MSG
|
87
87
|
'#{dependency}' is not supported for #{action}
|
88
88
|
Supported values are: :nullify, :cascade
|
89
89
|
MSG
|
@@ -35,7 +35,7 @@ module ActiveRecord
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
class SynonymDefinition < Struct.new(:name, :table_owner, :table_name
|
38
|
+
class SynonymDefinition < Struct.new(:name, :table_owner, :table_name) #:nodoc:
|
39
39
|
end
|
40
40
|
|
41
41
|
class IndexDefinition < ActiveRecord::ConnectionAdapters::IndexDefinition
|
@@ -53,10 +53,20 @@ module ActiveRecord
|
|
53
53
|
include OracleEnhanced::ColumnMethods
|
54
54
|
|
55
55
|
attr_accessor :tablespace, :organization
|
56
|
-
def initialize(
|
56
|
+
def initialize(
|
57
|
+
conn,
|
58
|
+
name,
|
59
|
+
temporary: false,
|
60
|
+
options: nil,
|
61
|
+
as: nil,
|
62
|
+
tablespace: nil,
|
63
|
+
organization: nil,
|
64
|
+
comment: nil,
|
65
|
+
**
|
66
|
+
)
|
57
67
|
@tablespace = tablespace
|
58
68
|
@organization = organization
|
59
|
-
super(name, temporary, options, as, comment: comment)
|
69
|
+
super(conn, name, temporary: temporary, options: options, as: as, comment: comment)
|
60
70
|
end
|
61
71
|
|
62
72
|
def new_column_definition(name, type, **options) # :nodoc:
|
@@ -13,8 +13,6 @@ module ActiveRecord #:nodoc:
|
|
13
13
|
# add table prefix or suffix for schema_migrations
|
14
14
|
next if ignored? tbl
|
15
15
|
table(tbl, stream)
|
16
|
-
# add primary key trigger if table has it
|
17
|
-
primary_key_trigger(tbl, stream)
|
18
16
|
end
|
19
17
|
# following table definitions
|
20
18
|
# add foreign keys if table has them
|
@@ -27,22 +25,12 @@ module ActiveRecord #:nodoc:
|
|
27
25
|
synonyms(stream)
|
28
26
|
end
|
29
27
|
|
30
|
-
def primary_key_trigger(table_name, stream)
|
31
|
-
if @connection.has_primary_key_trigger?(table_name)
|
32
|
-
pk, _pk_seq = @connection.pk_and_sequence_for(table_name)
|
33
|
-
stream.print " add_primary_key_trigger #{table_name.inspect}"
|
34
|
-
stream.print ", primary_key: \"#{pk}\"" if pk != "id"
|
35
|
-
stream.print "\n\n"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
28
|
def synonyms(stream)
|
40
29
|
syns = @connection.synonyms
|
41
30
|
syns.each do |syn|
|
42
31
|
next if ignored? syn.name
|
43
32
|
table_name = syn.table_name
|
44
33
|
table_name = "#{syn.table_owner}.#{table_name}" if syn.table_owner
|
45
|
-
table_name = "#{table_name}@#{syn.db_link}" if syn.db_link
|
46
34
|
stream.print " add_synonym #{syn.name.inspect}, #{table_name.inspect}, force: true"
|
47
35
|
stream.puts
|
48
36
|
end
|
@@ -179,7 +167,7 @@ module ActiveRecord #:nodoc:
|
|
179
167
|
table_name = column.table_name
|
180
168
|
@connection.select_value(<<-SQL.strip.gsub(/\s+/, " "), "Table comment", [bind_string("table_name", table_name.upcase), bind_string("column_name", column_name.upcase)]).inspect
|
181
169
|
select data_default from all_tab_columns
|
182
|
-
where owner = SYS_CONTEXT('userenv', '
|
170
|
+
where owner = SYS_CONTEXT('userenv', 'current_schema')
|
183
171
|
and table_name = :table_name
|
184
172
|
and column_name = :column_name
|
185
173
|
SQL
|
@@ -16,6 +16,10 @@ module ActiveRecord
|
|
16
16
|
FROM all_tables
|
17
17
|
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
18
18
|
AND secondary = 'N'
|
19
|
+
minus
|
20
|
+
SELECT DECODE(mview_name, UPPER(mview_name), LOWER(mview_name), mview_name)
|
21
|
+
FROM all_mviews
|
22
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
19
23
|
SQL
|
20
24
|
end
|
21
25
|
|
@@ -48,7 +52,7 @@ module ActiveRecord
|
|
48
52
|
end
|
49
53
|
|
50
54
|
def data_source_exists?(table_name)
|
51
|
-
(_owner,
|
55
|
+
(_owner, _table_name) = @connection.describe(table_name)
|
52
56
|
true
|
53
57
|
rescue
|
54
58
|
false
|
@@ -69,34 +73,34 @@ module ActiveRecord
|
|
69
73
|
# get synonyms for schema dump
|
70
74
|
def synonyms
|
71
75
|
result = select_all(<<-SQL.strip.gsub(/\s+/, " "), "synonyms")
|
72
|
-
SELECT synonym_name, table_owner, table_name
|
73
|
-
FROM all_synonyms where owner = SYS_CONTEXT('userenv', '
|
76
|
+
SELECT synonym_name, table_owner, table_name
|
77
|
+
FROM all_synonyms where owner = SYS_CONTEXT('userenv', 'current_schema')
|
74
78
|
SQL
|
75
79
|
|
76
80
|
result.collect do |row|
|
77
81
|
OracleEnhanced::SynonymDefinition.new(oracle_downcase(row["synonym_name"]),
|
78
|
-
oracle_downcase(row["table_owner"]), oracle_downcase(row["table_name"])
|
82
|
+
oracle_downcase(row["table_owner"]), oracle_downcase(row["table_name"]))
|
79
83
|
end
|
80
84
|
end
|
81
85
|
|
82
86
|
def indexes(table_name) #:nodoc:
|
83
|
-
(
|
87
|
+
(_owner, table_name) = @connection.describe(table_name)
|
84
88
|
default_tablespace_name = default_tablespace
|
85
89
|
|
86
|
-
result = select_all(<<-SQL.strip.gsub(/\s+/, " "), "indexes", [bind_string("
|
90
|
+
result = select_all(<<-SQL.strip.gsub(/\s+/, " "), "indexes", [bind_string("table_name", table_name)])
|
87
91
|
SELECT LOWER(i.table_name) AS table_name, LOWER(i.index_name) AS index_name, i.uniqueness,
|
88
92
|
i.index_type, i.ityp_owner, i.ityp_name, i.parameters,
|
89
93
|
LOWER(i.tablespace_name) AS tablespace_name,
|
90
94
|
LOWER(c.column_name) AS column_name, e.column_expression,
|
91
95
|
atc.virtual_column
|
92
|
-
FROM all_indexes
|
93
|
-
JOIN all_ind_columns
|
94
|
-
LEFT OUTER JOIN all_ind_expressions
|
96
|
+
FROM all_indexes i
|
97
|
+
JOIN all_ind_columns c ON c.index_name = i.index_name AND c.index_owner = i.owner
|
98
|
+
LEFT OUTER JOIN all_ind_expressions e ON e.index_name = i.index_name AND
|
95
99
|
e.index_owner = i.owner AND e.column_position = c.column_position
|
96
|
-
LEFT OUTER JOIN all_tab_cols
|
100
|
+
LEFT OUTER JOIN all_tab_cols atc ON i.table_name = atc.table_name AND
|
97
101
|
c.column_name = atc.column_name AND i.owner = atc.owner AND atc.hidden_column = 'NO'
|
98
|
-
WHERE i.owner =
|
99
|
-
AND i.table_owner =
|
102
|
+
WHERE i.owner = SYS_CONTEXT('userenv', 'current_schema')
|
103
|
+
AND i.table_owner = SYS_CONTEXT('userenv', 'current_schema')
|
100
104
|
AND i.table_name = :table_name
|
101
105
|
AND NOT EXISTS (SELECT uc.index_name FROM all_constraints uc
|
102
106
|
WHERE uc.index_name = i.index_name AND uc.owner = i.owner AND uc.constraint_type = 'P')
|
@@ -113,10 +117,10 @@ module ActiveRecord
|
|
113
117
|
statement_parameters = nil
|
114
118
|
if row["index_type"] == "DOMAIN" && row["ityp_owner"] == "CTXSYS" && row["ityp_name"] == "CONTEXT"
|
115
119
|
procedure_name = default_datastore_procedure(row["index_name"])
|
116
|
-
source = select_values(<<-SQL.strip.gsub(/\s+/, " "), "procedure", [bind_string("
|
120
|
+
source = select_values(<<-SQL.strip.gsub(/\s+/, " "), "procedure", [bind_string("procedure_name", procedure_name.upcase)]).join
|
117
121
|
SELECT text
|
118
|
-
FROM all_source
|
119
|
-
WHERE owner =
|
122
|
+
FROM all_source
|
123
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
120
124
|
AND name = :procedure_name
|
121
125
|
ORDER BY line
|
122
126
|
SQL
|
@@ -192,9 +196,9 @@ module ActiveRecord
|
|
192
196
|
# t.string :last_name, :comment => “Surname”
|
193
197
|
# end
|
194
198
|
|
195
|
-
def create_table(table_name,
|
199
|
+
def create_table(table_name, **options)
|
196
200
|
create_sequence = options[:id] != false
|
197
|
-
td = create_table_definition table_name, options
|
201
|
+
td = create_table_definition table_name, options
|
198
202
|
|
199
203
|
if options[:id] != false && !options[:as]
|
200
204
|
pk = options.fetch(:primary_key) do
|
@@ -231,7 +235,9 @@ module ActiveRecord
|
|
231
235
|
create_sequence_and_trigger(table_name, options) if create_sequence
|
232
236
|
|
233
237
|
if supports_comments? && !supports_comments_in_create?
|
234
|
-
|
238
|
+
if table_comment = options[:comment].presence
|
239
|
+
change_table_comment(table_name, table_comment)
|
240
|
+
end
|
235
241
|
td.columns.each do |column|
|
236
242
|
change_column_comment(table_name, column.name, column.comment) if column.comment.present?
|
237
243
|
end
|
@@ -242,8 +248,8 @@ module ActiveRecord
|
|
242
248
|
end
|
243
249
|
|
244
250
|
def rename_table(table_name, new_name) #:nodoc:
|
245
|
-
if new_name.to_s.length >
|
246
|
-
raise ArgumentError, "New table name '#{new_name}' is too long; the limit is #{
|
251
|
+
if new_name.to_s.length > DatabaseLimits::IDENTIFIER_MAX_LENGTH
|
252
|
+
raise ArgumentError, "New table name '#{new_name}' is too long; the limit is #{DatabaseLimits::IDENTIFIER_MAX_LENGTH} characters"
|
247
253
|
end
|
248
254
|
execute "RENAME #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
|
249
255
|
execute "RENAME #{quote_table_name("#{table_name}_seq")} TO #{default_sequence_name(new_name)}" rescue nil
|
@@ -265,7 +271,7 @@ module ActiveRecord
|
|
265
271
|
sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
|
266
272
|
|
267
273
|
if supports_multi_insert?
|
268
|
-
versions.inject("INSERT ALL\n"
|
274
|
+
versions.inject(+"INSERT ALL\n") { |sql, version|
|
269
275
|
sql << "INTO #{sm_table} (version) VALUES (#{quote(version)})\n"
|
270
276
|
} << "SELECT * FROM DUAL\n"
|
271
277
|
else
|
@@ -285,7 +291,7 @@ module ActiveRecord
|
|
285
291
|
index_name, index_type, quoted_column_names, tablespace, index_options = add_index_options(table_name, column_name, options)
|
286
292
|
execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})#{tablespace} #{index_options}"
|
287
293
|
if index_type == "UNIQUE"
|
288
|
-
unless
|
294
|
+
unless /\(.*\)/.match?(quoted_column_names)
|
289
295
|
execute "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{quote_column_name(index_name)} #{index_type} (#{quoted_column_names})"
|
290
296
|
end
|
291
297
|
end
|
@@ -354,11 +360,11 @@ module ActiveRecord
|
|
354
360
|
#
|
355
361
|
# Will always query database and not index cache.
|
356
362
|
def index_name_exists?(table_name, index_name)
|
357
|
-
(
|
363
|
+
(_owner, table_name) = @connection.describe(table_name)
|
358
364
|
result = select_value(<<-SQL.strip.gsub(/\s+/, " "), "index name exists")
|
359
|
-
SELECT 1 FROM all_indexes
|
360
|
-
WHERE i.owner = '
|
361
|
-
AND i.table_owner = '
|
365
|
+
SELECT 1 FROM all_indexes i
|
366
|
+
WHERE i.owner = SYS_CONTEXT('userenv', 'current_schema')
|
367
|
+
AND i.table_owner = SYS_CONTEXT('userenv', 'current_schema')
|
362
368
|
AND i.table_name = '#{table_name}'
|
363
369
|
AND i.index_name = '#{index_name.to_s.upcase}'
|
364
370
|
SQL
|
@@ -376,10 +382,10 @@ module ActiveRecord
|
|
376
382
|
#
|
377
383
|
# add_synonym :posts, "blog.posts"
|
378
384
|
# add_synonym :posts_seq, "blog.posts_seq"
|
379
|
-
# add_synonym :employees, "hr.employees
|
385
|
+
# add_synonym :employees, "hr.employees", :force => true
|
380
386
|
#
|
381
387
|
def add_synonym(name, table_name, options = {})
|
382
|
-
sql = "CREATE"
|
388
|
+
sql = +"CREATE"
|
383
389
|
if options[:force] == true
|
384
390
|
sql << " OR REPLACE"
|
385
391
|
end
|
@@ -486,10 +492,10 @@ module ActiveRecord
|
|
486
492
|
end
|
487
493
|
|
488
494
|
def table_comment(table_name) #:nodoc:
|
489
|
-
(
|
490
|
-
select_value(<<-SQL.strip.gsub(/\s+/, " "), "Table comment", [bind_string("
|
491
|
-
SELECT comments FROM all_tab_comments
|
492
|
-
WHERE owner =
|
495
|
+
(_owner, table_name) = @connection.describe(table_name)
|
496
|
+
select_value(<<-SQL.strip.gsub(/\s+/, " "), "Table comment", [bind_string("table_name", table_name)])
|
497
|
+
SELECT comments FROM all_tab_comments
|
498
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
493
499
|
AND table_name = :table_name
|
494
500
|
SQL
|
495
501
|
end
|
@@ -502,10 +508,10 @@ module ActiveRecord
|
|
502
508
|
|
503
509
|
def column_comment(table_name, column_name) #:nodoc:
|
504
510
|
# TODO: it does not exist in Abstract adapter
|
505
|
-
(
|
506
|
-
select_value(<<-SQL.strip.gsub(/\s+/, " "), "Column comment", [bind_string("
|
507
|
-
SELECT comments FROM all_col_comments
|
508
|
-
WHERE owner =
|
511
|
+
(_owner, table_name) = @connection.describe(table_name)
|
512
|
+
select_value(<<-SQL.strip.gsub(/\s+/, " "), "Column comment", [bind_string("table_name", table_name), bind_string("column_name", column_name.upcase)])
|
513
|
+
SELECT comments FROM all_col_comments
|
514
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
509
515
|
AND table_name = :table_name
|
510
516
|
AND column_name = :column_name
|
511
517
|
SQL
|
@@ -524,23 +530,23 @@ module ActiveRecord
|
|
524
530
|
SELECT tablespace_name
|
525
531
|
FROM all_tables
|
526
532
|
WHERE table_name='#{table_name.to_s.upcase}'
|
527
|
-
AND owner = SYS_CONTEXT('userenv', '
|
533
|
+
AND owner = SYS_CONTEXT('userenv', 'current_schema')
|
528
534
|
SQL
|
529
535
|
end
|
530
536
|
|
531
537
|
# get table foreign keys for schema dump
|
532
538
|
def foreign_keys(table_name) #:nodoc:
|
533
|
-
(
|
539
|
+
(_owner, desc_table_name) = @connection.describe(table_name)
|
534
540
|
|
535
|
-
fk_info = select_all(<<-SQL.strip.gsub(/\s+/, " "), "Foreign Keys", [bind_string("
|
541
|
+
fk_info = select_all(<<-SQL.strip.gsub(/\s+/, " "), "Foreign Keys", [bind_string("desc_table_name", desc_table_name)])
|
536
542
|
SELECT r.table_name to_table
|
537
543
|
,rc.column_name references_column
|
538
544
|
,cc.column_name
|
539
545
|
,c.constraint_name name
|
540
546
|
,c.delete_rule
|
541
|
-
FROM all_constraints
|
542
|
-
all_constraints
|
543
|
-
WHERE c.owner =
|
547
|
+
FROM all_constraints c, all_cons_columns cc,
|
548
|
+
all_constraints r, all_cons_columns rc
|
549
|
+
WHERE c.owner = SYS_CONTEXT('userenv', 'current_schema')
|
544
550
|
AND c.table_name = :desc_table_name
|
545
551
|
AND c.constraint_type = 'R'
|
546
552
|
AND cc.owner = c.owner
|
@@ -579,7 +585,7 @@ module ActiveRecord
|
|
579
585
|
FROM all_constraints
|
580
586
|
WHERE constraint_type = 'R'
|
581
587
|
AND status = 'ENABLED'
|
582
|
-
AND owner = SYS_CONTEXT('userenv', '
|
588
|
+
AND owner = SYS_CONTEXT('userenv', 'current_schema')
|
583
589
|
SQL
|
584
590
|
begin
|
585
591
|
old_constraints.each do |constraint|
|
@@ -594,7 +600,7 @@ module ActiveRecord
|
|
594
600
|
end
|
595
601
|
|
596
602
|
def create_alter_table(name)
|
597
|
-
OracleEnhanced::AlterTable.new create_table_definition(name
|
603
|
+
OracleEnhanced::AlterTable.new create_table_definition(name)
|
598
604
|
end
|
599
605
|
|
600
606
|
def update_table_definition(table_name, base)
|
@@ -612,7 +618,7 @@ module ActiveRecord
|
|
612
618
|
end
|
613
619
|
|
614
620
|
def create_table_definition(*args)
|
615
|
-
OracleEnhanced::TableDefinition.new(*args)
|
621
|
+
OracleEnhanced::TableDefinition.new(self, *args)
|
616
622
|
end
|
617
623
|
|
618
624
|
def new_column_from_field(table_name, field)
|
@@ -636,7 +642,7 @@ module ActiveRecord
|
|
636
642
|
field["data_default"].sub!(/^'(.*)'$/m, '\1')
|
637
643
|
field["data_default"] = nil if field["data_default"] =~ /^(null|empty_[bc]lob\(\))$/i
|
638
644
|
# TODO: Needs better fix to fallback "N" to false
|
639
|
-
field["data_default"] = false if
|
645
|
+
field["data_default"] = false if field["data_default"] == "N" && OracleEnhancedAdapter.emulate_booleans_from_strings
|
640
646
|
end
|
641
647
|
|
642
648
|
type_metadata = fetch_type_metadata(field["sql_type"], is_virtual)
|
@@ -656,7 +662,7 @@ module ActiveRecord
|
|
656
662
|
end
|
657
663
|
|
658
664
|
def tablespace_for(obj_type, tablespace_option, table_name = nil, column_name = nil)
|
659
|
-
tablespace_sql = ""
|
665
|
+
tablespace_sql = +""
|
660
666
|
if tablespace = (tablespace_option || default_tablespace_for(obj_type))
|
661
667
|
if [:blob, :clob, :nclob].include?(obj_type.to_sym)
|
662
668
|
tablespace_sql << " LOB (#{quote_column_name(column_name)}) STORE AS #{column_name.to_s[0..10]}_#{table_name.to_s[0..14]}_ls (TABLESPACE #{tablespace})"
|
@@ -679,33 +685,11 @@ module ActiveRecord
|
|
679
685
|
end
|
680
686
|
|
681
687
|
def create_sequence_and_trigger(table_name, options)
|
688
|
+
# TODO: Needs rename since no triggers created
|
689
|
+
# This method will be removed since sequence will not be created separately
|
682
690
|
seq_name = options[:sequence_name] || default_sequence_name(table_name)
|
683
691
|
seq_start_value = options[:sequence_start_value] || default_sequence_start_value
|
684
692
|
execute "CREATE SEQUENCE #{quote_table_name(seq_name)} START WITH #{seq_start_value}"
|
685
|
-
|
686
|
-
create_primary_key_trigger(table_name, options) if options[:primary_key_trigger]
|
687
|
-
end
|
688
|
-
|
689
|
-
def create_primary_key_trigger(table_name, options)
|
690
|
-
seq_name = options[:sequence_name] || default_sequence_name(table_name)
|
691
|
-
trigger_name = options[:trigger_name] || default_trigger_name(table_name)
|
692
|
-
primary_key = options[:primary_key] || Base.get_primary_key(table_name.to_s.singularize)
|
693
|
-
execute <<-SQL
|
694
|
-
CREATE OR REPLACE TRIGGER #{quote_table_name(trigger_name)}
|
695
|
-
BEFORE INSERT ON #{quote_table_name(table_name)} FOR EACH ROW
|
696
|
-
BEGIN
|
697
|
-
IF inserting THEN
|
698
|
-
IF :new.#{quote_column_name(primary_key)} IS NULL THEN
|
699
|
-
SELECT #{quote_table_name(seq_name)}.NEXTVAL INTO :new.#{quote_column_name(primary_key)} FROM dual;
|
700
|
-
END IF;
|
701
|
-
END IF;
|
702
|
-
END;
|
703
|
-
SQL
|
704
|
-
end
|
705
|
-
|
706
|
-
def default_trigger_name(table_name)
|
707
|
-
# truncate table name if necessary to fit in max length of identifier
|
708
|
-
"#{table_name.to_s[0, table_name_length - 4]}_pkt"
|
709
693
|
end
|
710
694
|
|
711
695
|
def rebuild_primary_key_index_to_default_tablespace(table_name, options)
|