aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2019-04-22 21:56:08 +0900
committerGitHub <noreply@github.com>2019-04-22 21:56:08 +0900
commitada56f859113a5ab055c49b79a514cdae281d56b (patch)
treee6e7cf223d7fbdec96099c59806a3bccb4c772f0
parent759c8d58c796ae670f3fc17a35766540f5740ecf (diff)
parentb6828fc91531ae0cc0a0f216705dd19112596301 (diff)
downloadrails-ada56f859113a5ab055c49b79a514cdae281d56b.tar.gz
rails-ada56f859113a5ab055c49b79a514cdae281d56b.tar.bz2
rails-ada56f859113a5ab055c49b79a514cdae281d56b.zip
Merge pull request #36052 from kamipo/fast_id
PERF: 20% faster pk attribute access
-rw-r--r--activerecord/lib/active_record/attribute_methods.rb2
-rw-r--r--activerecord/lib/active_record/attribute_methods/primary_key.rb16
-rw-r--r--activerecord/lib/active_record/attribute_methods/read.rb3
-rw-r--r--activerecord/lib/active_record/attribute_methods/write.rb3
-rw-r--r--activerecord/lib/active_record/core.rb6
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb4
-rw-r--r--activerecord/lib/active_record/persistence.rb9
-rw-r--r--activerecord/lib/active_record/transactions.rb5
-rw-r--r--activerecord/test/cases/primary_keys_test.rb8
9 files changed, 30 insertions, 26 deletions
diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb
index 331813f338..220043c061 100644
--- a/activerecord/lib/active_record/attribute_methods.rb
+++ b/activerecord/lib/active_record/attribute_methods.rb
@@ -465,7 +465,7 @@ module ActiveRecord
end
def pk_attribute?(name)
- name == self.class.primary_key
+ name == @primary_key
end
end
end
diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb
index feaef72a30..b4f5e6e75a 100644
--- a/activerecord/lib/active_record/attribute_methods/primary_key.rb
+++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb
@@ -16,34 +16,32 @@ module ActiveRecord
# Returns the primary key column's value.
def id
- primary_key = self.class.primary_key
- _read_attribute(primary_key) if primary_key
+ _read_attribute(@primary_key)
end
# Sets the primary key column's value.
def id=(value)
- primary_key = self.class.primary_key
- _write_attribute(primary_key, value) if primary_key
+ _write_attribute(@primary_key, value)
end
# Queries the primary key column's value.
def id?
- query_attribute(self.class.primary_key)
+ query_attribute(@primary_key)
end
# Returns the primary key column's value before type cast.
def id_before_type_cast
- read_attribute_before_type_cast(self.class.primary_key)
+ read_attribute_before_type_cast(@primary_key)
end
# Returns the primary key column's previous value.
def id_was
- attribute_was(self.class.primary_key)
+ attribute_was(@primary_key)
end
# Returns the primary key column's value from the database.
def id_in_database
- attribute_in_database(self.class.primary_key)
+ attribute_in_database(@primary_key)
end
private
@@ -116,7 +114,7 @@ module ActiveRecord
#
# Project.primary_key # => "foo_id"
def primary_key=(value)
- @primary_key = value && value.to_s
+ @primary_key = value && -value.to_s
@quoted_primary_key = nil
@attributes_builder = nil
end
diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb
index 409a150e56..c787fb6a94 100644
--- a/activerecord/lib/active_record/attribute_methods/read.rb
+++ b/activerecord/lib/active_record/attribute_methods/read.rb
@@ -31,8 +31,7 @@ module ActiveRecord
name = self.class.attribute_alias(name)
end
- primary_key = self.class.primary_key
- name = primary_key if name == "id" && primary_key
+ name = @primary_key if name == "id" && @primary_key
_read_attribute(name, &block)
end
diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb
index 6a21643884..6a54bd2fc2 100644
--- a/activerecord/lib/active_record/attribute_methods/write.rb
+++ b/activerecord/lib/active_record/attribute_methods/write.rb
@@ -35,8 +35,7 @@ module ActiveRecord
name = self.class.attribute_alias(name)
end
- primary_key = self.class.primary_key
- name = primary_key if name == "id" && primary_key
+ name = @primary_key if name == "id" && @primary_key
_write_attribute(name, value)
end
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index b9046fcc1a..068ebf3c09 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -174,8 +174,7 @@ module ActiveRecord
record = statement.execute([id], connection)&.first
unless record
- raise RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}",
- name, primary_key, id)
+ raise RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id)
end
record
end
@@ -398,7 +397,7 @@ module ActiveRecord
##
def initialize_dup(other) # :nodoc:
@attributes = @attributes.deep_dup
- @attributes.reset(self.class.primary_key)
+ @attributes.reset(@primary_key)
_run_initialize_callbacks
@@ -570,6 +569,7 @@ module ActiveRecord
end
def init_internals
+ @primary_key = self.class.primary_key
@readonly = false
@destroyed = false
@marked_for_destruction = false
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index b7eecda59e..6711ee9bf4 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -87,7 +87,7 @@ module ActiveRecord
affected_rows = self.class._update_record(
attributes_with_values(attribute_names),
- self.class.primary_key => id_in_database,
+ @primary_key => id_in_database,
locking_column => previous_lock_value
)
@@ -110,7 +110,7 @@ module ActiveRecord
locking_column = self.class.locking_column
affected_rows = self.class._delete_record(
- self.class.primary_key => id_in_database,
+ @primary_key => id_in_database,
locking_column => read_attribute_before_type_cast(locking_column)
)
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index bd572486c8..1ff7ee4d89 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -353,6 +353,7 @@ module ActiveRecord
end
def _insert_record(values) # :nodoc:
+ primary_key = self.primary_key
primary_key_value = nil
if primary_key && Hash === values
@@ -674,7 +675,7 @@ module ActiveRecord
affected_rows = self.class._update_record(
attributes,
- self.class.primary_key => id_in_database
+ @primary_key => id_in_database
)
affected_rows == 1
@@ -874,7 +875,7 @@ module ActiveRecord
end
def _delete_row
- self.class._delete_record(self.class.primary_key => id_in_database)
+ self.class._delete_record(@primary_key => id_in_database)
end
def _touch_row(attribute_names, time)
@@ -890,7 +891,7 @@ module ActiveRecord
def _update_row(attribute_names, attempted_action = "update")
self.class._update_record(
attributes_with_values(attribute_names),
- self.class.primary_key => id_in_database
+ @primary_key => id_in_database
)
end
@@ -928,7 +929,7 @@ module ActiveRecord
attributes_with_values(attribute_names)
)
- self.id ||= new_id if self.class.primary_key
+ self.id ||= new_id if @primary_key
@new_record = false
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index 9f52734e00..49a8206c84 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -432,9 +432,8 @@ module ActiveRecord
end
@mutations_from_database = nil
@mutations_before_last_save = nil
- pk = self.class.primary_key
- if pk && @attributes.fetch_value(pk) != restore_state[:id]
- @attributes.write_from_user(pk, restore_state[:id])
+ if @attributes.fetch_value(@primary_key) != restore_state[:id]
+ @attributes.write_from_user(@primary_key, restore_state[:id])
end
freeze if restore_state[:frozen?]
end
diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb
index 4759d3b6b2..511d7fc982 100644
--- a/activerecord/test/cases/primary_keys_test.rb
+++ b/activerecord/test/cases/primary_keys_test.rb
@@ -203,6 +203,14 @@ class PrimaryKeysTest < ActiveRecord::TestCase
assert_queries(3, ignore_none: true) { klass.create! }
end
+ def test_assign_id_raises_error_if_primary_key_doesnt_exist
+ klass = Class.new(ActiveRecord::Base) do
+ self.table_name = "dashboards"
+ end
+ dashboard = klass.new
+ assert_raises(ActiveModel::MissingAttributeError) { dashboard.id = "1" }
+ end
+
if current_adapter?(:PostgreSQLAdapter)
def test_serial_with_quoted_sequence_name
column = MixedCaseMonkey.columns_hash[MixedCaseMonkey.primary_key]