From 0239207dfb7d124e51b02d597f61433677c2e69f Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Thu, 16 Nov 2023 09:10:58 -0800 Subject: [PATCH] Respect :skip_transaction option in PostgreSQL Dataset#paged_each (Fixes #2097) This turns on the hold option, which does have effects beyond just not using a transaction, but you cannot use a non-HOLD cursor outside of a transaction. --- CHANGELOG | 2 ++ lib/sequel/adapters/postgres.rb | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index a5fb87eee4..dfa16a703c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ === master +* Respect :skip_transaction option in PostgreSQL Dataset#paged_each (jeremyevans) (#2097) + * Add TimestampMigrator.run_single to run a single migration file up or down (opya, jeremyevans) (#2093) * Support INSERT RETURNING on MariaDB 10.5+, and use it when saving new model objects (jeremyevans) diff --git a/lib/sequel/adapters/postgres.rb b/lib/sequel/adapters/postgres.rb index 15cff955ae..c373dbecf7 100644 --- a/lib/sequel/adapters/postgres.rb +++ b/lib/sequel/adapters/postgres.rb @@ -672,6 +672,7 @@ def paged_each(opts=OPTS, &block) # cursor usage. # :rows_per_fetch :: The number of rows per fetch (default 1000). Higher # numbers result in fewer queries but greater memory use. + # :skip_transaction :: Same as :hold, but :hold takes priority. # # Usage: # @@ -764,13 +765,13 @@ def call_procedure(name, args) # Use a cursor to fetch groups of records at a time, yielding them to the block. def cursor_fetch_rows(sql) - server_opts = {:server=>@opts[:server] || :read_only} cursor = @opts[:cursor] - hold = cursor[:hold] + hold = cursor.fetch(:hold){cursor[:skip_transaction]} + server_opts = {:server=>@opts[:server] || :read_only, :skip_transaction=>hold} cursor_name = quote_identifier(cursor[:cursor_name] || 'sequel_cursor') rows_per_fetch = cursor[:rows_per_fetch].to_i - db.public_send(*(hold ? [:synchronize, server_opts[:server]] : [:transaction, server_opts])) do + db.transaction(server_opts) do begin execute_ddl("DECLARE #{cursor_name} NO SCROLL CURSOR WITH#{'OUT' unless hold} HOLD FOR #{sql}", server_opts) rows_per_fetch = 1000 if rows_per_fetch <= 0