diff --git a/lib/active_record/pg_extensions/transaction.rb b/lib/active_record/pg_extensions/transaction.rb index aac3d02..94826c4 100644 --- a/lib/active_record/pg_extensions/transaction.rb +++ b/lib/active_record/pg_extensions/transaction.rb @@ -14,6 +14,9 @@ def #{kind}(local: false) private def #{kind}=(timeout) return if @#{kind} == timeout + # must precede dirty!, which disables lazy connect; connecting after would discard this transaction + connection.connect! unless connection.connected? + @#{kind} = timeout # If we have set an explicit timeout, the transaction has state that must be materialized # separately from any other transaction, so it cannot be `restartable` diff --git a/spec/postgresql_adapter_spec.rb b/spec/postgresql_adapter_spec.rb index b3dac06..7ca6599 100644 --- a/spec/postgresql_adapter_spec.rb +++ b/spec/postgresql_adapter_spec.rb @@ -437,6 +437,26 @@ end end + describe "#statement_timeout= on a connection that hasn't been used yet" do + before { connection.disconnect! } + + it "materializes the transaction against a live connection" do + expect do + connection.transaction do + connection.statement_timeout = 30 + connection.select_value("SELECT 1") + end + end.not_to raise_error + end + + it "still applies the timeout" do + connection.transaction do + connection.statement_timeout = 0.01 + expect { connection.execute("SELECT pg_sleep(3)") }.to raise_error(ActiveRecord::QueryCanceled) + end + end + end + describe "#rename_constraint" do around do |example| connection.dont_execute(&example)