Skip to content

Commit 4e37a4c

Browse files
committed
The server discards prepared statements when disconnected
Most of the time this would currently be skipping deallocations because the connection is dead at the time of the call, but instead of relying on that call sequencing (and pointlessly sending a series of deallocations in other circumstances), we can simply drop our cache if the whole connection gets reset.
1 parent 746d115 commit 4e37a4c

File tree

4 files changed

+23
-6
lines changed

4 files changed

+23
-6
lines changed

activerecord/lib/active_record/connection_adapters/abstract_adapter.rb

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -549,14 +549,14 @@ def active?
549549
# new connection with the database. Implementors should call super if they
550550
# override the default implementation.
551551
def reconnect!
552-
clear_cache!
552+
clear_cache!(new_connection: true)
553553
reset_transaction
554554
end
555555

556556
# Disconnects from the database if already connected. Otherwise, this
557557
# method does nothing.
558558
def disconnect!
559-
clear_cache!
559+
clear_cache!(new_connection: true)
560560
reset_transaction
561561
end
562562

@@ -593,8 +593,16 @@ def throw_away!
593593
end
594594

595595
# Clear any caching the database adapter may be doing.
596-
def clear_cache!
597-
@lock.synchronize { @statements.clear } if @statements
596+
def clear_cache!(new_connection: false)
597+
if @statements
598+
@lock.synchronize do
599+
if new_connection
600+
@statements.reset
601+
else
602+
@statements.clear
603+
end
604+
end
605+
end
598606
end
599607

600608
# Returns true if its required to reload the connection between requests for development mode.

activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,23 +321,23 @@ def reload_type_map # :nodoc:
321321
# Close then reopen the connection.
322322
def reconnect!
323323
@lock.synchronize do
324-
super
325324
@connection.reset
326325
configure_connection
327326
reload_type_map
327+
super
328328
rescue PG::ConnectionBad
329329
connect
330330
end
331331
end
332332

333333
def reset!
334334
@lock.synchronize do
335-
clear_cache!
336335
reset_transaction
337336
unless @connection.transaction_status == ::PG::PQTRANS_IDLE
338337
@connection.query "ROLLBACK"
339338
end
340339
@connection.query "DISCARD ALL"
340+
clear_cache!(new_connection: true)
341341
configure_connection
342342
end
343343
end

activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ class SQLite3Adapter < AbstractAdapter
7777
}
7878

7979
class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
80+
alias reset clear
81+
8082
private
8183
def dealloc(stmt)
8284
stmt.close unless stmt.closed?

activerecord/lib/active_record/connection_adapters/statement_pool.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ def clear
4242
cache.clear
4343
end
4444

45+
# Clear the pool without deallocating; this is only safe when we
46+
# know the server has independently deallocated all statements
47+
# (e.g. due to a reconnect, or a DISCARD ALL)
48+
def reset
49+
cache.clear
50+
end
51+
4552
def delete(key)
4653
dealloc cache[key]
4754
cache.delete(key)

0 commit comments

Comments
 (0)