From bde898c1df17722a83e5e8866b2009273c5190c6 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 11 Dec 2018 04:33:48 +0900 Subject: Prevent write queries for `exec_query` Follow up #34505. --- .../connection_adapters/postgresql_adapter.rb | 4 +++ .../connection_adapters/sqlite3_adapter.rb | 6 +++- activerecord/test/cases/adapter_test.rb | 37 ++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 1c4e625ead..381d5ab29b 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -609,6 +609,10 @@ module ActiveRecord FEATURE_NOT_SUPPORTED = "0A000" #:nodoc: def execute_and_clear(sql, name, binds, prepare: false) + if preventing_writes? && write_query?(sql) + raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}" + end + if without_prepared_statement?(binds) result = exec_no_cache(sql, name, []) elsif !prepare diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index dcad230335..0b77dc7bc9 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -209,7 +209,7 @@ module ActiveRecord # DATABASE STATEMENTS ====================================== #++ - READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(:select) # :nodoc: + READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(:select, :pragma) # :nodoc: private_constant :READ_QUERY def write_query?(sql) # :nodoc: @@ -222,6 +222,10 @@ module ActiveRecord end def exec_query(sql, name = nil, binds = [], prepare: false) + if preventing_writes? && write_query?(sql) + raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}" + end + materialize_transactions type_casted_binds = type_casted_binds(binds) diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index e40ae3090c..79a431c7ee 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -165,6 +165,43 @@ module ActiveRecord end end + def test_errors_when_an_insert_query_is_called_while_preventing_writes + assert_raises(ActiveRecord::ReadOnlyError) do + @connection.while_preventing_writes do + @connection.insert("INSERT INTO subscribers(nick) VALUES ('138853948594')") + end + end + end + + def test_errors_when_an_update_query_is_called_while_preventing_writes + @connection.insert("INSERT INTO subscribers(nick) VALUES ('138853948594')") + + assert_raises(ActiveRecord::ReadOnlyError) do + @connection.while_preventing_writes do + @connection.update("UPDATE subscribers SET nick = '9989' WHERE nick = '138853948594'") + end + end + end + + def test_errors_when_a_delete_query_is_called_while_preventing_writes + @connection.insert("INSERT INTO subscribers(nick) VALUES ('138853948594')") + + assert_raises(ActiveRecord::ReadOnlyError) do + @connection.while_preventing_writes do + @connection.delete("DELETE FROM subscribers WHERE nick = '138853948594'") + end + end + end + + def test_doesnt_error_when_a_select_query_is_called_while_preventing_writes + @connection.insert("INSERT INTO subscribers(nick) VALUES ('138853948594')") + + @connection.while_preventing_writes do + result = @connection.select_all("SELECT subscribers.* FROM subscribers WHERE nick = '138853948594'") + assert_equal 1, result.length + end + end + def test_uniqueness_violations_are_translated_to_specific_exception @connection.execute "INSERT INTO subscribers(nick) VALUES('me')" error = assert_raises(ActiveRecord::RecordNotUnique) do -- cgit v1.2.3