mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
PostgreSQL: Use native timestamp decoders of pg-1.1
This improves performance of timestamp conversion and avoids additional string allocations.
This commit is contained in:
parent
de0c705516
commit
c6d7e70be4
2 changed files with 33 additions and 3 deletions
|
@ -236,6 +236,8 @@ module ActiveRecord
|
|||
|
||||
# @local_tz is initialized as nil to avoid warnings when connect tries to use it
|
||||
@local_tz = nil
|
||||
@default_timezone = nil
|
||||
@timestamp_decoder = nil
|
||||
@max_identifier_length = nil
|
||||
|
||||
configure_connection
|
||||
|
@ -628,6 +630,10 @@ module ActiveRecord
|
|||
def exec_no_cache(sql, name, binds)
|
||||
materialize_transactions
|
||||
|
||||
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
||||
# made since we established the connection
|
||||
update_typemap_for_default_timezone
|
||||
|
||||
type_casted_binds = type_casted_binds(binds)
|
||||
log(sql, name, binds, type_casted_binds) do
|
||||
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
||||
|
@ -638,6 +644,7 @@ module ActiveRecord
|
|||
|
||||
def exec_cache(sql, name, binds)
|
||||
materialize_transactions
|
||||
update_typemap_for_default_timezone
|
||||
|
||||
stmt_key = prepare_statement(sql, binds)
|
||||
type_casted_binds = type_casted_binds(binds)
|
||||
|
@ -826,6 +833,18 @@ module ActiveRecord
|
|||
@connection.type_map_for_queries = map
|
||||
end
|
||||
|
||||
def update_typemap_for_default_timezone
|
||||
if @default_timezone != ActiveRecord::Base.default_timezone && @timestamp_decoder
|
||||
decoder_class = ActiveRecord::Base.default_timezone == :utc ?
|
||||
PG::TextDecoder::TimestampUtc :
|
||||
PG::TextDecoder::TimestampWithoutTimeZone
|
||||
|
||||
@timestamp_decoder = decoder_class.new(@timestamp_decoder.to_h)
|
||||
@connection.type_map_for_results.add_coder(@timestamp_decoder)
|
||||
@default_timezone = ActiveRecord::Base.default_timezone
|
||||
end
|
||||
end
|
||||
|
||||
def add_pg_decoders
|
||||
coders_by_name = {
|
||||
"int2" => PG::TextDecoder::Integer,
|
||||
|
@ -836,6 +855,13 @@ module ActiveRecord
|
|||
"float8" => PG::TextDecoder::Float,
|
||||
"bool" => PG::TextDecoder::Boolean,
|
||||
}
|
||||
|
||||
if defined?(PG::TextDecoder::TimestampUtc)
|
||||
# Use native PG encoders available since pg-1.1
|
||||
coders_by_name["timestamp"] = PG::TextDecoder::TimestampUtc
|
||||
coders_by_name["timestamptz"] = PG::TextDecoder::TimestampWithTimeZone
|
||||
end
|
||||
|
||||
known_coder_types = coders_by_name.keys.map { |n| quote(n) }
|
||||
query = <<~SQL % known_coder_types.join(", ")
|
||||
SELECT t.oid, t.typname
|
||||
|
@ -851,6 +877,10 @@ module ActiveRecord
|
|||
map = PG::TypeMapByOid.new
|
||||
coders.each { |coder| map.add_coder(coder) }
|
||||
@connection.type_map_for_results = map
|
||||
|
||||
# extract timestamp decoder for use in update_typemap_for_default_timezone
|
||||
@timestamp_decoder = coders.find { |coder| coder.name == "timestamp" }
|
||||
update_typemap_for_default_timezone
|
||||
end
|
||||
|
||||
def construct_coder(row, coder_class)
|
||||
|
|
|
@ -51,7 +51,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
test "cache_version is the same when it comes from the DB or from the user" do
|
||||
skip("Mysql2 does not return a string value for updated_at") if current_adapter?(:Mysql2Adapter)
|
||||
skip("Mysql2 and PostgreSQL don't return a string value for updated_at") if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
|
||||
|
||||
record = CacheMeWithVersion.create
|
||||
record_from_db = CacheMeWithVersion.find(record.id)
|
||||
|
@ -63,7 +63,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
test "cache_version does not truncate zeros when timestamp ends in zeros" do
|
||||
skip("Mysql2 does not return a string value for updated_at") if current_adapter?(:Mysql2Adapter)
|
||||
skip("Mysql2 and PostgreSQL don't return a string value for updated_at") if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
|
||||
|
||||
travel_to Time.now.beginning_of_day do
|
||||
record = CacheMeWithVersion.create
|
||||
|
@ -84,7 +84,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
test "cache_version does NOT call updated_at when value is from the database" do
|
||||
skip("Mysql2 does not return a string value for updated_at") if current_adapter?(:Mysql2Adapter)
|
||||
skip("Mysql2 and PostgreSQL don't return a string value for updated_at") if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
|
||||
|
||||
record = CacheMeWithVersion.create
|
||||
record_from_db = CacheMeWithVersion.find(record.id)
|
||||
|
|
Loading…
Reference in a new issue