oracle_enhanced 1.2.5

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.
Files changed (38) hide show
  1. data/.gitignore +10 -0
  2. data/History.txt +182 -0
  3. data/License.txt +20 -0
  4. data/Manifest.txt +32 -0
  5. data/README.rdoc +77 -0
  6. data/Rakefile +49 -0
  7. data/VERSION +1 -0
  8. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +5 -0
  9. data/lib/active_record/connection_adapters/oracle_enhanced.rake +51 -0
  10. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +1661 -0
  11. data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +121 -0
  12. data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +64 -0
  13. data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +21 -0
  14. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +39 -0
  15. data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +393 -0
  16. data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +389 -0
  17. data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +163 -0
  18. data/lib/active_record/connection_adapters/oracle_enhanced_reserved_words.rb +126 -0
  19. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +168 -0
  20. data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +213 -0
  21. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +224 -0
  22. data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +11 -0
  23. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +1 -0
  24. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +477 -0
  25. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_structure_dumper_spec.rb +267 -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 +203 -0
  35. data/spec/active_record/connection_adapters/oracle_enhanced_schema_spec.rb +784 -0
  36. data/spec/spec.opts +6 -0
  37. data/spec/spec_helper.rb +114 -0
  38. metadata +140 -0
@@ -0,0 +1,267 @@
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
+ pending "Not supported in this database version" unless @conn.select_value("SELECT * FROM v$version WHERE banner LIKE 'Oracle%11g%'")
94
+ @conn.execute <<-SQL
95
+ CREATE TABLE bars (
96
+ id NUMBER(38,0) NOT NULL,
97
+ id_plus NUMBER GENERATED ALWAYS AS(id + 2) VIRTUAL,
98
+ PRIMARY KEY (ID)
99
+ )
100
+ SQL
101
+ dump = ActiveRecord::Base.connection.structure_dump
102
+ dump.should =~ /id_plus number GENERATED ALWAYS AS \(ID\+2\) VIRTUAL/
103
+ end
104
+
105
+ it "should dump unique keys" do
106
+ @conn.execute <<-SQL
107
+ ALTER TABLE test_posts
108
+ add CONSTRAINT uk_foo_foo_id UNIQUE (foo, foo_id)
109
+ SQL
110
+ dump = ActiveRecord::Base.connection.structure_dump_unique_keys("test_posts")
111
+ dump.should == [" CONSTRAINT UK_FOO_FOO_ID UNIQUE (FOO,FOO_ID)"]
112
+
113
+ dump = ActiveRecord::Base.connection.structure_dump
114
+ dump.should =~ /CONSTRAINT UK_FOO_FOO_ID UNIQUE \(FOO,FOO_ID\)/
115
+ end
116
+
117
+ it "should dump indexes" do
118
+ ActiveRecord::Base.connection.add_index(:test_posts, :foo, :name => :ix_test_posts_foo)
119
+ ActiveRecord::Base.connection.add_index(:test_posts, :foo_id, :name => :ix_test_posts_foo_id, :unique => true)
120
+
121
+ @conn.execute <<-SQL
122
+ ALTER TABLE test_posts
123
+ add CONSTRAINT uk_foo_foo_id UNIQUE (foo, foo_id)
124
+ SQL
125
+
126
+ dump = ActiveRecord::Base.connection.structure_dump
127
+ dump.should =~ /create unique index ix_test_posts_foo_id on test_posts \(foo_id\)/i
128
+ dump.should =~ /create index ix_test_posts_foo on test_posts \(foo\)/i
129
+ dump.should_not =~ /create unique index uk_test_posts_/i
130
+ end
131
+ end
132
+ describe "temporary tables" do
133
+ after(:all) do
134
+ @conn.drop_table :test_comments rescue nil
135
+ end
136
+ it "should dump correctly" do
137
+ @conn.create_table :test_comments, :temporary => true, :id => false do |t|
138
+ t.integer :post_id
139
+ end
140
+ dump = ActiveRecord::Base.connection.structure_dump
141
+ dump.should =~ /create global temporary table test_comments/i
142
+ end
143
+ end
144
+
145
+ describe "database stucture dump extentions" do
146
+ before(:all) do
147
+ @conn.execute <<-SQL
148
+ CREATE TABLE nvarchartable (
149
+ unq_nvarchar NVARCHAR2(255) DEFAULT NULL
150
+ )
151
+ SQL
152
+ end
153
+
154
+ after(:all) do
155
+ @conn.execute "DROP TABLE nvarchartable"
156
+ end
157
+
158
+ it "should return the character size of nvarchar fields" do
159
+ if /.*unq_nvarchar nvarchar2\((\d+)\).*/ =~ @conn.structure_dump
160
+ "#$1".should == "255"
161
+ end
162
+ end
163
+ end
164
+
165
+ describe "temp_table_drop" do
166
+ before(:each) do
167
+ @conn.create_table :temp_tbl, :temporary => true do |t|
168
+ t.string :foo
169
+ end
170
+ @conn.create_table :not_temp_tbl do |t|
171
+ t.string :foo
172
+ end
173
+ end
174
+ it "should dump drop sql for just temp tables" do
175
+ dump = @conn.temp_table_drop
176
+ dump.should =~ /drop table temp_tbl/i
177
+ dump.should_not =~ /drop table not_temp_tbl/i
178
+ end
179
+ after(:each) do
180
+ @conn.drop_table :temp_tbl
181
+ @conn.drop_table :not_temp_tbl
182
+ end
183
+ end
184
+
185
+ describe "full drop" do
186
+ before(:each) do
187
+ @conn.create_table :full_drop_test do |t|
188
+ t.integer :id
189
+ end
190
+ @conn.create_table :full_drop_test_temp, :temporary => true do |t|
191
+ t.string :foo
192
+ end
193
+ #view
194
+ @conn.execute <<-SQL
195
+ create or replace view full_drop_test_view (foo) as select id as "foo" from full_drop_test
196
+ SQL
197
+ #package
198
+ @conn.execute <<-SQL
199
+ create or replace package full_drop_test_package as
200
+ function test_func return varchar2;
201
+ end test_package;
202
+ SQL
203
+ @conn.execute <<-SQL
204
+ create or replace package body full_drop_test_package as
205
+ function test_func return varchar2 is
206
+ begin
207
+ return ('foo');
208
+ end test_func;
209
+ end test_package;
210
+ SQL
211
+ #function
212
+ @conn.execute <<-SQL
213
+ create or replace function full_drop_test_function
214
+ return varchar2
215
+ is
216
+ foo varchar2(3);
217
+ begin
218
+ return('foo');
219
+ end;
220
+ SQL
221
+ #procedure
222
+ @conn.execute <<-SQL
223
+ create or replace procedure full_drop_test_procedure
224
+ begin
225
+ delete from full_drop_test where id=1231231231
226
+ exception
227
+ when no_data_found then
228
+ dbms_output.put_line('foo');
229
+ end;
230
+ SQL
231
+ #synonym
232
+ @conn.execute <<-SQL
233
+ create or replace synonym full_drop_test_synonym for full_drop_test
234
+ SQL
235
+ #type
236
+ @conn.execute <<-SQL
237
+ create or replace type full_drop_test_type as table of number
238
+ SQL
239
+ end
240
+ after(:each) do
241
+ @conn.drop_table :full_drop_test
242
+ @conn.drop_table :full_drop_test_temp
243
+ @conn.execute "DROP VIEW FULL_DROP_TEST_VIEW" rescue nil
244
+ @conn.execute "DROP SYNONYM FULL_DROP_TEST_SYNONYM" rescue nil
245
+ @conn.execute "DROP PACKAGE FULL_DROP_TEST_PACKAGE" rescue nil
246
+ @conn.execute "DROP FUNCTION FULL_DROP_TEST_FUNCTION" rescue nil
247
+ @conn.execute "DROP PROCEDURE FULL_DROP_TEST_PROCEDURE" rescue nil
248
+ @conn.execute "DROP TYPE FULL_DROP_TEST_TYPE" rescue nil
249
+ end
250
+ it "should contain correct sql" do
251
+ drop = @conn.full_drop
252
+ drop.should =~ /drop table full_drop_test cascade constraints/i
253
+ drop.should =~ /drop sequence full_drop_test_seq/i
254
+ drop.should =~ /drop view "full_drop_test_view"/i
255
+ drop.should =~ /drop package full_drop_test_package/i
256
+ drop.should =~ /drop function full_drop_test_function/i
257
+ drop.should =~ /drop procedure full_drop_test_procedure/i
258
+ drop.should =~ /drop synonym "full_drop_test_synonym"/i
259
+ drop.should =~ /drop type "full_drop_test_type"/i
260
+ end
261
+ it "should not drop tables when preserve_tables is true" do
262
+ drop = @conn.full_drop(true)
263
+ drop.should =~ /drop table full_drop_test_temp/i
264
+ drop.should_not =~ /drop table full_drop_test cascade constraints/i
265
+ end
266
+ end
267
+ 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