aboutsummaryrefslogtreecommitdiff
path: root/contrib/postgres_fdw/postgres_fdw.c
diff options
context:
space:
mode:
authorEtsuro Fujita <efujita@postgresql.org>2024-07-19 13:15:03 +0900
committerEtsuro Fujita <efujita@postgresql.org>2024-07-19 13:15:03 +0900
commitd97f2ee50e49046a984665fb72fa14a06bd58435 (patch)
tree97606a4356090e8f76924015e4860d9fc1e6c228 /contrib/postgres_fdw/postgres_fdw.c
parent9cd365f28f31dc8ea9d8c10ec7abd658aa29fcf5 (diff)
downloadpostgresql-d97f2ee50e49046a984665fb72fa14a06bd58435.tar.gz
postgresql-d97f2ee50e49046a984665fb72fa14a06bd58435.zip
postgres_fdw: Avoid "cursor can only scan forward" error.
Commit d844cd75a disallowed rewind in a non-scrollable cursor to resolve anomalies arising from such a cursor operation. However, this failed to take into account the assumption in postgres_fdw that when rescanning a foreign relation, it can rewind the cursor created for scanning the foreign relation without specifying the SCROLL option, regardless of its scrollability, causing this error when it tried to do such a rewind in a non-scrollable cursor. Fix by modifying postgres_fdw to instead recreate the cursor, regardless of its scrollability, when rescanning the foreign relation. (If we had a way to check its scrollability, we could improve this by rewinding it if it is scrollable and recreating it if not, but we do not have it, so this commit modifies it to recreate it in any case.) Per bug #17889 from Eric Cyr. Devrim Gunduz also reported this problem. Back-patch to v15 where that commit enforced the prohibition. Reviewed by Tom Lane. Discussion: https://postgr.es/m/17889-e8c39a251d258dda%40postgresql.org Discussion: https://postgr.es/m/b415ac3255f8352d1ea921cf3b7ba39e0587768a.camel%40gunduz.org
Diffstat (limited to 'contrib/postgres_fdw/postgres_fdw.c')
-rw-r--r--contrib/postgres_fdw/postgres_fdw.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 7ee83c2940e..8657a3b0e23 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -1659,9 +1659,12 @@ postgresReScanForeignScan(ForeignScanState *node)
/*
* If any internal parameters affecting this node have changed, we'd
- * better destroy and recreate the cursor. Otherwise, rewinding it should
- * be good enough. If we've only fetched zero or one batch, we needn't
- * even rewind the cursor, just rescan what we have.
+ * better destroy and recreate the cursor. Otherwise, if the remote
+ * server is v14 or older, rewinding it should be good enough; if not,
+ * rewind is only allowed for scrollable cursors, but we don't have a way
+ * to check the scrollability of it, so destroy and recreate it in any
+ * case. If we've only fetched zero or one batch, we needn't even rewind
+ * the cursor, just rescan what we have.
*/
if (node->ss.ps.chgParam != NULL)
{
@@ -1671,8 +1674,15 @@ postgresReScanForeignScan(ForeignScanState *node)
}
else if (fsstate->fetch_ct_2 > 1)
{
- snprintf(sql, sizeof(sql), "MOVE BACKWARD ALL IN c%u",
- fsstate->cursor_number);
+ if (PQserverVersion(fsstate->conn) < 150000)
+ snprintf(sql, sizeof(sql), "MOVE BACKWARD ALL IN c%u",
+ fsstate->cursor_number);
+ else
+ {
+ fsstate->cursor_exists = false;
+ snprintf(sql, sizeof(sql), "CLOSE c%u",
+ fsstate->cursor_number);
+ }
}
else
{