*** a/doc/src/sgml/ref/deallocate.sgml
--- b/doc/src/sgml/ref/deallocate.sgml
***************
*** 26,32 **** PostgreSQL documentation
! DEALLOCATE [ PREPARE ] { name | ALL }
--- 26,33 ----
! DEALLOCATE [ PREPARE ] [ IF EXISTS ] name
! DEALLOCATE [ PREPARE ] ALL
***************
*** 59,64 **** DEALLOCATE [ PREPARE ] { name | ALL
--- 60,75 ----
+ IFÂ EXISTS
+
+
+ Do not throw an error if the prepared statement does not exist.
+ A notice is issued in this case.
+
+
+
+
+
name
*** a/src/backend/commands/prepare.c
--- b/src/backend/commands/prepare.c
***************
*** 556,562 **** void
DeallocateQuery(DeallocateStmt *stmt)
{
if (stmt->name)
! DropPreparedStatement(stmt->name, true);
else
DropAllPreparedStatements();
}
--- 556,562 ----
DeallocateQuery(DeallocateStmt *stmt)
{
if (stmt->name)
! DropPreparedStatement(stmt->name, !stmt->missing_ok);
else
DropAllPreparedStatements();
}
***************
*** 582,587 **** DropPreparedStatement(const char *stmt_name, bool showError)
--- 582,591 ----
/* Now we can remove the hash table entry */
hash_search(prepared_queries, entry->stmt_name, HASH_REMOVE, NULL);
}
+ else
+ ereport(NOTICE,
+ (errmsg("prepared statement \"%s\" does not exist, skipping",
+ stmt_name)));
}
/*
*** a/src/backend/nodes/copyfuncs.c
--- b/src/backend/nodes/copyfuncs.c
***************
*** 3675,3680 **** _copyDeallocateStmt(const DeallocateStmt *from)
--- 3675,3681 ----
DeallocateStmt *newnode = makeNode(DeallocateStmt);
COPY_STRING_FIELD(name);
+ COPY_SCALAR_FIELD(missing_ok);
return newnode;
}
*** a/src/backend/nodes/equalfuncs.c
--- b/src/backend/nodes/equalfuncs.c
***************
*** 1961,1966 **** static bool
--- 1961,1967 ----
_equalDeallocateStmt(const DeallocateStmt *a, const DeallocateStmt *b)
{
COMPARE_STRING_FIELD(name);
+ COMPARE_SCALAR_FIELD(missing_ok);
return true;
}
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 8571,8582 **** DeallocateStmt: DEALLOCATE name
--- 8571,8598 ----
{
DeallocateStmt *n = makeNode(DeallocateStmt);
n->name = $2;
+ n->missing_ok = FALSE;
$$ = (Node *) n;
}
| DEALLOCATE PREPARE name
{
DeallocateStmt *n = makeNode(DeallocateStmt);
n->name = $3;
+ n->missing_ok = FALSE;
+ $$ = (Node *) n;
+ }
+ | DEALLOCATE IF_P EXISTS name
+ {
+ DeallocateStmt *n = makeNode(DeallocateStmt);
+ n->name = $4;
+ n->missing_ok = TRUE;
+ $$ = (Node *) n;
+ }
+ | DEALLOCATE PREPARE IF_P EXISTS name
+ {
+ DeallocateStmt *n = makeNode(DeallocateStmt);
+ n->name = $5;
+ n->missing_ok = TRUE;
$$ = (Node *) n;
}
| DEALLOCATE ALL
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
***************
*** 2575,2580 **** typedef struct DeallocateStmt
--- 2575,2581 ----
NodeTag type;
char *name; /* The name of the plan to remove */
/* NULL means DEALLOCATE ALL */
+ bool missing_ok; /* skip error if table missing */
} DeallocateStmt;
/*
*** a/src/test/regress/expected/prepare.out
--- b/src/test/regress/expected/prepare.out
***************
*** 178,180 **** SELECT name, statement, parameter_types FROM pg_prepared_statements
--- 178,183 ----
------+-----------+-----------------
(0 rows)
+ -- test DEALLOCATE IF EXISTS;
+ DEALLOCATE IF EXISTS unprepared_statement;
+ NOTICE: prepared statement "unprepared_statement" does not exist, skipping
*** a/src/test/regress/sql/prepare.sql
--- b/src/test/regress/sql/prepare.sql
***************
*** 75,77 **** SELECT name, statement, parameter_types FROM pg_prepared_statements
--- 75,80 ----
DEALLOCATE ALL;
SELECT name, statement, parameter_types FROM pg_prepared_statements
ORDER BY name;
+
+ -- test DEALLOCATE IF EXISTS;
+ DEALLOCATE IF EXISTS unprepared_statement;