unclebilly-activerecord-oracle_enhanced-adapter 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/History.txt +165 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +32 -0
  4. data/README.rdoc +75 -0
  5. data/Rakefile +49 -0
  6. data/VERSION +1 -0
  7. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +5 -0
  8. data/lib/active_record/connection_adapters/oracle_enhanced.rake +51 -0
  9. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +1723 -0
  10. data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +121 -0
  11. data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +64 -0
  12. data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +21 -0
  13. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +39 -0
  14. data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +369 -0
  15. data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +396 -0
  16. data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +164 -0
  17. data/lib/active_record/connection_adapters/oracle_enhanced_reserved_words.rb +126 -0
  18. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +177 -0
  19. data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +214 -0
  20. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +224 -0
  21. data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +11 -0
  22. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +1 -0
  23. data/lib/active_record/connection_adapters/oracle_enhanced_virtual_column.rb +35 -0
  24. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +610 -0
  25. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_structure_dumper_spec.rb +266 -0
  26. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +206 -0
  27. data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +40 -0
  28. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +107 -0
  29. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +984 -0
  30. data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +67 -0
  31. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +93 -0
  32. data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +25 -0
  33. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +370 -0
  34. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +268 -0
  35. data/spec/active_record/connection_adapters/oracle_enhanced_schema_spec.rb +761 -0
  36. data/spec/spec.opts +6 -0
  37. data/spec/spec_helper.rb +130 -0
  38. metadata +149 -0
@@ -0,0 +1,266 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe "OracleEnhancedAdapter structure dump" do
4
+ include LoggerSpecHelper
5
+
6
+ before(:all) do
7
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
8
+ @conn = ActiveRecord::Base.connection
9
+ end
10
+ describe "structure dump" do
11
+ before(:each) do
12
+ @conn.create_table :test_posts, :force => true do |t|
13
+ t.string :title
14
+ t.string :foo
15
+ t.integer :foo_id
16
+ end
17
+ @conn.create_table :foos do |t|
18
+ end
19
+ class ::TestPost < ActiveRecord::Base
20
+ end
21
+ TestPost.set_table_name "test_posts"
22
+ end
23
+
24
+ after(:each) do
25
+ @conn.drop_table :test_posts
26
+ @conn.drop_table :foos
27
+ @conn.execute "DROP SEQUENCE test_posts_seq" rescue nil
28
+ @conn.execute "ALTER TABLE test_posts drop CONSTRAINT fk_test_post_foo" rescue nil
29
+ @conn.execute "DROP TRIGGER test_post_trigger" rescue nil
30
+ @conn.execute "DROP TYPE TEST_TYPE" rescue nil
31
+ @conn.execute "DROP TABLE bars" rescue nil
32
+ end
33
+
34
+ it "should dump single primary key" do
35
+ dump = ActiveRecord::Base.connection.structure_dump
36
+ dump.should =~ /CONSTRAINT (.+) PRIMARY KEY \(ID\)\n/
37
+ end
38
+
39
+ it "should dump composite primary keys" do
40
+ pk = @conn.send(:select_one, <<-SQL)
41
+ select constraint_name from user_constraints where table_name = 'TEST_POSTS' and constraint_type='P'
42
+ SQL
43
+ @conn.execute <<-SQL
44
+ alter table test_posts drop constraint #{pk["constraint_name"]}
45
+ SQL
46
+ @conn.execute <<-SQL
47
+ ALTER TABLE TEST_POSTS
48
+ add CONSTRAINT pk_id_title PRIMARY KEY (id, title)
49
+ SQL
50
+ dump = ActiveRecord::Base.connection.structure_dump
51
+ dump.should =~ /CONSTRAINT (.+) PRIMARY KEY \(ID,TITLE\)\n/
52
+ end
53
+
54
+ it "should dump foreign keys" do
55
+ @conn.execute <<-SQL
56
+ ALTER TABLE TEST_POSTS
57
+ ADD CONSTRAINT fk_test_post_foo FOREIGN KEY (foo_id) REFERENCES foos(id)
58
+ SQL
59
+ dump = ActiveRecord::Base.connection.structure_dump_fk_constraints
60
+ dump.split('\n').length.should == 1
61
+ dump.should =~ /ALTER TABLE TEST_POSTS ADD CONSTRAINT fk_test_post_foo FOREIGN KEY \(foo_id\) REFERENCES foos\(id\)/
62
+ end
63
+
64
+ it "should not error when no foreign keys are present" do
65
+ dump = ActiveRecord::Base.connection.structure_dump_fk_constraints
66
+ dump.split('\n').length.should == 0
67
+ dump.should == ''
68
+ end
69
+
70
+ it "should dump triggers" do
71
+ @conn.execute <<-SQL
72
+ create or replace TRIGGER TEST_POST_TRIGGER
73
+ BEFORE INSERT
74
+ ON TEST_POSTS
75
+ FOR EACH ROW
76
+ BEGIN
77
+ SELECT 'bar' INTO :new.FOO FROM DUAL;
78
+ END;
79
+ SQL
80
+ dump = ActiveRecord::Base.connection.structure_dump_db_stored_code.gsub(/\n|\s+/,' ')
81
+ dump.should =~ /create or replace TRIGGER TEST_POST_TRIGGER/
82
+ end
83
+
84
+ it "should dump types" do
85
+ @conn.execute <<-SQL
86
+ create or replace TYPE TEST_TYPE AS TABLE OF VARCHAR2(10);
87
+ SQL
88
+ dump = ActiveRecord::Base.connection.structure_dump_db_stored_code.gsub(/\n|\s+/,' ')
89
+ dump.should =~ /create or replace TYPE TEST_TYPE/
90
+ end
91
+
92
+ it "should dump virtual columns" do
93
+ @conn.execute <<-SQL
94
+ CREATE TABLE bars (
95
+ id NUMBER(38,0) NOT NULL,
96
+ id_plus NUMBER GENERATED ALWAYS AS(id + 2) VIRTUAL,
97
+ PRIMARY KEY (ID)
98
+ )
99
+ SQL
100
+ dump = ActiveRecord::Base.connection.structure_dump
101
+ dump.should =~ /id_plus number GENERATED ALWAYS AS \(ID\+2\) VIRTUAL/
102
+ end
103
+
104
+ it "should dump unique keys" do
105
+ @conn.execute <<-SQL
106
+ ALTER TABLE test_posts
107
+ add CONSTRAINT uk_foo_foo_id UNIQUE (foo, foo_id)
108
+ SQL
109
+ dump = ActiveRecord::Base.connection.structure_dump_unique_keys("test_posts")
110
+ dump.should == [" CONSTRAINT UK_FOO_FOO_ID UNIQUE (FOO,FOO_ID)"]
111
+
112
+ dump = ActiveRecord::Base.connection.structure_dump
113
+ dump.should =~ /CONSTRAINT UK_FOO_FOO_ID UNIQUE \(FOO,FOO_ID\)/
114
+ end
115
+
116
+ it "should dump indexes" do
117
+ ActiveRecord::Base.connection.add_index(:test_posts, :foo, :name => :ix_test_posts_foo)
118
+ ActiveRecord::Base.connection.add_index(:test_posts, :foo_id, :name => :ix_test_posts_foo_id, :unique => true)
119
+
120
+ @conn.execute <<-SQL
121
+ ALTER TABLE test_posts
122
+ add CONSTRAINT uk_foo_foo_id UNIQUE (foo, foo_id)
123
+ SQL
124
+
125
+ dump = ActiveRecord::Base.connection.structure_dump
126
+ dump.should =~ /create unique index ix_test_posts_foo_id on test_posts \(foo_id\)/i
127
+ dump.should =~ /create index ix_test_posts_foo on test_posts \(foo\)/i
128
+ dump.should_not =~ /create unique index uk_test_posts_/i
129
+ end
130
+ end
131
+ describe "temporary tables" do
132
+ after(:all) do
133
+ @conn.drop_table :test_comments rescue nil
134
+ end
135
+ it "should dump correctly" do
136
+ @conn.create_table :test_comments, :temporary => true, :id => false do |t|
137
+ t.integer :post_id
138
+ end
139
+ dump = ActiveRecord::Base.connection.structure_dump
140
+ dump.should =~ /create global temporary table test_comments/i
141
+ end
142
+ end
143
+
144
+ describe "database stucture dump extentions" do
145
+ before(:all) do
146
+ @conn.execute <<-SQL
147
+ CREATE TABLE nvarchartable (
148
+ unq_nvarchar NVARCHAR2(255) DEFAULT NULL
149
+ )
150
+ SQL
151
+ end
152
+
153
+ after(:all) do
154
+ @conn.execute "DROP TABLE nvarchartable"
155
+ end
156
+
157
+ it "should return the character size of nvarchar fields" do
158
+ if /.*unq_nvarchar nvarchar2\((\d+)\).*/ =~ @conn.structure_dump
159
+ "#$1".should == "255"
160
+ end
161
+ end
162
+ end
163
+
164
+ describe "temp_table_drop" do
165
+ before(:each) do
166
+ @conn.create_table :temp_tbl, :temporary => true do |t|
167
+ t.string :foo
168
+ end
169
+ @conn.create_table :not_temp_tbl do |t|
170
+ t.string :foo
171
+ end
172
+ end
173
+ it "should dump drop sql for just temp tables" do
174
+ dump = @conn.temp_table_drop
175
+ dump.should =~ /drop table temp_tbl/i
176
+ dump.should_not =~ /drop table not_temp_tbl/i
177
+ end
178
+ after(:each) do
179
+ @conn.drop_table :temp_tbl
180
+ @conn.drop_table :not_temp_tbl
181
+ end
182
+ end
183
+
184
+ describe "full drop" do
185
+ before(:each) do
186
+ @conn.create_table :full_drop_test do |t|
187
+ t.integer :id
188
+ end
189
+ @conn.create_table :full_drop_test_temp, :temporary => true do |t|
190
+ t.string :foo
191
+ end
192
+ #view
193
+ @conn.execute <<-SQL
194
+ create or replace view full_drop_test_view (foo) as select id as "foo" from full_drop_test
195
+ SQL
196
+ #package
197
+ @conn.execute <<-SQL
198
+ create or replace package full_drop_test_package as
199
+ function test_func return varchar2;
200
+ end test_package;
201
+ SQL
202
+ @conn.execute <<-SQL
203
+ create or replace package body full_drop_test_package as
204
+ function test_func return varchar2 is
205
+ begin
206
+ return ('foo');
207
+ end test_func;
208
+ end test_package;
209
+ SQL
210
+ #function
211
+ @conn.execute <<-SQL
212
+ create or replace function full_drop_test_function
213
+ return varchar2
214
+ is
215
+ foo varchar2(3);
216
+ begin
217
+ return('foo');
218
+ end;
219
+ SQL
220
+ #procedure
221
+ @conn.execute <<-SQL
222
+ create or replace procedure full_drop_test_procedure
223
+ begin
224
+ delete from full_drop_test where id=1231231231
225
+ exception
226
+ when no_data_found then
227
+ dbms_output.put_line('foo');
228
+ end;
229
+ SQL
230
+ #synonym
231
+ @conn.execute <<-SQL
232
+ create or replace synonym full_drop_test_synonym for full_drop_test
233
+ SQL
234
+ #type
235
+ @conn.execute <<-SQL
236
+ create or replace type full_drop_test_type as table of number
237
+ SQL
238
+ end
239
+ after(:each) do
240
+ @conn.drop_table :full_drop_test
241
+ @conn.drop_table :full_drop_test_temp
242
+ @conn.execute "DROP VIEW FULL_DROP_TEST_VIEW" rescue nil
243
+ @conn.execute "DROP SYNONYM FULL_DROP_TEST_SYNONYM" rescue nil
244
+ @conn.execute "DROP PACKAGE FULL_DROP_TEST_PACKAGE" rescue nil
245
+ @conn.execute "DROP FUNCTION FULL_DROP_TEST_FUNCTION" rescue nil
246
+ @conn.execute "DROP PROCEDURE FULL_DROP_TEST_PROCEDURE" rescue nil
247
+ @conn.execute "DROP TYPE FULL_DROP_TEST_TYPE" rescue nil
248
+ end
249
+ it "should contain correct sql" do
250
+ drop = @conn.full_drop
251
+ drop.should =~ /drop table full_drop_test cascade constraints/i
252
+ drop.should =~ /drop sequence full_drop_test_seq/i
253
+ drop.should =~ /drop view "full_drop_test_view"/i
254
+ drop.should =~ /drop package full_drop_test_package/i
255
+ drop.should =~ /drop function full_drop_test_function/i
256
+ drop.should =~ /drop procedure full_drop_test_procedure/i
257
+ drop.should =~ /drop synonym "full_drop_test_synonym"/i
258
+ drop.should =~ /drop type "full_drop_test_type"/i
259
+ end
260
+ it "should not drop tables when preserve_tables is true" do
261
+ drop = @conn.full_drop(true)
262
+ drop.should =~ /drop table full_drop_test_temp/i
263
+ drop.should_not =~ /drop table full_drop_test cascade constraints/i
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,206 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe "OracleEnhancedConnection create connection" do
4
+
5
+ before(:all) do
6
+ @conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(CONNECTION_PARAMS)
7
+ end
8
+
9
+ before(:each) do
10
+ @conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(CONNECTION_PARAMS) unless @conn.active?
11
+ end
12
+
13
+ after(:all) do
14
+ @conn.logoff if @conn.active?
15
+ end
16
+
17
+ it "should create new connection" do
18
+ @conn.should be_active
19
+ end
20
+
21
+ it "should ping active connection" do
22
+ @conn.ping.should be_true
23
+ end
24
+
25
+ it "should not ping inactive connection" do
26
+ @conn.logoff
27
+ lambda { @conn.ping }.should raise_error(ActiveRecord::ConnectionAdapters::OracleEnhancedConnectionException)
28
+ end
29
+
30
+ it "should reset active connection" do
31
+ @conn.reset!
32
+ @conn.should be_active
33
+ end
34
+
35
+ it "should be in autocommit mode after connection" do
36
+ @conn.should be_autocommit
37
+ end
38
+
39
+ end
40
+
41
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
42
+
43
+ describe "OracleEnhancedConnection create JDBC connection" do
44
+ after(:each) do
45
+ @conn.logoff if @conn.active?
46
+ end
47
+
48
+ it "should create new connection using :url" do
49
+ params = CONNECTION_PARAMS.dup
50
+ params[:url] = "jdbc:oracle:thin:@#{DATABASE_HOST}:#{DATABASE_PORT}:#{DATABASE_NAME}"
51
+ params[:host] = nil
52
+ params[:database] = nil
53
+ @conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(params)
54
+ @conn.should be_active
55
+ end
56
+
57
+ it "should create new connection using :url and tnsnames alias" do
58
+ params = CONNECTION_PARAMS.dup
59
+ params[:url] = "jdbc:oracle:thin:@#{DATABASE_NAME}"
60
+ params[:host] = nil
61
+ params[:database] = nil
62
+ @conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(params)
63
+ @conn.should be_active
64
+ end
65
+
66
+ it "should create new connection using just tnsnames alias" do
67
+ params = CONNECTION_PARAMS.dup
68
+ params[:host] = nil
69
+ @conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(params)
70
+ @conn.should be_active
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+
77
+ describe "OracleEnhancedConnection SQL execution" do
78
+
79
+ before(:all) do
80
+ @conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(CONNECTION_PARAMS)
81
+ end
82
+
83
+ before(:each) do
84
+ @conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(CONNECTION_PARAMS) unless @conn.active?
85
+ end
86
+
87
+ after(:all) do
88
+ @conn.logoff if @conn.active?
89
+ end
90
+
91
+ it "should execute SQL statement" do
92
+ @conn.exec("SELECT * FROM dual").should_not be_nil
93
+ end
94
+
95
+ it "should execute SQL select" do
96
+ @conn.select("SELECT * FROM dual").should == [{'dummy' => 'X'}]
97
+ end
98
+
99
+ it "should execute SQL select and return also columns" do
100
+ @conn.select("SELECT * FROM dual", nil, true).should == [ [{'dummy' => 'X'}], ['dummy'] ]
101
+ end
102
+
103
+ end
104
+
105
+ describe "OracleEnhancedConnection auto reconnection" do
106
+
107
+ before(:all) do
108
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
109
+ @conn = ActiveRecord::Base.connection.instance_variable_get("@connection")
110
+ @sys_conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(SYS_CONNECTION_PARAMS)
111
+ end
112
+
113
+ before(:each) do
114
+ ActiveRecord::Base.connection.reconnect! unless @conn.active?
115
+ end
116
+
117
+ after(:all) do
118
+ ActiveRecord::Base.connection.disconnect! if @conn.active?
119
+ end
120
+
121
+ def kill_current_session
122
+ audsid = @conn.select("SELECT userenv('sessionid') audsid FROM dual").first['audsid']
123
+ sid_serial = @sys_conn.select("SELECT s.sid||','||s.serial# sid_serial
124
+ FROM v$session s
125
+ WHERE audsid = '#{audsid}'").first['sid_serial']
126
+ @sys_conn.exec "ALTER SYSTEM KILL SESSION '#{sid_serial}' IMMEDIATE"
127
+ end
128
+
129
+ it "should reconnect and execute SQL statement if connection is lost and auto retry is enabled" do
130
+ # @conn.auto_retry = true
131
+ ActiveRecord::Base.connection.auto_retry = true
132
+ kill_current_session
133
+ @conn.exec("SELECT * FROM dual").should_not be_nil
134
+ end
135
+
136
+ it "should not reconnect and execute SQL statement if connection is lost and auto retry is disabled" do
137
+ # @conn.auto_retry = false
138
+ ActiveRecord::Base.connection.auto_retry = false
139
+ kill_current_session
140
+ lambda { @conn.exec("SELECT * FROM dual") }.should raise_error
141
+ end
142
+
143
+ it "should reconnect and execute SQL select if connection is lost and auto retry is enabled" do
144
+ # @conn.auto_retry = true
145
+ ActiveRecord::Base.connection.auto_retry = true
146
+ kill_current_session
147
+ @conn.select("SELECT * FROM dual").should == [{'dummy' => 'X'}]
148
+ end
149
+
150
+ it "should not reconnect and execute SQL select if connection is lost and auto retry is disabled" do
151
+ # @conn.auto_retry = false
152
+ ActiveRecord::Base.connection.auto_retry = false
153
+ kill_current_session
154
+ lambda { @conn.select("SELECT * FROM dual") }.should raise_error
155
+ end
156
+
157
+ end
158
+
159
+ describe "OracleEnhancedConnection describe table" do
160
+
161
+ before(:all) do
162
+ @conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(CONNECTION_PARAMS)
163
+ @owner = CONNECTION_PARAMS[:username].upcase
164
+ end
165
+
166
+ after(:all) do
167
+ @conn.logoff if @conn.active?
168
+ end
169
+
170
+ it "should describe existing table" do
171
+ @conn.exec "CREATE TABLE test_employees (first_name VARCHAR2(20))" rescue nil
172
+ @conn.describe("test_employees").should == [@owner, "TEST_EMPLOYEES"]
173
+ @conn.exec "DROP TABLE test_employees" rescue nil
174
+ end
175
+
176
+ it "should not describe non-existing table" do
177
+ lambda { @conn.describe("test_xxx") }.should raise_error(ActiveRecord::ConnectionAdapters::OracleEnhancedConnectionException)
178
+ end
179
+
180
+ it "should describe table in other schema" do
181
+ @conn.describe("sys.dual").should == ["SYS", "DUAL"]
182
+ end
183
+
184
+ it "should describe existing view" do
185
+ @conn.exec "CREATE TABLE test_employees (first_name VARCHAR2(20))" rescue nil
186
+ @conn.exec "CREATE VIEW test_employees_v AS SELECT * FROM test_employees" rescue nil
187
+ @conn.describe("test_employees_v").should == [@owner, "TEST_EMPLOYEES_V"]
188
+ @conn.exec "DROP VIEW test_employees_v" rescue nil
189
+ @conn.exec "DROP TABLE test_employees" rescue nil
190
+ end
191
+
192
+ it "should describe view in other schema" do
193
+ @conn.describe("sys.v_$version").should == ["SYS", "V_$VERSION"]
194
+ end
195
+
196
+ it "should describe existing private synonym" do
197
+ @conn.exec "CREATE SYNONYM test_dual FOR sys.dual" rescue nil
198
+ @conn.describe("test_dual").should == ["SYS", "DUAL"]
199
+ @conn.exec "DROP SYNONYM test_dual" rescue nil
200
+ end
201
+
202
+ it "should describe existing public synonym" do
203
+ @conn.describe("all_tables").should == ["SYS", "ALL_TABLES"]
204
+ end
205
+
206
+ end