aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/CHANGELOG.md7
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb5
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb4
-rw-r--r--activerecord/lib/active_record/errors.rb8
-rw-r--r--activerecord/lib/active_record/relation.rb1
-rw-r--r--activerecord/test/cases/adapters/mysql2/transaction_test.rb31
-rw-r--r--activerecord/test/cases/adapters/postgresql/transaction_test.rb35
-rw-r--r--activerecord/test/cases/finder_test.rb16
-rw-r--r--railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt6
-rw-r--r--railties/lib/rails/generators/named_base.rb4
-rw-r--r--railties/test/generators/scaffold_generator_test.rb8
11 files changed, 85 insertions, 40 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 217eada1d7..40a26d98e1 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,8 @@
+* Add new error class `QueryCanceled` which will be raised
+ when canceling statement due to user request.
+
+ *Ryuta Kamizono*
+
* Add `#up_only` to database migrations for code that is only relevant when
migrating up, e.g. populating a new column.
@@ -190,7 +195,7 @@
*Jeremy Green*
-* Add new error class `TransactionTimeout` which will be raised
+* Add new error class `LockWaitTimeout` which will be raised
when lock wait timeout exceeded.
*Gabriel Courtemanche*
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 0e552dba95..ede8a9c1e2 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -635,6 +635,7 @@ module ActiveRecord
ER_CANNOT_ADD_FOREIGN = 1215
ER_CANNOT_CREATE_TABLE = 1005
ER_LOCK_WAIT_TIMEOUT = 1205
+ ER_QUERY_INTERRUPTED = 1317
ER_QUERY_TIMEOUT = 3024
def translate_exception(exception, message)
@@ -660,9 +661,11 @@ module ActiveRecord
when ER_LOCK_DEADLOCK
Deadlocked.new(message)
when ER_LOCK_WAIT_TIMEOUT
- TransactionTimeout.new(message)
+ LockWaitTimeout.new(message)
when ER_QUERY_TIMEOUT
StatementTimeout.new(message)
+ when ER_QUERY_INTERRUPTED
+ QueryCanceled.new(message)
else
super
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 1739c288b6..7b27f6b7a0 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -418,9 +418,9 @@ module ActiveRecord
when DEADLOCK_DETECTED
Deadlocked.new(message)
when LOCK_NOT_AVAILABLE
- TransactionTimeout.new(message)
+ LockWaitTimeout.new(message)
when QUERY_CANCELED
- StatementTimeout.new(message)
+ QueryCanceled.new(message)
else
super
end
diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb
index 7382879fce..efcbd44776 100644
--- a/activerecord/lib/active_record/errors.rb
+++ b/activerecord/lib/active_record/errors.rb
@@ -335,14 +335,18 @@ module ActiveRecord
class IrreversibleOrderError < ActiveRecordError
end
- # TransactionTimeout will be raised when lock wait timeout exceeded.
- class TransactionTimeout < StatementInvalid
+ # LockWaitTimeout will be raised when lock wait timeout exceeded.
+ class LockWaitTimeout < StatementInvalid
end
# StatementTimeout will be raised when statement timeout exceeded.
class StatementTimeout < StatementInvalid
end
+ # QueryCanceled will be raised when canceling statement due to user request.
+ class QueryCanceled < StatementInvalid
+ end
+
# UnknownAttributeReference is raised when an unknown and potentially unsafe
# value is passed to a query method when allow_unsafe_raw_sql is set to
# :disabled. For example, passing a non column name value to a relation's
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index d3b8091665..081ef5771f 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -544,7 +544,6 @@ module ActiveRecord
end
@records.each(&:readonly!) if readonly_value
- @offsets = {} unless @offsets.empty?
@loaded = true
@records
diff --git a/activerecord/test/cases/adapters/mysql2/transaction_test.rb b/activerecord/test/cases/adapters/mysql2/transaction_test.rb
index 4a3a4503de..cb183cc54c 100644
--- a/activerecord/test/cases/adapters/mysql2/transaction_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/transaction_test.rb
@@ -60,8 +60,8 @@ module ActiveRecord
end
end
- test "raises TransactionTimeout when lock wait timeout exceeded" do
- assert_raises(ActiveRecord::TransactionTimeout) do
+ test "raises LockWaitTimeout when lock wait timeout exceeded" do
+ assert_raises(ActiveRecord::LockWaitTimeout) do
s = Sample.create!(value: 1)
latch1 = Concurrent::CountDownLatch.new
latch2 = Concurrent::CountDownLatch.new
@@ -116,5 +116,32 @@ module ActiveRecord
end
end
end
+
+ test "raises QueryCanceled when canceling statement due to user request" do
+ assert_raises(ActiveRecord::QueryCanceled) do
+ s = Sample.create!(value: 1)
+ latch = Concurrent::CountDownLatch.new
+
+ thread = Thread.new do
+ Sample.transaction do
+ Sample.lock.find(s.id)
+ latch.count_down
+ sleep(0.5)
+ conn = Sample.connection
+ pid = conn.query_value("SELECT id FROM information_schema.processlist WHERE info LIKE '% FOR UPDATE'")
+ conn.execute("KILL QUERY #{pid}")
+ end
+ end
+
+ begin
+ Sample.transaction do
+ latch.wait
+ Sample.lock.find(s.id)
+ end
+ ensure
+ thread.join
+ end
+ end
+ end
end
end
diff --git a/activerecord/test/cases/adapters/postgresql/transaction_test.rb b/activerecord/test/cases/adapters/postgresql/transaction_test.rb
index 4d63bbce59..c24dfeb345 100644
--- a/activerecord/test/cases/adapters/postgresql/transaction_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/transaction_test.rb
@@ -91,9 +91,9 @@ module ActiveRecord
end
end
- test "raises TransactionTimeout when lock wait timeout exceeded" do
+ test "raises LockWaitTimeout when lock wait timeout exceeded" do
skip unless ActiveRecord::Base.connection.postgresql_version >= 90300
- assert_raises(ActiveRecord::TransactionTimeout) do
+ assert_raises(ActiveRecord::LockWaitTimeout) do
s = Sample.create!(value: 1)
latch1 = Concurrent::CountDownLatch.new
latch2 = Concurrent::CountDownLatch.new
@@ -120,8 +120,8 @@ module ActiveRecord
end
end
- test "raises StatementTimeout when statement timeout exceeded" do
- assert_raises(ActiveRecord::StatementTimeout) do
+ test "raises QueryCanceled when statement timeout exceeded" do
+ assert_raises(ActiveRecord::QueryCanceled) do
s = Sample.create!(value: 1)
latch1 = Concurrent::CountDownLatch.new
latch2 = Concurrent::CountDownLatch.new
@@ -148,6 +148,33 @@ module ActiveRecord
end
end
+ test "raises QueryCanceled when canceling statement due to user request" do
+ assert_raises(ActiveRecord::QueryCanceled) do
+ s = Sample.create!(value: 1)
+ latch = Concurrent::CountDownLatch.new
+
+ thread = Thread.new do
+ Sample.transaction do
+ Sample.lock.find(s.id)
+ latch.count_down
+ sleep(0.5)
+ conn = Sample.connection
+ pid = conn.query_value("SELECT pid FROM pg_stat_activity WHERE query LIKE '% FOR UPDATE'")
+ conn.execute("SELECT pg_cancel_backend(#{pid})")
+ end
+ end
+
+ begin
+ Sample.transaction do
+ latch.wait
+ Sample.lock.find(s.id)
+ end
+ ensure
+ thread.join
+ end
+ end
+ end
+
private
def with_warning_suppression
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index 93957ff50f..e936c56ab8 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -691,22 +691,6 @@ class FinderTest < ActiveRecord::TestCase
assert_kind_of Array, Topic.last(5)
end
- def test_first_should_respect_loaded_records
- authors = Author.order(:name)
-
- assert_equal authors(:bob), authors.first
-
- aaron = authors.create!(name: "Aaron")
-
- authors.load
-
- assert_no_queries do
- assert_equal aaron, authors.first
- assert_equal authors(:bob), authors.second
- assert_not_equal authors.first, authors.second
- end
- end
-
def test_unexisting_record_exception_handling
assert_raise(ActiveRecord::RecordNotFound) {
Topic.find(1).parent
diff --git a/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt
index 0eb9d82bbb..518cb1121e 100644
--- a/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt
+++ b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt
@@ -15,15 +15,15 @@
<div class="field">
<% if attribute.password_digest? -%>
<%%= form.label :password %>
- <%%= form.password_field :password, id: :<%= field_id(:password) %> %>
+ <%%= form.password_field :password %>
</div>
<div class="field">
<%%= form.label :password_confirmation %>
- <%%= form.password_field :password_confirmation, id: :<%= field_id(:password_confirmation) %> %>
+ <%%= form.password_field :password_confirmation %>
<% else -%>
<%%= form.label :<%= attribute.column_name %> %>
- <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, id: :<%= field_id(attribute.column_name) %> %>
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %> %>
<% end -%>
</div>
diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb
index 99165168fd..98fcc95964 100644
--- a/railties/lib/rails/generators/named_base.rb
+++ b/railties/lib/rails/generators/named_base.rb
@@ -114,10 +114,6 @@ module Rails
"new_#{singular_route_name}_url"
end
- def field_id(attribute_name)
- [singular_table_name, attribute_name].join("_")
- end
-
def singular_table_name # :doc:
@singular_table_name ||= (pluralize_table_names? ? table_name.singularize : table_name)
end
diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb
index b6294c3b94..29426cd99f 100644
--- a/railties/test/generators/scaffold_generator_test.rb
+++ b/railties/test/generators/scaffold_generator_test.rb
@@ -471,8 +471,8 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
end
assert_file "app/views/accounts/_form.html.erb" do |content|
- assert_match(/^\W{4}<%= form\.text_field :name, id: :account_name %>/, content)
- assert_match(/^\W{4}<%= form\.text_field :currency_id, id: :account_currency_id %>/, content)
+ assert_match(/^\W{4}<%= form\.text_field :name %>/, content)
+ assert_match(/^\W{4}<%= form\.text_field :currency_id %>/, content)
end
end
@@ -495,8 +495,8 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
end
assert_file "app/views/users/_form.html.erb" do |content|
- assert_match(/<%= form\.password_field :password, id: :user_password %>/, content)
- assert_match(/<%= form\.password_field :password_confirmation, id: :user_password_confirmation %>/, content)
+ assert_match(/<%= form\.password_field :password %>/, content)
+ assert_match(/<%= form\.password_field :password_confirmation %>/, content)
end
assert_file "app/views/users/index.html.erb" do |content|