plukevdh-activerecord-oracle_enhanced-adapter 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. data/History.txt +111 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +26 -0
  4. data/README.rdoc +68 -0
  5. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +5 -0
  6. data/lib/active_record/connection_adapters/oracle_enhanced.rake +48 -0
  7. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +1200 -0
  8. data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +71 -0
  9. data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +64 -0
  10. data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +21 -0
  11. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +39 -0
  12. data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +358 -0
  13. data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +368 -0
  14. data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +150 -0
  15. data/lib/active_record/connection_adapters/oracle_enhanced_reserved_words.rb +126 -0
  16. data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +11 -0
  17. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +7 -0
  18. data/oracle-enhanced.gemspec +59 -0
  19. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +659 -0
  20. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +170 -0
  21. data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +40 -0
  22. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +103 -0
  23. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +951 -0
  24. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +93 -0
  25. data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +27 -0
  26. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +340 -0
  27. data/spec/spec.opts +6 -0
  28. data/spec/spec_helper.rb +94 -0
  29. metadata +94 -0
@@ -0,0 +1,170 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+ describe "OracleEnhancedConnection create connection" do
4
+
5
+ before(:all) do
6
+ @conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(CONNECTION_PARAMS)
7
+ end
8
+
9
+ before(:each) do
10
+ @conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(CONNECTION_PARAMS) unless @conn.active?
11
+ end
12
+
13
+ after(:all) do
14
+ @conn.logoff if @conn.active?
15
+ end
16
+
17
+ it "should create new connection" do
18
+ @conn.should be_active
19
+ end
20
+
21
+ it "should ping active connection" do
22
+ @conn.ping.should be_true
23
+ end
24
+
25
+ it "should not ping inactive connection" do
26
+ @conn.logoff
27
+ lambda { @conn.ping }.should raise_error(ActiveRecord::ConnectionAdapters::OracleEnhancedConnectionException)
28
+ end
29
+
30
+ it "should reset active connection" do
31
+ @conn.reset!
32
+ @conn.should be_active
33
+ end
34
+
35
+ it "should be in autocommit mode after connection" do
36
+ @conn.should be_autocommit
37
+ end
38
+
39
+ end
40
+
41
+ describe "OracleEnhancedConnection SQL execution" do
42
+
43
+ before(:all) do
44
+ @conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(CONNECTION_PARAMS)
45
+ end
46
+
47
+ before(:each) do
48
+ @conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(CONNECTION_PARAMS) unless @conn.active?
49
+ end
50
+
51
+ after(:all) do
52
+ @conn.logoff if @conn.active?
53
+ end
54
+
55
+ it "should execute SQL statement" do
56
+ @conn.exec("SELECT * FROM dual").should_not be_nil
57
+ end
58
+
59
+ it "should execute SQL select" do
60
+ @conn.select("SELECT * FROM dual").should == [{'dummy' => 'X'}]
61
+ end
62
+
63
+ it "should execute SQL select and return also columns" do
64
+ @conn.select("SELECT * FROM dual", nil, true).should == [ [{'dummy' => 'X'}], ['dummy'] ]
65
+ end
66
+
67
+ end
68
+
69
+ describe "OracleEnhancedConnection auto reconnection" do
70
+
71
+ before(:all) do
72
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
73
+ @conn = ActiveRecord::Base.connection.instance_variable_get("@connection")
74
+ @sys_conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(SYS_CONNECTION_PARAMS)
75
+ end
76
+
77
+ before(:each) do
78
+ ActiveRecord::Base.connection.reconnect! unless @conn.active?
79
+ end
80
+
81
+ after(:all) do
82
+ ActiveRecord::Base.connection.disconnect! if @conn.active?
83
+ end
84
+
85
+ def kill_current_session
86
+ audsid = @conn.select("SELECT userenv('sessionid') audsid FROM dual").first['audsid']
87
+ sid_serial = @sys_conn.select("SELECT s.sid||','||s.serial# sid_serial
88
+ FROM v$session s
89
+ WHERE audsid = '#{audsid}'").first['sid_serial']
90
+ @sys_conn.exec "ALTER SYSTEM KILL SESSION '#{sid_serial}' IMMEDIATE"
91
+ end
92
+
93
+ it "should reconnect and execute SQL statement if connection is lost and auto retry is enabled" do
94
+ # @conn.auto_retry = true
95
+ ActiveRecord::Base.connection.auto_retry = true
96
+ kill_current_session
97
+ @conn.exec("SELECT * FROM dual").should_not be_nil
98
+ end
99
+
100
+ it "should not reconnect and execute SQL statement if connection is lost and auto retry is disabled" do
101
+ # @conn.auto_retry = false
102
+ ActiveRecord::Base.connection.auto_retry = false
103
+ kill_current_session
104
+ lambda { @conn.exec("SELECT * FROM dual") }.should raise_error
105
+ end
106
+
107
+ it "should reconnect and execute SQL select if connection is lost and auto retry is enabled" do
108
+ # @conn.auto_retry = true
109
+ ActiveRecord::Base.connection.auto_retry = true
110
+ kill_current_session
111
+ @conn.select("SELECT * FROM dual").should == [{'dummy' => 'X'}]
112
+ end
113
+
114
+ it "should not reconnect and execute SQL select if connection is lost and auto retry is disabled" do
115
+ # @conn.auto_retry = false
116
+ ActiveRecord::Base.connection.auto_retry = false
117
+ kill_current_session
118
+ lambda { @conn.select("SELECT * FROM dual") }.should raise_error
119
+ end
120
+
121
+ end
122
+
123
+ describe "OracleEnhancedConnection describe table" do
124
+
125
+ before(:all) do
126
+ @conn = ActiveRecord::ConnectionAdapters::OracleEnhancedConnection.create(CONNECTION_PARAMS)
127
+ @owner = CONNECTION_PARAMS[:username].upcase
128
+ end
129
+
130
+ after(:all) do
131
+ @conn.logoff if @conn.active?
132
+ end
133
+
134
+ it "should describe existing table" do
135
+ @conn.exec "CREATE TABLE test_employees (first_name VARCHAR2(20))" rescue nil
136
+ @conn.describe("test_employees").should == [@owner, "TEST_EMPLOYEES"]
137
+ @conn.exec "DROP TABLE test_employees" rescue nil
138
+ end
139
+
140
+ it "should not describe non-existing table" do
141
+ lambda { @conn.describe("test_xxx") }.should raise_error(ActiveRecord::ConnectionAdapters::OracleEnhancedConnectionException)
142
+ end
143
+
144
+ it "should describe table in other schema" do
145
+ @conn.describe("sys.dual").should == ["SYS", "DUAL"]
146
+ end
147
+
148
+ it "should describe existing view" do
149
+ @conn.exec "CREATE TABLE test_employees (first_name VARCHAR2(20))" rescue nil
150
+ @conn.exec "CREATE VIEW test_employees_v AS SELECT * FROM test_employees" rescue nil
151
+ @conn.describe("test_employees_v").should == [@owner, "TEST_EMPLOYEES_V"]
152
+ @conn.exec "DROP VIEW test_employees_v" rescue nil
153
+ @conn.exec "DROP TABLE test_employees" rescue nil
154
+ end
155
+
156
+ it "should describe view in other schema" do
157
+ @conn.describe("sys.v_$version").should == ["SYS", "V_$VERSION"]
158
+ end
159
+
160
+ it "should describe existing private synonym" do
161
+ @conn.exec "CREATE SYNONYM test_dual FOR sys.dual" rescue nil
162
+ @conn.describe("test_dual").should == ["SYS", "DUAL"]
163
+ @conn.exec "DROP SYNONYM test_dual" rescue nil
164
+ end
165
+
166
+ it "should describe existing public synonym" do
167
+ @conn.describe("all_tables").should == ["SYS", "ALL_TABLES"]
168
+ end
169
+
170
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+
3
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
4
+
5
+ describe "OracleEnhancedAdapter to_d method" do
6
+ it "BigDecimal#to_d returns the same decimal number" do
7
+ d = BigDecimal.new("12345678901234567890.0123456789")
8
+ d.to_d.should == d
9
+ end
10
+
11
+ it "Bignum#to_d translates large integer to decimal" do
12
+ n = 12345678901234567890
13
+ n.to_d.should == BigDecimal.new(n.to_s)
14
+ end
15
+
16
+ it "Fixnum#to_d translates small integer to decimal" do
17
+ n = 123456
18
+ n.to_d.should == BigDecimal.new(n.to_s)
19
+ end
20
+ end
21
+
22
+ if ENV['RAILS_GEM_VERSION'] >= '2.3'
23
+
24
+ describe "OracleEnhancedAdapter Unicode aware upcase and downcase" do
25
+ before(:all) do
26
+ @down = "āčēģīķļņšūž"
27
+ @up = "ĀČĒĢĪĶĻŅŠŪŽ"
28
+ end
29
+
30
+ it "should translate Unicode string to upcase" do
31
+ @down.mb_chars.upcase.to_s.should == @up
32
+ end
33
+
34
+ it "should translate Unicode string to downcase" do
35
+ @up.mb_chars.downcase.to_s.should == @down
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,103 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+ describe "OracleEnhancedAdapter composite_primary_keys support" do
4
+
5
+ before(:all) do
6
+ if defined?(::ActiveRecord::ConnectionAdapters::OracleAdapter)
7
+ @old_oracle_adapter = ::ActiveRecord::ConnectionAdapters::OracleAdapter
8
+ ::ActiveRecord::ConnectionAdapters.send(:remove_const, :OracleAdapter)
9
+ end
10
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
11
+ if $cpk_oracle_adapter
12
+ ::ActiveRecord::ConnectionAdapters::OracleAdapter = $cpk_oracle_adapter
13
+ $cpk_oracle_adapter = nil
14
+ end
15
+ require 'composite_primary_keys'
16
+ end
17
+
18
+ after(:all) do
19
+ # Object.send(:remove_const, 'CompositePrimaryKeys') if defined?(CompositePrimaryKeys)
20
+ if defined?(::ActiveRecord::ConnectionAdapters::OracleAdapter)
21
+ $cpk_oracle_adapter = ::ActiveRecord::ConnectionAdapters::OracleAdapter
22
+ ::ActiveRecord::ConnectionAdapters.send(:remove_const, :OracleAdapter)
23
+ end
24
+ if @old_oracle_adapter
25
+ ::ActiveRecord::ConnectionAdapters::OracleAdapter = @old_oracle_adapter
26
+ @old_oracle_adapter = nil
27
+ end
28
+ end
29
+
30
+ describe "do not use count distinct" do
31
+ before(:all) do
32
+ class ::JobHistory < ActiveRecord::Base
33
+ set_table_name "job_history"
34
+ set_primary_keys :employee_id, :start_date
35
+ end
36
+ end
37
+
38
+ after(:all) do
39
+ Object.send(:remove_const, 'JobHistory') if defined?(JobHistory)
40
+ end
41
+
42
+ it "should tell ActiveRecord that count distinct is not supported" do
43
+ ActiveRecord::Base.connection.supports_count_distinct?.should be_false
44
+ end
45
+
46
+ it "should execute correct SQL COUNT DISTINCT statement on table with composite primary keys" do
47
+ lambda { JobHistory.count(:distinct => true) }.should_not raise_error
48
+ end
49
+ end
50
+
51
+ describe "table with LOB" do
52
+ before(:all) do
53
+ ActiveRecord::Schema.define do
54
+ suppress_messages do
55
+ create_table :cpk_write_lobs_test, :primary_key => [:type_category, :date_value], :force => true do |t|
56
+ t.string :type_category, :limit => 15, :null => false
57
+ t.date :date_value, :null => false
58
+ t.text :results, :null => false
59
+ t.timestamps
60
+ end
61
+ create_table :non_cpk_write_lobs_test, :force => true do |t|
62
+ t.date :date_value, :null => false
63
+ t.text :results, :null => false
64
+ t.timestamps
65
+ end
66
+ end
67
+ end
68
+ class ::CpkWriteLobsTest < ActiveRecord::Base
69
+ set_table_name 'cpk_write_lobs_test'
70
+ set_primary_keys :type_category, :date_value
71
+ end
72
+ class ::NonCpkWriteLobsTest < ActiveRecord::Base
73
+ set_table_name 'non_cpk_write_lobs_test'
74
+ end
75
+ end
76
+
77
+ after(:all) do
78
+ ActiveRecord::Schema.define do
79
+ suppress_messages do
80
+ drop_table :cpk_write_lobs_test
81
+ drop_table :non_cpk_write_lobs_test
82
+ end
83
+ end
84
+ Object.send(:remove_const, "CpkWriteLobsTest")
85
+ Object.send(:remove_const, "NonCpkWriteLobsTest")
86
+ end
87
+
88
+ it "should create new record in table with CPK and LOB" do
89
+ lambda {
90
+ CpkWriteLobsTest.create(:type_category => 'AAA', :date_value => Date.today, :results => 'DATA '*10)
91
+ }.should_not raise_error
92
+ end
93
+
94
+ it "should create new record in table without CPK and with LOB" do
95
+ lambda {
96
+ NonCpkWriteLobsTest.create(:date_value => Date.today, :results => 'DATA '*10)
97
+ }.should_not raise_error
98
+ end
99
+ end
100
+
101
+ # Other testing was done based on composite_primary_keys tests
102
+
103
+ end
@@ -0,0 +1,951 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+ describe "OracleEnhancedAdapter date type detection based on column names" do
4
+ before(:all) do
5
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
6
+ @conn = ActiveRecord::Base.connection
7
+ @conn.execute <<-SQL
8
+ CREATE TABLE test_employees (
9
+ employee_id NUMBER(6,0),
10
+ first_name VARCHAR2(20),
11
+ last_name VARCHAR2(25),
12
+ email VARCHAR2(25),
13
+ phone_number VARCHAR2(20),
14
+ hire_date DATE,
15
+ job_id NUMBER(6,0),
16
+ salary NUMBER(8,2),
17
+ commission_pct NUMBER(2,2),
18
+ manager_id NUMBER(6,0),
19
+ department_id NUMBER(4,0),
20
+ created_at DATE,
21
+ updated_at DATE
22
+ )
23
+ SQL
24
+ @conn.execute <<-SQL
25
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
26
+ INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
27
+ SQL
28
+ end
29
+
30
+ after(:all) do
31
+ @conn.execute "DROP TABLE test_employees"
32
+ @conn.execute "DROP SEQUENCE test_employees_seq"
33
+ end
34
+
35
+ it "should set DATE column type as datetime if emulate_dates_by_column_name is false" do
36
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
37
+ columns = @conn.columns('test_employees')
38
+ column = columns.detect{|c| c.name == "hire_date"}
39
+ column.type.should == :datetime
40
+ end
41
+
42
+ it "should set DATE column type as date if column name contains '_date_' and emulate_dates_by_column_name is true" do
43
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
44
+ columns = @conn.columns('test_employees')
45
+ column = columns.detect{|c| c.name == "hire_date"}
46
+ column.type.should == :date
47
+ end
48
+
49
+ it "should set DATE column type as datetime if column name does not contain '_date_' and emulate_dates_by_column_name is true" do
50
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
51
+ columns = @conn.columns('test_employees')
52
+ column = columns.detect{|c| c.name == "created_at"}
53
+ column.type.should == :datetime
54
+ end
55
+
56
+ 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
57
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
58
+ columns = @conn.columns('test_employees')
59
+ column = columns.detect{|c| c.name == "updated_at"}
60
+ column.type.should == :datetime
61
+ end
62
+
63
+ it "should return Time value from DATE column if emulate_dates_by_column_name is false" do
64
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
65
+ columns = @conn.columns('test_employees')
66
+ column = columns.detect{|c| c.name == "hire_date"}
67
+ column.type_cast(Time.now).class.should == Time
68
+ end
69
+
70
+ it "should return Date value from DATE column if column name contains 'date' and emulate_dates_by_column_name is true" do
71
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
72
+ columns = @conn.columns('test_employees')
73
+ column = columns.detect{|c| c.name == "hire_date"}
74
+ column.type_cast(Time.now).class.should == Date
75
+ end
76
+
77
+ 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
78
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
79
+ columns = @conn.columns('test_employees')
80
+ column = columns.detect{|c| c.name == "hire_date"}
81
+ column.type_cast(DateTime.new(1900,1,1)).class.should == Date
82
+ end
83
+
84
+ describe "/ DATE values from ActiveRecord model" do
85
+ before(:each) do
86
+ ActiveRecord::Base.connection.clear_types_for_columns
87
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
88
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates = false
89
+ class ::TestEmployee < ActiveRecord::Base
90
+ set_table_name "hr.test_employees"
91
+ set_primary_key :employee_id
92
+ end
93
+ end
94
+
95
+ def create_test_employee(params={})
96
+ @today = params[:today] || Date.new(2008,8,19)
97
+ @now = params[:now] || Time.local(2008,8,19,17,03,59)
98
+ @employee = TestEmployee.create(
99
+ :first_name => "First",
100
+ :last_name => "Last",
101
+ :hire_date => @today,
102
+ :created_at => @now
103
+ )
104
+ @employee.reload
105
+ end
106
+
107
+ after(:each) do
108
+ # @employee.destroy if @employee
109
+ Object.send(:remove_const, "TestEmployee")
110
+ end
111
+
112
+ it "should return Time value from DATE column if emulate_dates_by_column_name is false" do
113
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
114
+ create_test_employee
115
+ @employee.hire_date.class.should == Time
116
+ end
117
+
118
+ it "should return Date value from DATE column if column name contains 'date' and emulate_dates_by_column_name is true" do
119
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
120
+ create_test_employee
121
+ @employee.hire_date.class.should == Date
122
+ end
123
+
124
+ 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
125
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
126
+ create_test_employee(:today => Date.new(1900,1,1))
127
+ @employee.hire_date.class.should == Date
128
+ end
129
+
130
+ it "should return Time value from DATE column if column name does not contain 'date' and emulate_dates_by_column_name is true" do
131
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
132
+ create_test_employee
133
+ @employee.created_at.class.should == Time
134
+ end
135
+
136
+ it "should return Date value from DATE column if emulate_dates_by_column_name is false but column is defined as date" do
137
+ class ::TestEmployee < ActiveRecord::Base
138
+ set_date_columns :hire_date
139
+ end
140
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
141
+ create_test_employee
142
+ @employee.hire_date.class.should == Date
143
+ end
144
+
145
+ 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
146
+ class ::TestEmployee < ActiveRecord::Base
147
+ set_date_columns :hire_date
148
+ end
149
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
150
+ create_test_employee(:today => Date.new(1900,1,1))
151
+ @employee.hire_date.class.should == Date
152
+ end
153
+
154
+ it "should return Time value from DATE column if emulate_dates_by_column_name is true but column is defined as datetime" do
155
+ class ::TestEmployee < ActiveRecord::Base
156
+ set_datetime_columns :hire_date
157
+ end
158
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
159
+ create_test_employee
160
+ @employee.hire_date.class.should == Time
161
+ # change to current time with hours, minutes and seconds
162
+ @employee.hire_date = @now
163
+ @employee.save!
164
+ @employee.reload
165
+ @employee.hire_date.class.should == Time
166
+ @employee.hire_date.should == @now
167
+ end
168
+
169
+ it "should guess Date or Time value if emulate_dates is true" do
170
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates = true
171
+ create_test_employee
172
+ @employee.hire_date.class.should == Date
173
+ @employee.created_at.class.should == Time
174
+ end
175
+
176
+ end
177
+
178
+ end
179
+
180
+ describe "OracleEnhancedAdapter integer type detection based on column names" do
181
+ before(:all) do
182
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
183
+ @conn = ActiveRecord::Base.connection
184
+ @conn.execute <<-SQL
185
+ CREATE TABLE test2_employees (
186
+ id NUMBER,
187
+ first_name VARCHAR2(20),
188
+ last_name VARCHAR2(25),
189
+ email VARCHAR2(25),
190
+ phone_number VARCHAR2(20),
191
+ hire_date DATE,
192
+ job_id NUMBER,
193
+ salary NUMBER,
194
+ commission_pct NUMBER(2,2),
195
+ manager_id NUMBER(6),
196
+ department_id NUMBER(4,0),
197
+ created_at DATE
198
+ )
199
+ SQL
200
+ @conn.execute <<-SQL
201
+ CREATE SEQUENCE test2_employees_seq MINVALUE 1
202
+ INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
203
+ SQL
204
+ end
205
+
206
+ after(:all) do
207
+ @conn.execute "DROP TABLE test2_employees"
208
+ @conn.execute "DROP SEQUENCE test2_employees_seq"
209
+ end
210
+
211
+ it "should set NUMBER column type as decimal if emulate_integers_by_column_name is false" do
212
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = false
213
+ columns = @conn.columns('test2_employees')
214
+ column = columns.detect{|c| c.name == "job_id"}
215
+ column.type.should == :decimal
216
+ end
217
+
218
+ it "should set NUMBER column type as integer if emulate_integers_by_column_name is true" do
219
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
220
+ columns = @conn.columns('test2_employees')
221
+ column = columns.detect{|c| c.name == "job_id"}
222
+ column.type.should == :integer
223
+ column = columns.detect{|c| c.name == "id"}
224
+ column.type.should == :integer
225
+ end
226
+
227
+ it "should set NUMBER column type as decimal if column name does not contain 'id' and emulate_integers_by_column_name is true" do
228
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
229
+ columns = @conn.columns('test2_employees')
230
+ column = columns.detect{|c| c.name == "salary"}
231
+ column.type.should == :decimal
232
+ end
233
+
234
+ it "should return BigDecimal value from NUMBER column if emulate_integers_by_column_name is false" do
235
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = false
236
+ columns = @conn.columns('test2_employees')
237
+ column = columns.detect{|c| c.name == "job_id"}
238
+ column.type_cast(1.0).class.should == BigDecimal
239
+ end
240
+
241
+ it "should return Fixnum value from NUMBER column if column name contains '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 == "job_id"}
245
+ column.type_cast(1.0).class.should == Fixnum
246
+ end
247
+
248
+ describe "/ NUMBER values from ActiveRecord model" do
249
+ before(:each) do
250
+ class ::Test2Employee < ActiveRecord::Base
251
+ end
252
+ end
253
+
254
+ after(:each) do
255
+ Object.send(:remove_const, "Test2Employee")
256
+ end
257
+
258
+ def create_employee2
259
+ @employee2 = Test2Employee.create(
260
+ :first_name => "First",
261
+ :last_name => "Last",
262
+ :job_id => 1,
263
+ :salary => 1000
264
+ )
265
+ @employee2.reload
266
+ end
267
+
268
+ it "should return BigDecimal value from NUMBER column if emulate_integers_by_column_name is false" do
269
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = false
270
+ create_employee2
271
+ @employee2.job_id.class.should == BigDecimal
272
+ end
273
+
274
+ it "should return Fixnum value from NUMBER column if column name contains 'id' and emulate_integers_by_column_name is true" do
275
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
276
+ create_employee2
277
+ @employee2.job_id.class.should == Fixnum
278
+ end
279
+
280
+ it "should return BigDecimal value from NUMBER column if column name does not contain 'id' and emulate_integers_by_column_name is true" do
281
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
282
+ create_employee2
283
+ @employee2.salary.class.should == BigDecimal
284
+ end
285
+
286
+ end
287
+
288
+ end
289
+
290
+ describe "OracleEnhancedAdapter boolean type detection based on string column types and names" do
291
+ before(:all) do
292
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
293
+ @conn = ActiveRecord::Base.connection
294
+ @conn.execute <<-SQL
295
+ CREATE TABLE test3_employees (
296
+ id NUMBER,
297
+ first_name VARCHAR2(20),
298
+ last_name VARCHAR2(25),
299
+ email VARCHAR2(25),
300
+ phone_number VARCHAR2(20),
301
+ hire_date DATE,
302
+ job_id NUMBER,
303
+ salary NUMBER,
304
+ commission_pct NUMBER(2,2),
305
+ manager_id NUMBER(6),
306
+ department_id NUMBER(4,0),
307
+ created_at DATE,
308
+ has_email CHAR(1),
309
+ has_phone VARCHAR2(1) DEFAULT 'Y',
310
+ active_flag VARCHAR2(2),
311
+ manager_yn VARCHAR2(3) DEFAULT 'N',
312
+ test_boolean VARCHAR2(3)
313
+ )
314
+ SQL
315
+ @conn.execute <<-SQL
316
+ CREATE SEQUENCE test3_employees_seq MINVALUE 1
317
+ INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
318
+ SQL
319
+ end
320
+
321
+ after(:all) do
322
+ @conn.execute "DROP TABLE test3_employees"
323
+ @conn.execute "DROP SEQUENCE test3_employees_seq"
324
+ end
325
+
326
+ it "should set CHAR/VARCHAR2 column type as string if emulate_booleans_from_strings is false" do
327
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
328
+ columns = @conn.columns('test3_employees')
329
+ %w(has_email has_phone active_flag manager_yn).each do |col|
330
+ column = columns.detect{|c| c.name == col}
331
+ column.type.should == :string
332
+ end
333
+ end
334
+
335
+ it "should set CHAR/VARCHAR2 column type as boolean if emulate_booleans_from_strings is true" do
336
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
337
+ columns = @conn.columns('test3_employees')
338
+ %w(has_email has_phone active_flag manager_yn).each do |col|
339
+ column = columns.detect{|c| c.name == col}
340
+ column.type.should == :boolean
341
+ end
342
+ end
343
+
344
+ 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
345
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
346
+ columns = @conn.columns('test3_employees')
347
+ %w(phone_number email).each do |col|
348
+ column = columns.detect{|c| c.name == col}
349
+ column.type.should == :string
350
+ end
351
+ end
352
+
353
+ it "should return string value from VARCHAR2 boolean column if emulate_booleans_from_strings is false" do
354
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
355
+ columns = @conn.columns('test3_employees')
356
+ %w(has_email has_phone active_flag manager_yn).each do |col|
357
+ column = columns.detect{|c| c.name == col}
358
+ column.type_cast("Y").class.should == String
359
+ end
360
+ end
361
+
362
+ it "should return boolean value from VARCHAR2 boolean column if emulate_booleans_from_strings is true" do
363
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
364
+ columns = @conn.columns('test3_employees')
365
+ %w(has_email has_phone active_flag manager_yn).each do |col|
366
+ column = columns.detect{|c| c.name == col}
367
+ column.type_cast("Y").class.should == TrueClass
368
+ column.type_cast("N").class.should == FalseClass
369
+ end
370
+ end
371
+
372
+ it "should translate boolean type to VARCHAR2(1) if emulate_booleans_from_strings is true" do
373
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
374
+ ActiveRecord::Base.connection.type_to_sql(
375
+ :boolean, nil, nil, nil).should == "VARCHAR2(1)"
376
+ end
377
+
378
+ it "should translate boolean type to NUMBER(1) if emulate_booleans_from_strings is true" do
379
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
380
+ ActiveRecord::Base.connection.type_to_sql(
381
+ :boolean, nil, nil, nil).should == "NUMBER(1)"
382
+ end
383
+
384
+ it "should get default value from VARCHAR2 boolean column if emulate_booleans_from_strings is true" do
385
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
386
+ columns = @conn.columns('test3_employees')
387
+ columns.detect{|c| c.name == 'has_phone'}.default.should be_true
388
+ columns.detect{|c| c.name == 'manager_yn'}.default.should be_false
389
+ end
390
+
391
+ describe "/ VARCHAR2 boolean values from ActiveRecord model" do
392
+ before(:each) do
393
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
394
+ class ::Test3Employee < ActiveRecord::Base
395
+ end
396
+ end
397
+
398
+ after(:each) do
399
+ Object.send(:remove_const, "Test3Employee")
400
+ end
401
+
402
+ def create_employee3(params={})
403
+ @employee3 = Test3Employee.create(
404
+ {
405
+ :first_name => "First",
406
+ :last_name => "Last",
407
+ :has_email => true,
408
+ :has_phone => false,
409
+ :active_flag => true,
410
+ :manager_yn => false
411
+ }.merge(params)
412
+ )
413
+ @employee3.reload
414
+ end
415
+
416
+ it "should return String value from VARCHAR2 boolean column if emulate_booleans_from_strings is false" do
417
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
418
+ create_employee3
419
+ %w(has_email has_phone active_flag manager_yn).each do |col|
420
+ @employee3.send(col.to_sym).class.should == String
421
+ end
422
+ end
423
+
424
+ it "should return boolean value from VARCHAR2 boolean column if emulate_booleans_from_strings is true" do
425
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
426
+ create_employee3
427
+ %w(has_email active_flag).each do |col|
428
+ @employee3.send(col.to_sym).class.should == TrueClass
429
+ @employee3.send((col+"_before_type_cast").to_sym).should == "Y"
430
+ end
431
+ %w(has_phone manager_yn).each do |col|
432
+ @employee3.send(col.to_sym).class.should == FalseClass
433
+ @employee3.send((col+"_before_type_cast").to_sym).should == "N"
434
+ end
435
+ end
436
+
437
+ it "should return string value from VARCHAR2 column if it is not boolean column and emulate_booleans_from_strings is true" do
438
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
439
+ create_employee3
440
+ @employee3.first_name.class.should == String
441
+ end
442
+
443
+ it "should return boolean value from VARCHAR2 boolean column if column specified in set_boolean_columns" do
444
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
445
+ class ::Test3Employee < ActiveRecord::Base
446
+ set_boolean_columns :test_boolean
447
+ end
448
+ create_employee3(:test_boolean => true)
449
+ @employee3.test_boolean.class.should == TrueClass
450
+ @employee3.test_boolean_before_type_cast.should == "Y"
451
+ create_employee3(:test_boolean => false)
452
+ @employee3.test_boolean.class.should == FalseClass
453
+ @employee3.test_boolean_before_type_cast.should == "N"
454
+ create_employee3(:test_boolean => nil)
455
+ @employee3.test_boolean.class.should == NilClass
456
+ @employee3.test_boolean_before_type_cast.should == nil
457
+ create_employee3(:test_boolean => "")
458
+ @employee3.test_boolean.class.should == NilClass
459
+ @employee3.test_boolean_before_type_cast.should == nil
460
+ end
461
+
462
+ end
463
+
464
+ end
465
+
466
+ describe "OracleEnhancedAdapter timestamp with timezone support" do
467
+ before(:all) do
468
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
469
+ @conn = ActiveRecord::Base.connection
470
+ @conn.execute <<-SQL
471
+ CREATE TABLE test_employees (
472
+ employee_id NUMBER(6,0),
473
+ first_name VARCHAR2(20),
474
+ last_name VARCHAR2(25),
475
+ email VARCHAR2(25),
476
+ phone_number VARCHAR2(20),
477
+ hire_date DATE,
478
+ job_id NUMBER(6,0),
479
+ salary NUMBER(8,2),
480
+ commission_pct NUMBER(2,2),
481
+ manager_id NUMBER(6,0),
482
+ department_id NUMBER(4,0),
483
+ created_at TIMESTAMP,
484
+ created_at_tz TIMESTAMP WITH TIME ZONE,
485
+ created_at_ltz TIMESTAMP WITH LOCAL TIME ZONE
486
+ )
487
+ SQL
488
+ @conn.execute <<-SQL
489
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
490
+ INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
491
+ SQL
492
+ end
493
+
494
+ after(:all) do
495
+ @conn.execute "DROP TABLE test_employees"
496
+ @conn.execute "DROP SEQUENCE test_employees_seq"
497
+ end
498
+
499
+ it "should set TIMESTAMP columns type as datetime" do
500
+ columns = @conn.columns('test_employees')
501
+ ts_columns = columns.select{|c| c.name =~ /created_at/}
502
+ ts_columns.each {|c| c.type.should == :timestamp}
503
+ end
504
+
505
+ describe "/ TIMESTAMP WITH TIME ZONE values from ActiveRecord model" do
506
+ before(:all) do
507
+ class ::TestEmployee < ActiveRecord::Base
508
+ set_primary_key :employee_id
509
+ end
510
+ end
511
+
512
+ after(:all) do
513
+ Object.send(:remove_const, "TestEmployee")
514
+ end
515
+
516
+ it "should return Time value from TIMESTAMP columns" do
517
+ # currently fractional seconds are not retrieved from database
518
+ @now = Time.local(2008,5,26,23,11,11,0)
519
+ @employee = TestEmployee.create(
520
+ :created_at => @now,
521
+ :created_at_tz => @now,
522
+ :created_at_ltz => @now
523
+ )
524
+ @employee.reload
525
+ [:created_at, :created_at_tz, :created_at_ltz].each do |c|
526
+ @employee.send(c).class.should == Time
527
+ @employee.send(c).to_f.should == @now.to_f
528
+ end
529
+ end
530
+
531
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
532
+ it "should return Time value with fractional seconds from TIMESTAMP columns" do
533
+ # currently fractional seconds are not retrieved from database
534
+ @now = Time.local(2008,5,26,23,11,11,10)
535
+ @employee = TestEmployee.create(
536
+ :created_at => @now,
537
+ :created_at_tz => @now,
538
+ :created_at_ltz => @now
539
+ )
540
+ @employee.reload
541
+ [:created_at, :created_at_tz, :created_at_ltz].each do |c|
542
+ @employee.send(c).class.should == Time
543
+ @employee.send(c).to_f.should == @now.to_f
544
+ end
545
+ end
546
+ else
547
+ it "should return Time value without fractional seconds from TIMESTAMP columns" do
548
+ # currently fractional seconds are not retrieved from database
549
+ @now = Time.local(2008,5,26,23,11,11,10)
550
+ @employee = TestEmployee.create(
551
+ :created_at => @now,
552
+ :created_at_tz => @now,
553
+ :created_at_ltz => @now
554
+ )
555
+ @employee.reload
556
+ [:created_at, :created_at_tz, :created_at_ltz].each do |c|
557
+ @employee.send(c).class.should == Time
558
+ @employee.send(c).to_f.should == @now.to_f.to_i.to_f # remove fractional seconds
559
+ end
560
+ end
561
+ end
562
+
563
+ end
564
+
565
+ end
566
+
567
+
568
+ describe "OracleEnhancedAdapter date and timestamp with different NLS date formats" do
569
+ before(:all) do
570
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
571
+ @conn = ActiveRecord::Base.connection
572
+ @conn.execute <<-SQL
573
+ CREATE TABLE test_employees (
574
+ employee_id NUMBER(6,0),
575
+ first_name VARCHAR2(20),
576
+ last_name VARCHAR2(25),
577
+ email VARCHAR2(25),
578
+ phone_number VARCHAR2(20),
579
+ hire_date DATE,
580
+ job_id NUMBER(6,0),
581
+ salary NUMBER(8,2),
582
+ commission_pct NUMBER(2,2),
583
+ manager_id NUMBER(6,0),
584
+ department_id NUMBER(4,0),
585
+ created_at DATE,
586
+ created_at_ts TIMESTAMP
587
+ )
588
+ SQL
589
+ @conn.execute <<-SQL
590
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
591
+ INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
592
+ SQL
593
+ # @conn.execute %q{alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'}
594
+ @conn.execute %q{alter session set nls_date_format = 'DD-MON-YYYY HH24:MI:SS'}
595
+ # @conn.execute %q{alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'}
596
+ @conn.execute %q{alter session set nls_timestamp_format = 'DD-MON-YYYY HH24:MI:SS'}
597
+ end
598
+
599
+ after(:all) do
600
+ @conn.execute "DROP TABLE test_employees"
601
+ @conn.execute "DROP SEQUENCE test_employees_seq"
602
+ end
603
+
604
+ before(:each) do
605
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates = false
606
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
607
+ class ::TestEmployee < ActiveRecord::Base
608
+ set_primary_key :employee_id
609
+ end
610
+ @today = Date.new(2008,6,28)
611
+ @now = Time.local(2008,6,28,13,34,33)
612
+ end
613
+
614
+ after(:each) do
615
+ Object.send(:remove_const, "TestEmployee")
616
+ end
617
+
618
+ def create_test_employee
619
+ @employee = TestEmployee.create(
620
+ :first_name => "First",
621
+ :last_name => "Last",
622
+ :hire_date => @today,
623
+ :created_at => @now,
624
+ :created_at_ts => @now
625
+ )
626
+ @employee.reload
627
+ end
628
+
629
+ it "should return Time value from DATE column if emulate_dates_by_column_name is false" do
630
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
631
+ create_test_employee
632
+ @employee.hire_date.class.should == Time
633
+ @employee.hire_date.should == @today.to_time
634
+ end
635
+
636
+ it "should return Date value from DATE column if column name contains 'date' and emulate_dates_by_column_name is true" do
637
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
638
+ create_test_employee
639
+ @employee.hire_date.class.should == Date
640
+ @employee.hire_date.should == @today
641
+ end
642
+
643
+ it "should return Time value from DATE column if column name does not contain 'date' and emulate_dates_by_column_name is true" do
644
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
645
+ create_test_employee
646
+ @employee.created_at.class.should == Time
647
+ @employee.created_at.should == @now
648
+ end
649
+
650
+ it "should return Time value from TIMESTAMP columns" do
651
+ create_test_employee
652
+ @employee.created_at_ts.class.should == Time
653
+ @employee.created_at_ts.should == @now
654
+ end
655
+
656
+ it "should quote Date values with TO_DATE" do
657
+ @conn.quote(@today).should == "TO_DATE('#{@today.year}-#{"%02d" % @today.month}-#{"%02d" % @today.day}','YYYY-MM-DD HH24:MI:SS')"
658
+ end
659
+
660
+ it "should quote Time values with TO_DATE" do
661
+ @conn.quote(@now).should == "TO_DATE('#{@now.year}-#{"%02d" % @now.month}-#{"%02d" % @now.day} "+
662
+ "#{"%02d" % @now.hour}:#{"%02d" % @now.min}:#{"%02d" % @now.sec}','YYYY-MM-DD HH24:MI:SS')"
663
+ end
664
+
665
+ it "should quote Time values with TO_TIMESTAMP" do
666
+ @ts = @now + 0.1
667
+ @conn.quote(@ts).should == "TO_TIMESTAMP('#{@ts.year}-#{"%02d" % @ts.month}-#{"%02d" % @ts.day} "+
668
+ "#{"%02d" % @ts.hour}:#{"%02d" % @ts.min}:#{"%02d" % @ts.sec}.100000','YYYY-MM-DD HH24:MI:SS.FF6')"
669
+ end
670
+
671
+ end
672
+
673
+ describe "OracleEnhancedAdapter assign string to :date and :datetime columns" do
674
+ before(:all) do
675
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
676
+ @conn = ActiveRecord::Base.connection
677
+ @conn.execute <<-SQL
678
+ CREATE TABLE test_employees (
679
+ employee_id NUMBER(6,0),
680
+ first_name VARCHAR2(20),
681
+ last_name VARCHAR2(25),
682
+ hire_date DATE,
683
+ last_login_at DATE,
684
+ last_login_at_ts TIMESTAMP
685
+ )
686
+ SQL
687
+ @conn.execute <<-SQL
688
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
689
+ INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
690
+ SQL
691
+ class ::TestEmployee < ActiveRecord::Base
692
+ set_primary_key :employee_id
693
+ end
694
+ end
695
+
696
+ after(:all) do
697
+ Object.send(:remove_const, "TestEmployee")
698
+ @conn.execute "DROP TABLE test_employees"
699
+ @conn.execute "DROP SEQUENCE test_employees_seq"
700
+ end
701
+
702
+ before(:each) do
703
+ @today = Date.new(2008,6,28)
704
+ @today_iso = "2008-06-28"
705
+ @today_nls = "28.06.2008"
706
+ @nls_date_format = "%d.%m.%Y"
707
+ @now = Time.local(2008,6,28,13,34,33)
708
+ @now_iso = "2008-06-28 13:34:33"
709
+ @now_nls = "28.06.2008 13:34:33"
710
+ @nls_time_format = "%d.%m.%Y %H:%M:%S"
711
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
712
+ end
713
+
714
+ it "should assign ISO string to date column" do
715
+ @employee = TestEmployee.create(
716
+ :first_name => "First",
717
+ :last_name => "Last",
718
+ :hire_date => @today_iso
719
+ )
720
+ @employee.reload
721
+ @employee.hire_date.should == @today
722
+ end
723
+
724
+ it "should assign NLS string to date column" do
725
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_date_format = @nls_date_format
726
+ @employee = TestEmployee.create(
727
+ :first_name => "First",
728
+ :last_name => "Last",
729
+ :hire_date => @today_nls
730
+ )
731
+ @employee.reload
732
+ @employee.hire_date.should == @today
733
+ end
734
+
735
+ it "should assign ISO time string to date column" do
736
+ @employee = TestEmployee.create(
737
+ :first_name => "First",
738
+ :last_name => "Last",
739
+ :hire_date => @now_iso
740
+ )
741
+ @employee.reload
742
+ @employee.hire_date.should == @today
743
+ end
744
+
745
+ it "should assign NLS time string to date column" do
746
+ # ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_date_format = @nls_date_format
747
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_time_format = @nls_time_format
748
+ @employee = TestEmployee.create(
749
+ :first_name => "First",
750
+ :last_name => "Last",
751
+ :hire_date => @now_nls
752
+ )
753
+ @employee.reload
754
+ @employee.hire_date.should == @today
755
+ end
756
+
757
+ it "should assign ISO time string to datetime column" do
758
+ @employee = TestEmployee.create(
759
+ :first_name => "First",
760
+ :last_name => "Last",
761
+ :last_login_at => @now_iso
762
+ )
763
+ @employee.reload
764
+ @employee.last_login_at.should == @now
765
+ end
766
+
767
+ it "should assign NLS time string to datetime column" do
768
+ # ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_date_format = @nls_date_format
769
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_time_format = @nls_time_format
770
+ @employee = TestEmployee.create(
771
+ :first_name => "First",
772
+ :last_name => "Last",
773
+ :last_login_at => @now_nls
774
+ )
775
+ @employee.reload
776
+ @employee.last_login_at.should == @now
777
+ end
778
+
779
+ it "should assign ISO date string to datetime column" do
780
+ @employee = TestEmployee.create(
781
+ :first_name => "First",
782
+ :last_name => "Last",
783
+ :last_login_at => @today_iso
784
+ )
785
+ @employee.reload
786
+ @employee.last_login_at.should == @today.to_time
787
+ end
788
+
789
+ it "should assign NLS date string to datetime column" do
790
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_date_format = @nls_date_format
791
+ # ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_time_format = @nls_time_format
792
+ @employee = TestEmployee.create(
793
+ :first_name => "First",
794
+ :last_name => "Last",
795
+ :last_login_at => @today_nls
796
+ )
797
+ @employee.reload
798
+ @employee.last_login_at.should == @today.to_time
799
+ end
800
+
801
+ end
802
+
803
+ describe "OracleEnhancedAdapter handling of CLOB columns" do
804
+ before(:all) do
805
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
806
+ @conn = ActiveRecord::Base.connection
807
+ @conn.execute <<-SQL
808
+ CREATE TABLE test_employees (
809
+ employee_id NUMBER(6,0),
810
+ first_name VARCHAR2(20),
811
+ last_name VARCHAR2(25),
812
+ comments CLOB
813
+ )
814
+ SQL
815
+ @conn.execute <<-SQL
816
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
817
+ INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
818
+ SQL
819
+ class ::TestEmployee < ActiveRecord::Base
820
+ set_primary_key :employee_id
821
+ end
822
+ end
823
+
824
+ after(:all) do
825
+ Object.send(:remove_const, "TestEmployee")
826
+ @conn.execute "DROP TABLE test_employees"
827
+ @conn.execute "DROP SEQUENCE test_employees_seq"
828
+ end
829
+
830
+ before(:each) do
831
+ end
832
+
833
+ it "should create record without CLOB data when attribute is serialized" do
834
+ TestEmployee.serialize :comments
835
+ @employee = TestEmployee.create!(
836
+ :first_name => "First",
837
+ :last_name => "Last"
838
+ )
839
+ @employee.should be_valid
840
+ TestEmployee.serialized_attributes.delete('comments')
841
+ end
842
+
843
+ it "should order by CLOB column" do
844
+ @employee = TestEmployee.create!(
845
+ :first_name => "First",
846
+ :last_name => "Last",
847
+ :comments => "comments"
848
+ )
849
+ TestEmployee.find(:all, :order => "comments ASC").should_not be_empty
850
+ TestEmployee.find(:all, :order => " comments ASC ").should_not be_empty
851
+ TestEmployee.find(:all, :order => "comments").should_not be_empty
852
+ TestEmployee.find(:all, :order => " comments ").should_not be_empty
853
+ TestEmployee.find(:all, :order => :comments).should_not be_empty
854
+ TestEmployee.find(:all, :order => " first_name DESC, last_name ASC ").should_not be_empty
855
+ end
856
+
857
+ it "should accept Symbol value for CLOB column" do
858
+ @employee = TestEmployee.create!(
859
+ :comments => :test_comment
860
+ )
861
+ @employee.should be_valid
862
+ end
863
+
864
+ end
865
+
866
+ describe "OracleEnhancedAdapter handling of BLOB columns" do
867
+ before(:all) do
868
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
869
+ @conn = ActiveRecord::Base.connection
870
+ @conn.execute <<-SQL
871
+ CREATE TABLE test_employees (
872
+ employee_id NUMBER(6,0),
873
+ first_name VARCHAR2(20),
874
+ last_name VARCHAR2(25),
875
+ binary_data BLOB
876
+ )
877
+ SQL
878
+ @conn.execute <<-SQL
879
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
880
+ INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
881
+ SQL
882
+ @binary_data = "\0\1\2\3\4\5\6\7\8\9"*10000
883
+ @binary_data2 = "\1\2\3\4\5\6\7\8\9\0"*10000
884
+ end
885
+
886
+ after(:all) do
887
+ @conn.execute "DROP TABLE test_employees"
888
+ @conn.execute "DROP SEQUENCE test_employees_seq"
889
+ end
890
+
891
+ before(:each) do
892
+ class ::TestEmployee < ActiveRecord::Base
893
+ set_primary_key :employee_id
894
+ end
895
+ end
896
+
897
+ after(:each) do
898
+ Object.send(:remove_const, "TestEmployee")
899
+ end
900
+
901
+ it "should create record with BLOB data" do
902
+ @employee = TestEmployee.create!(
903
+ :first_name => "First",
904
+ :last_name => "Last",
905
+ :binary_data => @binary_data
906
+ )
907
+ @employee.reload
908
+ @employee.binary_data.should == @binary_data
909
+ end
910
+
911
+ it "should update record with BLOB data" do
912
+ @employee = TestEmployee.create!(
913
+ :first_name => "First",
914
+ :last_name => "Last"
915
+ )
916
+ @employee.reload
917
+ @employee.binary_data.should be_nil
918
+ @employee.binary_data = @binary_data
919
+ @employee.save!
920
+ @employee.reload
921
+ @employee.binary_data.should == @binary_data
922
+ end
923
+
924
+ it "should update record that has existing BLOB data with different BLOB data" do
925
+ @employee = TestEmployee.create!(
926
+ :first_name => "First",
927
+ :last_name => "Last",
928
+ :binary_data => @binary_data
929
+ )
930
+ @employee.reload
931
+ @employee.binary_data = @binary_data2
932
+ @employee.save!
933
+ @employee.reload
934
+ @employee.binary_data.should == @binary_data2
935
+ end
936
+
937
+ it "should update record that has existing BLOB data with nil" do
938
+ @employee = TestEmployee.create!(
939
+ :first_name => "First",
940
+ :last_name => "Last",
941
+ :binary_data => @binary_data
942
+ )
943
+ @employee.reload
944
+ @employee.binary_data = nil
945
+ @employee.save!
946
+ @employee.reload
947
+ @employee.binary_data.should be_nil
948
+ end
949
+
950
+ end
951
+