plukevdh-activerecord-oracle_enhanced-adapter 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. data/History.txt +111 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +26 -0
  4. data/README.rdoc +68 -0
  5. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +5 -0
  6. data/lib/active_record/connection_adapters/oracle_enhanced.rake +48 -0
  7. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +1200 -0
  8. data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +71 -0
  9. data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +64 -0
  10. data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +21 -0
  11. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +39 -0
  12. data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +358 -0
  13. data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +368 -0
  14. data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +150 -0
  15. data/lib/active_record/connection_adapters/oracle_enhanced_reserved_words.rb +126 -0
  16. data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +11 -0
  17. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +7 -0
  18. data/oracle-enhanced.gemspec +59 -0
  19. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +659 -0
  20. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +170 -0
  21. data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +40 -0
  22. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +103 -0
  23. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +951 -0
  24. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +93 -0
  25. data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +27 -0
  26. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +340 -0
  27. data/spec/spec.opts +6 -0
  28. data/spec/spec_helper.rb +94 -0
  29. metadata +94 -0
@@ -0,0 +1,93 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+ if ActiveRecord::Base.instance_methods.include?('changed?')
4
+
5
+ describe "OracleEnhancedAdapter dirty object tracking" do
6
+
7
+ before(:all) do
8
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
9
+ @conn = ActiveRecord::Base.connection
10
+ @conn.execute <<-SQL
11
+ CREATE TABLE test_employees (
12
+ id NUMBER,
13
+ first_name VARCHAR2(20),
14
+ last_name VARCHAR2(25),
15
+ job_id NUMBER(6,0) NULL,
16
+ salary NUMBER(8,2),
17
+ comments CLOB,
18
+ hire_date DATE
19
+ )
20
+ SQL
21
+ @conn.execute <<-SQL
22
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
23
+ INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
24
+ SQL
25
+ class TestEmployee < ActiveRecord::Base
26
+ end
27
+ end
28
+
29
+ after(:all) do
30
+ Object.send(:remove_const, "TestEmployee")
31
+ @conn.execute "DROP TABLE test_employees"
32
+ @conn.execute "DROP SEQUENCE test_employees_seq"
33
+ end
34
+
35
+ it "should not mark empty string (stored as NULL) as changed when reassigning it" do
36
+ @employee = TestEmployee.create!(:first_name => '')
37
+ @employee.first_name = ''
38
+ @employee.should_not be_changed
39
+ @employee.reload
40
+ @employee.first_name = ''
41
+ @employee.should_not be_changed
42
+ end
43
+
44
+ it "should not mark empty integer (stored as NULL) as changed when reassigning it" do
45
+ @employee = TestEmployee.create!(:job_id => '')
46
+ @employee.job_id = ''
47
+ @employee.should_not be_changed
48
+ @employee.reload
49
+ @employee.job_id = ''
50
+ @employee.should_not be_changed
51
+ end
52
+
53
+ it "should not mark empty decimal (stored as NULL) as changed when reassigning it" do
54
+ @employee = TestEmployee.create!(:salary => '')
55
+ @employee.salary = ''
56
+ @employee.should_not be_changed
57
+ @employee.reload
58
+ @employee.salary = ''
59
+ @employee.should_not be_changed
60
+ end
61
+
62
+ it "should not mark empty text (stored as NULL) as changed when reassigning it" do
63
+ @employee = TestEmployee.create!(:comments => '')
64
+ @employee.comments = ''
65
+ @employee.should_not be_changed
66
+ @employee.reload
67
+ @employee.comments = ''
68
+ @employee.should_not be_changed
69
+ end
70
+
71
+ it "should not mark empty date (stored as NULL) as changed when reassigning it" do
72
+ @employee = TestEmployee.create!(:hire_date => '')
73
+ @employee.hire_date = ''
74
+ @employee.should_not be_changed
75
+ @employee.reload
76
+ @employee.hire_date = ''
77
+ @employee.should_not be_changed
78
+ end
79
+
80
+ it "should not mark integer as changed when reassigning it" do
81
+ @employee = TestEmployee.new
82
+ @employee.job_id = 0
83
+ @employee.save!.should be_true
84
+
85
+ @employee.should_not be_changed
86
+
87
+ @employee.job_id = '0'
88
+ @employee.should_not be_changed
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+
4
+
5
+ describe "OracleEnhancedAdapter emulate OracleAdapter" do
6
+
7
+ before(:all) do
8
+ if defined?(ActiveRecord::ConnectionAdapters::OracleAdapter)
9
+ @old_oracle_adapter = ActiveRecord::ConnectionAdapters::OracleAdapter
10
+ ActiveRecord::ConnectionAdapters.send(:remove_const, :OracleAdapter)
11
+ end
12
+ end
13
+
14
+ it "should be an OracleAdapter" do
15
+ @conn = ActiveRecord::Base.establish_connection(CONNECTION_PARAMS.merge(:emulate_oracle_adapter => true))
16
+ ActiveRecord::Base.connection.should_not be_nil
17
+ ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters::OracleAdapter).should be_true
18
+ end
19
+
20
+ after(:all) do
21
+ if @old_oracle_adapter
22
+ ActiveRecord::ConnectionAdapters.send(:remove_const, :OracleAdapter)
23
+ ActiveRecord::ConnectionAdapters::OracleAdapter = @old_oracle_adapter
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,340 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+ describe "OracleEnhancedAdapter custom methods for create, update and destroy" do
4
+ include LoggerSpecHelper
5
+
6
+ before(:all) do
7
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
8
+ @conn = ActiveRecord::Base.connection
9
+ plsql.connection = ActiveRecord::Base.connection.raw_connection
10
+ @conn.execute("DROP TABLE test_employees") rescue nil
11
+ @conn.execute <<-SQL
12
+ CREATE TABLE test_employees (
13
+ employee_id NUMBER(6,0),
14
+ first_name VARCHAR2(20),
15
+ last_name VARCHAR2(25),
16
+ hire_date DATE,
17
+ salary NUMBER(8,2),
18
+ description CLOB,
19
+ version NUMBER(15,0),
20
+ create_time DATE,
21
+ update_time DATE
22
+ )
23
+ SQL
24
+ @conn.execute("DROP SEQUENCE test_employees_s") rescue nil
25
+ @conn.execute <<-SQL
26
+ CREATE SEQUENCE test_employees_s MINVALUE 1
27
+ INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
28
+ SQL
29
+ @conn.execute <<-SQL
30
+ CREATE OR REPLACE PACKAGE test_employees_pkg IS
31
+ PROCEDURE create_employee(
32
+ p_first_name VARCHAR2,
33
+ p_last_name VARCHAR2,
34
+ p_hire_date DATE,
35
+ p_salary NUMBER,
36
+ p_description VARCHAR2,
37
+ p_employee_id OUT NUMBER);
38
+ PROCEDURE update_employee(
39
+ p_employee_id NUMBER,
40
+ p_first_name VARCHAR2,
41
+ p_last_name VARCHAR2,
42
+ p_hire_date DATE,
43
+ p_salary NUMBER,
44
+ p_description VARCHAR2);
45
+ PROCEDURE delete_employee(
46
+ p_employee_id NUMBER);
47
+ END;
48
+ SQL
49
+ @conn.execute <<-SQL
50
+ CREATE OR REPLACE PACKAGE BODY test_employees_pkg IS
51
+ PROCEDURE create_employee(
52
+ p_first_name VARCHAR2,
53
+ p_last_name VARCHAR2,
54
+ p_hire_date DATE,
55
+ p_salary NUMBER,
56
+ p_description VARCHAR2,
57
+ p_employee_id OUT NUMBER)
58
+ IS
59
+ BEGIN
60
+ SELECT test_employees_s.NEXTVAL INTO p_employee_id FROM dual;
61
+ INSERT INTO test_employees (employee_id, first_name, last_name, hire_date, salary, description,
62
+ version, create_time, update_time)
63
+ VALUES (p_employee_id, p_first_name, p_last_name, p_hire_date, p_salary, p_description,
64
+ 1, SYSDATE, SYSDATE);
65
+ END create_employee;
66
+
67
+ PROCEDURE update_employee(
68
+ p_employee_id NUMBER,
69
+ p_first_name VARCHAR2,
70
+ p_last_name VARCHAR2,
71
+ p_hire_date DATE,
72
+ p_salary NUMBER,
73
+ p_description VARCHAR2)
74
+ IS
75
+ v_version NUMBER;
76
+ BEGIN
77
+ SELECT version INTO v_version FROM test_employees WHERE employee_id = p_employee_id FOR UPDATE;
78
+ UPDATE test_employees
79
+ SET employee_id = p_employee_id, first_name = p_first_name, last_name = p_last_name,
80
+ hire_date = p_hire_date, salary = p_salary, description = p_description,
81
+ version = v_version + 1, update_time = SYSDATE;
82
+ END update_employee;
83
+
84
+ PROCEDURE delete_employee(
85
+ p_employee_id NUMBER)
86
+ IS
87
+ BEGIN
88
+ DELETE FROM test_employees WHERE employee_id = p_employee_id;
89
+ END delete_employee;
90
+ END;
91
+ SQL
92
+
93
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
94
+
95
+ class ::TestEmployee < ActiveRecord::Base
96
+ set_primary_key :employee_id
97
+
98
+ validates_presence_of :first_name, :last_name, :hire_date
99
+
100
+ # should return ID of new record
101
+ set_create_method do
102
+ plsql.test_employees_pkg.create_employee(
103
+ :p_first_name => first_name,
104
+ :p_last_name => last_name,
105
+ :p_hire_date => hire_date,
106
+ :p_salary => salary,
107
+ :p_description => "#{first_name} #{last_name}",
108
+ :p_employee_id => nil
109
+ )[:p_employee_id]
110
+ end
111
+
112
+ # return value is ignored
113
+ set_update_method do
114
+ plsql.test_employees_pkg.update_employee(
115
+ :p_employee_id => id,
116
+ :p_first_name => first_name,
117
+ :p_last_name => last_name,
118
+ :p_hire_date => hire_date,
119
+ :p_salary => salary,
120
+ :p_description => "#{first_name} #{last_name}"
121
+ )
122
+ end
123
+
124
+ # return value is ignored
125
+ set_delete_method do
126
+ plsql.test_employees_pkg.delete_employee(
127
+ :p_employee_id => id
128
+ )
129
+ end
130
+
131
+ end
132
+ end
133
+
134
+ after(:all) do
135
+ Object.send(:remove_const, "TestEmployee")
136
+ @conn = ActiveRecord::Base.connection
137
+ @conn.execute "DROP TABLE test_employees"
138
+ @conn.execute "DROP SEQUENCE test_employees_s"
139
+ @conn.execute "DROP PACKAGE test_employees_pkg"
140
+ end
141
+
142
+ before(:each) do
143
+ @today = Date.new(2008,6,28)
144
+ @buffer = StringIO.new
145
+ end
146
+
147
+ it "should create record" do
148
+ @employee = TestEmployee.create(
149
+ :first_name => "First",
150
+ :last_name => "Last",
151
+ :hire_date => @today
152
+ )
153
+ @employee.reload
154
+ @employee.first_name.should == "First"
155
+ @employee.last_name.should == "Last"
156
+ @employee.hire_date.should == @today
157
+ @employee.description.should == "First Last"
158
+ @employee.create_time.should_not be_nil
159
+ @employee.update_time.should_not be_nil
160
+ end
161
+
162
+ it "should rollback record when exception is raised in after_create callback" do
163
+ @employee = TestEmployee.new(
164
+ :first_name => "First",
165
+ :last_name => "Last",
166
+ :hire_date => @today
167
+ )
168
+ TestEmployee.class_eval { def after_create() raise "Make the transaction rollback" end }
169
+ begin
170
+ employees_count = TestEmployee.count
171
+ @employee.save
172
+ fail "Did not raise exception"
173
+ rescue => e
174
+ e.message.should == "Make the transaction rollback"
175
+ @employee.id.should == nil
176
+ TestEmployee.count.should == employees_count
177
+ ensure
178
+ TestEmployee.class_eval { remove_method :after_create }
179
+ end
180
+ end
181
+
182
+ it "should update record" do
183
+ @employee = TestEmployee.create(
184
+ :first_name => "First",
185
+ :last_name => "Last",
186
+ :hire_date => @today,
187
+ :description => "description"
188
+ )
189
+ @employee.reload
190
+ @employee.first_name = "Second"
191
+ @employee.save!
192
+ @employee.reload
193
+ @employee.description.should == "Second Last"
194
+ end
195
+
196
+ it "should rollback record when exception is raised in after_update callback" do
197
+ TestEmployee.class_eval { def after_update() raise "Make the transaction rollback" end }
198
+ begin
199
+ @employee = TestEmployee.create(
200
+ :first_name => "First",
201
+ :last_name => "Last",
202
+ :hire_date => @today,
203
+ :description => "description"
204
+ )
205
+ empl_id = @employee.id
206
+ @employee.reload
207
+ @employee.first_name = "Second"
208
+ @employee.save!
209
+ fail "Did not raise exception"
210
+ rescue => e
211
+ e.message.should == "Make the transaction rollback"
212
+ @employee.reload
213
+ @employee.first_name.should == "First"
214
+ ensure
215
+ TestEmployee.class_eval { remove_method :after_update }
216
+ end
217
+ end
218
+
219
+ it "should not update record if nothing is changed and partial updates are enabled" do
220
+ return pending("Not in this ActiveRecord version") unless TestEmployee.respond_to?(:partial_updates=)
221
+ TestEmployee.partial_updates = true
222
+ @employee = TestEmployee.create(
223
+ :first_name => "First",
224
+ :last_name => "Last",
225
+ :hire_date => @today
226
+ )
227
+ @employee.reload
228
+ @employee.save!
229
+ @employee.reload
230
+ @employee.version.should == 1
231
+ end
232
+
233
+ it "should update record if nothing is changed and partial updates are disabled" do
234
+ return pending("Not in this ActiveRecord version") unless TestEmployee.respond_to?(:partial_updates=)
235
+ TestEmployee.partial_updates = false
236
+ @employee = TestEmployee.create(
237
+ :first_name => "First",
238
+ :last_name => "Last",
239
+ :hire_date => @today
240
+ )
241
+ @employee.reload
242
+ @employee.save!
243
+ @employee.reload
244
+ @employee.version.should == 2
245
+ end
246
+
247
+ it "should delete record" do
248
+ @employee = TestEmployee.create(
249
+ :first_name => "First",
250
+ :last_name => "Last",
251
+ :hire_date => @today
252
+ )
253
+ @employee.reload
254
+ empl_id = @employee.id
255
+ @employee.destroy
256
+ @employee.should be_frozen
257
+ TestEmployee.find_by_employee_id(empl_id).should be_nil
258
+ end
259
+
260
+ it "should rollback record when exception is raised in after_desotry callback" do
261
+ TestEmployee.class_eval { def after_destroy() raise "Make the transaction rollback" end }
262
+ @employee = TestEmployee.create(
263
+ :first_name => "First",
264
+ :last_name => "Last",
265
+ :hire_date => @today
266
+ )
267
+ @employee.reload
268
+ empl_id = @employee.id
269
+ begin
270
+ @employee.destroy
271
+ fail "Did not raise exception"
272
+ rescue => e
273
+ e.message.should == "Make the transaction rollback"
274
+ @employee.id.should == empl_id
275
+ TestEmployee.find_by_employee_id(empl_id).should_not be_nil
276
+ ensure
277
+ TestEmployee.class_eval { remove_method :after_destroy }
278
+ end
279
+ end
280
+
281
+ it "should log create record" do
282
+ log_to @buffer
283
+ # reestablish plsql.connection as log_to might reset existing connection
284
+ plsql.connection = ActiveRecord::Base.connection.raw_connection
285
+ @employee = TestEmployee.create(
286
+ :first_name => "First",
287
+ :last_name => "Last",
288
+ :hire_date => @today
289
+ )
290
+ @buffer.string.should match(/^TestEmployee Create \(\d+\.\d+(ms)?\) custom create method$/)
291
+ end
292
+
293
+ it "should log update record" do
294
+ (TestEmployee.partial_updates = false) rescue nil
295
+ @employee = TestEmployee.create(
296
+ :first_name => "First",
297
+ :last_name => "Last",
298
+ :hire_date => @today
299
+ )
300
+ log_to @buffer
301
+ # reestablish plsql.connection as log_to might reset existing connection
302
+ plsql.connection = ActiveRecord::Base.connection.raw_connection
303
+ @employee.save!
304
+ @buffer.string.should match(/^TestEmployee Update \(\d+\.\d+(ms)?\) custom update method with employee_id=#{@employee.id}$/)
305
+ end
306
+
307
+ it "should log delete record" do
308
+ @employee = TestEmployee.create(
309
+ :first_name => "First",
310
+ :last_name => "Last",
311
+ :hire_date => @today
312
+ )
313
+ log_to @buffer
314
+ # reestablish plsql.connection as log_to might reset existing connection
315
+ plsql.connection = ActiveRecord::Base.connection.raw_connection
316
+ @employee.destroy
317
+ @buffer.string.should match(/^TestEmployee Destroy \(\d+\.\d+(ms)?\) custom delete method with employee_id=#{@employee.id}$/)
318
+ end
319
+
320
+ it "should validate new record before creation" do
321
+ @employee = TestEmployee.new(
322
+ :last_name => "Last",
323
+ :hire_date => @today
324
+ )
325
+ @employee.save.should be_false
326
+ @employee.errors.on(:first_name).should_not be_nil
327
+ end
328
+
329
+ it "should validate existing record before update" do
330
+ @employee = TestEmployee.create(
331
+ :first_name => "First",
332
+ :last_name => "Last",
333
+ :hire_date => @today
334
+ )
335
+ @employee.first_name = nil
336
+ @employee.save.should be_false
337
+ @employee.errors.on(:first_name).should_not be_nil
338
+ end
339
+
340
+ end