activerecord-oracle_enhanced-adapter 1.7.3 → 1.8.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 +288 -0
- data/README.md +44 -0
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +7 -63
- data/lib/active_record/connection_adapters/oracle_enhanced/column_dumper.rb +6 -52
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +13 -16
- data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +117 -119
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +33 -27
- data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +10 -10
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +59 -77
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +0 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +56 -82
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +4 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +77 -77
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +16 -45
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +60 -65
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +33 -51
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +149 -162
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +119 -122
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +3 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +69 -107
- data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +315 -538
- data/lib/active_record/oracle_enhanced/type/boolean.rb +7 -11
- data/lib/active_record/oracle_enhanced/type/integer.rb +4 -5
- data/lib/active_record/oracle_enhanced/type/json.rb +8 -0
- data/lib/active_record/oracle_enhanced/type/national_character_string.rb +1 -2
- data/lib/active_record/oracle_enhanced/type/raw.rb +2 -4
- data/lib/active_record/oracle_enhanced/type/string.rb +2 -3
- data/lib/active_record/oracle_enhanced/type/text.rb +2 -4
- data/lib/active_record/oracle_enhanced/type/timestamptz.rb +23 -0
- data/lib/activerecord-oracle_enhanced-adapter.rb +14 -13
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +129 -166
- data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +50 -33
- data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +44 -42
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +283 -378
- data/spec/active_record/connection_adapters/oracle_enhanced_database_tasks_spec.rb +14 -7
- data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +5 -7
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +118 -127
- data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +2 -3
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +74 -78
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +68 -83
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +308 -321
- data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +103 -48
- data/spec/spec_config.yaml.template +11 -0
- data/spec/spec_helper.rb +59 -60
- data/spec/support/alter_system_user_password.sql +2 -0
- data/spec/support/create_oracle_enhanced_users.sql +31 -0
- metadata +25 -25
- data/.rspec +0 -2
- data/Gemfile +0 -22
- data/RUNNING_TESTS.md +0 -50
- data/Rakefile +0 -45
- data/activerecord-oracle_enhanced-adapter.gemspec +0 -95
- data/lib/active_record/connection_adapters/oracle_enhanced/cpk.rb +0 -21
- data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +0 -113
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
module ActiveRecord #:nodoc:
|
|
2
2
|
module ConnectionAdapters #:nodoc:
|
|
3
3
|
module OracleEnhancedStructureDump #:nodoc:
|
|
4
|
-
|
|
5
4
|
# Statements separator used in structure dump to allow loading of structure dump also with SQL*Plus
|
|
6
5
|
STATEMENT_TOKEN = "\n\n/\n\n"
|
|
7
6
|
|
|
@@ -16,20 +15,20 @@ module ActiveRecord #:nodoc:
|
|
|
16
15
|
ORDER BY 1").each do |table_name|
|
|
17
16
|
virtual_columns = virtual_columns_for(table_name)
|
|
18
17
|
ddl = "CREATE#{ ' GLOBAL TEMPORARY' if temporary_table?(table_name)} TABLE \"#{table_name}\" (\n"
|
|
19
|
-
cols = select_all(
|
|
18
|
+
cols = select_all("
|
|
20
19
|
SELECT column_name, data_type, data_length, char_used, char_length, data_precision, data_scale, data_default, nullable
|
|
21
20
|
FROM all_tab_columns
|
|
22
21
|
WHERE table_name = '#{table_name}'
|
|
23
22
|
AND owner = SYS_CONTEXT('userenv', 'session_user')
|
|
24
23
|
ORDER BY column_id
|
|
25
|
-
|
|
26
|
-
if(v = virtual_columns.find {|col| col[
|
|
27
|
-
structure_dump_virtual_column(row, v[
|
|
24
|
+
").map do |row|
|
|
25
|
+
if (v = virtual_columns.find { |col| col["column_name"] == row["column_name"] })
|
|
26
|
+
structure_dump_virtual_column(row, v["data_default"])
|
|
28
27
|
else
|
|
29
28
|
structure_dump_column(row)
|
|
30
29
|
end
|
|
31
30
|
end
|
|
32
|
-
ddl << cols.join(",\n
|
|
31
|
+
ddl << cols.map { |col| " #{col}" }.join(",\n")
|
|
33
32
|
ddl << structure_dump_primary_key(table_name)
|
|
34
33
|
ddl << "\n)"
|
|
35
34
|
structure << ddl
|
|
@@ -44,36 +43,36 @@ module ActiveRecord #:nodoc:
|
|
|
44
43
|
|
|
45
44
|
def structure_dump_column(column) #:nodoc:
|
|
46
45
|
col = "\"#{column['column_name']}\" #{column['data_type']}"
|
|
47
|
-
if column[
|
|
46
|
+
if (column["data_type"] == "NUMBER") && !column["data_precision"].nil?
|
|
48
47
|
col << "(#{column['data_precision'].to_i}"
|
|
49
|
-
col << ",#{column['data_scale'].to_i}" if !column[
|
|
50
|
-
col <<
|
|
51
|
-
elsif column[
|
|
52
|
-
length = column[
|
|
53
|
-
col <<
|
|
48
|
+
col << ",#{column['data_scale'].to_i}" if !column["data_scale"].nil?
|
|
49
|
+
col << ")"
|
|
50
|
+
elsif column["data_type"].include?("CHAR") || column["data_type"] == "RAW"
|
|
51
|
+
length = column["char_used"] == "C" ? column["char_length"].to_i : column["data_length"].to_i
|
|
52
|
+
col << "(#{length})"
|
|
54
53
|
end
|
|
55
|
-
col << " DEFAULT #{column['data_default']}" if !column[
|
|
56
|
-
col <<
|
|
54
|
+
col << " DEFAULT #{column['data_default']}" if !column["data_default"].nil?
|
|
55
|
+
col << " NOT NULL" if column["nullable"] == "N"
|
|
57
56
|
col
|
|
58
57
|
end
|
|
59
58
|
|
|
60
59
|
def structure_dump_virtual_column(column, data_default) #:nodoc:
|
|
61
|
-
data_default = data_default.gsub(/"/,
|
|
60
|
+
data_default = data_default.gsub(/"/, "")
|
|
62
61
|
col = "\"#{column['column_name']}\" #{column['data_type']}"
|
|
63
|
-
if column[
|
|
62
|
+
if (column["data_type"] == "NUMBER") && !column["data_precision"].nil?
|
|
64
63
|
col << "(#{column['data_precision'].to_i}"
|
|
65
|
-
col << ",#{column['data_scale'].to_i}" if !column[
|
|
66
|
-
col <<
|
|
67
|
-
elsif column[
|
|
68
|
-
length = column[
|
|
69
|
-
col <<
|
|
64
|
+
col << ",#{column['data_scale'].to_i}" if !column["data_scale"].nil?
|
|
65
|
+
col << ")"
|
|
66
|
+
elsif column["data_type"].include?("CHAR") || column["data_type"] == "RAW"
|
|
67
|
+
length = column["char_used"] == "C" ? column["char_length"].to_i : column["data_length"].to_i
|
|
68
|
+
col << "(#{length})"
|
|
70
69
|
end
|
|
71
70
|
col << " GENERATED ALWAYS AS (#{data_default}) VIRTUAL"
|
|
72
71
|
end
|
|
73
72
|
|
|
74
73
|
def structure_dump_primary_key(table) #:nodoc:
|
|
75
|
-
opts = {:
|
|
76
|
-
pks = select_all(<<-SQL, "Primary Keys")
|
|
74
|
+
opts = { name: "", cols: [] }
|
|
75
|
+
pks = select_all(<<-SQL, "Primary Keys")
|
|
77
76
|
SELECT a.constraint_name, a.column_name, a.position
|
|
78
77
|
FROM all_cons_columns a
|
|
79
78
|
JOIN all_constraints c
|
|
@@ -84,15 +83,15 @@ module ActiveRecord #:nodoc:
|
|
|
84
83
|
AND c.owner = SYS_CONTEXT('userenv', 'current_schema')
|
|
85
84
|
SQL
|
|
86
85
|
pks.each do |row|
|
|
87
|
-
opts[:name] = row[
|
|
88
|
-
opts[:cols][row[
|
|
86
|
+
opts[:name] = row["constraint_name"]
|
|
87
|
+
opts[:cols][row["position"] - 1] = row["column_name"]
|
|
89
88
|
end
|
|
90
|
-
opts[:cols].length > 0 ? ",\n CONSTRAINT #{opts[:name]} PRIMARY KEY (#{opts[:cols].join(',')})" :
|
|
89
|
+
opts[:cols].length > 0 ? ",\n CONSTRAINT #{opts[:name]} PRIMARY KEY (#{opts[:cols].join(',')})" : ""
|
|
91
90
|
end
|
|
92
91
|
|
|
93
92
|
def structure_dump_unique_keys(table) #:nodoc:
|
|
94
93
|
keys = {}
|
|
95
|
-
uks = select_all(<<-SQL, "Primary Keys")
|
|
94
|
+
uks = select_all(<<-SQL, "Primary Keys")
|
|
96
95
|
SELECT a.constraint_name, a.column_name, a.position
|
|
97
96
|
FROM all_cons_columns a
|
|
98
97
|
JOIN all_constraints c
|
|
@@ -103,10 +102,10 @@ module ActiveRecord #:nodoc:
|
|
|
103
102
|
AND c.owner = SYS_CONTEXT('userenv', 'current_schema')
|
|
104
103
|
SQL
|
|
105
104
|
uks.each do |uk|
|
|
106
|
-
keys[uk[
|
|
107
|
-
keys[uk[
|
|
105
|
+
keys[uk["constraint_name"]] ||= []
|
|
106
|
+
keys[uk["constraint_name"]][uk["position"] - 1] = uk["column_name"]
|
|
108
107
|
end
|
|
109
|
-
keys.map do |k,v|
|
|
108
|
+
keys.map do |k, v|
|
|
110
109
|
"ALTER TABLE #{table.upcase} ADD CONSTRAINT #{k} UNIQUE (#{v.join(',')})"
|
|
111
110
|
end
|
|
112
111
|
end
|
|
@@ -114,8 +113,8 @@ module ActiveRecord #:nodoc:
|
|
|
114
113
|
def structure_dump_indexes(table_name) #:nodoc:
|
|
115
114
|
indexes(table_name).map do |options|
|
|
116
115
|
column_names = options[:columns]
|
|
117
|
-
options = {:
|
|
118
|
-
index_name
|
|
116
|
+
options = { name: options[:name], unique: options[:unique] }
|
|
117
|
+
index_name = index_name(table_name, column: column_names)
|
|
119
118
|
if Hash === options # legacy support, since this param was a string
|
|
120
119
|
index_type = options[:unique] ? "UNIQUE" : ""
|
|
121
120
|
index_name = options[:name] || index_name
|
|
@@ -165,22 +164,11 @@ module ActiveRecord #:nodoc:
|
|
|
165
164
|
end
|
|
166
165
|
|
|
167
166
|
def foreign_key_definition(to_table, options = {}) #:nodoc:
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
# composite foreign key
|
|
172
|
-
columns_sql = columns.map {|c| quote_column_name(c)}.join(',')
|
|
173
|
-
references = options[:references] || columns
|
|
174
|
-
references_sql = references.map {|c| quote_column_name(c)}.join(',')
|
|
175
|
-
else
|
|
176
|
-
columns_sql = quote_column_name(columns.first || "#{to_table.to_s.singularize}_id")
|
|
177
|
-
references = options[:references] ? options[:references].first : nil
|
|
178
|
-
references_sql = quote_column_name(options[:primary_key] || references || "id")
|
|
179
|
-
end
|
|
167
|
+
column_sql = quote_column_name(options[:column] || "#{to_table.to_s.singularize}_id")
|
|
168
|
+
references = options[:references] ? options[:references].first : nil
|
|
169
|
+
references_sql = quote_column_name(options[:primary_key] || references || "id")
|
|
180
170
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
sql = "FOREIGN KEY (#{columns_sql}) REFERENCES #{quote_table_name(table_name)}(#{references_sql})"
|
|
171
|
+
sql = "FOREIGN KEY (#{column_sql}) REFERENCES #{quote_table_name(to_table)}(#{references_sql})"
|
|
184
172
|
|
|
185
173
|
case options[:dependent]
|
|
186
174
|
when :nullify
|
|
@@ -191,7 +179,6 @@ module ActiveRecord #:nodoc:
|
|
|
191
179
|
sql
|
|
192
180
|
end
|
|
193
181
|
|
|
194
|
-
|
|
195
182
|
# Extract all stored procedures, packages, synonyms and views.
|
|
196
183
|
def structure_dump_db_stored_code #:nodoc:
|
|
197
184
|
structure = []
|
|
@@ -201,21 +188,21 @@ module ActiveRecord #:nodoc:
|
|
|
201
188
|
AND name NOT LIKE 'BIN$%'
|
|
202
189
|
AND owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY type").each do |source|
|
|
203
190
|
ddl = "CREATE OR REPLACE \n"
|
|
204
|
-
select_all(
|
|
191
|
+
select_all("
|
|
205
192
|
SELECT text
|
|
206
193
|
FROM all_source
|
|
207
194
|
WHERE name = '#{source['name']}'
|
|
208
195
|
AND type = '#{source['type']}'
|
|
209
196
|
AND owner = SYS_CONTEXT('userenv', 'current_schema')
|
|
210
197
|
ORDER BY line
|
|
211
|
-
|
|
212
|
-
ddl << row[
|
|
198
|
+
").each do |row|
|
|
199
|
+
ddl << row["text"]
|
|
213
200
|
end
|
|
214
|
-
ddl << ";" unless ddl.strip[-1,1] ==
|
|
201
|
+
ddl << ";" unless ddl.strip[-1, 1] == ";"
|
|
215
202
|
structure << ddl
|
|
216
203
|
end
|
|
217
204
|
|
|
218
|
-
# export views
|
|
205
|
+
# export views
|
|
219
206
|
select_all("SELECT view_name, text FROM all_views WHERE owner = SYS_CONTEXT('userenv', 'session_user') ORDER BY view_name ASC").each do |view|
|
|
220
207
|
structure << "CREATE OR REPLACE FORCE VIEW #{view['view_name']} AS\n #{view['text']}"
|
|
221
208
|
end
|
|
@@ -253,7 +240,7 @@ module ActiveRecord #:nodoc:
|
|
|
253
240
|
end)
|
|
254
241
|
end
|
|
255
242
|
|
|
256
|
-
def full_drop(preserve_tables=false) #:nodoc:
|
|
243
|
+
def full_drop(preserve_tables = false) #:nodoc:
|
|
257
244
|
s = preserve_tables ? [] : [structure_drop]
|
|
258
245
|
s << temp_table_drop if preserve_tables
|
|
259
246
|
s << drop_sql_for_feature("view")
|
|
@@ -266,30 +253,6 @@ module ActiveRecord #:nodoc:
|
|
|
266
253
|
s.join
|
|
267
254
|
end
|
|
268
255
|
|
|
269
|
-
def add_column_options!(sql, options) #:nodoc:
|
|
270
|
-
type = options[:type] || ((column = options[:column]) && column.type)
|
|
271
|
-
type = type && type.to_sym
|
|
272
|
-
# handle case of defaults for CLOB columns, which would otherwise get "quoted" incorrectly
|
|
273
|
-
if options_include_default?(options)
|
|
274
|
-
if type == :text
|
|
275
|
-
sql << " DEFAULT #{quote(options[:default])}"
|
|
276
|
-
else
|
|
277
|
-
# from abstract adapter
|
|
278
|
-
sql << " DEFAULT #{quote(options[:default], options[:column])}"
|
|
279
|
-
end
|
|
280
|
-
end
|
|
281
|
-
# must explicitly add NULL or NOT NULL to allow change_column to work on migrations
|
|
282
|
-
if options[:null] == false
|
|
283
|
-
sql << " NOT NULL"
|
|
284
|
-
elsif options[:null] == true
|
|
285
|
-
sql << " NULL" unless type == :primary_key
|
|
286
|
-
end
|
|
287
|
-
# add AS expression for virtual columns
|
|
288
|
-
if options[:as].present?
|
|
289
|
-
sql << " AS (#{options[:as]})"
|
|
290
|
-
end
|
|
291
|
-
end
|
|
292
|
-
|
|
293
256
|
def execute_structure_dump(string)
|
|
294
257
|
string.split(STATEMENT_TOKEN).each do |ddl|
|
|
295
258
|
execute(ddl) unless ddl.blank?
|
|
@@ -298,45 +261,44 @@ module ActiveRecord #:nodoc:
|
|
|
298
261
|
|
|
299
262
|
private
|
|
300
263
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
264
|
+
# virtual columns are an 11g feature. This returns [] if feature is not
|
|
265
|
+
# present or none are found.
|
|
266
|
+
# return [{'column_name' => 'FOOS', 'data_default' => '...'}, ...]
|
|
267
|
+
def virtual_columns_for(table)
|
|
268
|
+
begin
|
|
269
|
+
select_all <<-SQL
|
|
307
270
|
SELECT column_name, data_default
|
|
308
271
|
FROM all_tab_cols
|
|
309
272
|
WHERE virtual_column = 'YES'
|
|
310
273
|
AND owner = SYS_CONTEXT('userenv', 'session_user')
|
|
311
274
|
AND table_name = '#{table.upcase}'
|
|
312
275
|
SQL
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
276
|
+
# feature not supported previous to 11g
|
|
277
|
+
rescue ActiveRecord::StatementInvalid => _e
|
|
278
|
+
[]
|
|
279
|
+
end
|
|
316
280
|
end
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
def drop_sql_for_feature(type)
|
|
320
|
-
short_type = type == 'materialized view' ? 'mview' : type
|
|
321
|
-
join_with_statement_token(
|
|
322
|
-
select_values("SELECT #{short_type}_name FROM all_#{short_type.tableize} where owner = SYS_CONTEXT('userenv', 'session_user')").map do |name|
|
|
323
|
-
"DROP #{type.upcase} \"#{name}\""
|
|
324
|
-
end)
|
|
325
|
-
end
|
|
326
281
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
"
|
|
331
|
-
|
|
332
|
-
|
|
282
|
+
def drop_sql_for_feature(type)
|
|
283
|
+
short_type = type == "materialized view" ? "mview" : type
|
|
284
|
+
join_with_statement_token(
|
|
285
|
+
select_values("SELECT #{short_type}_name FROM all_#{short_type.tableize} where owner = SYS_CONTEXT('userenv', 'session_user')").map do |name|
|
|
286
|
+
"DROP #{type.upcase} \"#{name}\""
|
|
287
|
+
end)
|
|
288
|
+
end
|
|
333
289
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
290
|
+
def drop_sql_for_object(type)
|
|
291
|
+
join_with_statement_token(
|
|
292
|
+
select_values("SELECT object_name FROM all_objects WHERE object_type = '#{type.upcase}' and owner = SYS_CONTEXT('userenv', 'session_user')").map do |name|
|
|
293
|
+
"DROP #{type.upcase} \"#{name}\""
|
|
294
|
+
end)
|
|
295
|
+
end
|
|
339
296
|
|
|
297
|
+
def join_with_statement_token(array)
|
|
298
|
+
string = array.join(STATEMENT_TOKEN)
|
|
299
|
+
string << STATEMENT_TOKEN unless string.blank?
|
|
300
|
+
string
|
|
301
|
+
end
|
|
340
302
|
end
|
|
341
303
|
end
|
|
342
304
|
end
|
|
@@ -1 +1 @@
|
|
|
1
|
-
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter::VERSION = File.read(File.expand_path(
|
|
1
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter::VERSION = File.read(File.expand_path("../../../../../VERSION", __FILE__)).chomp
|