activerecord-oracle_enhanced-adapter 1.8.2 → 5.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +190 -5
  3. data/README.md +10 -10
  4. data/VERSION +1 -1
  5. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +2 -0
  6. data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +9 -71
  7. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +84 -73
  8. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +12 -12
  9. data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +52 -0
  10. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +35 -7
  11. data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +2 -0
  12. data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +59 -0
  13. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +379 -402
  14. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +7 -1
  15. data/lib/active_record/connection_adapters/oracle_enhanced/lob.rb +46 -0
  16. data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +242 -247
  17. data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +9 -1
  18. data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +3 -1
  19. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +25 -9
  20. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +9 -6
  21. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +10 -5
  22. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +48 -51
  23. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +261 -59
  24. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +2 -34
  25. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +267 -222
  26. data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +33 -0
  27. data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +2 -0
  28. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +136 -547
  29. data/lib/active_record/{oracle_enhanced/type → type/oracle_enhanced}/boolean.rb +4 -2
  30. data/lib/active_record/{oracle_enhanced/type → type/oracle_enhanced}/integer.rb +4 -2
  31. data/lib/active_record/type/oracle_enhanced/json.rb +10 -0
  32. data/lib/active_record/{oracle_enhanced/type → type/oracle_enhanced}/national_character_string.rb +5 -3
  33. data/lib/active_record/type/oracle_enhanced/national_character_text.rb +36 -0
  34. data/lib/active_record/{oracle_enhanced/type → type/oracle_enhanced}/raw.rb +4 -2
  35. data/lib/active_record/{oracle_enhanced/type → type/oracle_enhanced}/string.rb +4 -2
  36. data/lib/active_record/{oracle_enhanced/type → type/oracle_enhanced}/text.rb +4 -2
  37. data/lib/active_record/type/oracle_enhanced/timestampltz.rb +25 -0
  38. data/lib/active_record/{oracle_enhanced/type → type/oracle_enhanced}/timestamptz.rb +4 -2
  39. data/lib/activerecord-oracle_enhanced-adapter.rb +2 -6
  40. data/spec/active_record/connection_adapters/{oracle_enhanced_emulate_oracle_adapter_spec.rb → emulation/oracle_adapter_spec.rb} +2 -0
  41. data/spec/active_record/connection_adapters/{oracle_enhanced_connection_spec.rb → oracle_enhanced/connection_spec.rb} +82 -38
  42. data/spec/active_record/connection_adapters/{oracle_enhanced_context_index_spec.rb → oracle_enhanced/context_index_spec.rb} +20 -16
  43. data/spec/active_record/connection_adapters/{oracle_enhanced_database_tasks_spec.rb → oracle_enhanced/database_tasks_spec.rb} +17 -5
  44. data/spec/active_record/connection_adapters/{oracle_enhanced_dbms_output_spec.rb → oracle_enhanced/dbms_output_spec.rb} +2 -0
  45. data/spec/active_record/connection_adapters/{oracle_enhanced_procedures_spec.rb → oracle_enhanced/procedures_spec.rb} +26 -33
  46. data/spec/active_record/connection_adapters/oracle_enhanced/quoting_spec.rb +196 -0
  47. data/spec/active_record/connection_adapters/{oracle_enhanced_schema_dump_spec.rb → oracle_enhanced/schema_dumper_spec.rb} +61 -90
  48. data/spec/active_record/connection_adapters/{oracle_enhanced_schema_statements_spec.rb → oracle_enhanced/schema_statements_spec.rb} +95 -28
  49. data/spec/active_record/connection_adapters/{oracle_enhanced_structure_dump_spec.rb → oracle_enhanced/structure_dump_spec.rb} +48 -2
  50. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +202 -331
  51. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +15 -1106
  52. data/spec/active_record/oracle_enhanced/type/binary_spec.rb +119 -0
  53. data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +207 -0
  54. data/spec/active_record/{connection_adapters/oracle_enhanced_dirty_spec.rb → oracle_enhanced/type/dirty_spec.rb} +3 -1
  55. data/spec/active_record/oracle_enhanced/type/float_spec.rb +48 -0
  56. data/spec/active_record/oracle_enhanced/type/integer_spec.rb +91 -0
  57. data/spec/active_record/oracle_enhanced/type/json_spec.rb +57 -0
  58. data/spec/active_record/oracle_enhanced/type/national_character_string_spec.rb +55 -0
  59. data/spec/active_record/oracle_enhanced/type/national_character_text_spec.rb +230 -0
  60. data/spec/active_record/oracle_enhanced/type/raw_spec.rb +122 -0
  61. data/spec/active_record/oracle_enhanced/type/text_spec.rb +229 -0
  62. data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +75 -0
  63. data/spec/spec_helper.rb +15 -1
  64. data/spec/support/alter_system_set_open_cursors.sql +1 -0
  65. metadata +63 -48
  66. data/lib/active_record/connection_adapters/oracle_enhanced/column_dumper.rb +0 -28
  67. data/lib/active_record/oracle_enhanced/type/json.rb +0 -8
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  describe "OracleEnhancedAdapter structure dump" do
2
4
  include LoggerSpecHelper
3
5
 
@@ -150,6 +152,18 @@ describe "OracleEnhancedAdapter structure dump" do
150
152
  expect(dump).to match(/CREATE TABLE \"BARS\" \(\n \"ID\" NUMBER\(38,0\) NOT NULL,\n \"SUPER\" RAW\(255\) GENERATED ALWAYS AS \(HEXTORAW\(TO_CHAR\(ID\)\)\) VIRTUAL/)
151
153
  end
152
154
 
155
+ it "should dump NCLOB columns" do
156
+ @conn.execute <<-SQL
157
+ CREATE TABLE bars (
158
+ id NUMBER(38,0) NOT NULL,
159
+ nclob_text NCLOB,
160
+ PRIMARY KEY (ID)
161
+ )
162
+ SQL
163
+ dump = ActiveRecord::Base.connection.structure_dump
164
+ expect(dump).to match(/CREATE TABLE \"BARS\" \(\n \"ID\" NUMBER\(38,0\) NOT NULL,\n \"NCLOB_TEXT\" NCLOB/)
165
+ end
166
+
153
167
  it "should dump unique keys" do
154
168
  @conn.execute <<-SQL
155
169
  ALTER TABLE test_posts
@@ -232,7 +246,7 @@ describe "OracleEnhancedAdapter structure dump" do
232
246
  end
233
247
  describe "temporary tables" do
234
248
  after(:all) do
235
- @conn.drop_table :test_comments rescue nil
249
+ @conn.drop_table :test_comments, if_exists: true
236
250
  end
237
251
  it "should dump correctly" do
238
252
  @conn.create_table :test_comments, temporary: true, id: false do |t|
@@ -243,7 +257,39 @@ describe "OracleEnhancedAdapter structure dump" do
243
257
  end
244
258
  end
245
259
 
246
- describe "database stucture dump extentions" do
260
+ describe "sequences" do
261
+ let(:sequence_name) { "test_sequence_a" }
262
+ before(:each) do
263
+ @conn.execute sql
264
+ end
265
+ after(:each) do
266
+ @conn.execute "drop SEQUENCE \"#{sequence_name}\""
267
+ end
268
+ subject do
269
+ ActiveRecord::Base.connection.structure_dump
270
+ end
271
+ context "default sequence" do
272
+ let(:sql) { "CREATE SEQUENCE \"#{sequence_name}\"" }
273
+ it { is_expected.to_not match(%r{CREATE SEQUENCE \"#{sequence_name}" MAXVALUE \d+ MINVALUE \d+ NOORDER NOCYCLE}) }
274
+ end
275
+ context "noorder" do
276
+ let(:sql) { "CREATE SEQUENCE \"#{sequence_name}\" NOORDER" }
277
+ it { is_expected.to include("NOORDER") }
278
+ it { is_expected.to_not include(" ORDER") }
279
+ end
280
+ context "order" do
281
+ let(:sql) { "CREATE SEQUENCE \"#{sequence_name}\" ORDER" }
282
+ it { is_expected.to include(" ORDER") }
283
+ it { is_expected.to_not include("NOORDER") }
284
+ end
285
+ context "min max values" do
286
+ let(:sql) { "CREATE SEQUENCE \"#{sequence_name}\" MINVALUE 7 MAXVALUE 444" }
287
+ it { is_expected.to include("MINVALUE 7") }
288
+ it { is_expected.to include("MAXVALUE 444") }
289
+ end
290
+ end
291
+
292
+ describe "database structure dump extensions" do
247
293
  before(:all) do
248
294
  @conn.execute <<-SQL
249
295
  CREATE TABLE nvarchartable (
@@ -1,35 +1,4 @@
1
- describe "OracleEnhancedAdapter establish connection" do
2
-
3
- it "should connect to database" do
4
- ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
5
- expect(ActiveRecord::Base.connection).not_to be_nil
6
- expect(ActiveRecord::Base.connection.class).to eq(ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter)
7
- end
8
-
9
- it "should connect to database as SYSDBA" do
10
- ActiveRecord::Base.establish_connection(SYS_CONNECTION_PARAMS)
11
- expect(ActiveRecord::Base.connection).not_to be_nil
12
- expect(ActiveRecord::Base.connection.class).to eq(ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter)
13
- end
14
-
15
- it "should be active after connection to database" do
16
- ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
17
- expect(ActiveRecord::Base.connection).to be_active
18
- end
19
-
20
- it "should not be active after disconnection to database" do
21
- ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
22
- ActiveRecord::Base.connection.disconnect!
23
- expect(ActiveRecord::Base.connection).not_to be_active
24
- end
25
-
26
- it "should be active after reconnection to database" do
27
- ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
28
- ActiveRecord::Base.connection.reconnect!
29
- expect(ActiveRecord::Base.connection).to be_active
30
- end
31
-
32
- end
1
+ # frozen_string_literal: true
33
2
 
34
3
  describe "OracleEnhancedAdapter" do
35
4
  include LoggerSpecHelper
@@ -42,27 +11,27 @@ describe "OracleEnhancedAdapter" do
42
11
  describe "cache table columns" do
43
12
  before(:all) do
44
13
  @conn = ActiveRecord::Base.connection
45
- @conn.execute "DROP TABLE test_employees" rescue nil
46
- @oracle11g_or_higher = !! @conn.select_value(
47
- "select * from product_component_version where product like 'Oracle%' and to_number(substr(version,1,2)) >= 11")
48
- @conn.execute <<-SQL
49
- CREATE TABLE test_employees (
50
- id NUMBER PRIMARY KEY,
51
- first_name VARCHAR2(20),
52
- last_name VARCHAR2(25),
53
- #{ @oracle11g_or_higher ? "full_name AS (first_name || ' ' || last_name)," : "full_name VARCHAR2(46),"}
54
- hire_date DATE
55
- )
56
- SQL
57
- @conn.execute <<-SQL
58
- CREATE TABLE test_employees_without_pk (
59
- first_name VARCHAR2(20),
60
- last_name VARCHAR2(25),
61
- hire_date DATE
62
- )
63
- SQL
14
+ schema_define do
15
+ create_table :test_employees, force: true do |t|
16
+ t.string :first_name, limit: 20
17
+ t.string :last_name, limit: 25
18
+ if ActiveRecord::Base.connection.supports_virtual_columns?
19
+ t.virtual :full_name, as: "(first_name || ' ' || last_name)"
20
+ else
21
+ t.string :full_name, limit: 46
22
+ end
23
+ t.date :hire_date
24
+ end
25
+ end
26
+ schema_define do
27
+ create_table :test_employees_without_pk, id: false, force: true do |t|
28
+ t.string :first_name, limit: 20
29
+ t.string :last_name, limit: 25
30
+ t.date :hire_date
31
+ end
32
+ end
64
33
  @column_names = ["id", "first_name", "last_name", "full_name", "hire_date"]
65
- @column_sql_types = ["NUMBER", "VARCHAR2(20)", "VARCHAR2(25)", "VARCHAR2(46)", "DATE"]
34
+ @column_sql_types = ["NUMBER(38)", "VARCHAR2(20)", "VARCHAR2(25)", "VARCHAR2(46)", "DATE"]
66
35
  class ::TestEmployee < ActiveRecord::Base
67
36
  end
68
37
  # Another class using the same table
@@ -75,16 +44,14 @@ describe "OracleEnhancedAdapter" do
75
44
  @conn = ActiveRecord::Base.connection
76
45
  Object.send(:remove_const, "TestEmployee")
77
46
  Object.send(:remove_const, "TestEmployee2")
78
- @conn.execute "DROP TABLE test_employees"
79
- @conn.execute "DROP TABLE test_employees_without_pk"
80
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = nil
47
+ @conn.drop_table :test_employees, if_exists: true
48
+ @conn.drop_table :test_employees_without_pk, if_exists: true
81
49
  ActiveRecord::Base.clear_cache!
82
50
  end
83
51
 
84
52
  before(:each) do
85
53
  set_logger
86
54
  @conn = ActiveRecord::Base.connection
87
- @conn.clear_columns_cache
88
55
  end
89
56
 
90
57
  after(:each) do
@@ -93,12 +60,8 @@ describe "OracleEnhancedAdapter" do
93
60
 
94
61
  describe "without column caching" do
95
62
 
96
- before(:each) do
97
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = false
98
- end
99
-
100
63
  it "should identify virtual columns as such" do
101
- skip "Not supported in this database version" unless @oracle11g_or_higher
64
+ skip "Not supported in this database version" unless @conn.supports_virtual_columns?
102
65
  te = TestEmployee.connection.columns("test_employees").detect(&:virtual?)
103
66
  expect(te.name).to eq("full_name")
104
67
  end
@@ -116,14 +79,14 @@ describe "OracleEnhancedAdapter" do
116
79
  end
117
80
 
118
81
  it "should get primary key from database at first time" do
119
- expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", nil])
82
+ expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", "test_employees_seq"])
120
83
  expect(@logger.logged(:debug).last).to match(/select .* from all_constraints/im)
121
84
  end
122
85
 
123
86
  it "should get primary key from database at first time" do
124
- expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", nil])
87
+ expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", "test_employees_seq"])
125
88
  @logger.clear(:debug)
126
- expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", nil])
89
+ expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", "test_employees_seq"])
127
90
  expect(@logger.logged(:debug).last).to match(/select .* from all_constraints/im)
128
91
  end
129
92
 
@@ -133,229 +96,6 @@ describe "OracleEnhancedAdapter" do
133
96
  expect(TestEmployee2.columns.map(&:sql_type)).to eq(@column_sql_types)
134
97
  end
135
98
  end
136
-
137
- end
138
-
139
- describe "with column caching" do
140
-
141
- before(:each) do
142
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = true
143
- end
144
-
145
- it "should get columns from database at first time" do
146
- expect(TestEmployee.connection.columns("test_employees").map(&:name)).to eq(@column_names)
147
- expect(@logger.logged(:debug).last).to match(/select .* from all_tab_cols/im)
148
- end
149
-
150
- it "should get columns from cache at second time" do
151
- TestEmployee.connection.columns("test_employees")
152
- @logger.clear(:debug)
153
- expect(TestEmployee.connection.columns("test_employees").map(&:name)).to eq(@column_names)
154
- expect(@logger.logged(:debug).last).to be_blank
155
- end
156
-
157
- it "should get primary key from database at first time" do
158
- expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", nil])
159
- expect(@logger.logged(:debug).last).to match(/select .* from all_constraints/im)
160
- end
161
-
162
- it "should get primary key from cache at first time" do
163
- expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", nil])
164
- @logger.clear(:debug)
165
- expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", nil])
166
- expect(@logger.logged(:debug).last).to be_blank
167
- end
168
-
169
- it "should store primary key as nil in cache at first time for table without primary key" do
170
- expect(TestEmployee.connection.pk_and_sequence_for("test_employees_without_pk")).to eq(nil)
171
- @logger.clear(:debug)
172
- expect(TestEmployee.connection.pk_and_sequence_for("test_employees_without_pk")).to eq(nil)
173
- expect(@logger.logged(:debug).last).to be_blank
174
- end
175
-
176
- end
177
-
178
- end
179
-
180
- describe "reserved words column quoting" do
181
-
182
- before(:all) do
183
- schema_define do
184
- create_table :test_reserved_words do |t|
185
- t.string :varchar2
186
- t.integer :integer
187
- t.text :comment
188
- end
189
- end
190
- class ::TestReservedWord < ActiveRecord::Base; end
191
- end
192
-
193
- after(:all) do
194
- schema_define do
195
- drop_table :test_reserved_words
196
- end
197
- Object.send(:remove_const, "TestReservedWord")
198
- ActiveRecord::Base.table_name_prefix = nil
199
- ActiveRecord::Base.clear_cache!
200
- end
201
-
202
- before(:each) do
203
- set_logger
204
- end
205
-
206
- after(:each) do
207
- clear_logger
208
- end
209
-
210
- it "should create table" do
211
- [:varchar2, :integer, :comment].each do |attr|
212
- expect(TestReservedWord.columns_hash[attr.to_s].name).to eq(attr.to_s)
213
- end
214
- end
215
-
216
- it "should create record" do
217
- attrs = {
218
- varchar2: "dummy",
219
- integer: 1,
220
- comment: "dummy"
221
- }
222
- record = TestReservedWord.create!(attrs)
223
- record.reload
224
- attrs.each do |k, v|
225
- expect(record.send(k)).to eq(v)
226
- end
227
- end
228
-
229
- it "should remove double quotes in column quoting" do
230
- expect(ActiveRecord::Base.connection.quote_column_name('aaa "bbb" ccc')).to eq('"aaa bbb ccc"')
231
- end
232
-
233
- end
234
-
235
- describe "valid table names" do
236
- before(:all) do
237
- @adapter = ActiveRecord::ConnectionAdapters::OracleEnhanced::Quoting
238
- end
239
-
240
- it "should be valid with letters and digits" do
241
- expect(@adapter.valid_table_name?("abc_123")).to be_truthy
242
- end
243
-
244
- it "should be valid with schema name" do
245
- expect(@adapter.valid_table_name?("abc_123.def_456")).to be_truthy
246
- end
247
-
248
- it "should be valid with $ in name" do
249
- expect(@adapter.valid_table_name?("sys.v$session")).to be_truthy
250
- end
251
-
252
- it "should be valid with upcase schema name" do
253
- expect(@adapter.valid_table_name?("ABC_123.DEF_456")).to be_truthy
254
- end
255
-
256
- it "should be valid with irregular schema name and database links" do
257
- expect(@adapter.valid_table_name?('abc$#_123.abc$#_123@abc$#@._123')).to be_truthy
258
- end
259
-
260
- it "should not be valid with two dots in name" do
261
- expect(@adapter.valid_table_name?("abc_123.def_456.ghi_789")).to be_falsey
262
- end
263
-
264
- it "should not be valid with invalid characters" do
265
- expect(@adapter.valid_table_name?("warehouse-things")).to be_falsey
266
- end
267
-
268
- it "should not be valid with for camel-case" do
269
- expect(@adapter.valid_table_name?("Abc")).to be_falsey
270
- expect(@adapter.valid_table_name?("aBc")).to be_falsey
271
- expect(@adapter.valid_table_name?("abC")).to be_falsey
272
- end
273
-
274
- it "should not be valid for names > 30 characters" do
275
- expect(@adapter.valid_table_name?("a" * 31)).to be_falsey
276
- end
277
-
278
- it "should not be valid for schema names > 30 characters" do
279
- expect(@adapter.valid_table_name?(("a" * 31) + ".validname")).to be_falsey
280
- end
281
-
282
- it "should not be valid for database links > 128 characters" do
283
- expect(@adapter.valid_table_name?("name@" + "a" * 129)).to be_falsey
284
- end
285
-
286
- it "should not be valid for names that do not begin with alphabetic characters" do
287
- expect(@adapter.valid_table_name?("1abc")).to be_falsey
288
- expect(@adapter.valid_table_name?("_abc")).to be_falsey
289
- expect(@adapter.valid_table_name?("abc.1xyz")).to be_falsey
290
- expect(@adapter.valid_table_name?("abc._xyz")).to be_falsey
291
- end
292
- end
293
-
294
- describe "table quoting" do
295
-
296
- def create_warehouse_things_table
297
- ActiveRecord::Schema.define do
298
- suppress_messages do
299
- create_table "warehouse-things" do |t|
300
- t.string :name
301
- t.integer :foo
302
- end
303
- end
304
- end
305
- end
306
-
307
- def create_camel_case_table
308
- ActiveRecord::Schema.define do
309
- suppress_messages do
310
- create_table "CamelCase" do |t|
311
- t.string :name
312
- t.integer :foo
313
- end
314
- end
315
- end
316
- end
317
-
318
- before(:all) do
319
- @conn = ActiveRecord::Base.connection
320
- end
321
-
322
- after(:each) do
323
- ActiveRecord::Schema.define do
324
- suppress_messages do
325
- drop_table "warehouse-things" rescue nil
326
- drop_table "CamelCase" rescue nil
327
- end
328
- end
329
- Object.send(:remove_const, "WarehouseThing") rescue nil
330
- Object.send(:remove_const, "CamelCase") rescue nil
331
- end
332
-
333
- it "should allow creation of a table with non alphanumeric characters" do
334
- create_warehouse_things_table
335
- class ::WarehouseThing < ActiveRecord::Base
336
- self.table_name = "warehouse-things"
337
- end
338
-
339
- wh = WarehouseThing.create!(name: "Foo", foo: 2)
340
- expect(wh.id).not_to be_nil
341
-
342
- expect(@conn.tables).to include("warehouse-things")
343
- end
344
-
345
- it "should allow creation of a table with CamelCase name" do
346
- create_camel_case_table
347
- class ::CamelCase < ActiveRecord::Base
348
- self.table_name = "CamelCase"
349
- end
350
-
351
- cc = CamelCase.create!(name: "Foo", foo: 2)
352
- expect(cc.id).not_to be_nil
353
-
354
- expect(@conn.tables).to include("CamelCase")
355
- end
356
-
357
- it "properly quotes database links" do
358
- expect(@conn.quote_table_name("asdf@some.link")).to eq('"ASDF"@"SOME.LINK"')
359
99
  end
360
100
  end
361
101
 
@@ -364,7 +104,7 @@ describe "OracleEnhancedAdapter" do
364
104
  @conn = ActiveRecord::Base.connection
365
105
  @db_link = "db_link"
366
106
  @sys_conn = ActiveRecord::Base.oracle_enhanced_connection(SYSTEM_CONNECTION_PARAMS)
367
- @sys_conn.drop_table :test_posts rescue nil
107
+ @sys_conn.drop_table :test_posts, if_exists: true
368
108
  @sys_conn.create_table :test_posts do |t|
369
109
  t.string :title
370
110
  # cannot update LOBs over database link
@@ -387,7 +127,7 @@ describe "OracleEnhancedAdapter" do
387
127
  @conn.execute "DROP SYNONYM test_posts"
388
128
  @conn.execute "DROP SYNONYM test_posts_seq"
389
129
  @conn.execute "DROP DATABASE LINK #{@db_link}" rescue nil
390
- @sys_conn.drop_table :test_posts rescue nil
130
+ @sys_conn.drop_table :test_posts, if_exists: true
391
131
  Object.send(:remove_const, "TestPost") rescue nil
392
132
  ActiveRecord::Base.clear_cache!
393
133
  end
@@ -435,7 +175,7 @@ describe "OracleEnhancedAdapter" do
435
175
  end
436
176
 
437
177
  after(:each) do
438
- @conn.drop_table :foos rescue nil
178
+ @conn.drop_table :foos, if_exists: true
439
179
  end
440
180
  it "should create ok" do
441
181
  @conn.create_table :foos, temporary: true, id: false do |t|
@@ -500,7 +240,7 @@ describe "OracleEnhancedAdapter" do
500
240
  ActiveRecord::Base.establish_connection(CONNECTION_PARAMS.merge(statement_limit: 3))
501
241
  @conn = ActiveRecord::Base.connection
502
242
  schema_define do
503
- drop_table :test_posts rescue nil
243
+ drop_table :test_posts, if_exists: true
504
244
  create_table :test_posts
505
245
  end
506
246
  class ::TestPost < ActiveRecord::Base
@@ -521,23 +261,20 @@ describe "OracleEnhancedAdapter" do
521
261
  end
522
262
 
523
263
  it "should clear older cursors when statement limit is reached" do
524
- pk = TestPost.columns_hash[TestPost.primary_key]
525
- sub = Arel::Nodes::BindParam.new.to_sql
526
- binds = [ActiveRecord::Relation::QueryAttribute.new(pk, 1, ActiveRecord::Type::Integer.new)]
527
-
264
+ binds = [ActiveRecord::Relation::QueryAttribute.new("id", 1, ActiveRecord::Type::OracleEnhanced::Integer.new)]
265
+ # free statement pool from dictionary selections to ensure next selects will increase statement pool
266
+ @statements.clear
528
267
  expect {
529
268
  4.times do |i|
530
- @conn.exec_query("SELECT * FROM test_posts WHERE #{i}=#{i} AND id = #{sub}", "SQL", binds)
269
+ @conn.exec_query("SELECT * FROM test_posts WHERE #{i}=#{i} AND id = :id", "SQL", binds)
531
270
  end
532
271
  }.to change(@statements, :length).by(+3)
533
272
  end
534
273
 
535
274
  it "should cache UPDATE statements with bind variables" do
536
275
  expect {
537
- pk = TestPost.columns_hash[TestPost.primary_key]
538
- sub = Arel::Nodes::BindParam.new.to_sql
539
- binds = [ActiveRecord::Relation::QueryAttribute.new(pk, 1, ActiveRecord::Type::Integer.new)]
540
- @conn.exec_update("UPDATE test_posts SET id = #{sub}", "SQL", binds)
276
+ binds = [ActiveRecord::Relation::QueryAttribute.new("id", 1, ActiveRecord::Type::OracleEnhanced::Integer.new)]
277
+ @conn.exec_update("UPDATE test_posts SET id = :id", "SQL", binds)
541
278
  }.to change(@statements, :length).by(+1)
542
279
  end
543
280
 
@@ -553,7 +290,7 @@ describe "OracleEnhancedAdapter" do
553
290
  before(:all) do
554
291
  @conn = ActiveRecord::Base.connection
555
292
  schema_define do
556
- drop_table :test_posts rescue nil
293
+ drop_table :test_posts, if_exists: true
557
294
  create_table :test_posts
558
295
  end
559
296
  class ::TestPost < ActiveRecord::Base
@@ -575,35 +312,24 @@ describe "OracleEnhancedAdapter" do
575
312
  end
576
313
 
577
314
  it "should explain query with binds" do
578
- pending "Pending until further investigation made for #908" if RUBY_ENGINE == "jruby"
579
- pk = TestPost.columns_hash[TestPost.primary_key]
580
- sub = Arel::Nodes::BindParam.new.to_sql
581
- binds = [ActiveRecord::Relation::QueryAttribute.new(pk, 1, ActiveRecord::Type::Integer.new)]
582
- explain = @conn.explain(TestPost.where(TestPost.arel_table[pk.name].eq(sub)), binds)
315
+ binds = [ActiveRecord::Relation::QueryAttribute.new("id", 1, ActiveRecord::Type::OracleEnhanced::Integer.new)]
316
+ explain = TestPost.where(id: binds).explain
583
317
  expect(explain).to include("Cost")
584
- expect(explain).to include("INDEX UNIQUE SCAN")
318
+ expect(explain).to include("INDEX UNIQUE SCAN").or include("TABLE ACCESS FULL")
585
319
  end
586
320
  end
587
321
 
588
322
  describe "using offset and limit" do
589
323
  before(:all) do
590
324
  @conn = ActiveRecord::Base.connection
591
- @conn.execute "DROP TABLE test_employees" rescue nil
592
- @conn.execute <<-SQL
593
- CREATE TABLE test_employees (
594
- id NUMBER PRIMARY KEY,
595
- sort_order NUMBER(38,0),
596
- first_name VARCHAR2(20),
597
- last_name VARCHAR2(25),
598
- updated_at DATE,
599
- created_at DATE
600
- )
601
- SQL
602
- @conn.execute "DROP SEQUENCE test_employees_seq" rescue nil
603
- @conn.execute <<-SQL
604
- CREATE SEQUENCE test_employees_seq MINVALUE 1
605
- INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE
606
- SQL
325
+ schema_define do
326
+ create_table :test_employees, force: true do |t|
327
+ t.integer :sort_order
328
+ t.string :first_name, limit: 20
329
+ t.string :last_name, limit: 20
330
+ t.timestamps
331
+ end
332
+ end
607
333
  @employee = Class.new(ActiveRecord::Base) do
608
334
  self.table_name = :test_employees
609
335
  end
@@ -616,8 +342,7 @@ describe "OracleEnhancedAdapter" do
616
342
  end
617
343
 
618
344
  after(:all) do
619
- @conn.execute "DROP TABLE test_employees"
620
- @conn.execute "DROP SEQUENCE test_employees_seq"
345
+ @conn.drop_table :test_employees, if_exists: true
621
346
  end
622
347
 
623
348
  after(:each) do
@@ -643,15 +368,15 @@ describe "OracleEnhancedAdapter" do
643
368
  describe "valid_type?" do
644
369
  before(:all) do
645
370
  @conn = ActiveRecord::Base.connection
646
- @conn.execute <<-SQL
647
- CREATE TABLE test_employees (
648
- first_name VARCHAR2(20)
649
- )
650
- SQL
371
+ schema_define do
372
+ create_table :test_employees, force: true do |t|
373
+ t.string :first_name, limit: 20
374
+ end
375
+ end
651
376
  end
652
377
 
653
378
  after(:all) do
654
- @conn.execute "DROP TABLE test_employees"
379
+ @conn.drop_table :test_employees, if_exists: true
655
380
  end
656
381
 
657
382
  it "returns true when passed a valid type" do
@@ -736,4 +461,150 @@ describe "OracleEnhancedAdapter" do
736
461
  expect(TestLog.count).to eq 2
737
462
  end
738
463
  end
464
+
465
+ describe "synonym_names" do
466
+ before(:all) do
467
+ schema_define do
468
+ create_table :test_comments, force: true do |t|
469
+ t.string :comment
470
+ end
471
+ add_synonym :synonym_comments, :test_comments
472
+ end
473
+ end
474
+
475
+ after(:all) do
476
+ schema_define do
477
+ drop_table :test_comments
478
+ remove_synonym :synonym_comments
479
+ end
480
+ ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
481
+ end
482
+
483
+ it "includes synonyms in data_source" do
484
+ conn = ActiveRecord::Base.connection
485
+ expect(conn).to be_data_source_exist("synonym_comments")
486
+ expect(conn.data_sources).to include("synonym_comments")
487
+ end
488
+ end
489
+
490
+ describe "dictionary selects with bind variables" do
491
+ before(:all) do
492
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
493
+ @conn = ActiveRecord::Base.connection
494
+ schema_define do
495
+ drop_table :test_posts, if_exists: true
496
+ create_table :test_posts
497
+ end
498
+ class ::TestPost < ActiveRecord::Base
499
+ end
500
+ end
501
+
502
+ before(:each) do
503
+ @conn.clear_cache!
504
+ set_logger
505
+ end
506
+
507
+ after(:each) do
508
+ clear_logger
509
+ end
510
+
511
+ after(:all) do
512
+ schema_define do
513
+ drop_table :test_posts
514
+ end
515
+ Object.send(:remove_const, "TestPost")
516
+ ActiveRecord::Base.clear_cache!
517
+ end
518
+
519
+ it "should test table existence" do
520
+ expect(@conn.table_exists?("TEST_POSTS")).to eq true
521
+ expect(@conn.table_exists?("NOT_EXISTING")).to eq false
522
+ end
523
+
524
+ it "should return array from indexes with bind usage" do
525
+ expect(@conn.indexes("TEST_POSTS").class).to eq Array
526
+ expect(@logger.logged(:debug).last).to match(/:owner/)
527
+ expect(@logger.logged(:debug).last).to match(/\[\["owner", "#{DATABASE_USER.upcase}"\], \["owner", "#{DATABASE_USER.upcase}"\]\]/)
528
+ end
529
+
530
+ it "should not have primary key trigger with bind usage" do
531
+ expect(@conn.has_primary_key_trigger?("TEST_POSTS")).to eq false
532
+ expect(@logger.logged(:debug).last).to match(/:owner/)
533
+ expect(@logger.logged(:debug).last).to match(/:table_name/)
534
+ expect(@logger.logged(:debug).last).to match(/\[\["owner", "#{DATABASE_USER.upcase}"\], \["trigger_name", "TEST_POSTS_PKT"\], \["owner", "#{DATABASE_USER.upcase}"\], \["table_name", "TEST_POSTS"\]\]/)
535
+ end
536
+
537
+ it "should return content from columns with bind usage" do
538
+ expect(@conn.columns("TEST_POSTS").length).to be > 0
539
+ expect(@logger.logged(:debug).last).to match(/:owner/)
540
+ expect(@logger.logged(:debug).last).to match(/:table_name/)
541
+ expect(@logger.logged(:debug).last).to match(/\[\["owner", "#{DATABASE_USER.upcase}"\], \["table_name", "TEST_POSTS"\]\]/)
542
+ end
543
+
544
+ it "should return pk and sequence from pk_and_sequence_for with bind usage" do
545
+ expect(@conn.pk_and_sequence_for("TEST_POSTS").length).to eq 2
546
+ expect(@logger.logged(:debug).last).to match(/:owner/)
547
+ expect(@logger.logged(:debug).last).to match(/\[\["owner", "#{DATABASE_USER.upcase}"\], \["table_name", "TEST_POSTS"\]\]/)
548
+ end
549
+
550
+ it "should return pk from primary_keys with bind usage" do
551
+ expect(@conn.primary_keys("TEST_POSTS")).to eq ["id"]
552
+ expect(@logger.logged(:debug).last).to match(/:owner/)
553
+ expect(@logger.logged(:debug).last).to match(/\[\["owner", "#{DATABASE_USER.upcase}"\], \["table_name", "TEST_POSTS"\]\]/)
554
+ end
555
+
556
+ it "should return false from temporary_table? with bind usage" do
557
+ expect(@conn.temporary_table?("TEST_POSTS")).to eq false
558
+ expect(@logger.logged(:debug).last).to match(/:table_name/)
559
+ expect(@logger.logged(:debug).last).to match(/\[\["table_name", "TEST_POSTS"\]\]/)
560
+ end
561
+
562
+ end
563
+
564
+ describe "Transaction" do
565
+ before(:all) do
566
+ schema_define do
567
+ create_table :test_posts do |t|
568
+ t.string :title
569
+ end
570
+ end
571
+ class ::TestPost < ActiveRecord::Base
572
+ end
573
+ end
574
+
575
+ it "Raises Deadlocked when a deadlock is encountered" do
576
+ expect {
577
+ barrier = Concurrent::CyclicBarrier.new(2)
578
+
579
+ t1 = TestPost.create(title: "one")
580
+ t2 = TestPost.create(title: "two")
581
+
582
+ thread = Thread.new do
583
+ TestPost.transaction do
584
+ t1.lock!
585
+ barrier.wait
586
+ t2.update_attributes(title: "one")
587
+ end
588
+ end
589
+
590
+ begin
591
+ TestPost.transaction do
592
+ t2.lock!
593
+ barrier.wait
594
+ t1.update_attributes(title: "two")
595
+ end
596
+ ensure
597
+ thread.join
598
+ end
599
+ }.to raise_error(ActiveRecord::Deadlocked)
600
+ end
601
+
602
+ after(:all) do
603
+ schema_define do
604
+ drop_table :test_posts
605
+ end
606
+ Object.send(:remove_const, "TestPost") rescue nil
607
+ ActiveRecord::Base.clear_cache!
608
+ end
609
+ end
739
610
  end