c3-activerecord-oracle_enhanced-adapter 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/History.txt +182 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +32 -0
  4. data/README.rdoc +77 -0
  5. data/Rakefile +49 -0
  6. data/VERSION +1 -0
  7. data/activerecord-oracle_enhanced-adapter.gemspec +79 -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 +1664 -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 +218 -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 +137 -0
@@ -0,0 +1,218 @@
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 "dumping default values" do
37
+ before :each do
38
+ schema_define do
39
+ drop_table "test_defaults"
40
+ end
41
+ @conn.create_table "test_defaults" do |t|
42
+ t.string "regular", :default => "c"
43
+ t.string "special_c", :default => "\n"
44
+ end
45
+ end
46
+
47
+ it "should be able to dump default values using special characters" do
48
+ standard_dump.should =~ /t.string \"special_c\", :default => "\\n"/
49
+ end
50
+ end
51
+ describe "table prefixes and suffixes" do
52
+ after(:each) do
53
+ drop_test_posts_table
54
+ @conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if @conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
55
+ ActiveRecord::Base.table_name_prefix = ''
56
+ ActiveRecord::Base.table_name_suffix = ''
57
+ end
58
+
59
+ it "should remove table prefix in schema dump" do
60
+ ActiveRecord::Base.table_name_prefix = 'xxx_'
61
+ create_test_posts_table
62
+ standard_dump.should =~ /create_table "test_posts".*add_index "test_posts"/m
63
+ end
64
+
65
+ it "should remove table suffix in schema dump" do
66
+ ActiveRecord::Base.table_name_suffix = '_xxx'
67
+ create_test_posts_table
68
+ standard_dump.should =~ /create_table "test_posts".*add_index "test_posts"/m
69
+ end
70
+
71
+ it "should not include schema_migrations table with prefix in schema dump" do
72
+ ActiveRecord::Base.table_name_prefix = 'xxx_'
73
+ @conn.initialize_schema_migrations_table
74
+ standard_dump.should_not =~ /schema_migrations/
75
+ end
76
+
77
+ it "should not include schema_migrations table with suffix in schema dump" do
78
+ ActiveRecord::Base.table_name_suffix = '_xxx'
79
+ @conn.initialize_schema_migrations_table
80
+ standard_dump.should_not =~ /schema_migrations/
81
+ end
82
+
83
+ end
84
+
85
+ describe "table with non-default primary key" do
86
+ after(:each) do
87
+ drop_test_posts_table
88
+ end
89
+
90
+ it "should include non-default primary key in schema dump" do
91
+ create_test_posts_table(:primary_key => 'post_id')
92
+ standard_dump.should =~ /create_table "test_posts", :primary_key => "post_id"/
93
+ end
94
+
95
+ end
96
+
97
+ describe "table with primary key trigger" do
98
+
99
+ after(:each) do
100
+ drop_test_posts_table
101
+ @conn.clear_prefetch_primary_key
102
+ end
103
+
104
+ it "should include primary key trigger in schema dump" do
105
+ create_test_posts_table(:primary_key_trigger => true)
106
+ standard_dump.should =~ /create_table "test_posts".*add_primary_key_trigger "test_posts"/m
107
+ end
108
+
109
+ it "should include primary key trigger with non-default primary key in schema dump" do
110
+ create_test_posts_table(:primary_key_trigger => true, :primary_key => 'post_id')
111
+ standard_dump.should =~ /create_table "test_posts", :primary_key => "post_id".*add_primary_key_trigger "test_posts", :primary_key => "post_id"/m
112
+ end
113
+
114
+ end
115
+
116
+ describe "foreign key constraints" do
117
+ before(:all) do
118
+ schema_define do
119
+ create_table :test_posts, :force => true do |t|
120
+ t.string :title
121
+ end
122
+ create_table :test_comments, :force => true do |t|
123
+ t.string :body, :limit => 4000
124
+ t.references :test_post
125
+ end
126
+ end
127
+ end
128
+
129
+ after(:each) do
130
+ schema_define do
131
+ remove_foreign_key :test_comments, :test_posts
132
+ end
133
+ end
134
+ after(:all) do
135
+ schema_define do
136
+ drop_table :test_comments rescue nil
137
+ drop_table :test_posts rescue nil
138
+ end
139
+ end
140
+
141
+ it "should include foreign key in schema dump" do
142
+ schema_define do
143
+ add_foreign_key :test_comments, :test_posts
144
+ end
145
+ standard_dump.should =~ /add_foreign_key "test_comments", "test_posts", :name => "test_comments_test_post_id_fk"/
146
+ end
147
+
148
+ it "should include foreign key with delete dependency in schema dump" do
149
+ schema_define do
150
+ add_foreign_key :test_comments, :test_posts, :dependent => :delete
151
+ end
152
+ standard_dump.should =~ /add_foreign_key "test_comments", "test_posts", :name => "test_comments_test_post_id_fk", :dependent => :delete/
153
+ end
154
+
155
+ it "should include foreign key with nullify dependency in schema dump" do
156
+ schema_define do
157
+ add_foreign_key :test_comments, :test_posts, :dependent => :nullify
158
+ end
159
+ standard_dump.should =~ /add_foreign_key "test_comments", "test_posts", :name => "test_comments_test_post_id_fk", :dependent => :nullify/
160
+ end
161
+
162
+ end
163
+
164
+ describe "synonyms" do
165
+ after(:each) do
166
+ schema_define do
167
+ remove_synonym :test_synonym
168
+ end
169
+ end
170
+
171
+ it "should include synonym to other schema table in schema dump" do
172
+ schema_define do
173
+ add_synonym :test_synonym, "schema_name.table_name", :force => true
174
+ end
175
+ standard_dump.should =~ /add_synonym "test_synonym", "schema_name.table_name", :force => true/
176
+ end
177
+
178
+ it "should include synonym to other database table in schema dump" do
179
+ schema_define do
180
+ add_synonym :test_synonym, "table_name@link_name", :force => true
181
+ end
182
+ standard_dump.should =~ /add_synonym "test_synonym", "table_name@link_name", :force => true/
183
+ end
184
+
185
+ end
186
+
187
+ describe "temporary tables" do
188
+ after(:each) do
189
+ drop_test_posts_table
190
+ end
191
+
192
+ it "should include temporary options" do
193
+ create_test_posts_table(:temporary => true)
194
+ standard_dump.should =~ /create_table "test_posts", :temporary => true/
195
+ end
196
+ end
197
+
198
+ describe "indexes" do
199
+ after(:each) do
200
+ drop_test_posts_table
201
+ end
202
+
203
+ it "should not specify default tablespace in add index" do
204
+ create_test_posts_table
205
+ standard_dump.should =~ /add_index \"test_posts\", \[\"title\"\], :name => \"index_test_posts_on_title\"$/
206
+ end
207
+
208
+ it "should not specify default tablespace in add index" do
209
+ tablespace_name = @conn.default_tablespace
210
+ @conn.stub!(:default_tablespace).and_return('dummy')
211
+ create_test_posts_table
212
+ standard_dump.should =~ /add_index \"test_posts\", \[\"title\"\], :name => \"index_test_posts_on_title\", :tablespace => \"#{tablespace_name}\"$/
213
+ end
214
+
215
+ end
216
+
217
+ end
218
+
@@ -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