Skip to content

Commit 442c6f1

Browse files
committed
Merge PR #41356
Closes #41356 Closes #41034
1 parent 48af94b commit 442c6f1

File tree

3 files changed

+26
-5
lines changed

3 files changed

+26
-5
lines changed

activerecord/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
* Increment postgres prepared statement counter before making a prepared statement, so if the statement is aborted
2+
without Rails knowledge (e.g., if app gets kill -9d during long-running query or due to Rack::Timeout), app won't end
3+
up in perpetual crash state for being inconsistent with Postgres.
4+
5+
*wbharding*, *Martin Tepper*
6+
7+
18
## Rails 6.1.2.1 (February 10, 2021) ##
29

310
* Fix possible DoS vector in PostgreSQL money type

activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -227,11 +227,7 @@ def initialize(connection, max)
227227
end
228228

229229
def next_key
230-
"a#{@counter + 1}"
231-
end
232-
233-
def []=(sql, key)
234-
super.tap { @counter += 1 }
230+
"a#{@counter += 1}"
235231
end
236232

237233
private

activerecord/test/cases/adapters/postgresql/statement_pool_test.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# frozen_string_literal: true
22

33
require "cases/helper"
4+
require "models/computer"
5+
require "models/developer"
46

57
module ActiveRecord
68
module ConnectionAdapters
@@ -16,6 +18,8 @@ def status
1618
end
1719

1820
class StatementPoolTest < ActiveRecord::PostgreSQLTestCase
21+
fixtures :developers
22+
1923
if Process.respond_to?(:fork)
2024
def test_cache_is_per_pid
2125
cache = StatementPool.new nil, 10
@@ -37,6 +41,20 @@ def test_dealloc_does_not_raise_on_inactive_connection
3741
cache["foo"] = "bar"
3842
assert_nothing_raised { cache.clear }
3943
end
44+
45+
def test_prepared_statements_do_not_get_stuck_on_query_interruption
46+
pg_connection = ActiveRecord::Base.connection.instance_variable_get(:@connection)
47+
pg_connection.stub(:get_last_result, -> { raise "random error" }) do
48+
assert_raises(RuntimeError) do
49+
Developer.where(name: "David").last
50+
end
51+
52+
# without fix, this raises PG::DuplicatePstatement: ERROR: prepared statement "a3" already exists
53+
assert_raises(RuntimeError) do
54+
Developer.where(name: "David").last
55+
end
56+
end
57+
end
4058
end
4159
end
4260
end

0 commit comments

Comments
 (0)