activerecord-oracle_enhanced-adapter 1.2.1 → 1.2.2
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.
- data/History.txt +34 -0
- data/README.rdoc +10 -5
- data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced.rake +4 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +534 -170
- data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +53 -3
- data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +10 -10
- data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +3 -3
- data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +3 -3
- data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +86 -58
- data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +105 -68
- data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +27 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +164 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +122 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +224 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +2 -2
- data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +1 -1
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +230 -455
- data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +37 -1
- data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +1 -1
- data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +6 -2
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +21 -4
- data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +63 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +1 -1
- data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +1 -3
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +1 -1
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +255 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_spec.rb +720 -0
- data/spec/spec_helper.rb +38 -7
- metadata +13 -15
@@ -0,0 +1,720 @@
|
|
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
|
+
schema_define do
|
576
|
+
create_table :test_comments, :force => true do |t|
|
577
|
+
t.string :body, :limit => 4000
|
578
|
+
t.references :test_post
|
579
|
+
end
|
580
|
+
change_table :test_comments do |t|
|
581
|
+
t.foreign_key :test_posts
|
582
|
+
end
|
583
|
+
end
|
584
|
+
lambda do
|
585
|
+
TestComment.create(:body => "test", :test_post_id => 1)
|
586
|
+
end.should raise_error() {|e| e.message.should =~ /ORA-02291/}
|
587
|
+
end
|
588
|
+
|
589
|
+
it "should add foreign key in change_table references" do
|
590
|
+
schema_define do
|
591
|
+
create_table :test_comments, :force => true do |t|
|
592
|
+
t.string :body, :limit => 4000
|
593
|
+
end
|
594
|
+
change_table :test_comments do |t|
|
595
|
+
t.references :test_post, :foreign_key => true
|
596
|
+
end
|
597
|
+
end
|
598
|
+
lambda do
|
599
|
+
TestComment.create(:body => "test", :test_post_id => 1)
|
600
|
+
end.should raise_error() {|e| e.message.should =~ /ORA-02291/}
|
601
|
+
end
|
602
|
+
|
603
|
+
it "should remove foreign key by table name" do
|
604
|
+
schema_define do
|
605
|
+
create_table :test_comments, :force => true do |t|
|
606
|
+
t.string :body, :limit => 4000
|
607
|
+
t.references :test_post
|
608
|
+
end
|
609
|
+
change_table :test_comments do |t|
|
610
|
+
t.foreign_key :test_posts
|
611
|
+
end
|
612
|
+
change_table :test_comments do |t|
|
613
|
+
t.remove_foreign_key :test_posts
|
614
|
+
end
|
615
|
+
end
|
616
|
+
lambda do
|
617
|
+
TestComment.create(:body => "test", :test_post_id => 1)
|
618
|
+
end.should_not raise_error
|
619
|
+
end
|
620
|
+
|
621
|
+
end
|
622
|
+
|
623
|
+
describe "disable referential integrity" do
|
624
|
+
before(:each) do
|
625
|
+
schema_define do
|
626
|
+
create_table :test_posts, :force => true do |t|
|
627
|
+
t.string :title
|
628
|
+
end
|
629
|
+
create_table :test_comments, :force => true do |t|
|
630
|
+
t.string :body, :limit => 4000
|
631
|
+
t.references :test_post, :foreign_key => true
|
632
|
+
end
|
633
|
+
end
|
634
|
+
end
|
635
|
+
|
636
|
+
after(:each) do
|
637
|
+
schema_define do
|
638
|
+
drop_table :test_comments rescue nil
|
639
|
+
drop_table :test_posts rescue nil
|
640
|
+
end
|
641
|
+
end
|
642
|
+
|
643
|
+
it "should disable all foreign keys" do
|
644
|
+
lambda do
|
645
|
+
@conn.execute "INSERT INTO test_comments (id, body, test_post_id) VALUES (1, 'test', 1)"
|
646
|
+
end.should raise_error
|
647
|
+
@conn.disable_referential_integrity do
|
648
|
+
lambda do
|
649
|
+
@conn.execute "INSERT INTO test_comments (id, body, test_post_id) VALUES (2, 'test', 2)"
|
650
|
+
@conn.execute "INSERT INTO test_posts (id, title) VALUES (2, 'test')"
|
651
|
+
end.should_not raise_error
|
652
|
+
end
|
653
|
+
lambda do
|
654
|
+
@conn.execute "INSERT INTO test_comments (id, body, test_post_id) VALUES (3, 'test', 3)"
|
655
|
+
end.should raise_error
|
656
|
+
end
|
657
|
+
|
658
|
+
end
|
659
|
+
|
660
|
+
describe "synonyms" do
|
661
|
+
before(:all) do
|
662
|
+
@db_link = "db_link"
|
663
|
+
@username = @db_link_username = CONNECTION_PARAMS[:username]
|
664
|
+
@db_link_password = CONNECTION_PARAMS[:password]
|
665
|
+
@db_link_database = CONNECTION_PARAMS[:database]
|
666
|
+
@conn.execute "DROP DATABASE LINK #{@db_link}" rescue nil
|
667
|
+
@conn.execute "CREATE DATABASE LINK #{@db_link} CONNECT TO #{@db_link_username} IDENTIFIED BY #{@db_link_password} USING '#{@db_link_database}'"
|
668
|
+
schema_define do
|
669
|
+
create_table :test_posts, :force => true do |t|
|
670
|
+
t.string :title
|
671
|
+
end
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
675
|
+
after(:all) do
|
676
|
+
schema_define do
|
677
|
+
drop_table :test_posts
|
678
|
+
end
|
679
|
+
@conn.execute "DROP DATABASE LINK #{@db_link}" rescue nil
|
680
|
+
end
|
681
|
+
|
682
|
+
before(:each) do
|
683
|
+
class ::TestPost < ActiveRecord::Base
|
684
|
+
set_table_name "synonym_to_posts"
|
685
|
+
end
|
686
|
+
end
|
687
|
+
|
688
|
+
after(:each) do
|
689
|
+
Object.send(:remove_const, "TestPost")
|
690
|
+
schema_define do
|
691
|
+
remove_synonym :synonym_to_posts
|
692
|
+
remove_synonym :synonym_to_posts_seq
|
693
|
+
end
|
694
|
+
end
|
695
|
+
|
696
|
+
it "should create synonym to table and sequence" do
|
697
|
+
schema_name = @username
|
698
|
+
schema_define do
|
699
|
+
add_synonym :synonym_to_posts, "#{schema_name}.test_posts", :force => true
|
700
|
+
add_synonym :synonym_to_posts_seq, "#{schema_name}.test_posts_seq", :force => true
|
701
|
+
end
|
702
|
+
lambda do
|
703
|
+
TestPost.create(:title => "test")
|
704
|
+
end.should_not raise_error
|
705
|
+
end
|
706
|
+
|
707
|
+
it "should create synonym to table over database link" do
|
708
|
+
db_link = @db_link
|
709
|
+
schema_define do
|
710
|
+
add_synonym :synonym_to_posts, "test_posts@#{db_link}", :force => true
|
711
|
+
add_synonym :synonym_to_posts_seq, "test_posts_seq@#{db_link}", :force => true
|
712
|
+
end
|
713
|
+
lambda do
|
714
|
+
TestPost.create(:title => "test")
|
715
|
+
end.should_not raise_error
|
716
|
+
end
|
717
|
+
|
718
|
+
end
|
719
|
+
|
720
|
+
end
|