diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index c9e0ec2..c01db8d 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -7019,6 +7019,32 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
+
+ allow_empty_updates (boolean)
+
+ allow_empty_updates configuration parameter
+
+
+
+
+ Allow UPDATE statements that lack a WHERE clause.
+
+
+
+
+
+ allow_empty_deletes (boolean)
+
+ allow_empty_deletes configuration parameter
+
+
+
+
+ Allow DELETE statements that lack a WHERE clause.
+
+
+
+
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 29c8c4e..0c8786e 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -48,6 +48,9 @@
/* Hook for plugins to get control at end of parse analysis */
post_parse_analyze_hook_type post_parse_analyze_hook = NULL;
+bool allow_empty_deletes = true;
+bool allow_empty_updates = true;
+
static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
static List *transformInsertRow(ParseState *pstate, List *exprlist,
@@ -408,6 +411,12 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
qual = transformWhereClause(pstate, stmt->whereClause,
EXPR_KIND_WHERE, "WHERE");
+ /* Check for allow_empty_deletes */
+ if (!allow_empty_deletes && qual == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_STATEMENT_HAS_NO_WHERE),
+ errmsg("DELETE without a WHERE clause is disallowed")));
+
qry->returningList = transformReturningList(pstate, stmt->returningList);
/* done building the range table and jointree */
@@ -2110,6 +2119,12 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
qual = transformWhereClause(pstate, stmt->whereClause,
EXPR_KIND_WHERE, "WHERE");
+ /* Check for allow_empty_updates */
+ if (!allow_empty_updates && qual == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_STATEMENT_HAS_NO_WHERE),
+ errmsg("UPDATE without a WHERE clause is disallowed")));
+
qry->returningList = transformReturningList(pstate, stmt->returningList);
/*
diff --git a/src/backend/utils/errcodes.txt b/src/backend/utils/errcodes.txt
index be924d5..254cf10 100644
--- a/src/backend/utils/errcodes.txt
+++ b/src/backend/utils/errcodes.txt
@@ -388,6 +388,7 @@ Section: Class 54 - Program Limit Exceeded
# this is for wired-in limits, not resource exhaustion problems (class borrowed from DB2)
54000 E ERRCODE_PROGRAM_LIMIT_EXCEEDED program_limit_exceeded
54001 E ERRCODE_STATEMENT_TOO_COMPLEX statement_too_complex
+54002 E ERRCODE_STATEMENT_HAS_NO_WHERE statement_has_no_where
54011 E ERRCODE_TOO_MANY_COLUMNS too_many_columns
54023 E ERRCODE_TOO_MANY_ARGUMENTS too_many_arguments
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 6ac5184..fca6b71 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -47,6 +47,7 @@
#include "optimizer/geqo.h"
#include "optimizer/paths.h"
#include "optimizer/planmain.h"
+#include "parser/analyze.h"
#include "parser/parse_expr.h"
#include "parser/parse_type.h"
#include "parser/parser.h"
@@ -1653,6 +1654,26 @@ static struct config_bool ConfigureNamesBool[] =
NULL, NULL, NULL
},
+ {
+ {"allow_empty_deletes", PGC_SUSET, QUERY_TUNING,
+ gettext_noop("Allow DELETE without a WHERE clause"),
+ NULL
+ },
+ &allow_empty_deletes,
+ true,
+ NULL, NULL, NULL
+ },
+
+ {
+ {"allow_empty_updates", PGC_SUSET, QUERY_TUNING,
+ gettext_noop("Allow UPDATE without a WHERE clause"),
+ NULL
+ },
+ &allow_empty_updates,
+ true,
+ NULL, NULL, NULL
+ },
+
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL
diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h
index 5ba322a..b88f8cd 100644
--- a/src/include/parser/analyze.h
+++ b/src/include/parser/analyze.h
@@ -42,4 +42,7 @@ extern void applyLockingClause(Query *qry, Index rtindex,
LockClauseStrength strength,
LockWaitPolicy waitPolicy, bool pushedDown);
+extern bool allow_empty_deletes;
+extern bool allow_empty_updates;
+
#endif /* ANALYZE_H */