From 66b4ddd3353e14b27214e156c949ba41e2ce5ba4 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Mon, 25 Feb 2019 23:40:20 +0900 Subject: Fix prepared statements caching to be enabled even when query caching is enabled Related cbcdecd, 2a56b2d. This is a regression caused by cbcdecd. If query caching is enabled, prepared statement handles are never re-used, since we missed that a query is preprocessed when query caching is enabled, but doesn't keep the `preparable` flag. We should care about that case. --- activerecord/test/cases/bind_parameter_test.rb | 57 +++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) (limited to 'activerecord/test') diff --git a/activerecord/test/cases/bind_parameter_test.rb b/activerecord/test/cases/bind_parameter_test.rb index ca97a5dc65..8c3fe0437c 100644 --- a/activerecord/test/cases/bind_parameter_test.rb +++ b/activerecord/test/cases/bind_parameter_test.rb @@ -34,6 +34,49 @@ if ActiveRecord::Base.connection.prepared_statements ActiveSupport::Notifications.unsubscribe(@subscription) end + def test_statement_cache + @connection.clear_cache! + + topics = Topic.where(id: 1) + assert_equal [1], topics.map(&:id) + assert_includes statement_cache, to_sql_key(topics.arel) + end + + def test_statement_cache_with_query_cache + @connection.enable_query_cache! + @connection.clear_cache! + + topics = Topic.where(id: 1) + assert_equal [1], topics.map(&:id) + assert_includes statement_cache, to_sql_key(topics.arel) + ensure + @connection.disable_query_cache! + end + + def test_statement_cache_with_find + @connection.clear_cache! + + topics = Topic.where(id: 1).limit(1) + assert_equal 1, Topic.find(1).id + assert_includes statement_cache, to_sql_key(topics.arel) + end + + def test_statement_cache_with_in_clause + @connection.clear_cache! + + topics = Topic.where(id: [1, 3]) + assert_equal [1, 3], topics.map(&:id) + assert_not_includes statement_cache, to_sql_key(topics.arel) + end + + def test_statement_cache_with_sql_string_literal + @connection.clear_cache! + + topics = Topic.where("topics.id = ?", 1) + assert_equal [1], topics.map(&:id) + assert_not_includes statement_cache, to_sql_key(topics.arel) + end + def test_too_many_binds bind_params_length = @connection.send(:bind_params_length) @@ -45,7 +88,8 @@ if ActiveRecord::Base.connection.prepared_statements end def test_too_many_binds_with_query_cache - Topic.connection.enable_query_cache! + @connection.enable_query_cache! + bind_params_length = @connection.send(:bind_params_length) topics = Topic.where(id: (1 .. bind_params_length + 1).to_a) assert_equal Topic.count, topics.count @@ -53,7 +97,7 @@ if ActiveRecord::Base.connection.prepared_statements topics = Topic.where.not(id: (1 .. bind_params_length + 1).to_a) assert_equal 0, topics.count ensure - Topic.connection.disable_query_cache! + @connection.disable_query_cache! end def test_bind_from_join_in_subquery @@ -90,6 +134,15 @@ if ActiveRecord::Base.connection.prepared_statements end private + def to_sql_key(arel) + sql = @connection.to_sql(arel) + @connection.respond_to?(:sql_key, true) ? @connection.send(:sql_key, sql) : sql + end + + def statement_cache + @connection.instance_variable_get(:@statements).send(:cache) + end + def assert_logs_binds(binds) payload = { name: "SQL", -- cgit v1.2.3