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.
- checksums.yaml +5 -5
- data/History.md +1162 -2
- data/README.md +567 -155
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +3 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +19 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +132 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +345 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +52 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +280 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +64 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +59 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +538 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +38 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/lob.rb +46 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +435 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +44 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +196 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +164 -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 +79 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +194 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +709 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +28 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +353 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +33 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +3 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +385 -1083
- data/lib/active_record/type/oracle_enhanced/boolean.rb +20 -0
- data/lib/active_record/type/oracle_enhanced/integer.rb +15 -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 +5 -13
- data/spec/active_record/connection_adapters/{oracle_enhanced_emulate_oracle_adapter_spec.rb → emulation/oracle_adapter_spec.rb} +5 -4
- data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +469 -0
- data/spec/active_record/connection_adapters/{oracle_enhanced_context_index_spec.rb → oracle_enhanced/context_index_spec.rb} +140 -128
- data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +112 -0
- data/spec/active_record/connection_adapters/{oracle_enhanced_dbms_output_spec.rb → oracle_enhanced/dbms_output_spec.rb} +13 -13
- data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +365 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/quoting_spec.rb +196 -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 +1433 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +478 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +385 -550
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +92 -1249
- data/spec/active_record/oracle_enhanced/type/binary_spec.rb +119 -0
- data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +208 -0
- data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +139 -0
- data/spec/active_record/oracle_enhanced/type/float_spec.rb +48 -0
- data/spec/active_record/oracle_enhanced/type/integer_spec.rb +91 -0
- data/spec/active_record/oracle_enhanced/type/json_spec.rb +57 -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 +122 -0
- data/spec/active_record/oracle_enhanced/type/text_spec.rb +229 -0
- data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +75 -0
- data/spec/spec_config.yaml.template +11 -0
- data/spec/spec_helper.rb +100 -93
- 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 +105 -152
- data/.rspec +0 -2
- data/Gemfile +0 -52
- data/RUNNING_TESTS.md +0 -45
- data/Rakefile +0 -59
- data/activerecord-oracle_enhanced-adapter.gemspec +0 -130
- data/lib/active_record/connection_adapters/oracle_enhanced.rake +0 -105
- data/lib/active_record/connection_adapters/oracle_enhanced_activerecord_patches.rb +0 -41
- data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +0 -121
- data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +0 -151
- data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +0 -119
- data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +0 -359
- data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +0 -25
- data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +0 -21
- data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +0 -46
- data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +0 -572
- data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +0 -497
- data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +0 -260
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +0 -227
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +0 -260
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +0 -428
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +0 -258
- data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +0 -294
- data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +0 -17
- data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +0 -1
- data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +0 -334
- data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +0 -19
- data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +0 -113
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +0 -141
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +0 -378
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +0 -440
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +0 -1400
- data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +0 -339
|
@@ -1,37 +1,4 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
-
|
|
179
|
-
|
|
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
|
-
|
|
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.
|
|
225
|
-
@conn.
|
|
226
|
-
ActiveRecord::
|
|
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
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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(
|
|
254
|
-
@logger.logged(:debug).last.
|
|
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(
|
|
75
|
+
TestEmployee.connection.columns("test_employees")
|
|
259
76
|
@logger.clear(:debug)
|
|
260
|
-
TestEmployee.connection.columns(
|
|
261
|
-
@logger.logged(:debug).last.
|
|
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(
|
|
266
|
-
@logger.logged(:debug).last.
|
|
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(
|
|
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(
|
|
273
|
-
@logger.logged(:debug).last.
|
|
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).
|
|
279
|
-
TestEmployee2.columns.map(&:sql_type).
|
|
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
|
|
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
|
-
|
|
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
|
|
130
|
+
@sys_conn.drop_table :test_posts, if_exists: true
|
|
584
131
|
Object.send(:remove_const, "TestPost") rescue nil
|
|
585
|
-
ActiveRecord::Base.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}") ==
|
|
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.
|
|
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(:
|
|
598
|
-
p.id.
|
|
599
|
-
TestPost.find(p.id).
|
|
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(
|
|
612
|
-
@conn.current_database.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.
|
|
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] =
|
|
623
|
-
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] =
|
|
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
|
|
178
|
+
@conn.drop_table :foos, if_exists: true
|
|
632
179
|
end
|
|
633
180
|
it "should create ok" do
|
|
634
|
-
@conn.create_table :foos, :
|
|
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, :
|
|
187
|
+
@conn.create_table :foos, temporary: true, id: false do |t|
|
|
641
188
|
t.integer :id
|
|
642
189
|
end
|
|
643
|
-
@conn.temporary_table?("foos").
|
|
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!(:
|
|
669
|
-
TestComment.create!(:
|
|
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!
|
|
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).
|
|
686
|
-
posts.size.
|
|
232
|
+
posts = TestPost.includes(:test_comments).to_a
|
|
233
|
+
expect(posts.size).to eq(@ids.size)
|
|
687
234
|
end
|
|
688
235
|
|
|
689
|
-
end
|
|
236
|
+
end
|
|
690
237
|
|
|
691
238
|
describe "with statement pool" do
|
|
692
239
|
before(:all) do
|
|
693
|
-
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS.merge(:
|
|
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
|
|
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!
|
|
260
|
+
ActiveRecord::Base.clear_cache!
|
|
714
261
|
end
|
|
715
262
|
|
|
716
263
|
it "should clear older cursors when statement limit is reached" do
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
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 =
|
|
269
|
+
@conn.exec_query("SELECT * FROM test_posts WHERE #{i}=#{i} AND id = :id", "SQL", binds)
|
|
724
270
|
end
|
|
725
|
-
}.
|
|
271
|
+
}.to change(@statements, :length).by(+3)
|
|
726
272
|
end
|
|
727
273
|
|
|
728
274
|
it "should cache UPDATE statements with bind variables" do
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
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
|
-
|
|
282
|
+
expect {
|
|
739
283
|
binds = []
|
|
740
284
|
@conn.exec_update("UPDATE test_posts SET id = 1", "SQL", binds)
|
|
741
|
-
}.
|
|
285
|
+
}.not_to change(@statements, :length)
|
|
742
286
|
end
|
|
743
|
-
end
|
|
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
|
|
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!
|
|
305
|
+
ActiveRecord::Base.clear_cache!
|
|
762
306
|
end
|
|
763
307
|
|
|
764
308
|
it "should explain query" do
|
|
765
|
-
explain = TestPost.where(:
|
|
766
|
-
explain.
|
|
767
|
-
explain.
|
|
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
|
-
|
|
772
|
-
|
|
773
|
-
explain
|
|
774
|
-
explain.
|
|
775
|
-
|
|
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
|
-
|
|
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
|