activerecord-oracle_enhanced-adapter 1.3.2 → 1.4.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.
- data/Gemfile +0 -2
- data/History.txt +19 -0
- data/README.md +378 -0
- data/RUNNING_TESTS.md +45 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/activerecord-oracle_enhanced-adapter.gemspec +6 -9
- data/lib/active_record/connection_adapters/oracle_enhanced.rake +34 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +209 -57
- data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +22 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +17 -3
- data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +19 -3
- data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +75 -17
- data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +41 -2
- data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +3 -3
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +40 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +10 -3
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +49 -10
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +54 -54
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +33 -5
- data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +66 -5
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +162 -13
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +1 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +1 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +43 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +150 -1
- data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +5 -4
- data/spec/spec_helper.rb +3 -1
- metadata +38 -52
- data/README.rdoc +0 -89
- data/RUNNING_TESTS.rdoc +0 -28
@@ -105,6 +105,12 @@ module ActiveRecord #:nodoc:
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def indexes_with_oracle_enhanced(table, stream)
|
108
|
+
# return original method if not using oracle_enhanced
|
109
|
+
if (rails_env = defined?(Rails.env) ? Rails.env : (defined?(RAILS_ENV) ? RAILS_ENV : nil)) &&
|
110
|
+
ActiveRecord::Base.configurations[rails_env] &&
|
111
|
+
ActiveRecord::Base.configurations[rails_env]['adapter'] != 'oracle_enhanced'
|
112
|
+
return indexes_without_oracle_enhanced(table, stream)
|
113
|
+
end
|
108
114
|
if (indexes = @connection.indexes(table)).any?
|
109
115
|
add_index_statements = indexes.map do |index|
|
110
116
|
case index.type
|
@@ -169,12 +175,13 @@ module ActiveRecord #:nodoc:
|
|
169
175
|
next if column.name == pk
|
170
176
|
spec = {}
|
171
177
|
spec[:name] = column.name.inspect
|
172
|
-
spec[:type] = column.type.to_s
|
178
|
+
spec[:type] = column.virtual? ? 'virtual' : column.type.to_s
|
173
179
|
spec[:limit] = column.limit.inspect if column.limit != @types[column.type][:limit] && column.type != :decimal
|
174
180
|
spec[:precision] = column.precision.inspect if !column.precision.nil?
|
175
181
|
spec[:scale] = column.scale.inspect if !column.scale.nil?
|
176
182
|
spec[:null] = 'false' if !column.null
|
177
|
-
spec[:default] =
|
183
|
+
spec[:default] = column.virtual_column_data_default if column.virtual?
|
184
|
+
spec[:default] ||= default_string(column.default) if column.has_default?
|
178
185
|
(spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.inspect} => ")}
|
179
186
|
spec
|
180
187
|
end.compact
|
@@ -228,7 +235,7 @@ module ActiveRecord #:nodoc:
|
|
228
235
|
|
229
236
|
private
|
230
237
|
def remove_prefix_and_suffix(table_name)
|
231
|
-
if table_name =~ /\A#{ActiveRecord::Base.table_name_prefix}(.*)#{ActiveRecord::Base.table_name_suffix}\Z/
|
238
|
+
if table_name =~ /\A#{ActiveRecord::Base.table_name_prefix.to_s.gsub('$','\$')}(.*)#{ActiveRecord::Base.table_name_suffix.to_s.gsub('$','\$')}\Z/
|
232
239
|
"\"#{$1}\""
|
233
240
|
else
|
234
241
|
"\"#{table_name}\""
|
@@ -71,16 +71,21 @@ module ActiveRecord
|
|
71
71
|
result = block.call(table_definition) if block
|
72
72
|
create_sequence = create_sequence || table_definition.create_sequence
|
73
73
|
column_comments = table_definition.column_comments if table_definition.column_comments
|
74
|
-
tablespace =
|
74
|
+
tablespace = tablespace_for(:table, options[:tablespace])
|
75
75
|
|
76
76
|
if options[:force] && table_exists?(name)
|
77
77
|
drop_table(name, options)
|
78
78
|
end
|
79
79
|
|
80
80
|
create_sql = "CREATE#{' GLOBAL TEMPORARY' if options[:temporary]} TABLE "
|
81
|
-
create_sql <<
|
82
|
-
create_sql << table_definition.to_sql
|
83
|
-
|
81
|
+
create_sql << quote_table_name(name)
|
82
|
+
create_sql << " (#{table_definition.to_sql})"
|
83
|
+
unless options[:temporary]
|
84
|
+
create_sql << " ORGANIZATION #{options[:organization]}" if options[:organization]
|
85
|
+
create_sql << tablespace
|
86
|
+
table_definition.lob_columns.each{|cd| create_sql << tablespace_for(cd.sql_type.downcase.to_sym, nil, name, cd.name)}
|
87
|
+
end
|
88
|
+
create_sql << " #{options[:options]}"
|
84
89
|
execute create_sql
|
85
90
|
|
86
91
|
create_sequence_and_trigger(name, options) if create_sequence
|
@@ -113,7 +118,7 @@ module ActiveRecord
|
|
113
118
|
if Hash === options # legacy support, since this param was a string
|
114
119
|
index_type = options[:unique] ? "UNIQUE" : ""
|
115
120
|
index_name = options[:name].to_s if options.key?(:name)
|
116
|
-
tablespace =
|
121
|
+
tablespace = tablespace_for(:index, options[:tablespace])
|
117
122
|
else
|
118
123
|
index_type = options
|
119
124
|
end
|
@@ -124,7 +129,7 @@ module ActiveRecord
|
|
124
129
|
if index_name_exists?(table_name, index_name, false)
|
125
130
|
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
|
126
131
|
end
|
127
|
-
quoted_column_names = column_names.map { |e|
|
132
|
+
quoted_column_names = column_names.map { |e| quote_column_name_or_expression(e) }.join(", ")
|
128
133
|
|
129
134
|
execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})#{tablespace} #{options[:options]}"
|
130
135
|
ensure
|
@@ -189,10 +194,19 @@ module ActiveRecord
|
|
189
194
|
result == 1
|
190
195
|
end
|
191
196
|
|
197
|
+
def rename_index(table_name, index_name, new_index_name) #:nodoc:
|
198
|
+
unless index_name_exists?(table_name, index_name, true)
|
199
|
+
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' does not exist"
|
200
|
+
end
|
201
|
+
execute "ALTER INDEX #{quote_column_name(index_name)} rename to #{quote_column_name(new_index_name)}"
|
202
|
+
ensure
|
203
|
+
self.all_schema_indexes = nil
|
204
|
+
end
|
205
|
+
|
192
206
|
def add_column(table_name, column_name, type, options = {}) #:nodoc:
|
193
207
|
add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
|
194
|
-
options
|
195
|
-
|
208
|
+
add_column_options!(add_column_sql, options.merge(:type=>type, :column_name=>column_name, :table_name=>table_name))
|
209
|
+
add_column_sql << tablespace_for((type_to_sql(type).downcase.to_sym), nil, table_name, column_name)
|
196
210
|
execute(add_column_sql)
|
197
211
|
ensure
|
198
212
|
clear_table_columns_cache(table_name)
|
@@ -224,8 +238,8 @@ module ActiveRecord
|
|
224
238
|
end
|
225
239
|
|
226
240
|
change_column_sql = "ALTER TABLE #{quote_table_name(table_name)} MODIFY #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
|
227
|
-
options
|
228
|
-
|
241
|
+
add_column_options!(change_column_sql, options.merge(:type=>type, :column_name=>column_name, :table_name=>table_name))
|
242
|
+
change_column_sql << tablespace_for((type_to_sql(type).downcase.to_sym), nil, options[:table_name], options[:column_name])
|
229
243
|
execute(change_column_sql)
|
230
244
|
ensure
|
231
245
|
clear_table_columns_cache(table_name)
|
@@ -280,8 +294,33 @@ module ActiveRecord
|
|
280
294
|
super
|
281
295
|
end
|
282
296
|
|
297
|
+
def tablespace(table_name)
|
298
|
+
select_value <<-SQL
|
299
|
+
SELECT tablespace_name
|
300
|
+
FROM user_tables
|
301
|
+
WHERE table_name='#{table_name.to_s.upcase}'
|
302
|
+
SQL
|
303
|
+
end
|
304
|
+
|
283
305
|
private
|
284
306
|
|
307
|
+
def tablespace_for(obj_type, tablespace_option, table_name=nil, column_name=nil)
|
308
|
+
tablespace_sql = ''
|
309
|
+
if tablespace = (tablespace_option || default_tablespace_for(obj_type))
|
310
|
+
tablespace_sql << if [:blob, :clob].include?(obj_type.to_sym)
|
311
|
+
" LOB (#{column_name}) STORE AS #{column_name.to_s[0..10]}_#{table_name.to_s[0..14]}_ls (TABLESPACE #{tablespace})"
|
312
|
+
else
|
313
|
+
" TABLESPACE #{tablespace}"
|
314
|
+
end
|
315
|
+
end
|
316
|
+
tablespace_sql
|
317
|
+
end
|
318
|
+
|
319
|
+
def default_tablespace_for(type)
|
320
|
+
(default_tablespaces[type] || default_tablespaces[native_database_types[type][:name]]) rescue nil
|
321
|
+
end
|
322
|
+
|
323
|
+
|
285
324
|
def column_for(table_name, column_name)
|
286
325
|
unless column = columns(table_name).find { |c| c.name == column_name.to_s }
|
287
326
|
raise "No such column: #{table_name}.#{column_name}"
|
@@ -21,7 +21,7 @@ module ActiveRecord
|
|
21
21
|
# # ...
|
22
22
|
# end
|
23
23
|
#
|
24
|
-
def add_primary_key_trigger(table_name, options)
|
24
|
+
def add_primary_key_trigger(table_name, options={})
|
25
25
|
# call the same private method that is used for create_table :primary_key_trigger => true
|
26
26
|
create_primary_key_trigger(table_name, options)
|
27
27
|
end
|
@@ -6,21 +6,21 @@ module ActiveRecord #:nodoc:
|
|
6
6
|
STATEMENT_TOKEN = "\n\n/\n\n"
|
7
7
|
|
8
8
|
def structure_dump #:nodoc:
|
9
|
-
structure = select_values("
|
9
|
+
structure = select_values("SELECT sequence_name FROM user_sequences ORDER BY 1").map do |seq|
|
10
10
|
"CREATE SEQUENCE \"#{seq}\""
|
11
11
|
end
|
12
|
-
select_values("
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
select_values("SELECT table_name FROM all_tables t
|
13
|
+
WHERE owner = SYS_CONTEXT('userenv', 'session_user') AND secondary = 'N'
|
14
|
+
AND NOT EXISTS (SELECT mv.mview_name FROM all_mviews mv WHERE mv.owner = t.owner AND mv.mview_name = t.table_name)
|
15
|
+
AND NOT EXISTS (SELECT mvl.log_table FROM all_mview_logs mvl WHERE mvl.log_owner = t.owner AND mvl.log_table = t.table_name)
|
16
|
+
ORDER BY 1").each do |table_name|
|
17
17
|
virtual_columns = virtual_columns_for(table_name)
|
18
18
|
ddl = "CREATE#{ ' GLOBAL TEMPORARY' if temporary_table?(table_name)} TABLE \"#{table_name}\" (\n"
|
19
19
|
cols = select_all(%Q{
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
SELECT column_name, data_type, data_length, char_used, char_length, data_precision, data_scale, data_default, nullable
|
21
|
+
FROM user_tab_columns
|
22
|
+
WHERE table_name = '#{table_name}'
|
23
|
+
ORDER BY column_id
|
24
24
|
}).map do |row|
|
25
25
|
if(v = virtual_columns.find {|col| col['column_name'] == row['column_name']})
|
26
26
|
structure_dump_virtual_column(row, v['data_default'])
|
@@ -71,13 +71,13 @@ module ActiveRecord #:nodoc:
|
|
71
71
|
def structure_dump_primary_key(table) #:nodoc:
|
72
72
|
opts = {:name => '', :cols => []}
|
73
73
|
pks = select_all(<<-SQL, "Primary Keys")
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
74
|
+
SELECT a.constraint_name, a.column_name, a.position
|
75
|
+
FROM user_cons_columns a
|
76
|
+
JOIN user_constraints c
|
77
|
+
ON a.constraint_name = c.constraint_name
|
78
|
+
WHERE c.table_name = '#{table.upcase}'
|
79
|
+
AND c.constraint_type = 'P'
|
80
|
+
AND c.owner = SYS_CONTEXT('userenv', 'session_user')
|
81
81
|
SQL
|
82
82
|
pks.each do |row|
|
83
83
|
opts[:name] = row['constraint_name']
|
@@ -89,13 +89,13 @@ module ActiveRecord #:nodoc:
|
|
89
89
|
def structure_dump_unique_keys(table) #:nodoc:
|
90
90
|
keys = {}
|
91
91
|
uks = select_all(<<-SQL, "Primary Keys")
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
92
|
+
SELECT a.constraint_name, a.column_name, a.position
|
93
|
+
FROM user_cons_columns a
|
94
|
+
JOIN user_constraints c
|
95
|
+
ON a.constraint_name = c.constraint_name
|
96
|
+
WHERE c.table_name = '#{table.upcase}'
|
97
|
+
AND c.constraint_type = 'U'
|
98
|
+
AND c.owner = SYS_CONTEXT('userenv', 'session_user')
|
99
99
|
SQL
|
100
100
|
uks.each do |uk|
|
101
101
|
keys[uk['constraint_name']] ||= []
|
@@ -123,7 +123,7 @@ module ActiveRecord #:nodoc:
|
|
123
123
|
end
|
124
124
|
|
125
125
|
def structure_dump_fk_constraints #:nodoc:
|
126
|
-
fks = select_all("
|
126
|
+
fks = select_all("SELECT table_name FROM all_tables WHERE owner = SYS_CONTEXT('userenv', 'session_user') ORDER BY 1").map do |table|
|
127
127
|
if respond_to?(:foreign_keys) && (foreign_keys = foreign_keys(table["table_name"])).any?
|
128
128
|
foreign_keys.map do |fk|
|
129
129
|
sql = "ALTER TABLE #{quote_table_name(fk.from_table)} ADD CONSTRAINT #{quote_column_name(fk.options[:name])} "
|
@@ -143,19 +143,19 @@ module ActiveRecord #:nodoc:
|
|
143
143
|
# Extract all stored procedures, packages, synonyms and views.
|
144
144
|
def structure_dump_db_stored_code #:nodoc:
|
145
145
|
structure = []
|
146
|
-
select_all("
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
146
|
+
select_all("SELECT DISTINCT name, type
|
147
|
+
FROM all_source
|
148
|
+
WHERE type IN ('PROCEDURE', 'PACKAGE', 'PACKAGE BODY', 'FUNCTION', 'TRIGGER', 'TYPE')
|
149
|
+
AND name NOT LIKE 'BIN$%'
|
150
|
+
AND owner = SYS_CONTEXT('userenv', 'session_user') ORDER BY type").each do |source|
|
151
151
|
ddl = "CREATE OR REPLACE \n"
|
152
152
|
lines = select_all(%Q{
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
153
|
+
SELECT text
|
154
|
+
FROM all_source
|
155
|
+
WHERE name = '#{source['name']}'
|
156
|
+
AND type = '#{source['type']}'
|
157
|
+
AND owner = SYS_CONTEXT('userenv', 'session_user')
|
158
|
+
ORDER BY line
|
159
159
|
}).map do |row|
|
160
160
|
ddl << row['text']
|
161
161
|
end
|
@@ -164,14 +164,14 @@ module ActiveRecord #:nodoc:
|
|
164
164
|
end
|
165
165
|
|
166
166
|
# export views
|
167
|
-
select_all("
|
167
|
+
select_all("SELECT view_name, text FROM user_views").each do |view|
|
168
168
|
structure << "CREATE OR REPLACE VIEW #{view['view_name']} AS\n #{view['text']}"
|
169
169
|
end
|
170
170
|
|
171
171
|
# export synonyms
|
172
|
-
select_all("
|
173
|
-
|
174
|
-
|
172
|
+
select_all("SELECT owner, synonym_name, table_name, table_owner
|
173
|
+
FROM all_synonyms
|
174
|
+
WHERE owner = SYS_CONTEXT('userenv', 'session_user') ").each do |synonym|
|
175
175
|
structure << "CREATE OR REPLACE #{synonym['owner'] == 'PUBLIC' ? 'PUBLIC' : '' } SYNONYM #{synonym['synonym_name']}"
|
176
176
|
structure << " FOR #{synonym['table_owner']}.#{synonym['table_name']}"
|
177
177
|
end
|
@@ -180,14 +180,14 @@ module ActiveRecord #:nodoc:
|
|
180
180
|
end
|
181
181
|
|
182
182
|
def structure_drop #:nodoc:
|
183
|
-
statements = select_values("
|
183
|
+
statements = select_values("SELECT sequence_name FROM user_sequences ORDER BY 1").map do |seq|
|
184
184
|
"DROP SEQUENCE \"#{seq}\""
|
185
185
|
end
|
186
|
-
select_values("
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
186
|
+
select_values("SELECT table_name from all_tables t
|
187
|
+
WHERE owner = SYS_CONTEXT('userenv', 'session_user') AND secondary = 'N'
|
188
|
+
AND NOT EXISTS (SELECT mv.mview_name FROM all_mviews mv WHERE mv.owner = t.owner AND mv.mview_name = t.table_name)
|
189
|
+
AND NOT EXISTS (SELECT mvl.log_table FROM all_mview_logs mvl WHERE mvl.log_owner = t.owner AND mvl.log_table = t.table_name)
|
190
|
+
ORDER BY 1").each do |table|
|
191
191
|
statements << "DROP TABLE \"#{table}\" CASCADE CONSTRAINTS"
|
192
192
|
end
|
193
193
|
join_with_statement_token(statements)
|
@@ -195,8 +195,8 @@ module ActiveRecord #:nodoc:
|
|
195
195
|
|
196
196
|
def temp_table_drop #:nodoc:
|
197
197
|
join_with_statement_token(select_values(
|
198
|
-
"
|
199
|
-
|
198
|
+
"SELECT table_name FROM all_tables
|
199
|
+
WHERE owner = SYS_CONTEXT('userenv', 'session_user') AND secondary = 'N' AND temporary = 'Y' ORDER BY 1").map do |table|
|
200
200
|
"DROP TABLE \"#{table}\" CASCADE CONSTRAINTS"
|
201
201
|
end)
|
202
202
|
end
|
@@ -249,10 +249,10 @@ module ActiveRecord #:nodoc:
|
|
249
249
|
def virtual_columns_for(table)
|
250
250
|
begin
|
251
251
|
select_all <<-SQL
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
252
|
+
SELECT column_name, data_default
|
253
|
+
FROM user_tab_cols
|
254
|
+
WHERE virtual_column = 'YES'
|
255
|
+
AND table_name = '#{table.upcase}'
|
256
256
|
SQL
|
257
257
|
# feature not supported previous to 11g
|
258
258
|
rescue ActiveRecord::StatementInvalid => e
|
@@ -263,14 +263,14 @@ module ActiveRecord #:nodoc:
|
|
263
263
|
def drop_sql_for_feature(type)
|
264
264
|
short_type = type == 'materialized view' ? 'mview' : type
|
265
265
|
join_with_statement_token(
|
266
|
-
select_values("
|
266
|
+
select_values("SELECT #{short_type}_name FROM user_#{short_type.tableize}").map do |name|
|
267
267
|
"DROP #{type.upcase} \"#{name}\""
|
268
268
|
end)
|
269
269
|
end
|
270
270
|
|
271
271
|
def drop_sql_for_object(type)
|
272
272
|
join_with_statement_token(
|
273
|
-
select_values("
|
273
|
+
select_values("SELECT object_name FROM user_objects WHERE object_type = '#{type.upcase}'").map do |name|
|
274
274
|
"DROP #{type.upcase} \"#{name}\""
|
275
275
|
end)
|
276
276
|
end
|
@@ -43,6 +43,8 @@ describe "OracleEnhancedAdapter" do
|
|
43
43
|
|
44
44
|
describe "database session store" do
|
45
45
|
before(:all) do
|
46
|
+
@conn.execute "DROP TABLE sessions" rescue nil
|
47
|
+
@conn.execute "DROP SEQUENCE sessions_seq" rescue nil
|
46
48
|
@conn = ActiveRecord::Base.connection
|
47
49
|
@conn.execute <<-SQL
|
48
50
|
CREATE TABLE sessions (
|
@@ -112,6 +114,7 @@ describe "OracleEnhancedAdapter" do
|
|
112
114
|
describe "ignore specified table columns" do
|
113
115
|
before(:all) do
|
114
116
|
@conn = ActiveRecord::Base.connection
|
117
|
+
@conn.execute "DROP TABLE test_employees" rescue nil
|
115
118
|
@conn.execute <<-SQL
|
116
119
|
CREATE TABLE test_employees (
|
117
120
|
id NUMBER PRIMARY KEY,
|
@@ -128,6 +131,7 @@ describe "OracleEnhancedAdapter" do
|
|
128
131
|
created_at DATE
|
129
132
|
)
|
130
133
|
SQL
|
134
|
+
@conn.execute "DROP SEQUENCE test_employees_seq" rescue nil
|
131
135
|
@conn.execute <<-SQL
|
132
136
|
CREATE SEQUENCE test_employees_seq MINVALUE 1
|
133
137
|
INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE
|
@@ -142,6 +146,7 @@ describe "OracleEnhancedAdapter" do
|
|
142
146
|
after(:each) do
|
143
147
|
Object.send(:remove_const, "TestEmployee")
|
144
148
|
ActiveRecord::Base.connection.clear_ignored_table_columns
|
149
|
+
ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
|
145
150
|
end
|
146
151
|
|
147
152
|
it "should ignore specified table columns" do
|
@@ -181,16 +186,18 @@ describe "OracleEnhancedAdapter" do
|
|
181
186
|
before(:all) do
|
182
187
|
@conn = ActiveRecord::Base.connection
|
183
188
|
@conn.execute "DROP TABLE test_employees" rescue nil
|
189
|
+
@oracle11g = !! @conn.select_value("SELECT * FROM v$version WHERE banner LIKE 'Oracle%11g%'")
|
184
190
|
@conn.execute <<-SQL
|
185
191
|
CREATE TABLE test_employees (
|
186
192
|
id NUMBER PRIMARY KEY,
|
187
193
|
first_name VARCHAR2(20),
|
188
194
|
last_name VARCHAR2(25),
|
195
|
+
#{ @oracle11g ? "full_name AS (first_name || ' ' || last_name)," : "full_name VARCHAR2(46),"}
|
189
196
|
hire_date DATE
|
190
197
|
)
|
191
198
|
SQL
|
192
|
-
@column_names = ['id', 'first_name', 'last_name', 'hire_date']
|
193
|
-
@column_sql_types = ["NUMBER", "VARCHAR2(20)", "VARCHAR2(25)", "DATE"]
|
199
|
+
@column_names = ['id', 'first_name', 'last_name', 'full_name', 'hire_date']
|
200
|
+
@column_sql_types = ["NUMBER", "VARCHAR2(20)", "VARCHAR2(25)", "VARCHAR2(46)", "DATE"]
|
194
201
|
class ::TestEmployee < ActiveRecord::Base
|
195
202
|
end
|
196
203
|
# Another class using the same table
|
@@ -205,6 +212,7 @@ describe "OracleEnhancedAdapter" do
|
|
205
212
|
Object.send(:remove_const, "TestEmployee2")
|
206
213
|
@conn.execute "DROP TABLE test_employees"
|
207
214
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = nil
|
215
|
+
ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
|
208
216
|
end
|
209
217
|
|
210
218
|
before(:each) do
|
@@ -223,16 +231,22 @@ describe "OracleEnhancedAdapter" do
|
|
223
231
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = false
|
224
232
|
end
|
225
233
|
|
234
|
+
it 'should identify virtual columns as such' do
|
235
|
+
pending "Not supported in this database version" unless @oracle11g
|
236
|
+
te = TestEmployee.connection.columns('test_employees').detect(&:virtual?)
|
237
|
+
te.name.should == 'full_name'
|
238
|
+
end
|
239
|
+
|
226
240
|
it "should get columns from database at first time" do
|
227
241
|
TestEmployee.connection.columns('test_employees').map(&:name).should == @column_names
|
228
|
-
@logger.logged(:debug).last.should =~ /select .* from
|
242
|
+
@logger.logged(:debug).last.should =~ /select .* from all_tab_cols/im
|
229
243
|
end
|
230
244
|
|
231
245
|
it "should get columns from database at second time" do
|
232
246
|
TestEmployee.connection.columns('test_employees')
|
233
247
|
@logger.clear(:debug)
|
234
248
|
TestEmployee.connection.columns('test_employees').map(&:name).should == @column_names
|
235
|
-
@logger.logged(:debug).last.should =~ /select .* from
|
249
|
+
@logger.logged(:debug).last.should =~ /select .* from all_tab_cols/im
|
236
250
|
end
|
237
251
|
|
238
252
|
it "should get primary key from database at first time" do
|
@@ -264,7 +278,7 @@ describe "OracleEnhancedAdapter" do
|
|
264
278
|
|
265
279
|
it "should get columns from database at first time" do
|
266
280
|
TestEmployee.connection.columns('test_employees').map(&:name).should == @column_names
|
267
|
-
@logger.logged(:debug).last.should =~ /select .* from
|
281
|
+
@logger.logged(:debug).last.should =~ /select .* from all_tab_cols/im
|
268
282
|
end
|
269
283
|
|
270
284
|
it "should get columns from cache at second time" do
|
@@ -310,6 +324,7 @@ describe "OracleEnhancedAdapter" do
|
|
310
324
|
after(:all) do
|
311
325
|
Object.send(:remove_const, "TestEmployee")
|
312
326
|
@conn.execute "DROP TABLE test_employees"
|
327
|
+
ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
|
313
328
|
end
|
314
329
|
|
315
330
|
it "should tell ActiveRecord that count distinct is supported" do
|
@@ -342,6 +357,7 @@ describe "OracleEnhancedAdapter" do
|
|
342
357
|
end
|
343
358
|
Object.send(:remove_const, "TestReservedWord")
|
344
359
|
ActiveRecord::Base.table_name_prefix = nil
|
360
|
+
ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
|
345
361
|
end
|
346
362
|
|
347
363
|
before(:each) do
|
@@ -371,6 +387,10 @@ describe "OracleEnhancedAdapter" do
|
|
371
387
|
end
|
372
388
|
end
|
373
389
|
|
390
|
+
it "should remove double quotes in column quoting" do
|
391
|
+
ActiveRecord::Base.connection.quote_column_name('aaa "bbb" ccc').should == '"aaa bbb ccc"'
|
392
|
+
end
|
393
|
+
|
374
394
|
end
|
375
395
|
|
376
396
|
describe "valid table names" do
|
@@ -527,6 +547,7 @@ describe "OracleEnhancedAdapter" do
|
|
527
547
|
@conn.execute "DROP DATABASE LINK #{@db_link}" rescue nil
|
528
548
|
@sys_conn.drop_table :test_posts rescue nil
|
529
549
|
Object.send(:remove_const, "TestPost") rescue nil
|
550
|
+
ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
|
530
551
|
end
|
531
552
|
|
532
553
|
it "should verify database link" do
|
@@ -563,8 +584,13 @@ describe "OracleEnhancedAdapter" do
|
|
563
584
|
|
564
585
|
describe "temporary tables" do
|
565
586
|
before(:all) do
|
587
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:table] = 'UNUSED'
|
588
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = 'UNUSED'
|
566
589
|
@conn = ActiveRecord::Base.connection
|
567
590
|
end
|
591
|
+
after(:all) do
|
592
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces={}
|
593
|
+
end
|
568
594
|
|
569
595
|
after(:each) do
|
570
596
|
@conn.drop_table :foos rescue nil
|
@@ -572,6 +598,7 @@ describe "OracleEnhancedAdapter" do
|
|
572
598
|
it "should create ok" do
|
573
599
|
@conn.create_table :foos, :temporary => true, :id => false do |t|
|
574
600
|
t.integer :id
|
601
|
+
t.text :bar
|
575
602
|
end
|
576
603
|
end
|
577
604
|
it "should show up as temporary" do
|
@@ -616,6 +643,7 @@ describe "OracleEnhancedAdapter" do
|
|
616
643
|
end
|
617
644
|
Object.send(:remove_const, "TestPost")
|
618
645
|
Object.send(:remove_const, "TestComment")
|
646
|
+
ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
|
619
647
|
end
|
620
648
|
|
621
649
|
it "should load included association with more than 1000 records" do
|