activerecord-oracle_enhanced-adapter 1.3.0 → 1.3.1
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/.gitignore +3 -1
- data/Gemfile +37 -0
- data/History.txt +17 -0
- data/README.rdoc +9 -4
- data/RUNNING_TESTS.rdoc +28 -0
- data/VERSION +1 -1
- data/activerecord-oracle_enhanced-adapter.gemspec +13 -6
- data/lib/active_record/connection_adapters/oracle_enhanced.rake +32 -24
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +19 -793
- data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +79 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +106 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +32 -2
- data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +3 -44
- data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +2 -2
- data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +4 -2
- data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +19 -3
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +14 -6
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +331 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +46 -14
- data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +290 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +15 -10
- data/lib/activerecord-oracle_enhanced-adapter.rb +25 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +51 -19
- data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +1 -1
- data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +31 -2
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +152 -11
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +27 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +19 -1
- data/spec/active_record/connection_adapters/{oracle_enhanced_schema_spec.rb → oracle_enhanced_schema_statements_spec.rb} +44 -1
- data/spec/active_record/connection_adapters/{oracle_enhanced_adapter_structure_dumper_spec.rb → oracle_enhanced_structure_dump_spec.rb} +49 -1
- data/spec/spec_helper.rb +60 -53
- metadata +15 -8
@@ -52,31 +52,51 @@ module ActiveRecord
|
|
52
52
|
# people_best_friend_id_fk FOREIGN KEY (best_friend_id) REFERENCES people (id)
|
53
53
|
# ON DELETE SET NULL
|
54
54
|
#
|
55
|
+
# ==== Creating a composite foreign key
|
56
|
+
# add_foreign_key(:comments, :posts, :columns => ['post_id', 'author_id'], :name => 'comments_post_fk')
|
57
|
+
# generates
|
58
|
+
# ALTER TABLE comments ADD CONSTRAINT
|
59
|
+
# comments_post_fk FOREIGN KEY (post_id, author_id) REFERENCES posts (post_id, author_id)
|
60
|
+
#
|
55
61
|
# === Supported options
|
56
62
|
# [:column]
|
57
63
|
# Specify the column name on the from_table that references the to_table. By default this is guessed
|
58
64
|
# to be the singular name of the to_table with "_id" suffixed. So a to_table of :posts will use "post_id"
|
59
65
|
# as the default <tt>:column</tt>.
|
66
|
+
# [:columns]
|
67
|
+
# An array of column names when defining composite foreign keys. An alias of <tt>:column</tt> provided for improved readability.
|
60
68
|
# [:primary_key]
|
61
69
|
# Specify the column name on the to_table that is referenced by this foreign key. By default this is
|
62
|
-
# assumed to be "id".
|
70
|
+
# assumed to be "id". Ignored when defining composite foreign keys.
|
63
71
|
# [:name]
|
64
72
|
# Specify the name of the foreign key constraint. This defaults to use from_table and foreign key column.
|
65
73
|
# [:dependent]
|
66
74
|
# If set to <tt>:delete</tt>, the associated records in from_table are deleted when records in to_table table are deleted.
|
67
75
|
# If set to <tt>:nullify</tt>, the foreign key column is set to +NULL+.
|
68
76
|
def add_foreign_key(from_table, to_table, options = {})
|
69
|
-
|
70
|
-
constraint_name = foreign_key_constraint_name(from_table,
|
77
|
+
columns = options[:column] || options[:columns] || "#{to_table.to_s.singularize}_id"
|
78
|
+
constraint_name = foreign_key_constraint_name(from_table, columns, options)
|
71
79
|
sql = "ALTER TABLE #{quote_table_name(from_table)} ADD CONSTRAINT #{quote_column_name(constraint_name)} "
|
72
80
|
sql << foreign_key_definition(to_table, options)
|
73
81
|
execute sql
|
74
82
|
end
|
75
83
|
|
76
84
|
def foreign_key_definition(to_table, options = {}) #:nodoc:
|
77
|
-
|
78
|
-
|
79
|
-
|
85
|
+
columns = Array(options[:column] || options[:columns])
|
86
|
+
|
87
|
+
if columns.size > 1
|
88
|
+
# composite foreign key
|
89
|
+
columns_sql = columns.map {|c| quote_column_name(c)}.join(',')
|
90
|
+
references = options[:references] || columns
|
91
|
+
references_sql = references.map {|c| quote_column_name(c)}.join(',')
|
92
|
+
else
|
93
|
+
columns_sql = quote_column_name(columns.first || "#{to_table.to_s.singularize}_id")
|
94
|
+
references = options[:references] ? options[:references].first : nil
|
95
|
+
references_sql = quote_column_name(options[:primary_key] || references || "id")
|
96
|
+
end
|
97
|
+
|
98
|
+
sql = "FOREIGN KEY (#{columns_sql}) REFERENCES #{quote_table_name(to_table)}(#{references_sql})"
|
99
|
+
|
80
100
|
case options[:dependent]
|
81
101
|
when :nullify
|
82
102
|
sql << " ON DELETE SET NULL"
|
@@ -106,9 +126,12 @@ module ActiveRecord
|
|
106
126
|
|
107
127
|
private
|
108
128
|
|
109
|
-
def foreign_key_constraint_name(table_name,
|
110
|
-
|
129
|
+
def foreign_key_constraint_name(table_name, columns, options = {})
|
130
|
+
columns = Array(columns)
|
131
|
+
constraint_name = original_name = options[:name] || "#{table_name}_#{columns.join('_')}_fk"
|
132
|
+
|
111
133
|
return constraint_name if constraint_name.length <= OracleEnhancedAdapter::IDENTIFIER_MAX_LENGTH
|
134
|
+
|
112
135
|
# leave just first three letters from each word
|
113
136
|
constraint_name = constraint_name.split('_').map{|w| w[0,3]}.join('_')
|
114
137
|
# generate unique name using hash function
|
@@ -128,7 +151,7 @@ module ActiveRecord
|
|
128
151
|
|
129
152
|
fk_info = select_all(<<-SQL, 'Foreign Keys')
|
130
153
|
SELECT r.table_name to_table
|
131
|
-
,rc.column_name
|
154
|
+
,rc.column_name references_column
|
132
155
|
,cc.column_name
|
133
156
|
,c.constraint_name name
|
134
157
|
,c.delete_rule
|
@@ -144,18 +167,27 @@ module ActiveRecord
|
|
144
167
|
AND rc.owner = r.owner
|
145
168
|
AND rc.constraint_name = r.constraint_name
|
146
169
|
AND rc.position = cc.position
|
170
|
+
ORDER BY name, to_table, column_name, references_column
|
147
171
|
SQL
|
148
172
|
|
173
|
+
fks = {}
|
174
|
+
|
149
175
|
fk_info.map do |row|
|
150
|
-
|
151
|
-
|
176
|
+
name = oracle_downcase(row['name'])
|
177
|
+
fks[name] ||= { :columns => [], :to_table => oracle_downcase(row['to_table']), :references => [] }
|
178
|
+
fks[name][:columns] << oracle_downcase(row['column_name'])
|
179
|
+
fks[name][:references] << oracle_downcase(row['references_column'])
|
152
180
|
case row['delete_rule']
|
153
181
|
when 'CASCADE'
|
154
|
-
|
182
|
+
fks[name][:dependent] = :delete
|
155
183
|
when 'SET NULL'
|
156
|
-
|
184
|
+
fks[name][:dependent] = :nullify
|
157
185
|
end
|
158
|
-
|
186
|
+
end
|
187
|
+
|
188
|
+
fks.map do |k, v|
|
189
|
+
options = {:name => k, :columns => v[:columns], :references => v[:references], :dependent => v[:dependent]}
|
190
|
+
OracleEnhancedForeignKeyDefinition.new(table_name, v[:to_table], options)
|
159
191
|
end
|
160
192
|
end
|
161
193
|
|
@@ -0,0 +1,290 @@
|
|
1
|
+
module ActiveRecord #:nodoc:
|
2
|
+
module ConnectionAdapters #:nodoc:
|
3
|
+
module OracleEnhancedStructureDump #:nodoc:
|
4
|
+
|
5
|
+
# Statements separator used in structure dump to allow loading of structure dump also with SQL*Plus
|
6
|
+
STATEMENT_TOKEN = "\n\n/\n\n"
|
7
|
+
|
8
|
+
def structure_dump #:nodoc:
|
9
|
+
structure = select_values("select sequence_name from user_sequences order by 1").map do |seq|
|
10
|
+
"CREATE SEQUENCE \"#{seq}\""
|
11
|
+
end
|
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
|
+
virtual_columns = virtual_columns_for(table_name)
|
18
|
+
ddl = "CREATE#{ ' GLOBAL TEMPORARY' if temporary_table?(table_name)} TABLE \"#{table_name}\" (\n"
|
19
|
+
cols = select_all(%Q{
|
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
|
+
}).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'])
|
27
|
+
else
|
28
|
+
structure_dump_column(row)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
ddl << cols.join(",\n ")
|
32
|
+
ddl << structure_dump_primary_key(table_name)
|
33
|
+
ddl << "\n)"
|
34
|
+
structure << ddl
|
35
|
+
structure << structure_dump_indexes(table_name)
|
36
|
+
structure << structure_dump_unique_keys(table_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
join_with_statement_token(structure) << structure_dump_fk_constraints
|
40
|
+
end
|
41
|
+
|
42
|
+
def structure_dump_column(column) #:nodoc:
|
43
|
+
col = "\"#{column['column_name']}\" #{column['data_type']}"
|
44
|
+
if column['data_type'] =='NUMBER' and !column['data_precision'].nil?
|
45
|
+
col << "(#{column['data_precision'].to_i}"
|
46
|
+
col << ",#{column['data_scale'].to_i}" if !column['data_scale'].nil?
|
47
|
+
col << ')'
|
48
|
+
elsif column['data_type'].include?('CHAR')
|
49
|
+
length = column['char_used'] == 'C' ? column['char_length'].to_i : column['data_length'].to_i
|
50
|
+
col << "(#{length})"
|
51
|
+
end
|
52
|
+
col << " DEFAULT #{column['data_default']}" if !column['data_default'].nil?
|
53
|
+
col << ' NOT NULL' if column['nullable'] == 'N'
|
54
|
+
col
|
55
|
+
end
|
56
|
+
|
57
|
+
def structure_dump_virtual_column(column, data_default) #:nodoc:
|
58
|
+
data_default = data_default.gsub(/"/, '')
|
59
|
+
col = "\"#{column['column_name']}\" #{column['data_type']}"
|
60
|
+
if column['data_type'] =='NUMBER' and !column['data_precision'].nil?
|
61
|
+
col << "(#{column['data_precision'].to_i}"
|
62
|
+
col << ",#{column['data_scale'].to_i}" if !column['data_scale'].nil?
|
63
|
+
col << ')'
|
64
|
+
elsif column['data_type'].include?('CHAR')
|
65
|
+
length = column['char_used'] == 'C' ? column['char_length'].to_i : column['data_length'].to_i
|
66
|
+
col << "(#{length})"
|
67
|
+
end
|
68
|
+
col << " GENERATED ALWAYS AS (#{data_default}) VIRTUAL"
|
69
|
+
end
|
70
|
+
|
71
|
+
def structure_dump_primary_key(table) #:nodoc:
|
72
|
+
opts = {:name => '', :cols => []}
|
73
|
+
pks = select_all(<<-SQL, "Primary Keys")
|
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
|
+
SQL
|
82
|
+
pks.each do |row|
|
83
|
+
opts[:name] = row['constraint_name']
|
84
|
+
opts[:cols][row['position']-1] = row['column_name']
|
85
|
+
end
|
86
|
+
opts[:cols].length > 0 ? ",\n CONSTRAINT #{opts[:name]} PRIMARY KEY (#{opts[:cols].join(',')})" : ''
|
87
|
+
end
|
88
|
+
|
89
|
+
def structure_dump_unique_keys(table) #:nodoc:
|
90
|
+
keys = {}
|
91
|
+
uks = select_all(<<-SQL, "Primary Keys")
|
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
|
+
SQL
|
100
|
+
uks.each do |uk|
|
101
|
+
keys[uk['constraint_name']] ||= []
|
102
|
+
keys[uk['constraint_name']][uk['position']-1] = uk['column_name']
|
103
|
+
end
|
104
|
+
keys.map do |k,v|
|
105
|
+
"ALTER TABLE #{table.upcase} ADD CONSTRAINT #{k} UNIQUE (#{v.join(',')})"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def structure_dump_indexes(table_name) #:nodoc:
|
110
|
+
indexes(table_name).map do |options|
|
111
|
+
column_names = options[:columns]
|
112
|
+
options = {:name => options[:name], :unique => options[:unique]}
|
113
|
+
index_name = index_name(table_name, :column => column_names)
|
114
|
+
if Hash === options # legacy support, since this param was a string
|
115
|
+
index_type = options[:unique] ? "UNIQUE" : ""
|
116
|
+
index_name = options[:name] || index_name
|
117
|
+
else
|
118
|
+
index_type = options
|
119
|
+
end
|
120
|
+
quoted_column_names = column_names.map { |e| quote_column_name(e) }.join(", ")
|
121
|
+
"CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def structure_dump_fk_constraints #:nodoc:
|
126
|
+
fks = select_all("select table_name from all_tables where owner = sys_context('userenv','session_user') order by 1").map do |table|
|
127
|
+
if respond_to?(:foreign_keys) && (foreign_keys = foreign_keys(table["table_name"])).any?
|
128
|
+
foreign_keys.map do |fk|
|
129
|
+
sql = "ALTER TABLE #{quote_table_name(fk.from_table)} ADD CONSTRAINT #{quote_column_name(fk.options[:name])} "
|
130
|
+
sql << "#{foreign_key_definition(fk.to_table, fk.options)}"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end.flatten.compact
|
134
|
+
join_with_statement_token(fks)
|
135
|
+
end
|
136
|
+
|
137
|
+
def dump_schema_information #:nodoc:
|
138
|
+
sm_table = ActiveRecord::Migrator.schema_migrations_table_name
|
139
|
+
migrated = select_values("SELECT version FROM #{sm_table}")
|
140
|
+
join_with_statement_token(migrated.map{|v| "INSERT INTO #{sm_table} (version) VALUES ('#{v}')" })
|
141
|
+
end
|
142
|
+
|
143
|
+
# Extract all stored procedures, packages, synonyms and views.
|
144
|
+
def structure_dump_db_stored_code #:nodoc:
|
145
|
+
structure = []
|
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
|
+
ddl = "CREATE OR REPLACE \n"
|
152
|
+
lines = select_all(%Q{
|
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
|
+
}).map do |row|
|
160
|
+
ddl << row['text']
|
161
|
+
end
|
162
|
+
ddl << ";" unless ddl.strip[-1,1] == ";"
|
163
|
+
structure << ddl
|
164
|
+
end
|
165
|
+
|
166
|
+
# export views
|
167
|
+
select_all("select view_name, text from user_views").each do |view|
|
168
|
+
structure << "CREATE OR REPLACE VIEW #{view['view_name']} AS\n #{view['text']}"
|
169
|
+
end
|
170
|
+
|
171
|
+
# export synonyms
|
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
|
+
structure << "CREATE OR REPLACE #{synonym['owner'] == 'PUBLIC' ? 'PUBLIC' : '' } SYNONYM #{synonym['synonym_name']}"
|
176
|
+
structure << " FOR #{synonym['table_owner']}.#{synonym['table_name']}"
|
177
|
+
end
|
178
|
+
|
179
|
+
join_with_statement_token(structure)
|
180
|
+
end
|
181
|
+
|
182
|
+
def structure_drop #:nodoc:
|
183
|
+
statements = select_values("select sequence_name from user_sequences order by 1").map do |seq|
|
184
|
+
"DROP SEQUENCE \"#{seq}\""
|
185
|
+
end
|
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
|
+
statements << "DROP TABLE \"#{table}\" CASCADE CONSTRAINTS"
|
192
|
+
end
|
193
|
+
join_with_statement_token(statements)
|
194
|
+
end
|
195
|
+
|
196
|
+
def temp_table_drop #:nodoc:
|
197
|
+
join_with_statement_token(select_values(
|
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
|
+
"DROP TABLE \"#{table}\" CASCADE CONSTRAINTS"
|
201
|
+
end)
|
202
|
+
end
|
203
|
+
|
204
|
+
def full_drop(preserve_tables=false) #:nodoc:
|
205
|
+
s = preserve_tables ? [] : [structure_drop]
|
206
|
+
s << temp_table_drop if preserve_tables
|
207
|
+
s << drop_sql_for_feature("view")
|
208
|
+
s << drop_sql_for_feature("materialized view")
|
209
|
+
s << drop_sql_for_feature("synonym")
|
210
|
+
s << drop_sql_for_feature("type")
|
211
|
+
s << drop_sql_for_object("package")
|
212
|
+
s << drop_sql_for_object("function")
|
213
|
+
s << drop_sql_for_object("procedure")
|
214
|
+
s.join
|
215
|
+
end
|
216
|
+
|
217
|
+
def add_column_options!(sql, options) #:nodoc:
|
218
|
+
type = options[:type] || ((column = options[:column]) && column.type)
|
219
|
+
type = type && type.to_sym
|
220
|
+
# handle case of defaults for CLOB columns, which would otherwise get "quoted" incorrectly
|
221
|
+
if options_include_default?(options)
|
222
|
+
if type == :text
|
223
|
+
sql << " DEFAULT #{quote(options[:default])}"
|
224
|
+
else
|
225
|
+
# from abstract adapter
|
226
|
+
sql << " DEFAULT #{quote(options[:default], options[:column])}"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
# must explicitly add NULL or NOT NULL to allow change_column to work on migrations
|
230
|
+
if options[:null] == false
|
231
|
+
sql << " NOT NULL"
|
232
|
+
elsif options[:null] == true
|
233
|
+
sql << " NULL" unless type == :primary_key
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def execute_structure_dump(string)
|
238
|
+
string.split(STATEMENT_TOKEN).each do |ddl|
|
239
|
+
ddl.chop! if ddl.last == ";"
|
240
|
+
execute(ddl) unless ddl.blank?
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
private
|
245
|
+
|
246
|
+
# virtual columns are an 11g feature. This returns [] if feature is not
|
247
|
+
# present or none are found.
|
248
|
+
# return [{'column_name' => 'FOOS', 'data_default' => '...'}, ...]
|
249
|
+
def virtual_columns_for(table)
|
250
|
+
begin
|
251
|
+
select_all <<-SQL
|
252
|
+
select column_name, data_default
|
253
|
+
from user_tab_cols
|
254
|
+
where virtual_column='YES'
|
255
|
+
and table_name='#{table.upcase}'
|
256
|
+
SQL
|
257
|
+
# feature not supported previous to 11g
|
258
|
+
rescue ActiveRecord::StatementInvalid => e
|
259
|
+
[]
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def drop_sql_for_feature(type)
|
264
|
+
short_type = type == 'materialized view' ? 'mview' : type
|
265
|
+
join_with_statement_token(
|
266
|
+
select_values("select #{short_type}_name from user_#{short_type.tableize}").map do |name|
|
267
|
+
"DROP #{type.upcase} \"#{name}\""
|
268
|
+
end)
|
269
|
+
end
|
270
|
+
|
271
|
+
def drop_sql_for_object(type)
|
272
|
+
join_with_statement_token(
|
273
|
+
select_values("select object_name from user_objects where object_type = '#{type.upcase}'").map do |name|
|
274
|
+
"DROP #{type.upcase} \"#{name}\""
|
275
|
+
end)
|
276
|
+
end
|
277
|
+
|
278
|
+
def join_with_statement_token(array)
|
279
|
+
string = array.join(STATEMENT_TOKEN)
|
280
|
+
string << STATEMENT_TOKEN unless string.blank?
|
281
|
+
string
|
282
|
+
end
|
283
|
+
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
|
289
|
+
include ActiveRecord::ConnectionAdapters::OracleEnhancedStructureDump
|
290
|
+
end
|
@@ -1,12 +1,17 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
if Rake.application.
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
# Used just for Rails 2.x
|
2
|
+
# In Rails 3.x rake tasks are loaded using railtie
|
3
|
+
if ActiveRecord::VERSION::MAJOR == 2
|
4
|
+
|
5
|
+
if defined?(Rake.application) && Rake.application &&
|
6
|
+
ActiveRecord::Base.configurations[defined?(Rails.env) ? Rails.env : RAILS_ENV]['adapter'] == 'oracle_enhanced'
|
7
|
+
oracle_enhanced_rakefile = File.dirname(__FILE__) + "/oracle_enhanced.rake"
|
8
|
+
if Rake.application.lookup("environment")
|
9
|
+
# rails tasks already defined; load the override tasks now
|
10
|
+
load oracle_enhanced_rakefile
|
11
|
+
else
|
12
|
+
# rails tasks not loaded yet; load as an import
|
13
|
+
Rake.application.add_import(oracle_enhanced_rakefile)
|
14
|
+
end
|
11
15
|
end
|
16
|
+
|
12
17
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# define railtie which will be executed in Rails 3
|
2
|
+
if defined?(::Rails::Railtie)
|
3
|
+
|
4
|
+
module ActiveRecord
|
5
|
+
module ConnectionAdapters
|
6
|
+
class OracleEnhancedRailtie < ::Rails::Railtie
|
7
|
+
rake_tasks do
|
8
|
+
load 'active_record/connection_adapters/oracle_enhanced.rake'
|
9
|
+
end
|
10
|
+
|
11
|
+
ActiveSupport.on_load(:active_record) do
|
12
|
+
require 'active_record/connection_adapters/oracle_enhanced_adapter'
|
13
|
+
|
14
|
+
# Cache column descriptions between requests in test and production environments
|
15
|
+
if Rails.env.test? || Rails.env.production?
|
16
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = true
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|