plukevdh-activerecord-oracle_enhanced-adapter 1.2.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.
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