From a67841eb61f808a965da0d61ea47e2d9810436b0 Mon Sep 17 00:00:00 2001
From: Ryuta Kamizono <kamipo@gmail.com>
Date: Sun, 3 Mar 2019 13:08:50 +0900
Subject: Ensure `clear_cache!` clears the prepared statements cache

Since #23461, all adapters supports prepared statements, so that clears
the prepared statements cache is no longer database specific.

Actually, I struggled to identify the cause of random CI failure in
#23461, that was missing `@statements.clear` in `clear_cache!`.

This extracts `clear_cache!` to ensure the common concerns in the
abstract adapter.
---
 .../active_record/connection_adapters/abstract_adapter.rb  | 10 ++++++----
 .../connection_adapters/abstract_mysql_adapter.rb          | 11 ++++++-----
 .../connection_adapters/postgresql_adapter.rb              | 14 ++++----------
 .../active_record/connection_adapters/sqlite3_adapter.rb   | 12 +++++-------
 4 files changed, 21 insertions(+), 26 deletions(-)

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index cf6a1217a0..c2087b8216 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -120,6 +120,7 @@ module ActiveRecord
         @quoted_column_names, @quoted_table_names = {}, {}
         @prevent_writes = false
         @visitor = arel_visitor
+        @statements = build_statement_pool
         @lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
 
         if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
@@ -492,11 +493,9 @@ module ActiveRecord
         # this should be overridden by concrete adapters
       end
 
-      ###
-      # Clear any caching the database adapter may be doing, for example
-      # clearing the prepared statement cache. This is database specific.
+      # Clear any caching the database adapter may be doing.
       def clear_cache!
-        # this should be overridden by concrete adapters
+        @lock.synchronize { @statements.clear } if @statements
       end
 
       # Returns true if its required to reload the connection between requests for development mode.
@@ -718,6 +717,9 @@ module ActiveRecord
         def arel_visitor
           Arel::Visitors::ToSql.new(self)
         end
+
+        def build_statement_pool
+        end
     end
   end
 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 1aab36c865..d99c9b9d02 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -53,8 +53,6 @@ module ActiveRecord
 
       def initialize(connection, logger, connection_options, config)
         super(connection, logger, config)
-
-        @statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
       end
 
       def version #:nodoc:
@@ -162,10 +160,9 @@ module ActiveRecord
 
       # CONNECTION MANAGEMENT ====================================
 
-      # Clears the prepared statements cache.
-      def clear_cache!
+      def clear_cache! # :nodoc:
         reload_type_map
-        @statements.clear
+        super
       end
 
       #--
@@ -806,6 +803,10 @@ module ActiveRecord
           Arel::Visitors::MySQL.new(self)
         end
 
+        def build_statement_pool
+          StatementPool.new(self.class.type_cast_config_to_integer(@config[:statement_limit]))
+        end
+
         def mismatched_foreign_key(message, sql:, binds:)
           match = %r/
             (?:CREATE|ALTER)\s+TABLE\s*(?:`?\w+`?\.)?`?(?<table>\w+)`?.+?
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 5919801519..05d8d5ac00 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -253,9 +253,6 @@ module ActiveRecord
 
         configure_connection
         add_pg_encoders
-        @statements = StatementPool.new @connection,
-                                        self.class.type_cast_config_to_integer(config[:statement_limit])
-
         add_pg_decoders
 
         @type_map = Type::HashLookupTypeMap.new
@@ -264,13 +261,6 @@ module ActiveRecord
         @use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
       end
 
-      # Clears the prepared statements cache.
-      def clear_cache!
-        @lock.synchronize do
-          @statements.clear
-        end
-      end
-
       def truncate(table_name, name = nil)
         exec_query "TRUNCATE TABLE #{quote_table_name(table_name)}", name, []
       end
@@ -828,6 +818,10 @@ module ActiveRecord
           Arel::Visitors::PostgreSQL.new(self)
         end
 
+        def build_statement_pool
+          StatementPool.new(@connection, self.class.type_cast_config_to_integer(@config[:statement_limit]))
+        end
+
         def can_perform_case_insensitive_comparison_for?(column)
           @case_insensitive_cache ||= {}
           @case_insensitive_cache[column.sql_type] ||= begin
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index 0ed7f3988d..cb3d34a740 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -96,8 +96,7 @@ module ActiveRecord
       def initialize(connection, logger, connection_options, config)
         super(connection, logger, config)
 
-        @active     = true
-        @statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
+        @active = true
         configure_connection
       end
 
@@ -156,11 +155,6 @@ module ActiveRecord
         @connection.close rescue nil
       end
 
-      # Clears the prepared statements cache.
-      def clear_cache!
-        @statements.clear
-      end
-
       def truncate(table_name, name = nil)
         execute "DELETE FROM #{quote_table_name(table_name)}", name
       end
@@ -613,6 +607,10 @@ module ActiveRecord
           Arel::Visitors::SQLite.new(self)
         end
 
+        def build_statement_pool
+          StatementPool.new(self.class.type_cast_config_to_integer(@config[:statement_limit]))
+        end
+
         def configure_connection
           execute("PRAGMA foreign_keys = ON", "SCHEMA")
         end
-- 
cgit v1.2.3