aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/associations/join_dependency.rb2
-rw-r--r--activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb16
-rw-r--r--activerecord/lib/active_record/base.rb3
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb2
-rw-r--r--activerecord/lib/active_record/explain.rb38
6 files changed, 46 insertions, 26 deletions
diff --git a/activerecord/lib/active_record/associations/join_dependency.rb b/activerecord/lib/active_record/associations/join_dependency.rb
index 6c878f0f00..827b01c5ac 100644
--- a/activerecord/lib/active_record/associations/join_dependency.rb
+++ b/activerecord/lib/active_record/associations/join_dependency.rb
@@ -184,7 +184,7 @@ module ActiveRecord
macro = join_part.reflection.macro
if macro == :has_one
- return if record.association_cache.key?(join_part.reflection.name)
+ return record.association(join_part.reflection.name).target if record.association_cache.key?(join_part.reflection.name)
association = join_part.instantiate(row) unless row[join_part.aliased_primary_key].nil?
set_target_and_inverse(join_part, association, record)
else
diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
index 236681096b..17cf34cdf6 100644
--- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
+++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
@@ -16,22 +16,16 @@ module ActiveRecord
module ClassMethods
protected
- # Defined for all +datetime+ and +timestamp+ attributes when +time_zone_aware_attributes+ are enabled.
- # This enhanced read method automatically converts the UTC time stored in the database to the time
+ # The enhanced read method automatically converts the UTC time stored in the database to the time
# zone stored in Time.zone.
- def internal_attribute_access_code(attr_name, cast_code)
+ def attribute_cast_code(attr_name)
column = columns_hash[attr_name]
if create_time_zone_conversion_attribute?(attr_name, column)
- super(attr_name, "(v=#{column.type_cast_code('v')}) && #{cast_code}")
- else
- super
- end
- end
+ typecast = "v = #{super}"
+ time_zone_conversion = "v.acts_like?(:time) ? v.in_time_zone : v"
- def attribute_cast_code(attr_name)
- if create_time_zone_conversion_attribute?(attr_name, columns_hash[attr_name])
- "(v.acts_like?(:time) ? v.in_time_zone : v)"
+ "((#{typecast}) && (#{time_zone_conversion}))"
else
super
end
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 3d55729318..9bc0023539 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -2028,7 +2028,7 @@ MSG
attribute_names.each do |name|
if (column = column_for_attribute(name)) && (include_primary_key || !column.primary)
- if include_readonly_attributes || (!include_readonly_attributes && !self.class.readonly_attributes.include?(name))
+ if include_readonly_attributes || !self.class.readonly_attributes.include?(name)
value = if klass.serialized_attributes.include?(name)
@attributes[name].serialized_value
@@ -2043,6 +2043,7 @@ MSG
end
end
end
+
attrs
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index 7f5ddf77d6..4d2c80356d 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -499,9 +499,14 @@ module ActiveRecord
# Returns a table's primary key and belonging sequence.
def pk_and_sequence_for(table)
- execute_and_free("SHOW INDEX FROM #{quote_table_name(table)} WHERE Key_name = 'PRIMARY'", 'SCHEMA') do |result|
- keys = each_hash(result).map { |row| row[:Column_name] }
- keys.length == 1 ? [keys.first, nil] : nil
+ execute_and_free("SHOW CREATE TABLE #{quote_table_name(table)}", 'SCHEMA') do |result|
+ create_table = each_hash(result).first[:"Create Table"]
+ if create_table.to_s =~ /PRIMARY KEY\s+\((.+)\)/
+ keys = $1.split(",").map { |key| key.gsub(/`/, "") }
+ keys.length == 1 ? [keys.first, nil] : nil
+ else
+ nil
+ end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index 0a0da0b5d3..386b3f7465 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -1,6 +1,6 @@
require 'active_record/connection_adapters/sqlite_adapter'
-gem 'sqlite3', '~> 1.3.4'
+gem 'sqlite3', '~> 1.3.5'
require 'sqlite3'
module ActiveRecord
diff --git a/activerecord/lib/active_record/explain.rb b/activerecord/lib/active_record/explain.rb
index 4d013f0ef4..abe6fff5d5 100644
--- a/activerecord/lib/active_record/explain.rb
+++ b/activerecord/lib/active_record/explain.rb
@@ -1,5 +1,5 @@
module ActiveRecord
- module Explain # :nodoc:
+ module Explain
# logging_query_plan calls could appear nested in the call stack. In
# particular this happens when a relation fetches its records, since
# that results in find_by_sql calls downwards.
@@ -13,33 +13,34 @@ module ActiveRecord
# whole. That is, the threshold is not checked against each individual
# query, but against the duration of the entire block. This approach is
# convenient for relations.
- def logging_query_plan(&block)
- if (t = auto_explain_threshold_in_seconds) && !Thread.current[LOGGING_QUERY_PLAN]
+ def logging_query_plan(&block) # :nodoc:
+ threshold = auto_explain_threshold_in_seconds
+ if threshold && !Thread.current[LOGGING_QUERY_PLAN] && !Thread.current[SILENCED]
begin
Thread.current[LOGGING_QUERY_PLAN] = true
start = Time.now
result, sqls, binds = collecting_sqls_for_explain(&block)
- logger.warn(exec_explain(sqls, binds)) if Time.now - start > t
+ logger.warn(exec_explain(sqls, binds)) if Time.now - start > threshold
result
ensure
Thread.current[LOGGING_QUERY_PLAN] = false
end
else
- block.call
+ yield
end
end
# SCHEMA queries cannot be EXPLAINed, also we do not want to run EXPLAIN on
# our own EXPLAINs now matter how loopingly beautiful that would be.
SKIP_EXPLAIN_FOR = %w(SCHEMA EXPLAIN)
- def ignore_explain_notification?(payload)
+ def ignore_explain_notification?(payload) # :nodoc:
payload[:exception] || SKIP_EXPLAIN_FOR.include?(payload[:name])
end
# Collects all queries executed while the passed block runs. Returns an
# array with three elements, the result of the block, the strings with the
# queries, and their respective bindings.
- def collecting_sqls_for_explain(&block)
+ def collecting_sqls_for_explain # :nodoc:
sqls = []
binds = []
callback = lambda do |*args|
@@ -52,7 +53,7 @@ module ActiveRecord
result = nil
ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
- result = block.call
+ result = yield
end
[result, sqls, binds]
@@ -60,7 +61,7 @@ module ActiveRecord
# Makes the adapter execute EXPLAIN for the given queries and bindings.
# Returns a formatted string ready to be logged.
- def exec_explain(sqls, binds)
+ def exec_explain(sqls, binds) # :nodoc:
sqls.zip(binds).map do |sql, bind|
[].tap do |msg|
msg << "EXPLAIN for: #{sql}"
@@ -72,5 +73,24 @@ module ActiveRecord
end.join("\n")
end.join("\n")
end
+
+ SILENCED = :silence_explain
+
+ # Silences automatic EXPLAIN logging for the duration of the block.
+ #
+ # This has high priority, no EXPLAINs will be run even if downwards
+ # the threshold is set to 0.
+ #
+ # As the name of the method suggests this only applies to automatic
+ # EXPLAINs, manual calls to +ActiveRecord::Relation#explain+ run.
+ def silence_auto_explain
+ # Implemented as a flag rather that setting the threshold to nil
+ # because we should not depend on a value that may be changed
+ # downwards.
+ Thread.current[SILENCED] = true
+ yield
+ ensure
+ Thread.current[SILENCED] = false
+ end
end
end