oracle_enhanced 1.2.5

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 (38) hide show
  1. data/.gitignore +10 -0
  2. data/History.txt +182 -0
  3. data/License.txt +20 -0
  4. data/Manifest.txt +32 -0
  5. data/README.rdoc +77 -0
  6. data/Rakefile +49 -0
  7. data/VERSION +1 -0
  8. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +5 -0
  9. data/lib/active_record/connection_adapters/oracle_enhanced.rake +51 -0
  10. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +1661 -0
  11. data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +121 -0
  12. data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +64 -0
  13. data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +21 -0
  14. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +39 -0
  15. data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +393 -0
  16. data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +389 -0
  17. data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +163 -0
  18. data/lib/active_record/connection_adapters/oracle_enhanced_reserved_words.rb +126 -0
  19. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +168 -0
  20. data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +213 -0
  21. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +224 -0
  22. data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +11 -0
  23. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +1 -0
  24. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +477 -0
  25. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_structure_dumper_spec.rb +267 -0
  26. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +206 -0
  27. data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +40 -0
  28. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +107 -0
  29. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +984 -0
  30. data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +67 -0
  31. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +93 -0
  32. data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +25 -0
  33. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +370 -0
  34. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +203 -0
  35. data/spec/active_record/connection_adapters/oracle_enhanced_schema_spec.rb +784 -0
  36. data/spec/spec.opts +6 -0
  37. data/spec/spec_helper.rb +114 -0
  38. metadata +140 -0
@@ -0,0 +1,203 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe "OracleEnhancedAdapter schema dump" do
4
+ include SchemaSpecHelper
5
+
6
+ before(:all) do
7
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
8
+ @conn = ActiveRecord::Base.connection
9
+ end
10
+
11
+ def standard_dump
12
+ stream = StringIO.new
13
+ ActiveRecord::SchemaDumper.ignore_tables = []
14
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
15
+ stream.string
16
+ end
17
+
18
+ def create_test_posts_table(options = {})
19
+ options.merge! :force => true
20
+ schema_define do
21
+ create_table :test_posts, options do |t|
22
+ t.string :title
23
+ end
24
+ add_index :test_posts, :title
25
+ end
26
+ end
27
+
28
+ def drop_test_posts_table
29
+ schema_define do
30
+ drop_table :test_posts
31
+ end
32
+ rescue
33
+ nil
34
+ end
35
+
36
+ describe "table prefixes and suffixes" do
37
+ after(:each) do
38
+ drop_test_posts_table
39
+ @conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if @conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
40
+ ActiveRecord::Base.table_name_prefix = ''
41
+ ActiveRecord::Base.table_name_suffix = ''
42
+ end
43
+
44
+ it "should remove table prefix in schema dump" do
45
+ ActiveRecord::Base.table_name_prefix = 'xxx_'
46
+ create_test_posts_table
47
+ standard_dump.should =~ /create_table "test_posts".*add_index "test_posts"/m
48
+ end
49
+
50
+ it "should remove table suffix in schema dump" do
51
+ ActiveRecord::Base.table_name_suffix = '_xxx'
52
+ create_test_posts_table
53
+ standard_dump.should =~ /create_table "test_posts".*add_index "test_posts"/m
54
+ end
55
+
56
+ it "should not include schema_migrations table with prefix in schema dump" do
57
+ ActiveRecord::Base.table_name_prefix = 'xxx_'
58
+ @conn.initialize_schema_migrations_table
59
+ standard_dump.should_not =~ /schema_migrations/
60
+ end
61
+
62
+ it "should not include schema_migrations table with suffix in schema dump" do
63
+ ActiveRecord::Base.table_name_suffix = '_xxx'
64
+ @conn.initialize_schema_migrations_table
65
+ standard_dump.should_not =~ /schema_migrations/
66
+ end
67
+
68
+ end
69
+
70
+ describe "table with non-default primary key" do
71
+ after(:each) do
72
+ drop_test_posts_table
73
+ end
74
+
75
+ it "should include non-default primary key in schema dump" do
76
+ create_test_posts_table(:primary_key => 'post_id')
77
+ standard_dump.should =~ /create_table "test_posts", :primary_key => "post_id"/
78
+ end
79
+
80
+ end
81
+
82
+ describe "table with primary key trigger" do
83
+
84
+ after(:each) do
85
+ drop_test_posts_table
86
+ @conn.clear_prefetch_primary_key
87
+ end
88
+
89
+ it "should include primary key trigger in schema dump" do
90
+ create_test_posts_table(:primary_key_trigger => true)
91
+ standard_dump.should =~ /create_table "test_posts".*add_primary_key_trigger "test_posts"/m
92
+ end
93
+
94
+ it "should include primary key trigger with non-default primary key in schema dump" do
95
+ create_test_posts_table(:primary_key_trigger => true, :primary_key => 'post_id')
96
+ standard_dump.should =~ /create_table "test_posts", :primary_key => "post_id".*add_primary_key_trigger "test_posts", :primary_key => "post_id"/m
97
+ end
98
+
99
+ end
100
+
101
+ describe "foreign key constraints" do
102
+ before(:all) do
103
+ schema_define do
104
+ create_table :test_posts, :force => true do |t|
105
+ t.string :title
106
+ end
107
+ create_table :test_comments, :force => true do |t|
108
+ t.string :body, :limit => 4000
109
+ t.references :test_post
110
+ end
111
+ end
112
+ end
113
+
114
+ after(:each) do
115
+ schema_define do
116
+ remove_foreign_key :test_comments, :test_posts
117
+ end
118
+ end
119
+ after(:all) do
120
+ schema_define do
121
+ drop_table :test_comments rescue nil
122
+ drop_table :test_posts rescue nil
123
+ end
124
+ end
125
+
126
+ it "should include foreign key in schema dump" do
127
+ schema_define do
128
+ add_foreign_key :test_comments, :test_posts
129
+ end
130
+ standard_dump.should =~ /add_foreign_key "test_comments", "test_posts", :name => "test_comments_test_post_id_fk"/
131
+ end
132
+
133
+ it "should include foreign key with delete dependency in schema dump" do
134
+ schema_define do
135
+ add_foreign_key :test_comments, :test_posts, :dependent => :delete
136
+ end
137
+ standard_dump.should =~ /add_foreign_key "test_comments", "test_posts", :name => "test_comments_test_post_id_fk", :dependent => :delete/
138
+ end
139
+
140
+ it "should include foreign key with nullify dependency in schema dump" do
141
+ schema_define do
142
+ add_foreign_key :test_comments, :test_posts, :dependent => :nullify
143
+ end
144
+ standard_dump.should =~ /add_foreign_key "test_comments", "test_posts", :name => "test_comments_test_post_id_fk", :dependent => :nullify/
145
+ end
146
+
147
+ end
148
+
149
+ describe "synonyms" do
150
+ after(:each) do
151
+ schema_define do
152
+ remove_synonym :test_synonym
153
+ end
154
+ end
155
+
156
+ it "should include synonym to other schema table in schema dump" do
157
+ schema_define do
158
+ add_synonym :test_synonym, "schema_name.table_name", :force => true
159
+ end
160
+ standard_dump.should =~ /add_synonym "test_synonym", "schema_name.table_name", :force => true/
161
+ end
162
+
163
+ it "should include synonym to other database table in schema dump" do
164
+ schema_define do
165
+ add_synonym :test_synonym, "table_name@link_name", :force => true
166
+ end
167
+ standard_dump.should =~ /add_synonym "test_synonym", "table_name@link_name", :force => true/
168
+ end
169
+
170
+ end
171
+
172
+ describe "temporary tables" do
173
+ after(:each) do
174
+ drop_test_posts_table
175
+ end
176
+
177
+ it "should include temporary options" do
178
+ create_test_posts_table(:temporary => true)
179
+ standard_dump.should =~ /create_table "test_posts", :temporary => true/
180
+ end
181
+ end
182
+
183
+ describe "indexes" do
184
+ after(:each) do
185
+ drop_test_posts_table
186
+ end
187
+
188
+ it "should not specify default tablespace in add index" do
189
+ create_test_posts_table
190
+ standard_dump.should =~ /add_index \"test_posts\", \[\"title\"\], :name => \"index_test_posts_on_title\"$/
191
+ end
192
+
193
+ it "should not specify default tablespace in add index" do
194
+ tablespace_name = @conn.default_tablespace
195
+ @conn.stub!(:default_tablespace).and_return('dummy')
196
+ create_test_posts_table
197
+ standard_dump.should =~ /add_index \"test_posts\", \[\"title\"\], :name => \"index_test_posts_on_title\", :tablespace => \"#{tablespace_name}\"$/
198
+ end
199
+
200
+ end
201
+
202
+ end
203
+
@@ -0,0 +1,784 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe "OracleEnhancedAdapter schema definition" do
4
+ include SchemaSpecHelper
5
+
6
+ before(:all) do
7
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
8
+ @conn = ActiveRecord::Base.connection
9
+ end
10
+
11
+ describe "table and sequence creation with non-default primary key" do
12
+
13
+ before(:all) do
14
+ schema_define do
15
+ create_table :keyboards, :force => true, :id => false do |t|
16
+ t.primary_key :key_number
17
+ t.string :name
18
+ end
19
+ create_table :id_keyboards, :force => true do |t|
20
+ t.string :name
21
+ end
22
+ end
23
+ class ::Keyboard < ActiveRecord::Base
24
+ set_primary_key :key_number
25
+ end
26
+ class ::IdKeyboard < ActiveRecord::Base
27
+ end
28
+ end
29
+
30
+ after(:all) do
31
+ schema_define do
32
+ drop_table :keyboards
33
+ drop_table :id_keyboards
34
+ end
35
+ Object.send(:remove_const, "Keyboard")
36
+ Object.send(:remove_const, "IdKeyboard")
37
+ end
38
+
39
+ it "should create sequence for non-default primary key" do
40
+ ActiveRecord::Base.connection.next_sequence_value(Keyboard.sequence_name).should_not be_nil
41
+ end
42
+
43
+ it "should create sequence for default primary key" do
44
+ ActiveRecord::Base.connection.next_sequence_value(IdKeyboard.sequence_name).should_not be_nil
45
+ end
46
+ end
47
+
48
+ describe "sequence creation parameters" do
49
+
50
+ def create_test_employees_table(sequence_start_value = nil)
51
+ schema_define do
52
+ create_table :test_employees, sequence_start_value ? {:sequence_start_value => sequence_start_value} : {} do |t|
53
+ t.string :first_name
54
+ t.string :last_name
55
+ end
56
+ end
57
+ end
58
+
59
+ def save_default_sequence_start_value
60
+ @saved_sequence_start_value = ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value
61
+ end
62
+
63
+ def restore_default_sequence_start_value
64
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value = @saved_sequence_start_value
65
+ end
66
+
67
+ before(:each) do
68
+ save_default_sequence_start_value
69
+ end
70
+ after(:each) do
71
+ restore_default_sequence_start_value
72
+ schema_define do
73
+ drop_table :test_employees
74
+ end
75
+ Object.send(:remove_const, "TestEmployee")
76
+ end
77
+
78
+ it "should use default sequence start value 10000" do
79
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value.should == 10000
80
+
81
+ create_test_employees_table
82
+ class ::TestEmployee < ActiveRecord::Base; end
83
+
84
+ employee = TestEmployee.create!
85
+ employee.id.should == 10000
86
+ end
87
+
88
+ it "should use specified default sequence start value" do
89
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value = 1
90
+
91
+ create_test_employees_table
92
+ class ::TestEmployee < ActiveRecord::Base; end
93
+
94
+ employee = TestEmployee.create!
95
+ employee.id.should == 1
96
+ end
97
+
98
+ it "should use sequence start value from table definition" do
99
+ create_test_employees_table(10)
100
+ class ::TestEmployee < ActiveRecord::Base; end
101
+
102
+ employee = TestEmployee.create!
103
+ employee.id.should == 10
104
+ end
105
+
106
+ it "should use sequence start value and other options from table definition" do
107
+ create_test_employees_table("100 NOCACHE INCREMENT BY 10")
108
+ class ::TestEmployee < ActiveRecord::Base; end
109
+
110
+ employee = TestEmployee.create!
111
+ employee.id.should == 100
112
+ employee = TestEmployee.create!
113
+ employee.id.should == 110
114
+ end
115
+
116
+ end
117
+
118
+ describe "create table with primary key trigger" do
119
+ def create_table_with_trigger(options = {})
120
+ options.merge! :primary_key_trigger => true, :force => true
121
+ schema_define do
122
+ create_table :test_employees, options do |t|
123
+ t.string :first_name
124
+ t.string :last_name
125
+ end
126
+ end
127
+ end
128
+
129
+ def create_table_and_separately_trigger(options = {})
130
+ options.merge! :force => true
131
+ schema_define do
132
+ create_table :test_employees, options do |t|
133
+ t.string :first_name
134
+ t.string :last_name
135
+ end
136
+ add_primary_key_trigger :test_employees, options
137
+ end
138
+ end
139
+
140
+ after(:all) do
141
+ seq_name = @sequence_name
142
+ schema_define do
143
+ drop_table :test_employees, (seq_name ? {:sequence_name => seq_name} : {})
144
+ end
145
+ Object.send(:remove_const, "TestEmployee")
146
+ @conn.clear_prefetch_primary_key
147
+ end
148
+
149
+ describe "with default primary key" do
150
+ before(:all) do
151
+ create_table_with_trigger
152
+ class ::TestEmployee < ActiveRecord::Base
153
+ end
154
+ end
155
+
156
+ it "should populate primary key using trigger" do
157
+ lambda do
158
+ @conn.execute "INSERT INTO test_employees (first_name) VALUES ('Raimonds')"
159
+ end.should_not raise_error
160
+ end
161
+
162
+ it "should return new key value using connection insert method" do
163
+ insert_id = @conn.insert("INSERT INTO test_employees (first_name) VALUES ('Raimonds')", nil, "id")
164
+ @conn.select_value("SELECT test_employees_seq.currval FROM dual").should == insert_id
165
+ end
166
+
167
+ it "should create new record for model" do
168
+ e = TestEmployee.create!(:first_name => 'Raimonds')
169
+ @conn.select_value("SELECT test_employees_seq.currval FROM dual").should == e.id
170
+ end
171
+ end
172
+
173
+ describe "with separate creation of primary key trigger" do
174
+ before(:all) do
175
+ create_table_and_separately_trigger
176
+ class ::TestEmployee < ActiveRecord::Base
177
+ end
178
+ end
179
+
180
+ it "should populate primary key using trigger" do
181
+ lambda do
182
+ @conn.execute "INSERT INTO test_employees (first_name) VALUES ('Raimonds')"
183
+ end.should_not raise_error
184
+ end
185
+
186
+ it "should return new key value using connection insert method" do
187
+ insert_id = @conn.insert("INSERT INTO test_employees (first_name) VALUES ('Raimonds')", nil, "id")
188
+ @conn.select_value("SELECT test_employees_seq.currval FROM dual").should == insert_id
189
+ end
190
+
191
+ it "should create new record for model" do
192
+ e = TestEmployee.create!(:first_name => 'Raimonds')
193
+ @conn.select_value("SELECT test_employees_seq.currval FROM dual").should == e.id
194
+ end
195
+ end
196
+
197
+ describe "with non-default primary key and non-default sequence name" do
198
+ before(:all) do
199
+ @primary_key = "employee_id"
200
+ @sequence_name = "test_employees_s"
201
+ create_table_with_trigger(:primary_key => @primary_key, :sequence_name => @sequence_name)
202
+ class ::TestEmployee < ActiveRecord::Base
203
+ set_primary_key "employee_id"
204
+ end
205
+ end
206
+
207
+ it "should populate primary key using trigger" do
208
+ lambda do
209
+ @conn.execute "INSERT INTO test_employees (first_name) VALUES ('Raimonds')"
210
+ end.should_not raise_error
211
+ end
212
+
213
+ it "should return new key value using connection insert method" do
214
+ insert_id = @conn.insert("INSERT INTO test_employees (first_name) VALUES ('Raimonds')", nil, @primary_key)
215
+ @conn.select_value("SELECT #{@sequence_name}.currval FROM dual").should == insert_id
216
+ end
217
+
218
+ it "should create new record for model with autogenerated sequence option" do
219
+ e = TestEmployee.create!(:first_name => 'Raimonds')
220
+ @conn.select_value("SELECT #{@sequence_name}.currval FROM dual").should == e.id
221
+ end
222
+ end
223
+
224
+ describe "with non-default sequence name and non-default trigger name" do
225
+ before(:all) do
226
+ @sequence_name = "test_employees_s"
227
+ create_table_with_trigger(:sequence_name => @sequence_name, :trigger_name => "test_employees_t1")
228
+ class ::TestEmployee < ActiveRecord::Base
229
+ set_sequence_name :autogenerated
230
+ end
231
+ end
232
+
233
+ it "should populate primary key using trigger" do
234
+ lambda do
235
+ @conn.execute "INSERT INTO test_employees (first_name) VALUES ('Raimonds')"
236
+ end.should_not raise_error
237
+ end
238
+
239
+ it "should return new key value using connection insert method" do
240
+ insert_id = @conn.insert("INSERT INTO test_employees (first_name) VALUES ('Raimonds')", nil, "id")
241
+ @conn.select_value("SELECT #{@sequence_name}.currval FROM dual").should == insert_id
242
+ end
243
+
244
+ it "should create new record for model with autogenerated sequence option" do
245
+ e = TestEmployee.create!(:first_name => 'Raimonds')
246
+ @conn.select_value("SELECT #{@sequence_name}.currval FROM dual").should == e.id
247
+ end
248
+ end
249
+
250
+ end
251
+
252
+ describe "table and column comments" do
253
+
254
+ def create_test_employees_table(table_comment=nil, column_comments={})
255
+ schema_define do
256
+ create_table :test_employees, :comment => table_comment do |t|
257
+ t.string :first_name, :comment => column_comments[:first_name]
258
+ t.string :last_name, :comment => column_comments[:last_name]
259
+ end
260
+ end
261
+ end
262
+
263
+ after(:each) do
264
+ schema_define do
265
+ drop_table :test_employees
266
+ end
267
+ Object.send(:remove_const, "TestEmployee")
268
+ ActiveRecord::Base.table_name_prefix = nil
269
+ end
270
+
271
+ it "should create table with table comment" do
272
+ table_comment = "Test Employees"
273
+ create_test_employees_table(table_comment)
274
+ class ::TestEmployee < ActiveRecord::Base; end
275
+
276
+ @conn.table_comment("test_employees").should == table_comment
277
+ TestEmployee.table_comment.should == table_comment
278
+ end
279
+
280
+ it "should create table with columns comment" do
281
+ column_comments = {:first_name => "Given Name", :last_name => "Surname"}
282
+ create_test_employees_table(nil, column_comments)
283
+ class ::TestEmployee < ActiveRecord::Base; end
284
+
285
+ [:first_name, :last_name].each do |attr|
286
+ @conn.column_comment("test_employees", attr.to_s).should == column_comments[attr]
287
+ end
288
+ [:first_name, :last_name].each do |attr|
289
+ TestEmployee.columns_hash[attr.to_s].comment.should == column_comments[attr]
290
+ end
291
+ end
292
+
293
+ it "should create table with table and columns comment and custom table name prefix" do
294
+ ActiveRecord::Base.table_name_prefix = "xxx_"
295
+ table_comment = "Test Employees"
296
+ column_comments = {:first_name => "Given Name", :last_name => "Surname"}
297
+ create_test_employees_table(table_comment, column_comments)
298
+ class ::TestEmployee < ActiveRecord::Base; end
299
+
300
+ @conn.table_comment(TestEmployee.table_name).should == table_comment
301
+ TestEmployee.table_comment.should == table_comment
302
+ [:first_name, :last_name].each do |attr|
303
+ @conn.column_comment(TestEmployee.table_name, attr.to_s).should == column_comments[attr]
304
+ end
305
+ [:first_name, :last_name].each do |attr|
306
+ TestEmployee.columns_hash[attr.to_s].comment.should == column_comments[attr]
307
+ end
308
+ end
309
+
310
+ end
311
+
312
+ describe "create triggers" do
313
+
314
+ before(:all) do
315
+ schema_define do
316
+ create_table :test_employees do |t|
317
+ t.string :first_name
318
+ t.string :last_name
319
+ end
320
+ end
321
+ class ::TestEmployee < ActiveRecord::Base; end
322
+ end
323
+
324
+ after(:all) do
325
+ schema_define do
326
+ drop_table :test_employees
327
+ end
328
+ Object.send(:remove_const, "TestEmployee")
329
+ end
330
+
331
+ it "should create table trigger with :new reference" do
332
+ lambda do
333
+ @conn.execute <<-SQL
334
+ CREATE OR REPLACE TRIGGER test_employees_pkt
335
+ BEFORE INSERT ON test_employees FOR EACH ROW
336
+ BEGIN
337
+ IF inserting THEN
338
+ IF :new.id IS NULL THEN
339
+ SELECT test_employees_seq.NEXTVAL INTO :new.id FROM dual;
340
+ END IF;
341
+ END IF;
342
+ END;
343
+ SQL
344
+ end.should_not raise_error
345
+ end
346
+ end
347
+
348
+ describe "add index" do
349
+
350
+ it "should return default index name if it is not larger than 30 characters" do
351
+ @conn.index_name("employees", :column => "first_name").should == "index_employees_on_first_name"
352
+ end
353
+
354
+ it "should return shortened index name by removing 'index', 'on' and 'and' keywords" do
355
+ @conn.index_name("employees", :column => ["first_name", "email"]).should == "i_employees_first_name_email"
356
+ end
357
+
358
+ it "should return shortened index name by shortening table and column names" do
359
+ @conn.index_name("employees", :column => ["first_name", "last_name"]).should == "i_emp_fir_nam_las_nam"
360
+ end
361
+
362
+ it "should raise error if too large index name cannot be shortened" do
363
+ @conn.index_name("test_employees", :column => ["first_name", "middle_name", "last_name"]).should ==
364
+ 'i'+Digest::SHA1.hexdigest("index_test_employees_on_first_name_and_middle_name_and_last_name")[0,29]
365
+ end
366
+
367
+ end
368
+
369
+ describe "ignore options for LOB columns" do
370
+ after(:each) do
371
+ schema_define do
372
+ drop_table :test_posts
373
+ end
374
+ end
375
+
376
+ it "should ignore :limit option for :text column" do
377
+ lambda do
378
+ schema_define do
379
+ create_table :test_posts, :force => true do |t|
380
+ t.text :body, :limit => 10000
381
+ end
382
+ end
383
+ end.should_not raise_error
384
+ end
385
+
386
+ it "should ignore :limit option for :binary column" do
387
+ lambda do
388
+ schema_define do
389
+ create_table :test_posts, :force => true do |t|
390
+ t.binary :picture, :limit => 10000
391
+ end
392
+ end
393
+ end.should_not raise_error
394
+ end
395
+
396
+ end
397
+
398
+ describe "foreign key constraints" do
399
+ before(:each) do
400
+ schema_define do
401
+ create_table :test_posts, :force => true do |t|
402
+ t.string :title
403
+ end
404
+ create_table :test_comments, :force => true do |t|
405
+ t.string :body, :limit => 4000
406
+ t.references :test_post
407
+ t.integer :post_id
408
+ end
409
+ end
410
+ class ::TestPost < ActiveRecord::Base
411
+ has_many :test_comments
412
+ end
413
+ class ::TestComment < ActiveRecord::Base
414
+ belongs_to :test_post
415
+ end
416
+ end
417
+
418
+ after(:each) do
419
+ Object.send(:remove_const, "TestPost")
420
+ Object.send(:remove_const, "TestComment")
421
+ schema_define do
422
+ drop_table :test_comments rescue nil
423
+ drop_table :test_posts rescue nil
424
+ end
425
+ end
426
+
427
+ it "should add foreign key" do
428
+ schema_define do
429
+ add_foreign_key :test_comments, :test_posts
430
+ end
431
+ lambda do
432
+ TestComment.create(:body => "test", :test_post_id => 1)
433
+ end.should raise_error() {|e| e.message.should =~ /ORA-02291.*\.TEST_COMMENTS_TEST_POST_ID_FK/}
434
+ end
435
+
436
+ it "should add foreign key with name" do
437
+ schema_define do
438
+ add_foreign_key :test_comments, :test_posts, :name => "comments_posts_fk"
439
+ end
440
+ lambda do
441
+ TestComment.create(:body => "test", :test_post_id => 1)
442
+ end.should raise_error() {|e| e.message.should =~ /ORA-02291.*\.COMMENTS_POSTS_FK/}
443
+ end
444
+
445
+ it "should add foreign key with long name which is shortened" do
446
+ schema_define do
447
+ add_foreign_key :test_comments, :test_posts, :name => "test_comments_test_post_id_foreign_key"
448
+ end
449
+ lambda do
450
+ TestComment.create(:body => "test", :test_post_id => 1)
451
+ end.should raise_error() {|e| e.message.should =~ /ORA-02291.*\.TES_COM_TES_POS_ID_FOR_KEY/}
452
+ end
453
+
454
+ it "should add foreign key with very long name which is shortened" do
455
+ schema_define do
456
+ add_foreign_key :test_comments, :test_posts, :name => "long_prefix_test_comments_test_post_id_foreign_key"
457
+ end
458
+ lambda do
459
+ TestComment.create(:body => "test", :test_post_id => 1)
460
+ end.should raise_error() {|e| e.message.should =~
461
+ /ORA-02291.*\.C#{Digest::SHA1.hexdigest("long_prefix_test_comments_test_post_id_foreign_key")[0,29].upcase}/}
462
+ end
463
+
464
+ it "should add foreign key with column" do
465
+ schema_define do
466
+ add_foreign_key :test_comments, :test_posts, :column => "post_id"
467
+ end
468
+ lambda do
469
+ TestComment.create(:body => "test", :post_id => 1)
470
+ end.should raise_error() {|e| e.message.should =~ /ORA-02291.*\.TEST_COMMENTS_POST_ID_FK/}
471
+ end
472
+
473
+ it "should add foreign key with delete dependency" do
474
+ schema_define do
475
+ add_foreign_key :test_comments, :test_posts, :dependent => :delete
476
+ end
477
+ p = TestPost.create(:title => "test")
478
+ c = TestComment.create(:body => "test", :test_post => p)
479
+ TestPost.delete(p.id)
480
+ TestComment.find_by_id(c.id).should be_nil
481
+ end
482
+
483
+ it "should add foreign key with nullify dependency" do
484
+ schema_define do
485
+ add_foreign_key :test_comments, :test_posts, :dependent => :nullify
486
+ end
487
+ p = TestPost.create(:title => "test")
488
+ c = TestComment.create(:body => "test", :test_post => p)
489
+ TestPost.delete(p.id)
490
+ TestComment.find_by_id(c.id).test_post_id.should be_nil
491
+ end
492
+
493
+ it "should remove foreign key by table name" do
494
+ schema_define do
495
+ add_foreign_key :test_comments, :test_posts
496
+ remove_foreign_key :test_comments, :test_posts
497
+ end
498
+ lambda do
499
+ TestComment.create(:body => "test", :test_post_id => 1)
500
+ end.should_not raise_error
501
+ end
502
+
503
+ it "should remove foreign key by constraint name" do
504
+ schema_define do
505
+ add_foreign_key :test_comments, :test_posts, :name => "comments_posts_fk"
506
+ remove_foreign_key :test_comments, :name => "comments_posts_fk"
507
+ end
508
+ lambda do
509
+ TestComment.create(:body => "test", :test_post_id => 1)
510
+ end.should_not raise_error
511
+ end
512
+
513
+ it "should remove foreign key by column name" do
514
+ schema_define do
515
+ add_foreign_key :test_comments, :test_posts
516
+ remove_foreign_key :test_comments, :column => "test_post_id"
517
+ end
518
+ lambda do
519
+ TestComment.create(:body => "test", :test_post_id => 1)
520
+ end.should_not raise_error
521
+ end
522
+
523
+ end
524
+
525
+ describe "foreign key in table definition" do
526
+ before(:each) do
527
+ schema_define do
528
+ create_table :test_posts, :force => true do |t|
529
+ t.string :title
530
+ end
531
+ end
532
+ class ::TestPost < ActiveRecord::Base
533
+ has_many :test_comments
534
+ end
535
+ class ::TestComment < ActiveRecord::Base
536
+ belongs_to :test_post
537
+ end
538
+ end
539
+
540
+ after(:each) do
541
+ Object.send(:remove_const, "TestPost")
542
+ Object.send(:remove_const, "TestComment")
543
+ schema_define do
544
+ drop_table :test_comments rescue nil
545
+ drop_table :test_posts rescue nil
546
+ end
547
+ end
548
+
549
+ it "should add foreign key in create_table" do
550
+ schema_define do
551
+ create_table :test_comments, :force => true do |t|
552
+ t.string :body, :limit => 4000
553
+ t.references :test_post
554
+ t.foreign_key :test_posts
555
+ end
556
+ end
557
+ lambda do
558
+ TestComment.create(:body => "test", :test_post_id => 1)
559
+ end.should raise_error() {|e| e.message.should =~ /ORA-02291/}
560
+ end
561
+
562
+ it "should add foreign key in create_table references" do
563
+ schema_define do
564
+ create_table :test_comments, :force => true do |t|
565
+ t.string :body, :limit => 4000
566
+ t.references :test_post, :foreign_key => true
567
+ end
568
+ end
569
+ lambda do
570
+ TestComment.create(:body => "test", :test_post_id => 1)
571
+ end.should raise_error() {|e| e.message.should =~ /ORA-02291/}
572
+ end
573
+
574
+ it "should add foreign key in change_table" do
575
+ return pending("Not in this ActiveRecord version") unless ENV['RAILS_GEM_VERSION'] >= '2.1'
576
+ schema_define do
577
+ create_table :test_comments, :force => true do |t|
578
+ t.string :body, :limit => 4000
579
+ t.references :test_post
580
+ end
581
+ change_table :test_comments do |t|
582
+ t.foreign_key :test_posts
583
+ end
584
+ end
585
+ lambda do
586
+ TestComment.create(:body => "test", :test_post_id => 1)
587
+ end.should raise_error() {|e| e.message.should =~ /ORA-02291/}
588
+ end
589
+
590
+ it "should add foreign key in change_table references" do
591
+ return pending("Not in this ActiveRecord version") unless ENV['RAILS_GEM_VERSION'] >= '2.1'
592
+ schema_define do
593
+ create_table :test_comments, :force => true do |t|
594
+ t.string :body, :limit => 4000
595
+ end
596
+ change_table :test_comments do |t|
597
+ t.references :test_post, :foreign_key => true
598
+ end
599
+ end
600
+ lambda do
601
+ TestComment.create(:body => "test", :test_post_id => 1)
602
+ end.should raise_error() {|e| e.message.should =~ /ORA-02291/}
603
+ end
604
+
605
+ it "should remove foreign key by table name" do
606
+ return pending("Not in this ActiveRecord version") unless ENV['RAILS_GEM_VERSION'] >= '2.1'
607
+ schema_define do
608
+ create_table :test_comments, :force => true do |t|
609
+ t.string :body, :limit => 4000
610
+ t.references :test_post
611
+ end
612
+ change_table :test_comments do |t|
613
+ t.foreign_key :test_posts
614
+ end
615
+ change_table :test_comments do |t|
616
+ t.remove_foreign_key :test_posts
617
+ end
618
+ end
619
+ lambda do
620
+ TestComment.create(:body => "test", :test_post_id => 1)
621
+ end.should_not raise_error
622
+ end
623
+
624
+ end
625
+
626
+ describe "disable referential integrity" do
627
+ before(:each) do
628
+ schema_define do
629
+ create_table :test_posts, :force => true do |t|
630
+ t.string :title
631
+ end
632
+ create_table :test_comments, :force => true do |t|
633
+ t.string :body, :limit => 4000
634
+ t.references :test_post, :foreign_key => true
635
+ end
636
+ end
637
+ end
638
+
639
+ after(:each) do
640
+ schema_define do
641
+ drop_table :test_comments rescue nil
642
+ drop_table :test_posts rescue nil
643
+ end
644
+ end
645
+
646
+ it "should disable all foreign keys" do
647
+ lambda do
648
+ @conn.execute "INSERT INTO test_comments (id, body, test_post_id) VALUES (1, 'test', 1)"
649
+ end.should raise_error
650
+ @conn.disable_referential_integrity do
651
+ lambda do
652
+ @conn.execute "INSERT INTO test_comments (id, body, test_post_id) VALUES (2, 'test', 2)"
653
+ @conn.execute "INSERT INTO test_posts (id, title) VALUES (2, 'test')"
654
+ end.should_not raise_error
655
+ end
656
+ lambda do
657
+ @conn.execute "INSERT INTO test_comments (id, body, test_post_id) VALUES (3, 'test', 3)"
658
+ end.should raise_error
659
+ end
660
+
661
+ end
662
+
663
+ describe "synonyms" do
664
+ before(:all) do
665
+ @db_link = "db_link"
666
+ @username = @db_link_username = CONNECTION_PARAMS[:username]
667
+ @db_link_password = CONNECTION_PARAMS[:password]
668
+ @db_link_database = CONNECTION_PARAMS[:database]
669
+ @conn.execute "DROP DATABASE LINK #{@db_link}" rescue nil
670
+ @conn.execute "CREATE DATABASE LINK #{@db_link} CONNECT TO #{@db_link_username} IDENTIFIED BY #{@db_link_password} USING '#{@db_link_database}'"
671
+ schema_define do
672
+ create_table :test_posts, :force => true do |t|
673
+ t.string :title
674
+ end
675
+ end
676
+ end
677
+
678
+ after(:all) do
679
+ schema_define do
680
+ drop_table :test_posts
681
+ end
682
+ @conn.execute "DROP DATABASE LINK #{@db_link}" rescue nil
683
+ end
684
+
685
+ before(:each) do
686
+ class ::TestPost < ActiveRecord::Base
687
+ set_table_name "synonym_to_posts"
688
+ end
689
+ end
690
+
691
+ after(:each) do
692
+ Object.send(:remove_const, "TestPost")
693
+ schema_define do
694
+ remove_synonym :synonym_to_posts
695
+ remove_synonym :synonym_to_posts_seq
696
+ end
697
+ end
698
+
699
+ it "should create synonym to table and sequence" do
700
+ schema_name = @username
701
+ schema_define do
702
+ add_synonym :synonym_to_posts, "#{schema_name}.test_posts", :force => true
703
+ add_synonym :synonym_to_posts_seq, "#{schema_name}.test_posts_seq", :force => true
704
+ end
705
+ lambda do
706
+ TestPost.create(:title => "test")
707
+ end.should_not raise_error
708
+ end
709
+
710
+ it "should create synonym to table over database link" do
711
+ db_link = @db_link
712
+ schema_define do
713
+ add_synonym :synonym_to_posts, "test_posts@#{db_link}", :force => true
714
+ add_synonym :synonym_to_posts_seq, "test_posts_seq@#{db_link}", :force => true
715
+ end
716
+ lambda do
717
+ TestPost.create(:title => "test")
718
+ end.should_not raise_error
719
+ end
720
+
721
+ end
722
+
723
+ describe "alter columns with column cache" do
724
+ include LoggerSpecHelper
725
+
726
+ before(:all) do
727
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = true
728
+ end
729
+
730
+ after(:all) do
731
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = nil
732
+ end
733
+
734
+ before(:each) do
735
+ schema_define do
736
+ create_table :test_posts, :force => true do |t|
737
+ t.string :title, :null => false
738
+ end
739
+ end
740
+ class ::TestPost < ActiveRecord::Base; end
741
+ TestPost.columns_hash['title'].null.should be_false
742
+ end
743
+
744
+ after(:each) do
745
+ Object.send(:remove_const, "TestPost")
746
+ schema_define { drop_table :test_posts }
747
+ end
748
+
749
+ it "should change column to nullable" do
750
+ schema_define do
751
+ change_column :test_posts, :title, :string, :null => true
752
+ end
753
+ TestPost.reset_column_information
754
+ TestPost.columns_hash['title'].null.should be_true
755
+ end
756
+
757
+ it "should add column" do
758
+ schema_define do
759
+ add_column :test_posts, :body, :string
760
+ end
761
+ TestPost.reset_column_information
762
+ TestPost.columns_hash['body'].should_not be_nil
763
+ end
764
+
765
+ it "should rename column" do
766
+ schema_define do
767
+ rename_column :test_posts, :title, :subject
768
+ end
769
+ TestPost.reset_column_information
770
+ TestPost.columns_hash['subject'].should_not be_nil
771
+ TestPost.columns_hash['title'].should be_nil
772
+ end
773
+
774
+ it "should remove column" do
775
+ schema_define do
776
+ remove_column :test_posts, :title
777
+ end
778
+ TestPost.reset_column_information
779
+ TestPost.columns_hash['title'].should be_nil
780
+ end
781
+
782
+ end
783
+
784
+ end