From da26910fbcfa3aa23ebc1474b43b048b78b60e4c Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 12 Feb 2021 22:25:35 +0900 Subject: [PATCH] Fix `unprepared_statement` to work it when nesting I've been reported a problem by @osyo-manga, preloading queries in `unprepared_statement` doesn't work as expected in main branch (queries are executed as prepared statements). It is caused by #41385, due to `scope.to_sql` in `grouping_key` depends on `unprepared_statement` which has an issue when nesting. To fix the issue, don't add/delete object_id in the prepared statements disabled cache if that is already disabled. --- .../connection_adapters/abstract_adapter.rb | 5 +++-- activerecord/test/cases/bind_parameter_test.rb | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index f588f76d85..7e0160e7cb 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -160,9 +160,10 @@ module ActiveRecord end end - def prepared_statements + def prepared_statements? @prepared_statements && !prepared_statements_disabled_cache.include?(object_id) end + alias :prepared_statements :prepared_statements? def prepared_statements_disabled_cache # :nodoc: Thread.current[:ar_prepared_statements_disabled_cache] ||= Set.new @@ -256,7 +257,7 @@ module ActiveRecord end def unprepared_statement - cache = prepared_statements_disabled_cache.add(object_id) if @prepared_statements + cache = prepared_statements_disabled_cache.add?(object_id) if @prepared_statements yield ensure cache&.delete(object_id) diff --git a/activerecord/test/cases/bind_parameter_test.rb b/activerecord/test/cases/bind_parameter_test.rb index 3de48e13a1..dab940b12e 100644 --- a/activerecord/test/cases/bind_parameter_test.rb +++ b/activerecord/test/cases/bind_parameter_test.rb @@ -173,6 +173,22 @@ if ActiveRecord::Base.connection.prepared_statements end end + def test_nested_unprepared_statements + assert_predicate @connection, :prepared_statements? + + @connection.unprepared_statement do + assert_not_predicate @connection, :prepared_statements? + + @connection.unprepared_statement do + assert_not_predicate @connection, :prepared_statements? + end + + assert_not_predicate @connection, :prepared_statements? + end + + assert_predicate @connection, :prepared_statements? + end + private def assert_bind_params_to_sql table = Author.quoted_table_name