activerecord-oracle_enhanced-adapter 7.0.0 → 7.1.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 +4 -4
- data/History.md +56 -0
- data/README.md +0 -1
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +5 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +2 -2
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +35 -27
- data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +15 -2
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +9 -2
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +3 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +24 -15
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +3 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +7 -5
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +5 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +24 -22
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +17 -17
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +72 -29
- data/lib/activerecord-oracle_enhanced-adapter.rb +8 -0
- data/lib/arel/visitors/oracle.rb +6 -3
- data/lib/arel/visitors/oracle12.rb +6 -5
- data/lib/arel/visitors/oracle_common.rb +46 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +24 -5
- data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +7 -2
- data/spec/active_record/connection_adapters/oracle_enhanced/dbms_output_spec.rb +2 -2
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +3 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +25 -15
- data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +15 -18
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +14 -10
- data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +2 -2
- data/spec/active_record/oracle_enhanced/type/character_string_spec.rb +24 -0
- data/spec/active_record/oracle_enhanced/type/custom_spec.rb +90 -0
- data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +4 -2
- data/spec/active_record/oracle_enhanced/type/integer_spec.rb +8 -0
- data/spec/active_record/oracle_enhanced/type/national_character_text_spec.rb +3 -3
- data/spec/active_record/oracle_enhanced/type/raw_spec.rb +15 -0
- data/spec/active_record/oracle_enhanced/type/text_spec.rb +18 -3
- data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +5 -1
- data/spec/spec_config.yaml.template +2 -2
- data/spec/spec_helper.rb +14 -3
- metadata +27 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c54d072a9a65f5b91b230da739c0b2f117d397813b9f2dfb0ca56c13da00979
|
4
|
+
data.tar.gz: 0b4e805aff8d23258dda658e70a87494cb93d6da7b5e0024bd74a3807f54295e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72464c92eb71576aae495a2e93674d6823e1a2967f7f8bc45116d14dfbe8f29291c71b7f122e83c74698834be25e729bfddc0b64baf23de7e1b26044960faf26
|
7
|
+
data.tar.gz: 165de73dc654f318d7dc3042ae10f669047733255decd38f9abb2c3db3522bbb6f4c471db44a1ffe40ebaab05b400f9cd2eede381ea1018ea28217529a1c7610
|
data/History.md
CHANGED
@@ -1,3 +1,59 @@
|
|
1
|
+
## 7.1.0 / 2024-09-25
|
2
|
+
|
3
|
+
* Changes and bug fixes
|
4
|
+
No changes since 7.1.0.beta2
|
5
|
+
|
6
|
+
## 7.1.0.beta2 / 2024-09-23
|
7
|
+
* Changes and bug fixes
|
8
|
+
* Implement `build_explain_clause(options = [])` as no-op [#2394, #2398, #2402]
|
9
|
+
|
10
|
+
## 7.1.0.beta1 / 2024-09-23
|
11
|
+
|
12
|
+
* Changes and bug fixes
|
13
|
+
* Support Rails 7.1 [#2384]
|
14
|
+
* All attributes serialized before writing [#2203]
|
15
|
+
* Support LIKE case-insensitive matching [#2247]
|
16
|
+
* Support LOB equality [#2258]
|
17
|
+
* Rename the raw connection ivar to @raw_connection [#2265]
|
18
|
+
* Require 'activerecord', not 'rails' not to attempt to install digest [#2241]
|
19
|
+
* Add ruby-oci8 as dependency only for CRuby [#2240]
|
20
|
+
* Address uninitialized constant TestEmployee::AttributeSignature::Base64 [#2264]
|
21
|
+
* Enable Lint/EnsureReturn cop [#2259]
|
22
|
+
* Enable Performance/OpenStruct cop [#2263]
|
23
|
+
* Enable Style/MapToHash cop [#2266]
|
24
|
+
* Fix broken link [#2250]
|
25
|
+
* Use debug gem to replace byebug [#2275]
|
26
|
+
* Support linting YAML files [#2272]
|
27
|
+
|
28
|
+
* Known issues
|
29
|
+
* `build_explain_clause(options = [])` has not been implemented yet [#2394]
|
30
|
+
* `supports_fetch_first_n_rows_and_offset?` always returns `false` [#2395]
|
31
|
+
* Oracle enhanced adapter has not been tested against JRuby
|
32
|
+
* bug_report_templates are not tested [#2318]
|
33
|
+
|
34
|
+
## 7.0.3 / 2023-08-10
|
35
|
+
|
36
|
+
* Changes and bug fixes
|
37
|
+
* Support Rails 7.0.7
|
38
|
+
* Make ActiveRecord's quoted name caches thread-safe on JRuby/TruffleRuby [#2347, #2346]
|
39
|
+
* Address `NameError: uninitialized constant TestEmployee::AttributeSignature::Base64` [#2347]
|
40
|
+
* Address `Style/RedundantRegexpEscape` offense [#2347]
|
41
|
+
|
42
|
+
## 7.0.2 / 2022-01-21
|
43
|
+
|
44
|
+
* Changes and bug fixes
|
45
|
+
* Fix `columns_for_distinct` when using Rails 6.1 [#2249 #2251 rails/rails#31966]
|
46
|
+
|
47
|
+
## 7.0.1 / 2022-01-13
|
48
|
+
|
49
|
+
* Changes and bug fixes
|
50
|
+
* Add ruby-oci8 as dependency only for CRuby [#2238 #2240 #2243]
|
51
|
+
* Add if_exists option to remove_index [#2219 #2233]
|
52
|
+
* all attributes serialized before writing [#2203 #2234]
|
53
|
+
* Require 'activerecord', not 'rails' not to attempt to install digest [#2241]
|
54
|
+
* CI
|
55
|
+
* Bump Ruby versions at Travis CI [#2242]
|
56
|
+
* CI against Ruby 3.1 at GitHub Actions [#2235 #2244]
|
1
57
|
## 7.0.0 / 2021-12-16
|
2
58
|
* Changes and bug fixes
|
3
59
|
* Support Rails 7.0.0
|
data/README.md
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
7.
|
1
|
+
7.1.0
|
@@ -17,13 +17,13 @@ module ActiveRecord
|
|
17
17
|
def table_name_length
|
18
18
|
IDENTIFIER_MAX_LENGTH
|
19
19
|
end
|
20
|
-
deprecate :table_name_length
|
20
|
+
deprecate :table_name_length, deprecator: ActiveSupport::Deprecation.new
|
21
21
|
|
22
22
|
# the maximum length of a column name
|
23
23
|
def column_name_length
|
24
24
|
IDENTIFIER_MAX_LENGTH
|
25
25
|
end
|
26
|
-
deprecate :column_name_length
|
26
|
+
deprecate :column_name_length, deprecator: ActiveSupport::Deprecation.new
|
27
27
|
|
28
28
|
# the maximum length of an index name
|
29
29
|
# supported by this database
|
@@ -9,13 +9,13 @@ module ActiveRecord
|
|
9
9
|
# see: abstract/database_statements.rb
|
10
10
|
|
11
11
|
# Executes a SQL statement
|
12
|
-
def execute(sql, name = nil, async: false)
|
12
|
+
def execute(sql, name = nil, async: false, allow_retry: false)
|
13
13
|
sql = transform_query(sql)
|
14
14
|
|
15
|
-
log(sql, name, async: async) {
|
15
|
+
log(sql, name, async: async) { _connection.exec(sql, allow_retry: allow_retry) }
|
16
16
|
end
|
17
17
|
|
18
|
-
def exec_query(sql, name = "SQL", binds = [], prepare: false, async: false)
|
18
|
+
def exec_query(sql, name = "SQL", binds = [], prepare: false, async: false, allow_retry: false)
|
19
19
|
sql = transform_query(sql)
|
20
20
|
|
21
21
|
type_casted_binds = type_casted_binds(binds)
|
@@ -25,10 +25,10 @@ module ActiveRecord
|
|
25
25
|
cached = false
|
26
26
|
with_retry do
|
27
27
|
if without_prepared_statement?(binds)
|
28
|
-
cursor =
|
28
|
+
cursor = _connection.prepare(sql)
|
29
29
|
else
|
30
30
|
unless @statements.key? sql
|
31
|
-
@statements[sql] =
|
31
|
+
@statements[sql] = _connection.prepare(sql)
|
32
32
|
end
|
33
33
|
|
34
34
|
cursor = @statements[sql]
|
@@ -59,12 +59,13 @@ module ActiveRecord
|
|
59
59
|
res
|
60
60
|
end
|
61
61
|
end
|
62
|
+
alias_method :internal_exec_query, :exec_query
|
62
63
|
|
63
64
|
def supports_explain?
|
64
65
|
true
|
65
66
|
end
|
66
67
|
|
67
|
-
def explain(arel, binds = [])
|
68
|
+
def explain(arel, binds = [], options = [])
|
68
69
|
sql = "EXPLAIN PLAN FOR #{to_sql(arel, binds)}"
|
69
70
|
return if /FROM all_/.match?(sql)
|
70
71
|
if ORACLE_ENHANCED_CONNECTION == :jdbc
|
@@ -75,9 +76,14 @@ module ActiveRecord
|
|
75
76
|
select_values("SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)", "EXPLAIN").join("\n")
|
76
77
|
end
|
77
78
|
|
79
|
+
def build_explain_clause(options = [])
|
80
|
+
# Oracle does not have anything similar to "EXPLAIN ANALYZE"
|
81
|
+
# https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/EXPLAIN-PLAN.html#GUID-FD540872-4ED3-4936-96A2-362539931BA0
|
82
|
+
end
|
83
|
+
|
78
84
|
# New method in ActiveRecord 3.1
|
79
85
|
# Will add RETURNING clause in case of trigger generated primary keys
|
80
|
-
def sql_for_insert(sql, pk, binds)
|
86
|
+
def sql_for_insert(sql, pk, binds, _returning)
|
81
87
|
unless pk == false || pk.nil? || pk.is_a?(Array) || pk.is_a?(String)
|
82
88
|
sql = "#{sql} RETURNING #{quote_column_name(pk)} INTO :returning_id"
|
83
89
|
(binds = binds.dup) << ActiveRecord::Relation::QueryAttribute.new("returning_id", nil, Type::OracleEnhanced::Integer.new)
|
@@ -85,14 +91,14 @@ module ActiveRecord
|
|
85
91
|
super
|
86
92
|
end
|
87
93
|
|
88
|
-
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
|
94
|
+
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [], returning: nil)
|
89
95
|
pk = nil if id_value
|
90
|
-
super
|
96
|
+
Array(super || id_value)
|
91
97
|
end
|
92
98
|
|
93
99
|
# New method in ActiveRecord 3.1
|
94
|
-
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
|
95
|
-
sql, binds = sql_for_insert(sql, pk, binds)
|
100
|
+
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil, returning: nil)
|
101
|
+
sql, binds = sql_for_insert(sql, pk, binds, returning)
|
96
102
|
type_casted_binds = type_casted_binds(binds)
|
97
103
|
|
98
104
|
log(sql, name, binds, type_casted_binds) do
|
@@ -101,10 +107,10 @@ module ActiveRecord
|
|
101
107
|
returning_id_col = returning_id_index = nil
|
102
108
|
with_retry do
|
103
109
|
if without_prepared_statement?(binds)
|
104
|
-
cursor =
|
110
|
+
cursor = _connection.prepare(sql)
|
105
111
|
else
|
106
112
|
unless @statements.key?(sql)
|
107
|
-
@statements[sql] =
|
113
|
+
@statements[sql] = _connection.prepare(sql)
|
108
114
|
end
|
109
115
|
|
110
116
|
cursor = @statements[sql]
|
@@ -141,12 +147,12 @@ module ActiveRecord
|
|
141
147
|
with_retry do
|
142
148
|
cached = false
|
143
149
|
if without_prepared_statement?(binds)
|
144
|
-
cursor =
|
150
|
+
cursor = _connection.prepare(sql)
|
145
151
|
else
|
146
152
|
if @statements.key?(sql)
|
147
153
|
cursor = @statements[sql]
|
148
154
|
else
|
149
|
-
cursor = @statements[sql] =
|
155
|
+
cursor = @statements[sql] = _connection.prepare(sql)
|
150
156
|
end
|
151
157
|
|
152
158
|
cursor.bind_params(type_casted_binds)
|
@@ -163,8 +169,12 @@ module ActiveRecord
|
|
163
169
|
|
164
170
|
alias :exec_delete :exec_update
|
165
171
|
|
172
|
+
def returning_column_values(result)
|
173
|
+
result.rows.first
|
174
|
+
end
|
175
|
+
|
166
176
|
def begin_db_transaction # :nodoc:
|
167
|
-
|
177
|
+
_connection.autocommit = false
|
168
178
|
end
|
169
179
|
|
170
180
|
def transaction_isolation_levels
|
@@ -183,15 +193,15 @@ module ActiveRecord
|
|
183
193
|
end
|
184
194
|
|
185
195
|
def commit_db_transaction # :nodoc:
|
186
|
-
|
196
|
+
_connection.commit
|
187
197
|
ensure
|
188
|
-
|
198
|
+
_connection.autocommit = true
|
189
199
|
end
|
190
200
|
|
191
201
|
def exec_rollback_db_transaction # :nodoc:
|
192
|
-
|
202
|
+
_connection.rollback
|
193
203
|
ensure
|
194
|
-
|
204
|
+
_connection.autocommit = true
|
195
205
|
end
|
196
206
|
|
197
207
|
def create_savepoint(name = current_savepoint_name) # :nodoc:
|
@@ -254,11 +264,9 @@ module ActiveRecord
|
|
254
264
|
value = attributes[col.name]
|
255
265
|
# changed sequence of next two lines - should check if value is nil before converting to yaml
|
256
266
|
next unless value
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
next unless value
|
261
|
-
end
|
267
|
+
value = klass.attribute_types[col.name].serialize(value)
|
268
|
+
# value can be nil after serialization because ActiveRecord serializes [] and {} as nil
|
269
|
+
next unless value
|
262
270
|
uncached do
|
263
271
|
unless lob_record = select_one(sql = <<~SQL.squish, "Writable Large Object")
|
264
272
|
SELECT #{quote_column_name(col.name)} FROM #{quote_table_name(table_name)}
|
@@ -267,14 +275,14 @@ module ActiveRecord
|
|
267
275
|
raise ActiveRecord::RecordNotFound, "statement #{sql} returned no rows"
|
268
276
|
end
|
269
277
|
lob = lob_record[col.name]
|
270
|
-
|
278
|
+
_connection.write_lob(lob, value.to_s, col.type == :binary)
|
271
279
|
end
|
272
280
|
end
|
273
281
|
end
|
274
282
|
|
275
283
|
private
|
276
284
|
def with_retry
|
277
|
-
|
285
|
+
_connection.with_retry do
|
278
286
|
yield
|
279
287
|
rescue
|
280
288
|
@statements.clear
|
@@ -31,8 +31,21 @@ module ActiveRecord
|
|
31
31
|
end
|
32
32
|
|
33
33
|
private
|
34
|
-
def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil, async: false)
|
35
|
-
|
34
|
+
def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil, async: false, &block)
|
35
|
+
@instrumenter.instrument(
|
36
|
+
"sql.active_record",
|
37
|
+
sql: sql,
|
38
|
+
name: name,
|
39
|
+
binds: binds,
|
40
|
+
type_casted_binds: type_casted_binds,
|
41
|
+
statement_name: statement_name,
|
42
|
+
async: async,
|
43
|
+
connection: self,
|
44
|
+
&block
|
45
|
+
)
|
46
|
+
rescue => e
|
47
|
+
# FIXME: raise ex.set_query(sql, binds)
|
48
|
+
raise translate_exception_class(e, sql, binds)
|
36
49
|
ensure
|
37
50
|
log_dbms_output if dbms_output_enabled?
|
38
51
|
end
|
@@ -135,6 +135,13 @@ module ActiveRecord
|
|
135
135
|
properties.put("defaultRowPrefetch", "#{prefetch_rows}") if prefetch_rows
|
136
136
|
properties.put("internal_logon", privilege) if privilege
|
137
137
|
|
138
|
+
if config[:jdbc_connect_properties] # arbitrary additional properties for JDBC connection
|
139
|
+
raise "jdbc_connect_properties should contain an associative array / hash" unless config[:jdbc_connect_properties].is_a? Hash
|
140
|
+
config[:jdbc_connect_properties].each do |key, value|
|
141
|
+
properties.put(key, value)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
138
145
|
begin
|
139
146
|
@raw_connection = java.sql.DriverManager.getConnection(url, properties)
|
140
147
|
rescue
|
@@ -295,7 +302,7 @@ module ActiveRecord
|
|
295
302
|
|
296
303
|
class Cursor
|
297
304
|
def initialize(connection, raw_statement)
|
298
|
-
@
|
305
|
+
@raw_connection = connection
|
299
306
|
@raw_statement = raw_statement
|
300
307
|
end
|
301
308
|
|
@@ -384,7 +391,7 @@ module ActiveRecord
|
|
384
391
|
row_values = []
|
385
392
|
column_types.each_with_index do |column_type, i|
|
386
393
|
row_values <<
|
387
|
-
@
|
394
|
+
@raw_connection.get_ruby_value_from_result_set(@raw_result_set, i + 1, column_type, get_lob_value)
|
388
395
|
end
|
389
396
|
row_values
|
390
397
|
else
|
@@ -7,15 +7,15 @@ module ActiveRecord
|
|
7
7
|
def type_cast(value)
|
8
8
|
case value
|
9
9
|
when ActiveModel::Type::Binary::Data
|
10
|
-
blob = Java::OracleSql::BLOB.createTemporary(@
|
10
|
+
blob = Java::OracleSql::BLOB.createTemporary(@raw_connection.raw_connection, false, Java::OracleSql::BLOB::DURATION_SESSION)
|
11
11
|
blob.setBytes(1, value.to_s.to_java_bytes)
|
12
12
|
blob
|
13
13
|
when Type::OracleEnhanced::Text::Data
|
14
|
-
clob = Java::OracleSql::CLOB.createTemporary(@
|
14
|
+
clob = Java::OracleSql::CLOB.createTemporary(@raw_connection.raw_connection, false, Java::OracleSql::CLOB::DURATION_SESSION)
|
15
15
|
clob.setString(1, value.to_s)
|
16
16
|
clob
|
17
17
|
when Type::OracleEnhanced::NationalCharacterText::Data
|
18
|
-
clob = Java::OracleSql::NCLOB.createTemporary(@
|
18
|
+
clob = Java::OracleSql::NCLOB.createTemporary(@raw_connection.raw_connection, false, Java::OracleSql::NCLOB::DURATION_SESSION)
|
19
19
|
clob.setString(1, value.to_s)
|
20
20
|
clob
|
21
21
|
else
|
@@ -41,7 +41,7 @@ module ActiveRecord
|
|
41
41
|
# ActiveRecord Oracle enhanced adapter puts OCI8EnhancedAutoRecover wrapper around OCI8
|
42
42
|
# in this case we need to pass original OCI8 connection
|
43
43
|
else
|
44
|
-
@raw_connection.instance_variable_get(:@
|
44
|
+
@raw_connection.instance_variable_get(:@raw_connection)
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -87,18 +87,22 @@ module ActiveRecord
|
|
87
87
|
@raw_connection.active?
|
88
88
|
end
|
89
89
|
|
90
|
+
def reset
|
91
|
+
@raw_connection.reset
|
92
|
+
end
|
93
|
+
|
90
94
|
def reset!
|
91
95
|
@raw_connection.reset!
|
92
96
|
rescue OCIException => e
|
93
97
|
raise OracleEnhanced::ConnectionException, e.message
|
94
98
|
end
|
95
99
|
|
96
|
-
def exec(sql, *bindvars, &block)
|
97
|
-
@raw_connection.exec(sql, *bindvars, &block)
|
100
|
+
def exec(sql, *bindvars, allow_retry: false, &block)
|
101
|
+
with_retry(allow_retry: allow_retry) { @raw_connection.exec(sql, *bindvars, &block) }
|
98
102
|
end
|
99
103
|
|
100
|
-
def with_retry(&block)
|
101
|
-
@raw_connection.with_retry(&block)
|
104
|
+
def with_retry(allow_retry: false, &block)
|
105
|
+
@raw_connection.with_retry(allow_retry: allow_retry, &block)
|
102
106
|
end
|
103
107
|
|
104
108
|
def prepare(sql)
|
@@ -107,7 +111,7 @@ module ActiveRecord
|
|
107
111
|
|
108
112
|
class Cursor
|
109
113
|
def initialize(connection, raw_cursor)
|
110
|
-
@
|
114
|
+
@raw_connection = connection
|
111
115
|
@raw_cursor = raw_cursor
|
112
116
|
end
|
113
117
|
|
@@ -159,7 +163,7 @@ module ActiveRecord
|
|
159
163
|
get_lob_value = options[:get_lob_value]
|
160
164
|
col_index = 0
|
161
165
|
row.map do |col|
|
162
|
-
col_value = @
|
166
|
+
col_value = @raw_connection.typecast_result_value(col, get_lob_value)
|
163
167
|
col_metadata = @raw_cursor.column_metadata.fetch(col_index)
|
164
168
|
if !col_metadata.nil?
|
165
169
|
key = col_metadata.data_type
|
@@ -390,27 +394,32 @@ class OCI8EnhancedAutoRecover < DelegateClass(OCI8) # :nodoc:
|
|
390
394
|
@active = true
|
391
395
|
@config = config
|
392
396
|
@factory = factory
|
393
|
-
@
|
394
|
-
super @
|
397
|
+
@raw_connection = @factory.new_connection @config
|
398
|
+
super @raw_connection
|
395
399
|
end
|
396
400
|
|
397
401
|
# Checks connection, returns true if active. Note that ping actively
|
398
402
|
# checks the connection, while #active? simply returns the last
|
399
403
|
# known state.
|
400
404
|
def ping # :nodoc:
|
401
|
-
@
|
405
|
+
@raw_connection.exec("select 1 from dual") { |r| nil }
|
402
406
|
@active = true
|
403
407
|
rescue
|
404
408
|
@active = false
|
405
409
|
raise
|
406
410
|
end
|
407
411
|
|
412
|
+
def reset
|
413
|
+
# tentative
|
414
|
+
reset!
|
415
|
+
end
|
416
|
+
|
408
417
|
# Resets connection, by logging off and creating a new connection.
|
409
418
|
def reset! # :nodoc:
|
410
419
|
logoff rescue nil
|
411
420
|
begin
|
412
|
-
@
|
413
|
-
__setobj__ @
|
421
|
+
@raw_connection = @factory.new_connection @config
|
422
|
+
__setobj__ @raw_connection
|
414
423
|
@active = true
|
415
424
|
rescue
|
416
425
|
@active = false
|
@@ -426,8 +435,8 @@ class OCI8EnhancedAutoRecover < DelegateClass(OCI8) # :nodoc:
|
|
426
435
|
LOST_CONNECTION_ERROR_CODES = [ 28, 1012, 3113, 3114, 3135 ] # :nodoc:
|
427
436
|
|
428
437
|
# Adds auto-recovery functionality.
|
429
|
-
def with_retry # :nodoc:
|
430
|
-
should_retry = self.class.auto_retry? && autocommit?
|
438
|
+
def with_retry(allow_retry: false) # :nodoc:
|
439
|
+
should_retry = (allow_retry || self.class.auto_retry?) && autocommit?
|
431
440
|
|
432
441
|
begin
|
433
442
|
yield
|
@@ -442,7 +451,7 @@ class OCI8EnhancedAutoRecover < DelegateClass(OCI8) # :nodoc:
|
|
442
451
|
end
|
443
452
|
|
444
453
|
def exec(sql, *bindvars, &block) # :nodoc:
|
445
|
-
with_retry { @
|
454
|
+
with_retry { @raw_connection.exec(sql, *bindvars, &block) }
|
446
455
|
end
|
447
456
|
end
|
448
457
|
# :startdoc:
|
@@ -9,19 +9,19 @@ module ActiveRecord
|
|
9
9
|
when ActiveModel::Type::Binary::Data
|
10
10
|
lob_value = value == "" ? " " : value
|
11
11
|
bind_type = OCI8::BLOB
|
12
|
-
ora_value = bind_type.new(
|
12
|
+
ora_value = bind_type.new(_connection.raw_oci_connection, lob_value)
|
13
13
|
ora_value.size = 0 if value == ""
|
14
14
|
ora_value
|
15
15
|
when Type::OracleEnhanced::Text::Data
|
16
16
|
lob_value = value.to_s == "" ? " " : value.to_s
|
17
17
|
bind_type = OCI8::CLOB
|
18
|
-
ora_value = bind_type.new(
|
18
|
+
ora_value = bind_type.new(_connection.raw_oci_connection, lob_value)
|
19
19
|
ora_value.size = 0 if value.to_s == ""
|
20
20
|
ora_value
|
21
21
|
when Type::OracleEnhanced::NationalCharacterText::Data
|
22
22
|
lob_value = value.to_s == "" ? " " : value.to_s
|
23
23
|
bind_type = OCI8::NCLOB
|
24
|
-
ora_value = bind_type.new(
|
24
|
+
ora_value = bind_type.new(_connection.raw_oci_connection, lob_value)
|
25
25
|
ora_value.size = 0 if value.to_s == ""
|
26
26
|
ora_value
|
27
27
|
else
|
@@ -7,10 +7,12 @@ module ActiveRecord
|
|
7
7
|
# QUOTING ==================================================
|
8
8
|
#
|
9
9
|
# see: abstract/quoting.rb
|
10
|
+
QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
|
11
|
+
QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
|
10
12
|
|
11
13
|
def quote_column_name(name) # :nodoc:
|
12
14
|
name = name.to_s
|
13
|
-
|
15
|
+
QUOTED_COLUMN_NAMES[name] ||= if /\A[a-z][a-z_0-9$#]*\Z/.match?(name)
|
14
16
|
"\"#{name.upcase}\""
|
15
17
|
else
|
16
18
|
# remove double quotes which cannot be used inside quoted identifier
|
@@ -26,7 +28,7 @@ module ActiveRecord
|
|
26
28
|
# if only valid lowercase column characters in name
|
27
29
|
when /^[a-z][a-z_0-9$#]*$/
|
28
30
|
"\"#{name.upcase}\""
|
29
|
-
when /^[a-z][a-z_0-9
|
31
|
+
when /^[a-z][a-z_0-9$#-]*$/i
|
30
32
|
"\"#{name}\""
|
31
33
|
# if other characters present then assume that it is expression
|
32
34
|
# which should not be quoted
|
@@ -67,7 +69,7 @@ module ActiveRecord
|
|
67
69
|
|
68
70
|
def quote_table_name(name) # :nodoc:
|
69
71
|
name, _link = name.to_s.split("@")
|
70
|
-
|
72
|
+
QUOTED_TABLE_NAMES[name] ||= [name.split(".").map { |n| quote_column_name(n) }].join(".")
|
71
73
|
end
|
72
74
|
|
73
75
|
def quote_string(s) # :nodoc:
|
@@ -142,7 +144,7 @@ module ActiveRecord
|
|
142
144
|
(
|
143
145
|
(?:
|
144
146
|
# "table_name"."column_name" | function(one or no argument)
|
145
|
-
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")
|
147
|
+
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+") | \w+\((?:|\g<2>)\))
|
146
148
|
)
|
147
149
|
(?:(?:\s+AS)?\s+(?:\w+|"\w+"))?
|
148
150
|
)
|
@@ -155,7 +157,7 @@ module ActiveRecord
|
|
155
157
|
(
|
156
158
|
(?:
|
157
159
|
# "table_name"."column_name" | function(one or no argument)
|
158
|
-
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")
|
160
|
+
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+") | \w+\((?:|\g<2>)\))
|
159
161
|
)
|
160
162
|
(?:\s+ASC|\s+DESC)?
|
161
163
|
(?:\s+NULLS\s+(?:FIRST|LAST))?
|
@@ -81,6 +81,11 @@ module ActiveRecord
|
|
81
81
|
super(*args, type: :integer, **options)
|
82
82
|
end
|
83
83
|
alias :belongs_to :references
|
84
|
+
|
85
|
+
private
|
86
|
+
def valid_column_definition_options
|
87
|
+
super + [ :as, :sequence_name, :sequence_start_value, :type ]
|
88
|
+
end
|
84
89
|
end
|
85
90
|
|
86
91
|
class AlterTable < ActiveRecord::ConnectionAdapters::AlterTable
|
@@ -181,7 +181,7 @@ module ActiveRecord # :nodoc:
|
|
181
181
|
def extract_expression_for_virtual_column(column)
|
182
182
|
column_name = column.name
|
183
183
|
@connection.select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name.upcase), bind_string("column_name", column_name.upcase)]).inspect
|
184
|
-
select
|
184
|
+
select data_default from all_tab_columns
|
185
185
|
where owner = SYS_CONTEXT('userenv', 'current_schema')
|
186
186
|
and table_name = :table_name
|
187
187
|
and column_name = :column_name
|