activerecord-oracle_enhanced-adapter 8.1.0-java
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.
- checksums.yaml +7 -0
- data/History.md +1971 -0
- data/License.txt +20 -0
- data/README.md +947 -0
- data/VERSION +1 -0
- data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +7 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +24 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +137 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +359 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +47 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +325 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +63 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +71 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +629 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +38 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/lob.rb +57 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +465 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +44 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +195 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +186 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +95 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +99 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +197 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +739 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +394 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +34 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +3 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +886 -0
- data/lib/active_record/type/oracle_enhanced/boolean.rb +19 -0
- data/lib/active_record/type/oracle_enhanced/character_string.rb +36 -0
- data/lib/active_record/type/oracle_enhanced/integer.rb +14 -0
- data/lib/active_record/type/oracle_enhanced/json.rb +10 -0
- data/lib/active_record/type/oracle_enhanced/national_character_string.rb +26 -0
- data/lib/active_record/type/oracle_enhanced/national_character_text.rb +36 -0
- data/lib/active_record/type/oracle_enhanced/raw.rb +25 -0
- data/lib/active_record/type/oracle_enhanced/string.rb +29 -0
- data/lib/active_record/type/oracle_enhanced/text.rb +32 -0
- data/lib/active_record/type/oracle_enhanced/timestampltz.rb +25 -0
- data/lib/active_record/type/oracle_enhanced/timestamptz.rb +25 -0
- data/lib/activerecord-oracle_enhanced-adapter.rb +25 -0
- data/lib/arel/visitors/oracle.rb +216 -0
- data/lib/arel/visitors/oracle12.rb +121 -0
- data/lib/arel/visitors/oracle_common.rb +51 -0
- data/spec/active_record/connection_adapters/emulation/oracle_adapter_spec.rb +24 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/compatibility_spec.rb +40 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/composite_spec.rb +84 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +589 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/context_index_spec.rb +431 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +122 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/dbconsole_spec.rb +63 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/dbms_output_spec.rb +69 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +362 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/quoting_spec.rb +181 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +492 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +1318 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +485 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +815 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +230 -0
- data/spec/active_record/oracle_enhanced/type/binary_spec.rb +119 -0
- data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +206 -0
- data/spec/active_record/oracle_enhanced/type/character_string_spec.rb +67 -0
- data/spec/active_record/oracle_enhanced/type/custom_spec.rb +90 -0
- data/spec/active_record/oracle_enhanced/type/decimal_spec.rb +56 -0
- data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +141 -0
- data/spec/active_record/oracle_enhanced/type/float_spec.rb +48 -0
- data/spec/active_record/oracle_enhanced/type/integer_spec.rb +101 -0
- data/spec/active_record/oracle_enhanced/type/json_spec.rb +56 -0
- data/spec/active_record/oracle_enhanced/type/national_character_string_spec.rb +55 -0
- data/spec/active_record/oracle_enhanced/type/national_character_text_spec.rb +230 -0
- data/spec/active_record/oracle_enhanced/type/raw_spec.rb +137 -0
- data/spec/active_record/oracle_enhanced/type/text_spec.rb +295 -0
- data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +107 -0
- data/spec/spec_config.yaml.template +11 -0
- data/spec/spec_helper.rb +225 -0
- data/spec/support/alter_system_set_open_cursors.sql +1 -0
- data/spec/support/alter_system_user_password.sql +2 -0
- data/spec/support/create_oracle_enhanced_users.sql +31 -0
- metadata +181 -0
|
@@ -0,0 +1,1318 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe "OracleEnhancedAdapter schema definition" do
|
|
4
|
+
include SchemaSpecHelper
|
|
5
|
+
include LoggerSpecHelper
|
|
6
|
+
|
|
7
|
+
before(:all) do
|
|
8
|
+
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
|
9
|
+
@oracle11g_or_higher = !! !! ActiveRecord::Base.connection.select_value(
|
|
10
|
+
"select * from product_component_version where product like 'Oracle%' and to_number(substr(version,1,2)) >= 11")
|
|
11
|
+
@oracle12cr2_or_higher = !! !! ActiveRecord::Base.connection.select_value(
|
|
12
|
+
"select * from product_component_version where product like 'Oracle%' and to_number(substr(version,1,4)) >= 12.2")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe "option to create sequence when adding a column" do
|
|
16
|
+
before do
|
|
17
|
+
@conn = ActiveRecord::Base.connection
|
|
18
|
+
schema_define do
|
|
19
|
+
create_table :keyboards, force: true, id: false do |t|
|
|
20
|
+
t.string :name
|
|
21
|
+
end
|
|
22
|
+
add_column :keyboards, :id, :primary_key
|
|
23
|
+
end
|
|
24
|
+
class ::Keyboard < ActiveRecord::Base; end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "creates a sequence when adding a column with create_sequence = true" do
|
|
28
|
+
_, sequence_name = ActiveRecord::Base.connection.pk_and_sequence_for(:keyboards)
|
|
29
|
+
|
|
30
|
+
expect(sequence_name).to eq(Keyboard.sequence_name)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe "table and sequence creation with non-default primary key" do
|
|
35
|
+
before(:all) do
|
|
36
|
+
@conn = ActiveRecord::Base.connection
|
|
37
|
+
schema_define do
|
|
38
|
+
create_table :keyboards, force: true, id: false do |t|
|
|
39
|
+
t.primary_key :key_number
|
|
40
|
+
t.string :name
|
|
41
|
+
end
|
|
42
|
+
create_table :id_keyboards, force: true do |t|
|
|
43
|
+
t.string :name
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
class ::Keyboard < ActiveRecord::Base
|
|
47
|
+
self.primary_key = :key_number
|
|
48
|
+
end
|
|
49
|
+
class ::IdKeyboard < ActiveRecord::Base
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
after(:all) do
|
|
54
|
+
schema_define do
|
|
55
|
+
drop_table :keyboards
|
|
56
|
+
drop_table :id_keyboards
|
|
57
|
+
end
|
|
58
|
+
Object.send(:remove_const, "Keyboard")
|
|
59
|
+
Object.send(:remove_const, "IdKeyboard")
|
|
60
|
+
ActiveRecord::Base.clear_cache!
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "should create sequence for non-default primary key" do
|
|
64
|
+
expect(ActiveRecord::Base.connection.next_sequence_value(Keyboard.sequence_name)).not_to be_nil
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "should create sequence for default primary key" do
|
|
68
|
+
expect(ActiveRecord::Base.connection.next_sequence_value(IdKeyboard.sequence_name)).not_to be_nil
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe "primary_key inside create_table block with type and keyword options" do
|
|
73
|
+
before(:all) do
|
|
74
|
+
@conn = ActiveRecord::Base.connection
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
after(:each) do
|
|
78
|
+
schema_define do
|
|
79
|
+
drop_table :test_lookups, if_exists: true
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "accepts a type argument and keyword options without raising ArgumentError" do
|
|
84
|
+
expect {
|
|
85
|
+
schema_define do
|
|
86
|
+
create_table :test_lookups, force: true, id: false do |t|
|
|
87
|
+
t.primary_key :zlookupid, :string, limit: 1, null: false
|
|
88
|
+
t.string :name
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
}.not_to raise_error
|
|
92
|
+
|
|
93
|
+
columns = @conn.columns(:test_lookups)
|
|
94
|
+
pk = columns.find { |c| c.name == "zlookupid" }
|
|
95
|
+
expect(pk).not_to be_nil
|
|
96
|
+
expect(pk.sql_type).to match(/VARCHAR2\(1\)/i)
|
|
97
|
+
expect(pk.null).to be(false)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
describe "default sequence name" do
|
|
102
|
+
it "should return sequence name without truncating too much" do
|
|
103
|
+
seq_name_length = ActiveRecord::Base.connection.sequence_name_length
|
|
104
|
+
tname = "#{DATABASE_USER}" + "." + "a" * (seq_name_length - DATABASE_USER.length) + "z" * (DATABASE_USER).length
|
|
105
|
+
expect(ActiveRecord::Base.connection.default_sequence_name(tname)).to match (/z_seq$/)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
describe "sequence creation parameters" do
|
|
110
|
+
def create_test_employees_table(sequence_start_value = nil)
|
|
111
|
+
schema_define do
|
|
112
|
+
options = sequence_start_value ? { sequence_start_value: sequence_start_value } : {}
|
|
113
|
+
create_table :test_employees, **options do |t|
|
|
114
|
+
t.string :first_name
|
|
115
|
+
t.string :last_name
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def save_default_sequence_start_value
|
|
121
|
+
@saved_sequence_start_value = ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def restore_default_sequence_start_value
|
|
125
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value = @saved_sequence_start_value
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
before(:all) do
|
|
129
|
+
@conn = ActiveRecord::Base.connection
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
before(:each) do
|
|
133
|
+
save_default_sequence_start_value
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
after(:each) do
|
|
137
|
+
restore_default_sequence_start_value
|
|
138
|
+
schema_define do
|
|
139
|
+
drop_table :test_employees
|
|
140
|
+
end
|
|
141
|
+
Object.send(:remove_const, "TestEmployee")
|
|
142
|
+
ActiveRecord::Base.clear_cache!
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "should use default sequence start value 1" do
|
|
146
|
+
expect(ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value).to eq(1)
|
|
147
|
+
|
|
148
|
+
create_test_employees_table
|
|
149
|
+
class ::TestEmployee < ActiveRecord::Base; end
|
|
150
|
+
|
|
151
|
+
employee = TestEmployee.create!
|
|
152
|
+
expect(employee.id).to eq(1)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it "should use specified default sequence start value" do
|
|
156
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value = 10000
|
|
157
|
+
|
|
158
|
+
create_test_employees_table
|
|
159
|
+
class ::TestEmployee < ActiveRecord::Base; end
|
|
160
|
+
|
|
161
|
+
employee = TestEmployee.create!
|
|
162
|
+
expect(employee.id).to eq(10000)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it "should use sequence start value from table definition" do
|
|
166
|
+
create_test_employees_table(10)
|
|
167
|
+
class ::TestEmployee < ActiveRecord::Base; end
|
|
168
|
+
|
|
169
|
+
employee = TestEmployee.create!
|
|
170
|
+
expect(employee.id).to eq(10)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
it "should use sequence start value and other options from table definition" do
|
|
174
|
+
create_test_employees_table("100 NOCACHE INCREMENT BY 10")
|
|
175
|
+
class ::TestEmployee < ActiveRecord::Base; end
|
|
176
|
+
|
|
177
|
+
employee = TestEmployee.create!
|
|
178
|
+
expect(employee.id).to eq(100)
|
|
179
|
+
employee = TestEmployee.create!
|
|
180
|
+
expect(employee.id).to eq(110)
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
describe "table and column comments" do
|
|
185
|
+
def create_test_employees_table(table_comment = nil, column_comments = {})
|
|
186
|
+
schema_define do
|
|
187
|
+
create_table :test_employees, comment: table_comment do |t|
|
|
188
|
+
t.string :first_name, comment: column_comments[:first_name]
|
|
189
|
+
t.string :last_name, comment: column_comments[:last_name]
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
before(:all) do
|
|
195
|
+
@conn = ActiveRecord::Base.connection
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
before(:each) do
|
|
199
|
+
@conn.clear_cache!
|
|
200
|
+
set_logger
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
after(:each) do
|
|
204
|
+
clear_logger
|
|
205
|
+
schema_define do
|
|
206
|
+
drop_table :test_employees
|
|
207
|
+
end
|
|
208
|
+
Object.send(:remove_const, "TestEmployee")
|
|
209
|
+
ActiveRecord::Base.table_name_prefix = ""
|
|
210
|
+
ActiveRecord::Base.clear_cache!
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
it "should create table with table comment" do
|
|
214
|
+
table_comment = "Test Employees"
|
|
215
|
+
create_test_employees_table(table_comment)
|
|
216
|
+
class ::TestEmployee < ActiveRecord::Base; end
|
|
217
|
+
expect(@conn.table_comment("test_employees")).to eq(table_comment)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
it "should create table with columns comment" do
|
|
221
|
+
column_comments = { first_name: "Given Name", last_name: "Surname" }
|
|
222
|
+
create_test_employees_table(nil, column_comments)
|
|
223
|
+
class ::TestEmployee < ActiveRecord::Base; end
|
|
224
|
+
|
|
225
|
+
[:first_name, :last_name].each do |attr|
|
|
226
|
+
expect(@conn.column_comment("test_employees", attr.to_s)).to eq(column_comments[attr])
|
|
227
|
+
end
|
|
228
|
+
[:first_name, :last_name].each do |attr|
|
|
229
|
+
expect(TestEmployee.columns_hash[attr.to_s].comment).to eq(column_comments[attr])
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
it "should create table with table and columns comment and custom table name prefix" do
|
|
234
|
+
ActiveRecord::Base.table_name_prefix = "xxx_"
|
|
235
|
+
table_comment = "Test Employees"
|
|
236
|
+
column_comments = { first_name: "Given Name", last_name: "Surname" }
|
|
237
|
+
create_test_employees_table(table_comment, column_comments)
|
|
238
|
+
class ::TestEmployee < ActiveRecord::Base; end
|
|
239
|
+
|
|
240
|
+
expect(@conn.table_comment(TestEmployee.table_name)).to eq(table_comment)
|
|
241
|
+
[:first_name, :last_name].each do |attr|
|
|
242
|
+
expect(@conn.column_comment(TestEmployee.table_name, attr.to_s)).to eq(column_comments[attr])
|
|
243
|
+
end
|
|
244
|
+
[:first_name, :last_name].each do |attr|
|
|
245
|
+
expect(TestEmployee.columns_hash[attr.to_s].comment).to eq(column_comments[attr])
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
it "should query table_comment using bind variables" do
|
|
250
|
+
table_comment = "Test Employees"
|
|
251
|
+
create_test_employees_table(table_comment)
|
|
252
|
+
class ::TestEmployee < ActiveRecord::Base; end
|
|
253
|
+
expect(@conn.table_comment(TestEmployee.table_name)).to eq(table_comment)
|
|
254
|
+
expect(@logger.logged(:debug).last).to match(/:table_name/)
|
|
255
|
+
expect(@logger.logged(:debug).last).to match(/\["table_name", "TEST_EMPLOYEES"\]\]/)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
it "should query column_comment using bind variables" do
|
|
259
|
+
table_comment = "Test Employees"
|
|
260
|
+
column_comment = { first_name: "Given Name" }
|
|
261
|
+
create_test_employees_table(table_comment, column_comment)
|
|
262
|
+
class ::TestEmployee < ActiveRecord::Base; end
|
|
263
|
+
expect(@conn.column_comment(TestEmployee.table_name, :first_name)).to eq(column_comment[:first_name])
|
|
264
|
+
expect(@logger.logged(:debug).last).to match(/:table_name/)
|
|
265
|
+
expect(@logger.logged(:debug).last).to match(/:column_name/)
|
|
266
|
+
expect(@logger.logged(:debug).last).to match(/\["table_name", "TEST_EMPLOYEES"\], \["column_name", "FIRST_NAME"\]\]/)
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
describe "drop tables" do
|
|
271
|
+
before(:each) do
|
|
272
|
+
@conn = ActiveRecord::Base.connection
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
it "should drop table with :if_exists option no raise error" do
|
|
276
|
+
expect do
|
|
277
|
+
@conn.drop_table("nonexistent_table", if_exists: true)
|
|
278
|
+
end.not_to raise_error
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
describe "rename tables and sequences" do
|
|
283
|
+
before(:each) do
|
|
284
|
+
@conn = ActiveRecord::Base.connection
|
|
285
|
+
schema_define do
|
|
286
|
+
create_table :test_employees, force: true do |t|
|
|
287
|
+
t.string :first_name
|
|
288
|
+
t.string :last_name
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
create_table :test_employees_no_pkey, force: true, id: false do |t|
|
|
292
|
+
t.string :first_name
|
|
293
|
+
t.string :last_name
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
after(:each) do
|
|
299
|
+
schema_define do
|
|
300
|
+
drop_table :test_employees_no_primary_key, if_exists: true
|
|
301
|
+
drop_table :test_employees, if_exists: true
|
|
302
|
+
drop_table :new_test_employees, if_exists: true
|
|
303
|
+
drop_table :test_employees_no_pkey, if_exists: true
|
|
304
|
+
drop_table :new_test_employees_no_pkey, if_exists: true
|
|
305
|
+
drop_table :aaaaaaaaaaaaaaaaaaaaaaaaaaa, if_exists: true
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
it "should rename table name with new one" do
|
|
310
|
+
expect do
|
|
311
|
+
@conn.rename_table("test_employees", "new_test_employees")
|
|
312
|
+
end.not_to raise_error
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
it "should raise error when new table name length is too long" do
|
|
316
|
+
expect do
|
|
317
|
+
@conn.rename_table("test_employees", "a" * 31)
|
|
318
|
+
end.to raise_error(ArgumentError)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
it "should not raise error when new sequence name length is too long" do
|
|
322
|
+
expect do
|
|
323
|
+
@conn.rename_table("test_employees", "a" * 27)
|
|
324
|
+
end.not_to raise_error
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
it "should rename table when table has no primary key and sequence" do
|
|
328
|
+
expect do
|
|
329
|
+
@conn.rename_table("test_employees_no_pkey", "new_test_employees_no_pkey")
|
|
330
|
+
end.not_to raise_error
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
describe "add index" do
|
|
335
|
+
before(:all) do
|
|
336
|
+
@conn = ActiveRecord::Base.connection
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
it "should return default index name if it is not larger than 30 characters" do
|
|
340
|
+
expect(@conn.index_name("employees", column: "first_name")).to eq("index_employees_on_first_name")
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
it "should return shortened index name by removing 'index', 'on' and 'and' keywords" do
|
|
344
|
+
if @oracle12cr2_or_higher
|
|
345
|
+
expect(@conn.index_name("employees", column: ["first_name", "email"])).to eq("index_employees_on_first_name_and_email")
|
|
346
|
+
else
|
|
347
|
+
expect(@conn.index_name("employees", column: ["first_name", "email"])).to eq("i_employees_first_name_email")
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
it "should return shortened index name by shortening table and column names" do
|
|
352
|
+
if @oracle12cr2_or_higher
|
|
353
|
+
expect(@conn.index_name("employees", column: ["first_name", "last_name"])).to eq("index_employees_on_first_name_and_last_name")
|
|
354
|
+
else
|
|
355
|
+
expect(@conn.index_name("employees", column: ["first_name", "last_name"])).to eq("i_emp_fir_nam_las_nam")
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
it "should raise error if too large index name cannot be shortened" do
|
|
360
|
+
if @oracle12cr2_or_higher
|
|
361
|
+
expect(@conn.index_name("test_employees", column: ["first_name", "middle_name", "last_name"])).to eq(
|
|
362
|
+
("index_test_employees_on_first_name_and_middle_name_and_last_name"))
|
|
363
|
+
else
|
|
364
|
+
expect(@conn.index_name("test_employees", column: ["first_name", "middle_name", "last_name"])).to eq(
|
|
365
|
+
"i" + OpenSSL::Digest::SHA1.hexdigest("index_test_employees_on_first_name_and_middle_name_and_last_name")[0, 29]
|
|
366
|
+
)
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
describe "rename index" do
|
|
372
|
+
before(:each) do
|
|
373
|
+
@conn = ActiveRecord::Base.connection
|
|
374
|
+
schema_define do
|
|
375
|
+
create_table :test_employees do |t|
|
|
376
|
+
t.string :first_name
|
|
377
|
+
t.string :last_name
|
|
378
|
+
end
|
|
379
|
+
add_index :test_employees, :first_name
|
|
380
|
+
end
|
|
381
|
+
class ::TestEmployee < ActiveRecord::Base; end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
after(:each) do
|
|
385
|
+
schema_define do
|
|
386
|
+
drop_table :test_employees
|
|
387
|
+
end
|
|
388
|
+
Object.send(:remove_const, "TestEmployee")
|
|
389
|
+
ActiveRecord::Base.clear_cache!
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
it "should raise error when current index name and new index name are identical" do
|
|
393
|
+
expect do
|
|
394
|
+
@conn.rename_index("test_employees", "i_test_employees_first_name", "i_test_employees_first_name")
|
|
395
|
+
end.to raise_error(ActiveRecord::StatementInvalid)
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
it "should raise error when new index name length is too long" do
|
|
399
|
+
skip if @oracle12cr2_or_higher
|
|
400
|
+
expect do
|
|
401
|
+
@conn.rename_index("test_employees", "i_test_employees_first_name", "a" * 31)
|
|
402
|
+
end.to raise_error(ArgumentError)
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
it "should raise error when current index name does not exist" do
|
|
406
|
+
expect do
|
|
407
|
+
@conn.rename_index("test_employees", "nonexist_index_name", "new_index_name")
|
|
408
|
+
end.to raise_error(ActiveRecord::StatementInvalid)
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
it "should rename index name with new one" do
|
|
412
|
+
skip if @oracle12cr2_or_higher
|
|
413
|
+
expect do
|
|
414
|
+
@conn.rename_index("test_employees", "i_test_employees_first_name", "new_index_name")
|
|
415
|
+
end.not_to raise_error
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
describe "add timestamps" do
|
|
420
|
+
before(:each) do
|
|
421
|
+
@conn = ActiveRecord::Base.connection
|
|
422
|
+
schema_define do
|
|
423
|
+
create_table :test_employees, force: true
|
|
424
|
+
end
|
|
425
|
+
class ::TestEmployee < ActiveRecord::Base; end
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
after(:each) do
|
|
429
|
+
schema_define do
|
|
430
|
+
drop_table :test_employees, if_exists: true
|
|
431
|
+
end
|
|
432
|
+
Object.send(:remove_const, "TestEmployee")
|
|
433
|
+
ActiveRecord::Base.clear_cache!
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
it "should add created_at and updated_at" do
|
|
437
|
+
expect do
|
|
438
|
+
@conn.add_timestamps("test_employees")
|
|
439
|
+
end.not_to raise_error
|
|
440
|
+
|
|
441
|
+
TestEmployee.reset_column_information
|
|
442
|
+
expect(TestEmployee.columns_hash["created_at"]).not_to be_nil
|
|
443
|
+
expect(TestEmployee.columns_hash["updated_at"]).not_to be_nil
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
describe "ignore options for LOB columns" do
|
|
448
|
+
after(:each) do
|
|
449
|
+
schema_define do
|
|
450
|
+
drop_table :test_posts
|
|
451
|
+
end
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
it "should ignore :limit option for :text column" do
|
|
455
|
+
expect do
|
|
456
|
+
schema_define do
|
|
457
|
+
create_table :test_posts, force: true do |t|
|
|
458
|
+
t.text :body, limit: 10000
|
|
459
|
+
end
|
|
460
|
+
end
|
|
461
|
+
end.not_to raise_error
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
it "should ignore :limit option for :binary column" do
|
|
465
|
+
expect do
|
|
466
|
+
schema_define do
|
|
467
|
+
create_table :test_posts, force: true do |t|
|
|
468
|
+
t.binary :picture, limit: 10000
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
end.not_to raise_error
|
|
472
|
+
end
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
describe "foreign key constraints" do
|
|
476
|
+
let(:table_name_prefix) { "" }
|
|
477
|
+
let(:table_name_suffix) { "" }
|
|
478
|
+
|
|
479
|
+
before(:each) do
|
|
480
|
+
ActiveRecord::Base.table_name_prefix = table_name_prefix
|
|
481
|
+
ActiveRecord::Base.table_name_suffix = table_name_suffix
|
|
482
|
+
schema_define do
|
|
483
|
+
create_table :test_posts, force: true do |t|
|
|
484
|
+
t.string :title
|
|
485
|
+
end
|
|
486
|
+
create_table :test_comments, force: true do |t|
|
|
487
|
+
t.string :body, limit: 4000
|
|
488
|
+
t.references :test_post
|
|
489
|
+
t.integer :post_id
|
|
490
|
+
end
|
|
491
|
+
end
|
|
492
|
+
class ::TestPost < ActiveRecord::Base
|
|
493
|
+
has_many :test_comments
|
|
494
|
+
end
|
|
495
|
+
class ::TestComment < ActiveRecord::Base
|
|
496
|
+
belongs_to :test_post
|
|
497
|
+
end
|
|
498
|
+
set_logger
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
after(:each) do
|
|
502
|
+
Object.send(:remove_const, "TestPost")
|
|
503
|
+
Object.send(:remove_const, "TestComment")
|
|
504
|
+
schema_define do
|
|
505
|
+
drop_table :test_comments, if_exists: true
|
|
506
|
+
drop_table :test_posts, if_exists: true
|
|
507
|
+
end
|
|
508
|
+
ActiveRecord::Base.table_name_prefix = ""
|
|
509
|
+
ActiveRecord::Base.table_name_suffix = ""
|
|
510
|
+
ActiveRecord::Base.clear_cache!
|
|
511
|
+
clear_logger
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
it "should add foreign key" do
|
|
515
|
+
fk_name = "fk_rails_#{OpenSSL::Digest::SHA256.hexdigest("test_comments_test_post_id_fk").first(10)}"
|
|
516
|
+
|
|
517
|
+
schema_define do
|
|
518
|
+
add_foreign_key :test_comments, :test_posts
|
|
519
|
+
end
|
|
520
|
+
expect do
|
|
521
|
+
TestComment.create(body: "test", test_post_id: 1)
|
|
522
|
+
end.to raise_error() { |e| expect(e.message).to match(/ORA-02291.*\.#{fk_name}/i) }
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
it "should add foreign key with name" do
|
|
526
|
+
schema_define do
|
|
527
|
+
add_foreign_key :test_comments, :test_posts, name: "comments_posts_fk"
|
|
528
|
+
end
|
|
529
|
+
expect do
|
|
530
|
+
TestComment.create(body: "test", test_post_id: 1)
|
|
531
|
+
end.to raise_error() { |e| expect(e.message).to match(/ORA-02291.*\.COMMENTS_POSTS_FK/) }
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
it "should add foreign key with column" do
|
|
535
|
+
fk_name = "fk_rails_#{OpenSSL::Digest::SHA256.hexdigest("test_comments_post_id_fk").first(10)}"
|
|
536
|
+
|
|
537
|
+
schema_define do
|
|
538
|
+
add_foreign_key :test_comments, :test_posts, column: "post_id"
|
|
539
|
+
end
|
|
540
|
+
expect do
|
|
541
|
+
TestComment.create(body: "test", post_id: 1)
|
|
542
|
+
end.to raise_error() { |e| expect(e.message).to match(/ORA-02291.*\.#{fk_name}/i) }
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
it "should add foreign key with delete dependency" do
|
|
546
|
+
schema_define do
|
|
547
|
+
add_foreign_key :test_comments, :test_posts, on_delete: :cascade
|
|
548
|
+
end
|
|
549
|
+
p = TestPost.create(title: "test")
|
|
550
|
+
c = TestComment.create(body: "test", test_post: p)
|
|
551
|
+
TestPost.delete(p.id)
|
|
552
|
+
expect(TestComment.find_by_id(c.id)).to be_nil
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
it "should add foreign key with nullify dependency" do
|
|
556
|
+
schema_define do
|
|
557
|
+
add_foreign_key :test_comments, :test_posts, on_delete: :nullify
|
|
558
|
+
end
|
|
559
|
+
p = TestPost.create(title: "test")
|
|
560
|
+
c = TestComment.create(body: "test", test_post: p)
|
|
561
|
+
TestPost.delete(p.id)
|
|
562
|
+
expect(TestComment.find_by_id(c.id).test_post_id).to be_nil
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
it "should remove foreign key by table name" do
|
|
566
|
+
schema_define do
|
|
567
|
+
add_foreign_key :test_comments, :test_posts
|
|
568
|
+
remove_foreign_key :test_comments, :test_posts
|
|
569
|
+
end
|
|
570
|
+
expect do
|
|
571
|
+
TestComment.create(body: "test", test_post_id: 1)
|
|
572
|
+
end.not_to raise_error
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
it "should remove foreign key by constraint name" do
|
|
576
|
+
schema_define do
|
|
577
|
+
add_foreign_key :test_comments, :test_posts, name: "comments_posts_fk"
|
|
578
|
+
remove_foreign_key :test_comments, name: "comments_posts_fk"
|
|
579
|
+
end
|
|
580
|
+
expect do
|
|
581
|
+
TestComment.create(body: "test", test_post_id: 1)
|
|
582
|
+
end.not_to raise_error
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
it "should remove foreign key by column name" do
|
|
586
|
+
schema_define do
|
|
587
|
+
add_foreign_key :test_comments, :test_posts
|
|
588
|
+
remove_foreign_key :test_comments, column: "test_post_id"
|
|
589
|
+
end
|
|
590
|
+
expect do
|
|
591
|
+
TestComment.create(body: "test", test_post_id: 1)
|
|
592
|
+
end.not_to raise_error
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
it "should query foreign_keys using bind variables" do
|
|
596
|
+
schema_define do
|
|
597
|
+
add_foreign_key :test_comments, :test_posts
|
|
598
|
+
end
|
|
599
|
+
ActiveRecord::Base.connection.foreign_keys(:test_comments)
|
|
600
|
+
expect(@logger.logged(:debug).last).to match(/:desc_table_name/)
|
|
601
|
+
expect(@logger.logged(:debug).last).to match(/\["desc_table_name", "TEST_COMMENTS"\]\]/)
|
|
602
|
+
end
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
describe "lob in table definition" do
|
|
606
|
+
before do
|
|
607
|
+
class ::TestPost < ActiveRecord::Base
|
|
608
|
+
end
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
it "should use default tablespace for clobs" do
|
|
612
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = DATABASE_NON_DEFAULT_TABLESPACE
|
|
613
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:nclob] = nil
|
|
614
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:blob] = nil
|
|
615
|
+
schema_define do
|
|
616
|
+
create_table :test_posts, force: true do |t|
|
|
617
|
+
t.text :test_clob
|
|
618
|
+
t.ntext :test_nclob
|
|
619
|
+
t.binary :test_blob
|
|
620
|
+
end
|
|
621
|
+
end
|
|
622
|
+
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_lobs WHERE table_name='TEST_POSTS' and column_name = 'TEST_CLOB'")).to eq(DATABASE_NON_DEFAULT_TABLESPACE)
|
|
623
|
+
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_lobs WHERE table_name='TEST_POSTS' and column_name = 'TEST_NCLOB'")).not_to eq(DATABASE_NON_DEFAULT_TABLESPACE)
|
|
624
|
+
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_lobs WHERE table_name='TEST_POSTS' and column_name = 'TEST_BLOB'")).not_to eq(DATABASE_NON_DEFAULT_TABLESPACE)
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
it "should use default tablespace for nclobs" do
|
|
628
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:nclob] = DATABASE_NON_DEFAULT_TABLESPACE
|
|
629
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = nil
|
|
630
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:blob] = nil
|
|
631
|
+
schema_define do
|
|
632
|
+
create_table :test_posts, force: true do |t|
|
|
633
|
+
t.text :test_clob
|
|
634
|
+
t.ntext :test_nclob
|
|
635
|
+
t.binary :test_blob
|
|
636
|
+
end
|
|
637
|
+
end
|
|
638
|
+
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_lobs WHERE table_name='TEST_POSTS' and column_name = 'TEST_NCLOB'")).to eq(DATABASE_NON_DEFAULT_TABLESPACE)
|
|
639
|
+
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_lobs WHERE table_name='TEST_POSTS' and column_name = 'TEST_CLOB'")).not_to eq(DATABASE_NON_DEFAULT_TABLESPACE)
|
|
640
|
+
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_lobs WHERE table_name='TEST_POSTS' and column_name = 'TEST_BLOB'")).not_to eq(DATABASE_NON_DEFAULT_TABLESPACE)
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
it "should use default tablespace for blobs" do
|
|
644
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:blob] = DATABASE_NON_DEFAULT_TABLESPACE
|
|
645
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = nil
|
|
646
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:nclob] = nil
|
|
647
|
+
schema_define do
|
|
648
|
+
create_table :test_posts, force: true do |t|
|
|
649
|
+
t.text :test_clob
|
|
650
|
+
t.ntext :test_nclob
|
|
651
|
+
t.binary :test_blob
|
|
652
|
+
end
|
|
653
|
+
end
|
|
654
|
+
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_lobs WHERE table_name='TEST_POSTS' and column_name = 'TEST_BLOB'")).to eq(DATABASE_NON_DEFAULT_TABLESPACE)
|
|
655
|
+
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_lobs WHERE table_name='TEST_POSTS' and column_name = 'TEST_CLOB'")).not_to eq(DATABASE_NON_DEFAULT_TABLESPACE)
|
|
656
|
+
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_lobs WHERE table_name='TEST_POSTS' and column_name = 'TEST_NCLOB'")).not_to eq(DATABASE_NON_DEFAULT_TABLESPACE)
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
after do
|
|
660
|
+
Object.send(:remove_const, "TestPost")
|
|
661
|
+
schema_define do
|
|
662
|
+
drop_table :test_posts, if_exists: true
|
|
663
|
+
end
|
|
664
|
+
end
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
describe "primary key in table definition" do
|
|
668
|
+
before do
|
|
669
|
+
@conn = ActiveRecord::Base.connection
|
|
670
|
+
|
|
671
|
+
class ::TestPost < ActiveRecord::Base
|
|
672
|
+
end
|
|
673
|
+
end
|
|
674
|
+
|
|
675
|
+
it "should use default tablespace for primary key" do
|
|
676
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:index] = nil
|
|
677
|
+
schema_define do
|
|
678
|
+
create_table :test_posts, force: true
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
index_name = @conn.select_value(
|
|
682
|
+
"SELECT index_name FROM all_constraints
|
|
683
|
+
WHERE table_name = 'TEST_POSTS'
|
|
684
|
+
AND constraint_type = 'P'
|
|
685
|
+
AND owner = SYS_CONTEXT('userenv', 'current_schema')")
|
|
686
|
+
|
|
687
|
+
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_indexes WHERE index_name = '#{index_name}'")).to eq("USERS")
|
|
688
|
+
end
|
|
689
|
+
|
|
690
|
+
it "should use non default tablespace for primary key" do
|
|
691
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:index] = DATABASE_NON_DEFAULT_TABLESPACE
|
|
692
|
+
schema_define do
|
|
693
|
+
create_table :test_posts, force: true
|
|
694
|
+
end
|
|
695
|
+
|
|
696
|
+
index_name = @conn.select_value(
|
|
697
|
+
"SELECT index_name FROM all_constraints
|
|
698
|
+
WHERE table_name = 'TEST_POSTS'
|
|
699
|
+
AND constraint_type = 'P'
|
|
700
|
+
AND owner = SYS_CONTEXT('userenv', 'current_schema')")
|
|
701
|
+
|
|
702
|
+
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_indexes WHERE index_name = '#{index_name}'")).to eq(DATABASE_NON_DEFAULT_TABLESPACE)
|
|
703
|
+
end
|
|
704
|
+
|
|
705
|
+
after do
|
|
706
|
+
Object.send(:remove_const, "TestPost")
|
|
707
|
+
schema_define do
|
|
708
|
+
drop_table :test_posts, if_exists: true
|
|
709
|
+
end
|
|
710
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:index] = nil
|
|
711
|
+
end
|
|
712
|
+
end
|
|
713
|
+
|
|
714
|
+
describe "foreign key in table definition" do
|
|
715
|
+
before(:each) do
|
|
716
|
+
schema_define do
|
|
717
|
+
create_table :test_posts, force: true do |t|
|
|
718
|
+
t.string :title
|
|
719
|
+
end
|
|
720
|
+
end
|
|
721
|
+
class ::TestPost < ActiveRecord::Base
|
|
722
|
+
has_many :test_comments
|
|
723
|
+
end
|
|
724
|
+
class ::TestComment < ActiveRecord::Base
|
|
725
|
+
belongs_to :test_post
|
|
726
|
+
end
|
|
727
|
+
end
|
|
728
|
+
|
|
729
|
+
after(:each) do
|
|
730
|
+
Object.send(:remove_const, "TestPost")
|
|
731
|
+
Object.send(:remove_const, "TestComment")
|
|
732
|
+
schema_define do
|
|
733
|
+
drop_table :test_comments, if_exists: true
|
|
734
|
+
drop_table :test_posts, if_exists: true
|
|
735
|
+
end
|
|
736
|
+
ActiveRecord::Base.clear_cache!
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
it "should add foreign key in create_table" do
|
|
740
|
+
schema_define do
|
|
741
|
+
create_table :test_comments, force: true do |t|
|
|
742
|
+
t.string :body, limit: 4000
|
|
743
|
+
t.references :test_post
|
|
744
|
+
t.foreign_key :test_posts
|
|
745
|
+
end
|
|
746
|
+
end
|
|
747
|
+
expect do
|
|
748
|
+
TestComment.create(body: "test", test_post_id: 1)
|
|
749
|
+
end.to raise_error() { |e| expect(e.message).to match(/ORA-02291/) }
|
|
750
|
+
end
|
|
751
|
+
|
|
752
|
+
it "should add foreign key in create_table references" do
|
|
753
|
+
schema_define do
|
|
754
|
+
create_table :test_comments, force: true do |t|
|
|
755
|
+
t.string :body, limit: 4000
|
|
756
|
+
t.references :test_post, foreign_key: true
|
|
757
|
+
end
|
|
758
|
+
end
|
|
759
|
+
expect do
|
|
760
|
+
TestComment.create(body: "test", test_post_id: 1)
|
|
761
|
+
end.to raise_error() { |e| expect(e.message).to match(/ORA-02291/) }
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
it "should add foreign key in change_table" do
|
|
765
|
+
schema_define do
|
|
766
|
+
create_table :test_comments, force: true do |t|
|
|
767
|
+
t.string :body, limit: 4000
|
|
768
|
+
t.references :test_post
|
|
769
|
+
end
|
|
770
|
+
change_table :test_comments do |t|
|
|
771
|
+
t.foreign_key :test_posts
|
|
772
|
+
end
|
|
773
|
+
end
|
|
774
|
+
expect do
|
|
775
|
+
TestComment.create(body: "test", test_post_id: 1)
|
|
776
|
+
end.to raise_error() { |e| expect(e.message).to match(/ORA-02291/) }
|
|
777
|
+
end
|
|
778
|
+
|
|
779
|
+
it "should add foreign key in change_table references" do
|
|
780
|
+
schema_define do
|
|
781
|
+
create_table :test_comments, force: true do |t|
|
|
782
|
+
t.string :body, limit: 4000
|
|
783
|
+
end
|
|
784
|
+
change_table :test_comments do |t|
|
|
785
|
+
t.references :test_post, foreign_key: true
|
|
786
|
+
end
|
|
787
|
+
end
|
|
788
|
+
expect do
|
|
789
|
+
TestComment.create(body: "test", test_post_id: 1)
|
|
790
|
+
end.to raise_error() { |e| expect(e.message).to match(/ORA-02291/) }
|
|
791
|
+
end
|
|
792
|
+
end
|
|
793
|
+
|
|
794
|
+
describe "disable referential integrity" do
|
|
795
|
+
before(:all) do
|
|
796
|
+
@conn = ActiveRecord::Base.connection
|
|
797
|
+
end
|
|
798
|
+
|
|
799
|
+
before(:each) do
|
|
800
|
+
schema_define do
|
|
801
|
+
create_table :test_posts, force: true do |t|
|
|
802
|
+
t.string :title
|
|
803
|
+
end
|
|
804
|
+
create_table :test_comments, force: true do |t|
|
|
805
|
+
t.string :body, limit: 4000
|
|
806
|
+
t.references :test_post, foreign_key: true
|
|
807
|
+
end
|
|
808
|
+
create_table "test_Mixed_Comments", force: true do |t|
|
|
809
|
+
t.string :body, limit: 4000
|
|
810
|
+
t.references :test_post, foreign_key: true
|
|
811
|
+
end
|
|
812
|
+
end
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
after(:each) do
|
|
816
|
+
schema_define do
|
|
817
|
+
drop_table "test_Mixed_Comments", if_exists: true
|
|
818
|
+
drop_table :test_comments, if_exists: true
|
|
819
|
+
drop_table :test_posts, if_exists: true
|
|
820
|
+
end
|
|
821
|
+
end
|
|
822
|
+
|
|
823
|
+
it "should disable all foreign keys" do
|
|
824
|
+
expect do
|
|
825
|
+
@conn.execute "INSERT INTO test_comments (id, body, test_post_id) VALUES (1, 'test', 1)"
|
|
826
|
+
end.to raise_error(ActiveRecord::InvalidForeignKey)
|
|
827
|
+
@conn.disable_referential_integrity do
|
|
828
|
+
expect do
|
|
829
|
+
@conn.execute "INSERT INTO \"test_Mixed_Comments\" (id, body, test_post_id) VALUES (2, 'test', 2)"
|
|
830
|
+
@conn.execute "INSERT INTO test_comments (id, body, test_post_id) VALUES (2, 'test', 2)"
|
|
831
|
+
@conn.execute "INSERT INTO test_posts (id, title) VALUES (2, 'test')"
|
|
832
|
+
end.not_to raise_error
|
|
833
|
+
end
|
|
834
|
+
expect do
|
|
835
|
+
@conn.execute "INSERT INTO test_comments (id, body, test_post_id) VALUES (3, 'test', 3)"
|
|
836
|
+
end.to raise_error(ActiveRecord::InvalidForeignKey)
|
|
837
|
+
end
|
|
838
|
+
end
|
|
839
|
+
|
|
840
|
+
describe "synonyms" do
|
|
841
|
+
before(:all) do
|
|
842
|
+
@conn = ActiveRecord::Base.connection
|
|
843
|
+
@username = CONNECTION_PARAMS[:username]
|
|
844
|
+
schema_define do
|
|
845
|
+
create_table :test_posts, force: true do |t|
|
|
846
|
+
t.string :title
|
|
847
|
+
end
|
|
848
|
+
end
|
|
849
|
+
end
|
|
850
|
+
|
|
851
|
+
after(:all) do
|
|
852
|
+
schema_define do
|
|
853
|
+
drop_table :test_posts
|
|
854
|
+
end
|
|
855
|
+
end
|
|
856
|
+
|
|
857
|
+
before(:each) do
|
|
858
|
+
class ::TestPost < ActiveRecord::Base
|
|
859
|
+
self.table_name = "synonym_to_posts"
|
|
860
|
+
end
|
|
861
|
+
end
|
|
862
|
+
|
|
863
|
+
after(:each) do
|
|
864
|
+
Object.send(:remove_const, "TestPost")
|
|
865
|
+
schema_define do
|
|
866
|
+
remove_synonym :synonym_to_posts
|
|
867
|
+
remove_synonym :synonym_to_posts_seq
|
|
868
|
+
end
|
|
869
|
+
ActiveRecord::Base.clear_cache!
|
|
870
|
+
end
|
|
871
|
+
|
|
872
|
+
it "should create synonym to table and sequence" do
|
|
873
|
+
schema_name = @username
|
|
874
|
+
schema_define do
|
|
875
|
+
add_synonym :synonym_to_posts, "#{schema_name}.test_posts", force: true
|
|
876
|
+
add_synonym :synonym_to_posts_seq, "#{schema_name}.test_posts_seq", force: true
|
|
877
|
+
end
|
|
878
|
+
expect do
|
|
879
|
+
TestPost.create(title: "test")
|
|
880
|
+
end.not_to raise_error
|
|
881
|
+
end
|
|
882
|
+
end
|
|
883
|
+
|
|
884
|
+
describe "alter columns with column cache" do
|
|
885
|
+
include LoggerSpecHelper
|
|
886
|
+
|
|
887
|
+
before(:all) do
|
|
888
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:clob)
|
|
889
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:nclob)
|
|
890
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:blob)
|
|
891
|
+
end
|
|
892
|
+
|
|
893
|
+
after(:all) do
|
|
894
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:clob)
|
|
895
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:nclob)
|
|
896
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:blob)
|
|
897
|
+
end
|
|
898
|
+
|
|
899
|
+
before(:each) do
|
|
900
|
+
schema_define do
|
|
901
|
+
create_table :test_posts, force: true do |t|
|
|
902
|
+
t.string :title, null: false
|
|
903
|
+
t.string :content
|
|
904
|
+
end
|
|
905
|
+
end
|
|
906
|
+
class ::TestPost < ActiveRecord::Base; end
|
|
907
|
+
expect(TestPost.columns_hash["title"].null).to be_falsey
|
|
908
|
+
end
|
|
909
|
+
|
|
910
|
+
after(:each) do
|
|
911
|
+
Object.send(:remove_const, "TestPost")
|
|
912
|
+
schema_define { drop_table :test_posts }
|
|
913
|
+
ActiveRecord::Base.clear_cache!
|
|
914
|
+
end
|
|
915
|
+
|
|
916
|
+
it "should change column to nullable" do
|
|
917
|
+
schema_define do
|
|
918
|
+
change_column :test_posts, :title, :string, null: true
|
|
919
|
+
end
|
|
920
|
+
TestPost.reset_column_information
|
|
921
|
+
expect(TestPost.columns_hash["title"].null).to be_truthy
|
|
922
|
+
end
|
|
923
|
+
|
|
924
|
+
it "should add column" do
|
|
925
|
+
schema_define do
|
|
926
|
+
add_column :test_posts, :body, :string
|
|
927
|
+
end
|
|
928
|
+
TestPost.reset_column_information
|
|
929
|
+
expect(TestPost.columns_hash["body"]).not_to be_nil
|
|
930
|
+
end
|
|
931
|
+
|
|
932
|
+
it "should add longer column" do
|
|
933
|
+
skip unless @oracle12cr2_or_higher
|
|
934
|
+
schema_define do
|
|
935
|
+
add_column :test_posts, "a" * 128, :string
|
|
936
|
+
end
|
|
937
|
+
TestPost.reset_column_information
|
|
938
|
+
expect(TestPost.columns_hash["a" * 128]).not_to be_nil
|
|
939
|
+
end
|
|
940
|
+
|
|
941
|
+
it "should add text type lob column with non_default tablespace" do
|
|
942
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = DATABASE_NON_DEFAULT_TABLESPACE
|
|
943
|
+
schema_define do
|
|
944
|
+
add_column :test_posts, :body, :text
|
|
945
|
+
end
|
|
946
|
+
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_lobs WHERE table_name='TEST_POSTS' and column_name = 'BODY'")).to eq(DATABASE_NON_DEFAULT_TABLESPACE)
|
|
947
|
+
end
|
|
948
|
+
|
|
949
|
+
it "should add ntext type lob column with non_default tablespace" do
|
|
950
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:nclob] = DATABASE_NON_DEFAULT_TABLESPACE
|
|
951
|
+
schema_define do
|
|
952
|
+
add_column :test_posts, :body, :ntext
|
|
953
|
+
end
|
|
954
|
+
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_lobs WHERE table_name='TEST_POSTS' and column_name = 'BODY'")).to eq(DATABASE_NON_DEFAULT_TABLESPACE)
|
|
955
|
+
end
|
|
956
|
+
|
|
957
|
+
it "should add blob column with non_default tablespace" do
|
|
958
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:blob] = DATABASE_NON_DEFAULT_TABLESPACE
|
|
959
|
+
schema_define do
|
|
960
|
+
add_column :test_posts, :attachment, :binary
|
|
961
|
+
end
|
|
962
|
+
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_lobs WHERE table_name='TEST_POSTS' and column_name = 'ATTACHMENT'")).to eq(DATABASE_NON_DEFAULT_TABLESPACE)
|
|
963
|
+
end
|
|
964
|
+
|
|
965
|
+
it "should rename column" do
|
|
966
|
+
schema_define do
|
|
967
|
+
rename_column :test_posts, :title, :subject
|
|
968
|
+
end
|
|
969
|
+
TestPost.reset_column_information
|
|
970
|
+
expect(TestPost.columns_hash["subject"]).not_to be_nil
|
|
971
|
+
expect(TestPost.columns_hash["title"]).to be_nil
|
|
972
|
+
end
|
|
973
|
+
|
|
974
|
+
it "should remove column" do
|
|
975
|
+
schema_define do
|
|
976
|
+
remove_column :test_posts, :title
|
|
977
|
+
end
|
|
978
|
+
TestPost.reset_column_information
|
|
979
|
+
expect(TestPost.columns_hash["title"]).to be_nil
|
|
980
|
+
end
|
|
981
|
+
|
|
982
|
+
it "should remove column when using change_table" do
|
|
983
|
+
schema_define do
|
|
984
|
+
change_table :test_posts do |t|
|
|
985
|
+
t.remove :title
|
|
986
|
+
end
|
|
987
|
+
end
|
|
988
|
+
TestPost.reset_column_information
|
|
989
|
+
expect(TestPost.columns_hash["title"]).to be_nil
|
|
990
|
+
end
|
|
991
|
+
|
|
992
|
+
it "should remove multiple columns when using change_table" do
|
|
993
|
+
schema_define do
|
|
994
|
+
change_table :test_posts do |t|
|
|
995
|
+
t.remove :title, :content
|
|
996
|
+
end
|
|
997
|
+
end
|
|
998
|
+
TestPost.reset_column_information
|
|
999
|
+
expect(TestPost.columns_hash["title"]).to be_nil
|
|
1000
|
+
expect(TestPost.columns_hash["content"]).to be_nil
|
|
1001
|
+
end
|
|
1002
|
+
|
|
1003
|
+
it "should ignore type and options parameter and remove column" do
|
|
1004
|
+
schema_define do
|
|
1005
|
+
remove_column :test_posts, :title, :string, {}
|
|
1006
|
+
end
|
|
1007
|
+
TestPost.reset_column_information
|
|
1008
|
+
expect(TestPost.columns_hash["title"]).to be_nil
|
|
1009
|
+
end
|
|
1010
|
+
end
|
|
1011
|
+
|
|
1012
|
+
describe "virtual columns in create_table" do
|
|
1013
|
+
before(:each) do
|
|
1014
|
+
skip "Not supported in this database version" unless @oracle11g_or_higher
|
|
1015
|
+
end
|
|
1016
|
+
|
|
1017
|
+
it "should raise error if column expression is not provided" do
|
|
1018
|
+
expect {
|
|
1019
|
+
schema_define do
|
|
1020
|
+
create_table :test_fractions do |t|
|
|
1021
|
+
t.integer :field1
|
|
1022
|
+
t.virtual :field2
|
|
1023
|
+
end
|
|
1024
|
+
end
|
|
1025
|
+
}.to raise_error(RuntimeError, "No virtual column definition found.")
|
|
1026
|
+
end
|
|
1027
|
+
end
|
|
1028
|
+
|
|
1029
|
+
describe "virtual columns" do
|
|
1030
|
+
before(:each) do
|
|
1031
|
+
skip "Not supported in this database version" unless @oracle11g_or_higher
|
|
1032
|
+
expr = "( numerator/NULLIF(denominator,0) )*100"
|
|
1033
|
+
schema_define do
|
|
1034
|
+
create_table :test_fractions, force: true do |t|
|
|
1035
|
+
t.integer :numerator, default: 0
|
|
1036
|
+
t.integer :denominator, default: 0
|
|
1037
|
+
t.virtual :percent, as: expr
|
|
1038
|
+
end
|
|
1039
|
+
end
|
|
1040
|
+
class ::TestFraction < ActiveRecord::Base
|
|
1041
|
+
self.table_name = "test_fractions"
|
|
1042
|
+
end
|
|
1043
|
+
TestFraction.reset_column_information
|
|
1044
|
+
end
|
|
1045
|
+
|
|
1046
|
+
after(:each) do
|
|
1047
|
+
if @oracle11g_or_higher
|
|
1048
|
+
schema_define do
|
|
1049
|
+
drop_table :test_fractions
|
|
1050
|
+
end
|
|
1051
|
+
end
|
|
1052
|
+
end
|
|
1053
|
+
|
|
1054
|
+
it "should include virtual columns and not try to update them" do
|
|
1055
|
+
tf = TestFraction.columns.detect { |c| c.virtual? }
|
|
1056
|
+
expect(tf).not_to be_nil
|
|
1057
|
+
expect(tf.name).to eq("percent")
|
|
1058
|
+
expect(tf.virtual?).to be true
|
|
1059
|
+
expect do
|
|
1060
|
+
tf = TestFraction.new(numerator: 20, denominator: 100)
|
|
1061
|
+
expect(tf.percent).to be_nil # not whatever is in DATA_DEFAULT column
|
|
1062
|
+
tf.save!
|
|
1063
|
+
tf.reload
|
|
1064
|
+
end.not_to raise_error
|
|
1065
|
+
expect(tf.percent.to_i).to eq(20)
|
|
1066
|
+
end
|
|
1067
|
+
|
|
1068
|
+
it "should add virtual column" do
|
|
1069
|
+
schema_define do
|
|
1070
|
+
add_column :test_fractions, :rem, :virtual, as: "remainder(numerator, NULLIF(denominator,0))"
|
|
1071
|
+
end
|
|
1072
|
+
TestFraction.reset_column_information
|
|
1073
|
+
tf = TestFraction.columns.detect { |c| c.name == "rem" }
|
|
1074
|
+
expect(tf).not_to be_nil
|
|
1075
|
+
expect(tf.virtual?).to be true
|
|
1076
|
+
expect do
|
|
1077
|
+
tf = TestFraction.new(numerator: 7, denominator: 5)
|
|
1078
|
+
expect(tf.rem).to be_nil
|
|
1079
|
+
tf.save!
|
|
1080
|
+
tf.reload
|
|
1081
|
+
end.not_to raise_error
|
|
1082
|
+
expect(tf.rem.to_i).to eq(2)
|
|
1083
|
+
end
|
|
1084
|
+
|
|
1085
|
+
it "should add virtual column with explicit type" do
|
|
1086
|
+
schema_define do
|
|
1087
|
+
add_column :test_fractions, :expression, :virtual, as: "TO_CHAR(numerator) || '/' || TO_CHAR(denominator)", type: :string, limit: 100
|
|
1088
|
+
end
|
|
1089
|
+
TestFraction.reset_column_information
|
|
1090
|
+
tf = TestFraction.columns.detect { |c| c.name == "expression" }
|
|
1091
|
+
expect(tf).not_to be_nil
|
|
1092
|
+
expect(tf.virtual?).to be true
|
|
1093
|
+
expect(tf.type).to be :string
|
|
1094
|
+
expect(tf.limit).to be 100
|
|
1095
|
+
expect do
|
|
1096
|
+
tf = TestFraction.new(numerator: 7, denominator: 5)
|
|
1097
|
+
expect(tf.expression).to be_nil
|
|
1098
|
+
tf.save!
|
|
1099
|
+
tf.reload
|
|
1100
|
+
end.not_to raise_error
|
|
1101
|
+
expect(tf.expression).to eq("7/5")
|
|
1102
|
+
end
|
|
1103
|
+
|
|
1104
|
+
it "should change virtual column definition" do
|
|
1105
|
+
schema_define do
|
|
1106
|
+
change_column :test_fractions, :percent, :virtual,
|
|
1107
|
+
as: "ROUND((numerator/NULLIF(denominator,0))*100, 2)", type: :decimal, precision: 15, scale: 2
|
|
1108
|
+
end
|
|
1109
|
+
TestFraction.reset_column_information
|
|
1110
|
+
tf = TestFraction.columns.detect { |c| c.name == "percent" }
|
|
1111
|
+
expect(tf).not_to be_nil
|
|
1112
|
+
expect(tf.virtual?).to be true
|
|
1113
|
+
expect(tf.type).to be :decimal
|
|
1114
|
+
expect(tf.precision).to be 15
|
|
1115
|
+
expect(tf.scale).to be 2
|
|
1116
|
+
expect do
|
|
1117
|
+
tf = TestFraction.new(numerator: 11, denominator: 17)
|
|
1118
|
+
expect(tf.percent).to be_nil
|
|
1119
|
+
tf.save!
|
|
1120
|
+
tf.reload
|
|
1121
|
+
end.not_to raise_error
|
|
1122
|
+
expect(tf.percent).to eq("64.71".to_d)
|
|
1123
|
+
end
|
|
1124
|
+
|
|
1125
|
+
it "should change virtual column type" do
|
|
1126
|
+
schema_define do
|
|
1127
|
+
change_column :test_fractions, :percent, :virtual, type: :decimal, precision: 12, scale: 5
|
|
1128
|
+
end
|
|
1129
|
+
TestFraction.reset_column_information
|
|
1130
|
+
tf = TestFraction.columns.detect { |c| c.name == "percent" }
|
|
1131
|
+
expect(tf).not_to be_nil
|
|
1132
|
+
expect(tf.virtual?).to be true
|
|
1133
|
+
expect(tf.type).to be :decimal
|
|
1134
|
+
expect(tf.precision).to be 12
|
|
1135
|
+
expect(tf.scale).to be 5
|
|
1136
|
+
expect do
|
|
1137
|
+
tf = TestFraction.new(numerator: 11, denominator: 17)
|
|
1138
|
+
expect(tf.percent).to be_nil
|
|
1139
|
+
tf.save!
|
|
1140
|
+
tf.reload
|
|
1141
|
+
end.not_to raise_error
|
|
1142
|
+
expect(tf.percent).to eq("64.70588".to_d)
|
|
1143
|
+
end
|
|
1144
|
+
end
|
|
1145
|
+
|
|
1146
|
+
describe "materialized views" do
|
|
1147
|
+
before(:all) do
|
|
1148
|
+
@conn = ActiveRecord::Base.connection
|
|
1149
|
+
schema_define do
|
|
1150
|
+
create_table :test_employees, force: true do |t|
|
|
1151
|
+
t.string :first_name
|
|
1152
|
+
t.string :last_name
|
|
1153
|
+
end
|
|
1154
|
+
end
|
|
1155
|
+
@conn.execute("create materialized view sum_test_employees as select first_name, count(*) from test_employees group by first_name")
|
|
1156
|
+
class ::TestEmployee < ActiveRecord::Base; end
|
|
1157
|
+
end
|
|
1158
|
+
|
|
1159
|
+
after(:all) do
|
|
1160
|
+
@conn.execute("drop materialized view sum_test_employees") rescue nil
|
|
1161
|
+
schema_define do
|
|
1162
|
+
drop_table :sum_test_employees, if_exists: true
|
|
1163
|
+
drop_table :test_employees, if_exists: true
|
|
1164
|
+
end
|
|
1165
|
+
end
|
|
1166
|
+
|
|
1167
|
+
it "tables should not return materialized views" do
|
|
1168
|
+
expect(@conn.tables).not_to include("sum_test_employees")
|
|
1169
|
+
end
|
|
1170
|
+
|
|
1171
|
+
it "materialized_views should return materialized views" do
|
|
1172
|
+
expect(@conn.materialized_views).to include("sum_test_employees")
|
|
1173
|
+
end
|
|
1174
|
+
end
|
|
1175
|
+
|
|
1176
|
+
describe "miscellaneous options" do
|
|
1177
|
+
before(:all) do
|
|
1178
|
+
@conn = ActiveRecord::Base.connection
|
|
1179
|
+
end
|
|
1180
|
+
|
|
1181
|
+
before(:each) do
|
|
1182
|
+
@conn.instance_variable_set :@would_execute_sql, @would_execute_sql = +""
|
|
1183
|
+
class << @conn
|
|
1184
|
+
def execute(sql, name = nil); @would_execute_sql << sql << ";\n"; end
|
|
1185
|
+
end
|
|
1186
|
+
end
|
|
1187
|
+
|
|
1188
|
+
after(:each) do
|
|
1189
|
+
class << @conn
|
|
1190
|
+
remove_method :execute
|
|
1191
|
+
end
|
|
1192
|
+
@conn.instance_eval { remove_instance_variable :@would_execute_sql }
|
|
1193
|
+
end
|
|
1194
|
+
|
|
1195
|
+
it "should support the :options option to create_table" do
|
|
1196
|
+
schema_define do
|
|
1197
|
+
create_table :test_posts, options: "NOLOGGING", force: true do |t|
|
|
1198
|
+
t.string :title, null: false
|
|
1199
|
+
end
|
|
1200
|
+
end
|
|
1201
|
+
expect(@would_execute_sql).to match(/CREATE +TABLE .* \(.*\) NOLOGGING/)
|
|
1202
|
+
end
|
|
1203
|
+
|
|
1204
|
+
it "should support the :tablespace option to create_table" do
|
|
1205
|
+
schema_define do
|
|
1206
|
+
create_table :test_posts, tablespace: "bogus", force: true do |t|
|
|
1207
|
+
t.string :title, null: false
|
|
1208
|
+
end
|
|
1209
|
+
end
|
|
1210
|
+
expect(@would_execute_sql).to match(/CREATE +TABLE .* \(.*\) TABLESPACE bogus/)
|
|
1211
|
+
end
|
|
1212
|
+
|
|
1213
|
+
describe "creating a table with a tablespace defaults set" do
|
|
1214
|
+
after(:each) do
|
|
1215
|
+
@conn.drop_table :tablespace_tests, if_exists: true
|
|
1216
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:table)
|
|
1217
|
+
end
|
|
1218
|
+
|
|
1219
|
+
it "should use correct tablespace" do
|
|
1220
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:table] = DATABASE_NON_DEFAULT_TABLESPACE
|
|
1221
|
+
@conn.create_table :tablespace_tests do |t|
|
|
1222
|
+
t.string :foo
|
|
1223
|
+
end
|
|
1224
|
+
expect(@would_execute_sql).to match(/CREATE +TABLE .* \(.*\) TABLESPACE #{DATABASE_NON_DEFAULT_TABLESPACE}/)
|
|
1225
|
+
end
|
|
1226
|
+
end
|
|
1227
|
+
|
|
1228
|
+
describe "creating an index-organized table" do
|
|
1229
|
+
after(:each) do
|
|
1230
|
+
@conn.drop_table :tablespace_tests, if_exists: true
|
|
1231
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:table)
|
|
1232
|
+
end
|
|
1233
|
+
|
|
1234
|
+
it "should use correct tablespace" do
|
|
1235
|
+
@conn.create_table :tablespace_tests, id: false, organization: "INDEX INITRANS 4 COMPRESS 1", tablespace: "bogus" do |t|
|
|
1236
|
+
t.integer :id
|
|
1237
|
+
end
|
|
1238
|
+
expect(@would_execute_sql).to match(/CREATE +TABLE .*\(.*\)\s+ORGANIZATION INDEX INITRANS 4 COMPRESS 1 TABLESPACE bogus/)
|
|
1239
|
+
end
|
|
1240
|
+
end
|
|
1241
|
+
|
|
1242
|
+
it "should support the :options option to add_index" do
|
|
1243
|
+
schema_define do
|
|
1244
|
+
add_index :keyboards, :name, options: "NOLOGGING"
|
|
1245
|
+
end
|
|
1246
|
+
expect(@would_execute_sql).to match(/CREATE +INDEX .* ON .* \(.*\) NOLOGGING/)
|
|
1247
|
+
end
|
|
1248
|
+
|
|
1249
|
+
it "should support the :tablespace option to add_index" do
|
|
1250
|
+
schema_define do
|
|
1251
|
+
add_index :keyboards, :name, tablespace: "bogus"
|
|
1252
|
+
end
|
|
1253
|
+
expect(@would_execute_sql).to match(/CREATE +INDEX .* ON .* \(.*\) TABLESPACE bogus/)
|
|
1254
|
+
end
|
|
1255
|
+
|
|
1256
|
+
it "should use default_tablespaces in add_index" do
|
|
1257
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:index] = DATABASE_NON_DEFAULT_TABLESPACE
|
|
1258
|
+
schema_define do
|
|
1259
|
+
add_index :keyboards, :name
|
|
1260
|
+
end
|
|
1261
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:index)
|
|
1262
|
+
expect(@would_execute_sql).to match(/CREATE +INDEX .* ON .* \(.*\) TABLESPACE #{DATABASE_NON_DEFAULT_TABLESPACE}/)
|
|
1263
|
+
end
|
|
1264
|
+
|
|
1265
|
+
it "should create unique function index but not create unique constraints" do
|
|
1266
|
+
schema_define do
|
|
1267
|
+
add_index :keyboards, "lower(name)", unique: true, name: :index_keyboards_on_lower_name
|
|
1268
|
+
end
|
|
1269
|
+
expect(@would_execute_sql).not_to include("ADD CONSTRAINT")
|
|
1270
|
+
end
|
|
1271
|
+
|
|
1272
|
+
it "should add unique constraint only to the index where it was defined" do
|
|
1273
|
+
schema_define do
|
|
1274
|
+
add_index :keyboards, ["name"], unique: true, name: :this_index
|
|
1275
|
+
end
|
|
1276
|
+
expect(@would_execute_sql.lines.last).to match(/ALTER +TABLE .* ADD CONSTRAINT .* UNIQUE \(.*\) USING INDEX "THIS_INDEX";/)
|
|
1277
|
+
end
|
|
1278
|
+
end
|
|
1279
|
+
|
|
1280
|
+
describe "load schema" do
|
|
1281
|
+
let(:versions) {
|
|
1282
|
+
%w(20160101000000 20160102000000 20160103000000)
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
before do
|
|
1286
|
+
@conn = ActiveRecord::Base.connection
|
|
1287
|
+
ActiveRecord::Base.connection_pool.schema_migration.create_table
|
|
1288
|
+
end
|
|
1289
|
+
|
|
1290
|
+
context "multi insert is supported" do
|
|
1291
|
+
it "should loads the migration schema table from insert versions sql" do
|
|
1292
|
+
skip "Not supported in this database version" unless ActiveRecord::Base.connection.supports_multi_insert?
|
|
1293
|
+
|
|
1294
|
+
expect {
|
|
1295
|
+
@conn.execute @conn.insert_versions_sql(versions)
|
|
1296
|
+
}.not_to raise_error
|
|
1297
|
+
|
|
1298
|
+
expect(@conn.select_value("SELECT COUNT(version) FROM schema_migrations")).to eq versions.count
|
|
1299
|
+
end
|
|
1300
|
+
end
|
|
1301
|
+
|
|
1302
|
+
context "multi insert is NOT supported" do
|
|
1303
|
+
it "should loads the migration schema table from insert versions sql" do
|
|
1304
|
+
skip "Not supported in this database version" if ActiveRecord::Base.connection.supports_multi_insert?
|
|
1305
|
+
|
|
1306
|
+
expect {
|
|
1307
|
+
versions.each { |version| @conn.execute @conn.insert_versions_sql(version) }
|
|
1308
|
+
}.not_to raise_error
|
|
1309
|
+
|
|
1310
|
+
expect(@conn.select_value("SELECT COUNT(version) FROM schema_migrations")).to eq versions.count
|
|
1311
|
+
end
|
|
1312
|
+
end
|
|
1313
|
+
|
|
1314
|
+
after do
|
|
1315
|
+
ActiveRecord::Base.connection_pool.schema_migration.drop_table
|
|
1316
|
+
end
|
|
1317
|
+
end
|
|
1318
|
+
end
|