Subject: [PATCH] Little refactoring of portalcmds.c

From: Aleksander Alekseev <[email-masked]>
Date: Wed, 8 Oct 2025 17:02:00 +0300

Hi,

The proposed patch places some repetitive code in a helper function.
The value of this change is arguably not that high but it makes the
code a bit neater IMO.

-- 
Best regards,
Aleksander Alekseev
From af051406d09dedf87bde8802d7f7dea0ab4458ec Mon Sep 17 00:00:00 2001
From: Aleksander Alekseev <[email-masked]>
Date: Wed, 8 Oct 2025 16:54:17 +0300
Subject: [PATCH v1] Refactor portalcmds.c

Place some repetitive code in a helper function.

Author: Aleksander Alekseev <[email-masked]>
Reviewed-by: TODO FIXME
Discussion: TODO FIXME
---
 src/backend/commands/portalcmds.c | 40 +++++++++++++------------------
 1 file changed, 16 insertions(+), 24 deletions(-)

diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c
index ec96c2efcd3..d74a01c01a3 100644
--- a/src/backend/commands/portalcmds.c
+++ b/src/backend/commands/portalcmds.c
@@ -36,6 +36,19 @@
 #include "utils/memutils.h"
 #include "utils/snapmgr.h"
 
+/*
+ * Check that cursor name is not empty, which would conflict with protocol-level
+ * unnamed portal.
+ */
+static void
+check_cursor_name(const char *name)
+{
+	if (!name || name[0] == '\0')
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_CURSOR_NAME),
+				 errmsg("invalid cursor name: must not be empty")));
+}
+
 
 /*
  * PerformCursorOpen
@@ -53,14 +66,7 @@ PerformCursorOpen(ParseState *pstate, DeclareCursorStmt *cstmt, ParamListInfo pa
 	MemoryContext oldContext;
 	char	   *queryString;
 
-	/*
-	 * Disallow empty-string cursor name (conflicts with protocol-level
-	 * unnamed portal).
-	 */
-	if (!cstmt->portalname || cstmt->portalname[0] == '\0')
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_CURSOR_NAME),
-				 errmsg("invalid cursor name: must not be empty")));
+	check_cursor_name(cstmt->portalname);
 
 	/*
 	 * If this is a non-holdable cursor, we require that this statement has
@@ -182,14 +188,7 @@ PerformPortalFetch(FetchStmt *stmt,
 	Portal		portal;
 	uint64		nprocessed;
 
-	/*
-	 * Disallow empty-string cursor name (conflicts with protocol-level
-	 * unnamed portal).
-	 */
-	if (!stmt->portalname || stmt->portalname[0] == '\0')
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_CURSOR_NAME),
-				 errmsg("invalid cursor name: must not be empty")));
+	check_cursor_name(stmt->portalname);
 
 	/* get the portal from the portal name */
 	portal = GetPortalByName(stmt->portalname);
@@ -233,14 +232,7 @@ PerformPortalClose(const char *name)
 		return;
 	}
 
-	/*
-	 * Disallow empty-string cursor name (conflicts with protocol-level
-	 * unnamed portal).
-	 */
-	if (name[0] == '\0')
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_CURSOR_NAME),
-				 errmsg("invalid cursor name: must not be empty")));
+	check_cursor_name(name);
 
 	/*
 	 * get the portal from the portal name
-- 
2.43.0

---

From: Quan Zongliang <[email-masked]>
Date: Mon, 27 Oct 2025 14:02:41 +0800

> The value of this change is arguably not that high but it makes the

It also reduces the ease of reading the code.
Just add a function for a single if statement. I don't think it's necessary.

Regards,
Quan Zongliang

---

From: wenhui qiu <[email-masked]>
Date: Mon, 27 Oct 2025 17:50:21 +0800

Hi Aleksander Alekseev
> The value of this change is arguably not that high but it makes the
I  agree with your suggestion to refactor the duplicated code into a
function.

Thanks

---

From: Zizhuan Liu <[email-masked]>
Date: Tue, 26 May 2026 03:36:06 +0000

The newly introduced check_cursor_name() implements the logic to reject empty cursor names, which matches the existing checks in PerformCursorOpen() and PerformPortalFetch().

However, this helper function is not a good fit for PerformPortalClose(). At the start of this function(PerformPortalClose), there is a check for name == NULL — a NULL name corresponds to the CLOSE ALL command — and this check runs prior to validating whether the name is an empty string.

While calling check_cursor_name() inside PerformPortalClose() would keep the current behavior intact, it could confuse future readers. This approach also fails to achieve truly consistent cursor name validation across all three functions, and may add extra maintenance burdens in the long term.

On the other hand, if we only refactor PerformCursorOpen() and PerformPortalFetch(), the change would end up being rather minimal.

Considering all these factors, I'd suggest leaving the code as it is and skipping this refactoring.

---

From: Zizhuan Liu <[email-masked]>
Date: Tue, 26 May 2026 03:42:46 +0000

The following review has been posted through the commitfest application:
make installcheck-world:  not tested
Implements feature:       not tested
Spec compliant:           not tested
Documentation:            not tested

However, this helper function is not a good fit for PerformPortalClose(). At the start of this function, there is a check for name == NULL — a NULL name corresponds to the CLOSE ALL command — and this check runs prior to validating whether the name is an empty string.