Hi

čt 1. 1. 2026 v 11:05 odesílatel jian he <[email protected]>
napsal:

> On Thu, Jan 1, 2026 at 3:10 PM Pavel Stehule <[email protected]>
> wrote:
> >
> > Hi
> >
> > I tested one use case, and maybe I found little bit possible error
> message
> >
> > create procedure test()
> > as $$
> > begin
> >   vacuum;
> > end;
> > $$ language plpgsql;
> >
> > (2026-01-01 08:04:05) postgres=# call test();
> > ERROR:  25001: VACUUM cannot be executed from a function
> > CONTEXT:  SQL statement "vacuum"
> > PL/pgSQL function test() line 3 at SQL statement
> > LOCATION:  PreventInTransactionBlock, xact.c:3695
> > (2026-01-01 08:09:18) postgres=#
> >
> > should be "VACUUM cannot be executed from a function or a procedure"
> instead ?
> >
>
> hi.
> "VACUUM cannot be executed from a function or a procedure"
> looks good to me.
>
> similarly, in ExecWaitStmt we have:
>         ereport(ERROR,
>                 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
>                 errmsg("WAIT FOR must be only called without an active
> or registered snapshot"),
>                 errdetail("WAIT FOR cannot be executed from a function
> or a procedure or within a transaction with an isolation level higher
> than READ COMMITTED."));
>
> PreventInTransactionBlock is used in so many places, but this error
> message:
> ``
> (errmsg("%s cannot be executed from a function", stmtType)));
> ``
> only appears once in the regress tests.
> maybe we can add some dummy tests for it.
>

here is a patch (with small regress test)

Regards

Pavel
From aa57e3a80e5ee7bce121addc607d198e67941fc7 Mon Sep 17 00:00:00 2001
From: "[email protected]" <[email protected]>
Date: Sat, 3 Jan 2026 07:32:26 +0100
Subject: [PATCH] VACUUM cannot be executed inside a function or a procedure

---
 src/backend/access/transam/xact.c                  |  2 +-
 .../plpgsql/src/expected/plpgsql_transaction.out   | 13 +++++++++++++
 src/pl/plpgsql/src/sql/plpgsql_transaction.sql     | 14 ++++++++++++++
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 842faa44232..5cf85e2f35c 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -3695,7 +3695,7 @@ PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
 		ereport(ERROR,
 				(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
 		/* translator: %s represents an SQL statement name */
-				 errmsg("%s cannot be executed from a function", stmtType)));
+				 errmsg("%s cannot be executed from a function or a procedure", stmtType)));
 
 	/* If we got past IsTransactionBlock test, should be in default state */
 	if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
diff --git a/src/pl/plpgsql/src/expected/plpgsql_transaction.out b/src/pl/plpgsql/src/expected/plpgsql_transaction.out
index adff10fa6d6..bcdf7958823 100644
--- a/src/pl/plpgsql/src/expected/plpgsql_transaction.out
+++ b/src/pl/plpgsql/src/expected/plpgsql_transaction.out
@@ -736,6 +736,19 @@ SELECT * FROM test1;
  2 | 
 (2 rows)
 
+-- VACUUM cannot be executed inside a function or a procedure
+CREATE PROCEDURE vacuum_inside_procedure()
+LANGUAGE plpgsql AS $$
+BEGIN
+  VACUUM;
+END;
+$$;
+-- error
+CALL vacuum_inside_procedure();
+ERROR:  VACUUM cannot be executed from a function or a procedure
+CONTEXT:  SQL statement "VACUUM"
+PL/pgSQL function vacuum_inside_procedure() line 3 at SQL statement
+DROP PROCEDURE vacuum_inside_procedure();
 DROP TABLE test1;
 DROP TABLE test2;
 DROP TABLE test3;
diff --git a/src/pl/plpgsql/src/sql/plpgsql_transaction.sql b/src/pl/plpgsql/src/sql/plpgsql_transaction.sql
index c73fca7e03e..5e8da3ec4c4 100644
--- a/src/pl/plpgsql/src/sql/plpgsql_transaction.sql
+++ b/src/pl/plpgsql/src/sql/plpgsql_transaction.sql
@@ -631,6 +631,20 @@ $$;
 SELECT * FROM test1;
 
 
+-- VACUUM cannot be executed inside a function or a procedure
+
+CREATE PROCEDURE vacuum_inside_procedure()
+LANGUAGE plpgsql AS $$
+BEGIN
+  VACUUM;
+END;
+$$;
+
+-- error
+CALL vacuum_inside_procedure();
+
+DROP PROCEDURE vacuum_inside_procedure();
+
 DROP TABLE test1;
 DROP TABLE test2;
 DROP TABLE test3;
-- 
2.52.0

Reply via email to