Skip to content

Commit 293c24b

Browse files
authored
Merge pull request #2199 from yahonda/define_adapter_type_maps_statically_when_possible
Define adapter type maps statically when possible
2 parents d612678 + 05090c8 commit 293c24b

File tree

6 files changed

+98
-95
lines changed

6 files changed

+98
-95
lines changed

.github/workflows/test.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ jobs:
2323
'2.7'
2424
]
2525
env:
26-
ORACLE_HOME: /usr/lib/oracle/18.5/client64
27-
LD_LIBRARY_PATH: /usr/lib/oracle/18.5/client64/lib
26+
ORACLE_HOME: /usr/lib/oracle/21/client64
27+
LD_LIBRARY_PATH: /usr/lib/oracle/21/client64/lib
2828
NLS_LANG: AMERICAN_AMERICA.AL32UTF8
2929
TNS_ADMIN: ./ci/network/admin
3030
DATABASE_NAME: XEPDB1
@@ -57,14 +57,14 @@ jobs:
5757
sudo apt-get install alien
5858
- name: Download Oracle client
5959
run: |
60-
wget -q https://download.oracle.com/otn_software/linux/instantclient/185000/oracle-instantclient18.5-basic-18.5.0.0.0-3.x86_64.rpm
61-
wget -q https://download.oracle.com/otn_software/linux/instantclient/185000/oracle-instantclient18.5-sqlplus-18.5.0.0.0-3.x86_64.rpm
62-
wget -q https://download.oracle.com/otn_software/linux/instantclient/185000/oracle-instantclient18.5-devel-18.5.0.0.0-3.x86_64.rpm
60+
wget -q https://download.oracle.com/otn_software/linux/instantclient/214000/oracle-instantclient-basic-21.4.0.0.0-1.x86_64.rpm
61+
wget -q https://download.oracle.com/otn_software/linux/instantclient/214000/oracle-instantclient-sqlplus-21.4.0.0.0-1.x86_64.rpm
62+
wget -q https://download.oracle.com/otn_software/linux/instantclient/214000/oracle-instantclient-devel-21.4.0.0.0-1.x86_64.rpm
6363
- name: Install Oracle client
6464
run: |
65-
sudo alien -i oracle-instantclient18.5-basic-18.5.0.0.0-3.x86_64.rpm
66-
sudo alien -i oracle-instantclient18.5-sqlplus-18.5.0.0.0-3.x86_64.rpm
67-
sudo alien -i oracle-instantclient18.5-devel-18.5.0.0.0-3.x86_64.rpm
65+
sudo alien -i oracle-instantclient-basic-21.4.0.0.0-1.x86_64.rpm
66+
sudo alien -i oracle-instantclient-sqlplus-21.4.0.0.0-1.x86_64.rpm
67+
sudo alien -i oracle-instantclient-devel-21.4.0.0.0-1.x86_64.rpm
6868
- name: Install JDBC Driver
6969
run: |
7070
wget -q https://download.oracle.com/otn-pub/otn_software/jdbc/211/ojdbc11.jar -O ./lib/ojdbc11.jar

lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,6 @@ def execute(sql, name = nil, async: false)
1313
log(sql, name, async: async) { @connection.exec(sql) }
1414
end
1515

16-
def clear_cache! # :nodoc:
17-
reload_type_map
18-
super
19-
end
20-
2116
def exec_query(sql, name = "SQL", binds = [], prepare: false, async: false)
2217
type_casted_binds = type_casted_binds(binds)
2318

lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module ActiveRecord
44
module ConnectionAdapters
55
module OracleEnhanced
66
module JDBCQuoting
7-
def _type_cast(value)
7+
def type_cast(value)
88
case value
99
when ActiveModel::Type::Binary::Data
1010
blob = Java::OracleSql::BLOB.createTemporary(@connection.raw_connection, false, Java::OracleSql::BLOB::DURATION_SESSION)

lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module ActiveRecord
44
module ConnectionAdapters
55
module OracleEnhanced
66
module OCIQuoting
7-
def _type_cast(value)
7+
def type_cast(value)
88
case value
99
when ActiveModel::Type::Binary::Data
1010
lob_value = value == "" ? " " : value

lib/active_record/connection_adapters/oracle_enhanced/quoting.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def quote_string(s) # :nodoc:
7474
s.gsub(/'/, "''")
7575
end
7676

77-
def _quote(value) # :nodoc:
77+
def quote(value) # :nodoc:
7878
case value
7979
when Type::OracleEnhanced::CharacterString::Data then
8080
"'#{quote_string(value.to_s)}'"
@@ -111,7 +111,7 @@ def unquoted_false # :nodoc:
111111
"0"
112112
end
113113

114-
def _type_cast(value)
114+
def type_cast(value)
115115
case value
116116
when Type::OracleEnhanced::TimestampTz::Data, Type::OracleEnhanced::TimestampLtz::Data
117117
if value.acts_like?(:time)

lib/active_record/connection_adapters/oracle_enhanced_adapter.rb

Lines changed: 86 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -690,98 +690,106 @@ def check_version
690690
end
691691
end
692692

693-
private
694-
def initialize_type_map(m = type_map)
695-
super
696-
# oracle
697-
register_class_with_precision m, %r(WITH TIME ZONE)i, Type::OracleEnhanced::TimestampTz
698-
register_class_with_precision m, %r(WITH LOCAL TIME ZONE)i, Type::OracleEnhanced::TimestampLtz
699-
register_class_with_limit m, %r(raw)i, Type::OracleEnhanced::Raw
700-
register_class_with_limit m, %r{^(char)}i, Type::OracleEnhanced::CharacterString
701-
register_class_with_limit m, %r{^(nchar)}i, Type::OracleEnhanced::String
702-
register_class_with_limit m, %r(varchar)i, Type::OracleEnhanced::String
703-
register_class_with_limit m, %r(clob)i, Type::OracleEnhanced::Text
704-
register_class_with_limit m, %r(nclob)i, Type::OracleEnhanced::NationalCharacterText
705-
706-
m.register_type "NCHAR", Type::OracleEnhanced::NationalCharacterString.new
707-
m.alias_type %r(NVARCHAR2)i, "NCHAR"
708-
709-
m.register_type(%r(NUMBER)i) do |sql_type|
710-
scale = extract_scale(sql_type)
711-
precision = extract_precision(sql_type)
712-
limit = extract_limit(sql_type)
713-
if scale == 0
714-
Type::OracleEnhanced::Integer.new(precision: precision, limit: limit)
715-
else
716-
Type::Decimal.new(precision: precision, scale: scale)
693+
class << self
694+
private
695+
def initialize_type_map(m)
696+
super
697+
# oracle
698+
register_class_with_precision m, %r(WITH TIME ZONE)i, Type::OracleEnhanced::TimestampTz
699+
register_class_with_precision m, %r(WITH LOCAL TIME ZONE)i, Type::OracleEnhanced::TimestampLtz
700+
register_class_with_limit m, %r(raw)i, Type::OracleEnhanced::Raw
701+
register_class_with_limit m, %r{^(char)}i, Type::OracleEnhanced::CharacterString
702+
register_class_with_limit m, %r{^(nchar)}i, Type::OracleEnhanced::String
703+
register_class_with_limit m, %r(varchar)i, Type::OracleEnhanced::String
704+
register_class_with_limit m, %r(clob)i, Type::OracleEnhanced::Text
705+
register_class_with_limit m, %r(nclob)i, Type::OracleEnhanced::NationalCharacterText
706+
707+
m.register_type "NCHAR", Type::OracleEnhanced::NationalCharacterString.new
708+
m.alias_type %r(NVARCHAR2)i, "NCHAR"
709+
710+
m.register_type(%r(NUMBER)i) do |sql_type|
711+
scale = extract_scale(sql_type)
712+
precision = extract_precision(sql_type)
713+
limit = extract_limit(sql_type)
714+
if scale == 0
715+
Type::OracleEnhanced::Integer.new(precision: precision, limit: limit)
716+
else
717+
Type::Decimal.new(precision: precision, scale: scale)
718+
end
717719
end
718-
end
719720

720-
if OracleEnhancedAdapter.emulate_booleans
721-
m.register_type %r(^NUMBER\(1\))i, Type::Boolean.new
721+
if OracleEnhancedAdapter.emulate_booleans
722+
m.register_type %r(^NUMBER\(1\))i, Type::Boolean.new
723+
end
722724
end
723-
end
725+
end
724726

725-
def extract_value_from_default(default)
726-
case default
727-
when String
728-
default.gsub("''", "'")
729-
else
730-
default
731-
end
732-
end
727+
TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
733728

734-
def extract_limit(sql_type) # :nodoc:
735-
case sql_type
736-
when /^bigint/i
737-
19
738-
when /\((.*)\)/
739-
$1.to_i
740-
end
729+
def type_map
730+
TYPE_MAP
731+
end
732+
733+
def extract_value_from_default(default)
734+
case default
735+
when String
736+
default.gsub("''", "'")
737+
else
738+
default
741739
end
740+
end
742741

743-
def translate_exception(exception, message:, sql:, binds:) # :nodoc:
744-
case @connection.error_code(exception)
745-
when 1
746-
RecordNotUnique.new(message, sql: sql, binds: binds)
747-
when 60
748-
Deadlocked.new(message)
749-
when 900, 904, 942, 955, 1418, 2289, 2449, 17008
750-
ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
751-
when 1400
752-
ActiveRecord::NotNullViolation.new(message, sql: sql, binds: binds)
753-
when 2291, 2292
754-
InvalidForeignKey.new(message, sql: sql, binds: binds)
755-
when 12899
756-
ValueTooLong.new(message, sql: sql, binds: binds)
757-
else
758-
super
759-
end
742+
def extract_limit(sql_type) # :nodoc:
743+
case sql_type
744+
when /^bigint/i
745+
19
746+
when /\((.*)\)/
747+
$1.to_i
760748
end
749+
end
761750

762-
# create bind object for type String
763-
def bind_string(name, value)
764-
ActiveRecord::Relation::QueryAttribute.new(name, value, Type::OracleEnhanced::String.new)
751+
def translate_exception(exception, message:, sql:, binds:) # :nodoc:
752+
case @connection.error_code(exception)
753+
when 1
754+
RecordNotUnique.new(message, sql: sql, binds: binds)
755+
when 60
756+
Deadlocked.new(message)
757+
when 900, 904, 942, 955, 1418, 2289, 2449, 17008
758+
ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
759+
when 1400
760+
ActiveRecord::NotNullViolation.new(message, sql: sql, binds: binds)
761+
when 2291, 2292
762+
InvalidForeignKey.new(message, sql: sql, binds: binds)
763+
when 12899
764+
ValueTooLong.new(message, sql: sql, binds: binds)
765+
else
766+
super
765767
end
768+
end
766769

767-
# call select_values using binds even if surrounding SQL preparation/execution is done + # with conn.unprepared_statement (like AR.to_sql)
768-
def select_values_forcing_binds(arel, name, binds)
769-
# remove possible force of unprepared SQL during dictionary access
770-
unprepared_statement_forced = prepared_statements_disabled_cache.include?(object_id)
771-
prepared_statements_disabled_cache.delete(object_id) if unprepared_statement_forced
770+
# create bind object for type String
771+
def bind_string(name, value)
772+
ActiveRecord::Relation::QueryAttribute.new(name, value, Type::OracleEnhanced::String.new)
773+
end
772774

773-
select_values(arel, name, binds)
774-
ensure
775-
# Restore unprepared_statement setting for surrounding SQL
776-
prepared_statements_disabled_cache.add(object_id) if unprepared_statement_forced
777-
end
775+
# call select_values using binds even if surrounding SQL preparation/execution is done + # with conn.unprepared_statement (like AR.to_sql)
776+
def select_values_forcing_binds(arel, name, binds)
777+
# remove possible force of unprepared SQL during dictionary access
778+
unprepared_statement_forced = prepared_statements_disabled_cache.include?(object_id)
779+
prepared_statements_disabled_cache.delete(object_id) if unprepared_statement_forced
778780

779-
def select_value_forcing_binds(arel, name, binds)
780-
single_value_from_rows(select_values_forcing_binds(arel, name, binds))
781-
end
781+
select_values(arel, name, binds)
782+
ensure
783+
# Restore unprepared_statement setting for surrounding SQL
784+
prepared_statements_disabled_cache.add(object_id) if unprepared_statement_forced
785+
end
786+
787+
def select_value_forcing_binds(arel, name, binds)
788+
single_value_from_rows(select_values_forcing_binds(arel, name, binds))
789+
end
782790

783-
ActiveRecord::Type.register(:boolean, Type::OracleEnhanced::Boolean, adapter: :oracle_enhanced)
784-
ActiveRecord::Type.register(:json, Type::OracleEnhanced::Json, adapter: :oracle_enhanced)
791+
ActiveRecord::Type.register(:boolean, Type::OracleEnhanced::Boolean, adapter: :oracle_enhanced)
792+
ActiveRecord::Type.register(:json, Type::OracleEnhanced::Json, adapter: :oracle_enhanced)
785793
end
786794
end
787795
end

0 commit comments

Comments
 (0)