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,126 @@
1
+ module ActiveRecord #:nodoc:
2
+ module ConnectionAdapters #:nodoc:
3
+ module OracleEnhancedReservedWords #:nodoc:
4
+
5
+ RESERVED_WORDS = {
6
+ "ACCESS" => true,
7
+ "ADD" => true,
8
+ "ALL" => true,
9
+ "ALTER" => true,
10
+ "AND" => true,
11
+ "ANY" => true,
12
+ "AS" => true,
13
+ "ASC" => true,
14
+ "AUDIT" => true,
15
+ "BETWEEN" => true,
16
+ "BY" => true,
17
+ "CHAR" => true,
18
+ "CHECK" => true,
19
+ "CLUSTER" => true,
20
+ "COLUMN" => true,
21
+ "COMMENT" => true,
22
+ "COMPRESS" => true,
23
+ "CONNECT" => true,
24
+ "CREATE" => true,
25
+ "CURRENT" => true,
26
+ "DATE" => true,
27
+ "DECIMAL" => true,
28
+ "DEFAULT" => true,
29
+ "DELETE" => true,
30
+ "DESC" => true,
31
+ "DISTINCT" => true,
32
+ "DROP" => true,
33
+ "ELSE" => true,
34
+ "EXCLUSIVE" => true,
35
+ "EXISTS" => true,
36
+ "FILE" => true,
37
+ "FLOAT" => true,
38
+ "FOR" => true,
39
+ "FROM" => true,
40
+ "GRANT" => true,
41
+ "GROUP" => true,
42
+ "HAVING" => true,
43
+ "IDENTIFIED" => true,
44
+ "IMMEDIATE" => true,
45
+ "IN" => true,
46
+ "INCREMENT" => true,
47
+ "INDEX" => true,
48
+ "INITIAL" => true,
49
+ "INSERT" => true,
50
+ "INTEGER" => true,
51
+ "INTERSECT" => true,
52
+ "INTO" => true,
53
+ "IS" => true,
54
+ "LEVEL" => true,
55
+ "LIKE" => true,
56
+ "LOCK" => true,
57
+ "LONG" => true,
58
+ "MAXEXTENTS" => true,
59
+ "MINUS" => true,
60
+ "MLSLABEL" => true,
61
+ "MODE" => true,
62
+ "MODIFY" => true,
63
+ "NOAUDIT" => true,
64
+ "NOCOMPRESS" => true,
65
+ "NOT" => true,
66
+ "NOWAIT" => true,
67
+ "NULL" => true,
68
+ "NUMBER" => true,
69
+ "OF" => true,
70
+ "OFFLINE" => true,
71
+ "ON" => true,
72
+ "ONLINE" => true,
73
+ "OPTION" => true,
74
+ "OR" => true,
75
+ "ORDER" => true,
76
+ "PCTFREE" => true,
77
+ "PRIOR" => true,
78
+ "PRIVILEGES" => true,
79
+ "PUBLIC" => true,
80
+ "RAW" => true,
81
+ "RENAME" => true,
82
+ "RESOURCE" => true,
83
+ "REVOKE" => true,
84
+ "ROW" => true,
85
+ "ROWID" => true,
86
+ "ROWNUM" => true,
87
+ "ROWS" => true,
88
+ "SELECT" => true,
89
+ "SESSION" => true,
90
+ "SET" => true,
91
+ "SHARE" => true,
92
+ "SIZE" => true,
93
+ "SMALLINT" => true,
94
+ "START" => true,
95
+ "SUCCESSFUL" => true,
96
+ "SYNONYM" => true,
97
+ "SYSDATE" => true,
98
+ "TABLE" => true,
99
+ "THEN" => true,
100
+ "TO" => true,
101
+ "TRIGGER" => true,
102
+ "UID" => true,
103
+ "UNION" => true,
104
+ "UNIQUE" => true,
105
+ "UPDATE" => true,
106
+ "USER" => true,
107
+ "VALIDATE" => true,
108
+ "VALUES" => true,
109
+ "VARCHAR" => true,
110
+ "VARCHAR2" => true,
111
+ "VIEW" => true,
112
+ "WHENEVER" => true,
113
+ "WHERE" => true,
114
+ "WITH" => true
115
+ }
116
+
117
+ def quote_oracle_reserved_words(name)
118
+ RESERVED_WORDS[name.to_s.upcase].nil? ? name : "\"#{name}\""
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
125
+ include ActiveRecord::ConnectionAdapters::OracleEnhancedReservedWords
126
+ end
@@ -0,0 +1,11 @@
1
+ # implementation idea taken from JDBC adapter
2
+ if defined?(Rake.application) && Rake.application && ActiveRecord::Base.configurations[RAILS_ENV]['adapter'] == 'oracle_enhanced'
3
+ oracle_enhanced_rakefile = File.dirname(__FILE__) + "/oracle_enhanced.rake"
4
+ if Rake.application.lookup("environment")
5
+ # rails tasks already defined; load the override tasks now
6
+ load oracle_enhanced_rakefile
7
+ else
8
+ # rails tasks not loaded yet; load as an import
9
+ Rake.application.add_import(oracle_enhanced_rakefile)
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module ActiveRecord #:nodoc:
2
+ module ConnectionAdapters #:nodoc:
3
+ module OracleEnhancedVersion #:nodoc:
4
+ VERSION = '1.2.1'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,59 @@
1
+ # encoding: utf-8
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{activerecord-oracle_enhanced-adapter}
5
+ s.version = "1.2.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Raimonds Simanovskis"]
9
+ s.date = %q{2009-09-04}
10
+ s.description = %q{Oracle enhanced adapter for ActiveRecord}
11
+ s.email = ["raimonds.simanovskis@gmail.com"]
12
+ s.extra_rdoc_files = ["History.txt", "License.txt", "Manifest.txt", "README.rdoc"]
13
+ s.files = ["History.txt", "License.txt", "Manifest.txt", "README.rdoc",
14
+ "lib/active_record/connection_adapters/emulation/oracle_adapter.rb",
15
+ "lib/active_record/connection_adapters/oracle_enhanced.rake",
16
+ "lib/active_record/connection_adapters/oracle_enhanced_adapter.rb",
17
+ "lib/active_record/connection_adapters/oracle_enhanced_connection.rb",
18
+ "lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb",
19
+ "lib/active_record/connection_adapters/oracle_enhanced_cpk.rb",
20
+ "lib/active_record/connection_adapters/oracle_enhanced_dirty.rb",
21
+ "lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb",
22
+ "lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb",
23
+ "lib/active_record/connection_adapters/oracle_enhanced_procedures.rb",
24
+ "lib/active_record/connection_adapters/oracle_enhanced_reserved_words.rb",
25
+ "lib/active_record/connection_adapters/oracle_enhanced_tasks.rb",
26
+ "lib/active_record/connection_adapters/oracle_enhanced_version.rb",
27
+ "oracle-enhanced.gemspec",
28
+ "spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb",
29
+ "spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb",
30
+ "spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb",
31
+ "spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb",
32
+ "spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb",
33
+ "spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb",
34
+ "spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb",
35
+ "spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb",
36
+ "spec/spec.opts",
37
+ "spec/spec_helper.rb"]
38
+ s.has_rdoc = true
39
+ s.homepage = %q{http://oracle-enhanced.rubyforge.org}
40
+ s.post_install_message = %q{}
41
+ s.rdoc_options = ["--main", "README.rdoc"]
42
+ s.require_paths = ["lib"]
43
+ s.rubyforge_project = %q{oracle-enhanced}
44
+ s.rubygems_version = %q{1.3.1}
45
+ s.summary = %q{Oracle enhanced adapter for ActiveRecord}
46
+
47
+ if s.respond_to? :specification_version then
48
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
49
+ s.specification_version = 2
50
+
51
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
52
+ s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
53
+ else
54
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
55
+ end
56
+ else
57
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
58
+ end
59
+ end
@@ -0,0 +1,659 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+ describe "OracleEnhancedAdapter establish connection" do
4
+
5
+ it "should connect to database" do
6
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
7
+ ActiveRecord::Base.connection.should_not be_nil
8
+ ActiveRecord::Base.connection.class.should == ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
9
+ end
10
+
11
+ it "should connect to database as SYSDBA" do
12
+ ActiveRecord::Base.establish_connection(SYS_CONNECTION_PARAMS)
13
+ ActiveRecord::Base.connection.should_not be_nil
14
+ ActiveRecord::Base.connection.class.should == ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
15
+ end
16
+
17
+ it "should be active after connection to database" do
18
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
19
+ ActiveRecord::Base.connection.should be_active
20
+ end
21
+
22
+ it "should not be active after disconnection to database" do
23
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
24
+ ActiveRecord::Base.connection.disconnect!
25
+ ActiveRecord::Base.connection.should_not be_active
26
+ end
27
+
28
+ it "should be active after reconnection to database" do
29
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
30
+ ActiveRecord::Base.connection.reconnect!
31
+ ActiveRecord::Base.connection.should be_active
32
+ end
33
+
34
+ end
35
+
36
+ describe "OracleEnhancedAdapter schema dump" do
37
+
38
+ before(:all) do
39
+ if !defined?(RUBY_ENGINE)
40
+ @old_conn = ActiveRecord::Base.oracle_connection(CONNECTION_PARAMS)
41
+ @old_conn.class.should == ActiveRecord::ConnectionAdapters::OracleAdapter
42
+ elsif RUBY_ENGINE == 'jruby'
43
+ @old_conn = ActiveRecord::Base.jdbc_connection(JDBC_CONNECTION_PARAMS)
44
+ @old_conn.class.should == ActiveRecord::ConnectionAdapters::JdbcAdapter
45
+ end
46
+
47
+ @new_conn = ActiveRecord::Base.oracle_enhanced_connection(CONNECTION_PARAMS)
48
+ @new_conn.class.should == ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
49
+ end
50
+
51
+ after(:all) do
52
+ # Workaround for undefining callback that was defined by JDBC adapter
53
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
54
+ ActiveRecord::Base.class_eval do
55
+ def after_save_with_oracle_lob
56
+ nil
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ unless defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" && RUBY_VERSION =~ /^1\.9/
63
+ it "should return the same tables list as original oracle adapter" do
64
+ @new_conn.tables.sort.should == @old_conn.tables.sort
65
+ end
66
+
67
+ it "should return the same index list as original oracle adapter" do
68
+ @new_conn.indexes('employees').sort_by(&:name).should == @old_conn.indexes('employees').sort_by(&:name)
69
+ end
70
+
71
+ it "should return the same pk_and_sequence_for as original oracle adapter" do
72
+ if @old_conn.respond_to?(:pk_and_sequence_for)
73
+ @new_conn.tables.each do |t|
74
+ @new_conn.pk_and_sequence_for(t).should == @old_conn.pk_and_sequence_for(t)
75
+ end
76
+ end
77
+ end
78
+
79
+ it "should return the same structure dump as original oracle adapter" do
80
+ @new_conn.structure_dump.split(";\n\n").sort.should == @old_conn.structure_dump.split(";\n\n").sort
81
+ end
82
+
83
+ it "should return the same structure drop as original oracle adapter" do
84
+ @new_conn.structure_drop.split(";\n\n").sort.should == @old_conn.structure_drop.split(";\n\n").sort
85
+ end
86
+ end
87
+
88
+ it "should return the character size of nvarchar fields" do
89
+ @new_conn.execute <<-SQL
90
+ CREATE TABLE nvarchartable (
91
+ session_id NVARCHAR2(255) DEFAULT NULL
92
+ )
93
+ SQL
94
+ if /.*session_id nvarchar2\((\d+)\).*/ =~ @new_conn.structure_dump
95
+ "#$1".should == "255"
96
+ end
97
+ @new_conn.execute "DROP TABLE nvarchartable"
98
+ end
99
+ end
100
+
101
+ describe "OracleEnhancedAdapter database stucture dump extentions" do
102
+ before(:all) do
103
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
104
+ @conn = ActiveRecord::Base.connection
105
+ @conn.execute <<-SQL
106
+ CREATE TABLE nvarchartable (
107
+ unq_nvarchar NVARCHAR2(255) DEFAULT NULL
108
+ )
109
+ SQL
110
+ end
111
+
112
+ after(:all) do
113
+ @conn.execute "DROP TABLE nvarchartable"
114
+ end
115
+
116
+ it "should return the character size of nvarchar fields" do
117
+ if /.*unq_nvarchar nvarchar2\((\d+)\).*/ =~ @conn.structure_dump
118
+ "#$1".should == "255"
119
+ end
120
+ end
121
+ end
122
+
123
+ describe "OracleEnhancedAdapter database session store" do
124
+ before(:all) do
125
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
126
+ @conn = ActiveRecord::Base.connection
127
+ @conn.execute <<-SQL
128
+ CREATE TABLE sessions (
129
+ id NUMBER(38,0) NOT NULL,
130
+ session_id VARCHAR2(255) DEFAULT NULL,
131
+ data CLOB DEFAULT NULL,
132
+ created_at DATE DEFAULT NULL,
133
+ updated_at DATE DEFAULT NULL,
134
+ PRIMARY KEY (ID)
135
+ )
136
+ SQL
137
+ @conn.execute <<-SQL
138
+ CREATE SEQUENCE sessions_seq MINVALUE 1 MAXVALUE 999999999999999999999999999
139
+ INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
140
+ SQL
141
+ if ENV['RAILS_GEM_VERSION'] >= '2.3'
142
+ @session_class = ActiveRecord::SessionStore::Session
143
+ else
144
+ @session_class = CGI::Session::ActiveRecordStore::Session
145
+ end
146
+ end
147
+
148
+ after(:all) do
149
+ @conn.execute "DROP TABLE sessions"
150
+ @conn.execute "DROP SEQUENCE sessions_seq"
151
+ end
152
+
153
+ it "should create sessions table" do
154
+ ActiveRecord::Base.connection.tables.grep("sessions").should_not be_empty
155
+ end
156
+
157
+ it "should save session data" do
158
+ @session = @session_class.new :session_id => "111111", :data => "something" #, :updated_at => Time.now
159
+ @session.save!
160
+ @session = @session_class.find_by_session_id("111111")
161
+ @session.data.should == "something"
162
+ end
163
+
164
+ it "should change session data when partial updates enabled" do
165
+ return pending("Not in this ActiveRecord version") unless @session_class.respond_to?(:partial_updates=)
166
+ @session_class.partial_updates = true
167
+ @session = @session_class.new :session_id => "222222", :data => "something" #, :updated_at => Time.now
168
+ @session.save!
169
+ @session = @session_class.find_by_session_id("222222")
170
+ @session.data = "other thing"
171
+ @session.save!
172
+ # second save should call again blob writing callback
173
+ @session.save!
174
+ @session = @session_class.find_by_session_id("222222")
175
+ @session.data.should == "other thing"
176
+ end
177
+
178
+ it "should have one enhanced_write_lobs callback" do
179
+ return pending("Not in this ActiveRecord version") unless @session_class.respond_to?(:after_save_callback_chain)
180
+ @session_class.after_save_callback_chain.select{|cb| cb.method == :enhanced_write_lobs}.should have(1).record
181
+ end
182
+
183
+ it "should not set sessions table session_id column type as integer if emulate_integers_by_column_name is true" do
184
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
185
+ columns = @conn.columns('sessions')
186
+ column = columns.detect{|c| c.name == "session_id"}
187
+ column.type.should == :string
188
+ end
189
+
190
+ end
191
+
192
+ describe "OracleEnhancedAdapter ignore specified table columns" do
193
+ before(:all) do
194
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
195
+ @conn = ActiveRecord::Base.connection
196
+ @conn.execute <<-SQL
197
+ CREATE TABLE test_employees (
198
+ id NUMBER,
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
+ department_id NUMBER(4,0),
209
+ created_at DATE
210
+ )
211
+ SQL
212
+ @conn.execute <<-SQL
213
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
214
+ INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE
215
+ SQL
216
+ end
217
+
218
+ after(:all) do
219
+ @conn.execute "DROP TABLE test_employees"
220
+ @conn.execute "DROP SEQUENCE test_employees_seq"
221
+ end
222
+
223
+ after(:each) do
224
+ Object.send(:remove_const, "TestEmployee")
225
+ end
226
+
227
+ it "should ignore specified table columns" do
228
+ class ::TestEmployee < ActiveRecord::Base
229
+ ignore_table_columns :phone_number, :hire_date
230
+ end
231
+ TestEmployee.connection.columns('test_employees').select{|c| ['phone_number','hire_date'].include?(c.name) }.should be_empty
232
+ end
233
+
234
+ it "should ignore specified table columns specified in several lines" do
235
+ class ::TestEmployee < ActiveRecord::Base
236
+ ignore_table_columns :phone_number
237
+ ignore_table_columns :hire_date
238
+ end
239
+ TestEmployee.connection.columns('test_employees').select{|c| ['phone_number','hire_date'].include?(c.name) }.should be_empty
240
+ end
241
+
242
+ it "should not ignore unspecified table columns" do
243
+ class ::TestEmployee < ActiveRecord::Base
244
+ ignore_table_columns :phone_number, :hire_date
245
+ end
246
+ TestEmployee.connection.columns('test_employees').select{|c| c.name == 'email' }.should_not be_empty
247
+ end
248
+
249
+
250
+ end
251
+
252
+ describe "OracleEnhancedAdapter table and sequence creation with non-default primary key" do
253
+
254
+ before(:all) do
255
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
256
+ ActiveRecord::Schema.define do
257
+ suppress_messages do
258
+ create_table :keyboards, :force => true, :id => false do |t|
259
+ t.primary_key :key_number
260
+ t.string :name
261
+ end
262
+ create_table :id_keyboards, :force => true do |t|
263
+ t.string :name
264
+ end
265
+ end
266
+ end
267
+ class ::Keyboard < ActiveRecord::Base
268
+ set_primary_key :key_number
269
+ end
270
+ class ::IdKeyboard < ActiveRecord::Base
271
+ end
272
+ end
273
+
274
+ after(:all) do
275
+ ActiveRecord::Schema.define do
276
+ suppress_messages do
277
+ drop_table :keyboards
278
+ drop_table :id_keyboards
279
+ end
280
+ end
281
+ Object.send(:remove_const, "Keyboard")
282
+ Object.send(:remove_const, "IdKeyboard")
283
+ end
284
+
285
+ it "should create sequence for non-default primary key" do
286
+ ActiveRecord::Base.connection.next_sequence_value(Keyboard.sequence_name).should_not be_nil
287
+ end
288
+
289
+ it "should create sequence for default primary key" do
290
+ ActiveRecord::Base.connection.next_sequence_value(IdKeyboard.sequence_name).should_not be_nil
291
+ end
292
+ end
293
+
294
+ describe "OracleEnhancedAdapter without composite_primary_keys" do
295
+
296
+ before(:all) do
297
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
298
+ Object.send(:remove_const, 'CompositePrimaryKeys') if defined?(CompositePrimaryKeys)
299
+ class ::Employee < ActiveRecord::Base
300
+ set_primary_key :employee_id
301
+ end
302
+ end
303
+
304
+ it "should tell ActiveRecord that count distinct is supported" do
305
+ ActiveRecord::Base.connection.supports_count_distinct?.should be_true
306
+ end
307
+
308
+ it "should execute correct SQL COUNT DISTINCT statement" do
309
+ lambda { Employee.count(:employee_id, :distinct => true) }.should_not raise_error
310
+ end
311
+
312
+ end
313
+
314
+ describe "OracleEnhancedAdapter sequence creation parameters" do
315
+
316
+ before(:all) do
317
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
318
+ end
319
+
320
+ def create_test_employees_table(sequence_start_value = nil)
321
+ ActiveRecord::Schema.define do
322
+ suppress_messages do
323
+ create_table :test_employees, sequence_start_value ? {:sequence_start_value => sequence_start_value} : {} do |t|
324
+ t.string :first_name
325
+ t.string :last_name
326
+ end
327
+ end
328
+ end
329
+ end
330
+
331
+ def save_default_sequence_start_value
332
+ @saved_sequence_start_value = ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value
333
+ end
334
+
335
+ def restore_default_sequence_start_value
336
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value = @saved_sequence_start_value
337
+ end
338
+
339
+ before(:each) do
340
+ save_default_sequence_start_value
341
+ end
342
+ after(:each) do
343
+ restore_default_sequence_start_value
344
+ ActiveRecord::Schema.define do
345
+ suppress_messages do
346
+ drop_table :test_employees
347
+ end
348
+ end
349
+ Object.send(:remove_const, "TestEmployee")
350
+ end
351
+
352
+ it "should use default sequence start value 10000" do
353
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value.should == 10000
354
+
355
+ create_test_employees_table
356
+ class ::TestEmployee < ActiveRecord::Base; end
357
+
358
+ employee = TestEmployee.create!
359
+ employee.id.should == 10000
360
+ end
361
+
362
+ it "should use specified default sequence start value" do
363
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value = 1
364
+
365
+ create_test_employees_table
366
+ class ::TestEmployee < ActiveRecord::Base; end
367
+
368
+ employee = TestEmployee.create!
369
+ employee.id.should == 1
370
+ end
371
+
372
+ it "should use sequence start value from table definition" do
373
+ create_test_employees_table(10)
374
+ class ::TestEmployee < ActiveRecord::Base; end
375
+
376
+ employee = TestEmployee.create!
377
+ employee.id.should == 10
378
+ end
379
+
380
+ it "should use sequence start value and other options from table definition" do
381
+ create_test_employees_table("100 NOCACHE INCREMENT BY 10")
382
+ class ::TestEmployee < ActiveRecord::Base; end
383
+
384
+ employee = TestEmployee.create!
385
+ employee.id.should == 100
386
+ employee = TestEmployee.create!
387
+ employee.id.should == 110
388
+ end
389
+
390
+ end
391
+
392
+ describe "OracleEnhancedAdapter table and column comments" do
393
+
394
+ before(:all) do
395
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
396
+ @conn = ActiveRecord::Base.connection
397
+ end
398
+
399
+ def create_test_employees_table(table_comment=nil, column_comments={})
400
+ ActiveRecord::Schema.define do
401
+ suppress_messages do
402
+ create_table :test_employees, :comment => table_comment do |t|
403
+ t.string :first_name, :comment => column_comments[:first_name]
404
+ t.string :last_name, :comment => column_comments[:last_name]
405
+ end
406
+ end
407
+ end
408
+ end
409
+
410
+ after(:each) do
411
+ ActiveRecord::Schema.define do
412
+ suppress_messages do
413
+ drop_table :test_employees
414
+ end
415
+ end
416
+ Object.send(:remove_const, "TestEmployee")
417
+ ActiveRecord::Base.table_name_prefix = nil
418
+ end
419
+
420
+ it "should create table with table comment" do
421
+ table_comment = "Test Employees"
422
+ create_test_employees_table(table_comment)
423
+ class ::TestEmployee < ActiveRecord::Base; end
424
+
425
+ @conn.table_comment("test_employees").should == table_comment
426
+ TestEmployee.table_comment.should == table_comment
427
+ end
428
+
429
+ it "should create table with columns comment" do
430
+ column_comments = {:first_name => "Given Name", :last_name => "Surname"}
431
+ create_test_employees_table(nil, column_comments)
432
+ class ::TestEmployee < ActiveRecord::Base; end
433
+
434
+ [:first_name, :last_name].each do |attr|
435
+ @conn.column_comment("test_employees", attr.to_s).should == column_comments[attr]
436
+ end
437
+ [:first_name, :last_name].each do |attr|
438
+ TestEmployee.columns_hash[attr.to_s].comment.should == column_comments[attr]
439
+ end
440
+ end
441
+
442
+ it "should create table with table and columns comment and custom table name prefix" do
443
+ ActiveRecord::Base.table_name_prefix = "xxx_"
444
+ table_comment = "Test Employees"
445
+ column_comments = {:first_name => "Given Name", :last_name => "Surname"}
446
+ create_test_employees_table(table_comment, column_comments)
447
+ class ::TestEmployee < ActiveRecord::Base; end
448
+
449
+ @conn.table_comment(TestEmployee.table_name).should == table_comment
450
+ TestEmployee.table_comment.should == table_comment
451
+ [:first_name, :last_name].each do |attr|
452
+ @conn.column_comment(TestEmployee.table_name, attr.to_s).should == column_comments[attr]
453
+ end
454
+ [:first_name, :last_name].each do |attr|
455
+ TestEmployee.columns_hash[attr.to_s].comment.should == column_comments[attr]
456
+ end
457
+ end
458
+
459
+ end
460
+
461
+ describe "OracleEnhancedAdapter column quoting" do
462
+
463
+ before(:all) do
464
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
465
+ @conn = ActiveRecord::Base.connection
466
+ end
467
+
468
+ def create_test_reserved_words_table
469
+ ActiveRecord::Schema.define do
470
+ suppress_messages do
471
+ create_table :test_reserved_words do |t|
472
+ t.string :varchar2
473
+ t.integer :integer
474
+ end
475
+ end
476
+ end
477
+ end
478
+
479
+ after(:each) do
480
+ ActiveRecord::Schema.define do
481
+ suppress_messages do
482
+ drop_table :test_reserved_words
483
+ end
484
+ end
485
+ Object.send(:remove_const, "TestReservedWord")
486
+ ActiveRecord::Base.table_name_prefix = nil
487
+ end
488
+
489
+ it "should allow creation of a table with oracle reserved words as column names" do
490
+ create_test_reserved_words_table
491
+ class ::TestReservedWord < ActiveRecord::Base; end
492
+
493
+ [:varchar2, :integer].each do |attr|
494
+ TestReservedWord.columns_hash[attr.to_s].name.should == attr.to_s
495
+ end
496
+ end
497
+
498
+ end
499
+
500
+ describe "OracleEnhancedAdapter valid table names" do
501
+ before(:all) do
502
+ @adapter = ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
503
+ end
504
+ it "should be valid with letters and digits" do
505
+ @adapter.valid_table_name?("abc_123").should be_true
506
+ end
507
+
508
+ it "should be valid with schema name" do
509
+ @adapter.valid_table_name?("abc_123.def_456").should be_true
510
+ end
511
+
512
+ it "should be valid with $ in name" do
513
+ @adapter.valid_table_name?("sys.v$session").should be_true
514
+ end
515
+
516
+ it "should not be valid with two dots in name" do
517
+ @adapter.valid_table_name?("abc_123.def_456.ghi_789").should be_false
518
+ end
519
+
520
+ it "should not be valid with invalid characters" do
521
+ @adapter.valid_table_name?("warehouse-things").should be_false
522
+ end
523
+
524
+ end
525
+
526
+ describe "OracleEnhancedAdapter table quoting" do
527
+
528
+ before(:all) do
529
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
530
+ @conn = ActiveRecord::Base.connection
531
+ end
532
+
533
+ def create_warehouse_things_table
534
+ ActiveRecord::Schema.define do
535
+ suppress_messages do
536
+ create_table "warehouse-things" do |t|
537
+ t.string :name
538
+ t.integer :foo
539
+ end
540
+ end
541
+ end
542
+ end
543
+
544
+ def create_camel_case_table
545
+ ActiveRecord::Schema.define do
546
+ suppress_messages do
547
+ create_table "CamelCase" do |t|
548
+ t.string :name
549
+ t.integer :foo
550
+ end
551
+ end
552
+ end
553
+ end
554
+
555
+ after(:each) do
556
+ ActiveRecord::Schema.define do
557
+ suppress_messages do
558
+ drop_table "warehouse-things" rescue nil
559
+ drop_table "CamelCase" rescue nil
560
+ end
561
+ end
562
+ Object.send(:remove_const, "WarehouseThing") rescue nil
563
+ Object.send(:remove_const, "CamelCase") rescue nil
564
+ end
565
+
566
+ it "should allow creation of a table with non alphanumeric characters" do
567
+ create_warehouse_things_table
568
+ class ::WarehouseThing < ActiveRecord::Base
569
+ set_table_name "warehouse-things"
570
+ end
571
+
572
+ wh = WarehouseThing.create!(:name => "Foo", :foo => 2)
573
+ wh.id.should_not be_nil
574
+
575
+ @conn.tables.should include("warehouse-things")
576
+ end
577
+
578
+ it "should allow creation of a table with CamelCase name" do
579
+ create_camel_case_table
580
+ class ::CamelCase < ActiveRecord::Base
581
+ set_table_name "CamelCase"
582
+ end
583
+
584
+ cc = CamelCase.create!(:name => "Foo", :foo => 2)
585
+ cc.id.should_not be_nil
586
+
587
+ @conn.tables.should include("CamelCase")
588
+ end
589
+
590
+ end
591
+
592
+ describe "OracleEnhancedAdapter create triggers" do
593
+
594
+ before(:all) do
595
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
596
+ @conn = ActiveRecord::Base.connection
597
+ ActiveRecord::Schema.define do
598
+ suppress_messages do
599
+ create_table :test_employees do |t|
600
+ t.string :first_name
601
+ t.string :last_name
602
+ end
603
+ end
604
+ end
605
+ class ::TestEmployee < ActiveRecord::Base; end
606
+ end
607
+
608
+ after(:all) do
609
+ ActiveRecord::Schema.define do
610
+ suppress_messages do
611
+ drop_table :test_employees
612
+ end
613
+ end
614
+ Object.send(:remove_const, "TestEmployee")
615
+ end
616
+
617
+ it "should create table trigger with :new reference" do
618
+ lambda do
619
+ @conn.execute <<-SQL
620
+ CREATE OR REPLACE TRIGGER test_employees_pkt
621
+ BEFORE INSERT ON test_employees FOR EACH ROW
622
+ BEGIN
623
+ IF inserting THEN
624
+ IF :new.id IS NULL THEN
625
+ SELECT test_employees_seq.NEXTVAL INTO :new.id FROM dual;
626
+ END IF;
627
+ END IF;
628
+ END;
629
+ SQL
630
+ end.should_not raise_error
631
+ end
632
+ end
633
+
634
+ describe "OracleEnhancedAdapter add index" do
635
+
636
+ before(:all) do
637
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
638
+ @conn = ActiveRecord::Base.connection
639
+ end
640
+
641
+ it "should return default index name if it is not larger than 30 characters" do
642
+ @conn.index_name("employees", :column => "first_name").should == "index_employees_on_first_name"
643
+ end
644
+
645
+ it "should return shortened index name by removing 'index', 'on' and 'and' keywords" do
646
+ @conn.index_name("employees", :column => ["first_name", "email"]).should == "i_employees_first_name_email"
647
+ end
648
+
649
+ it "should return shortened index name by shortening table and column names" do
650
+ @conn.index_name("employees", :column => ["first_name", "last_name"]).should == "i_emp_fir_nam_las_nam"
651
+ end
652
+
653
+ it "should raise error if too large index name cannot be shortened" do
654
+ lambda do
655
+ @conn.index_name("test_employees", :column => ["first_name", "middle_name", "last_name"])
656
+ end.should raise_error(ArgumentError)
657
+ end
658
+
659
+ end