From a456acb2f2af8365eb9151c7cd2d5a10c189d191 Mon Sep 17 00:00:00 2001 From: Harry Marr Date: Wed, 28 Oct 2015 16:30:02 +0000 Subject: Avoid disabling postgres errors The standard_conforming_strings setting doesn't exist on all versions of Postgres, but if it does exist, Rails turns it on. Previously this was done by effectively disabling errors on the Postgres connection, issuing a SET to turn the setting on, then re-enabling errors on the connection. However, if you're running pgbouncer in transaction-pooling mode, you can't guarantee that successive calls to `#execute` will be sent to the same pgbouncer-postgres connection, so you can end up disabling errors on a different postgres connection, and never re-enabling them. Future queries on that connection that result in errors (e.g. violating unique constraints) will leave the connection in a bad state where successive queries will fail. This commit sets standard_conforming_strings by issuing an UPDATE to pg_settings, which will update the setting if it exists, and do nothing if it doesn't (rather than erroring out like SET would), which means we can remove the error-disabling code. It's also worth noting that Postgres has allowed standard_conforming_strings to be updated since 8.2 (which is the oldest version Rails supports), so technically we probably don't even need to be defensive here. --- .../lib/active_record/connection_adapters/postgresql_adapter.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (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 236c067fd5..2c9b1a0b3d 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -283,10 +283,11 @@ module ActiveRecord # Enable standard-conforming strings if available. def set_standard_conforming_strings - old, self.client_min_messages = client_min_messages, 'panic' - execute('SET standard_conforming_strings = on', 'SCHEMA') rescue nil - ensure - self.client_min_messages = old + execute(<<-SQL, 'SCHEMA') + UPDATE pg_settings + SET setting = 'on' + WHERE name = 'standard_conforming_strings' + SQL end def supports_ddl_transactions? -- cgit v1.2.3 From d05bfa82ae1bb6dfb6dd4c4a7e089eff456cf4af Mon Sep 17 00:00:00 2001 From: Harry Marr Date: Thu, 29 Oct 2015 12:03:43 +0000 Subject: Check standard_conforming_strings is not readonly In Postgres 8.1 the standard_conforming_strings setting was read-only, meaning you got an error if you tried to update it. By filtering on `context = 'user'` we only try to update the setting if it's user-writable[1]. [1]: http://www.postgresql.org/docs/9.4/static/view-pg-settings.html --- .../lib/active_record/connection_adapters/postgresql_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 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 2c9b1a0b3d..1b8f8cab94 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -286,7 +286,7 @@ module ActiveRecord execute(<<-SQL, 'SCHEMA') UPDATE pg_settings SET setting = 'on' - WHERE name = 'standard_conforming_strings' + WHERE name = 'standard_conforming_strings' AND context = 'user' SQL end -- cgit v1.2.3