activerecord-oracle_enhanced-adapter 1.4.3 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +1162 -2
  3. data/README.md +567 -155
  4. data/VERSION +1 -1
  5. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +3 -1
  6. data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +19 -0
  7. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +132 -0
  8. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +345 -0
  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 +280 -0
  11. data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +64 -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 +538 -0
  14. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +38 -0
  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 +435 -0
  17. data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +44 -0
  18. data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +196 -0
  19. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +164 -0
  20. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +95 -0
  21. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +79 -0
  22. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +194 -0
  23. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +709 -0
  24. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +28 -0
  25. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +353 -0
  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 +3 -0
  28. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +385 -1083
  29. data/lib/active_record/type/oracle_enhanced/boolean.rb +20 -0
  30. data/lib/active_record/type/oracle_enhanced/integer.rb +15 -0
  31. data/lib/active_record/type/oracle_enhanced/json.rb +10 -0
  32. data/lib/active_record/type/oracle_enhanced/national_character_string.rb +26 -0
  33. data/lib/active_record/type/oracle_enhanced/national_character_text.rb +36 -0
  34. data/lib/active_record/type/oracle_enhanced/raw.rb +25 -0
  35. data/lib/active_record/type/oracle_enhanced/string.rb +29 -0
  36. data/lib/active_record/type/oracle_enhanced/text.rb +32 -0
  37. data/lib/active_record/type/oracle_enhanced/timestampltz.rb +25 -0
  38. data/lib/active_record/type/oracle_enhanced/timestamptz.rb +25 -0
  39. data/lib/activerecord-oracle_enhanced-adapter.rb +5 -13
  40. data/spec/active_record/connection_adapters/{oracle_enhanced_emulate_oracle_adapter_spec.rb → emulation/oracle_adapter_spec.rb} +5 -4
  41. data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +469 -0
  42. data/spec/active_record/connection_adapters/{oracle_enhanced_context_index_spec.rb → oracle_enhanced/context_index_spec.rb} +140 -128
  43. data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +112 -0
  44. data/spec/active_record/connection_adapters/{oracle_enhanced_dbms_output_spec.rb → oracle_enhanced/dbms_output_spec.rb} +13 -13
  45. data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +365 -0
  46. data/spec/active_record/connection_adapters/oracle_enhanced/quoting_spec.rb +196 -0
  47. data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +492 -0
  48. data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +1433 -0
  49. data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +478 -0
  50. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +385 -550
  51. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +92 -1249
  52. data/spec/active_record/oracle_enhanced/type/binary_spec.rb +119 -0
  53. data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +208 -0
  54. data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +139 -0
  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_config.yaml.template +11 -0
  64. data/spec/spec_helper.rb +100 -93
  65. data/spec/support/alter_system_set_open_cursors.sql +1 -0
  66. data/spec/support/alter_system_user_password.sql +2 -0
  67. data/spec/support/create_oracle_enhanced_users.sql +31 -0
  68. metadata +105 -152
  69. data/.rspec +0 -2
  70. data/Gemfile +0 -52
  71. data/RUNNING_TESTS.md +0 -45
  72. data/Rakefile +0 -59
  73. data/activerecord-oracle_enhanced-adapter.gemspec +0 -130
  74. data/lib/active_record/connection_adapters/oracle_enhanced.rake +0 -105
  75. data/lib/active_record/connection_adapters/oracle_enhanced_activerecord_patches.rb +0 -41
  76. data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +0 -121
  77. data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +0 -151
  78. data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +0 -119
  79. data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +0 -359
  80. data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +0 -25
  81. data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +0 -21
  82. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +0 -46
  83. data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +0 -572
  84. data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +0 -497
  85. data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +0 -260
  86. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +0 -227
  87. data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +0 -260
  88. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +0 -428
  89. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +0 -258
  90. data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +0 -294
  91. data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +0 -17
  92. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +0 -1
  93. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +0 -334
  94. data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +0 -19
  95. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +0 -113
  96. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +0 -141
  97. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +0 -378
  98. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +0 -440
  99. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +0 -1400
  100. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +0 -339
@@ -1,37 +1,4 @@
1
- require 'spec_helper'
2
-
3
- describe "OracleEnhancedAdapter establish connection" do
4
-
5
- it "should connect to database" do
6
- ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
7
- ActiveRecord::Base.connection.should_not be_nil
8
- ActiveRecord::Base.connection.class.should == ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
9
- end
10
-
11
- it "should connect to database as SYSDBA" do
12
- ActiveRecord::Base.establish_connection(SYS_CONNECTION_PARAMS)
13
- ActiveRecord::Base.connection.should_not be_nil
14
- ActiveRecord::Base.connection.class.should == ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
15
- end
16
-
17
- it "should be active after connection to database" do
18
- ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
19
- ActiveRecord::Base.connection.should be_active
20
- end
21
-
22
- it "should not be active after disconnection to database" do
23
- ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
24
- ActiveRecord::Base.connection.disconnect!
25
- ActiveRecord::Base.connection.should_not be_active
26
- end
27
-
28
- it "should be active after reconnection to database" do
29
- ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
30
- ActiveRecord::Base.connection.reconnect!
31
- ActiveRecord::Base.connection.should be_active
32
- end
33
-
34
- end
1
+ # frozen_string_literal: true
35
2
 
36
3
  describe "OracleEnhancedAdapter" do
37
4
  include LoggerSpecHelper
@@ -40,180 +7,36 @@ describe "OracleEnhancedAdapter" do
40
7
  before(:all) do
41
8
  ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
42
9
  end
43
-
44
- describe "database session store" do
45
- before(:all) do
46
- @conn.execute "DROP TABLE sessions" rescue nil
47
- @conn.execute "DROP SEQUENCE sessions_seq" rescue nil
48
- @conn = ActiveRecord::Base.connection
49
- @conn.execute <<-SQL
50
- CREATE TABLE sessions (
51
- id NUMBER(38,0) NOT NULL,
52
- session_id VARCHAR2(255) DEFAULT NULL,
53
- data CLOB DEFAULT NULL,
54
- created_at DATE DEFAULT NULL,
55
- updated_at DATE DEFAULT NULL,
56
- PRIMARY KEY (ID)
57
- )
58
- SQL
59
- @conn.execute <<-SQL
60
- CREATE SEQUENCE sessions_seq MINVALUE 1 MAXVALUE 999999999999999999999999999
61
- INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
62
- SQL
63
- if ENV['RAILS_GEM_VERSION'] >= '2.3'
64
- @session_class = ActiveRecord::SessionStore::Session
65
- else
66
- @session_class = CGI::Session::ActiveRecordStore::Session
67
- end
68
- end
69
-
70
- after(:all) do
71
- @conn.execute "DROP TABLE sessions"
72
- @conn.execute "DROP SEQUENCE sessions_seq"
73
- end
74
10
 
75
- it "should create sessions table" do
76
- ActiveRecord::Base.connection.tables.grep("sessions").should_not be_empty
77
- end
78
-
79
- it "should save session data" do
80
- @session = @session_class.new :session_id => "111111", :data => "something" #, :updated_at => Time.now
81
- @session.save!
82
- @session = @session_class.find_by_session_id("111111")
83
- @session.data.should == "something"
84
- end
85
-
86
- it "should change session data when partial updates enabled" do
87
- return pending("Not in this ActiveRecord version") unless @session_class.respond_to?(:partial_updates=)
88
- @session_class.partial_updates = true
89
- @session = @session_class.new :session_id => "222222", :data => "something" #, :updated_at => Time.now
90
- @session.save!
91
- @session = @session_class.find_by_session_id("222222")
92
- @session.data = "other thing"
93
- @session.save!
94
- # second save should call again blob writing callback
95
- @session.save!
96
- @session = @session_class.find_by_session_id("222222")
97
- @session.data.should == "other thing"
98
- end
99
-
100
- it "should have one enhanced_write_lobs callback" do
101
- return pending("Not in this ActiveRecord version") unless @session_class.respond_to?(:after_save_callback_chain)
102
- @session_class.after_save_callback_chain.select{|cb| cb.method == :enhanced_write_lobs}.should have(1).record
103
- end
104
-
105
- it "should not set sessions table session_id column type as integer if emulate_integers_by_column_name is true" do
106
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
107
- columns = @conn.columns('sessions')
108
- column = columns.detect{|c| c.name == "session_id"}
109
- column.type.should == :string
110
- end
111
-
112
- end
113
-
114
- describe "ignore specified table columns" do
11
+ describe "cache table columns" do
115
12
  before(:all) do
116
13
  @conn = ActiveRecord::Base.connection
117
- @conn.execute "DROP TABLE test_employees" rescue nil
118
- @conn.execute <<-SQL
119
- CREATE TABLE test_employees (
120
- id NUMBER PRIMARY KEY,
121
- first_name VARCHAR2(20),
122
- last_name VARCHAR2(25),
123
- email VARCHAR2(25),
124
- phone_number VARCHAR2(20),
125
- hire_date DATE,
126
- job_id NUMBER,
127
- salary NUMBER,
128
- commission_pct NUMBER(2,2),
129
- manager_id NUMBER(6),
130
- department_id NUMBER(4,0),
131
- created_at DATE
132
- )
133
- SQL
134
- @conn.execute "DROP SEQUENCE test_employees_seq" rescue nil
135
- @conn.execute <<-SQL
136
- CREATE SEQUENCE test_employees_seq MINVALUE 1
137
- INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE
138
- SQL
139
- end
140
-
141
- after(:all) do
142
- @conn.execute "DROP TABLE test_employees"
143
- @conn.execute "DROP SEQUENCE test_employees_seq"
144
- end
145
-
146
- after(:each) do
147
- Object.send(:remove_const, "TestEmployee")
148
- ActiveRecord::Base.connection.clear_ignored_table_columns
149
- ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
150
- end
151
-
152
- it "should ignore specified table columns" do
153
- class ::TestEmployee < ActiveRecord::Base
154
- ignore_table_columns :phone_number, :hire_date
155
- end
156
- TestEmployee.connection.columns('test_employees').select{|c| ['phone_number','hire_date'].include?(c.name) }.should be_empty
157
- end
158
-
159
- it "should ignore specified table columns specified in several lines" do
160
- class ::TestEmployee < ActiveRecord::Base
161
- ignore_table_columns :phone_number
162
- ignore_table_columns :hire_date
163
- end
164
- TestEmployee.connection.columns('test_employees').select{|c| ['phone_number','hire_date'].include?(c.name) }.should be_empty
165
- end
166
-
167
- it "should not ignore unspecified table columns" do
168
- class ::TestEmployee < ActiveRecord::Base
169
- ignore_table_columns :phone_number, :hire_date
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
170
25
  end
171
- TestEmployee.connection.columns('test_employees').select{|c| c.name == 'email' }.should_not be_empty
172
- end
173
-
174
- it "should ignore specified table columns in other connection" do
175
- class ::TestEmployee < ActiveRecord::Base
176
- ignore_table_columns :phone_number, :hire_date
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
177
32
  end
178
- # establish other connection
179
- other_conn = ActiveRecord::Base.oracle_enhanced_connection(CONNECTION_PARAMS)
180
- other_conn.columns('test_employees').select{|c| ['phone_number','hire_date'].include?(c.name) }.should be_empty
181
- end
182
-
183
- end
184
-
185
- describe "cache table columns" do
186
- before(:all) do
187
- @conn = ActiveRecord::Base.connection
188
- @conn.execute "DROP TABLE test_employees" rescue nil
189
- @oracle11g = !! @conn.select_value("SELECT * FROM v$version WHERE banner LIKE 'Oracle%11g%'")
190
- @conn.execute <<-SQL
191
- CREATE TABLE test_employees (
192
- id NUMBER PRIMARY KEY,
193
- first_name VARCHAR2(20),
194
- last_name VARCHAR2(25),
195
- #{ @oracle11g ? "full_name AS (first_name || ' ' || last_name)," : "full_name VARCHAR2(46),"}
196
- hire_date DATE
197
- )
198
- SQL
199
- @conn.execute <<-SQL
200
- CREATE TABLE test_employees_without_pk (
201
- first_name VARCHAR2(20),
202
- last_name VARCHAR2(25),
203
- hire_date DATE
204
- )
205
- SQL
206
- @column_names = ['id', 'first_name', 'last_name', 'full_name', 'hire_date']
207
- @column_sql_types = ["NUMBER", "VARCHAR2(20)", "VARCHAR2(25)", "VARCHAR2(46)", "DATE"]
33
+ @column_names = ["id", "first_name", "last_name", "full_name", "hire_date"]
34
+ @column_sql_types = ["NUMBER(38)", "VARCHAR2(20)", "VARCHAR2(25)", "VARCHAR2(46)", "DATE"]
208
35
  class ::TestEmployee < ActiveRecord::Base
209
36
  end
210
37
  # Another class using the same table
211
38
  class ::TestEmployee2 < ActiveRecord::Base
212
- if self.respond_to?(:table_name=)
213
- self.table_name = "test_employees"
214
- else
215
- set_table_name "test_employees"
216
- end
39
+ self.table_name = "test_employees"
217
40
  end
218
41
  end
219
42
 
@@ -221,16 +44,14 @@ describe "OracleEnhancedAdapter" do
221
44
  @conn = ActiveRecord::Base.connection
222
45
  Object.send(:remove_const, "TestEmployee")
223
46
  Object.send(:remove_const, "TestEmployee2")
224
- @conn.execute "DROP TABLE test_employees"
225
- @conn.execute "DROP TABLE test_employees_without_pk"
226
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = nil
227
- ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
47
+ @conn.drop_table :test_employees, if_exists: true
48
+ @conn.drop_table :test_employees_without_pk, if_exists: true
49
+ ActiveRecord::Base.clear_cache!
228
50
  end
229
51
 
230
52
  before(:each) do
231
53
  set_logger
232
54
  @conn = ActiveRecord::Base.connection
233
- @conn.clear_columns_cache
234
55
  end
235
56
 
236
57
  after(:each) do
@@ -239,313 +60,43 @@ describe "OracleEnhancedAdapter" do
239
60
 
240
61
  describe "without column caching" do
241
62
 
242
- before(:each) do
243
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = false
244
- end
245
-
246
- it 'should identify virtual columns as such' do
247
- pending "Not supported in this database version" unless @oracle11g
248
- te = TestEmployee.connection.columns('test_employees').detect(&:virtual?)
249
- te.name.should == 'full_name'
63
+ it "should identify virtual columns as such" do
64
+ skip "Not supported in this database version" unless @conn.supports_virtual_columns?
65
+ te = TestEmployee.connection.columns("test_employees").detect(&:virtual?)
66
+ expect(te.name).to eq("full_name")
250
67
  end
251
68
 
252
69
  it "should get columns from database at first time" do
253
- TestEmployee.connection.columns('test_employees').map(&:name).should == @column_names
254
- @logger.logged(:debug).last.should =~ /select .* from all_tab_cols/im
70
+ expect(TestEmployee.connection.columns("test_employees").map(&:name)).to eq(@column_names)
71
+ expect(@logger.logged(:debug).last).to match(/select .* from all_tab_cols/im)
255
72
  end
256
73
 
257
74
  it "should get columns from database at second time" do
258
- TestEmployee.connection.columns('test_employees')
75
+ TestEmployee.connection.columns("test_employees")
259
76
  @logger.clear(:debug)
260
- TestEmployee.connection.columns('test_employees').map(&:name).should == @column_names
261
- @logger.logged(:debug).last.should =~ /select .* from all_tab_cols/im
77
+ expect(TestEmployee.connection.columns("test_employees").map(&:name)).to eq(@column_names)
78
+ expect(@logger.logged(:debug).last).to match(/select .* from all_tab_cols/im)
262
79
  end
263
80
 
264
81
  it "should get primary key from database at first time" do
265
- TestEmployee.connection.pk_and_sequence_for('test_employees').should == ['id', nil]
266
- @logger.logged(:debug).last.should =~ /select .* from all_constraints/im
82
+ expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", "test_employees_seq"])
83
+ expect(@logger.logged(:debug).last).to match(/select .* from all_constraints/im)
267
84
  end
268
85
 
269
86
  it "should get primary key from database at first time" do
270
- TestEmployee.connection.pk_and_sequence_for('test_employees').should == ['id', nil]
87
+ expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", "test_employees_seq"])
271
88
  @logger.clear(:debug)
272
- TestEmployee.connection.pk_and_sequence_for('test_employees').should == ['id', nil]
273
- @logger.logged(:debug).last.should =~ /select .* from all_constraints/im
89
+ expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", "test_employees_seq"])
90
+ expect(@logger.logged(:debug).last).to match(/select .* from all_constraints/im)
274
91
  end
275
92
 
276
93
  it "should have correct sql types when 2 models are using the same table and AR query cache is enabled" do
277
94
  @conn.cache do
278
- TestEmployee.columns.map(&:sql_type).should == @column_sql_types
279
- TestEmployee2.columns.map(&:sql_type).should == @column_sql_types
280
- end
281
- end
282
-
283
- end
284
-
285
- describe "with column caching" do
286
-
287
- before(:each) do
288
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = true
289
- end
290
-
291
- it "should get columns from database at first time" do
292
- TestEmployee.connection.columns('test_employees').map(&:name).should == @column_names
293
- @logger.logged(:debug).last.should =~ /select .* from all_tab_cols/im
294
- end
295
-
296
- it "should get columns from cache at second time" do
297
- TestEmployee.connection.columns('test_employees')
298
- @logger.clear(:debug)
299
- TestEmployee.connection.columns('test_employees').map(&:name).should == @column_names
300
- @logger.logged(:debug).last.should be_blank
301
- end
302
-
303
- it "should get primary key from database at first time" do
304
- TestEmployee.connection.pk_and_sequence_for('test_employees').should == ['id', nil]
305
- @logger.logged(:debug).last.should =~ /select .* from all_constraints/im
306
- end
307
-
308
- it "should get primary key from cache at first time" do
309
- TestEmployee.connection.pk_and_sequence_for('test_employees').should == ['id', nil]
310
- @logger.clear(:debug)
311
- TestEmployee.connection.pk_and_sequence_for('test_employees').should == ['id', nil]
312
- @logger.logged(:debug).last.should be_blank
313
- end
314
-
315
- it "should store primary key as nil in cache at first time for table without primary key" do
316
- TestEmployee.connection.pk_and_sequence_for('test_employees_without_pk').should == nil
317
- @logger.clear(:debug)
318
- TestEmployee.connection.pk_and_sequence_for('test_employees_without_pk').should == nil
319
- @logger.logged(:debug).last.should be_blank
320
- end
321
-
322
- end
323
-
324
- end
325
-
326
- describe "without composite_primary_keys" do
327
-
328
- before(:all) do
329
- @conn = ActiveRecord::Base.connection
330
- @conn.execute "DROP TABLE test_employees" rescue nil
331
- @conn.execute <<-SQL
332
- CREATE TABLE test_employees (
333
- employee_id NUMBER PRIMARY KEY,
334
- name VARCHAR2(50)
335
- )
336
- SQL
337
- Object.send(:remove_const, 'CompositePrimaryKeys') if defined?(CompositePrimaryKeys)
338
- class ::TestEmployee < ActiveRecord::Base
339
- if self.respond_to?(:primary_key=)
340
- self.primary_key = :employee_id
341
- else
342
- set_primary_key :employee_id
343
- end
344
- end
345
- end
346
-
347
- after(:all) do
348
- Object.send(:remove_const, "TestEmployee")
349
- @conn.execute "DROP TABLE test_employees"
350
- ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
351
- end
352
-
353
- it "should tell ActiveRecord that count distinct is supported" do
354
- ActiveRecord::Base.connection.supports_count_distinct?.should be_true
355
- end
356
-
357
- it "should execute correct SQL COUNT DISTINCT statement" do
358
- lambda { TestEmployee.count(:employee_id, :distinct => true) }.should_not raise_error
359
- end
360
-
361
- end
362
-
363
-
364
- describe "reserved words column quoting" do
365
-
366
- before(:all) do
367
- schema_define do
368
- create_table :test_reserved_words do |t|
369
- t.string :varchar2
370
- t.integer :integer
371
- t.text :comment
372
- end
373
- end
374
- class ::TestReservedWord < ActiveRecord::Base; end
375
- end
376
-
377
- after(:all) do
378
- schema_define do
379
- drop_table :test_reserved_words
380
- end
381
- Object.send(:remove_const, "TestReservedWord")
382
- ActiveRecord::Base.table_name_prefix = nil
383
- ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
384
- end
385
-
386
- before(:each) do
387
- set_logger
388
- end
389
-
390
- after(:each) do
391
- clear_logger
392
- end
393
-
394
- it "should create table" do
395
- [:varchar2, :integer, :comment].each do |attr|
396
- TestReservedWord.columns_hash[attr.to_s].name.should == attr.to_s
397
- end
398
- end
399
-
400
- it "should create record" do
401
- attrs = {
402
- :varchar2 => 'dummy',
403
- :integer => 1,
404
- :comment => 'dummy'
405
- }
406
- record = TestReservedWord.create!(attrs)
407
- record.reload
408
- attrs.each do |k, v|
409
- record.send(k).should == v
410
- end
411
- end
412
-
413
- it "should remove double quotes in column quoting" do
414
- ActiveRecord::Base.connection.quote_column_name('aaa "bbb" ccc').should == '"aaa bbb ccc"'
415
- end
416
-
417
- end
418
-
419
- describe "valid table names" do
420
- before(:all) do
421
- @adapter = ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
422
- end
423
-
424
- it "should be valid with letters and digits" do
425
- @adapter.valid_table_name?("abc_123").should be_true
426
- end
427
-
428
- it "should be valid with schema name" do
429
- @adapter.valid_table_name?("abc_123.def_456").should be_true
430
- end
431
-
432
- it "should be valid with $ in name" do
433
- @adapter.valid_table_name?("sys.v$session").should be_true
434
- end
435
-
436
- it "should be valid with upcase schema name" do
437
- @adapter.valid_table_name?("ABC_123.DEF_456").should be_true
438
- end
439
-
440
- it "should be valid with irregular schema name and database links" do
441
- @adapter.valid_table_name?('abc$#_123.abc$#_123@abc$#@._123').should be_true
442
- end
443
-
444
- it "should not be valid with two dots in name" do
445
- @adapter.valid_table_name?("abc_123.def_456.ghi_789").should be_false
446
- end
447
-
448
- it "should not be valid with invalid characters" do
449
- @adapter.valid_table_name?("warehouse-things").should be_false
450
- end
451
-
452
- it "should not be valid with for camel-case" do
453
- @adapter.valid_table_name?("Abc").should be_false
454
- @adapter.valid_table_name?("aBc").should be_false
455
- @adapter.valid_table_name?("abC").should be_false
456
- end
457
-
458
- it "should not be valid for names > 30 characters" do
459
- @adapter.valid_table_name?("a" * 31).should be_false
460
- end
461
-
462
- it "should not be valid for schema names > 30 characters" do
463
- @adapter.valid_table_name?(("a" * 31) + ".validname").should be_false
464
- end
465
-
466
- it "should not be valid for database links > 128 characters" do
467
- @adapter.valid_table_name?("name@" + "a" * 129).should be_false
468
- end
469
-
470
- it "should not be valid for names that do not begin with alphabetic characters" do
471
- @adapter.valid_table_name?("1abc").should be_false
472
- @adapter.valid_table_name?("_abc").should be_false
473
- @adapter.valid_table_name?("abc.1xyz").should be_false
474
- @adapter.valid_table_name?("abc._xyz").should be_false
475
- end
476
- end
477
-
478
- describe "table quoting" do
479
-
480
- def create_warehouse_things_table
481
- ActiveRecord::Schema.define do
482
- suppress_messages do
483
- create_table "warehouse-things" do |t|
484
- t.string :name
485
- t.integer :foo
486
- end
487
- end
488
- end
489
- end
490
-
491
- def create_camel_case_table
492
- ActiveRecord::Schema.define do
493
- suppress_messages do
494
- create_table "CamelCase" do |t|
495
- t.string :name
496
- t.integer :foo
497
- end
498
- end
499
- end
500
- end
501
-
502
- before(:all) do
503
- @conn = ActiveRecord::Base.connection
504
- end
505
-
506
- after(:each) do
507
- ActiveRecord::Schema.define do
508
- suppress_messages do
509
- drop_table "warehouse-things" rescue nil
510
- drop_table "CamelCase" rescue nil
511
- end
512
- end
513
- Object.send(:remove_const, "WarehouseThing") rescue nil
514
- Object.send(:remove_const, "CamelCase") rescue nil
515
- end
516
-
517
- it "should allow creation of a table with non alphanumeric characters" do
518
- create_warehouse_things_table
519
- class ::WarehouseThing < ActiveRecord::Base
520
- if self.respond_to?(:table_name=)
521
- self.table_name = "warehouse-things"
522
- else
523
- set_table_name "warehouse-things"
524
- end
525
- end
526
-
527
- wh = WarehouseThing.create!(:name => "Foo", :foo => 2)
528
- wh.id.should_not be_nil
529
-
530
- @conn.tables.should include("warehouse-things")
531
- end
532
-
533
- it "should allow creation of a table with CamelCase name" do
534
- create_camel_case_table
535
- class ::CamelCase < ActiveRecord::Base
536
- if self.respond_to?(:table_name=)
537
- self.table_name = "CamelCase"
538
- else
539
- set_table_name "CamelCase"
95
+ expect(TestEmployee.columns.map(&:sql_type)).to eq(@column_sql_types)
96
+ expect(TestEmployee2.columns.map(&:sql_type)).to eq(@column_sql_types)
540
97
  end
541
98
  end
542
-
543
- cc = CamelCase.create!(:name => "Foo", :foo => 2)
544
- cc.id.should_not be_nil
545
-
546
- @conn.tables.should include("CamelCase")
547
99
  end
548
-
549
100
  end
550
101
 
551
102
  describe "access table over database link" do
@@ -553,12 +104,12 @@ describe "OracleEnhancedAdapter" do
553
104
  @conn = ActiveRecord::Base.connection
554
105
  @db_link = "db_link"
555
106
  @sys_conn = ActiveRecord::Base.oracle_enhanced_connection(SYSTEM_CONNECTION_PARAMS)
556
- @sys_conn.drop_table :test_posts rescue nil
107
+ @sys_conn.drop_table :test_posts, if_exists: true
557
108
  @sys_conn.create_table :test_posts do |t|
558
109
  t.string :title
559
110
  # cannot update LOBs over database link
560
111
  t.string :body
561
- t.timestamps
112
+ t.timestamps null: true
562
113
  end
563
114
  @db_link_username = SYSTEM_CONNECTION_PARAMS[:username]
564
115
  @db_link_password = SYSTEM_CONNECTION_PARAMS[:password]
@@ -569,34 +120,30 @@ describe "OracleEnhancedAdapter" do
569
120
  @conn.execute "CREATE OR REPLACE SYNONYM test_posts_seq FOR test_posts_seq@#{@db_link}"
570
121
  class ::TestPost < ActiveRecord::Base
571
122
  end
572
- if TestPost.respond_to?(:table_name=)
573
- TestPost.table_name = "test_posts"
574
- else
575
- TestPost.set_table_name "test_posts"
576
- end
123
+ TestPost.table_name = "test_posts"
577
124
  end
578
125
 
579
126
  after(:all) do
580
127
  @conn.execute "DROP SYNONYM test_posts"
581
128
  @conn.execute "DROP SYNONYM test_posts_seq"
582
129
  @conn.execute "DROP DATABASE LINK #{@db_link}" rescue nil
583
- @sys_conn.drop_table :test_posts rescue nil
130
+ @sys_conn.drop_table :test_posts, if_exists: true
584
131
  Object.send(:remove_const, "TestPost") rescue nil
585
- ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
132
+ ActiveRecord::Base.clear_cache!
586
133
  end
587
134
 
588
135
  it "should verify database link" do
589
- @conn.select_value("select * from dual@#{@db_link}") == 'X'
136
+ @conn.select_value("select * from dual@#{@db_link}") == "X"
590
137
  end
591
138
 
592
139
  it "should get column names" do
593
- TestPost.column_names.should == ["id", "title", "body", "created_at", "updated_at"]
140
+ expect(TestPost.column_names).to eq(["id", "title", "body", "created_at", "updated_at"])
594
141
  end
595
142
 
596
143
  it "should create record" do
597
- p = TestPost.create(:title => "Title", :body => "Body")
598
- p.id.should_not be_nil
599
- TestPost.find(p.id).should_not be_nil
144
+ p = TestPost.create(title: "Title", body: "Body")
145
+ expect(p.id).not_to be_nil
146
+ expect(TestPost.find(p.id)).not_to be_nil
600
147
  end
601
148
 
602
149
  end
@@ -608,39 +155,39 @@ describe "OracleEnhancedAdapter" do
608
155
 
609
156
  it "should get current database name" do
610
157
  # get database name if using //host:port/database connection string
611
- database_name = CONNECTION_PARAMS[:database].split('/').last
612
- @conn.current_database.upcase.should == database_name.upcase
158
+ database_name = CONNECTION_PARAMS[:database].split("/").last
159
+ expect(@conn.current_database.upcase).to eq(database_name.upcase)
613
160
  end
614
161
 
615
162
  it "should get current database session user" do
616
- @conn.current_user.upcase.should == CONNECTION_PARAMS[:username].upcase
163
+ expect(@conn.current_user.upcase).to eq(CONNECTION_PARAMS[:username].upcase)
617
164
  end
618
165
  end
619
166
 
620
167
  describe "temporary tables" do
621
168
  before(:all) do
622
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:table] = 'UNUSED'
623
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = 'UNUSED'
169
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:table] = "UNUSED"
170
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = "UNUSED"
624
171
  @conn = ActiveRecord::Base.connection
625
172
  end
626
173
  after(:all) do
627
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces={}
174
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces = {}
628
175
  end
629
176
 
630
177
  after(:each) do
631
- @conn.drop_table :foos rescue nil
178
+ @conn.drop_table :foos, if_exists: true
632
179
  end
633
180
  it "should create ok" do
634
- @conn.create_table :foos, :temporary => true, :id => false do |t|
181
+ @conn.create_table :foos, temporary: true, id: false do |t|
635
182
  t.integer :id
636
183
  t.text :bar
637
184
  end
638
185
  end
639
186
  it "should show up as temporary" do
640
- @conn.create_table :foos, :temporary => true, :id => false do |t|
187
+ @conn.create_table :foos, temporary: true, id: false do |t|
641
188
  t.integer :id
642
189
  end
643
- @conn.temporary_table?("foos").should be_true
190
+ expect(@conn.temporary_table?("foos")).to be_truthy
644
191
  end
645
192
  end
646
193
 
@@ -665,8 +212,8 @@ describe "OracleEnhancedAdapter" do
665
212
  @ids = (1..1010).to_a
666
213
  TestPost.transaction do
667
214
  @ids.each do |id|
668
- TestPost.create!(:id => id, :title => "Title #{id}")
669
- TestComment.create!(:test_post_id => id, :description => "Description #{id}")
215
+ TestPost.create!(id: id, title: "Title #{id}")
216
+ TestComment.create!(test_post_id: id, description: "Description #{id}")
670
217
  end
671
218
  end
672
219
  end
@@ -678,22 +225,22 @@ describe "OracleEnhancedAdapter" do
678
225
  end
679
226
  Object.send(:remove_const, "TestPost")
680
227
  Object.send(:remove_const, "TestComment")
681
- ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
228
+ ActiveRecord::Base.clear_cache!
682
229
  end
683
230
 
684
231
  it "should load included association with more than 1000 records" do
685
- posts = TestPost.includes(:test_comments).all
686
- posts.size.should == @ids.size
232
+ posts = TestPost.includes(:test_comments).to_a
233
+ expect(posts.size).to eq(@ids.size)
687
234
  end
688
235
 
689
- end if ENV['RAILS_GEM_VERSION'] >= '3.1'
236
+ end
690
237
 
691
238
  describe "with statement pool" do
692
239
  before(:all) do
693
- ActiveRecord::Base.establish_connection(CONNECTION_PARAMS.merge(:statement_limit => 3))
240
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS.merge(statement_limit: 3))
694
241
  @conn = ActiveRecord::Base.connection
695
242
  schema_define do
696
- drop_table :test_posts rescue nil
243
+ drop_table :test_posts, if_exists: true
697
244
  create_table :test_posts
698
245
  end
699
246
  class ::TestPost < ActiveRecord::Base
@@ -710,43 +257,40 @@ describe "OracleEnhancedAdapter" do
710
257
  drop_table :test_posts
711
258
  end
712
259
  Object.send(:remove_const, "TestPost")
713
- ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
260
+ ActiveRecord::Base.clear_cache!
714
261
  end
715
262
 
716
263
  it "should clear older cursors when statement limit is reached" do
717
- pk = TestPost.columns.find { |c| c.primary }
718
- sub = @conn.substitute_at(pk, 0)
719
- binds = [[pk, 1]]
720
-
721
- lambda {
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
267
+ expect {
722
268
  4.times do |i|
723
- @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)
724
270
  end
725
- }.should change(@statements, :length).by(+3)
271
+ }.to change(@statements, :length).by(+3)
726
272
  end
727
273
 
728
274
  it "should cache UPDATE statements with bind variables" do
729
- lambda {
730
- pk = TestPost.columns.find { |c| c.primary }
731
- sub = @conn.substitute_at(pk, 0)
732
- binds = [[pk, 1]]
733
- @conn.exec_update("UPDATE test_posts SET id = #{sub}", "SQL", binds)
734
- }.should change(@statements, :length).by(+1)
275
+ expect {
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)
278
+ }.to change(@statements, :length).by(+1)
735
279
  end
736
280
 
737
281
  it "should not cache UPDATE statements without bind variables" do
738
- lambda {
282
+ expect {
739
283
  binds = []
740
284
  @conn.exec_update("UPDATE test_posts SET id = 1", "SQL", binds)
741
- }.should_not change(@statements, :length)
285
+ }.not_to change(@statements, :length)
742
286
  end
743
- end if ENV['RAILS_GEM_VERSION'] >= '3.1'
287
+ end
744
288
 
745
289
  describe "explain" do
746
290
  before(:all) do
747
291
  @conn = ActiveRecord::Base.connection
748
292
  schema_define do
749
- drop_table :test_posts rescue nil
293
+ drop_table :test_posts, if_exists: true
750
294
  create_table :test_posts
751
295
  end
752
296
  class ::TestPost < ActiveRecord::Base
@@ -758,21 +302,312 @@ describe "OracleEnhancedAdapter" do
758
302
  drop_table :test_posts
759
303
  end
760
304
  Object.send(:remove_const, "TestPost")
761
- ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
305
+ ActiveRecord::Base.clear_cache!
762
306
  end
763
307
 
764
308
  it "should explain query" do
765
- explain = TestPost.where(:id => 1).explain
766
- explain.should include("Cost")
767
- explain.should include("INDEX UNIQUE SCAN")
309
+ explain = TestPost.where(id: 1).explain
310
+ expect(explain).to include("Cost")
311
+ expect(explain).to include("INDEX UNIQUE SCAN")
768
312
  end
769
313
 
770
314
  it "should explain query with binds" do
771
- pk = TestPost.columns.find { |c| c.primary }
772
- sub = @conn.substitute_at(pk, 0)
773
- explain = TestPost.where(TestPost.arel_table[pk.name].eq(sub)).bind([pk, 1]).explain
774
- explain.should include("Cost")
775
- explain.should include("INDEX UNIQUE SCAN")
315
+ binds = [ActiveRecord::Relation::QueryAttribute.new("id", 1, ActiveRecord::Type::OracleEnhanced::Integer.new)]
316
+ explain = TestPost.where(id: binds).explain
317
+ expect(explain).to include("Cost")
318
+ expect(explain).to include("INDEX UNIQUE SCAN").or include("TABLE ACCESS FULL")
319
+ end
320
+ end
321
+
322
+ describe "using offset and limit" do
323
+ before(:all) do
324
+ @conn = ActiveRecord::Base.connection
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
333
+ @employee = Class.new(ActiveRecord::Base) do
334
+ self.table_name = :test_employees
335
+ end
336
+ i = 0
337
+ @employee.create!(sort_order: i += 1, first_name: "Peter", last_name: "Parker")
338
+ @employee.create!(sort_order: i += 1, first_name: "Tony", last_name: "Stark")
339
+ @employee.create!(sort_order: i += 1, first_name: "Steven", last_name: "Rogers")
340
+ @employee.create!(sort_order: i += 1, first_name: "Bruce", last_name: "Banner")
341
+ @employee.create!(sort_order: i += 1, first_name: "Natasha", last_name: "Romanova")
342
+ end
343
+
344
+ after(:all) do
345
+ @conn.drop_table :test_employees, if_exists: true
346
+ end
347
+
348
+ after(:each) do
349
+ ActiveRecord::Base.clear_cache!
350
+ end
351
+
352
+ it "should return n records with limit(n)" do
353
+ expect(@employee.limit(3).to_a.size).to be(3)
354
+ end
355
+
356
+ it "should return less than n records with limit(n) if there exist less than n records" do
357
+ expect(@employee.limit(10).to_a.size).to be(5)
358
+ end
359
+
360
+ it "should return the records starting from offset n with offset(n)" do
361
+ expect(@employee.order(:sort_order).first.first_name).to eq("Peter")
362
+ expect(@employee.order(:sort_order).offset(0).first.first_name).to eq("Peter")
363
+ expect(@employee.order(:sort_order).offset(1).first.first_name).to eq("Tony")
364
+ expect(@employee.order(:sort_order).offset(4).first.first_name).to eq("Natasha")
365
+ end
366
+ end
367
+
368
+ describe "valid_type?" do
369
+ before(:all) do
370
+ @conn = ActiveRecord::Base.connection
371
+ schema_define do
372
+ create_table :test_employees, force: true do |t|
373
+ t.string :first_name, limit: 20
374
+ end
375
+ end
376
+ end
377
+
378
+ after(:all) do
379
+ @conn.drop_table :test_employees, if_exists: true
380
+ end
381
+
382
+ it "returns true when passed a valid type" do
383
+ column = @conn.columns("test_employees").find { |col| col.name == "first_name" }
384
+ expect(@conn.valid_type?(column.type)).to be true
385
+ end
386
+
387
+ it "returns false when passed an invalid type" do
388
+ expect(@conn.valid_type?(:foobar)).to be false
389
+ end
390
+ end
391
+
392
+ describe "serialized column" do
393
+ before(:all) do
394
+ schema_define do
395
+ create_table :test_serialized_columns do |t|
396
+ t.text :serialized
397
+ end
398
+ end
399
+ class ::TestSerializedColumn < ActiveRecord::Base
400
+ serialize :serialized, Array
401
+ end
402
+ end
403
+
404
+ after(:all) do
405
+ schema_define do
406
+ drop_table :test_serialized_columns
407
+ end
408
+ Object.send(:remove_const, "TestSerializedColumn")
409
+ ActiveRecord::Base.table_name_prefix = nil
410
+ ActiveRecord::Base.clear_cache!
411
+ end
412
+
413
+ before(:each) do
414
+ set_logger
415
+ end
416
+
417
+ after(:each) do
418
+ clear_logger
419
+ end
420
+
421
+ it "should serialize" do
422
+ new_value = "new_value"
423
+ serialized_column = TestSerializedColumn.new
424
+
425
+ expect(serialized_column.serialized).to eq([])
426
+ serialized_column.serialized << new_value
427
+ expect(serialized_column.serialized).to eq([new_value])
428
+ serialized_column.save
429
+ expect(serialized_column.save!).to eq(true)
430
+
431
+ serialized_column.reload
432
+ expect(serialized_column.serialized).to eq([new_value])
433
+ serialized_column.serialized = []
434
+ expect(serialized_column.save!).to eq(true)
435
+ end
436
+ end
437
+
438
+ describe "quoting" do
439
+ before(:all) do
440
+ schema_define do
441
+ create_table :test_logs, force: true do |t|
442
+ t.timestamp :send_time
443
+ end
444
+ end
445
+ class TestLog < ActiveRecord::Base
446
+ validates_uniqueness_of :send_time
447
+ end
448
+ end
449
+
450
+ after(:all) do
451
+ schema_define do
452
+ drop_table :test_logs
453
+ end
454
+ Object.send(:remove_const, "TestLog")
455
+ ActiveRecord::Base.clear_cache! if ActiveRecord::Base.respond_to?(:"clear_cache!")
456
+ end
457
+
458
+ it "should create records including Time" do
459
+ TestLog.create! send_time: Time.now + 1.seconds
460
+ TestLog.create! send_time: Time.now + 2.seconds
461
+ expect(TestLog.count).to eq 2
462
+ end
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"\]\]/)
776
560
  end
777
- end if ENV['RAILS_GEM_VERSION'] >= '3.2'
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
+ Thread.report_on_exception, @original_report_on_exception = false, Thread.report_on_exception if Thread.respond_to?(:report_on_exception)
574
+ end
575
+
576
+ it "Raises Deadlocked when a deadlock is encountered" do
577
+ skip "Skip temporary due to #1599" if ActiveRecord::Base.connection.supports_fetch_first_n_rows_and_offset?
578
+ expect {
579
+ barrier = Concurrent::CyclicBarrier.new(2)
580
+
581
+ t1 = TestPost.create(title: "one")
582
+ t2 = TestPost.create(title: "two")
583
+
584
+ thread = Thread.new do
585
+ TestPost.transaction do
586
+ t1.lock!
587
+ barrier.wait
588
+ t2.update_attributes(title: "one")
589
+ end
590
+ end
591
+
592
+ begin
593
+ TestPost.transaction do
594
+ t2.lock!
595
+ barrier.wait
596
+ t1.update_attributes(title: "two")
597
+ end
598
+ ensure
599
+ thread.join
600
+ end
601
+ }.to raise_error(ActiveRecord::Deadlocked)
602
+ end
603
+
604
+ after(:all) do
605
+ schema_define do
606
+ drop_table :test_posts
607
+ end
608
+ Object.send(:remove_const, "TestPost") rescue nil
609
+ ActiveRecord::Base.clear_cache!
610
+ Thread.report_on_exception = @original_report_on_exception if Thread.respond_to?(:report_on_exception)
611
+ end
612
+ end
778
613
  end