unclebilly-activerecord-oracle_enhanced-adapter 1.2.4

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/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