ctreatma-activerecord-oracle_enhanced-adapter 1.4.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.rspec +2 -0
  2. data/Gemfile +51 -0
  3. data/History.md +269 -0
  4. data/License.txt +20 -0
  5. data/README.md +378 -0
  6. data/RUNNING_TESTS.md +45 -0
  7. data/Rakefile +46 -0
  8. data/VERSION +1 -0
  9. data/activerecord-oracle_enhanced-adapter.gemspec +130 -0
  10. data/ctreatma-activerecord-oracle_enhanced-adapter.gemspec +129 -0
  11. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +5 -0
  12. data/lib/active_record/connection_adapters/oracle_enhanced.rake +105 -0
  13. data/lib/active_record/connection_adapters/oracle_enhanced_activerecord_patches.rb +41 -0
  14. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +1390 -0
  15. data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +106 -0
  16. data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +136 -0
  17. data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +119 -0
  18. data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +328 -0
  19. data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +25 -0
  20. data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +21 -0
  21. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +39 -0
  22. data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +553 -0
  23. data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +492 -0
  24. data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +260 -0
  25. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +213 -0
  26. data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +252 -0
  27. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +373 -0
  28. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +265 -0
  29. data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +290 -0
  30. data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +17 -0
  31. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +1 -0
  32. data/lib/activerecord-oracle_enhanced-adapter.rb +25 -0
  33. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +749 -0
  34. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +310 -0
  35. data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +426 -0
  36. data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +19 -0
  37. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +113 -0
  38. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +1330 -0
  39. data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +69 -0
  40. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +121 -0
  41. data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +25 -0
  42. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +374 -0
  43. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +380 -0
  44. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +1112 -0
  45. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +323 -0
  46. data/spec/spec_helper.rb +185 -0
  47. metadata +287 -0
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe "OracleEnhancedAdapter to_d method" do
5
+ it "BigDecimal#to_d returns the same decimal number" do
6
+ d = BigDecimal.new("12345678901234567890.0123456789")
7
+ d.to_d.should == d
8
+ end
9
+
10
+ it "Bignum#to_d translates large integer to decimal" do
11
+ n = 12345678901234567890
12
+ n.to_d.should == BigDecimal.new(n.to_s)
13
+ end
14
+
15
+ it "Fixnum#to_d translates small integer to decimal" do
16
+ n = 123456
17
+ n.to_d.should == BigDecimal.new(n.to_s)
18
+ end
19
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+
3
+ unless defined?(NO_COMPOSITE_PRIMARY_KEYS)
4
+
5
+ describe "OracleEnhancedAdapter composite_primary_keys support" do
6
+ include SchemaSpecHelper
7
+
8
+ before(:all) do
9
+ if defined?(::ActiveRecord::ConnectionAdapters::OracleAdapter)
10
+ @old_oracle_adapter = ::ActiveRecord::ConnectionAdapters::OracleAdapter
11
+ ::ActiveRecord::ConnectionAdapters.send(:remove_const, :OracleAdapter)
12
+ end
13
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
14
+ if $cpk_oracle_adapter
15
+ ::ActiveRecord::ConnectionAdapters::OracleAdapter = $cpk_oracle_adapter
16
+ $cpk_oracle_adapter = nil
17
+ end
18
+ require 'composite_primary_keys'
19
+ end
20
+
21
+ after(:all) do
22
+ # Object.send(:remove_const, 'CompositePrimaryKeys') if defined?(CompositePrimaryKeys)
23
+ if defined?(::ActiveRecord::ConnectionAdapters::OracleAdapter)
24
+ $cpk_oracle_adapter = ::ActiveRecord::ConnectionAdapters::OracleAdapter
25
+ ::ActiveRecord::ConnectionAdapters.send(:remove_const, :OracleAdapter)
26
+ end
27
+ if @old_oracle_adapter
28
+ ::ActiveRecord::ConnectionAdapters::OracleAdapter = @old_oracle_adapter
29
+ @old_oracle_adapter = nil
30
+ end
31
+ end
32
+
33
+ describe "do not use count distinct" do
34
+ before(:all) do
35
+ schema_define do
36
+ create_table :job_history, :primary_key => [:employee_id, :start_date], :force => true do |t|
37
+ t.integer :employee_id
38
+ t.date :start_date
39
+ end
40
+ end
41
+ class ::JobHistory < ActiveRecord::Base
42
+ set_table_name "job_history"
43
+ set_primary_keys :employee_id, :start_date
44
+ end
45
+ end
46
+
47
+ after(:all) do
48
+ Object.send(:remove_const, 'JobHistory') if defined?(JobHistory)
49
+ schema_define do
50
+ drop_table :job_history
51
+ end
52
+ end
53
+
54
+ it "should tell ActiveRecord that count distinct is not supported" do
55
+ ActiveRecord::Base.connection.supports_count_distinct?.should be_false
56
+ end
57
+
58
+ it "should execute correct SQL COUNT DISTINCT statement on table with composite primary keys" do
59
+ lambda { JobHistory.count(:distinct => true) }.should_not raise_error
60
+ end
61
+ end
62
+
63
+ describe "table with LOB" do
64
+ before(:all) do
65
+ schema_define do
66
+ create_table :cpk_write_lobs_test, :primary_key => [:type_category, :date_value], :force => true do |t|
67
+ t.string :type_category, :limit => 15, :null => false
68
+ t.date :date_value, :null => false
69
+ t.text :results, :null => false
70
+ t.timestamps
71
+ end
72
+ create_table :non_cpk_write_lobs_test, :force => true do |t|
73
+ t.date :date_value, :null => false
74
+ t.text :results, :null => false
75
+ t.timestamps
76
+ end
77
+ end
78
+ class ::CpkWriteLobsTest < ActiveRecord::Base
79
+ set_table_name 'cpk_write_lobs_test'
80
+ set_primary_keys :type_category, :date_value
81
+ end
82
+ class ::NonCpkWriteLobsTest < ActiveRecord::Base
83
+ set_table_name 'non_cpk_write_lobs_test'
84
+ end
85
+ end
86
+
87
+ after(:all) do
88
+ schema_define do
89
+ drop_table :cpk_write_lobs_test
90
+ drop_table :non_cpk_write_lobs_test
91
+ end
92
+ Object.send(:remove_const, "CpkWriteLobsTest")
93
+ Object.send(:remove_const, "NonCpkWriteLobsTest")
94
+ end
95
+
96
+ it "should create new record in table with CPK and LOB" do
97
+ lambda {
98
+ CpkWriteLobsTest.create(:type_category => 'AAA', :date_value => Date.today, :results => 'DATA '*10)
99
+ }.should_not raise_error
100
+ end
101
+
102
+ it "should create new record in table without CPK and with LOB" do
103
+ lambda {
104
+ NonCpkWriteLobsTest.create(:date_value => Date.today, :results => 'DATA '*10)
105
+ }.should_not raise_error
106
+ end
107
+ end
108
+
109
+ # Other testing was done based on composite_primary_keys tests
110
+
111
+ end
112
+
113
+ end
@@ -0,0 +1,1330 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe "OracleEnhancedAdapter date type detection based on column names" do
5
+ before(:all) do
6
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
7
+ @conn = ActiveRecord::Base.connection
8
+ @conn.execute <<-SQL
9
+ CREATE TABLE test_employees (
10
+ employee_id NUMBER(6,0) PRIMARY KEY,
11
+ first_name VARCHAR2(20),
12
+ last_name VARCHAR2(25),
13
+ email VARCHAR2(25),
14
+ phone_number VARCHAR2(20),
15
+ hire_date DATE,
16
+ job_id NUMBER(6,0),
17
+ salary NUMBER(8,2),
18
+ commission_pct NUMBER(2,2),
19
+ manager_id NUMBER(6,0),
20
+ department_id NUMBER(4,0),
21
+ created_at DATE,
22
+ updated_at DATE
23
+ )
24
+ SQL
25
+ @conn.execute <<-SQL
26
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
27
+ INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
28
+ SQL
29
+ end
30
+
31
+ after(:all) do
32
+ @conn.execute "DROP TABLE test_employees"
33
+ @conn.execute "DROP SEQUENCE test_employees_seq"
34
+ end
35
+
36
+ it "should set DATE column type as datetime if emulate_dates_by_column_name is false" do
37
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
38
+ columns = @conn.columns('test_employees')
39
+ column = columns.detect{|c| c.name == "hire_date"}
40
+ column.type.should == :datetime
41
+ end
42
+
43
+ it "should set DATE column type as date if column name contains '_date_' and emulate_dates_by_column_name is true" do
44
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
45
+ columns = @conn.columns('test_employees')
46
+ column = columns.detect{|c| c.name == "hire_date"}
47
+ column.type.should == :date
48
+ end
49
+
50
+ it "should set DATE column type as datetime if column name does not contain '_date_' and emulate_dates_by_column_name is true" do
51
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
52
+ columns = @conn.columns('test_employees')
53
+ column = columns.detect{|c| c.name == "created_at"}
54
+ column.type.should == :datetime
55
+ end
56
+
57
+ it "should set DATE column type as datetime if column name contains 'date' as part of other word and emulate_dates_by_column_name is true" do
58
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
59
+ columns = @conn.columns('test_employees')
60
+ column = columns.detect{|c| c.name == "updated_at"}
61
+ column.type.should == :datetime
62
+ end
63
+
64
+ it "should return Time value from DATE column if emulate_dates_by_column_name is false" do
65
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
66
+ columns = @conn.columns('test_employees')
67
+ column = columns.detect{|c| c.name == "hire_date"}
68
+ column.type_cast(Time.now).class.should == Time
69
+ end
70
+
71
+ it "should return Date value from DATE column if column name contains 'date' and emulate_dates_by_column_name is true" do
72
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
73
+ columns = @conn.columns('test_employees')
74
+ column = columns.detect{|c| c.name == "hire_date"}
75
+ column.type_cast(Time.now).class.should == Date
76
+ end
77
+
78
+ it "should typecast DateTime value to Date value from DATE column if column name contains 'date' and emulate_dates_by_column_name is true" do
79
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
80
+ columns = @conn.columns('test_employees')
81
+ column = columns.detect{|c| c.name == "hire_date"}
82
+ column.type_cast(DateTime.new(1900,1,1)).class.should == Date
83
+ end
84
+
85
+ describe "/ DATE values from ActiveRecord model" do
86
+ before(:each) do
87
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
88
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates = false
89
+ class ::TestEmployee < ActiveRecord::Base
90
+ set_primary_key :employee_id
91
+ end
92
+ end
93
+
94
+ def create_test_employee(params={})
95
+ @today = params[:today] || Date.new(2008,8,19)
96
+ @now = params[:now] || Time.local(2008,8,19,17,03,59)
97
+ @employee = TestEmployee.create(
98
+ :first_name => "First",
99
+ :last_name => "Last",
100
+ :hire_date => @today,
101
+ :created_at => @now
102
+ )
103
+ @employee.reload
104
+ end
105
+
106
+ after(:each) do
107
+ # @employee.destroy if @employee
108
+ Object.send(:remove_const, "TestEmployee")
109
+ @conn.clear_types_for_columns
110
+ ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
111
+ end
112
+
113
+ it "should return Time value from DATE column if emulate_dates_by_column_name is false" do
114
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
115
+ create_test_employee
116
+ @employee.hire_date.class.should == Time
117
+ end
118
+
119
+ it "should return Date value from DATE column if column name contains 'date' and emulate_dates_by_column_name is true" do
120
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
121
+ create_test_employee
122
+ @employee.hire_date.class.should == Date
123
+ end
124
+
125
+ it "should return Date value from DATE column with old date value if column name contains 'date' and emulate_dates_by_column_name is true" do
126
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
127
+ create_test_employee(:today => Date.new(1900,1,1))
128
+ @employee.hire_date.class.should == Date
129
+ end
130
+
131
+ it "should return Time value from DATE column if column name does not contain 'date' and emulate_dates_by_column_name is true" do
132
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
133
+ create_test_employee
134
+ @employee.created_at.class.should == Time
135
+ end
136
+
137
+ it "should return Date value from DATE column if emulate_dates_by_column_name is false but column is defined as date" do
138
+ class ::TestEmployee < ActiveRecord::Base
139
+ set_date_columns :hire_date
140
+ end
141
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
142
+ create_test_employee
143
+ @employee.hire_date.class.should == Date
144
+ end
145
+
146
+ it "should return Date value from DATE column with old date value if emulate_dates_by_column_name is false but column is defined as date" do
147
+ class ::TestEmployee < ActiveRecord::Base
148
+ set_date_columns :hire_date
149
+ end
150
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
151
+ create_test_employee(:today => Date.new(1900,1,1))
152
+ @employee.hire_date.class.should == Date
153
+ end
154
+
155
+ it "should see set_date_columns values in different connection" do
156
+ class ::TestEmployee < ActiveRecord::Base
157
+ set_date_columns :hire_date
158
+ end
159
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
160
+ # establish other connection
161
+ other_conn = ActiveRecord::Base.oracle_enhanced_connection(CONNECTION_PARAMS)
162
+ other_conn.get_type_for_column('test_employees', 'hire_date').should == :date
163
+ end
164
+
165
+ it "should return Time value from DATE column if emulate_dates_by_column_name is true but column is defined as datetime" do
166
+ class ::TestEmployee < ActiveRecord::Base
167
+ set_datetime_columns :hire_date
168
+ end
169
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
170
+ create_test_employee
171
+ @employee.hire_date.class.should == Time
172
+ # change to current time with hours, minutes and seconds
173
+ @employee.hire_date = @now
174
+ @employee.save!
175
+ @employee.reload
176
+ @employee.hire_date.class.should == Time
177
+ @employee.hire_date.should == @now
178
+ end
179
+
180
+ it "should guess Date or Time value if emulate_dates is true" do
181
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates = true
182
+ create_test_employee
183
+ @employee.hire_date.class.should == Date
184
+ @employee.created_at.class.should == Time
185
+ end
186
+
187
+ end
188
+
189
+ end
190
+
191
+ describe "OracleEnhancedAdapter integer type detection based on column names" do
192
+ before(:all) do
193
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
194
+ @conn = ActiveRecord::Base.connection
195
+ @conn.execute "DROP TABLE test2_employees" rescue nil
196
+ @conn.execute <<-SQL
197
+ CREATE TABLE test2_employees (
198
+ id NUMBER PRIMARY KEY,
199
+ first_name VARCHAR2(20),
200
+ last_name VARCHAR2(25),
201
+ email VARCHAR2(25),
202
+ phone_number VARCHAR2(20),
203
+ hire_date DATE,
204
+ job_id NUMBER,
205
+ salary NUMBER,
206
+ commission_pct NUMBER(2,2),
207
+ manager_id NUMBER(6),
208
+ is_manager NUMBER(1),
209
+ department_id NUMBER(4,0),
210
+ created_at DATE
211
+ )
212
+ SQL
213
+ @conn.execute "DROP SEQUENCE test2_employees_seq" rescue nil
214
+ @conn.execute <<-SQL
215
+ CREATE SEQUENCE test2_employees_seq MINVALUE 1
216
+ INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
217
+ SQL
218
+ end
219
+
220
+ after(:all) do
221
+ @conn.execute "DROP TABLE test2_employees"
222
+ @conn.execute "DROP SEQUENCE test2_employees_seq"
223
+ end
224
+
225
+ it "should set NUMBER column type as decimal if emulate_integers_by_column_name is false" do
226
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = false
227
+ columns = @conn.columns('test2_employees')
228
+ column = columns.detect{|c| c.name == "job_id"}
229
+ column.type.should == :decimal
230
+ end
231
+
232
+ it "should set NUMBER column type as integer if emulate_integers_by_column_name is true" do
233
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
234
+ columns = @conn.columns('test2_employees')
235
+ column = columns.detect{|c| c.name == "job_id"}
236
+ column.type.should == :integer
237
+ column = columns.detect{|c| c.name == "id"}
238
+ column.type.should == :integer
239
+ end
240
+
241
+ it "should set NUMBER column type as decimal if column name does not contain 'id' and emulate_integers_by_column_name is true" do
242
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
243
+ columns = @conn.columns('test2_employees')
244
+ column = columns.detect{|c| c.name == "salary"}
245
+ column.type.should == :decimal
246
+ end
247
+
248
+ it "should return BigDecimal value from NUMBER column if emulate_integers_by_column_name is false" do
249
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = false
250
+ columns = @conn.columns('test2_employees')
251
+ column = columns.detect{|c| c.name == "job_id"}
252
+ column.type_cast(1.0).class.should == BigDecimal
253
+ end
254
+
255
+ it "should return Fixnum value from NUMBER column if column name contains 'id' and emulate_integers_by_column_name is true" do
256
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
257
+ columns = @conn.columns('test2_employees')
258
+ column = columns.detect{|c| c.name == "job_id"}
259
+ column.type_cast(1.0).class.should == Fixnum
260
+ end
261
+
262
+ describe "/ NUMBER values from ActiveRecord model" do
263
+ before(:each) do
264
+ class ::Test2Employee < ActiveRecord::Base
265
+ end
266
+ end
267
+
268
+ after(:each) do
269
+ Object.send(:remove_const, "Test2Employee")
270
+ @conn.clear_types_for_columns
271
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans = true
272
+ ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
273
+ end
274
+
275
+ def create_employee2
276
+ @employee2 = Test2Employee.create(
277
+ :first_name => "First",
278
+ :last_name => "Last",
279
+ :job_id => 1,
280
+ :is_manager => 1,
281
+ :salary => 1000
282
+ )
283
+ @employee2.reload
284
+ end
285
+
286
+ it "should return BigDecimal value from NUMBER column if emulate_integers_by_column_name is false" do
287
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = false
288
+ create_employee2
289
+ @employee2.job_id.class.should == BigDecimal
290
+ end
291
+
292
+ it "should return Fixnum value from NUMBER column if column name contains 'id' and emulate_integers_by_column_name is true" do
293
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
294
+ create_employee2
295
+ @employee2.job_id.class.should == Fixnum
296
+ end
297
+
298
+ it "should return Fixnum value from NUMBER column with integer value using _before_type_cast method" do
299
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
300
+ create_employee2
301
+ @employee2.job_id_before_type_cast.class.should == Fixnum
302
+ end
303
+
304
+ it "should return BigDecimal value from NUMBER column if column name does not contain 'id' and emulate_integers_by_column_name is true" do
305
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
306
+ create_employee2
307
+ @employee2.salary.class.should == BigDecimal
308
+ end
309
+
310
+ it "should return Fixnum value from NUMBER column if column specified in set_integer_columns" do
311
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = false
312
+ Test2Employee.set_integer_columns :job_id
313
+ create_employee2
314
+ @employee2.job_id.class.should == Fixnum
315
+ end
316
+
317
+ it "should return Boolean value from NUMBER(1) column if emulate booleans is used" do
318
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans = true
319
+ create_employee2
320
+ @employee2.is_manager.class.should == TrueClass
321
+ end
322
+
323
+ it "should return Fixnum value from NUMBER(1) column if emulate booleans is not used" do
324
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans = false
325
+ create_employee2
326
+ @employee2.is_manager.class.should == Fixnum
327
+ end
328
+
329
+ it "should return Fixnum value from NUMBER(1) column if column specified in set_integer_columns" do
330
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans = true
331
+ Test2Employee.set_integer_columns :is_manager
332
+ create_employee2
333
+ @employee2.is_manager.class.should == Fixnum
334
+ end
335
+
336
+ end
337
+
338
+ end
339
+
340
+ describe "OracleEnhancedAdapter boolean type detection based on string column types and names" do
341
+ before(:all) do
342
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
343
+ @conn = ActiveRecord::Base.connection
344
+ @conn.execute <<-SQL
345
+ CREATE TABLE test3_employees (
346
+ id NUMBER PRIMARY KEY,
347
+ first_name VARCHAR2(20),
348
+ last_name VARCHAR2(25),
349
+ email VARCHAR2(25),
350
+ phone_number VARCHAR2(20),
351
+ hire_date DATE,
352
+ job_id NUMBER,
353
+ salary NUMBER,
354
+ commission_pct NUMBER(2,2),
355
+ manager_id NUMBER(6),
356
+ department_id NUMBER(4,0),
357
+ created_at DATE,
358
+ has_email CHAR(1),
359
+ has_phone VARCHAR2(1) DEFAULT 'Y',
360
+ active_flag VARCHAR2(2),
361
+ manager_yn VARCHAR2(3) DEFAULT 'N',
362
+ test_boolean VARCHAR2(3)
363
+ )
364
+ SQL
365
+ @conn.execute <<-SQL
366
+ CREATE SEQUENCE test3_employees_seq MINVALUE 1
367
+ INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
368
+ SQL
369
+ end
370
+
371
+ after(:all) do
372
+ @conn.execute "DROP TABLE test3_employees"
373
+ @conn.execute "DROP SEQUENCE test3_employees_seq"
374
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
375
+ end
376
+
377
+ it "should set CHAR/VARCHAR2 column type as string if emulate_booleans_from_strings is false" do
378
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
379
+ columns = @conn.columns('test3_employees')
380
+ %w(has_email has_phone active_flag manager_yn).each do |col|
381
+ column = columns.detect{|c| c.name == col}
382
+ column.type.should == :string
383
+ end
384
+ end
385
+
386
+ it "should set CHAR/VARCHAR2 column type as boolean if emulate_booleans_from_strings is true" do
387
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
388
+ columns = @conn.columns('test3_employees')
389
+ %w(has_email has_phone active_flag manager_yn).each do |col|
390
+ column = columns.detect{|c| c.name == col}
391
+ column.type.should == :boolean
392
+ end
393
+ end
394
+
395
+ it "should set VARCHAR2 column type as string if column name does not contain 'flag' or 'yn' and emulate_booleans_from_strings is true" do
396
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
397
+ columns = @conn.columns('test3_employees')
398
+ %w(phone_number email).each do |col|
399
+ column = columns.detect{|c| c.name == col}
400
+ column.type.should == :string
401
+ end
402
+ end
403
+
404
+ it "should return string value from VARCHAR2 boolean column if emulate_booleans_from_strings is false" do
405
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
406
+ columns = @conn.columns('test3_employees')
407
+ %w(has_email has_phone active_flag manager_yn).each do |col|
408
+ column = columns.detect{|c| c.name == col}
409
+ column.type_cast("Y").class.should == String
410
+ end
411
+ end
412
+
413
+ it "should return boolean value from VARCHAR2 boolean column if emulate_booleans_from_strings is true" do
414
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
415
+ columns = @conn.columns('test3_employees')
416
+ %w(has_email has_phone active_flag manager_yn).each do |col|
417
+ column = columns.detect{|c| c.name == col}
418
+ column.type_cast("Y").class.should == TrueClass
419
+ column.type_cast("N").class.should == FalseClass
420
+ end
421
+ end
422
+
423
+ it "should translate boolean type to VARCHAR2(1) if emulate_booleans_from_strings is true" do
424
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
425
+ ActiveRecord::Base.connection.type_to_sql(
426
+ :boolean, nil, nil, nil).should == "VARCHAR2(1)"
427
+ end
428
+
429
+ it "should translate boolean type to NUMBER(1) if emulate_booleans_from_strings is false" do
430
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
431
+ ActiveRecord::Base.connection.type_to_sql(
432
+ :boolean, nil, nil, nil).should == "NUMBER(1)"
433
+ end
434
+
435
+ it "should get default value from VARCHAR2 boolean column if emulate_booleans_from_strings is true" do
436
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
437
+ columns = @conn.columns('test3_employees')
438
+ columns.detect{|c| c.name == 'has_phone'}.default.should be_true
439
+ columns.detect{|c| c.name == 'manager_yn'}.default.should be_false
440
+ end
441
+
442
+ describe "/ VARCHAR2 boolean values from ActiveRecord model" do
443
+ before(:each) do
444
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
445
+ class ::Test3Employee < ActiveRecord::Base
446
+ end
447
+ end
448
+
449
+ after(:each) do
450
+ Object.send(:remove_const, "Test3Employee")
451
+ @conn.clear_types_for_columns
452
+ ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
453
+ end
454
+
455
+ def create_employee3(params={})
456
+ @employee3 = Test3Employee.create(
457
+ {
458
+ :first_name => "First",
459
+ :last_name => "Last",
460
+ :has_email => true,
461
+ :has_phone => false,
462
+ :active_flag => true,
463
+ :manager_yn => false
464
+ }.merge(params)
465
+ )
466
+ @employee3.reload
467
+ end
468
+
469
+ it "should return String value from VARCHAR2 boolean column if emulate_booleans_from_strings is false" do
470
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
471
+ create_employee3
472
+ %w(has_email has_phone active_flag manager_yn).each do |col|
473
+ @employee3.send(col.to_sym).class.should == String
474
+ end
475
+ end
476
+
477
+ it "should return boolean value from VARCHAR2 boolean column if emulate_booleans_from_strings is true" do
478
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
479
+ create_employee3
480
+ %w(has_email active_flag).each do |col|
481
+ @employee3.send(col.to_sym).class.should == TrueClass
482
+ @employee3.send((col+"_before_type_cast").to_sym).should == "Y"
483
+ end
484
+ %w(has_phone manager_yn).each do |col|
485
+ @employee3.send(col.to_sym).class.should == FalseClass
486
+ @employee3.send((col+"_before_type_cast").to_sym).should == "N"
487
+ end
488
+ end
489
+
490
+ it "should return string value from VARCHAR2 column if it is not boolean column and emulate_booleans_from_strings is true" do
491
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
492
+ create_employee3
493
+ @employee3.first_name.class.should == String
494
+ end
495
+
496
+ it "should return boolean value from VARCHAR2 boolean column if column specified in set_boolean_columns" do
497
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
498
+ Test3Employee.set_boolean_columns :test_boolean
499
+ create_employee3(:test_boolean => true)
500
+ @employee3.test_boolean.class.should == TrueClass
501
+ @employee3.test_boolean_before_type_cast.should == "Y"
502
+ create_employee3(:test_boolean => false)
503
+ @employee3.test_boolean.class.should == FalseClass
504
+ @employee3.test_boolean_before_type_cast.should == "N"
505
+ create_employee3(:test_boolean => nil)
506
+ @employee3.test_boolean.class.should == NilClass
507
+ @employee3.test_boolean_before_type_cast.should == nil
508
+ create_employee3(:test_boolean => "")
509
+ @employee3.test_boolean.class.should == NilClass
510
+ @employee3.test_boolean_before_type_cast.should == nil
511
+ end
512
+
513
+ it "should return string value from VARCHAR2 column with boolean column name but is specified in set_string_columns" do
514
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
515
+ Test3Employee.set_string_columns :active_flag
516
+ create_employee3
517
+ @employee3.active_flag.class.should == String
518
+ end
519
+
520
+ end
521
+
522
+ end
523
+
524
+ describe "OracleEnhancedAdapter timestamp with timezone support" do
525
+ before(:all) do
526
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
527
+ @conn = ActiveRecord::Base.connection
528
+ @conn.execute <<-SQL
529
+ CREATE TABLE test_employees (
530
+ employee_id NUMBER(6,0) PRIMARY KEY,
531
+ first_name VARCHAR2(20),
532
+ last_name VARCHAR2(25),
533
+ email VARCHAR2(25),
534
+ phone_number VARCHAR2(20),
535
+ hire_date DATE,
536
+ job_id NUMBER(6,0),
537
+ salary NUMBER(8,2),
538
+ commission_pct NUMBER(2,2),
539
+ manager_id NUMBER(6,0),
540
+ department_id NUMBER(4,0),
541
+ created_at TIMESTAMP,
542
+ created_at_tz TIMESTAMP WITH TIME ZONE,
543
+ created_at_ltz TIMESTAMP WITH LOCAL TIME ZONE
544
+ )
545
+ SQL
546
+ @conn.execute <<-SQL
547
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
548
+ INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
549
+ SQL
550
+ end
551
+
552
+ after(:all) do
553
+ @conn.execute "DROP TABLE test_employees"
554
+ @conn.execute "DROP SEQUENCE test_employees_seq"
555
+ end
556
+
557
+ it "should set TIMESTAMP columns type as datetime" do
558
+ columns = @conn.columns('test_employees')
559
+ ts_columns = columns.select{|c| c.name =~ /created_at/}
560
+ ts_columns.each {|c| c.type.should == :timestamp}
561
+ end
562
+
563
+ describe "/ TIMESTAMP WITH TIME ZONE values from ActiveRecord model" do
564
+ before(:all) do
565
+ class ::TestEmployee < ActiveRecord::Base
566
+ set_primary_key :employee_id
567
+ end
568
+ end
569
+
570
+ after(:all) do
571
+ Object.send(:remove_const, "TestEmployee")
572
+ ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
573
+ end
574
+
575
+ it "should return Time value from TIMESTAMP columns" do
576
+ @now = Time.local(2008,5,26,23,11,11,0)
577
+ @employee = TestEmployee.create(
578
+ :created_at => @now,
579
+ :created_at_tz => @now,
580
+ :created_at_ltz => @now
581
+ )
582
+ @employee.reload
583
+ [:created_at, :created_at_tz, :created_at_ltz].each do |c|
584
+ @employee.send(c).class.should == Time
585
+ @employee.send(c).to_f.should == @now.to_f
586
+ end
587
+ end
588
+
589
+ it "should return Time value with fractional seconds from TIMESTAMP columns" do
590
+ @now = Time.local(2008,5,26,23,11,11,10)
591
+ @employee = TestEmployee.create(
592
+ :created_at => @now,
593
+ :created_at_tz => @now,
594
+ :created_at_ltz => @now
595
+ )
596
+ @employee.reload
597
+ [:created_at, :created_at_tz, :created_at_ltz].each do |c|
598
+ @employee.send(c).class.should == Time
599
+ @employee.send(c).to_f.should == @now.to_f
600
+ end
601
+ end
602
+
603
+ end
604
+
605
+ end
606
+
607
+
608
+ describe "OracleEnhancedAdapter date and timestamp with different NLS date formats" do
609
+ before(:all) do
610
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
611
+ @conn = ActiveRecord::Base.connection
612
+ @conn.execute <<-SQL
613
+ CREATE TABLE test_employees (
614
+ employee_id NUMBER(6,0) PRIMARY KEY,
615
+ first_name VARCHAR2(20),
616
+ last_name VARCHAR2(25),
617
+ email VARCHAR2(25),
618
+ phone_number VARCHAR2(20),
619
+ hire_date DATE,
620
+ job_id NUMBER(6,0),
621
+ salary NUMBER(8,2),
622
+ commission_pct NUMBER(2,2),
623
+ manager_id NUMBER(6,0),
624
+ department_id NUMBER(4,0),
625
+ created_at DATE,
626
+ created_at_ts TIMESTAMP
627
+ )
628
+ SQL
629
+ @conn.execute <<-SQL
630
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
631
+ INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
632
+ SQL
633
+ # @conn.execute %q{alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'}
634
+ @conn.execute %q{alter session set nls_date_format = 'DD-MON-YYYY HH24:MI:SS'}
635
+ # @conn.execute %q{alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'}
636
+ @conn.execute %q{alter session set nls_timestamp_format = 'DD-MON-YYYY HH24:MI:SS'}
637
+ end
638
+
639
+ after(:all) do
640
+ @conn.execute "DROP TABLE test_employees"
641
+ @conn.execute "DROP SEQUENCE test_employees_seq"
642
+ end
643
+
644
+ before(:each) do
645
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates = false
646
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
647
+ class ::TestEmployee < ActiveRecord::Base
648
+ set_primary_key :employee_id
649
+ end
650
+ @today = Date.new(2008,6,28)
651
+ @now = Time.local(2008,6,28,13,34,33)
652
+ end
653
+
654
+ after(:each) do
655
+ Object.send(:remove_const, "TestEmployee")
656
+ ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
657
+ end
658
+
659
+ def create_test_employee
660
+ @employee = TestEmployee.create(
661
+ :first_name => "First",
662
+ :last_name => "Last",
663
+ :hire_date => @today,
664
+ :created_at => @now,
665
+ :created_at_ts => @now
666
+ )
667
+ @employee.reload
668
+ end
669
+
670
+ it "should return Time value from DATE column if emulate_dates_by_column_name is false" do
671
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
672
+ create_test_employee
673
+ @employee.hire_date.class.should == Time
674
+ @employee.hire_date.should == @today.to_time
675
+ end
676
+
677
+ it "should return Date value from DATE column if column name contains 'date' and emulate_dates_by_column_name is true" do
678
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
679
+ create_test_employee
680
+ @employee.hire_date.class.should == Date
681
+ @employee.hire_date.should == @today
682
+ end
683
+
684
+ it "should return Time value from DATE column if column name does not contain 'date' and emulate_dates_by_column_name is true" do
685
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
686
+ create_test_employee
687
+ @employee.created_at.class.should == Time
688
+ @employee.created_at.should == @now
689
+ end
690
+
691
+ it "should return Time value from TIMESTAMP columns" do
692
+ create_test_employee
693
+ @employee.created_at_ts.class.should == Time
694
+ @employee.created_at_ts.should == @now
695
+ end
696
+
697
+ it "should quote Date values with TO_DATE" do
698
+ @conn.quote(@today).should == "TO_DATE('#{@today.year}-#{"%02d" % @today.month}-#{"%02d" % @today.day}','YYYY-MM-DD HH24:MI:SS')"
699
+ end
700
+
701
+ it "should quote Time values with TO_DATE" do
702
+ @conn.quote(@now).should == "TO_DATE('#{@now.year}-#{"%02d" % @now.month}-#{"%02d" % @now.day} "+
703
+ "#{"%02d" % @now.hour}:#{"%02d" % @now.min}:#{"%02d" % @now.sec}','YYYY-MM-DD HH24:MI:SS')"
704
+ end
705
+
706
+ it "should quote Time values with TO_TIMESTAMP" do
707
+ @ts = @now + 0.1
708
+ @conn.quote(@ts).should == "TO_TIMESTAMP('#{@ts.year}-#{"%02d" % @ts.month}-#{"%02d" % @ts.day} "+
709
+ "#{"%02d" % @ts.hour}:#{"%02d" % @ts.min}:#{"%02d" % @ts.sec}:100000','YYYY-MM-DD HH24:MI:SS:FF6')"
710
+ end
711
+
712
+ end
713
+
714
+ describe "OracleEnhancedAdapter assign string to :date and :datetime columns" do
715
+ before(:all) do
716
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
717
+ @conn = ActiveRecord::Base.connection
718
+ @conn.execute <<-SQL
719
+ CREATE TABLE test_employees (
720
+ employee_id NUMBER(6,0) PRIMARY KEY,
721
+ first_name VARCHAR2(20),
722
+ last_name VARCHAR2(25),
723
+ hire_date DATE,
724
+ last_login_at DATE,
725
+ last_login_at_ts TIMESTAMP
726
+ )
727
+ SQL
728
+ @conn.execute <<-SQL
729
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
730
+ INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
731
+ SQL
732
+ class ::TestEmployee < ActiveRecord::Base
733
+ set_primary_key :employee_id
734
+ end
735
+ @today = Date.new(2008,6,28)
736
+ @today_iso = "2008-06-28"
737
+ @today_nls = "28.06.2008"
738
+ @nls_date_format = "%d.%m.%Y"
739
+ @now = Time.local(2008,6,28,13,34,33)
740
+ @now_iso = "2008-06-28 13:34:33"
741
+ @now_nls = "28.06.2008 13:34:33"
742
+ @nls_time_format = "%d.%m.%Y %H:%M:%S"
743
+ @now_nls_with_tz = "28.06.2008 13:34:33+05:00"
744
+ @nls_with_tz_time_format = "%d.%m.%Y %H:%M:%S%Z"
745
+ @now_with_tz = Time.parse @now_nls_with_tz
746
+ end
747
+
748
+ after(:all) do
749
+ Object.send(:remove_const, "TestEmployee")
750
+ @conn.execute "DROP TABLE test_employees"
751
+ @conn.execute "DROP SEQUENCE test_employees_seq"
752
+ ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
753
+ end
754
+
755
+ before(:each) do
756
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
757
+ end
758
+
759
+ it "should assign ISO string to date column" do
760
+ @employee = TestEmployee.create(
761
+ :first_name => "First",
762
+ :last_name => "Last",
763
+ :hire_date => @today_iso
764
+ )
765
+ @employee.hire_date.should == @today
766
+ @employee.reload
767
+ @employee.hire_date.should == @today
768
+ end
769
+
770
+ it "should assign NLS string to date column" do
771
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_date_format = @nls_date_format
772
+ @employee = TestEmployee.create(
773
+ :first_name => "First",
774
+ :last_name => "Last",
775
+ :hire_date => @today_nls
776
+ )
777
+ @employee.hire_date.should == @today
778
+ @employee.reload
779
+ @employee.hire_date.should == @today
780
+ end
781
+
782
+ it "should assign ISO time string to date column" do
783
+ @employee = TestEmployee.create(
784
+ :first_name => "First",
785
+ :last_name => "Last",
786
+ :hire_date => @now_iso
787
+ )
788
+ @employee.hire_date.should == @today
789
+ @employee.reload
790
+ @employee.hire_date.should == @today
791
+ end
792
+
793
+ it "should assign NLS time string to date column" do
794
+ # ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_date_format = @nls_date_format
795
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_time_format = @nls_time_format
796
+ @employee = TestEmployee.create(
797
+ :first_name => "First",
798
+ :last_name => "Last",
799
+ :hire_date => @now_nls
800
+ )
801
+ @employee.hire_date.should == @today
802
+ @employee.reload
803
+ @employee.hire_date.should == @today
804
+ end
805
+
806
+ it "should assign ISO time string to datetime column" do
807
+ @employee = TestEmployee.create(
808
+ :first_name => "First",
809
+ :last_name => "Last",
810
+ :last_login_at => @now_iso
811
+ )
812
+ @employee.last_login_at.should == @now
813
+ @employee.reload
814
+ @employee.last_login_at.should == @now
815
+ end
816
+
817
+ it "should assign NLS time string to datetime column" do
818
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_time_format = @nls_time_format
819
+ @employee = TestEmployee.create(
820
+ :first_name => "First",
821
+ :last_name => "Last",
822
+ :last_login_at => @now_nls
823
+ )
824
+ @employee.last_login_at.should == @now
825
+ @employee.reload
826
+ @employee.last_login_at.should == @now
827
+ end
828
+
829
+ it "should assign NLS time string with time zone to datetime column" do
830
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_time_format = @nls_with_tz_time_format
831
+ @employee = TestEmployee.create(
832
+ :first_name => "First",
833
+ :last_name => "Last",
834
+ :last_login_at => @now_nls_with_tz
835
+ )
836
+ @employee.last_login_at.should == @now_with_tz
837
+ @employee.reload
838
+ @employee.last_login_at.should == @now_with_tz
839
+ end
840
+
841
+ it "should assign ISO date string to datetime column" do
842
+ @employee = TestEmployee.create(
843
+ :first_name => "First",
844
+ :last_name => "Last",
845
+ :last_login_at => @today_iso
846
+ )
847
+ @employee.last_login_at.should == @today.to_time
848
+ @employee.reload
849
+ @employee.last_login_at.should == @today.to_time
850
+ end
851
+
852
+ it "should assign NLS date string to datetime column" do
853
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_date_format = @nls_date_format
854
+ # ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_time_format = @nls_time_format
855
+ @employee = TestEmployee.create(
856
+ :first_name => "First",
857
+ :last_name => "Last",
858
+ :last_login_at => @today_nls
859
+ )
860
+ @employee.last_login_at.should == @today.to_time
861
+ @employee.reload
862
+ @employee.last_login_at.should == @today.to_time
863
+ end
864
+
865
+ end
866
+
867
+ describe "OracleEnhancedAdapter handling of CLOB columns" do
868
+ before(:all) do
869
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
870
+ @conn = ActiveRecord::Base.connection
871
+ @conn.execute <<-SQL
872
+ CREATE TABLE test_employees (
873
+ id NUMBER(6,0) PRIMARY KEY,
874
+ first_name VARCHAR2(20),
875
+ last_name VARCHAR2(25),
876
+ comments CLOB
877
+ )
878
+ SQL
879
+ @conn.execute <<-SQL
880
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
881
+ INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
882
+ SQL
883
+ @conn.execute <<-SQL
884
+ CREATE TABLE test2_employees (
885
+ id NUMBER(6,0) PRIMARY KEY,
886
+ first_name VARCHAR2(20),
887
+ last_name VARCHAR2(25),
888
+ comments CLOB
889
+ )
890
+ SQL
891
+ @conn.execute <<-SQL
892
+ CREATE SEQUENCE test2_employees_seq MINVALUE 1
893
+ INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
894
+ SQL
895
+ @char_data = (0..127).to_a.pack("C*") * 800
896
+ @char_data2 = ((1..127).to_a.pack("C*") + "\0") * 800
897
+
898
+ class ::TestEmployee < ActiveRecord::Base; end
899
+ class ::Test2Employee < ActiveRecord::Base
900
+ serialize :comments
901
+ end
902
+ end
903
+
904
+ after(:all) do
905
+ @conn.execute "DROP TABLE test_employees"
906
+ @conn.execute "DROP SEQUENCE test_employees_seq"
907
+ @conn.execute "DROP TABLE test2_employees"
908
+ @conn.execute "DROP SEQUENCE test2_employees_seq"
909
+ Object.send(:remove_const, "TestEmployee")
910
+ Object.send(:remove_const, "Test2Employee")
911
+ ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
912
+ end
913
+
914
+ it "should create record without CLOB data when attribute is serialized" do
915
+ @employee = Test2Employee.create!(
916
+ :first_name => "First",
917
+ :last_name => "Last"
918
+ )
919
+ @employee.should be_valid
920
+ end
921
+
922
+ it "should accept Symbol value for CLOB column" do
923
+ @employee = TestEmployee.create!(
924
+ :comments => :test_comment
925
+ )
926
+ @employee.should be_valid
927
+ end
928
+
929
+ it "should create record with CLOB data" do
930
+ @employee = TestEmployee.create!(
931
+ :first_name => "First",
932
+ :last_name => "Last",
933
+ :comments => @char_data
934
+ )
935
+ @employee.reload
936
+ @employee.comments.should == @char_data
937
+ end
938
+
939
+ it "should update record with CLOB data" do
940
+ @employee = TestEmployee.create!(
941
+ :first_name => "First",
942
+ :last_name => "Last"
943
+ )
944
+ @employee.reload
945
+ @employee.comments.should be_nil
946
+ @employee.comments = @char_data
947
+ @employee.save!
948
+ @employee.reload
949
+ @employee.comments.should == @char_data
950
+ end
951
+
952
+ it "should update record with zero-length CLOB data" do
953
+ @employee = TestEmployee.create!(
954
+ :first_name => "First",
955
+ :last_name => "Last"
956
+ )
957
+ @employee.reload
958
+ @employee.comments.should be_nil
959
+ @employee.comments = ''
960
+ @employee.save!
961
+ @employee.reload
962
+ @employee.comments.should == ''
963
+ end
964
+
965
+ it "should update record that has existing CLOB data with different CLOB data" do
966
+ @employee = TestEmployee.create!(
967
+ :first_name => "First",
968
+ :last_name => "Last",
969
+ :comments => @char_data
970
+ )
971
+ @employee.reload
972
+ @employee.comments = @char_data2
973
+ @employee.save!
974
+ @employee.reload
975
+ @employee.comments.should == @char_data2
976
+ end
977
+
978
+ it "should update record that has existing CLOB data with nil" do
979
+ @employee = TestEmployee.create!(
980
+ :first_name => "First",
981
+ :last_name => "Last",
982
+ :comments => @char_data
983
+ )
984
+ @employee.reload
985
+ @employee.comments = nil
986
+ @employee.save!
987
+ @employee.reload
988
+ @employee.comments.should be_nil
989
+ end
990
+
991
+ it "should update record that has existing CLOB data with zero-length CLOB data" do
992
+ @employee = TestEmployee.create!(
993
+ :first_name => "First",
994
+ :last_name => "Last",
995
+ :comments => @char_data
996
+ )
997
+ @employee.reload
998
+ @employee.comments = ''
999
+ @employee.save!
1000
+ @employee.reload
1001
+ @employee.comments.should == ''
1002
+ end
1003
+
1004
+ it "should update record that has zero-length CLOB data with non-empty CLOB data" do
1005
+ @employee = TestEmployee.create!(
1006
+ :first_name => "First",
1007
+ :last_name => "Last",
1008
+ :comments => ''
1009
+ )
1010
+ @employee.reload
1011
+ @employee.comments.should == ''
1012
+ @employee.comments = @char_data
1013
+ @employee.save!
1014
+ @employee.reload
1015
+ @employee.comments.should == @char_data
1016
+ end
1017
+ end
1018
+
1019
+ describe "OracleEnhancedAdapter handling of BLOB columns" do
1020
+ before(:all) do
1021
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
1022
+ @conn = ActiveRecord::Base.connection
1023
+ @conn.execute <<-SQL
1024
+ CREATE TABLE test_employees (
1025
+ employee_id NUMBER(6,0) PRIMARY KEY,
1026
+ first_name VARCHAR2(20),
1027
+ last_name VARCHAR2(25),
1028
+ binary_data BLOB
1029
+ )
1030
+ SQL
1031
+ @conn.execute <<-SQL
1032
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
1033
+ INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
1034
+ SQL
1035
+ @binary_data = "\0\1\2\3\4\5\6\7\8\9"*10000
1036
+ @binary_data2 = "\1\2\3\4\5\6\7\8\9\0"*10000
1037
+ end
1038
+
1039
+ after(:all) do
1040
+ @conn.execute "DROP TABLE test_employees"
1041
+ @conn.execute "DROP SEQUENCE test_employees_seq"
1042
+ end
1043
+
1044
+ before(:each) do
1045
+ class ::TestEmployee < ActiveRecord::Base
1046
+ set_primary_key :employee_id
1047
+ end
1048
+ end
1049
+
1050
+ after(:each) do
1051
+ Object.send(:remove_const, "TestEmployee")
1052
+ ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
1053
+ end
1054
+
1055
+ it "should create record with BLOB data" do
1056
+ @employee = TestEmployee.create!(
1057
+ :first_name => "First",
1058
+ :last_name => "Last",
1059
+ :binary_data => @binary_data
1060
+ )
1061
+ @employee.reload
1062
+ @employee.binary_data.should == @binary_data
1063
+ end
1064
+
1065
+ it "should update record with BLOB data" do
1066
+ @employee = TestEmployee.create!(
1067
+ :first_name => "First",
1068
+ :last_name => "Last"
1069
+ )
1070
+ @employee.reload
1071
+ @employee.binary_data.should be_nil
1072
+ @employee.binary_data = @binary_data
1073
+ @employee.save!
1074
+ @employee.reload
1075
+ @employee.binary_data.should == @binary_data
1076
+ end
1077
+
1078
+ it "should update record with zero-length BLOB data" do
1079
+ @employee = TestEmployee.create!(
1080
+ :first_name => "First",
1081
+ :last_name => "Last"
1082
+ )
1083
+ @employee.reload
1084
+ @employee.binary_data.should be_nil
1085
+ @employee.binary_data = ''
1086
+ @employee.save!
1087
+ @employee.reload
1088
+ @employee.binary_data.should == ''
1089
+ end
1090
+
1091
+ it "should update record that has existing BLOB data with different BLOB data" do
1092
+ @employee = TestEmployee.create!(
1093
+ :first_name => "First",
1094
+ :last_name => "Last",
1095
+ :binary_data => @binary_data
1096
+ )
1097
+ @employee.reload
1098
+ @employee.binary_data = @binary_data2
1099
+ @employee.save!
1100
+ @employee.reload
1101
+ @employee.binary_data.should == @binary_data2
1102
+ end
1103
+
1104
+ it "should update record that has existing BLOB data with nil" do
1105
+ @employee = TestEmployee.create!(
1106
+ :first_name => "First",
1107
+ :last_name => "Last",
1108
+ :binary_data => @binary_data
1109
+ )
1110
+ @employee.reload
1111
+ @employee.binary_data = nil
1112
+ @employee.save!
1113
+ @employee.reload
1114
+ @employee.binary_data.should be_nil
1115
+ end
1116
+
1117
+ it "should update record that has existing BLOB data with zero-length BLOB data" do
1118
+ @employee = TestEmployee.create!(
1119
+ :first_name => "First",
1120
+ :last_name => "Last",
1121
+ :binary_data => @binary_data
1122
+ )
1123
+ @employee.reload
1124
+ @employee.binary_data = ''
1125
+ @employee.save!
1126
+ @employee.reload
1127
+ @employee.binary_data.should == ''
1128
+ end
1129
+
1130
+ it "should update record that has zero-length BLOB data with non-empty BLOB data" do
1131
+ @employee = TestEmployee.create!(
1132
+ :first_name => "First",
1133
+ :last_name => "Last",
1134
+ :binary_data => ''
1135
+ )
1136
+ @employee.reload
1137
+ @employee.binary_data.should == ''
1138
+ @employee.binary_data = @binary_data
1139
+ @employee.save!
1140
+ @employee.reload
1141
+ @employee.binary_data.should == @binary_data
1142
+ end
1143
+ end
1144
+
1145
+ describe "OracleEnhancedAdapter handling of RAW columns" do
1146
+ before(:all) do
1147
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
1148
+ @conn = ActiveRecord::Base.connection
1149
+ @conn.execute <<-SQL
1150
+ CREATE TABLE test_employees (
1151
+ employee_id NUMBER(6,0) PRIMARY KEY,
1152
+ first_name VARCHAR2(20),
1153
+ last_name VARCHAR2(25),
1154
+ binary_data RAW(1024)
1155
+ )
1156
+ SQL
1157
+ @conn.execute <<-SQL
1158
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
1159
+ INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
1160
+ SQL
1161
+ @binary_data = "\0\1\2\3\4\5\6\7\8\9"*100
1162
+ @binary_data2 = "\1\2\3\4\5\6\7\8\9\0"*100
1163
+ end
1164
+
1165
+ after(:all) do
1166
+ @conn.execute "DROP TABLE test_employees"
1167
+ @conn.execute "DROP SEQUENCE test_employees_seq"
1168
+ end
1169
+
1170
+ before(:each) do
1171
+ class ::TestEmployee < ActiveRecord::Base
1172
+ set_primary_key :employee_id
1173
+ end
1174
+ end
1175
+
1176
+ after(:each) do
1177
+ Object.send(:remove_const, "TestEmployee")
1178
+ ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
1179
+ end
1180
+
1181
+ it "should create record with RAW data" do
1182
+ @employee = TestEmployee.create!(
1183
+ :first_name => "First",
1184
+ :last_name => "Last",
1185
+ :binary_data => @binary_data
1186
+ )
1187
+ @employee.reload
1188
+ @employee.binary_data.should == @binary_data
1189
+ end
1190
+
1191
+ it "should update record with RAW data" do
1192
+ @employee = TestEmployee.create!(
1193
+ :first_name => "First",
1194
+ :last_name => "Last"
1195
+ )
1196
+ @employee.reload
1197
+ @employee.binary_data.should be_nil
1198
+ @employee.binary_data = @binary_data
1199
+ @employee.save!
1200
+ @employee.reload
1201
+ @employee.binary_data.should == @binary_data
1202
+ end
1203
+
1204
+ it "should update record with zero-length RAW data" do
1205
+ @employee = TestEmployee.create!(
1206
+ :first_name => "First",
1207
+ :last_name => "Last"
1208
+ )
1209
+ @employee.reload
1210
+ @employee.binary_data.should be_nil
1211
+ @employee.binary_data = ''
1212
+ @employee.save!
1213
+ @employee.reload
1214
+ @employee.binary_data.should.nil?
1215
+ end
1216
+
1217
+ it "should update record that has existing RAW data with different RAW data" do
1218
+ @employee = TestEmployee.create!(
1219
+ :first_name => "First",
1220
+ :last_name => "Last",
1221
+ :binary_data => @binary_data
1222
+ )
1223
+ @employee.reload
1224
+ @employee.binary_data = @binary_data2
1225
+ @employee.save!
1226
+ @employee.reload
1227
+ @employee.binary_data.should == @binary_data2
1228
+ end
1229
+
1230
+ it "should update record that has existing RAW data with nil" do
1231
+ @employee = TestEmployee.create!(
1232
+ :first_name => "First",
1233
+ :last_name => "Last",
1234
+ :binary_data => @binary_data
1235
+ )
1236
+ @employee.reload
1237
+ @employee.binary_data = nil
1238
+ @employee.save!
1239
+ @employee.reload
1240
+ @employee.binary_data.should be_nil
1241
+ end
1242
+
1243
+ it "should update record that has existing RAW data with zero-length RAW data" do
1244
+ @employee = TestEmployee.create!(
1245
+ :first_name => "First",
1246
+ :last_name => "Last",
1247
+ :binary_data => @binary_data
1248
+ )
1249
+ @employee.reload
1250
+ @employee.binary_data = ''
1251
+ @employee.save!
1252
+ @employee.reload
1253
+ @employee.binary_data.should.nil?
1254
+ end
1255
+
1256
+ it "should update record that has zero-length BLOB data with non-empty RAW data" do
1257
+ @employee = TestEmployee.create!(
1258
+ :first_name => "First",
1259
+ :last_name => "Last",
1260
+ :binary_data => ''
1261
+ )
1262
+ @employee.reload
1263
+ @employee.binary_data = @binary_data
1264
+ @employee.save!
1265
+ @employee.reload
1266
+ @employee.binary_data.should == @binary_data
1267
+ end
1268
+ end
1269
+
1270
+
1271
+ describe "OracleEnhancedAdapter quoting of NCHAR and NVARCHAR2 columns" do
1272
+ before(:all) do
1273
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
1274
+ @conn = ActiveRecord::Base.connection
1275
+ @conn.execute <<-SQL
1276
+ CREATE TABLE test_items (
1277
+ id NUMBER(6,0) PRIMARY KEY,
1278
+ nchar_column NCHAR(20),
1279
+ nvarchar2_column NVARCHAR2(20),
1280
+ char_column CHAR(20),
1281
+ varchar2_column VARCHAR2(20)
1282
+ )
1283
+ SQL
1284
+ @conn.execute "CREATE SEQUENCE test_items_seq"
1285
+ end
1286
+
1287
+ after(:all) do
1288
+ @conn.execute "DROP TABLE test_items"
1289
+ @conn.execute "DROP SEQUENCE test_items_seq"
1290
+ end
1291
+
1292
+ before(:each) do
1293
+ class ::TestItem < ActiveRecord::Base
1294
+ end
1295
+ end
1296
+
1297
+ after(:each) do
1298
+ Object.send(:remove_const, "TestItem")
1299
+ ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
1300
+ end
1301
+
1302
+ it "should set nchar instance variable" do
1303
+ columns = @conn.columns('test_items')
1304
+ %w(nchar_column nvarchar2_column char_column varchar2_column).each do |col|
1305
+ column = columns.detect{|c| c.name == col}
1306
+ column.type.should == :string
1307
+ column.nchar.should == (col[0,1] == 'n' ? true : nil)
1308
+ end
1309
+ end
1310
+
1311
+ it "should quote with N prefix" do
1312
+ columns = @conn.columns('test_items')
1313
+ %w(nchar_column nvarchar2_column char_column varchar2_column).each do |col|
1314
+ column = columns.detect{|c| c.name == col}
1315
+ @conn.quote('abc', column).should == (column.nchar ? "N'abc'" : "'abc'")
1316
+ @conn.quote(nil, column).should == 'NULL'
1317
+ end
1318
+ end
1319
+
1320
+ it "should create record" do
1321
+ nchar_data = 'āčē'
1322
+ item = TestItem.create(
1323
+ :nchar_column => nchar_data,
1324
+ :nvarchar2_column => nchar_data
1325
+ ).reload
1326
+ item.nchar_column.should == nchar_data + ' '*17
1327
+ item.nvarchar2_column.should == nchar_data
1328
+ end
1329
+
1330
+ end