ctreatma-activerecord-oracle_enhanced-adapter 1.4.1.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 (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