activerecord-oracle_enhanced-adapter 8.1.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/History.md +1971 -0
- data/License.txt +20 -0
- data/README.md +947 -0
- data/VERSION +1 -0
- data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +7 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +24 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +137 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +359 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +47 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +325 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +63 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +71 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +629 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +38 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/lob.rb +57 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +465 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +44 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +195 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +186 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +95 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +99 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +197 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +739 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +394 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +34 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +3 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +886 -0
- data/lib/active_record/type/oracle_enhanced/boolean.rb +19 -0
- data/lib/active_record/type/oracle_enhanced/character_string.rb +36 -0
- data/lib/active_record/type/oracle_enhanced/integer.rb +14 -0
- data/lib/active_record/type/oracle_enhanced/json.rb +10 -0
- data/lib/active_record/type/oracle_enhanced/national_character_string.rb +26 -0
- data/lib/active_record/type/oracle_enhanced/national_character_text.rb +36 -0
- data/lib/active_record/type/oracle_enhanced/raw.rb +25 -0
- data/lib/active_record/type/oracle_enhanced/string.rb +29 -0
- data/lib/active_record/type/oracle_enhanced/text.rb +32 -0
- data/lib/active_record/type/oracle_enhanced/timestampltz.rb +25 -0
- data/lib/active_record/type/oracle_enhanced/timestamptz.rb +25 -0
- data/lib/activerecord-oracle_enhanced-adapter.rb +25 -0
- data/lib/arel/visitors/oracle.rb +216 -0
- data/lib/arel/visitors/oracle12.rb +121 -0
- data/lib/arel/visitors/oracle_common.rb +51 -0
- data/spec/active_record/connection_adapters/emulation/oracle_adapter_spec.rb +24 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/compatibility_spec.rb +40 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/composite_spec.rb +84 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +589 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/context_index_spec.rb +431 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +122 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/dbconsole_spec.rb +63 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/dbms_output_spec.rb +69 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +362 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/quoting_spec.rb +181 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +492 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +1318 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +485 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +815 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +230 -0
- data/spec/active_record/oracle_enhanced/type/binary_spec.rb +119 -0
- data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +206 -0
- data/spec/active_record/oracle_enhanced/type/character_string_spec.rb +67 -0
- data/spec/active_record/oracle_enhanced/type/custom_spec.rb +90 -0
- data/spec/active_record/oracle_enhanced/type/decimal_spec.rb +56 -0
- data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +141 -0
- data/spec/active_record/oracle_enhanced/type/float_spec.rb +48 -0
- data/spec/active_record/oracle_enhanced/type/integer_spec.rb +101 -0
- data/spec/active_record/oracle_enhanced/type/json_spec.rb +56 -0
- data/spec/active_record/oracle_enhanced/type/national_character_string_spec.rb +55 -0
- data/spec/active_record/oracle_enhanced/type/national_character_text_spec.rb +230 -0
- data/spec/active_record/oracle_enhanced/type/raw_spec.rb +137 -0
- data/spec/active_record/oracle_enhanced/type/text_spec.rb +295 -0
- data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +107 -0
- data/spec/spec_config.yaml.template +11 -0
- data/spec/spec_helper.rb +225 -0
- data/spec/support/alter_system_set_open_cursors.sql +1 -0
- data/spec/support/alter_system_user_password.sql +2 -0
- data/spec/support/create_oracle_enhanced_users.sql +31 -0
- metadata +181 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe "OracleEnhancedAdapter date and datetime type detection based on attribute settings" do
|
|
4
|
+
before(:all) do
|
|
5
|
+
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
|
6
|
+
@conn = ActiveRecord::Base.connection
|
|
7
|
+
@conn.execute "DROP TABLE test_employees" rescue nil
|
|
8
|
+
@conn.execute "DROP SEQUENCE test_employees_seq" rescue nil
|
|
9
|
+
@conn.execute <<~SQL
|
|
10
|
+
CREATE TABLE test_employees (
|
|
11
|
+
employee_id NUMBER(6,0) PRIMARY KEY,
|
|
12
|
+
first_name VARCHAR2(20),
|
|
13
|
+
last_name VARCHAR2(25),
|
|
14
|
+
email VARCHAR2(25),
|
|
15
|
+
phone_number VARCHAR2(20),
|
|
16
|
+
hire_date DATE,
|
|
17
|
+
job_id NUMBER(6,0),
|
|
18
|
+
salary NUMBER(8,2),
|
|
19
|
+
commission_pct NUMBER(2,2),
|
|
20
|
+
manager_id NUMBER(6,0),
|
|
21
|
+
department_id NUMBER(4,0),
|
|
22
|
+
created_at DATE,
|
|
23
|
+
updated_at DATE
|
|
24
|
+
)
|
|
25
|
+
SQL
|
|
26
|
+
@conn.execute <<~SQL
|
|
27
|
+
CREATE SEQUENCE test_employees_seq MINVALUE 1
|
|
28
|
+
INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
|
|
29
|
+
SQL
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
after(:all) do
|
|
33
|
+
@conn.execute "DROP TABLE test_employees"
|
|
34
|
+
@conn.execute "DROP SEQUENCE test_employees_seq"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe "/ DATE values from ActiveRecord model" do
|
|
38
|
+
before(:each) do
|
|
39
|
+
class ::TestEmployee < ActiveRecord::Base
|
|
40
|
+
self.primary_key = "employee_id"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def create_test_employee(params = {})
|
|
45
|
+
@today = params[:today] || Date.new(2008, 8, 19)
|
|
46
|
+
@now = params[:now] || Time.local(2008, 8, 19, 17, 03, 59)
|
|
47
|
+
@employee = TestEmployee.create(
|
|
48
|
+
first_name: "First",
|
|
49
|
+
last_name: "Last",
|
|
50
|
+
hire_date: @today,
|
|
51
|
+
created_at: @now
|
|
52
|
+
)
|
|
53
|
+
@employee.reload
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
after(:each) do
|
|
57
|
+
Object.send(:remove_const, "TestEmployee")
|
|
58
|
+
ActiveRecord::Base.clear_cache!
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "should return Date value from DATE column by default" do
|
|
62
|
+
create_test_employee
|
|
63
|
+
expect(@employee.hire_date.class).to eq(Date)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "should return Date value from DATE column with old date value by default" do
|
|
67
|
+
create_test_employee(today: Date.new(1900, 1, 1))
|
|
68
|
+
expect(@employee.hire_date.class).to eq(Date)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "should return Time value from DATE column if attribute is set to :datetime" do
|
|
72
|
+
class ::TestEmployee < ActiveRecord::Base
|
|
73
|
+
attribute :hire_date, :datetime
|
|
74
|
+
end
|
|
75
|
+
create_test_employee
|
|
76
|
+
expect(@employee.hire_date.class).to eq(Time)
|
|
77
|
+
# change to current time with hours, minutes and seconds
|
|
78
|
+
@employee.hire_date = @now
|
|
79
|
+
@employee.save!
|
|
80
|
+
@employee.reload
|
|
81
|
+
expect(@employee.hire_date.class).to eq(Time)
|
|
82
|
+
expect(@employee.hire_date).to eq(@now)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe "OracleEnhancedAdapter assign string to :date and :datetime columns" do
|
|
88
|
+
include SchemaSpecHelper
|
|
89
|
+
|
|
90
|
+
before(:all) do
|
|
91
|
+
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
|
92
|
+
@conn = ActiveRecord::Base.connection
|
|
93
|
+
schema_define do
|
|
94
|
+
create_table :test_employees, force: true do |t|
|
|
95
|
+
t.string :first_name, limit: 20
|
|
96
|
+
t.string :last_name, limit: 25
|
|
97
|
+
t.date :hire_date
|
|
98
|
+
t.date :last_login_at
|
|
99
|
+
t.datetime :last_login_at_ts
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
class ::TestEmployee < ActiveRecord::Base
|
|
103
|
+
attribute :last_login_at, :datetime
|
|
104
|
+
end
|
|
105
|
+
@today = Date.new(2008, 6, 28)
|
|
106
|
+
@today_iso = "2008-06-28"
|
|
107
|
+
@today_nls = "28.06.2008"
|
|
108
|
+
@nls_date_format = "%d.%m.%Y"
|
|
109
|
+
@now = Time.local(2008, 6, 28, 13, 34, 33)
|
|
110
|
+
@now_iso = "2008-06-28 13:34:33"
|
|
111
|
+
@now_nls = "28.06.2008 13:34:33"
|
|
112
|
+
@nls_time_format = "%d.%m.%Y %H:%M:%S"
|
|
113
|
+
@now_nls_with_tz = "28.06.2008 13:34:33+05:00"
|
|
114
|
+
@nls_with_tz_time_format = "%d.%m.%Y %H:%M:%S%Z"
|
|
115
|
+
@now_with_tz = Time.parse @now_nls_with_tz
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
after(:all) do
|
|
119
|
+
Object.send(:remove_const, "TestEmployee")
|
|
120
|
+
@conn.drop_table :test_employees, if_exists: true
|
|
121
|
+
ActiveRecord::Base.clear_cache!
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
after(:each) do
|
|
125
|
+
ActiveRecord.default_timezone = :utc
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "should assign ISO string to date column" do
|
|
129
|
+
@employee = TestEmployee.create(
|
|
130
|
+
first_name: "First",
|
|
131
|
+
last_name: "Last",
|
|
132
|
+
hire_date: @today_iso
|
|
133
|
+
)
|
|
134
|
+
expect(@employee.hire_date).to eq(@today)
|
|
135
|
+
@employee.reload
|
|
136
|
+
expect(@employee.hire_date).to eq(@today)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it "should assign NLS string to date column" do
|
|
140
|
+
@employee = TestEmployee.create(
|
|
141
|
+
first_name: "First",
|
|
142
|
+
last_name: "Last",
|
|
143
|
+
hire_date: @today_nls
|
|
144
|
+
)
|
|
145
|
+
expect(@employee.hire_date).to eq(@today)
|
|
146
|
+
@employee.reload
|
|
147
|
+
expect(@employee.hire_date).to eq(@today)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it "should assign ISO time string to date column" do
|
|
151
|
+
@employee = TestEmployee.create(
|
|
152
|
+
first_name: "First",
|
|
153
|
+
last_name: "Last",
|
|
154
|
+
hire_date: @now_iso
|
|
155
|
+
)
|
|
156
|
+
expect(@employee.hire_date).to eq(@today)
|
|
157
|
+
@employee.reload
|
|
158
|
+
expect(@employee.hire_date).to eq(@today)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it "should assign NLS time string to date column" do
|
|
162
|
+
@employee = TestEmployee.create(
|
|
163
|
+
first_name: "First",
|
|
164
|
+
last_name: "Last",
|
|
165
|
+
hire_date: @now_nls
|
|
166
|
+
)
|
|
167
|
+
expect(@employee.hire_date).to eq(@today)
|
|
168
|
+
@employee.reload
|
|
169
|
+
expect(@employee.hire_date).to eq(@today)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it "should assign ISO time string to datetime column" do
|
|
173
|
+
ActiveRecord.default_timezone = :local
|
|
174
|
+
@employee = TestEmployee.create(
|
|
175
|
+
first_name: "First",
|
|
176
|
+
last_name: "Last",
|
|
177
|
+
last_login_at: @now_iso
|
|
178
|
+
)
|
|
179
|
+
expect(@employee.last_login_at).to eq(@now)
|
|
180
|
+
@employee.reload
|
|
181
|
+
expect(@employee.last_login_at).to eq(@now)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it "should assign NLS time string to datetime column" do
|
|
185
|
+
ActiveRecord.default_timezone = :local
|
|
186
|
+
@employee = TestEmployee.create(
|
|
187
|
+
first_name: "First",
|
|
188
|
+
last_name: "Last",
|
|
189
|
+
last_login_at: @now_nls
|
|
190
|
+
)
|
|
191
|
+
expect(@employee.last_login_at).to eq(@now)
|
|
192
|
+
@employee.reload
|
|
193
|
+
expect(@employee.last_login_at).to eq(@now)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it "should assign NLS time string with time zone to datetime column" do
|
|
197
|
+
@employee = TestEmployee.create(
|
|
198
|
+
first_name: "First",
|
|
199
|
+
last_name: "Last",
|
|
200
|
+
last_login_at: @now_nls_with_tz
|
|
201
|
+
)
|
|
202
|
+
expect(@employee.last_login_at).to eq(@now_with_tz)
|
|
203
|
+
@employee.reload
|
|
204
|
+
expect(@employee.last_login_at).to eq(@now_with_tz)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it "should assign ISO date string to datetime column" do
|
|
208
|
+
ActiveRecord.default_timezone = :local
|
|
209
|
+
@employee = TestEmployee.create(
|
|
210
|
+
first_name: "First",
|
|
211
|
+
last_name: "Last",
|
|
212
|
+
last_login_at: @today_iso
|
|
213
|
+
)
|
|
214
|
+
expect(@employee.last_login_at).to eq(@today.to_time)
|
|
215
|
+
@employee.reload
|
|
216
|
+
expect(@employee.last_login_at).to eq(@today.to_time)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it "should assign NLS date string to datetime column" do
|
|
220
|
+
ActiveRecord.default_timezone = :local
|
|
221
|
+
@employee = TestEmployee.create(
|
|
222
|
+
first_name: "First",
|
|
223
|
+
last_name: "Last",
|
|
224
|
+
last_login_at: @today_nls
|
|
225
|
+
)
|
|
226
|
+
expect(@employee.last_login_at).to eq(@today.to_time)
|
|
227
|
+
@employee.reload
|
|
228
|
+
expect(@employee.last_login_at).to eq(@today.to_time)
|
|
229
|
+
end
|
|
230
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe "OracleEnhancedAdapter handling of BLOB columns" do
|
|
4
|
+
include SchemaSpecHelper
|
|
5
|
+
|
|
6
|
+
before(:all) do
|
|
7
|
+
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
|
8
|
+
@conn = ActiveRecord::Base.connection
|
|
9
|
+
schema_define do
|
|
10
|
+
create_table :test_employees, force: true do |t|
|
|
11
|
+
t.string :first_name, limit: 20
|
|
12
|
+
t.string :last_name, limit: 25
|
|
13
|
+
t.binary :binary_data
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
class ::TestEmployee < ActiveRecord::Base
|
|
17
|
+
end
|
|
18
|
+
@binary_data = "\0\1\2\3\4\5\6\7\8\9" * 10000
|
|
19
|
+
@binary_data2 = "\1\2\3\4\5\6\7\8\9\0" * 10000
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
after(:all) do
|
|
23
|
+
@conn.drop_table :test_employees, if_exists: true
|
|
24
|
+
Object.send(:remove_const, "TestEmployee")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
after(:each) do
|
|
28
|
+
ActiveRecord::Base.clear_cache!
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should create record with BLOB data" do
|
|
32
|
+
@employee = TestEmployee.create!(
|
|
33
|
+
first_name: "First",
|
|
34
|
+
last_name: "Last",
|
|
35
|
+
binary_data: @binary_data
|
|
36
|
+
)
|
|
37
|
+
@employee.reload
|
|
38
|
+
expect(@employee.binary_data).to eq(@binary_data)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should update record with BLOB data" do
|
|
42
|
+
@employee = TestEmployee.create!(
|
|
43
|
+
first_name: "First",
|
|
44
|
+
last_name: "Last"
|
|
45
|
+
)
|
|
46
|
+
@employee.reload
|
|
47
|
+
expect(@employee.binary_data).to be_nil
|
|
48
|
+
@employee.binary_data = @binary_data
|
|
49
|
+
@employee.save!
|
|
50
|
+
@employee.reload
|
|
51
|
+
expect(@employee.binary_data).to eq(@binary_data)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "should update record with zero-length BLOB data" do
|
|
55
|
+
@employee = TestEmployee.create!(
|
|
56
|
+
first_name: "First",
|
|
57
|
+
last_name: "Last"
|
|
58
|
+
)
|
|
59
|
+
@employee.reload
|
|
60
|
+
expect(@employee.binary_data).to be_nil
|
|
61
|
+
@employee.binary_data = ""
|
|
62
|
+
@employee.save!
|
|
63
|
+
@employee.reload
|
|
64
|
+
expect(@employee.binary_data).to eq("")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "should update record that has existing BLOB data with different BLOB data" do
|
|
68
|
+
@employee = TestEmployee.create!(
|
|
69
|
+
first_name: "First",
|
|
70
|
+
last_name: "Last",
|
|
71
|
+
binary_data: @binary_data
|
|
72
|
+
)
|
|
73
|
+
@employee.reload
|
|
74
|
+
@employee.binary_data = @binary_data2
|
|
75
|
+
@employee.save!
|
|
76
|
+
@employee.reload
|
|
77
|
+
expect(@employee.binary_data).to eq(@binary_data2)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should update record that has existing BLOB data with nil" do
|
|
81
|
+
@employee = TestEmployee.create!(
|
|
82
|
+
first_name: "First",
|
|
83
|
+
last_name: "Last",
|
|
84
|
+
binary_data: @binary_data
|
|
85
|
+
)
|
|
86
|
+
@employee.reload
|
|
87
|
+
@employee.binary_data = nil
|
|
88
|
+
@employee.save!
|
|
89
|
+
@employee.reload
|
|
90
|
+
expect(@employee.binary_data).to be_nil
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "should update record that has existing BLOB data with zero-length BLOB data" do
|
|
94
|
+
@employee = TestEmployee.create!(
|
|
95
|
+
first_name: "First",
|
|
96
|
+
last_name: "Last",
|
|
97
|
+
binary_data: @binary_data
|
|
98
|
+
)
|
|
99
|
+
@employee.reload
|
|
100
|
+
@employee.binary_data = ""
|
|
101
|
+
@employee.save!
|
|
102
|
+
@employee.reload
|
|
103
|
+
expect(@employee.binary_data).to eq("")
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "should update record that has zero-length BLOB data with non-empty BLOB data" do
|
|
107
|
+
@employee = TestEmployee.create!(
|
|
108
|
+
first_name: "First",
|
|
109
|
+
last_name: "Last",
|
|
110
|
+
binary_data: ""
|
|
111
|
+
)
|
|
112
|
+
@employee.reload
|
|
113
|
+
expect(@employee.binary_data).to eq("")
|
|
114
|
+
@employee.binary_data = @binary_data
|
|
115
|
+
@employee.save!
|
|
116
|
+
@employee.reload
|
|
117
|
+
expect(@employee.binary_data).to eq(@binary_data)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe "OracleEnhancedAdapter boolean type detection based on string column types and names" do
|
|
4
|
+
before(:all) do
|
|
5
|
+
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
|
6
|
+
@conn = ActiveRecord::Base.connection
|
|
7
|
+
@conn.execute <<~SQL
|
|
8
|
+
CREATE TABLE test3_employees (
|
|
9
|
+
id NUMBER PRIMARY KEY,
|
|
10
|
+
first_name VARCHAR2(20),
|
|
11
|
+
last_name VARCHAR2(25),
|
|
12
|
+
email VARCHAR2(25),
|
|
13
|
+
phone_number VARCHAR2(20),
|
|
14
|
+
hire_date DATE,
|
|
15
|
+
job_id NUMBER,
|
|
16
|
+
salary NUMBER,
|
|
17
|
+
commission_pct NUMBER(2,2),
|
|
18
|
+
manager_id NUMBER(6),
|
|
19
|
+
department_id NUMBER(4,0),
|
|
20
|
+
created_at DATE,
|
|
21
|
+
has_email CHAR(1),
|
|
22
|
+
has_phone VARCHAR2(1) DEFAULT 'Y',
|
|
23
|
+
active_flag VARCHAR2(2),
|
|
24
|
+
manager_yn VARCHAR2(3) DEFAULT 'N',
|
|
25
|
+
test_boolean VARCHAR2(3)
|
|
26
|
+
)
|
|
27
|
+
SQL
|
|
28
|
+
@conn.execute <<~SQL
|
|
29
|
+
CREATE SEQUENCE test3_employees_seq MINVALUE 1
|
|
30
|
+
INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
|
|
31
|
+
SQL
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
after(:all) do
|
|
35
|
+
@conn.execute "DROP TABLE test3_employees"
|
|
36
|
+
@conn.execute "DROP SEQUENCE test3_employees_seq"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
before(:each) do
|
|
40
|
+
class ::Test3Employee < ActiveRecord::Base
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
after(:each) do
|
|
45
|
+
Object.send(:remove_const, "Test3Employee")
|
|
46
|
+
ActiveRecord::Base.clear_cache!
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "default values in new records" do
|
|
50
|
+
context "when emulate_booleans_from_strings is false" do
|
|
51
|
+
before do
|
|
52
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "are Y or N" do
|
|
56
|
+
subject = Test3Employee.new
|
|
57
|
+
expect(subject.has_phone).to eq("Y")
|
|
58
|
+
expect(subject.manager_yn).to eq("N")
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
context "when emulate_booleans_from_strings is true" do
|
|
63
|
+
before do
|
|
64
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "are True or False" do
|
|
68
|
+
class ::Test3Employee < ActiveRecord::Base
|
|
69
|
+
attribute :has_phone, :boolean
|
|
70
|
+
attribute :manager_yn, :boolean, default: false
|
|
71
|
+
end
|
|
72
|
+
subject = Test3Employee.new
|
|
73
|
+
expect(subject.has_phone).to be_a(TrueClass)
|
|
74
|
+
expect(subject.manager_yn).to be_a(FalseClass)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should translate boolean type to NUMBER(1) if emulate_booleans_from_strings is false" do
|
|
80
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
|
|
81
|
+
sql_type = ActiveRecord::Base.connection.type_to_sql(:boolean)
|
|
82
|
+
expect(sql_type).to eq("NUMBER(1)")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe "/ VARCHAR2 boolean values from ActiveRecord model" do
|
|
86
|
+
before(:each) do
|
|
87
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
after(:each) do
|
|
91
|
+
ActiveRecord::Base.clear_cache!
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def create_employee3(params = {})
|
|
95
|
+
@employee3 = Test3Employee.create(
|
|
96
|
+
{
|
|
97
|
+
first_name: "First",
|
|
98
|
+
last_name: "Last",
|
|
99
|
+
has_email: true,
|
|
100
|
+
has_phone: false,
|
|
101
|
+
active_flag: true,
|
|
102
|
+
manager_yn: false
|
|
103
|
+
}.merge(params)
|
|
104
|
+
)
|
|
105
|
+
@employee3.reload
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "should return String value from VARCHAR2 boolean column if emulate_booleans_from_strings is false" do
|
|
109
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
|
|
110
|
+
create_employee3
|
|
111
|
+
%w(has_email has_phone active_flag manager_yn).each do |col|
|
|
112
|
+
expect(@employee3.send(col.to_sym).class).to eq(String)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it "should return boolean value from VARCHAR2 boolean column if emulate_booleans_from_strings is true" do
|
|
117
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
|
|
118
|
+
class ::Test3Employee < ActiveRecord::Base
|
|
119
|
+
attribute :has_email, :boolean
|
|
120
|
+
attribute :active_flag, :boolean
|
|
121
|
+
attribute :has_phone, :boolean, default: false
|
|
122
|
+
attribute :manager_yn, :boolean, default: false
|
|
123
|
+
end
|
|
124
|
+
create_employee3
|
|
125
|
+
%w(has_email active_flag).each do |col|
|
|
126
|
+
expect(@employee3.send(col.to_sym).class).to eq(TrueClass)
|
|
127
|
+
expect(@employee3.send((col + "_before_type_cast").to_sym)).to eq("Y")
|
|
128
|
+
end
|
|
129
|
+
%w(has_phone manager_yn).each do |col|
|
|
130
|
+
expect(@employee3.send(col.to_sym).class).to eq(FalseClass)
|
|
131
|
+
expect(@employee3.send((col + "_before_type_cast").to_sym)).to eq("N")
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "should return string value from VARCHAR2 column if it is not boolean column and emulate_booleans_from_strings is true" do
|
|
136
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
|
|
137
|
+
create_employee3
|
|
138
|
+
expect(@employee3.first_name.class).to eq(String)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it "should return boolean value from VARCHAR2 boolean column if attribute is set to :boolean" do
|
|
142
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
|
|
143
|
+
class ::Test3Employee < ActiveRecord::Base
|
|
144
|
+
attribute :test_boolean, :boolean
|
|
145
|
+
end
|
|
146
|
+
create_employee3(test_boolean: true)
|
|
147
|
+
expect(@employee3.test_boolean.class).to eq(TrueClass)
|
|
148
|
+
expect(@employee3.test_boolean_before_type_cast).to eq("Y")
|
|
149
|
+
create_employee3(test_boolean: false)
|
|
150
|
+
expect(@employee3.test_boolean.class).to eq(FalseClass)
|
|
151
|
+
expect(@employee3.test_boolean_before_type_cast).to eq("N")
|
|
152
|
+
create_employee3(test_boolean: nil)
|
|
153
|
+
expect(@employee3.test_boolean.class).to eq(NilClass)
|
|
154
|
+
expect(@employee3.test_boolean_before_type_cast).to be_nil
|
|
155
|
+
create_employee3(test_boolean: "")
|
|
156
|
+
expect(@employee3.test_boolean.class).to eq(NilClass)
|
|
157
|
+
expect(@employee3.test_boolean_before_type_cast).to be_nil
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "should return string value from VARCHAR2 column with boolean column name but attribute is set to :string" do
|
|
161
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
|
|
162
|
+
class ::Test3Employee < ActiveRecord::Base
|
|
163
|
+
attribute :active_flag, :string
|
|
164
|
+
end
|
|
165
|
+
create_employee3
|
|
166
|
+
expect(@employee3.active_flag.class).to eq(String)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
describe "OracleEnhancedAdapter boolean support when emulate_booleans_from_strings = true" do
|
|
172
|
+
include SchemaSpecHelper
|
|
173
|
+
|
|
174
|
+
before(:all) do
|
|
175
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
|
|
176
|
+
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
|
177
|
+
schema_define do
|
|
178
|
+
create_table :posts, force: true do |t|
|
|
179
|
+
t.string :name, null: false
|
|
180
|
+
t.boolean :is_default, default: false
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
after(:all) do
|
|
186
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
before(:each) do
|
|
190
|
+
class ::Post < ActiveRecord::Base
|
|
191
|
+
attribute :is_default, :boolean
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
after(:each) do
|
|
196
|
+
Object.send(:remove_const, "Post")
|
|
197
|
+
ActiveRecord::Base.clear_cache!
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
it "boolean should not change after reload" do
|
|
201
|
+
post = Post.create(name: "Test 1", is_default: false)
|
|
202
|
+
expect(post.is_default).to be false
|
|
203
|
+
post.reload
|
|
204
|
+
expect(post.is_default).to be false
|
|
205
|
+
end
|
|
206
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe "OracleEnhancedAdapter processing CHAR column" do
|
|
4
|
+
before(:all) do
|
|
5
|
+
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
|
6
|
+
@conn = ActiveRecord::Base.connection
|
|
7
|
+
@conn.execute <<~SQL
|
|
8
|
+
CREATE TABLE test_items (
|
|
9
|
+
id NUMBER(6,0) PRIMARY KEY,
|
|
10
|
+
padded CHAR(10)
|
|
11
|
+
)
|
|
12
|
+
SQL
|
|
13
|
+
@conn.execute "CREATE SEQUENCE test_items_seq"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
after(:all) do
|
|
17
|
+
@conn.execute "DROP TABLE test_items"
|
|
18
|
+
@conn.execute "DROP SEQUENCE test_items_seq"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
before(:each) do
|
|
22
|
+
class ::TestItem < ActiveRecord::Base
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
after(:each) do
|
|
27
|
+
TestItem.delete_all
|
|
28
|
+
Object.send(:remove_const, "TestItem")
|
|
29
|
+
ActiveRecord::Base.clear_cache!
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should create and find record" do
|
|
33
|
+
str = "ABC"
|
|
34
|
+
TestItem.create!
|
|
35
|
+
item = TestItem.first
|
|
36
|
+
item.padded = str
|
|
37
|
+
item.save
|
|
38
|
+
|
|
39
|
+
expect(TestItem.where(padded: item.padded).count).to eq(1)
|
|
40
|
+
|
|
41
|
+
item_reloaded = TestItem.first
|
|
42
|
+
expect(item_reloaded.padded).to eq(str)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should support case sensitive matching" do
|
|
46
|
+
TestItem.create!(
|
|
47
|
+
padded: "First",
|
|
48
|
+
)
|
|
49
|
+
TestItem.create!(
|
|
50
|
+
padded: "first",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
expect(TestItem.where(TestItem.arel_table[:padded].matches("first%", "\\", true))).to have_attributes(count: 1)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should support case insensitive matching" do
|
|
57
|
+
TestItem.create!(
|
|
58
|
+
padded: "First",
|
|
59
|
+
)
|
|
60
|
+
TestItem.create!(
|
|
61
|
+
padded: "first",
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
expect(TestItem.where(TestItem.arel_table[:padded].matches("first%", "\\", false))).to have_attributes(count: 2)
|
|
65
|
+
expect(TestItem.where(TestItem.arel_table[:padded].matches("first%"))).to have_attributes(count: 2)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "base64"
|
|
4
|
+
|
|
5
|
+
describe "OracleEnhancedAdapter custom types handling" do
|
|
6
|
+
include SchemaSpecHelper
|
|
7
|
+
|
|
8
|
+
before(:all) do
|
|
9
|
+
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
|
10
|
+
schema_define do
|
|
11
|
+
create_table :test_employees, force: true do |t|
|
|
12
|
+
t.string :first_name, limit: 20
|
|
13
|
+
t.string :last_name, limit: 25
|
|
14
|
+
t.text :signature
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class TestEmployee < ActiveRecord::Base
|
|
19
|
+
class AttributeSignature < ActiveRecord::Type::Text
|
|
20
|
+
def cast(value)
|
|
21
|
+
case value
|
|
22
|
+
when Signature
|
|
23
|
+
value
|
|
24
|
+
when nil
|
|
25
|
+
nil
|
|
26
|
+
else
|
|
27
|
+
Signature.new(Base64.decode64 value)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def serialize(value)
|
|
32
|
+
Base64.encode64 value.raw
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def changed_in_place?(raw_old_value, new_value)
|
|
36
|
+
new_value != cast(raw_old_value)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class Signature
|
|
41
|
+
attr_reader :raw
|
|
42
|
+
|
|
43
|
+
def initialize(raw_value)
|
|
44
|
+
@raw = raw_value
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def to_s
|
|
48
|
+
"Signature nice string #{raw[0..5]}"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def ==(object)
|
|
52
|
+
raw == object&.raw
|
|
53
|
+
end
|
|
54
|
+
alias eql? ==
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
attribute :signature, AttributeSignature.new
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
after(:all) do
|
|
62
|
+
schema_define do
|
|
63
|
+
drop_table :test_employees
|
|
64
|
+
end
|
|
65
|
+
Object.send(:remove_const, "TestEmployee")
|
|
66
|
+
ActiveRecord::Base.clear_cache!
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "should serialize LOBs when creating a record" do
|
|
70
|
+
raw_signature = "peter'ssignature"
|
|
71
|
+
signature = TestEmployee::Signature.new(raw_signature)
|
|
72
|
+
@employee = TestEmployee.create!(first_name: "Peter", last_name: "Doe", signature: signature)
|
|
73
|
+
@employee.reload
|
|
74
|
+
expect(@employee.signature).to eql(signature)
|
|
75
|
+
expect(@employee.signature).to_not be(signature)
|
|
76
|
+
expect(TestEmployee.first.read_attribute_before_type_cast(:signature)).to eq(Base64.encode64 raw_signature)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should serialize LOBs when updating a record" do
|
|
80
|
+
raw_signature = "peter'ssignature"
|
|
81
|
+
signature = TestEmployee::Signature.new(raw_signature)
|
|
82
|
+
@employee = TestEmployee.create!(first_name: "Peter", last_name: "Doe", signature: TestEmployee::Signature.new("old signature"))
|
|
83
|
+
@employee.signature = signature
|
|
84
|
+
@employee.save!
|
|
85
|
+
@employee.reload
|
|
86
|
+
expect(@employee.signature).to eql(signature)
|
|
87
|
+
expect(@employee.signature).to_not be(signature)
|
|
88
|
+
expect(TestEmployee.first.read_attribute_before_type_cast(:signature)).to eq(Base64.encode64 raw_signature)
|
|
89
|
+
end
|
|
90
|
+
end
|