Enhanced error message to include hint messages for redundant options error
Hi,
While reviewing one of the logical replication patches, I found that
we do not include hint messages to display the actual option which has
been specified more than once in case of redundant option error. I
felt including this will help in easily identifying the error, users
will not have to search through the statement to identify where the
actual error is present. Attached a patch for the same.
Thoughts?
Regards,
Vignesh
Attachments:
0001-Enhance-error-message.patchtext/x-patch; charset=US-ASCII; name=0001-Enhance-error-message.patchDownload
From 73f670b9206e3f0240d56435f838c67f3e9fb681 Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Mon, 26 Apr 2021 09:44:23 +0530
Subject: [PATCH] Enhance error message.
Enhanced error message, so that the user can easily identify the error.
---
src/backend/commands/copy.c | 3 +-
src/backend/commands/foreigncmds.c | 6 ++--
src/backend/commands/functioncmds.c | 6 ++--
src/backend/commands/publicationcmds.c | 6 ++--
src/backend/commands/subscriptioncmds.c | 28 +++++++++++------
src/backend/commands/tablecmds.c | 3 +-
src/backend/commands/typecmds.c | 18 +++++++----
src/backend/commands/user.c | 33 ++++++++++++++-------
src/backend/parser/parse_utilcmd.c | 3 +-
src/backend/replication/pgoutput/pgoutput.c | 15 ++++++----
src/backend/replication/walsender.c | 9 ++++--
src/test/regress/expected/copy2.out | 2 ++
src/test/regress/expected/foreign_data.out | 2 ++
src/test/regress/expected/publication.out | 1 +
14 files changed, 92 insertions(+), 43 deletions(-)
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 8265b981eb..77a50652cc 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -469,7 +469,8 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->force_null)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index eb7103fd3b..1239b0cafd 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -536,7 +536,8 @@ parse_func_options(List *func_options,
if (*handler_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"handler\" specified more than once")));
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
@@ -545,7 +546,8 @@ parse_func_options(List *func_options,
if (*validator_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"validator\" specified more than once")));
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9548287217..6772bdbce9 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -2065,7 +2065,8 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (as_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"as\" specified more than once")));
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
@@ -2073,7 +2074,8 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (language_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"language\" specified more than once")));
language_item = defel;
}
else
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 95c253c8e0..804082116b 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -87,7 +87,8 @@ parse_publication_options(List *options,
if (*publish_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"publish\" specified more than once")));
/*
* If publish option was given only the explicitly listed actions
@@ -130,7 +131,8 @@ parse_publication_options(List *options,
if (*publish_via_partition_root_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"publish_via_partition_root\" specified more than once")));
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 517c8edd3b..740e8169fe 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -121,7 +121,8 @@ parse_subscription_options(List *options,
if (connect_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"connect\" specified more than once")));
connect_given = true;
*connect = defGetBoolean(defel);
@@ -131,7 +132,8 @@ parse_subscription_options(List *options,
if (*enabled_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"enabled\" specified more than once")));
*enabled_given = true;
*enabled = defGetBoolean(defel);
@@ -141,7 +143,8 @@ parse_subscription_options(List *options,
if (create_slot_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"create_slot\" specified more than once")));
create_slot_given = true;
*create_slot = defGetBoolean(defel);
@@ -151,7 +154,8 @@ parse_subscription_options(List *options,
if (*slot_name_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"slot_name\" specified more than once")));
*slot_name_given = true;
*slot_name = defGetString(defel);
@@ -165,7 +169,8 @@ parse_subscription_options(List *options,
if (copy_data_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"copy_data\" specified more than once")));
copy_data_given = true;
*copy_data = defGetBoolean(defel);
@@ -176,7 +181,8 @@ parse_subscription_options(List *options,
if (*synchronous_commit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"synchronous_commit\" specified more than once")));
*synchronous_commit = defGetString(defel);
@@ -190,7 +196,8 @@ parse_subscription_options(List *options,
if (refresh_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"refresh\" specified more than once")));
refresh_given = true;
*refresh = defGetBoolean(defel);
@@ -200,7 +207,9 @@ parse_subscription_options(List *options,
if (*binary_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"binary\" specified more than once")));
+
*binary_given = true;
*binary = defGetBoolean(defel);
@@ -210,7 +219,8 @@ parse_subscription_options(List *options,
if (*streaming_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"streaming\" specified more than once")));
*streaming_given = true;
*streaming = defGetBoolean(defel);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 7d00f4eb25..f6095ab279 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7539,7 +7539,8 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmod
if (generatedEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"generated\" specified more than once")));
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 036fa69d17..3403029f3e 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -1413,7 +1413,8 @@ DefineRange(CreateRangeStmt *stmt)
if (OidIsValid(rangeSubtype))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"subtype\" specified more than once")));
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
@@ -1422,7 +1423,8 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeSubOpclassName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"subtype_opclass\" specified more than once")));
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
@@ -1430,7 +1432,8 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeCollationName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"collation\" specified more than once")));
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
@@ -1438,7 +1441,8 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeCanonicalName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"canonical\" specified more than once")));
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
@@ -1446,7 +1450,8 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeSubtypeDiffName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"subtype_diff\" specified more than once")));
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
@@ -1454,7 +1459,8 @@ DefineRange(CreateRangeStmt *stmt)
if (multirangeTypeName != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"multirange_type_name\" specified more than once")));
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 65bb733958..de46df71ca 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -579,7 +579,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dpassword)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"password\" specified more than once")));
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
@@ -587,7 +588,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dissuper)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"superuser\" specified more than once")));
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
@@ -595,7 +597,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dinherit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"inherit\" specified more than once")));
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
@@ -603,7 +606,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dcreaterole)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"createrole\" specified more than once")));
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
@@ -611,7 +615,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dcreatedb)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"createdb\" specified more than once")));
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
@@ -619,7 +624,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dcanlogin)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"canlogin\" specified more than once")));
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
@@ -627,7 +633,8 @@ AlterRole(AlterRoleStmt *stmt)
if (disreplication)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"isreplication\" specified more than once")));
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
@@ -635,7 +642,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"connectionlimit\" specified more than once")));
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
@@ -644,7 +652,8 @@ AlterRole(AlterRoleStmt *stmt)
if (drolemembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"rolemembers\" specified more than once")));
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
@@ -652,7 +661,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dvalidUntil)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"validUntil\" specified more than once")));
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
@@ -660,7 +670,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dbypassRLS)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"bypassrls\" specified more than once")));
dbypassRLS = defel;
}
else
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 9dd30370da..e3f652df4c 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -402,7 +402,8 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (nameEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"sequence_name\" specified more than once")));
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index f68348dcf4..6a02b4be16 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -189,7 +189,8 @@ parse_output_parameters(List *options, PGOutputData *data)
if (protocol_version_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"proto_version\" specified more than once")));
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -210,7 +211,8 @@ parse_output_parameters(List *options, PGOutputData *data)
if (publication_names_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"publication_names\" specified more than once")));
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -224,7 +226,8 @@ parse_output_parameters(List *options, PGOutputData *data)
if (binary_option_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"binary\" specified more than once")));
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -234,7 +237,8 @@ parse_output_parameters(List *options, PGOutputData *data)
if (messages_option_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"messages\" specified more than once")));
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -244,7 +248,8 @@ parse_output_parameters(List *options, PGOutputData *data)
if (streaming_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"streaming\" specified more than once")));
streaming_given = true;
data->streaming = defGetBoolean(defel);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 52fe9aba66..f3dc3eafe0 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -882,7 +882,8 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"export_snapshot\" specified more than once")));
snapshot_action_given = true;
*snapshot_action = defGetBoolean(defel) ? CRS_EXPORT_SNAPSHOT :
@@ -893,7 +894,8 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"use_snapshot\" specified more than once")));
snapshot_action_given = true;
*snapshot_action = CRS_USE_SNAPSHOT;
@@ -903,7 +905,8 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (reserve_wal_given || cmd->kind != REPLICATION_KIND_PHYSICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errhint("Option \"reserve_wal\" specified more than once")));
reserve_wal_given = true;
*reserve_wal = true;
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c64f0719e7..5f3685e9ef 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -67,6 +67,8 @@ LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
COPY x from stdin (force_null (a), force_null (b));
ERROR: conflicting or redundant options
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 5385f98a0f..039ea52ef5 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -95,6 +95,7 @@ CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
ERROR: conflicting or redundant options
+HINT: Option "handler" specified more than once
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -201,6 +202,7 @@ ALTER FOREIGN DATA WRAPPER foo HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
ERROR: conflicting or redundant options
+HINT: Option "handler" specified more than once
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 63d6ab7a4e..5f87c403ce 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -27,6 +27,7 @@ CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
ERROR: conflicting or redundant options
+HINT: Option "publish_via_partition_root" specified more than once
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
--
2.25.1
On Mon, Apr 26, 2021 at 5:29 PM vignesh C <vignesh21@gmail.com> wrote:
Hi,
While reviewing one of the logical replication patches, I found that
we do not include hint messages to display the actual option which has
been specified more than once in case of redundant option error. I
felt including this will help in easily identifying the error, users
will not have to search through the statement to identify where the
actual error is present. Attached a patch for the same.
Thoughts?
+1. A more detailed error will be useful in a rare scenario like users
have specified duplicate options along with a lot of other options,
they will know for which option the error is thrown by the server.
Instead of adding errhint or errdetail, how about just changing the
error message itself to something like "option \"%s\" specified more
than once" or "parameter \"%s\" specified more than once" like we have
in other places in the code?
Comments on the patch:
1) generally errhint and errdetail messages should end with a period
".", please see their usage in other places.
+ errhint("Option \"streaming\" specified more
than once")));
2) I think it should be errdetail instead of errhint, because you are
giving more information about the error, but not hinting user how to
overcome it. If you had to say something like "Remove duplicate
\"password\" option." or "The \"password\" option is specified more
than once. Remove all the duplicates.", then it makes sense to use
errhint.
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
On Mon, Apr 26, 2021 at 5:49 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:
On Mon, Apr 26, 2021 at 5:29 PM vignesh C <vignesh21@gmail.com> wrote:
Hi,
While reviewing one of the logical replication patches, I found that
we do not include hint messages to display the actual option which has
been specified more than once in case of redundant option error. I
felt including this will help in easily identifying the error, users
will not have to search through the statement to identify where the
actual error is present. Attached a patch for the same.
Thoughts?
+1 for improving the error
Comments on the patch:
1) generally errhint and errdetail messages should end with a period
".", please see their usage in other places.
+ errhint("Option \"streaming\" specified more
than once")));2) I think it should be errdetail instead of errhint, because you are
giving more information about the error, but not hinting user how to
overcome it. If you had to say something like "Remove duplicate
\"password\" option." or "The \"password\" option is specified more
than once. Remove all the duplicates.", then it makes sense to use
errhint.
I agree this should be errdetail.
--
Regards,
Dilip Kumar
EnterpriseDB: http://www.enterprisedb.com
On Mon, Apr 26, 2021 at 5:49 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:
On Mon, Apr 26, 2021 at 5:29 PM vignesh C <vignesh21@gmail.com> wrote:
Hi,
While reviewing one of the logical replication patches, I found that
we do not include hint messages to display the actual option which has
been specified more than once in case of redundant option error. I
felt including this will help in easily identifying the error, users
will not have to search through the statement to identify where the
actual error is present. Attached a patch for the same.
Thoughts?+1. A more detailed error will be useful in a rare scenario like users
have specified duplicate options along with a lot of other options,
they will know for which option the error is thrown by the server.Instead of adding errhint or errdetail, how about just changing the
error message itself to something like "option \"%s\" specified more
than once" or "parameter \"%s\" specified more than once" like we have
in other places in the code?
Both seemed fine but I preferred using errdetail as I felt it is
slightly better for the details to appear in a new line.
Comments on the patch:
1) generally errhint and errdetail messages should end with a period
".", please see their usage in other places.
+ errhint("Option \"streaming\" specified more
than once")));
Modified it.
2) I think it should be errdetail instead of errhint, because you are
giving more information about the error, but not hinting user how to
overcome it. If you had to say something like "Remove duplicate
\"password\" option." or "The \"password\" option is specified more
than once. Remove all the duplicates.", then it makes sense to use
errhint.
Modified it.
Attached patch for the same.
Regards,
Vignesh
Attachments:
v2-0001-Enhance-error-message.patchtext/x-patch; charset=US-ASCII; name=v2-0001-Enhance-error-message.patchDownload
From 19b33693873a9c6201a139370649f605978863f8 Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Mon, 26 Apr 2021 18:40:36 +0530
Subject: [PATCH v2] Enhance error message.
Enhanced error message, so that the user can easily identify the error.
---
src/backend/commands/copy.c | 3 +-
src/backend/commands/foreigncmds.c | 6 ++--
src/backend/commands/functioncmds.c | 6 ++--
src/backend/commands/publicationcmds.c | 6 ++--
src/backend/commands/subscriptioncmds.c | 28 +++++++++++------
src/backend/commands/tablecmds.c | 3 +-
src/backend/commands/typecmds.c | 18 +++++++----
src/backend/commands/user.c | 33 ++++++++++++++-------
src/backend/parser/parse_utilcmd.c | 3 +-
src/backend/replication/pgoutput/pgoutput.c | 15 ++++++----
src/backend/replication/walsender.c | 9 ++++--
src/test/regress/expected/copy2.out | 2 ++
src/test/regress/expected/foreign_data.out | 2 ++
src/test/regress/expected/publication.out | 1 +
14 files changed, 92 insertions(+), 43 deletions(-)
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 8265b981eb..77a50652cc 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -469,7 +469,8 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->force_null)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index eb7103fd3b..83b969a5f8 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -536,7 +536,8 @@ parse_func_options(List *func_options,
if (*handler_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"handler\" specified more than once.")));
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
@@ -545,7 +546,8 @@ parse_func_options(List *func_options,
if (*validator_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"validator\" specified more than once.")));
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9548287217..5508fad48f 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -2065,7 +2065,8 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (as_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"as\" specified more than once.")));
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
@@ -2073,7 +2074,8 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (language_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"language\" specified more than once.")));
language_item = defel;
}
else
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 95c253c8e0..50a876a533 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -87,7 +87,8 @@ parse_publication_options(List *options,
if (*publish_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"publish\" specified more than once.")));
/*
* If publish option was given only the explicitly listed actions
@@ -130,7 +131,8 @@ parse_publication_options(List *options,
if (*publish_via_partition_root_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"publish_via_partition_root\" specified more than once.")));
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 517c8edd3b..fd9fdb08d8 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -121,7 +121,8 @@ parse_subscription_options(List *options,
if (connect_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"connect\" specified more than once.")));
connect_given = true;
*connect = defGetBoolean(defel);
@@ -131,7 +132,8 @@ parse_subscription_options(List *options,
if (*enabled_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"enabled\" specified more than once.")));
*enabled_given = true;
*enabled = defGetBoolean(defel);
@@ -141,7 +143,8 @@ parse_subscription_options(List *options,
if (create_slot_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"create_slot\" specified more than once.")));
create_slot_given = true;
*create_slot = defGetBoolean(defel);
@@ -151,7 +154,8 @@ parse_subscription_options(List *options,
if (*slot_name_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"slot_name\" specified more than once.")));
*slot_name_given = true;
*slot_name = defGetString(defel);
@@ -165,7 +169,8 @@ parse_subscription_options(List *options,
if (copy_data_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"copy_data\" specified more than once.")));
copy_data_given = true;
*copy_data = defGetBoolean(defel);
@@ -176,7 +181,8 @@ parse_subscription_options(List *options,
if (*synchronous_commit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"synchronous_commit\" specified more than once.")));
*synchronous_commit = defGetString(defel);
@@ -190,7 +196,8 @@ parse_subscription_options(List *options,
if (refresh_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"refresh\" specified more than once.")));
refresh_given = true;
*refresh = defGetBoolean(defel);
@@ -200,7 +207,9 @@ parse_subscription_options(List *options,
if (*binary_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"binary\" specified more than once.")));
+
*binary_given = true;
*binary = defGetBoolean(defel);
@@ -210,7 +219,8 @@ parse_subscription_options(List *options,
if (*streaming_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"streaming\" specified more than once.")));
*streaming_given = true;
*streaming = defGetBoolean(defel);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 7d00f4eb25..3371040ba2 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7539,7 +7539,8 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmod
if (generatedEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"generated\" specified more than once.")));
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 036fa69d17..bbfc06113e 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -1413,7 +1413,8 @@ DefineRange(CreateRangeStmt *stmt)
if (OidIsValid(rangeSubtype))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"subtype\" specified more than once.")));
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
@@ -1422,7 +1423,8 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeSubOpclassName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"subtype_opclass\" specified more than once.")));
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
@@ -1430,7 +1432,8 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeCollationName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"collation\" specified more than once.")));
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
@@ -1438,7 +1441,8 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeCanonicalName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"canonical\" specified more than once.")));
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
@@ -1446,7 +1450,8 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeSubtypeDiffName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"subtype_diff\" specified more than once.")));
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
@@ -1454,7 +1459,8 @@ DefineRange(CreateRangeStmt *stmt)
if (multirangeTypeName != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"multirange_type_name\" specified more than once.")));
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 65bb733958..5f4274327d 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -579,7 +579,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dpassword)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"password\" specified more than once.")));
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
@@ -587,7 +588,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dissuper)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"superuser\" specified more than once.")));
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
@@ -595,7 +597,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dinherit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"inherit\" specified more than once.")));
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
@@ -603,7 +606,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dcreaterole)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"createrole\" specified more than once.")));
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
@@ -611,7 +615,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dcreatedb)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"createdb\" specified more than once.")));
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
@@ -619,7 +624,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dcanlogin)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"canlogin\" specified more than once.")));
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
@@ -627,7 +633,8 @@ AlterRole(AlterRoleStmt *stmt)
if (disreplication)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"isreplication\" specified more than once.")));
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
@@ -635,7 +642,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"connectionlimit\" specified more than once.")));
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
@@ -644,7 +652,8 @@ AlterRole(AlterRoleStmt *stmt)
if (drolemembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"rolemembers\" specified more than once.")));
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
@@ -652,7 +661,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dvalidUntil)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"validUntil\" specified more than once.")));
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
@@ -660,7 +670,8 @@ AlterRole(AlterRoleStmt *stmt)
if (dbypassRLS)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"bypassrls\" specified more than once.")));
dbypassRLS = defel;
}
else
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 9dd30370da..7565450820 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -402,7 +402,8 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (nameEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"sequence_name\" specified more than once.")));
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index f68348dcf4..1a28c6d2ce 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -189,7 +189,8 @@ parse_output_parameters(List *options, PGOutputData *data)
if (protocol_version_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"proto_version\" specified more than once.")));
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -210,7 +211,8 @@ parse_output_parameters(List *options, PGOutputData *data)
if (publication_names_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"publication_names\" specified more than once.")));
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -224,7 +226,8 @@ parse_output_parameters(List *options, PGOutputData *data)
if (binary_option_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"binary\" specified more than once.")));
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -234,7 +237,8 @@ parse_output_parameters(List *options, PGOutputData *data)
if (messages_option_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"messages\" specified more than once.")));
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -244,7 +248,8 @@ parse_output_parameters(List *options, PGOutputData *data)
if (streaming_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"streaming\" specified more than once.")));
streaming_given = true;
data->streaming = defGetBoolean(defel);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 52fe9aba66..6b436c6174 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -882,7 +882,8 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"export_snapshot\" specified more than once.")));
snapshot_action_given = true;
*snapshot_action = defGetBoolean(defel) ? CRS_EXPORT_SNAPSHOT :
@@ -893,7 +894,8 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"use_snapshot\" specified more than once.")));
snapshot_action_given = true;
*snapshot_action = CRS_USE_SNAPSHOT;
@@ -903,7 +905,8 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (reserve_wal_given || cmd->kind != REPLICATION_KIND_PHYSICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ errdetail("Option \"reserve_wal\" specified more than once.")));
reserve_wal_given = true;
*reserve_wal = true;
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c64f0719e7..5f3685e9ef 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -67,6 +67,8 @@ LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
COPY x from stdin (force_null (a), force_null (b));
ERROR: conflicting or redundant options
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 5385f98a0f..75ee3b8a75 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -95,6 +95,7 @@ CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
ERROR: conflicting or redundant options
+DETAIL: Option "handler" specified more than once.
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -201,6 +202,7 @@ ALTER FOREIGN DATA WRAPPER foo HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
ERROR: conflicting or redundant options
+DETAIL: Option "handler" specified more than once.
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 63d6ab7a4e..9f34d032af 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -27,6 +27,7 @@ CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
ERROR: conflicting or redundant options
+DETAIL: Option "publish_via_partition_root" specified more than once.
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
--
2.25.1
On Mon, Apr 26, 2021 at 6:18 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
On Mon, Apr 26, 2021 at 5:49 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Mon, Apr 26, 2021 at 5:29 PM vignesh C <vignesh21@gmail.com> wrote:
Hi,
While reviewing one of the logical replication patches, I found that
we do not include hint messages to display the actual option which has
been specified more than once in case of redundant option error. I
felt including this will help in easily identifying the error, users
will not have to search through the statement to identify where the
actual error is present. Attached a patch for the same.
Thoughts?+1 for improving the error
Comments on the patch:
1) generally errhint and errdetail messages should end with a period
".", please see their usage in other places.
+ errhint("Option \"streaming\" specified more
than once")));2) I think it should be errdetail instead of errhint, because you are
giving more information about the error, but not hinting user how to
overcome it. If you had to say something like "Remove duplicate
\"password\" option." or "The \"password\" option is specified more
than once. Remove all the duplicates.", then it makes sense to use
errhint.I agree this should be errdetail.
Thanks for the comment, I have modified and shared the v2 patch
attached in the previous mail.
Regards,
Vignesh
On Mon, Apr 26, 2021 at 7:02 PM vignesh C <vignesh21@gmail.com> wrote:
On Mon, Apr 26, 2021 at 5:49 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Mon, Apr 26, 2021 at 5:29 PM vignesh C <vignesh21@gmail.com> wrote:
Hi,
While reviewing one of the logical replication patches, I found that
we do not include hint messages to display the actual option which has
been specified more than once in case of redundant option error. I
felt including this will help in easily identifying the error, users
will not have to search through the statement to identify where the
actual error is present. Attached a patch for the same.
Thoughts?+1. A more detailed error will be useful in a rare scenario like users
have specified duplicate options along with a lot of other options,
they will know for which option the error is thrown by the server.Instead of adding errhint or errdetail, how about just changing the
error message itself to something like "option \"%s\" specified more
than once" or "parameter \"%s\" specified more than once" like we have
in other places in the code?Both seemed fine but I preferred using errdetail as I felt it is
slightly better for the details to appear in a new line.
Thanks! IMO, it is better to change the error message to "option
\"%s\" specified more than once" instead of adding an error detail.
Let's hear other hackers' opinions.
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
On 2021-Apr-26, Bharath Rupireddy wrote:
Thanks! IMO, it is better to change the error message to "option
\"%s\" specified more than once" instead of adding an error detail.
Let's hear other hackers' opinions.
Many other places have the message "conflicting or redundant options",
and then parser_errposition() shows the problem option. That seems
pretty unhelpful, so whenever the problem is the redundancy I would have
the message be explicit about that, and about which option is the
problem:
errmsg("option \"%s\" specified more than once", "someopt")
Do note that wording it this way means only one translatable message,
not dozens.
In some cases it is possible that you'd end up with two messages, one
for "redundant" and one for the other ways for options to conflict with
others; for example collationcmds.c has one that's not as obvious, and
force_quote/force_quote_all in COPY have their own thing too.
I think we should do parser_errposition() wherever possible, in
addition to the wording change.
--
�lvaro Herrera Valdivia, Chile
<inflex> really, I see PHP as like a strange amalgamation of C, Perl, Shell
<crab> inflex: you know that "amalgam" means "mixture with mercury",
more or less, right?
<crab> i.e., "deadly poison"
On Mon, Apr 26, 2021 at 8:06 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2021-Apr-26, Bharath Rupireddy wrote:
Thanks! IMO, it is better to change the error message to "option
\"%s\" specified more than once" instead of adding an error detail.
Let's hear other hackers' opinions.Many other places have the message "conflicting or redundant options",
and then parser_errposition() shows the problem option. That seems
pretty unhelpful, so whenever the problem is the redundancy I would have
the message be explicit about that, and about which option is the
problem:
errmsg("option \"%s\" specified more than once", "someopt")
Do note that wording it this way means only one translatable message,
not dozens.
I agree that we can just be clear about the problem. Looks like the
majority of the errors "conflicting or redundant options" are for
redundant options. So, wherever "conflicting or redundant options"
exists: 1) change the message to "option \"%s\" specified more than
once" and remove parser_errposition if it's there because the option
name in the error message would give the info with which user can
point to the location 2) change the message to something like "option
\"%s\" is conflicting with option \"%s\"".
In some cases it is possible that you'd end up with two messages, one
for "redundant" and one for the other ways for options to conflict with
others; for example collationcmds.c has one that's not as obvious, and
And yes, we need to divide up the message for conflicting and
redundant options on a case-to-case basis.
In createdb: we just need to modify the error message to "conflicting
options" or we could just get rid of errdetail and have the error
message directly saying "LOCALE cannot be specified together with
LC_COLLATE or LC_CTYPE". Redundant options are just caught in the
above for loop in createdb.
if (dlocale && (dcollate || dctype))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options"),
errdetail("LOCALE cannot be specified together with
LC_COLLATE or LC_CTYPE.")));
In AlterDatabase: we can remove parser_errposition because the option
name in the error message would give the right information.
if (list_length(stmt->options) != 1)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("option \"%s\" cannot be specified with
other options",
dtablespace->defname),
parser_errposition(pstate, dtablespace->location)));
In compute_common_attribute: we can remove goto duplicate_error and
have the message change to "option \"%s\" specified more than once".
In DefineType: we need to rework for loop.
I found another problem with collationcmds.c is that it doesn't error
out if some of the options are specified more than once, something
like below. I think the option checking "for loop" in DefineCollation
needs to be reworked.
CREATE COLLATION case_insensitive (provider = icu, provider =
someother locale = '@colStrength=secondary', deterministic = false,
deterministic = true);
force_quote/force_quote_all in COPY have their own thing too.
We can remove the errhint for force_not_null and force_null along with
the error message wording change to "option \"%s\" specified more than
once".
Upon looking at error "conflicting or redundant options" instances, to
do the above we need a lot of code changes, I'm not sure that will be
acceptable.
One thing is that all the option checking for loops are doing these
things in common: 1) fetching the values bool, int, float, string of
the options 2) redundant checking. I feel we need to invent a common
API to which we pass in 1) a list of allowed options for a particular
command, we can have these as static data structure
{allowed_option_name, data_type}, 2) a list of user specified options
3) the API will return a list of fetched i.e. parsed values
{user_specified_option_name, data_type, value}. Maybe the API can
return a hash table of these values so that the callers can look up
faster for the required option. The advantage of this API is that we
don't need to have many for-loops for options checking in the code.
I'm not sure it is worth doing though. Thoughts?
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
On 2021-Apr-26, Bharath Rupireddy wrote:
I agree that we can just be clear about the problem. Looks like the
majority of the errors "conflicting or redundant options" are for
redundant options. So, wherever "conflicting or redundant options"
exists: 1) change the message to "option \"%s\" specified more than
once" and remove parser_errposition if it's there because the option
name in the error message would give the info with which user can
point to the location
Hmm, I would keep the parser_errposition() even if the option name is
mentioned in the error message. There's no harm in being a little
redundant, with both the option name and the error cursor showing the
same thing.
2) change the message to something like "option \"%s\" is conflicting
with option \"%s\"".
Maybe, but since these would all be special cases, I think we'd need to
discuss them individually. I would suggest that in order not to stall
this patch, these cases should all stay as "redundant or conflicting
options" -- that is, avoid any further change apart from exactly the
thing you came here to change. You can submit a 0002 patch to change
those other errors. That way, even if those changes end up rejected for
whatever reason, you still got your 0001 done (which would change the
bulk of "conflicting or redundant" error to the "option %s already
specified" error). Some progress is better than none.
--
�lvaro Herrera 39�49'30"S 73�17'W
<Schwern> It does it in a really, really complicated way
<crab> why does it need to be complicated?
<Schwern> Because it's MakeMaker.
On Mon, Apr 26, 2021 at 9:24 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2021-Apr-26, Bharath Rupireddy wrote:
I agree that we can just be clear about the problem. Looks like the
majority of the errors "conflicting or redundant options" are for
redundant options. So, wherever "conflicting or redundant options"
exists: 1) change the message to "option \"%s\" specified more than
once" and remove parser_errposition if it's there because the option
name in the error message would give the info with which user can
point to the locationHmm, I would keep the parser_errposition() even if the option name is
mentioned in the error message. There's no harm in being a little
redundant, with both the option name and the error cursor showing the
same thing.
Agreed.
2) change the message to something like "option \"%s\" is conflicting
with option \"%s\"".Maybe, but since these would all be special cases, I think we'd need to
discuss them individually. I would suggest that in order not to stall
this patch, these cases should all stay as "redundant or conflicting
options" -- that is, avoid any further change apart from exactly the
thing you came here to change. You can submit a 0002 patch to change
those other errors. That way, even if those changes end up rejected for
whatever reason, you still got your 0001 done (which would change the
bulk of "conflicting or redundant" error to the "option %s already
specified" error). Some progress is better than none.
+1 to have all the conflicting options error message changes as 0002
patch or I'm okay even if we discuss those changes after the 0001
patch goes in.
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
On Mon, Apr 26, 2021 at 9:10 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:
I found another problem with collationcmds.c is that it doesn't error
out if some of the options are specified more than once, something
like below. I think the option checking "for loop" in DefineCollation
needs to be reworked.
CREATE COLLATION case_insensitive (provider = icu, provider =
someother locale = '@colStrength=secondary', deterministic = false,
deterministic = true);
I'm thinking that the above problem should be discussed separately. I
will start a new thread soon on this.
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
On Tue, Apr 27, 2021 at 6:23 AM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:
On Mon, Apr 26, 2021 at 9:10 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:I found another problem with collationcmds.c is that it doesn't error
out if some of the options are specified more than once, something
like below. I think the option checking "for loop" in DefineCollation
needs to be reworked.
CREATE COLLATION case_insensitive (provider = icu, provider =
someother locale = '@colStrength=secondary', deterministic = false,
deterministic = true);I'm thinking that the above problem should be discussed separately. I
will start a new thread soon on this.
I started a separate thread -
/messages/by-id/CALj2ACWtL6fTLdyF4R_YkPtf1YEDb6FUoD5DGAki3rpD+sWqiA@mail.gmail.com
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
On Mon, Apr 26, 2021 at 9:24 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2021-Apr-26, Bharath Rupireddy wrote:
I agree that we can just be clear about the problem. Looks like the
majority of the errors "conflicting or redundant options" are for
redundant options. So, wherever "conflicting or redundant options"
exists: 1) change the message to "option \"%s\" specified more than
once" and remove parser_errposition if it's there because the option
name in the error message would give the info with which user can
point to the locationHmm, I would keep the parser_errposition() even if the option name is
mentioned in the error message. There's no harm in being a little
redundant, with both the option name and the error cursor showing the
same thing.2) change the message to something like "option \"%s\" is conflicting
with option \"%s\"".Maybe, but since these would all be special cases, I think we'd need to
discuss them individually. I would suggest that in order not to stall
this patch, these cases should all stay as "redundant or conflicting
options" -- that is, avoid any further change apart from exactly the
thing you came here to change. You can submit a 0002 patch to change
those other errors. That way, even if those changes end up rejected for
whatever reason, you still got your 0001 done (which would change the
bulk of "conflicting or redundant" error to the "option %s already
specified" error). Some progress is better than none.
Thanks for the comments, please find the attached v3 patch which has
the change for the first part. I will make changes for 002 and post it
soon.
Thoughts?
Regards,
Vignesh
Attachments:
v3-0001-Enhance-error-message.patchtext/x-patch; charset=US-ASCII; name=v3-0001-Enhance-error-message.patchDownload
From 6ed153cdb45a0d41d3889dc7d80b3a743eb66725 Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Mon, 26 Apr 2021 18:40:36 +0530
Subject: [PATCH v3] Enhance error message.
Enhanced error message, so that the user can easily identify the error.
---
contrib/file_fdw/file_fdw.c | 6 +--
src/backend/catalog/aclchk.c | 4 +-
src/backend/commands/copy.c | 23 +++++-----
src/backend/commands/dbcommands.c | 28 ++++++------
src/backend/commands/extension.c | 8 ++--
src/backend/commands/foreigncmds.c | 4 +-
src/backend/commands/functioncmds.c | 12 +++---
src/backend/commands/publicationcmds.c | 4 +-
src/backend/commands/sequence.c | 18 ++++----
src/backend/commands/subscriptioncmds.c | 18 ++++----
src/backend/commands/tablecmds.c | 2 +-
src/backend/commands/typecmds.c | 14 +++---
src/backend/commands/user.c | 48 ++++++++++-----------
src/backend/parser/parse_utilcmd.c | 2 +-
src/backend/replication/pgoutput/pgoutput.c | 10 ++---
src/backend/replication/walsender.c | 6 +--
src/test/regress/expected/copy2.out | 24 ++++++-----
src/test/regress/expected/foreign_data.out | 4 +-
src/test/regress/expected/publication.out | 2 +-
19 files changed, 119 insertions(+), 118 deletions(-)
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 2c2f149fb0..10aa2fca28 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -292,8 +292,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
if (force_not_null)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_not_null\" supplied more than once for a column.")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
force_not_null = def;
/* Don't care what the value is, as long as it's a legal boolean */
(void) defGetBoolean(def);
@@ -304,8 +303,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
if (force_null)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_null\" supplied more than once for a column.")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
force_null = def;
(void) defGetBoolean(def);
}
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index e1573eb398..7885587bfc 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -923,7 +923,7 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
if (dnspnames)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dnspnames = defel;
}
@@ -932,7 +932,7 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
if (drolespecs)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
drolespecs = defel;
}
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 8265b981eb..2860f36f91 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -359,7 +359,7 @@ ProcessCopyOptions(ParseState *pstate,
if (format_specified)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
format_specified = true;
if (strcmp(fmt, "text") == 0)
@@ -379,7 +379,7 @@ ProcessCopyOptions(ParseState *pstate,
if (freeze_specified)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
freeze_specified = true;
opts_out->freeze = defGetBoolean(defel);
@@ -389,7 +389,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->delim)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->delim = defGetString(defel);
}
@@ -398,7 +398,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->null_print)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->null_print = defGetString(defel);
}
@@ -407,7 +407,7 @@ ProcessCopyOptions(ParseState *pstate,
if (header_specified)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
header_specified = true;
opts_out->header_line = defGetBoolean(defel);
@@ -417,7 +417,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->quote)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->quote = defGetString(defel);
}
@@ -426,7 +426,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->escape)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->escape = defGetString(defel);
}
@@ -453,7 +453,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->force_notnull)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
if (defel->arg && IsA(defel->arg, List))
opts_out->force_notnull = castNode(List, defel->arg);
@@ -469,7 +469,8 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->force_null)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
@@ -489,7 +490,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->convert_selectively)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->convert_selectively = true;
if (defel->arg == NULL || IsA(defel->arg, List))
@@ -506,7 +507,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->file_encoding >= 0)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
if (opts_out->file_encoding < 0)
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 2b159b60eb..15ca32c898 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -154,7 +154,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dtablespacename)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dtablespacename = defel;
}
@@ -163,7 +163,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (downer)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
downer = defel;
}
@@ -172,7 +172,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dtemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dtemplate = defel;
}
@@ -181,7 +181,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dencoding)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dencoding = defel;
}
@@ -190,7 +190,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dlocale)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dlocale = defel;
}
@@ -199,7 +199,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dcollate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcollate = defel;
}
@@ -208,7 +208,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dctype)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dctype = defel;
}
@@ -217,7 +217,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (distemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
distemplate = defel;
}
@@ -226,7 +226,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dallowconnections)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dallowconnections = defel;
}
@@ -235,7 +235,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
@@ -1499,7 +1499,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (distemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
distemplate = defel;
}
@@ -1508,7 +1508,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (dallowconnections)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dallowconnections = defel;
}
@@ -1517,7 +1517,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
@@ -1526,7 +1526,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (dtablespace)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dtablespace = defel;
}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 19db329fe6..5525919735 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1732,7 +1732,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
if (d_schema)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_schema = defel;
schemaName = defGetString(d_schema);
@@ -1742,7 +1742,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
if (d_new_version)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_new_version = defel;
versionName = defGetString(d_new_version);
@@ -1752,7 +1752,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
if (d_cascade)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_cascade = defel;
cascade = defGetBoolean(d_cascade);
@@ -3052,7 +3052,7 @@ ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
if (d_new_version)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_new_version = defel;
}
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index eb7103fd3b..d9cf3227fe 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -536,7 +536,7 @@ parse_func_options(List *func_options,
if (*handler_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
@@ -545,7 +545,7 @@ parse_func_options(List *func_options,
if (*validator_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9548287217..ed13bf547c 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -741,7 +741,7 @@ compute_function_attributes(ParseState *pstate,
if (as_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
as_item = defel;
}
@@ -750,7 +750,7 @@ compute_function_attributes(ParseState *pstate,
if (language_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
language_item = defel;
}
@@ -759,7 +759,7 @@ compute_function_attributes(ParseState *pstate,
if (transform_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
transform_item = defel;
}
@@ -768,7 +768,7 @@ compute_function_attributes(ParseState *pstate,
if (windowfunc_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
if (is_procedure)
ereport(ERROR,
@@ -2065,7 +2065,7 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (as_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
@@ -2073,7 +2073,7 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (language_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
language_item = defel;
}
else
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 95c253c8e0..9dc2bfdd60 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -87,7 +87,7 @@ parse_publication_options(List *options,
if (*publish_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
/*
* If publish option was given only the explicitly listed actions
@@ -130,7 +130,7 @@ parse_publication_options(List *options,
if (*publish_via_partition_root_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 0415df9ccb..f2180cd29b 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1263,7 +1263,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (as_type)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
as_type = defel;
*need_seq_rewrite = true;
@@ -1273,7 +1273,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (increment_by)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
increment_by = defel;
*need_seq_rewrite = true;
@@ -1283,7 +1283,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (start_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
start_value = defel;
*need_seq_rewrite = true;
@@ -1293,7 +1293,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (restart_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
restart_value = defel;
*need_seq_rewrite = true;
@@ -1303,7 +1303,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (max_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
max_value = defel;
*need_seq_rewrite = true;
@@ -1313,7 +1313,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (min_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
min_value = defel;
*need_seq_rewrite = true;
@@ -1323,7 +1323,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (cache_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
cache_value = defel;
*need_seq_rewrite = true;
@@ -1333,7 +1333,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (is_cycled)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
is_cycled = defel;
*need_seq_rewrite = true;
@@ -1343,7 +1343,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (*owned_by)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
*owned_by = defGetQualifiedName(defel);
}
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 517c8edd3b..662191bc9e 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -121,7 +121,7 @@ parse_subscription_options(List *options,
if (connect_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
connect_given = true;
*connect = defGetBoolean(defel);
@@ -131,7 +131,7 @@ parse_subscription_options(List *options,
if (*enabled_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*enabled_given = true;
*enabled = defGetBoolean(defel);
@@ -141,7 +141,7 @@ parse_subscription_options(List *options,
if (create_slot_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
create_slot_given = true;
*create_slot = defGetBoolean(defel);
@@ -151,7 +151,7 @@ parse_subscription_options(List *options,
if (*slot_name_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*slot_name_given = true;
*slot_name = defGetString(defel);
@@ -165,7 +165,7 @@ parse_subscription_options(List *options,
if (copy_data_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
copy_data_given = true;
*copy_data = defGetBoolean(defel);
@@ -176,7 +176,7 @@ parse_subscription_options(List *options,
if (*synchronous_commit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*synchronous_commit = defGetString(defel);
@@ -190,7 +190,7 @@ parse_subscription_options(List *options,
if (refresh_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
refresh_given = true;
*refresh = defGetBoolean(defel);
@@ -200,7 +200,7 @@ parse_subscription_options(List *options,
if (*binary_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*binary_given = true;
*binary = defGetBoolean(defel);
@@ -210,7 +210,7 @@ parse_subscription_options(List *options,
if (*streaming_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*streaming_given = true;
*streaming = defGetBoolean(defel);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index d9ba87a2a3..26a1f16271 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7524,7 +7524,7 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmod
if (generatedEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 036fa69d17..84d654d5a5 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -332,7 +332,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
if (*defelp != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
*defelp = defel;
}
@@ -1413,7 +1413,7 @@ DefineRange(CreateRangeStmt *stmt)
if (OidIsValid(rangeSubtype))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
@@ -1422,7 +1422,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeSubOpclassName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
@@ -1430,7 +1430,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeCollationName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
@@ -1438,7 +1438,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeCanonicalName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
@@ -1446,7 +1446,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeSubtypeDiffName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
@@ -1454,7 +1454,7 @@ DefineRange(CreateRangeStmt *stmt)
if (multirangeTypeName != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 65bb733958..4c7af6252d 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -130,7 +130,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dpassword)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dpassword = defel;
}
@@ -144,7 +144,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dissuper)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dissuper = defel;
}
@@ -153,7 +153,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dinherit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dinherit = defel;
}
@@ -162,7 +162,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dcreaterole)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcreaterole = defel;
}
@@ -171,7 +171,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dcreatedb)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcreatedb = defel;
}
@@ -180,7 +180,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dcanlogin)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcanlogin = defel;
}
@@ -189,7 +189,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (disreplication)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
disreplication = defel;
}
@@ -198,7 +198,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
@@ -207,7 +207,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (daddroleto)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
daddroleto = defel;
}
@@ -216,7 +216,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (drolemembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
drolemembers = defel;
}
@@ -225,7 +225,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dadminmembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dadminmembers = defel;
}
@@ -234,7 +234,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dvalidUntil)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dvalidUntil = defel;
}
@@ -243,7 +243,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dbypassRLS)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dbypassRLS = defel;
}
@@ -579,7 +579,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dpassword)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
@@ -587,7 +587,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dissuper)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
@@ -595,7 +595,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dinherit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
@@ -603,7 +603,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dcreaterole)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
@@ -611,7 +611,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dcreatedb)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
@@ -619,7 +619,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dcanlogin)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
@@ -627,7 +627,7 @@ AlterRole(AlterRoleStmt *stmt)
if (disreplication)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
@@ -635,7 +635,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
@@ -644,7 +644,7 @@ AlterRole(AlterRoleStmt *stmt)
if (drolemembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
@@ -652,7 +652,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dvalidUntil)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
@@ -660,7 +660,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dbypassRLS)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dbypassRLS = defel;
}
else
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 9dd30370da..9e44885146 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -402,7 +402,7 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (nameEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index f68348dcf4..50995868db 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -189,7 +189,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (protocol_version_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -210,7 +210,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (publication_names_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -224,7 +224,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (binary_option_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -234,7 +234,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (messages_option_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -244,7 +244,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (streaming_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
streaming_given = true;
data->streaming = defGetBoolean(defel);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 6fefc3bedc..e79690a0f9 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -882,7 +882,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
snapshot_action_given = true;
*snapshot_action = defGetBoolean(defel) ? CRS_EXPORT_SNAPSHOT :
@@ -893,7 +893,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
snapshot_action_given = true;
*snapshot_action = CRS_USE_SNAPSHOT;
@@ -903,7 +903,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (reserve_wal_given || cmd->kind != REPLICATION_KIND_PHYSICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
reserve_wal_given = true;
*reserve_wal = true;
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c64f0719e7..92fe8a121a 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -30,31 +30,31 @@ COPY x (xyz) from stdin;
ERROR: column "xyz" of relation "x" does not exist
-- redundant options
COPY x from stdin (format CSV, FORMAT CSV);
-ERROR: conflicting or redundant options
+ERROR: option "format" specified more than once
LINE 1: COPY x from stdin (format CSV, FORMAT CSV);
^
COPY x from stdin (freeze off, freeze on);
-ERROR: conflicting or redundant options
+ERROR: option "freeze" specified more than once
LINE 1: COPY x from stdin (freeze off, freeze on);
^
COPY x from stdin (delimiter ',', delimiter ',');
-ERROR: conflicting or redundant options
+ERROR: option "delimiter" specified more than once
LINE 1: COPY x from stdin (delimiter ',', delimiter ',');
^
COPY x from stdin (null ' ', null ' ');
-ERROR: conflicting or redundant options
+ERROR: option "null" specified more than once
LINE 1: COPY x from stdin (null ' ', null ' ');
^
COPY x from stdin (header off, header on);
-ERROR: conflicting or redundant options
+ERROR: option "header" specified more than once
LINE 1: COPY x from stdin (header off, header on);
^
COPY x from stdin (quote ':', quote ':');
-ERROR: conflicting or redundant options
+ERROR: option "quote" specified more than once
LINE 1: COPY x from stdin (quote ':', quote ':');
^
COPY x from stdin (escape ':', escape ':');
-ERROR: conflicting or redundant options
+ERROR: option "escape" specified more than once
LINE 1: COPY x from stdin (escape ':', escape ':');
^
COPY x from stdin (force_quote (a), force_quote *);
@@ -62,17 +62,19 @@ ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (force_quote (a), force_quote *);
^
COPY x from stdin (force_not_null (a), force_not_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_not_null" specified more than once
LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
COPY x from stdin (force_null (a), force_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_null" specified more than once
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
-ERROR: conflicting or redundant options
+ERROR: option "convert_selectively" specified more than once
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
^
COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
-ERROR: conflicting or redundant options
+ERROR: option "encoding" specified more than once
LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
^
-- too many columns in column list: should fail
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 5385f98a0f..0cdab88eed 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -94,7 +94,7 @@ CREATE FUNCTION invalid_fdw_handler() RETURNS int LANGUAGE SQL AS 'SELECT 1;';
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -200,7 +200,7 @@ ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo;
ALTER FOREIGN DATA WRAPPER foo HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 63d6ab7a4e..7887dada21 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -26,7 +26,7 @@ ERROR: unrecognized publication parameter: "foo"
CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
-ERROR: conflicting or redundant options
+ERROR: option "publish_via_partition_root" specified more than once
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
--
2.25.1
On 2021-Apr-29, vignesh C wrote:
Thanks for the comments, please find the attached v3 patch which has
the change for the first part.
Looks good to me. I would only add parser_errposition() to the few
error sites missing that.
--
�lvaro Herrera 39�49'30"S 73�17'W
"Uno puede defenderse de los ataques; contra los elogios se esta indefenso"
On Thu, Apr 29, 2021 at 10:44 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2021-Apr-29, vignesh C wrote:
Thanks for the comments, please find the attached v3 patch which has
the change for the first part.Looks good to me. I would only add parser_errposition() to the few
error sites missing that.
Yes, we need to add parser_errposition as agreed in [1]/messages/by-id/CALj2ACUa=ZM8QtOLPCHc7=WgFrx9P6-AgKQs8cmKLvNCvu7arQ@mail.gmail.com.
I think we will have to make changes in compute_common_attribute as
well because the error in the duplicate_error goto statement is
actually for the duplicate option specified more than once, we can do
something like the attached. If it seems okay, it can be merged with
the main patch.
[1]: /messages/by-id/CALj2ACUa=ZM8QtOLPCHc7=WgFrx9P6-AgKQs8cmKLvNCvu7arQ@mail.gmail.com
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
Attachments:
v1-0001-compute_common_attribute.patchapplication/octet-stream; name=v1-0001-compute_common_attribute.patchDownload
From b5f1d7cf8e48b7007e05e5cf6207644430ad810c Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddy@enterprisedb.com>
Date: Fri, 30 Apr 2021 07:57:36 +0530
Subject: [PATCH v1] compute_common_attribute
---
src/backend/commands/functioncmds.c | 31 +++++++++++++++--------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9548287217..e43044dba7 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -492,12 +492,14 @@ compute_common_attribute(ParseState *pstate,
DefElem **support_item,
DefElem **parallel_item)
{
+ DefElem *duplicate_item = NULL;
+
if (strcmp(defel->defname, "volatility") == 0)
{
if (is_procedure)
goto procedure_error;
if (*volatility_item)
- goto duplicate_error;
+ duplicate_item = defel;
*volatility_item = defel;
}
@@ -506,14 +508,14 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*strict_item)
- goto duplicate_error;
+ duplicate_item = defel;
*strict_item = defel;
}
else if (strcmp(defel->defname, "security") == 0)
{
if (*security_item)
- goto duplicate_error;
+ duplicate_item = defel;
*security_item = defel;
}
@@ -522,7 +524,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*leakproof_item)
- goto duplicate_error;
+ duplicate_item = defel;
*leakproof_item = defel;
}
@@ -535,7 +537,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*cost_item)
- goto duplicate_error;
+ duplicate_item = defel;
*cost_item = defel;
}
@@ -544,7 +546,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*rows_item)
- goto duplicate_error;
+ duplicate_item = defel;
*rows_item = defel;
}
@@ -553,7 +555,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*support_item)
- goto duplicate_error;
+ duplicate_item = defel;
*support_item = defel;
}
@@ -562,23 +564,22 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*parallel_item)
- goto duplicate_error;
+ duplicate_item = defel;
*parallel_item = defel;
}
else
return false;
+ if (duplicate_item)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", duplicate_item->defname),
+ parser_errposition(pstate, duplicate_item->location)));
+
/* Recognized an option */
return true;
-duplicate_error:
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
- return false; /* keep compiler quiet */
-
procedure_error:
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
--
2.25.1
On Fri, Apr 30, 2021 at 8:16 AM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:
On Thu, Apr 29, 2021 at 10:44 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2021-Apr-29, vignesh C wrote:
Thanks for the comments, please find the attached v3 patch which has
the change for the first part.Looks good to me. I would only add parser_errposition() to the few
error sites missing that.Yes, we need to add parser_errposition as agreed in [1].
I think we will have to make changes in compute_common_attribute as
well because the error in the duplicate_error goto statement is
actually for the duplicate option specified more than once, we can do
something like the attached. If it seems okay, it can be merged with
the main patch.
+ DefElem *duplicate_item = NULL;
+
if (strcmp(defel->defname, "volatility") == 0)
{
if (is_procedure)
goto procedure_error;
if (*volatility_item)
- goto duplicate_error;
+ duplicate_item = defel;
In this function, we already have the "defel" variable then I do not
understand why you are using one extra variable and assigning defel to
that?
If the goal is to just improve the error message then you can simply
use defel->defname?
--
Regards,
Dilip Kumar
EnterpriseDB: http://www.enterprisedb.com
On Fri, Apr 30, 2021 at 10:17 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
In this function, we already have the "defel" variable then I do not
understand why you are using one extra variable and assigning defel to
that?
If the goal is to just improve the error message then you can simply
use defel->defname?
Yeah. I can do that. Thanks for the comment.
While on this, I also removed the duplicate_error and procedure_error
goto statements, because IMHO, using goto statements is not an elegant
way. I used boolean flags to do the job instead. See the attached and
let me know what you think.
Just for completion, I also attached Vignesh's latest patch v3 as-is,
in case anybody wants to review it.
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
Attachments:
v3-0001-Enhance-error-message.patchapplication/octet-stream; name=v3-0001-Enhance-error-message.patchDownload
From 6ed153cdb45a0d41d3889dc7d80b3a743eb66725 Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Mon, 26 Apr 2021 18:40:36 +0530
Subject: [PATCH v3] Enhance error message.
Enhanced error message, so that the user can easily identify the error.
---
contrib/file_fdw/file_fdw.c | 6 +--
src/backend/catalog/aclchk.c | 4 +-
src/backend/commands/copy.c | 23 +++++-----
src/backend/commands/dbcommands.c | 28 ++++++------
src/backend/commands/extension.c | 8 ++--
src/backend/commands/foreigncmds.c | 4 +-
src/backend/commands/functioncmds.c | 12 +++---
src/backend/commands/publicationcmds.c | 4 +-
src/backend/commands/sequence.c | 18 ++++----
src/backend/commands/subscriptioncmds.c | 18 ++++----
src/backend/commands/tablecmds.c | 2 +-
src/backend/commands/typecmds.c | 14 +++---
src/backend/commands/user.c | 48 ++++++++++-----------
src/backend/parser/parse_utilcmd.c | 2 +-
src/backend/replication/pgoutput/pgoutput.c | 10 ++---
src/backend/replication/walsender.c | 6 +--
src/test/regress/expected/copy2.out | 24 ++++++-----
src/test/regress/expected/foreign_data.out | 4 +-
src/test/regress/expected/publication.out | 2 +-
19 files changed, 119 insertions(+), 118 deletions(-)
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 2c2f149fb0..10aa2fca28 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -292,8 +292,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
if (force_not_null)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_not_null\" supplied more than once for a column.")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
force_not_null = def;
/* Don't care what the value is, as long as it's a legal boolean */
(void) defGetBoolean(def);
@@ -304,8 +303,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
if (force_null)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_null\" supplied more than once for a column.")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
force_null = def;
(void) defGetBoolean(def);
}
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index e1573eb398..7885587bfc 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -923,7 +923,7 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
if (dnspnames)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dnspnames = defel;
}
@@ -932,7 +932,7 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
if (drolespecs)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
drolespecs = defel;
}
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 8265b981eb..2860f36f91 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -359,7 +359,7 @@ ProcessCopyOptions(ParseState *pstate,
if (format_specified)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
format_specified = true;
if (strcmp(fmt, "text") == 0)
@@ -379,7 +379,7 @@ ProcessCopyOptions(ParseState *pstate,
if (freeze_specified)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
freeze_specified = true;
opts_out->freeze = defGetBoolean(defel);
@@ -389,7 +389,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->delim)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->delim = defGetString(defel);
}
@@ -398,7 +398,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->null_print)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->null_print = defGetString(defel);
}
@@ -407,7 +407,7 @@ ProcessCopyOptions(ParseState *pstate,
if (header_specified)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
header_specified = true;
opts_out->header_line = defGetBoolean(defel);
@@ -417,7 +417,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->quote)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->quote = defGetString(defel);
}
@@ -426,7 +426,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->escape)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->escape = defGetString(defel);
}
@@ -453,7 +453,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->force_notnull)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
if (defel->arg && IsA(defel->arg, List))
opts_out->force_notnull = castNode(List, defel->arg);
@@ -469,7 +469,8 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->force_null)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
@@ -489,7 +490,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->convert_selectively)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->convert_selectively = true;
if (defel->arg == NULL || IsA(defel->arg, List))
@@ -506,7 +507,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->file_encoding >= 0)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
if (opts_out->file_encoding < 0)
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 2b159b60eb..15ca32c898 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -154,7 +154,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dtablespacename)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dtablespacename = defel;
}
@@ -163,7 +163,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (downer)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
downer = defel;
}
@@ -172,7 +172,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dtemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dtemplate = defel;
}
@@ -181,7 +181,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dencoding)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dencoding = defel;
}
@@ -190,7 +190,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dlocale)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dlocale = defel;
}
@@ -199,7 +199,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dcollate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcollate = defel;
}
@@ -208,7 +208,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dctype)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dctype = defel;
}
@@ -217,7 +217,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (distemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
distemplate = defel;
}
@@ -226,7 +226,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dallowconnections)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dallowconnections = defel;
}
@@ -235,7 +235,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
@@ -1499,7 +1499,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (distemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
distemplate = defel;
}
@@ -1508,7 +1508,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (dallowconnections)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dallowconnections = defel;
}
@@ -1517,7 +1517,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
@@ -1526,7 +1526,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (dtablespace)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dtablespace = defel;
}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 19db329fe6..5525919735 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1732,7 +1732,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
if (d_schema)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_schema = defel;
schemaName = defGetString(d_schema);
@@ -1742,7 +1742,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
if (d_new_version)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_new_version = defel;
versionName = defGetString(d_new_version);
@@ -1752,7 +1752,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
if (d_cascade)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_cascade = defel;
cascade = defGetBoolean(d_cascade);
@@ -3052,7 +3052,7 @@ ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
if (d_new_version)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_new_version = defel;
}
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index eb7103fd3b..d9cf3227fe 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -536,7 +536,7 @@ parse_func_options(List *func_options,
if (*handler_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
@@ -545,7 +545,7 @@ parse_func_options(List *func_options,
if (*validator_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9548287217..ed13bf547c 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -741,7 +741,7 @@ compute_function_attributes(ParseState *pstate,
if (as_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
as_item = defel;
}
@@ -750,7 +750,7 @@ compute_function_attributes(ParseState *pstate,
if (language_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
language_item = defel;
}
@@ -759,7 +759,7 @@ compute_function_attributes(ParseState *pstate,
if (transform_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
transform_item = defel;
}
@@ -768,7 +768,7 @@ compute_function_attributes(ParseState *pstate,
if (windowfunc_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
if (is_procedure)
ereport(ERROR,
@@ -2065,7 +2065,7 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (as_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
@@ -2073,7 +2073,7 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (language_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
language_item = defel;
}
else
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 95c253c8e0..9dc2bfdd60 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -87,7 +87,7 @@ parse_publication_options(List *options,
if (*publish_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
/*
* If publish option was given only the explicitly listed actions
@@ -130,7 +130,7 @@ parse_publication_options(List *options,
if (*publish_via_partition_root_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 0415df9ccb..f2180cd29b 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1263,7 +1263,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (as_type)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
as_type = defel;
*need_seq_rewrite = true;
@@ -1273,7 +1273,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (increment_by)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
increment_by = defel;
*need_seq_rewrite = true;
@@ -1283,7 +1283,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (start_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
start_value = defel;
*need_seq_rewrite = true;
@@ -1293,7 +1293,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (restart_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
restart_value = defel;
*need_seq_rewrite = true;
@@ -1303,7 +1303,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (max_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
max_value = defel;
*need_seq_rewrite = true;
@@ -1313,7 +1313,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (min_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
min_value = defel;
*need_seq_rewrite = true;
@@ -1323,7 +1323,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (cache_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
cache_value = defel;
*need_seq_rewrite = true;
@@ -1333,7 +1333,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (is_cycled)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
is_cycled = defel;
*need_seq_rewrite = true;
@@ -1343,7 +1343,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (*owned_by)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
*owned_by = defGetQualifiedName(defel);
}
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 517c8edd3b..662191bc9e 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -121,7 +121,7 @@ parse_subscription_options(List *options,
if (connect_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
connect_given = true;
*connect = defGetBoolean(defel);
@@ -131,7 +131,7 @@ parse_subscription_options(List *options,
if (*enabled_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*enabled_given = true;
*enabled = defGetBoolean(defel);
@@ -141,7 +141,7 @@ parse_subscription_options(List *options,
if (create_slot_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
create_slot_given = true;
*create_slot = defGetBoolean(defel);
@@ -151,7 +151,7 @@ parse_subscription_options(List *options,
if (*slot_name_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*slot_name_given = true;
*slot_name = defGetString(defel);
@@ -165,7 +165,7 @@ parse_subscription_options(List *options,
if (copy_data_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
copy_data_given = true;
*copy_data = defGetBoolean(defel);
@@ -176,7 +176,7 @@ parse_subscription_options(List *options,
if (*synchronous_commit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*synchronous_commit = defGetString(defel);
@@ -190,7 +190,7 @@ parse_subscription_options(List *options,
if (refresh_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
refresh_given = true;
*refresh = defGetBoolean(defel);
@@ -200,7 +200,7 @@ parse_subscription_options(List *options,
if (*binary_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*binary_given = true;
*binary = defGetBoolean(defel);
@@ -210,7 +210,7 @@ parse_subscription_options(List *options,
if (*streaming_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*streaming_given = true;
*streaming = defGetBoolean(defel);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index d9ba87a2a3..26a1f16271 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7524,7 +7524,7 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmod
if (generatedEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 036fa69d17..84d654d5a5 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -332,7 +332,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
if (*defelp != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
*defelp = defel;
}
@@ -1413,7 +1413,7 @@ DefineRange(CreateRangeStmt *stmt)
if (OidIsValid(rangeSubtype))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
@@ -1422,7 +1422,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeSubOpclassName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
@@ -1430,7 +1430,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeCollationName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
@@ -1438,7 +1438,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeCanonicalName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
@@ -1446,7 +1446,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeSubtypeDiffName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
@@ -1454,7 +1454,7 @@ DefineRange(CreateRangeStmt *stmt)
if (multirangeTypeName != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 65bb733958..4c7af6252d 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -130,7 +130,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dpassword)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dpassword = defel;
}
@@ -144,7 +144,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dissuper)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dissuper = defel;
}
@@ -153,7 +153,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dinherit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dinherit = defel;
}
@@ -162,7 +162,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dcreaterole)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcreaterole = defel;
}
@@ -171,7 +171,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dcreatedb)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcreatedb = defel;
}
@@ -180,7 +180,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dcanlogin)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcanlogin = defel;
}
@@ -189,7 +189,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (disreplication)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
disreplication = defel;
}
@@ -198,7 +198,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
@@ -207,7 +207,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (daddroleto)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
daddroleto = defel;
}
@@ -216,7 +216,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (drolemembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
drolemembers = defel;
}
@@ -225,7 +225,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dadminmembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dadminmembers = defel;
}
@@ -234,7 +234,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dvalidUntil)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dvalidUntil = defel;
}
@@ -243,7 +243,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dbypassRLS)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dbypassRLS = defel;
}
@@ -579,7 +579,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dpassword)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
@@ -587,7 +587,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dissuper)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
@@ -595,7 +595,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dinherit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
@@ -603,7 +603,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dcreaterole)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
@@ -611,7 +611,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dcreatedb)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
@@ -619,7 +619,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dcanlogin)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
@@ -627,7 +627,7 @@ AlterRole(AlterRoleStmt *stmt)
if (disreplication)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
@@ -635,7 +635,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
@@ -644,7 +644,7 @@ AlterRole(AlterRoleStmt *stmt)
if (drolemembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
@@ -652,7 +652,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dvalidUntil)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
@@ -660,7 +660,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dbypassRLS)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dbypassRLS = defel;
}
else
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 9dd30370da..9e44885146 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -402,7 +402,7 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (nameEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index f68348dcf4..50995868db 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -189,7 +189,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (protocol_version_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -210,7 +210,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (publication_names_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -224,7 +224,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (binary_option_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -234,7 +234,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (messages_option_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -244,7 +244,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (streaming_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
streaming_given = true;
data->streaming = defGetBoolean(defel);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 6fefc3bedc..e79690a0f9 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -882,7 +882,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
snapshot_action_given = true;
*snapshot_action = defGetBoolean(defel) ? CRS_EXPORT_SNAPSHOT :
@@ -893,7 +893,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
snapshot_action_given = true;
*snapshot_action = CRS_USE_SNAPSHOT;
@@ -903,7 +903,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (reserve_wal_given || cmd->kind != REPLICATION_KIND_PHYSICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
reserve_wal_given = true;
*reserve_wal = true;
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c64f0719e7..92fe8a121a 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -30,31 +30,31 @@ COPY x (xyz) from stdin;
ERROR: column "xyz" of relation "x" does not exist
-- redundant options
COPY x from stdin (format CSV, FORMAT CSV);
-ERROR: conflicting or redundant options
+ERROR: option "format" specified more than once
LINE 1: COPY x from stdin (format CSV, FORMAT CSV);
^
COPY x from stdin (freeze off, freeze on);
-ERROR: conflicting or redundant options
+ERROR: option "freeze" specified more than once
LINE 1: COPY x from stdin (freeze off, freeze on);
^
COPY x from stdin (delimiter ',', delimiter ',');
-ERROR: conflicting or redundant options
+ERROR: option "delimiter" specified more than once
LINE 1: COPY x from stdin (delimiter ',', delimiter ',');
^
COPY x from stdin (null ' ', null ' ');
-ERROR: conflicting or redundant options
+ERROR: option "null" specified more than once
LINE 1: COPY x from stdin (null ' ', null ' ');
^
COPY x from stdin (header off, header on);
-ERROR: conflicting or redundant options
+ERROR: option "header" specified more than once
LINE 1: COPY x from stdin (header off, header on);
^
COPY x from stdin (quote ':', quote ':');
-ERROR: conflicting or redundant options
+ERROR: option "quote" specified more than once
LINE 1: COPY x from stdin (quote ':', quote ':');
^
COPY x from stdin (escape ':', escape ':');
-ERROR: conflicting or redundant options
+ERROR: option "escape" specified more than once
LINE 1: COPY x from stdin (escape ':', escape ':');
^
COPY x from stdin (force_quote (a), force_quote *);
@@ -62,17 +62,19 @@ ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (force_quote (a), force_quote *);
^
COPY x from stdin (force_not_null (a), force_not_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_not_null" specified more than once
LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
COPY x from stdin (force_null (a), force_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_null" specified more than once
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
-ERROR: conflicting or redundant options
+ERROR: option "convert_selectively" specified more than once
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
^
COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
-ERROR: conflicting or redundant options
+ERROR: option "encoding" specified more than once
LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
^
-- too many columns in column list: should fail
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 5385f98a0f..0cdab88eed 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -94,7 +94,7 @@ CREATE FUNCTION invalid_fdw_handler() RETURNS int LANGUAGE SQL AS 'SELECT 1;';
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -200,7 +200,7 @@ ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo;
ALTER FOREIGN DATA WRAPPER foo HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 63d6ab7a4e..7887dada21 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -26,7 +26,7 @@ ERROR: unrecognized publication parameter: "foo"
CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
-ERROR: conflicting or redundant options
+ERROR: option "publish_via_partition_root" specified more than once
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
--
2.25.1
v2-0001-compute_common_attribute.patchapplication/octet-stream; name=v2-0001-compute_common_attribute.patchDownload
From df3c467dd3842ade113e0a6443d332dc48996af1 Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddy@enterprisedb.com>
Date: Fri, 30 Apr 2021 10:39:28 +0530
Subject: [PATCH v2] compute_common_attribute
---
src/backend/commands/functioncmds.c | 59 +++++++++++++++--------------
1 file changed, 30 insertions(+), 29 deletions(-)
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9548287217..3b3ebf67c4 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -492,37 +492,40 @@ compute_common_attribute(ParseState *pstate,
DefElem **support_item,
DefElem **parallel_item)
{
+ bool is_duplicate_error = false;
+ bool is_procedure_error = false;
+
if (strcmp(defel->defname, "volatility") == 0)
{
if (is_procedure)
- goto procedure_error;
+ is_procedure_error = true;
if (*volatility_item)
- goto duplicate_error;
+ is_duplicate_error = true;
*volatility_item = defel;
}
else if (strcmp(defel->defname, "strict") == 0)
{
if (is_procedure)
- goto procedure_error;
+ is_procedure_error = true;
if (*strict_item)
- goto duplicate_error;
+ is_duplicate_error = true;
*strict_item = defel;
}
else if (strcmp(defel->defname, "security") == 0)
{
if (*security_item)
- goto duplicate_error;
+ is_duplicate_error = true;
*security_item = defel;
}
else if (strcmp(defel->defname, "leakproof") == 0)
{
if (is_procedure)
- goto procedure_error;
+ is_procedure_error = true;
if (*leakproof_item)
- goto duplicate_error;
+ is_duplicate_error = true;
*leakproof_item = defel;
}
@@ -533,58 +536,56 @@ compute_common_attribute(ParseState *pstate,
else if (strcmp(defel->defname, "cost") == 0)
{
if (is_procedure)
- goto procedure_error;
+ is_procedure_error = true;
if (*cost_item)
- goto duplicate_error;
+ is_duplicate_error = true;
*cost_item = defel;
}
else if (strcmp(defel->defname, "rows") == 0)
{
if (is_procedure)
- goto procedure_error;
+ is_procedure_error = true;
if (*rows_item)
- goto duplicate_error;
+ is_duplicate_error = true;
*rows_item = defel;
}
else if (strcmp(defel->defname, "support") == 0)
{
if (is_procedure)
- goto procedure_error;
+ is_procedure_error = true;
if (*support_item)
- goto duplicate_error;
+ is_duplicate_error = true;
*support_item = defel;
}
else if (strcmp(defel->defname, "parallel") == 0)
{
if (is_procedure)
- goto procedure_error;
+ is_procedure_error = true;
if (*parallel_item)
- goto duplicate_error;
+ is_duplicate_error = true;
*parallel_item = defel;
}
else
return false;
+ if (is_procedure_error)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("invalid attribute in procedure definition"),
+ parser_errposition(pstate, defel->location)));
+
+ if (is_duplicate_error)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+
/* Recognized an option */
return true;
-
-duplicate_error:
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
- return false; /* keep compiler quiet */
-
-procedure_error:
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("invalid attribute in procedure definition"),
- parser_errposition(pstate, defel->location)));
- return false;
}
static char
--
2.25.1
On Fri, Apr 30, 2021 at 10:43 AM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:
On Fri, Apr 30, 2021 at 10:17 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
In this function, we already have the "defel" variable then I do not
understand why you are using one extra variable and assigning defel to
that?
If the goal is to just improve the error message then you can simply
use defel->defname?Yeah. I can do that. Thanks for the comment.
While on this, I also removed the duplicate_error and procedure_error
goto statements, because IMHO, using goto statements is not an elegant
way. I used boolean flags to do the job instead. See the attached and
let me know what you think.
Okay, but I see one side effect of this, basically earlier on
procedure_error and duplicate_error we were not assigning anything to
output parameters, e.g. volatility_item, but now those values will be
assigned with defel even if there is an error. So I think we should
better avoid such change. But even if you want to do then better
check for any impacts on the caller.
--
Regards,
Dilip Kumar
EnterpriseDB: http://www.enterprisedb.com
On Fri, Apr 30, 2021 at 10:51 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
On Fri, Apr 30, 2021 at 10:43 AM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Fri, Apr 30, 2021 at 10:17 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
In this function, we already have the "defel" variable then I do not
understand why you are using one extra variable and assigning defel to
that?
If the goal is to just improve the error message then you can simply
use defel->defname?Yeah. I can do that. Thanks for the comment.
While on this, I also removed the duplicate_error and procedure_error
goto statements, because IMHO, using goto statements is not an elegant
way. I used boolean flags to do the job instead. See the attached and
let me know what you think.Okay, but I see one side effect of this, basically earlier on
procedure_error and duplicate_error we were not assigning anything to
output parameters, e.g. volatility_item, but now those values will be
assigned with defel even if there is an error.
Yes, but on ereport(ERROR, we don't come back right? The txn gets
aborted and the control is not returned to the caller instead it will
go to sigjmp_buf of the backend.
So I think we should
better avoid such change. But even if you want to do then better
check for any impacts on the caller.
AFAICS, there will not be any impact on the caller, as the control
doesn't return to the caller on error.
And another good reason to remove the goto statements is that they
have return false; statements just to suppress the compiler and having
them after ereport(ERROR, doesn't make any sense to me.
duplicate_error:
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options"),
parser_errposition(pstate, defel->location)));
return false; /* keep compiler quiet */
procedure_error:
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("invalid attribute in procedure definition"),
parser_errposition(pstate, defel->location)));
return false;
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
On Fri, Apr 30, 2021 at 11:09 AM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:
On Fri, Apr 30, 2021 at 10:51 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
On Fri, Apr 30, 2021 at 10:43 AM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Fri, Apr 30, 2021 at 10:17 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
In this function, we already have the "defel" variable then I do not
understand why you are using one extra variable and assigning defel to
that?
If the goal is to just improve the error message then you can simply
use defel->defname?Yeah. I can do that. Thanks for the comment.
While on this, I also removed the duplicate_error and procedure_error
goto statements, because IMHO, using goto statements is not an elegant
way. I used boolean flags to do the job instead. See the attached and
let me know what you think.Okay, but I see one side effect of this, basically earlier on
procedure_error and duplicate_error we were not assigning anything to
output parameters, e.g. volatility_item, but now those values will be
assigned with defel even if there is an error.Yes, but on ereport(ERROR, we don't come back right? The txn gets
aborted and the control is not returned to the caller instead it will
go to sigjmp_buf of the backend.So I think we should
better avoid such change. But even if you want to do then better
check for any impacts on the caller.AFAICS, there will not be any impact on the caller, as the control
doesn't return to the caller on error.
I see.
other comments
if (strcmp(defel->defname, "volatility") == 0)
{
if (is_procedure)
- goto procedure_error;
+ is_procedure_error = true;
if (*volatility_item)
- goto duplicate_error;
+ is_duplicate_error = true;
Another side effect I see is, in the above check earlier if
is_procedure was true it was directly goto procedure_error, but now it
will also check the if (*volatility_item) and it may set
is_duplicate_error also true, which seems wrong to me. I think you
can change it to
if (is_procedure)
is_procedure_error = true;
else if (*volatility_item)
is_duplicate_error = true;
--
Regards,
Dilip Kumar
EnterpriseDB: http://www.enterprisedb.com
On Fri, Apr 30, 2021 at 11:23 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
On Fri, Apr 30, 2021 at 11:09 AM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Fri, Apr 30, 2021 at 10:51 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
On Fri, Apr 30, 2021 at 10:43 AM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Fri, Apr 30, 2021 at 10:17 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
In this function, we already have the "defel" variable then I do not
understand why you are using one extra variable and assigning defel to
that?
If the goal is to just improve the error message then you can simply
use defel->defname?Yeah. I can do that. Thanks for the comment.
While on this, I also removed the duplicate_error and procedure_error
goto statements, because IMHO, using goto statements is not an elegant
way. I used boolean flags to do the job instead. See the attached and
let me know what you think.Okay, but I see one side effect of this, basically earlier on
procedure_error and duplicate_error we were not assigning anything to
output parameters, e.g. volatility_item, but now those values will be
assigned with defel even if there is an error.Yes, but on ereport(ERROR, we don't come back right? The txn gets
aborted and the control is not returned to the caller instead it will
go to sigjmp_buf of the backend.So I think we should
better avoid such change. But even if you want to do then better
check for any impacts on the caller.AFAICS, there will not be any impact on the caller, as the control
doesn't return to the caller on error.I see.
other comments
if (strcmp(defel->defname, "volatility") == 0) { if (is_procedure) - goto procedure_error; + is_procedure_error = true; if (*volatility_item) - goto duplicate_error; + is_duplicate_error = true;Another side effect I see is, in the above check earlier if
is_procedure was true it was directly goto procedure_error, but now it
will also check the if (*volatility_item) and it may set
is_duplicate_error also true, which seems wrong to me. I think you
can change it toif (is_procedure)
is_procedure_error = true;
else if (*volatility_item)
is_duplicate_error = true;
Thanks. Done that way, see the attached v3. Let's see what others has to say.
Also attaching Vignesh's v3 patch as-is, just for completion.
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
Attachments:
v3-0001-Enhance-error-message.patchapplication/x-patch; name=v3-0001-Enhance-error-message.patchDownload
From 6ed153cdb45a0d41d3889dc7d80b3a743eb66725 Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Mon, 26 Apr 2021 18:40:36 +0530
Subject: [PATCH v3] Enhance error message.
Enhanced error message, so that the user can easily identify the error.
---
contrib/file_fdw/file_fdw.c | 6 +--
src/backend/catalog/aclchk.c | 4 +-
src/backend/commands/copy.c | 23 +++++-----
src/backend/commands/dbcommands.c | 28 ++++++------
src/backend/commands/extension.c | 8 ++--
src/backend/commands/foreigncmds.c | 4 +-
src/backend/commands/functioncmds.c | 12 +++---
src/backend/commands/publicationcmds.c | 4 +-
src/backend/commands/sequence.c | 18 ++++----
src/backend/commands/subscriptioncmds.c | 18 ++++----
src/backend/commands/tablecmds.c | 2 +-
src/backend/commands/typecmds.c | 14 +++---
src/backend/commands/user.c | 48 ++++++++++-----------
src/backend/parser/parse_utilcmd.c | 2 +-
src/backend/replication/pgoutput/pgoutput.c | 10 ++---
src/backend/replication/walsender.c | 6 +--
src/test/regress/expected/copy2.out | 24 ++++++-----
src/test/regress/expected/foreign_data.out | 4 +-
src/test/regress/expected/publication.out | 2 +-
19 files changed, 119 insertions(+), 118 deletions(-)
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 2c2f149fb0..10aa2fca28 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -292,8 +292,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
if (force_not_null)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_not_null\" supplied more than once for a column.")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
force_not_null = def;
/* Don't care what the value is, as long as it's a legal boolean */
(void) defGetBoolean(def);
@@ -304,8 +303,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
if (force_null)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_null\" supplied more than once for a column.")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
force_null = def;
(void) defGetBoolean(def);
}
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index e1573eb398..7885587bfc 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -923,7 +923,7 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
if (dnspnames)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dnspnames = defel;
}
@@ -932,7 +932,7 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
if (drolespecs)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
drolespecs = defel;
}
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 8265b981eb..2860f36f91 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -359,7 +359,7 @@ ProcessCopyOptions(ParseState *pstate,
if (format_specified)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
format_specified = true;
if (strcmp(fmt, "text") == 0)
@@ -379,7 +379,7 @@ ProcessCopyOptions(ParseState *pstate,
if (freeze_specified)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
freeze_specified = true;
opts_out->freeze = defGetBoolean(defel);
@@ -389,7 +389,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->delim)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->delim = defGetString(defel);
}
@@ -398,7 +398,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->null_print)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->null_print = defGetString(defel);
}
@@ -407,7 +407,7 @@ ProcessCopyOptions(ParseState *pstate,
if (header_specified)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
header_specified = true;
opts_out->header_line = defGetBoolean(defel);
@@ -417,7 +417,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->quote)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->quote = defGetString(defel);
}
@@ -426,7 +426,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->escape)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->escape = defGetString(defel);
}
@@ -453,7 +453,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->force_notnull)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
if (defel->arg && IsA(defel->arg, List))
opts_out->force_notnull = castNode(List, defel->arg);
@@ -469,7 +469,8 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->force_null)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
@@ -489,7 +490,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->convert_selectively)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->convert_selectively = true;
if (defel->arg == NULL || IsA(defel->arg, List))
@@ -506,7 +507,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->file_encoding >= 0)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
if (opts_out->file_encoding < 0)
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 2b159b60eb..15ca32c898 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -154,7 +154,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dtablespacename)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dtablespacename = defel;
}
@@ -163,7 +163,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (downer)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
downer = defel;
}
@@ -172,7 +172,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dtemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dtemplate = defel;
}
@@ -181,7 +181,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dencoding)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dencoding = defel;
}
@@ -190,7 +190,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dlocale)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dlocale = defel;
}
@@ -199,7 +199,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dcollate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcollate = defel;
}
@@ -208,7 +208,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dctype)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dctype = defel;
}
@@ -217,7 +217,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (distemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
distemplate = defel;
}
@@ -226,7 +226,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dallowconnections)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dallowconnections = defel;
}
@@ -235,7 +235,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
@@ -1499,7 +1499,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (distemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
distemplate = defel;
}
@@ -1508,7 +1508,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (dallowconnections)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dallowconnections = defel;
}
@@ -1517,7 +1517,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
@@ -1526,7 +1526,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (dtablespace)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dtablespace = defel;
}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 19db329fe6..5525919735 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1732,7 +1732,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
if (d_schema)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_schema = defel;
schemaName = defGetString(d_schema);
@@ -1742,7 +1742,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
if (d_new_version)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_new_version = defel;
versionName = defGetString(d_new_version);
@@ -1752,7 +1752,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
if (d_cascade)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_cascade = defel;
cascade = defGetBoolean(d_cascade);
@@ -3052,7 +3052,7 @@ ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
if (d_new_version)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_new_version = defel;
}
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index eb7103fd3b..d9cf3227fe 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -536,7 +536,7 @@ parse_func_options(List *func_options,
if (*handler_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
@@ -545,7 +545,7 @@ parse_func_options(List *func_options,
if (*validator_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9548287217..ed13bf547c 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -741,7 +741,7 @@ compute_function_attributes(ParseState *pstate,
if (as_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
as_item = defel;
}
@@ -750,7 +750,7 @@ compute_function_attributes(ParseState *pstate,
if (language_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
language_item = defel;
}
@@ -759,7 +759,7 @@ compute_function_attributes(ParseState *pstate,
if (transform_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
transform_item = defel;
}
@@ -768,7 +768,7 @@ compute_function_attributes(ParseState *pstate,
if (windowfunc_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
if (is_procedure)
ereport(ERROR,
@@ -2065,7 +2065,7 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (as_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
@@ -2073,7 +2073,7 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (language_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
language_item = defel;
}
else
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 95c253c8e0..9dc2bfdd60 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -87,7 +87,7 @@ parse_publication_options(List *options,
if (*publish_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
/*
* If publish option was given only the explicitly listed actions
@@ -130,7 +130,7 @@ parse_publication_options(List *options,
if (*publish_via_partition_root_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 0415df9ccb..f2180cd29b 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1263,7 +1263,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (as_type)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
as_type = defel;
*need_seq_rewrite = true;
@@ -1273,7 +1273,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (increment_by)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
increment_by = defel;
*need_seq_rewrite = true;
@@ -1283,7 +1283,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (start_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
start_value = defel;
*need_seq_rewrite = true;
@@ -1293,7 +1293,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (restart_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
restart_value = defel;
*need_seq_rewrite = true;
@@ -1303,7 +1303,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (max_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
max_value = defel;
*need_seq_rewrite = true;
@@ -1313,7 +1313,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (min_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
min_value = defel;
*need_seq_rewrite = true;
@@ -1323,7 +1323,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (cache_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
cache_value = defel;
*need_seq_rewrite = true;
@@ -1333,7 +1333,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (is_cycled)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
is_cycled = defel;
*need_seq_rewrite = true;
@@ -1343,7 +1343,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (*owned_by)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
*owned_by = defGetQualifiedName(defel);
}
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 517c8edd3b..662191bc9e 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -121,7 +121,7 @@ parse_subscription_options(List *options,
if (connect_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
connect_given = true;
*connect = defGetBoolean(defel);
@@ -131,7 +131,7 @@ parse_subscription_options(List *options,
if (*enabled_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*enabled_given = true;
*enabled = defGetBoolean(defel);
@@ -141,7 +141,7 @@ parse_subscription_options(List *options,
if (create_slot_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
create_slot_given = true;
*create_slot = defGetBoolean(defel);
@@ -151,7 +151,7 @@ parse_subscription_options(List *options,
if (*slot_name_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*slot_name_given = true;
*slot_name = defGetString(defel);
@@ -165,7 +165,7 @@ parse_subscription_options(List *options,
if (copy_data_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
copy_data_given = true;
*copy_data = defGetBoolean(defel);
@@ -176,7 +176,7 @@ parse_subscription_options(List *options,
if (*synchronous_commit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*synchronous_commit = defGetString(defel);
@@ -190,7 +190,7 @@ parse_subscription_options(List *options,
if (refresh_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
refresh_given = true;
*refresh = defGetBoolean(defel);
@@ -200,7 +200,7 @@ parse_subscription_options(List *options,
if (*binary_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*binary_given = true;
*binary = defGetBoolean(defel);
@@ -210,7 +210,7 @@ parse_subscription_options(List *options,
if (*streaming_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*streaming_given = true;
*streaming = defGetBoolean(defel);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index d9ba87a2a3..26a1f16271 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7524,7 +7524,7 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmod
if (generatedEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 036fa69d17..84d654d5a5 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -332,7 +332,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
if (*defelp != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
*defelp = defel;
}
@@ -1413,7 +1413,7 @@ DefineRange(CreateRangeStmt *stmt)
if (OidIsValid(rangeSubtype))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
@@ -1422,7 +1422,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeSubOpclassName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
@@ -1430,7 +1430,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeCollationName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
@@ -1438,7 +1438,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeCanonicalName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
@@ -1446,7 +1446,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeSubtypeDiffName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
@@ -1454,7 +1454,7 @@ DefineRange(CreateRangeStmt *stmt)
if (multirangeTypeName != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 65bb733958..4c7af6252d 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -130,7 +130,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dpassword)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dpassword = defel;
}
@@ -144,7 +144,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dissuper)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dissuper = defel;
}
@@ -153,7 +153,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dinherit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dinherit = defel;
}
@@ -162,7 +162,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dcreaterole)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcreaterole = defel;
}
@@ -171,7 +171,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dcreatedb)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcreatedb = defel;
}
@@ -180,7 +180,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dcanlogin)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcanlogin = defel;
}
@@ -189,7 +189,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (disreplication)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
disreplication = defel;
}
@@ -198,7 +198,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
@@ -207,7 +207,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (daddroleto)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
daddroleto = defel;
}
@@ -216,7 +216,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (drolemembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
drolemembers = defel;
}
@@ -225,7 +225,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dadminmembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dadminmembers = defel;
}
@@ -234,7 +234,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dvalidUntil)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dvalidUntil = defel;
}
@@ -243,7 +243,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dbypassRLS)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dbypassRLS = defel;
}
@@ -579,7 +579,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dpassword)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
@@ -587,7 +587,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dissuper)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
@@ -595,7 +595,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dinherit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
@@ -603,7 +603,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dcreaterole)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
@@ -611,7 +611,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dcreatedb)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
@@ -619,7 +619,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dcanlogin)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
@@ -627,7 +627,7 @@ AlterRole(AlterRoleStmt *stmt)
if (disreplication)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
@@ -635,7 +635,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
@@ -644,7 +644,7 @@ AlterRole(AlterRoleStmt *stmt)
if (drolemembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
@@ -652,7 +652,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dvalidUntil)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
@@ -660,7 +660,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dbypassRLS)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dbypassRLS = defel;
}
else
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 9dd30370da..9e44885146 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -402,7 +402,7 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (nameEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index f68348dcf4..50995868db 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -189,7 +189,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (protocol_version_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -210,7 +210,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (publication_names_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -224,7 +224,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (binary_option_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -234,7 +234,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (messages_option_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -244,7 +244,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (streaming_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
streaming_given = true;
data->streaming = defGetBoolean(defel);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 6fefc3bedc..e79690a0f9 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -882,7 +882,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
snapshot_action_given = true;
*snapshot_action = defGetBoolean(defel) ? CRS_EXPORT_SNAPSHOT :
@@ -893,7 +893,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
snapshot_action_given = true;
*snapshot_action = CRS_USE_SNAPSHOT;
@@ -903,7 +903,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (reserve_wal_given || cmd->kind != REPLICATION_KIND_PHYSICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
reserve_wal_given = true;
*reserve_wal = true;
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c64f0719e7..92fe8a121a 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -30,31 +30,31 @@ COPY x (xyz) from stdin;
ERROR: column "xyz" of relation "x" does not exist
-- redundant options
COPY x from stdin (format CSV, FORMAT CSV);
-ERROR: conflicting or redundant options
+ERROR: option "format" specified more than once
LINE 1: COPY x from stdin (format CSV, FORMAT CSV);
^
COPY x from stdin (freeze off, freeze on);
-ERROR: conflicting or redundant options
+ERROR: option "freeze" specified more than once
LINE 1: COPY x from stdin (freeze off, freeze on);
^
COPY x from stdin (delimiter ',', delimiter ',');
-ERROR: conflicting or redundant options
+ERROR: option "delimiter" specified more than once
LINE 1: COPY x from stdin (delimiter ',', delimiter ',');
^
COPY x from stdin (null ' ', null ' ');
-ERROR: conflicting or redundant options
+ERROR: option "null" specified more than once
LINE 1: COPY x from stdin (null ' ', null ' ');
^
COPY x from stdin (header off, header on);
-ERROR: conflicting or redundant options
+ERROR: option "header" specified more than once
LINE 1: COPY x from stdin (header off, header on);
^
COPY x from stdin (quote ':', quote ':');
-ERROR: conflicting or redundant options
+ERROR: option "quote" specified more than once
LINE 1: COPY x from stdin (quote ':', quote ':');
^
COPY x from stdin (escape ':', escape ':');
-ERROR: conflicting or redundant options
+ERROR: option "escape" specified more than once
LINE 1: COPY x from stdin (escape ':', escape ':');
^
COPY x from stdin (force_quote (a), force_quote *);
@@ -62,17 +62,19 @@ ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (force_quote (a), force_quote *);
^
COPY x from stdin (force_not_null (a), force_not_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_not_null" specified more than once
LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
COPY x from stdin (force_null (a), force_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_null" specified more than once
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
-ERROR: conflicting or redundant options
+ERROR: option "convert_selectively" specified more than once
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
^
COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
-ERROR: conflicting or redundant options
+ERROR: option "encoding" specified more than once
LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
^
-- too many columns in column list: should fail
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 5385f98a0f..0cdab88eed 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -94,7 +94,7 @@ CREATE FUNCTION invalid_fdw_handler() RETURNS int LANGUAGE SQL AS 'SELECT 1;';
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -200,7 +200,7 @@ ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo;
ALTER FOREIGN DATA WRAPPER foo HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 63d6ab7a4e..7887dada21 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -26,7 +26,7 @@ ERROR: unrecognized publication parameter: "foo"
CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
-ERROR: conflicting or redundant options
+ERROR: option "publish_via_partition_root" specified more than once
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
--
2.25.1
v3-0001-compute_common_attribute.patchapplication/x-patch; name=v3-0001-compute_common_attribute.patchDownload
From eee10389a5d2071e564ba174bb462f7500be33d4 Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddy@enterprisedb.com>
Date: Fri, 30 Apr 2021 11:35:05 +0530
Subject: [PATCH v3] compute_common_attribute
---
src/backend/commands/functioncmds.c | 73 +++++++++++++++--------------
1 file changed, 37 insertions(+), 36 deletions(-)
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9548287217..7bd97f5fad 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -492,37 +492,40 @@ compute_common_attribute(ParseState *pstate,
DefElem **support_item,
DefElem **parallel_item)
{
+ bool is_duplicate_error = false;
+ bool is_procedure_error = false;
+
if (strcmp(defel->defname, "volatility") == 0)
{
if (is_procedure)
- goto procedure_error;
- if (*volatility_item)
- goto duplicate_error;
+ is_procedure_error = true;
+ else if (*volatility_item)
+ is_duplicate_error = true;
*volatility_item = defel;
}
else if (strcmp(defel->defname, "strict") == 0)
{
if (is_procedure)
- goto procedure_error;
- if (*strict_item)
- goto duplicate_error;
+ is_procedure_error = true;
+ else if (*strict_item)
+ is_duplicate_error = true;
*strict_item = defel;
}
else if (strcmp(defel->defname, "security") == 0)
{
if (*security_item)
- goto duplicate_error;
+ is_duplicate_error = true;
*security_item = defel;
}
else if (strcmp(defel->defname, "leakproof") == 0)
{
if (is_procedure)
- goto procedure_error;
- if (*leakproof_item)
- goto duplicate_error;
+ is_procedure_error = true;
+ else if (*leakproof_item)
+ is_duplicate_error = true;
*leakproof_item = defel;
}
@@ -533,58 +536,56 @@ compute_common_attribute(ParseState *pstate,
else if (strcmp(defel->defname, "cost") == 0)
{
if (is_procedure)
- goto procedure_error;
- if (*cost_item)
- goto duplicate_error;
+ is_procedure_error = true;
+ else if (*cost_item)
+ is_duplicate_error = true;
*cost_item = defel;
}
else if (strcmp(defel->defname, "rows") == 0)
{
if (is_procedure)
- goto procedure_error;
- if (*rows_item)
- goto duplicate_error;
+ is_procedure_error = true;
+ else if (*rows_item)
+ is_duplicate_error = true;
*rows_item = defel;
}
else if (strcmp(defel->defname, "support") == 0)
{
if (is_procedure)
- goto procedure_error;
- if (*support_item)
- goto duplicate_error;
+ is_procedure_error = true;
+ else if (*support_item)
+ is_duplicate_error = true;
*support_item = defel;
}
else if (strcmp(defel->defname, "parallel") == 0)
{
if (is_procedure)
- goto procedure_error;
- if (*parallel_item)
- goto duplicate_error;
+ is_procedure_error = true;
+ else if (*parallel_item)
+ is_duplicate_error = true;
*parallel_item = defel;
}
else
return false;
+ if (is_procedure_error)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("invalid attribute in procedure definition"),
+ parser_errposition(pstate, defel->location)));
+
+ if (is_duplicate_error)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+
/* Recognized an option */
return true;
-
-duplicate_error:
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
- return false; /* keep compiler quiet */
-
-procedure_error:
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("invalid attribute in procedure definition"),
- parser_errposition(pstate, defel->location)));
- return false;
}
static char
--
2.25.1
On Fri, Apr 30, 2021 at 5:06 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:
On Fri, Apr 30, 2021 at 11:23 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
On Fri, Apr 30, 2021 at 11:09 AM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Fri, Apr 30, 2021 at 10:51 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
On Fri, Apr 30, 2021 at 10:43 AM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Fri, Apr 30, 2021 at 10:17 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
In this function, we already have the "defel" variable then I do not
understand why you are using one extra variable and assigning defel to
that?
If the goal is to just improve the error message then you can simply
use defel->defname?Yeah. I can do that. Thanks for the comment.
While on this, I also removed the duplicate_error and procedure_error
goto statements, because IMHO, using goto statements is not an elegant
way. I used boolean flags to do the job instead. See the attached and
let me know what you think.Okay, but I see one side effect of this, basically earlier on
procedure_error and duplicate_error we were not assigning anything to
output parameters, e.g. volatility_item, but now those values will be
assigned with defel even if there is an error.Yes, but on ereport(ERROR, we don't come back right? The txn gets
aborted and the control is not returned to the caller instead it will
go to sigjmp_buf of the backend.So I think we should
better avoid such change. But even if you want to do then better
check for any impacts on the caller.AFAICS, there will not be any impact on the caller, as the control
doesn't return to the caller on error.I see.
other comments
if (strcmp(defel->defname, "volatility") == 0) { if (is_procedure) - goto procedure_error; + is_procedure_error = true; if (*volatility_item) - goto duplicate_error; + is_duplicate_error = true;Another side effect I see is, in the above check earlier if
is_procedure was true it was directly goto procedure_error, but now it
will also check the if (*volatility_item) and it may set
is_duplicate_error also true, which seems wrong to me. I think you
can change it toif (is_procedure)
is_procedure_error = true;
else if (*volatility_item)
is_duplicate_error = true;Thanks. Done that way, see the attached v3. Let's see what others has to say.
Hmmm - I am not so sure about those goto replacements. I think the
poor goto has a bad reputation, but not all gotos are bad. I've met
some very nice gotos.
Each goto here was doing exactly what it looked like it was doing,
whereas all these boolean replacements have now introduced subtle
differences. e.g. now the *volatility_item = defel; assignment (and
all similar assignments) will happen which previously did not happen
at all. It leaves the reader wondering if assigning to those
references could have any side-effects at the caller. Probably there
are no problems at all....but can you be sure? Meanwhile, those
"inelegant" gotos did not give any cause for such doubts.
------
Kind Regards,
Peter Smith.
Fujitsu Australia
On Fri, Apr 30, 2021 at 12:36 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:
other comments
if (strcmp(defel->defname, "volatility") == 0) { if (is_procedure) - goto procedure_error; + is_procedure_error = true; if (*volatility_item) - goto duplicate_error; + is_duplicate_error = true;Another side effect I see is, in the above check earlier if
is_procedure was true it was directly goto procedure_error, but now it
will also check the if (*volatility_item) and it may set
is_duplicate_error also true, which seems wrong to me. I think you
can change it toif (is_procedure)
is_procedure_error = true;
else if (*volatility_item)
is_duplicate_error = true;Thanks. Done that way, see the attached v3. Let's see what others has to say.
Also attaching Vignesh's v3 patch as-is, just for completion.
Looking into this again, why not as shown below? IMHO, this way the
code will be logically the same as it was before the patch, basically
why to process an extra statement ( *volatility_item = defel;) if we
have already decided to error.
if (is_procedure)
is_procedure_error = true;
else if (*volatility_item)
is_duplicate_error = true;
else
*volatility_item = defel;
--
Regards,
Dilip Kumar
EnterpriseDB: http://www.enterprisedb.com
On Fri, Apr 30, 2021 at 2:49 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
Looking into this again, why not as shown below? IMHO, this way the
code will be logically the same as it was before the patch, basically
why to process an extra statement ( *volatility_item = defel;) if we
have already decided to error.
I changed my mind given the concerns raised on removing the goto
statements. We could just do as below:
diff --git a/src/backend/commands/functioncmds.c
b/src/backend/commands/functioncmds.c
index 9548287217..1f1c74c379 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -575,7 +575,7 @@ compute_common_attribute(ParseState *pstate,
duplicate_error:
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
return false; /* keep compiler quiet */
I'm not attaching above one line change as a patch, maybe Vignesh can
merge this into the main patch.
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
On Sat, May 1, 2021 at 10:43 AM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:
On Fri, Apr 30, 2021 at 2:49 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
Looking into this again, why not as shown below? IMHO, this way the
code will be logically the same as it was before the patch, basically
why to process an extra statement ( *volatility_item = defel;) if we
have already decided to error.I changed my mind given the concerns raised on removing the goto
statements. We could just do as below:
Okay, that make sense.
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 9548287217..1f1c74c379 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -575,7 +575,7 @@ compute_common_attribute(ParseState *pstate, duplicate_error: ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("conflicting or redundant options"), + errmsg("option \"%s\" specified more than once", defel->defname), parser_errposition(pstate, defel->location))); return false; /* keep compiler quiet */I'm not attaching above one line change as a patch, maybe Vignesh can
merge this into the main patch.
+1
--
Regards,
Dilip Kumar
EnterpriseDB: http://www.enterprisedb.com
On Sat, May 1, 2021 at 10:47 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
On Sat, May 1, 2021 at 10:43 AM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Fri, Apr 30, 2021 at 2:49 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
Looking into this again, why not as shown below? IMHO, this way the
code will be logically the same as it was before the patch, basically
why to process an extra statement ( *volatility_item = defel;) if we
have already decided to error.I changed my mind given the concerns raised on removing the goto
statements. We could just do as below:Okay, that make sense.
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 9548287217..1f1c74c379 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -575,7 +575,7 @@ compute_common_attribute(ParseState *pstate, duplicate_error: ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("conflicting or redundant options"), + errmsg("option \"%s\" specified more than once", defel->defname), parser_errposition(pstate, defel->location))); return false; /* keep compiler quiet */I'm not attaching above one line change as a patch, maybe Vignesh can
merge this into the main patch.
Thanks for the comments. I have merged the change into the attached patch.
Thoughts?
Regards,
Vignesh
Attachments:
v4-0001-Enhance-error-message.patchtext/x-patch; charset=US-ASCII; name=v4-0001-Enhance-error-message.patchDownload
From b76a67be6c162d064f0a9cecd3ebc66d6c8fcbd9 Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Mon, 26 Apr 2021 18:40:36 +0530
Subject: [PATCH v4] Enhance error message.
Enhanced error message, so that the user can easily identify the error.
---
contrib/file_fdw/file_fdw.c | 6 +--
src/backend/catalog/aclchk.c | 4 +-
src/backend/commands/copy.c | 23 +++++-----
src/backend/commands/dbcommands.c | 28 ++++++------
src/backend/commands/extension.c | 8 ++--
src/backend/commands/foreigncmds.c | 4 +-
src/backend/commands/functioncmds.c | 14 +++---
src/backend/commands/publicationcmds.c | 4 +-
src/backend/commands/sequence.c | 18 ++++----
src/backend/commands/subscriptioncmds.c | 18 ++++----
src/backend/commands/tablecmds.c | 2 +-
src/backend/commands/typecmds.c | 14 +++---
src/backend/commands/user.c | 48 ++++++++++-----------
src/backend/parser/parse_utilcmd.c | 2 +-
src/backend/replication/pgoutput/pgoutput.c | 10 ++---
src/backend/replication/walsender.c | 6 +--
src/test/regress/expected/copy2.out | 24 ++++++-----
src/test/regress/expected/foreign_data.out | 4 +-
src/test/regress/expected/publication.out | 2 +-
19 files changed, 120 insertions(+), 119 deletions(-)
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 2c2f149fb0..10aa2fca28 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -292,8 +292,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
if (force_not_null)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_not_null\" supplied more than once for a column.")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
force_not_null = def;
/* Don't care what the value is, as long as it's a legal boolean */
(void) defGetBoolean(def);
@@ -304,8 +303,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
if (force_null)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_null\" supplied more than once for a column.")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
force_null = def;
(void) defGetBoolean(def);
}
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index e1573eb398..7885587bfc 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -923,7 +923,7 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
if (dnspnames)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dnspnames = defel;
}
@@ -932,7 +932,7 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
if (drolespecs)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
drolespecs = defel;
}
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 8265b981eb..2860f36f91 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -359,7 +359,7 @@ ProcessCopyOptions(ParseState *pstate,
if (format_specified)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
format_specified = true;
if (strcmp(fmt, "text") == 0)
@@ -379,7 +379,7 @@ ProcessCopyOptions(ParseState *pstate,
if (freeze_specified)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
freeze_specified = true;
opts_out->freeze = defGetBoolean(defel);
@@ -389,7 +389,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->delim)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->delim = defGetString(defel);
}
@@ -398,7 +398,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->null_print)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->null_print = defGetString(defel);
}
@@ -407,7 +407,7 @@ ProcessCopyOptions(ParseState *pstate,
if (header_specified)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
header_specified = true;
opts_out->header_line = defGetBoolean(defel);
@@ -417,7 +417,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->quote)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->quote = defGetString(defel);
}
@@ -426,7 +426,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->escape)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->escape = defGetString(defel);
}
@@ -453,7 +453,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->force_notnull)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
if (defel->arg && IsA(defel->arg, List))
opts_out->force_notnull = castNode(List, defel->arg);
@@ -469,7 +469,8 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->force_null)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
@@ -489,7 +490,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->convert_selectively)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->convert_selectively = true;
if (defel->arg == NULL || IsA(defel->arg, List))
@@ -506,7 +507,7 @@ ProcessCopyOptions(ParseState *pstate,
if (opts_out->file_encoding >= 0)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
if (opts_out->file_encoding < 0)
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 2b159b60eb..15ca32c898 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -154,7 +154,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dtablespacename)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dtablespacename = defel;
}
@@ -163,7 +163,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (downer)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
downer = defel;
}
@@ -172,7 +172,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dtemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dtemplate = defel;
}
@@ -181,7 +181,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dencoding)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dencoding = defel;
}
@@ -190,7 +190,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dlocale)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dlocale = defel;
}
@@ -199,7 +199,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dcollate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcollate = defel;
}
@@ -208,7 +208,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dctype)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dctype = defel;
}
@@ -217,7 +217,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (distemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
distemplate = defel;
}
@@ -226,7 +226,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dallowconnections)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dallowconnections = defel;
}
@@ -235,7 +235,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
@@ -1499,7 +1499,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (distemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
distemplate = defel;
}
@@ -1508,7 +1508,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (dallowconnections)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dallowconnections = defel;
}
@@ -1517,7 +1517,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
@@ -1526,7 +1526,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (dtablespace)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dtablespace = defel;
}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 19db329fe6..5525919735 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1732,7 +1732,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
if (d_schema)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_schema = defel;
schemaName = defGetString(d_schema);
@@ -1742,7 +1742,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
if (d_new_version)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_new_version = defel;
versionName = defGetString(d_new_version);
@@ -1752,7 +1752,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
if (d_cascade)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_cascade = defel;
cascade = defGetBoolean(d_cascade);
@@ -3052,7 +3052,7 @@ ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
if (d_new_version)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_new_version = defel;
}
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index eb7103fd3b..d9cf3227fe 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -536,7 +536,7 @@ parse_func_options(List *func_options,
if (*handler_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
@@ -545,7 +545,7 @@ parse_func_options(List *func_options,
if (*validator_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", def->defname)));
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9548287217..a9b797ea8e 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -575,7 +575,7 @@ compute_common_attribute(ParseState *pstate,
duplicate_error:
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
return false; /* keep compiler quiet */
@@ -741,7 +741,7 @@ compute_function_attributes(ParseState *pstate,
if (as_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
as_item = defel;
}
@@ -750,7 +750,7 @@ compute_function_attributes(ParseState *pstate,
if (language_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
language_item = defel;
}
@@ -759,7 +759,7 @@ compute_function_attributes(ParseState *pstate,
if (transform_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
transform_item = defel;
}
@@ -768,7 +768,7 @@ compute_function_attributes(ParseState *pstate,
if (windowfunc_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
if (is_procedure)
ereport(ERROR,
@@ -2065,7 +2065,7 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (as_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
@@ -2073,7 +2073,7 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (language_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
language_item = defel;
}
else
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 95c253c8e0..9dc2bfdd60 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -87,7 +87,7 @@ parse_publication_options(List *options,
if (*publish_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
/*
* If publish option was given only the explicitly listed actions
@@ -130,7 +130,7 @@ parse_publication_options(List *options,
if (*publish_via_partition_root_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 0415df9ccb..f2180cd29b 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1263,7 +1263,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (as_type)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
as_type = defel;
*need_seq_rewrite = true;
@@ -1273,7 +1273,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (increment_by)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
increment_by = defel;
*need_seq_rewrite = true;
@@ -1283,7 +1283,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (start_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
start_value = defel;
*need_seq_rewrite = true;
@@ -1293,7 +1293,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (restart_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
restart_value = defel;
*need_seq_rewrite = true;
@@ -1303,7 +1303,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (max_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
max_value = defel;
*need_seq_rewrite = true;
@@ -1313,7 +1313,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (min_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
min_value = defel;
*need_seq_rewrite = true;
@@ -1323,7 +1323,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (cache_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
cache_value = defel;
*need_seq_rewrite = true;
@@ -1333,7 +1333,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (is_cycled)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
is_cycled = defel;
*need_seq_rewrite = true;
@@ -1343,7 +1343,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (*owned_by)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
*owned_by = defGetQualifiedName(defel);
}
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 517c8edd3b..662191bc9e 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -121,7 +121,7 @@ parse_subscription_options(List *options,
if (connect_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
connect_given = true;
*connect = defGetBoolean(defel);
@@ -131,7 +131,7 @@ parse_subscription_options(List *options,
if (*enabled_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*enabled_given = true;
*enabled = defGetBoolean(defel);
@@ -141,7 +141,7 @@ parse_subscription_options(List *options,
if (create_slot_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
create_slot_given = true;
*create_slot = defGetBoolean(defel);
@@ -151,7 +151,7 @@ parse_subscription_options(List *options,
if (*slot_name_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*slot_name_given = true;
*slot_name = defGetString(defel);
@@ -165,7 +165,7 @@ parse_subscription_options(List *options,
if (copy_data_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
copy_data_given = true;
*copy_data = defGetBoolean(defel);
@@ -176,7 +176,7 @@ parse_subscription_options(List *options,
if (*synchronous_commit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*synchronous_commit = defGetString(defel);
@@ -190,7 +190,7 @@ parse_subscription_options(List *options,
if (refresh_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
refresh_given = true;
*refresh = defGetBoolean(defel);
@@ -200,7 +200,7 @@ parse_subscription_options(List *options,
if (*binary_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*binary_given = true;
*binary = defGetBoolean(defel);
@@ -210,7 +210,7 @@ parse_subscription_options(List *options,
if (*streaming_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
*streaming_given = true;
*streaming = defGetBoolean(defel);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index d9ba87a2a3..26a1f16271 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7524,7 +7524,7 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmod
if (generatedEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 036fa69d17..84d654d5a5 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -332,7 +332,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
if (*defelp != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
*defelp = defel;
}
@@ -1413,7 +1413,7 @@ DefineRange(CreateRangeStmt *stmt)
if (OidIsValid(rangeSubtype))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
@@ -1422,7 +1422,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeSubOpclassName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
@@ -1430,7 +1430,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeCollationName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
@@ -1438,7 +1438,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeCanonicalName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
@@ -1446,7 +1446,7 @@ DefineRange(CreateRangeStmt *stmt)
if (rangeSubtypeDiffName != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
@@ -1454,7 +1454,7 @@ DefineRange(CreateRangeStmt *stmt)
if (multirangeTypeName != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 65bb733958..4c7af6252d 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -130,7 +130,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dpassword)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dpassword = defel;
}
@@ -144,7 +144,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dissuper)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dissuper = defel;
}
@@ -153,7 +153,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dinherit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dinherit = defel;
}
@@ -162,7 +162,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dcreaterole)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcreaterole = defel;
}
@@ -171,7 +171,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dcreatedb)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcreatedb = defel;
}
@@ -180,7 +180,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dcanlogin)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dcanlogin = defel;
}
@@ -189,7 +189,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (disreplication)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
disreplication = defel;
}
@@ -198,7 +198,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
@@ -207,7 +207,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (daddroleto)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
daddroleto = defel;
}
@@ -216,7 +216,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (drolemembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
drolemembers = defel;
}
@@ -225,7 +225,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dadminmembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dadminmembers = defel;
}
@@ -234,7 +234,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dvalidUntil)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dvalidUntil = defel;
}
@@ -243,7 +243,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (dbypassRLS)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
dbypassRLS = defel;
}
@@ -579,7 +579,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dpassword)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
@@ -587,7 +587,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dissuper)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
@@ -595,7 +595,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dinherit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
@@ -603,7 +603,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dcreaterole)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
@@ -611,7 +611,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dcreatedb)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
@@ -619,7 +619,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dcanlogin)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
@@ -627,7 +627,7 @@ AlterRole(AlterRoleStmt *stmt)
if (disreplication)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
@@ -635,7 +635,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
@@ -644,7 +644,7 @@ AlterRole(AlterRoleStmt *stmt)
if (drolemembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
@@ -652,7 +652,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dvalidUntil)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
@@ -660,7 +660,7 @@ AlterRole(AlterRoleStmt *stmt)
if (dbypassRLS)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
dbypassRLS = defel;
}
else
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 9dd30370da..9e44885146 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -402,7 +402,7 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (nameEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index f68348dcf4..50995868db 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -189,7 +189,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (protocol_version_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -210,7 +210,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (publication_names_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -224,7 +224,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (binary_option_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -234,7 +234,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (messages_option_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -244,7 +244,7 @@ parse_output_parameters(List *options, PGOutputData *data)
if (streaming_given)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
streaming_given = true;
data->streaming = defGetBoolean(defel);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 6fefc3bedc..e79690a0f9 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -882,7 +882,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
snapshot_action_given = true;
*snapshot_action = defGetBoolean(defel) ? CRS_EXPORT_SNAPSHOT :
@@ -893,7 +893,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
snapshot_action_given = true;
*snapshot_action = CRS_USE_SNAPSHOT;
@@ -903,7 +903,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (reserve_wal_given || cmd->kind != REPLICATION_KIND_PHYSICAL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
reserve_wal_given = true;
*reserve_wal = true;
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c64f0719e7..92fe8a121a 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -30,31 +30,31 @@ COPY x (xyz) from stdin;
ERROR: column "xyz" of relation "x" does not exist
-- redundant options
COPY x from stdin (format CSV, FORMAT CSV);
-ERROR: conflicting or redundant options
+ERROR: option "format" specified more than once
LINE 1: COPY x from stdin (format CSV, FORMAT CSV);
^
COPY x from stdin (freeze off, freeze on);
-ERROR: conflicting or redundant options
+ERROR: option "freeze" specified more than once
LINE 1: COPY x from stdin (freeze off, freeze on);
^
COPY x from stdin (delimiter ',', delimiter ',');
-ERROR: conflicting or redundant options
+ERROR: option "delimiter" specified more than once
LINE 1: COPY x from stdin (delimiter ',', delimiter ',');
^
COPY x from stdin (null ' ', null ' ');
-ERROR: conflicting or redundant options
+ERROR: option "null" specified more than once
LINE 1: COPY x from stdin (null ' ', null ' ');
^
COPY x from stdin (header off, header on);
-ERROR: conflicting or redundant options
+ERROR: option "header" specified more than once
LINE 1: COPY x from stdin (header off, header on);
^
COPY x from stdin (quote ':', quote ':');
-ERROR: conflicting or redundant options
+ERROR: option "quote" specified more than once
LINE 1: COPY x from stdin (quote ':', quote ':');
^
COPY x from stdin (escape ':', escape ':');
-ERROR: conflicting or redundant options
+ERROR: option "escape" specified more than once
LINE 1: COPY x from stdin (escape ':', escape ':');
^
COPY x from stdin (force_quote (a), force_quote *);
@@ -62,17 +62,19 @@ ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (force_quote (a), force_quote *);
^
COPY x from stdin (force_not_null (a), force_not_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_not_null" specified more than once
LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
COPY x from stdin (force_null (a), force_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_null" specified more than once
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
-ERROR: conflicting or redundant options
+ERROR: option "convert_selectively" specified more than once
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
^
COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
-ERROR: conflicting or redundant options
+ERROR: option "encoding" specified more than once
LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
^
-- too many columns in column list: should fail
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 5385f98a0f..0cdab88eed 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -94,7 +94,7 @@ CREATE FUNCTION invalid_fdw_handler() RETURNS int LANGUAGE SQL AS 'SELECT 1;';
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -200,7 +200,7 @@ ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo;
ALTER FOREIGN DATA WRAPPER foo HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 63d6ab7a4e..7887dada21 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -26,7 +26,7 @@ ERROR: unrecognized publication parameter: "foo"
CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
-ERROR: conflicting or redundant options
+ERROR: option "publish_via_partition_root" specified more than once
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
--
2.25.1
On Thu, Apr 29, 2021 at 10:44 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2021-Apr-29, vignesh C wrote:
Thanks for the comments, please find the attached v3 patch which has
the change for the first part.Looks good to me. I would only add parser_errposition() to the few
error sites missing that.
I have not included parser_errposition as ParseState was not available
for these errors.
Thoughts?
Regards,
Vignesh
On Sat, May 1, 2021 at 7:25 PM vignesh C <vignesh21@gmail.com> wrote:
I'm not attaching above one line change as a patch, maybe Vignesh can
merge this into the main patch.Thanks for the comments. I have merged the change into the attached patch.
Thoughts?
Thanks! v4 basically LGTM. Can we park this in the current commitfest
if not done already?
Upon looking at the number of places where we have the "option \"%s\"
specified more than once" error, I, now strongly feel that we should
use goto duplicate_error approach like in compute_common_attribute, so
that we will have only one ereport(ERROR. We can change it in
following files: copy.c, dbcommands.c, extension.c,
compute_function_attributes, sequence.c, subscriptioncmds.c,
typecmds.c, user.c, walsender.c, pgoutput.c. This will reduce the LOC
greatly.
Thoughts?
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
On 2021-May-01, vignesh C wrote:
On Thu, Apr 29, 2021 at 10:44 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2021-Apr-29, vignesh C wrote:
Thanks for the comments, please find the attached v3 patch which has
the change for the first part.Looks good to me. I would only add parser_errposition() to the few
error sites missing that.I have not included parser_errposition as ParseState was not available
for these errors.
Yeah, it's tough to do that in a few of those such as validator
functions, and I don't think we'd want to do that. However there are
some cases where we can easily add the parsestate as an argument -- for
example CreatePublication can get it in ProcessUtilitySlow and pass it
down to parse_publication_options; likewise for ExecuteDoStmt. I didn't
check other places.
--
�lvaro Herrera 39�49'30"S 73�17'W
On Sat, May 1, 2021, 10:54 PM Alvaro Herrera <alvherre@alvh.no-ip.org>
wrote:
On 2021-May-01, vignesh C wrote:
On Thu, Apr 29, 2021 at 10:44 PM Alvaro Herrera <alvherre@alvh.no-ip.org>
wrote:On 2021-Apr-29, vignesh C wrote:
Thanks for the comments, please find the attached v3 patch which has
the change for the first part.Looks good to me. I would only add parser_errposition() to the few
error sites missing that.I have not included parser_errposition as ParseState was not available
for these errors.Yeah, it's tough to do that in a few of those such as validator
functions, and I don't think we'd want to do that. However there are
some cases where we can easily add the parsestate as an argument -- for
example CreatePublication can get it in ProcessUtilitySlow and pass it
down to parse_publication_options; likewise for ExecuteDoStmt. I didn't
check other places.
IMO, it's not good to change the function API just for showing up
parse_position (which is there for cosmetic reasons I feel) in an error
which actually has the option name clearly mentioned in the error message.
Best Regards,
Bharath Rupireddy.
EnterpriseDB.
Show quoted text
On 2021-May-01, Bharath Rupireddy wrote:
IMO, it's not good to change the function API just for showing up
parse_position (which is there for cosmetic reasons I feel) in an error
which actually has the option name clearly mentioned in the error message.
Why not? We've done it before, I'm sure you can find examples in the
git log. The function API is not that critical -- these functions are
mostly only called from ProcessUtility and friends.
--
�lvaro Herrera 39�49'30"S 73�17'W
On Sun, May 2, 2021 at 4:27 AM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2021-May-01, Bharath Rupireddy wrote:
IMO, it's not good to change the function API just for showing up
parse_position (which is there for cosmetic reasons I feel) in an error
which actually has the option name clearly mentioned in the error message.Why not? We've done it before, I'm sure you can find examples in the
git log. The function API is not that critical -- these functions are
mostly only called from ProcessUtility and friends.
I feel it is better to include it wherever possible.
Regards,
Vignesh
Le dim. 2 mai 2021 à 18:31, vignesh C <vignesh21@gmail.com> a écrit :
On Sun, May 2, 2021 at 4:27 AM Alvaro Herrera <alvherre@alvh.no-ip.org>
wrote:On 2021-May-01, Bharath Rupireddy wrote:
IMO, it's not good to change the function API just for showing up
parse_position (which is there for cosmetic reasons I feel) in an error
which actually has the option name clearly mentioned in the errormessage.
Why not? We've done it before, I'm sure you can find examples in the
git log. The function API is not that critical -- these functions are
mostly only called from ProcessUtility and friends.I feel it is better to include it wherever possible.
+1
Show quoted text
On Sat, May 1, 2021 at 10:54 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2021-May-01, vignesh C wrote:
On Thu, Apr 29, 2021 at 10:44 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2021-Apr-29, vignesh C wrote:
Thanks for the comments, please find the attached v3 patch which has
the change for the first part.Looks good to me. I would only add parser_errposition() to the few
error sites missing that.I have not included parser_errposition as ParseState was not available
for these errors.Yeah, it's tough to do that in a few of those such as validator
functions, and I don't think we'd want to do that. However there are
some cases where we can easily add the parsestate as an argument -- for
example CreatePublication can get it in ProcessUtilitySlow and pass it
down to parse_publication_options; likewise for ExecuteDoStmt. I didn't
check other places.
Thanks for the comments. I have changed in most of the places except
for a few places like plugin functions, internal commands and changes
that required changing more levels of function callers. Attached patch
has the changes for the same.
Thoughts?
Regards,
Vignesh
Attachments:
v5-0001-Enhance-error-message.patchtext/x-patch; charset=US-ASCII; name=v5-0001-Enhance-error-message.patchDownload
From 7c56cea92947b82107e2298f6d48d934df6fd7d8 Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Mon, 26 Apr 2021 18:40:36 +0530
Subject: [PATCH v5] Enhance error message.
Enhanced error message, so that the user can easily identify the error.
---
contrib/file_fdw/file_fdw.c | 20 +--
src/backend/catalog/aclchk.c | 22 ++--
src/backend/commands/copy.c | 66 ++++------
src/backend/commands/dbcommands.c | 90 +++++---------
src/backend/commands/extension.c | 27 ++--
src/backend/commands/foreigncmds.c | 30 +++--
src/backend/commands/functioncmds.c | 55 ++++----
src/backend/commands/publicationcmds.c | 39 +++---
src/backend/commands/sequence.c | 57 +++------
src/backend/commands/subscriptioncmds.c | 75 +++++------
src/backend/commands/tablecmds.c | 2 +-
src/backend/commands/typecmds.c | 38 +++---
src/backend/commands/user.c | 131 +++++++-------------
src/backend/parser/parse_utilcmd.c | 2 +-
src/backend/replication/pgoutput/pgoutput.c | 31 +++--
src/backend/replication/walsender.c | 23 ++--
src/backend/tcop/utility.c | 20 +--
src/include/commands/defrem.h | 6 +-
src/include/commands/publicationcmds.h | 4 +-
src/include/commands/subscriptioncmds.h | 4 +-
src/include/commands/typecmds.h | 2 +-
src/include/commands/user.h | 2 +-
src/test/regress/expected/copy2.out | 24 ++--
src/test/regress/expected/foreign_data.out | 8 +-
src/test/regress/expected/publication.out | 4 +-
25 files changed, 352 insertions(+), 430 deletions(-)
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 2c2f149fb0..f857d5af97 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -200,6 +200,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
char *filename = NULL;
DefElem *force_not_null = NULL;
DefElem *force_null = NULL;
+ DefElem *def;
List *other_options = NIL;
ListCell *cell;
@@ -209,7 +210,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
*/
foreach(cell, options_list)
{
- DefElem *def = (DefElem *) lfirst(cell);
+ def = (DefElem *) lfirst(cell);
if (!is_valid_option(def->defname, catalog))
{
@@ -290,10 +291,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_not_null") == 0)
{
if (force_not_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_not_null\" supplied more than once for a column.")));
+ goto duplicate_error;
force_not_null = def;
/* Don't care what the value is, as long as it's a legal boolean */
(void) defGetBoolean(def);
@@ -302,10 +300,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_null") == 0)
{
if (force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_null\" supplied more than once for a column.")));
+ goto duplicate_error;
force_null = def;
(void) defGetBoolean(def);
}
@@ -328,6 +323,13 @@ file_fdw_validator(PG_FUNCTION_ARGS)
errmsg("either filename or program is required for file_fdw foreign tables")));
PG_RETURN_VOID();
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", def->defname)));
+ PG_RETURN_VOID(); /* keep compiler quiet */
+
}
/*
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index e1573eb398..be38488934 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -910,30 +910,25 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
List *nspnames = NIL;
DefElem *drolespecs = NULL;
DefElem *dnspnames = NULL;
+ DefElem *defel;
AclMode all_privileges;
const char *errormsg;
/* Deconstruct the "options" part of the statement */
foreach(cell, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(cell);
+ defel = (DefElem *) lfirst(cell);
if (strcmp(defel->defname, "schemas") == 0)
{
if (dnspnames)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dnspnames = defel;
}
else if (strcmp(defel->defname, "roles") == 0)
{
if (drolespecs)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
drolespecs = defel;
}
else
@@ -1087,6 +1082,15 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
SetDefaultACLsInSchemas(&iacls, nspnames);
}
}
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return; /* keep compiler quiet */
}
/*
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 8265b981eb..77fd923f2a 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -340,6 +340,7 @@ ProcessCopyOptions(ParseState *pstate,
bool freeze_specified = false;
bool header_specified = false;
ListCell *option;
+ DefElem *defel;
/* Support external use for option sanity checking */
if (opts_out == NULL)
@@ -350,17 +351,14 @@ ProcessCopyOptions(ParseState *pstate,
/* Extract options from the statement node tree */
foreach(option, options)
{
- DefElem *defel = lfirst_node(DefElem, option);
+ defel = lfirst_node(DefElem, option);
if (strcmp(defel->defname, "format") == 0)
{
char *fmt = defGetString(defel);
if (format_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
format_specified = true;
if (strcmp(fmt, "text") == 0)
/* default format */ ;
@@ -377,57 +375,39 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "freeze") == 0)
{
if (freeze_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
freeze_specified = true;
opts_out->freeze = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "delimiter") == 0)
{
if (opts_out->delim)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
opts_out->delim = defGetString(defel);
}
else if (strcmp(defel->defname, "null") == 0)
{
if (opts_out->null_print)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
opts_out->null_print = defGetString(defel);
}
else if (strcmp(defel->defname, "header") == 0)
{
if (header_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
header_specified = true;
opts_out->header_line = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "quote") == 0)
{
if (opts_out->quote)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
opts_out->quote = defGetString(defel);
}
else if (strcmp(defel->defname, "escape") == 0)
{
if (opts_out->escape)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
opts_out->escape = defGetString(defel);
}
else if (strcmp(defel->defname, "force_quote") == 0)
@@ -451,10 +431,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_not_null") == 0)
{
if (opts_out->force_notnull)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
if (defel->arg && IsA(defel->arg, List))
opts_out->force_notnull = castNode(List, defel->arg);
else
@@ -467,9 +444,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_null") == 0)
{
if (opts_out->force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
@@ -487,10 +462,7 @@ ProcessCopyOptions(ParseState *pstate,
* allowed for the column list to be NIL.
*/
if (opts_out->convert_selectively)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
opts_out->convert_selectively = true;
if (defel->arg == NULL || IsA(defel->arg, List))
opts_out->convert_select = castNode(List, defel->arg);
@@ -504,10 +476,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "encoding") == 0)
{
if (opts_out->file_encoding >= 0)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
if (opts_out->file_encoding < 0)
ereport(ERROR,
@@ -666,6 +635,15 @@ ProcessCopyOptions(ParseState *pstate,
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("CSV quote character must not appear in the NULL specification")));
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return; /* keep compiler quiet */
}
/*
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 2b159b60eb..8ad61a219e 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -143,100 +143,71 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
int notherbackends;
int npreparedxacts;
createdb_failure_params fparms;
+ DefElem *defel;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespacename)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dtablespacename = defel;
}
else if (strcmp(defel->defname, "owner") == 0)
{
if (downer)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
downer = defel;
}
else if (strcmp(defel->defname, "template") == 0)
{
if (dtemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dtemplate = defel;
}
else if (strcmp(defel->defname, "encoding") == 0)
{
if (dencoding)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dencoding = defel;
}
else if (strcmp(defel->defname, "locale") == 0)
{
if (dlocale)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dlocale = defel;
}
else if (strcmp(defel->defname, "lc_collate") == 0)
{
if (dcollate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dcollate = defel;
}
else if (strcmp(defel->defname, "lc_ctype") == 0)
{
if (dctype)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dctype = defel;
}
else if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dconnlimit = defel;
}
else if (strcmp(defel->defname, "location") == 0)
@@ -727,6 +698,13 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
PointerGetDatum(&fparms));
return dboid;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return InvalidOid; /* keep compiler quiet */
}
/*
@@ -1488,46 +1466,35 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
Datum new_record[Natts_pg_database];
bool new_record_nulls[Natts_pg_database];
bool new_record_repl[Natts_pg_database];
+ DefElem *defel;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dconnlimit = defel;
}
else if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespace)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dtablespace = defel;
}
else
@@ -1640,6 +1607,13 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
table_close(rel, NoLock);
return dboid;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return InvalidOid; /* keep compiler quiet */
}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 19db329fe6..0a462c1caa 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1682,6 +1682,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
DefElem *d_schema = NULL;
DefElem *d_new_version = NULL;
DefElem *d_cascade = NULL;
+ DefElem *defel;
char *schemaName = NULL;
char *versionName = NULL;
bool cascade = false;
@@ -1725,35 +1726,26 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
/* Deconstruct the statement option list */
foreach(lc, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "schema") == 0)
{
if (d_schema)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
d_schema = defel;
schemaName = defGetString(d_schema);
}
else if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
d_new_version = defel;
versionName = defGetString(d_new_version);
}
else if (strcmp(defel->defname, "cascade") == 0)
{
if (d_cascade)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
d_cascade = defel;
cascade = defGetBoolean(d_cascade);
}
@@ -1768,6 +1760,13 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
cascade,
NIL,
true);
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return InvalidObjectAddress; /* keep compiler quiet */
}
/*
@@ -3052,7 +3051,7 @@ ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
if (d_new_version)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_new_version = defel;
}
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index eb7103fd3b..8923093db9 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -515,11 +515,12 @@ lookup_fdw_validator_func(DefElem *validator)
* Process function options of CREATE/ALTER FDW
*/
static void
-parse_func_options(List *func_options,
+parse_func_options(ParseState *pstate, List *func_options,
bool *handler_given, Oid *fdwhandler,
bool *validator_given, Oid *fdwvalidator)
{
ListCell *cell;
+ DefElem *def;
*handler_given = false;
*validator_given = false;
@@ -529,23 +530,19 @@ parse_func_options(List *func_options,
foreach(cell, func_options)
{
- DefElem *def = (DefElem *) lfirst(cell);
+ def = (DefElem *) lfirst(cell);
if (strcmp(def->defname, "handler") == 0)
{
if (*handler_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
else if (strcmp(def->defname, "validator") == 0)
{
if (*validator_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
@@ -553,13 +550,22 @@ parse_func_options(List *func_options,
elog(ERROR, "option \"%s\" not recognized",
def->defname);
}
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", def->defname),
+ parser_errposition(pstate, def->location)));
+ return; /* keep compiler quiet */
}
/*
* Create a foreign-data wrapper
*/
ObjectAddress
-CreateForeignDataWrapper(CreateFdwStmt *stmt)
+CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt)
{
Relation rel;
Datum values[Natts_pg_foreign_data_wrapper];
@@ -611,7 +617,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
/* Lookup handler and validator functions, if given */
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
@@ -675,7 +681,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
* Alter foreign-data wrapper
*/
ObjectAddress
-AlterForeignDataWrapper(AlterFdwStmt *stmt)
+AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt)
{
Relation rel;
HeapTuple tp;
@@ -717,7 +723,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
memset(repl_null, false, sizeof(repl_null));
memset(repl_repl, false, sizeof(repl_repl));
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9548287217..1a8d23d4c6 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -575,7 +575,7 @@ compute_common_attribute(ParseState *pstate,
duplicate_error:
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
return false; /* keep compiler quiet */
@@ -731,45 +731,34 @@ compute_function_attributes(ParseState *pstate,
DefElem *rows_item = NULL;
DefElem *support_item = NULL;
DefElem *parallel_item = NULL;
+ DefElem *defel;
foreach(option, options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
language_item = defel;
}
else if (strcmp(defel->defname, "transform") == 0)
{
if (transform_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
transform_item = defel;
}
else if (strcmp(defel->defname, "window") == 0)
{
if (windowfunc_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
if (is_procedure)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -836,6 +825,15 @@ compute_function_attributes(ParseState *pstate,
*prosupport = interpret_func_support(support_item);
if (parallel_item)
*parallel_p = interpret_func_parallel(parallel_item);
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return; /* keep compiler quiet */
}
@@ -2044,12 +2042,13 @@ IsThereFunctionInNamespace(const char *proname, int pronargs,
* See at ExecuteCallStmt() about the atomic argument.
*/
void
-ExecuteDoStmt(DoStmt *stmt, bool atomic)
+ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
{
InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
ListCell *arg;
DefElem *as_item = NULL;
DefElem *language_item = NULL;
+ DefElem *defel;
char *language;
Oid laninline;
HeapTuple languageTuple;
@@ -2058,22 +2057,18 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
/* Process options we got from gram.y */
foreach(arg, stmt->args)
{
- DefElem *defel = (DefElem *) lfirst(arg);
+ defel = (DefElem *) lfirst(arg);
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
language_item = defel;
}
else
@@ -2139,6 +2134,14 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
/* execute the inline handler */
OidFunctionCall1(laninline, PointerGetDatum(codeblock));
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return; /* keep compiler quiet */
}
/*
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 95c253c8e0..3c58548fca 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -55,13 +55,15 @@ static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
static void
-parse_publication_options(List *options,
+parse_publication_options(ParseState *pstate,
+ List *options,
bool *publish_given,
PublicationActions *pubactions,
bool *publish_via_partition_root_given,
bool *publish_via_partition_root)
{
ListCell *lc;
+ DefElem *defel;
*publish_given = false;
*publish_via_partition_root_given = false;
@@ -76,7 +78,7 @@ parse_publication_options(List *options,
/* Parse options */
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "publish") == 0)
{
@@ -85,9 +87,7 @@ parse_publication_options(List *options,
ListCell *lc;
if (*publish_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
/*
* If publish option was given only the explicitly listed actions
@@ -128,9 +128,7 @@ parse_publication_options(List *options,
else if (strcmp(defel->defname, "publish_via_partition_root") == 0)
{
if (*publish_via_partition_root_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
@@ -139,13 +137,22 @@ parse_publication_options(List *options,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("unrecognized publication parameter: \"%s\"", defel->defname)));
}
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return; /* keep compiler quiet */
}
/*
* Create new publication.
*/
ObjectAddress
-CreatePublication(CreatePublicationStmt *stmt)
+CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
{
Relation rel;
ObjectAddress myself;
@@ -192,7 +199,8 @@ CreatePublication(CreatePublicationStmt *stmt)
DirectFunctionCall1(namein, CStringGetDatum(stmt->pubname));
values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId());
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -256,8 +264,8 @@ CreatePublication(CreatePublicationStmt *stmt)
* Change options of a publication.
*/
static void
-AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
- HeapTuple tup)
+AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
+ Relation rel, HeapTuple tup)
{
bool nulls[Natts_pg_publication];
bool replaces[Natts_pg_publication];
@@ -269,7 +277,8 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
ObjectAddress obj;
Form_pg_publication pubform;
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -434,7 +443,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
* AlterPublicationTables.
*/
void
-AlterPublication(AlterPublicationStmt *stmt)
+AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
{
Relation rel;
HeapTuple tup;
@@ -459,7 +468,7 @@ AlterPublication(AlterPublicationStmt *stmt)
stmt->pubname);
if (stmt->options)
- AlterPublicationOptions(stmt, rel, tup);
+ AlterPublicationOptions(pstate, stmt, rel, tup);
else
AlterPublicationTables(stmt, rel, tup);
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 0415df9ccb..d815f95b11 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1247,6 +1247,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
DefElem *min_value = NULL;
DefElem *cache_value = NULL;
DefElem *is_cycled = NULL;
+ DefElem *defel;
ListCell *option;
bool reset_max_value = false;
bool reset_min_value = false;
@@ -1256,95 +1257,68 @@ init_params(ParseState *pstate, List *options, bool for_identity,
foreach(option, options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "as") == 0)
{
if (as_type)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
as_type = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "increment") == 0)
{
if (increment_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
increment_by = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "start") == 0)
{
if (start_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
start_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "restart") == 0)
{
if (restart_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
restart_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "maxvalue") == 0)
{
if (max_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
max_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "minvalue") == 0)
{
if (min_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
min_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cache") == 0)
{
if (cache_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
cache_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cycle") == 0)
{
if (is_cycled)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
is_cycled = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "owned_by") == 0)
{
if (*owned_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
*owned_by = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "sequence_name") == 0)
@@ -1626,6 +1600,15 @@ init_params(ParseState *pstate, List *options, bool for_identity,
{
seqform->seqcache = 1;
}
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return;
}
/*
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 517c8edd3b..dd6cb75236 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -60,7 +60,8 @@ static void ReportSlotConnectionError(List *rstates, Oid subid, char *slotname,
* accommodate that.
*/
static void
-parse_subscription_options(List *options,
+parse_subscription_options(ParseState *pstate,
+ List *options,
bool *connect,
bool *enabled_given, bool *enabled,
bool *create_slot,
@@ -76,6 +77,7 @@ parse_subscription_options(List *options,
bool create_slot_given = false;
bool copy_data_given = false;
bool refresh_given = false;
+ DefElem *defel;
/* If connect is specified, the others also need to be. */
Assert(!connect || (enabled && create_slot && copy_data));
@@ -114,14 +116,12 @@ parse_subscription_options(List *options,
/* Parse options */
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "connect") == 0 && connect)
{
if (connect_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
connect_given = true;
*connect = defGetBoolean(defel);
@@ -129,9 +129,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "enabled") == 0 && enabled)
{
if (*enabled_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*enabled_given = true;
*enabled = defGetBoolean(defel);
@@ -139,9 +137,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "create_slot") == 0 && create_slot)
{
if (create_slot_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
create_slot_given = true;
*create_slot = defGetBoolean(defel);
@@ -149,9 +145,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "slot_name") == 0 && slot_name)
{
if (*slot_name_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*slot_name_given = true;
*slot_name = defGetString(defel);
@@ -163,9 +157,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "copy_data") == 0 && copy_data)
{
if (copy_data_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
copy_data_given = true;
*copy_data = defGetBoolean(defel);
@@ -174,9 +166,7 @@ parse_subscription_options(List *options,
synchronous_commit)
{
if (*synchronous_commit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*synchronous_commit = defGetString(defel);
@@ -188,9 +178,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "refresh") == 0 && refresh)
{
if (refresh_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
refresh_given = true;
*refresh = defGetBoolean(defel);
@@ -198,9 +186,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "binary") == 0 && binary)
{
if (*binary_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*binary_given = true;
*binary = defGetBoolean(defel);
@@ -208,9 +194,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "streaming") == 0 && streaming)
{
if (*streaming_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*streaming_given = true;
*streaming = defGetBoolean(defel);
@@ -285,6 +269,15 @@ parse_subscription_options(List *options,
errmsg("subscription with %s must also set %s",
"slot_name = NONE", "create_slot = false")));
}
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return; /* keep compiler quiet */
}
/*
@@ -322,7 +315,8 @@ publicationListToArray(List *publist)
* Create new subscription.
*/
ObjectAddress
-CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
+CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -352,7 +346,8 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
*
* Connection and publication should not be specified here.
*/
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
&connect,
&enabled_given, &enabled,
&create_slot,
@@ -750,7 +745,8 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data)
* Alter the existing subscription.
*/
ObjectAddress
-AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
+AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -805,7 +801,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool streaming_given;
bool streaming;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -862,7 +859,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool enabled,
enabled_given;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
&enabled_given, &enabled,
NULL, /* no "create_slot" */
@@ -907,7 +905,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool copy_data;
bool refresh;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -953,7 +952,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
publist = merge_publications(sub->publications, stmt->publication, isadd, stmt->subname);
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -1000,7 +1000,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions")));
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index d9ba87a2a3..26a1f16271 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7524,7 +7524,7 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmod
if (generatedEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 036fa69d17..f4a2678ffe 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -332,7 +332,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
if (*defelp != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
*defelp = defel;
}
@@ -1336,7 +1336,7 @@ checkEnumOwner(HeapTuple tup)
* and users might have queries with that same assumption.
*/
ObjectAddress
-DefineRange(CreateRangeStmt *stmt)
+DefineRange(ParseState *pstate, CreateRangeStmt *stmt)
{
char *typeName;
Oid typeNamespace;
@@ -1366,6 +1366,7 @@ DefineRange(CreateRangeStmt *stmt)
ObjectAddress address;
ObjectAddress mltrngaddress PG_USED_FOR_ASSERTS_ONLY;
Oid castFuncOid;
+ DefElem *defel;
/* Convert list of names to a name and namespace */
typeNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
@@ -1406,55 +1407,43 @@ DefineRange(CreateRangeStmt *stmt)
/* Extract the parameters from the parameter list */
foreach(lc, stmt->params)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "subtype") == 0)
{
if (OidIsValid(rangeSubtype))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
else if (strcmp(defel->defname, "subtype_opclass") == 0)
{
if (rangeSubOpclassName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
{
if (rangeCollationName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
{
if (rangeCanonicalName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
{
if (rangeSubtypeDiffName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
{
if (multirangeTypeName != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
@@ -1726,6 +1715,13 @@ DefineRange(CreateRangeStmt *stmt)
pfree(multirangeArrayName);
return address;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return InvalidObjectAddress; /* keep compiler quiet */
}
/*
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 65bb733958..f1fad6caa1 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -106,6 +106,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
DefElem *dadminmembers = NULL;
DefElem *dvalidUntil = NULL;
DefElem *dbypassRLS = NULL;
+ DefElem *defel;
/* The defaults can vary depending on the original statement type */
switch (stmt->stmt_type)
@@ -123,15 +124,12 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dpassword = defel;
}
else if (strcmp(defel->defname, "sysid") == 0)
@@ -142,109 +140,73 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dconnlimit = defel;
}
else if (strcmp(defel->defname, "addroleto") == 0)
{
if (daddroleto)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
daddroleto = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
drolemembers = defel;
}
else if (strcmp(defel->defname, "adminmembers") == 0)
{
if (dadminmembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dadminmembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dbypassRLS = defel;
}
else
@@ -517,6 +479,13 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
table_close(pg_authid_rel, NoLock);
return roleid;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return InvalidOid; /* keep compiler quiet */
}
@@ -528,7 +497,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
* "ALTER ROLE role ROLE rolenames", we don't document it.
*/
Oid
-AlterRole(AlterRoleStmt *stmt)
+AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
{
Datum new_record[Natts_pg_authid];
bool new_record_nulls[Natts_pg_authid];
@@ -564,6 +533,7 @@ AlterRole(AlterRoleStmt *stmt)
DefElem *drolemembers = NULL;
DefElem *dvalidUntil = NULL;
DefElem *dbypassRLS = NULL;
+ DefElem *defel;
Oid roleid;
check_rolespec_name(stmt->role,
@@ -572,95 +542,73 @@ AlterRole(AlterRoleStmt *stmt)
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
stmt->action != 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dbypassRLS = defel;
}
else
@@ -905,6 +853,13 @@ AlterRole(AlterRoleStmt *stmt)
table_close(pg_authid_rel, NoLock);
return roleid;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return InvalidOid; /* keep compiler quiet */
}
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 9dd30370da..9e44885146 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -402,7 +402,7 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (nameEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index f68348dcf4..9acfc3046b 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -165,6 +165,7 @@ static void
parse_output_parameters(List *options, PGOutputData *data)
{
ListCell *lc;
+ DefElem *defel;
bool protocol_version_given = false;
bool publication_names_given = false;
bool binary_option_given = false;
@@ -177,7 +178,7 @@ parse_output_parameters(List *options, PGOutputData *data)
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
Assert(defel->arg == NULL || IsA(defel->arg, String));
@@ -187,9 +188,7 @@ parse_output_parameters(List *options, PGOutputData *data)
int64 parsed;
if (protocol_version_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -208,9 +207,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "publication_names") == 0)
{
if (publication_names_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -222,9 +219,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "binary") == 0)
{
if (binary_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -232,9 +227,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "messages") == 0)
{
if (messages_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -242,9 +235,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "streaming") == 0)
{
if (streaming_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
streaming_given = true;
data->streaming = defGetBoolean(defel);
@@ -252,6 +243,14 @@ parse_output_parameters(List *options, PGOutputData *data)
else
elog(ERROR, "unrecognized pgoutput option: %s", defel->defname);
}
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname)));
+ return; /* keep compiler quiet */
}
/*
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 6fefc3bedc..1b50cdf8a6 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -871,18 +871,17 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
ListCell *lc;
bool snapshot_action_given = false;
bool reserve_wal_given = false;
+ DefElem *defel;
/* Parse options */
foreach(lc, cmd->options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "export_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
snapshot_action_given = true;
*snapshot_action = defGetBoolean(defel) ? CRS_EXPORT_SNAPSHOT :
@@ -891,9 +890,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else if (strcmp(defel->defname, "use_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
snapshot_action_given = true;
*snapshot_action = CRS_USE_SNAPSHOT;
@@ -901,9 +898,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else if (strcmp(defel->defname, "reserve_wal") == 0)
{
if (reserve_wal_given || cmd->kind != REPLICATION_KIND_PHYSICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
reserve_wal_given = true;
*reserve_wal = true;
@@ -911,6 +906,14 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else
elog(ERROR, "unrecognized option: %s", defel->defname);
}
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname)));
+ return; /* keep compiler quiet */
}
/*
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 16c6f17e23..2668ff26f9 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -693,7 +693,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
break;
case T_DoStmt:
- ExecuteDoStmt((DoStmt *) parsetree, isAtomicContext);
+ ExecuteDoStmt(pstate, (DoStmt *) parsetree, isAtomicContext);
break;
case T_CreateTableSpaceStmt:
@@ -873,7 +873,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
case T_AlterRoleStmt:
/* no event triggers for global objects */
- AlterRole((AlterRoleStmt *) parsetree);
+ AlterRole(pstate, (AlterRoleStmt *) parsetree);
break;
case T_AlterRoleSetStmt:
@@ -1536,11 +1536,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateFdwStmt:
- address = CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
+ address = CreateForeignDataWrapper(pstate, (CreateFdwStmt *) parsetree);
break;
case T_AlterFdwStmt:
- address = AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
+ address = AlterForeignDataWrapper(pstate, (AlterFdwStmt *) parsetree);
break;
case T_CreateForeignServerStmt:
@@ -1585,7 +1585,7 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
- address = DefineRange((CreateRangeStmt *) parsetree);
+ address = DefineRange(pstate, (CreateRangeStmt *) parsetree);
break;
case T_AlterEnumStmt: /* ALTER TYPE (enum) */
@@ -1786,11 +1786,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreatePublicationStmt:
- address = CreatePublication((CreatePublicationStmt *) parsetree);
+ address = CreatePublication(pstate, (CreatePublicationStmt *) parsetree);
break;
case T_AlterPublicationStmt:
- AlterPublication((AlterPublicationStmt *) parsetree);
+ AlterPublication(pstate, (AlterPublicationStmt *) parsetree);
/*
* AlterPublication calls EventTriggerCollectSimpleCommand
@@ -1800,12 +1800,14 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateSubscriptionStmt:
- address = CreateSubscription((CreateSubscriptionStmt *) parsetree,
+ address = CreateSubscription(pstate,
+ (CreateSubscriptionStmt *) parsetree,
isTopLevel);
break;
case T_AlterSubscriptionStmt:
- address = AlterSubscription((AlterSubscriptionStmt *) parsetree,
+ address = AlterSubscription(pstate,
+ (AlterSubscriptionStmt *) parsetree,
isTopLevel);
break;
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 6bce4d76fe..2a317257ea 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -56,7 +56,7 @@ extern ObjectAddress CreateCast(CreateCastStmt *stmt);
extern ObjectAddress CreateTransform(CreateTransformStmt *stmt);
extern void IsThereFunctionInNamespace(const char *proname, int pronargs,
oidvector *proargtypes, Oid nspOid);
-extern void ExecuteDoStmt(DoStmt *stmt, bool atomic);
+extern void ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic);
extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest);
extern TupleDesc CallStmtResultDesc(CallStmt *stmt);
extern Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok);
@@ -121,8 +121,8 @@ extern ObjectAddress AlterForeignServerOwner(const char *name, Oid newOwnerId);
extern void AlterForeignServerOwner_oid(Oid, Oid newOwnerId);
extern ObjectAddress AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId);
extern void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId);
-extern ObjectAddress CreateForeignDataWrapper(CreateFdwStmt *stmt);
-extern ObjectAddress AlterForeignDataWrapper(AlterFdwStmt *stmt);
+extern ObjectAddress CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt);
+extern ObjectAddress AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt);
extern ObjectAddress CreateForeignServer(CreateForeignServerStmt *stmt);
extern ObjectAddress AlterForeignServer(AlterForeignServerStmt *stmt);
extern ObjectAddress CreateUserMapping(CreateUserMappingStmt *stmt);
diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h
index 00e2e626e6..efea01f2a9 100644
--- a/src/include/commands/publicationcmds.h
+++ b/src/include/commands/publicationcmds.h
@@ -18,8 +18,8 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreatePublication(CreatePublicationStmt *stmt);
-extern void AlterPublication(AlterPublicationStmt *stmt);
+extern ObjectAddress CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt);
+extern void AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt);
extern void RemovePublicationRelById(Oid proid);
extern ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/subscriptioncmds.h b/src/include/commands/subscriptioncmds.h
index 3b926f35d7..8bf25ee66c 100644
--- a/src/include/commands/subscriptioncmds.h
+++ b/src/include/commands/subscriptioncmds.h
@@ -18,9 +18,9 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreateSubscription(CreateSubscriptionStmt *stmt,
+extern ObjectAddress CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
bool isTopLevel);
-extern ObjectAddress AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel);
+extern ObjectAddress AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, bool isTopLevel);
extern void DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel);
extern ObjectAddress AlterSubscriptionOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
index 880679127b..d5e22811d0 100644
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -25,7 +25,7 @@ extern ObjectAddress DefineType(ParseState *pstate, List *names, List *parameter
extern void RemoveTypeById(Oid typeOid);
extern ObjectAddress DefineDomain(CreateDomainStmt *stmt);
extern ObjectAddress DefineEnum(CreateEnumStmt *stmt);
-extern ObjectAddress DefineRange(CreateRangeStmt *stmt);
+extern ObjectAddress DefineRange(ParseState *pstate, CreateRangeStmt *stmt);
extern ObjectAddress AlterEnum(AlterEnumStmt *stmt);
extern ObjectAddress DefineCompositeType(RangeVar *typevar, List *coldeflist);
extern Oid AssignTypeArrayOid(void);
diff --git a/src/include/commands/user.h b/src/include/commands/user.h
index 028e0dde56..0b7a3cd65f 100644
--- a/src/include/commands/user.h
+++ b/src/include/commands/user.h
@@ -25,7 +25,7 @@ typedef void (*check_password_hook_type) (const char *username, const char *shad
extern PGDLLIMPORT check_password_hook_type check_password_hook;
extern Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt);
-extern Oid AlterRole(AlterRoleStmt *stmt);
+extern Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt);
extern Oid AlterRoleSet(AlterRoleSetStmt *stmt);
extern void DropRole(DropRoleStmt *stmt);
extern void GrantRole(GrantRoleStmt *stmt);
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c64f0719e7..92fe8a121a 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -30,31 +30,31 @@ COPY x (xyz) from stdin;
ERROR: column "xyz" of relation "x" does not exist
-- redundant options
COPY x from stdin (format CSV, FORMAT CSV);
-ERROR: conflicting or redundant options
+ERROR: option "format" specified more than once
LINE 1: COPY x from stdin (format CSV, FORMAT CSV);
^
COPY x from stdin (freeze off, freeze on);
-ERROR: conflicting or redundant options
+ERROR: option "freeze" specified more than once
LINE 1: COPY x from stdin (freeze off, freeze on);
^
COPY x from stdin (delimiter ',', delimiter ',');
-ERROR: conflicting or redundant options
+ERROR: option "delimiter" specified more than once
LINE 1: COPY x from stdin (delimiter ',', delimiter ',');
^
COPY x from stdin (null ' ', null ' ');
-ERROR: conflicting or redundant options
+ERROR: option "null" specified more than once
LINE 1: COPY x from stdin (null ' ', null ' ');
^
COPY x from stdin (header off, header on);
-ERROR: conflicting or redundant options
+ERROR: option "header" specified more than once
LINE 1: COPY x from stdin (header off, header on);
^
COPY x from stdin (quote ':', quote ':');
-ERROR: conflicting or redundant options
+ERROR: option "quote" specified more than once
LINE 1: COPY x from stdin (quote ':', quote ':');
^
COPY x from stdin (escape ':', escape ':');
-ERROR: conflicting or redundant options
+ERROR: option "escape" specified more than once
LINE 1: COPY x from stdin (escape ':', escape ':');
^
COPY x from stdin (force_quote (a), force_quote *);
@@ -62,17 +62,19 @@ ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (force_quote (a), force_quote *);
^
COPY x from stdin (force_not_null (a), force_not_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_not_null" specified more than once
LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
COPY x from stdin (force_null (a), force_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_null" specified more than once
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
-ERROR: conflicting or redundant options
+ERROR: option "convert_selectively" specified more than once
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
^
COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
-ERROR: conflicting or redundant options
+ERROR: option "encoding" specified more than once
LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
^
-- too many columns in column list: should fail
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 5385f98a0f..03d6eca747 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -94,7 +94,9 @@ CREATE FUNCTION invalid_fdw_handler() RETURNS int LANGUAGE SQL AS 'SELECT 1;';
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...GN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER in...
+ ^
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -200,7 +202,9 @@ ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo;
ALTER FOREIGN DATA WRAPPER foo HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER an...
+ ^
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 63d6ab7a4e..0f5cbe2e99 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -26,7 +26,9 @@ ERROR: unrecognized publication parameter: "foo"
CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
-ERROR: conflicting or redundant options
+ERROR: option "publish_via_partition_root" specified more than once
+LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi...
+ ^
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
--
2.25.1
On Sat, May 1, 2021 at 9:02 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:
On Sat, May 1, 2021 at 7:25 PM vignesh C <vignesh21@gmail.com> wrote:
I'm not attaching above one line change as a patch, maybe Vignesh can
merge this into the main patch.Thanks for the comments. I have merged the change into the attached patch.
Thoughts?Thanks! v4 basically LGTM. Can we park this in the current commitfest
if not done already?Upon looking at the number of places where we have the "option \"%s\"
specified more than once" error, I, now strongly feel that we should
use goto duplicate_error approach like in compute_common_attribute, so
that we will have only one ereport(ERROR. We can change it in
following files: copy.c, dbcommands.c, extension.c,
compute_function_attributes, sequence.c, subscriptioncmds.c,
typecmds.c, user.c, walsender.c, pgoutput.c. This will reduce the LOC
greatly.Thoughts?
I have made the changes for this, I have posted the same in the v5
patch posted in my earlier mail.
Regards,
Vignesh
On Sun, May 2, 2021 at 8:44 PM vignesh C <vignesh21@gmail.com> wrote:
On Sat, May 1, 2021 at 9:02 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Sat, May 1, 2021 at 7:25 PM vignesh C <vignesh21@gmail.com> wrote:
I'm not attaching above one line change as a patch, maybe Vignesh can
merge this into the main patch.Thanks for the comments. I have merged the change into the attached patch.
Thoughts?Thanks! v4 basically LGTM. Can we park this in the current commitfest
if not done already?Upon looking at the number of places where we have the "option \"%s\"
specified more than once" error, I, now strongly feel that we should
use goto duplicate_error approach like in compute_common_attribute, so
that we will have only one ereport(ERROR. We can change it in
following files: copy.c, dbcommands.c, extension.c,
compute_function_attributes, sequence.c, subscriptioncmds.c,
typecmds.c, user.c, walsender.c, pgoutput.c. This will reduce the LOC
greatly.Thoughts?
I have made the changes for this, I have posted the same in the v5
patch posted in my earlier mail.
Thanks! The v5 patch looks good to me. Let's see if all agree on the
goto duplicate_error approach which could reduce the LOC by ~80.
I don't see it in the current commitfest, can we park it there so that
the patch will get tested on cfbot systems?
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
On Mon, May 3, 2021 at 12:08 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:
On Sun, May 2, 2021 at 8:44 PM vignesh C <vignesh21@gmail.com> wrote:
On Sat, May 1, 2021 at 9:02 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Sat, May 1, 2021 at 7:25 PM vignesh C <vignesh21@gmail.com> wrote:
I'm not attaching above one line change as a patch, maybe Vignesh can
merge this into the main patch.Thanks for the comments. I have merged the change into the attached patch.
Thoughts?Thanks! v4 basically LGTM. Can we park this in the current commitfest
if not done already?Upon looking at the number of places where we have the "option \"%s\"
specified more than once" error, I, now strongly feel that we should
use goto duplicate_error approach like in compute_common_attribute, so
that we will have only one ereport(ERROR. We can change it in
following files: copy.c, dbcommands.c, extension.c,
compute_function_attributes, sequence.c, subscriptioncmds.c,
typecmds.c, user.c, walsender.c, pgoutput.c. This will reduce the LOC
greatly.Thoughts?
I have made the changes for this, I have posted the same in the v5
patch posted in my earlier mail.Thanks! The v5 patch looks good to me. Let's see if all agree on the
goto duplicate_error approach which could reduce the LOC by ~80.
I think the "goto duplicate_error" approach looks good, it avoids
duplicating the same error code multiple times.
--
Regards,
Dilip Kumar
EnterpriseDB: http://www.enterprisedb.com
On Mon, May 3, 2021 at 12:08 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:
On Sun, May 2, 2021 at 8:44 PM vignesh C <vignesh21@gmail.com> wrote:
On Sat, May 1, 2021 at 9:02 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Sat, May 1, 2021 at 7:25 PM vignesh C <vignesh21@gmail.com> wrote:
I'm not attaching above one line change as a patch, maybe Vignesh can
merge this into the main patch.Thanks for the comments. I have merged the change into the attached patch.
Thoughts?Thanks! v4 basically LGTM. Can we park this in the current commitfest
if not done already?Upon looking at the number of places where we have the "option \"%s\"
specified more than once" error, I, now strongly feel that we should
use goto duplicate_error approach like in compute_common_attribute, so
that we will have only one ereport(ERROR. We can change it in
following files: copy.c, dbcommands.c, extension.c,
compute_function_attributes, sequence.c, subscriptioncmds.c,
typecmds.c, user.c, walsender.c, pgoutput.c. This will reduce the LOC
greatly.Thoughts?
I have made the changes for this, I have posted the same in the v5
patch posted in my earlier mail.Thanks! The v5 patch looks good to me. Let's see if all agree on the
goto duplicate_error approach which could reduce the LOC by ~80.I don't see it in the current commitfest, can we park it there so that
the patch will get tested on cfbot systems?
I have added an entry in commitfest:
https://commitfest.postgresql.org/33/3103/
Regards,
Vignesh
On Mon, May 3, 2021 at 1:41 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
On Mon, May 3, 2021 at 12:08 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Sun, May 2, 2021 at 8:44 PM vignesh C <vignesh21@gmail.com> wrote:
On Sat, May 1, 2021 at 9:02 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Sat, May 1, 2021 at 7:25 PM vignesh C <vignesh21@gmail.com> wrote:
I'm not attaching above one line change as a patch, maybe Vignesh can
merge this into the main patch.Thanks for the comments. I have merged the change into the attached patch.
Thoughts?Thanks! v4 basically LGTM. Can we park this in the current commitfest
if not done already?Upon looking at the number of places where we have the "option \"%s\"
specified more than once" error, I, now strongly feel that we should
use goto duplicate_error approach like in compute_common_attribute, so
that we will have only one ereport(ERROR. We can change it in
following files: copy.c, dbcommands.c, extension.c,
compute_function_attributes, sequence.c, subscriptioncmds.c,
typecmds.c, user.c, walsender.c, pgoutput.c. This will reduce the LOC
greatly.Thoughts?
I have made the changes for this, I have posted the same in the v5
patch posted in my earlier mail.Thanks! The v5 patch looks good to me. Let's see if all agree on the
goto duplicate_error approach which could reduce the LOC by ~80.I think the "goto duplicate_error" approach looks good, it avoids
duplicating the same error code multiple times.
Thanks. I will mark the v5 patch "ready for committer" if no one has comments.
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
Thanks! The v5 patch looks good to me. Let's see if all agree on the
goto duplicate_error approach which could reduce the LOC by ~80.I think the "goto duplicate_error" approach looks good, it avoids
duplicating the same error code multiple times.Thanks. I will mark the v5 patch "ready for committer" if no one has comments.
Hi,
I looked into the patch and noticed a minor thing.
+ return; /* keep compiler quiet */
}
I think we do not need the comment here.
The compiler seems not require "return" at the end of function
when function's return type is VOID.
In addition, it seems better to remove these "return;" like what
commit "3974c4" did.
Best regards,
houzj
On Sat, May 8, 2021 at 12:01 PM houzj.fnst@fujitsu.com
<houzj.fnst@fujitsu.com> wrote:
Thanks! The v5 patch looks good to me. Let's see if all agree on the
goto duplicate_error approach which could reduce the LOC by ~80.I think the "goto duplicate_error" approach looks good, it avoids
duplicating the same error code multiple times.Thanks. I will mark the v5 patch "ready for committer" if no one has comments.
Hi,
I looked into the patch and noticed a minor thing.
+ return; /* keep compiler quiet */
}I think we do not need the comment here.
The compiler seems not require "return" at the end of function
when function's return type is VOID.In addition, it seems better to remove these "return;" like what
commit "3974c4" did.
It looks like that commit removed the plain return statements for a
void returning functions. I see in the code that there are return
statements that are there right after ereport(ERROR, just to keep the
compiler quiet. Here in this patch also, we have return; statements
after ereport(ERROR, for void returning functions. I'm not sure
removing them would cause some compiler warnings on some platforms
with some other compilers. If we're not sure, I'm okay to keep those
return; statements. Thoughts?
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
On Sat, May 8, 2021 at 2:20 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:
On Sat, May 8, 2021 at 12:01 PM houzj.fnst@fujitsu.com
<houzj.fnst@fujitsu.com> wrote:Thanks! The v5 patch looks good to me. Let's see if all agree on the
goto duplicate_error approach which could reduce the LOC by ~80.I think the "goto duplicate_error" approach looks good, it avoids
duplicating the same error code multiple times.Thanks. I will mark the v5 patch "ready for committer" if no one has comments.
Hi,
I looked into the patch and noticed a minor thing.
+ return; /* keep compiler quiet */
}I think we do not need the comment here.
The compiler seems not require "return" at the end of function
when function's return type is VOID.In addition, it seems better to remove these "return;" like what
commit "3974c4" did.It looks like that commit removed the plain return statements for a
void returning functions. I see in the code that there are return
statements that are there right after ereport(ERROR, just to keep the
compiler quiet. Here in this patch also, we have return; statements
after ereport(ERROR, for void returning functions. I'm not sure
removing them would cause some compiler warnings on some platforms
with some other compilers. If we're not sure, I'm okay to keep those
return; statements. Thoughts?
I felt we could retain the return statement and remove the comments.
If you are ok with that I will modify and post a patch for it.
Thoughts?
Regards,
Vignesh
On Sat, May 8, 2021 at 7:06 PM vignesh C <vignesh21@gmail.com> wrote:
On Sat, May 8, 2021 at 2:20 PM Bharath Rupireddy
<bharath.rupireddyforpostgres@gmail.com> wrote:On Sat, May 8, 2021 at 12:01 PM houzj.fnst@fujitsu.com
<houzj.fnst@fujitsu.com> wrote:Thanks! The v5 patch looks good to me. Let's see if all agree on the
goto duplicate_error approach which could reduce the LOC by ~80.I think the "goto duplicate_error" approach looks good, it avoids
duplicating the same error code multiple times.Thanks. I will mark the v5 patch "ready for committer" if no one has comments.
Hi,
I looked into the patch and noticed a minor thing.
+ return; /* keep compiler quiet */
}I think we do not need the comment here.
The compiler seems not require "return" at the end of function
when function's return type is VOID.In addition, it seems better to remove these "return;" like what
commit "3974c4" did.It looks like that commit removed the plain return statements for a
void returning functions. I see in the code that there are return
statements that are there right after ereport(ERROR, just to keep the
compiler quiet. Here in this patch also, we have return; statements
after ereport(ERROR, for void returning functions. I'm not sure
removing them would cause some compiler warnings on some platforms
with some other compilers. If we're not sure, I'm okay to keep those
return; statements. Thoughts?I felt we could retain the return statement and remove the comments.
If you are ok with that I will modify and post a patch for it.
Thoughts?
I would like to keep it as is i.e. both return statement and /* keep
compiler quiet */ comment. Having said that, it's better to leave it
to the committer on whether to have the return statement at all.
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
Thanks! The v5 patch looks good to me. Let's see if all
agree on the goto duplicate_error approach which could reducethe LOC by ~80.
I think the "goto duplicate_error" approach looks good, it
avoids duplicating the same error code multiple times.Thanks. I will mark the v5 patch "ready for committer" if no one has
comments.
Hi,
I looked into the patch and noticed a minor thing.
+ return; /* keep compiler quiet */
}I think we do not need the comment here.
The compiler seems not require "return" at the end of function
when function's return type is VOID.In addition, it seems better to remove these "return;" like what
commit "3974c4" did.It looks like that commit removed the plain return statements for a
void returning functions. I see in the code that there are return
statements that are there right after ereport(ERROR, just to keep
the compiler quiet. Here in this patch also, we have return;
statements after ereport(ERROR, for void returning functions. I'm
not sure removing them would cause some compiler warnings on some
platforms with some other compilers. If we're not sure, I'm okay to
keep those return; statements. Thoughts?I felt we could retain the return statement and remove the comments.
If you are ok with that I will modify and post a patch for it.
Thoughts?I would like to keep it as is i.e. both return statement and /* keep compiler
quiet */ comment. Having said that, it's better to leave it to the committer on
whether to have the return statement at all.
Yes, it's better to leave it to the committer on whether to have the "return;".
But, I think at least removing "return;" which is at the *end* of the function will not cause any warning.
Such as:
+ return; /* keep compiler quiet */
}
So, I'd vote for at least removing the comment " keep the compiler quiet ".
Best regards,
houzj
On Mon, May 10, 2021 at 6:00 AM houzj.fnst@fujitsu.com
<houzj.fnst@fujitsu.com> wrote:
Thanks! The v5 patch looks good to me. Let's see if all
agree on the goto duplicate_error approach which could reducethe LOC by ~80.
I think the "goto duplicate_error" approach looks good, it
avoids duplicating the same error code multiple times.Thanks. I will mark the v5 patch "ready for committer" if no one has
comments.
Hi,
I looked into the patch and noticed a minor thing.
+ return; /* keep compiler quiet */
}I think we do not need the comment here.
The compiler seems not require "return" at the end of function
when function's return type is VOID.In addition, it seems better to remove these "return;" like what
commit "3974c4" did.It looks like that commit removed the plain return statements for a
void returning functions. I see in the code that there are return
statements that are there right after ereport(ERROR, just to keep
the compiler quiet. Here in this patch also, we have return;
statements after ereport(ERROR, for void returning functions. I'm
not sure removing them would cause some compiler warnings on some
platforms with some other compilers. If we're not sure, I'm okay to
keep those return; statements. Thoughts?I felt we could retain the return statement and remove the comments.
If you are ok with that I will modify and post a patch for it.
Thoughts?I would like to keep it as is i.e. both return statement and /* keep compiler
quiet */ comment. Having said that, it's better to leave it to the committer on
whether to have the return statement at all.Yes, it's better to leave it to the committer on whether to have the "return;".
But, I think at least removing "return;" which is at the *end* of the function will not cause any warning.
Such as:+ return; /* keep compiler quiet */
}So, I'd vote for at least removing the comment " keep the compiler quiet ".
That sounds fine to me, Attached v6 patch which has the changes for the same.
Regards,
Vignesh
Attachments:
v6-0001-Enhance-error-message.patchtext/x-patch; charset=US-ASCII; name=v6-0001-Enhance-error-message.patchDownload
From e4db135ebba067c5ae0a53489acf687e4c6a6f33 Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Mon, 26 Apr 2021 18:40:36 +0530
Subject: [PATCH v6] Enhance error message.
Enhanced error message, so that the user can easily identify the error.
---
contrib/file_fdw/file_fdw.c | 20 +--
src/backend/catalog/aclchk.c | 22 ++--
src/backend/commands/copy.c | 66 ++++------
src/backend/commands/dbcommands.c | 90 +++++---------
src/backend/commands/extension.c | 27 ++--
src/backend/commands/foreigncmds.c | 30 +++--
src/backend/commands/functioncmds.c | 57 +++++----
src/backend/commands/publicationcmds.c | 39 +++---
src/backend/commands/sequence.c | 57 +++------
src/backend/commands/subscriptioncmds.c | 75 +++++------
src/backend/commands/tablecmds.c | 2 +-
src/backend/commands/typecmds.c | 38 +++---
src/backend/commands/user.c | 131 +++++++-------------
src/backend/parser/parse_utilcmd.c | 2 +-
src/backend/replication/pgoutput/pgoutput.c | 31 +++--
src/backend/replication/walsender.c | 23 ++--
src/backend/tcop/utility.c | 20 +--
src/include/commands/defrem.h | 6 +-
src/include/commands/publicationcmds.h | 4 +-
src/include/commands/subscriptioncmds.h | 4 +-
src/include/commands/typecmds.h | 2 +-
src/include/commands/user.h | 2 +-
src/test/regress/expected/copy2.out | 24 ++--
src/test/regress/expected/foreign_data.out | 8 +-
src/test/regress/expected/publication.out | 4 +-
25 files changed, 353 insertions(+), 431 deletions(-)
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 2c2f149fb0..32398c227f 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -200,6 +200,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
char *filename = NULL;
DefElem *force_not_null = NULL;
DefElem *force_null = NULL;
+ DefElem *def;
List *other_options = NIL;
ListCell *cell;
@@ -209,7 +210,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
*/
foreach(cell, options_list)
{
- DefElem *def = (DefElem *) lfirst(cell);
+ def = (DefElem *) lfirst(cell);
if (!is_valid_option(def->defname, catalog))
{
@@ -290,10 +291,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_not_null") == 0)
{
if (force_not_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_not_null\" supplied more than once for a column.")));
+ goto duplicate_error;
force_not_null = def;
/* Don't care what the value is, as long as it's a legal boolean */
(void) defGetBoolean(def);
@@ -302,10 +300,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_null") == 0)
{
if (force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_null\" supplied more than once for a column.")));
+ goto duplicate_error;
force_null = def;
(void) defGetBoolean(def);
}
@@ -328,6 +323,13 @@ file_fdw_validator(PG_FUNCTION_ARGS)
errmsg("either filename or program is required for file_fdw foreign tables")));
PG_RETURN_VOID();
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", def->defname)));
+ PG_RETURN_VOID();
+
}
/*
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index e1573eb398..6ecd99b1bf 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -910,30 +910,25 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
List *nspnames = NIL;
DefElem *drolespecs = NULL;
DefElem *dnspnames = NULL;
+ DefElem *defel;
AclMode all_privileges;
const char *errormsg;
/* Deconstruct the "options" part of the statement */
foreach(cell, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(cell);
+ defel = (DefElem *) lfirst(cell);
if (strcmp(defel->defname, "schemas") == 0)
{
if (dnspnames)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dnspnames = defel;
}
else if (strcmp(defel->defname, "roles") == 0)
{
if (drolespecs)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
drolespecs = defel;
}
else
@@ -1087,6 +1082,15 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
SetDefaultACLsInSchemas(&iacls, nspnames);
}
}
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return;
}
/*
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 8265b981eb..cecb935934 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -340,6 +340,7 @@ ProcessCopyOptions(ParseState *pstate,
bool freeze_specified = false;
bool header_specified = false;
ListCell *option;
+ DefElem *defel;
/* Support external use for option sanity checking */
if (opts_out == NULL)
@@ -350,17 +351,14 @@ ProcessCopyOptions(ParseState *pstate,
/* Extract options from the statement node tree */
foreach(option, options)
{
- DefElem *defel = lfirst_node(DefElem, option);
+ defel = lfirst_node(DefElem, option);
if (strcmp(defel->defname, "format") == 0)
{
char *fmt = defGetString(defel);
if (format_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
format_specified = true;
if (strcmp(fmt, "text") == 0)
/* default format */ ;
@@ -377,57 +375,39 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "freeze") == 0)
{
if (freeze_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
freeze_specified = true;
opts_out->freeze = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "delimiter") == 0)
{
if (opts_out->delim)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
opts_out->delim = defGetString(defel);
}
else if (strcmp(defel->defname, "null") == 0)
{
if (opts_out->null_print)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
opts_out->null_print = defGetString(defel);
}
else if (strcmp(defel->defname, "header") == 0)
{
if (header_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
header_specified = true;
opts_out->header_line = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "quote") == 0)
{
if (opts_out->quote)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
opts_out->quote = defGetString(defel);
}
else if (strcmp(defel->defname, "escape") == 0)
{
if (opts_out->escape)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
opts_out->escape = defGetString(defel);
}
else if (strcmp(defel->defname, "force_quote") == 0)
@@ -451,10 +431,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_not_null") == 0)
{
if (opts_out->force_notnull)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
if (defel->arg && IsA(defel->arg, List))
opts_out->force_notnull = castNode(List, defel->arg);
else
@@ -467,9 +444,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_null") == 0)
{
if (opts_out->force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
@@ -487,10 +462,7 @@ ProcessCopyOptions(ParseState *pstate,
* allowed for the column list to be NIL.
*/
if (opts_out->convert_selectively)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
opts_out->convert_selectively = true;
if (defel->arg == NULL || IsA(defel->arg, List))
opts_out->convert_select = castNode(List, defel->arg);
@@ -504,10 +476,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "encoding") == 0)
{
if (opts_out->file_encoding >= 0)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
if (opts_out->file_encoding < 0)
ereport(ERROR,
@@ -666,6 +635,15 @@ ProcessCopyOptions(ParseState *pstate,
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("CSV quote character must not appear in the NULL specification")));
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return;
}
/*
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 2b159b60eb..6ff9d87a9a 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -143,100 +143,71 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
int notherbackends;
int npreparedxacts;
createdb_failure_params fparms;
+ DefElem *defel;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespacename)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dtablespacename = defel;
}
else if (strcmp(defel->defname, "owner") == 0)
{
if (downer)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
downer = defel;
}
else if (strcmp(defel->defname, "template") == 0)
{
if (dtemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dtemplate = defel;
}
else if (strcmp(defel->defname, "encoding") == 0)
{
if (dencoding)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dencoding = defel;
}
else if (strcmp(defel->defname, "locale") == 0)
{
if (dlocale)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dlocale = defel;
}
else if (strcmp(defel->defname, "lc_collate") == 0)
{
if (dcollate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dcollate = defel;
}
else if (strcmp(defel->defname, "lc_ctype") == 0)
{
if (dctype)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dctype = defel;
}
else if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dconnlimit = defel;
}
else if (strcmp(defel->defname, "location") == 0)
@@ -727,6 +698,13 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
PointerGetDatum(&fparms));
return dboid;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return InvalidOid;
}
/*
@@ -1488,46 +1466,35 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
Datum new_record[Natts_pg_database];
bool new_record_nulls[Natts_pg_database];
bool new_record_repl[Natts_pg_database];
+ DefElem *defel;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dconnlimit = defel;
}
else if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespace)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dtablespace = defel;
}
else
@@ -1640,6 +1607,13 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
table_close(rel, NoLock);
return dboid;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return InvalidOid;
}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 19db329fe6..83c7f9cfdd 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1682,6 +1682,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
DefElem *d_schema = NULL;
DefElem *d_new_version = NULL;
DefElem *d_cascade = NULL;
+ DefElem *defel;
char *schemaName = NULL;
char *versionName = NULL;
bool cascade = false;
@@ -1725,35 +1726,26 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
/* Deconstruct the statement option list */
foreach(lc, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "schema") == 0)
{
if (d_schema)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
d_schema = defel;
schemaName = defGetString(d_schema);
}
else if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
d_new_version = defel;
versionName = defGetString(d_new_version);
}
else if (strcmp(defel->defname, "cascade") == 0)
{
if (d_cascade)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
d_cascade = defel;
cascade = defGetBoolean(d_cascade);
}
@@ -1768,6 +1760,13 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
cascade,
NIL,
true);
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return InvalidObjectAddress;
}
/*
@@ -3052,7 +3051,7 @@ ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
if (d_new_version)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
d_new_version = defel;
}
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index eb7103fd3b..700c33ce23 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -515,11 +515,12 @@ lookup_fdw_validator_func(DefElem *validator)
* Process function options of CREATE/ALTER FDW
*/
static void
-parse_func_options(List *func_options,
+parse_func_options(ParseState *pstate, List *func_options,
bool *handler_given, Oid *fdwhandler,
bool *validator_given, Oid *fdwvalidator)
{
ListCell *cell;
+ DefElem *def;
*handler_given = false;
*validator_given = false;
@@ -529,23 +530,19 @@ parse_func_options(List *func_options,
foreach(cell, func_options)
{
- DefElem *def = (DefElem *) lfirst(cell);
+ def = (DefElem *) lfirst(cell);
if (strcmp(def->defname, "handler") == 0)
{
if (*handler_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
else if (strcmp(def->defname, "validator") == 0)
{
if (*validator_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
@@ -553,13 +550,22 @@ parse_func_options(List *func_options,
elog(ERROR, "option \"%s\" not recognized",
def->defname);
}
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", def->defname),
+ parser_errposition(pstate, def->location)));
+ return;
}
/*
* Create a foreign-data wrapper
*/
ObjectAddress
-CreateForeignDataWrapper(CreateFdwStmt *stmt)
+CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt)
{
Relation rel;
Datum values[Natts_pg_foreign_data_wrapper];
@@ -611,7 +617,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
/* Lookup handler and validator functions, if given */
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
@@ -675,7 +681,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
* Alter foreign-data wrapper
*/
ObjectAddress
-AlterForeignDataWrapper(AlterFdwStmt *stmt)
+AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt)
{
Relation rel;
HeapTuple tp;
@@ -717,7 +723,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
memset(repl_null, false, sizeof(repl_null));
memset(repl_repl, false, sizeof(repl_repl));
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9548287217..115dad54b5 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -575,9 +575,9 @@ compute_common_attribute(ParseState *pstate,
duplicate_error:
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
- return false; /* keep compiler quiet */
+ return false;
procedure_error:
ereport(ERROR,
@@ -731,45 +731,34 @@ compute_function_attributes(ParseState *pstate,
DefElem *rows_item = NULL;
DefElem *support_item = NULL;
DefElem *parallel_item = NULL;
+ DefElem *defel;
foreach(option, options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
language_item = defel;
}
else if (strcmp(defel->defname, "transform") == 0)
{
if (transform_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
transform_item = defel;
}
else if (strcmp(defel->defname, "window") == 0)
{
if (windowfunc_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
if (is_procedure)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -836,6 +825,15 @@ compute_function_attributes(ParseState *pstate,
*prosupport = interpret_func_support(support_item);
if (parallel_item)
*parallel_p = interpret_func_parallel(parallel_item);
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return;
}
@@ -2044,12 +2042,13 @@ IsThereFunctionInNamespace(const char *proname, int pronargs,
* See at ExecuteCallStmt() about the atomic argument.
*/
void
-ExecuteDoStmt(DoStmt *stmt, bool atomic)
+ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
{
InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
ListCell *arg;
DefElem *as_item = NULL;
DefElem *language_item = NULL;
+ DefElem *defel;
char *language;
Oid laninline;
HeapTuple languageTuple;
@@ -2058,22 +2057,18 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
/* Process options we got from gram.y */
foreach(arg, stmt->args)
{
- DefElem *defel = (DefElem *) lfirst(arg);
+ defel = (DefElem *) lfirst(arg);
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
language_item = defel;
}
else
@@ -2139,6 +2134,14 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
/* execute the inline handler */
OidFunctionCall1(laninline, PointerGetDatum(codeblock));
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return;
}
/*
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 95c253c8e0..80e7720813 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -55,13 +55,15 @@ static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
static void
-parse_publication_options(List *options,
+parse_publication_options(ParseState *pstate,
+ List *options,
bool *publish_given,
PublicationActions *pubactions,
bool *publish_via_partition_root_given,
bool *publish_via_partition_root)
{
ListCell *lc;
+ DefElem *defel;
*publish_given = false;
*publish_via_partition_root_given = false;
@@ -76,7 +78,7 @@ parse_publication_options(List *options,
/* Parse options */
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "publish") == 0)
{
@@ -85,9 +87,7 @@ parse_publication_options(List *options,
ListCell *lc;
if (*publish_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
/*
* If publish option was given only the explicitly listed actions
@@ -128,9 +128,7 @@ parse_publication_options(List *options,
else if (strcmp(defel->defname, "publish_via_partition_root") == 0)
{
if (*publish_via_partition_root_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
@@ -139,13 +137,22 @@ parse_publication_options(List *options,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("unrecognized publication parameter: \"%s\"", defel->defname)));
}
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return;
}
/*
* Create new publication.
*/
ObjectAddress
-CreatePublication(CreatePublicationStmt *stmt)
+CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
{
Relation rel;
ObjectAddress myself;
@@ -192,7 +199,8 @@ CreatePublication(CreatePublicationStmt *stmt)
DirectFunctionCall1(namein, CStringGetDatum(stmt->pubname));
values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId());
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -256,8 +264,8 @@ CreatePublication(CreatePublicationStmt *stmt)
* Change options of a publication.
*/
static void
-AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
- HeapTuple tup)
+AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
+ Relation rel, HeapTuple tup)
{
bool nulls[Natts_pg_publication];
bool replaces[Natts_pg_publication];
@@ -269,7 +277,8 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
ObjectAddress obj;
Form_pg_publication pubform;
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -434,7 +443,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
* AlterPublicationTables.
*/
void
-AlterPublication(AlterPublicationStmt *stmt)
+AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
{
Relation rel;
HeapTuple tup;
@@ -459,7 +468,7 @@ AlterPublication(AlterPublicationStmt *stmt)
stmt->pubname);
if (stmt->options)
- AlterPublicationOptions(stmt, rel, tup);
+ AlterPublicationOptions(pstate, stmt, rel, tup);
else
AlterPublicationTables(stmt, rel, tup);
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 0415df9ccb..d815f95b11 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1247,6 +1247,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
DefElem *min_value = NULL;
DefElem *cache_value = NULL;
DefElem *is_cycled = NULL;
+ DefElem *defel;
ListCell *option;
bool reset_max_value = false;
bool reset_min_value = false;
@@ -1256,95 +1257,68 @@ init_params(ParseState *pstate, List *options, bool for_identity,
foreach(option, options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "as") == 0)
{
if (as_type)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
as_type = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "increment") == 0)
{
if (increment_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
increment_by = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "start") == 0)
{
if (start_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
start_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "restart") == 0)
{
if (restart_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
restart_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "maxvalue") == 0)
{
if (max_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
max_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "minvalue") == 0)
{
if (min_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
min_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cache") == 0)
{
if (cache_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
cache_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cycle") == 0)
{
if (is_cycled)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
is_cycled = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "owned_by") == 0)
{
if (*owned_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
*owned_by = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "sequence_name") == 0)
@@ -1626,6 +1600,15 @@ init_params(ParseState *pstate, List *options, bool for_identity,
{
seqform->seqcache = 1;
}
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return;
}
/*
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index bbb2f5d029..f0cfaafa8a 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -60,7 +60,8 @@ static void ReportSlotConnectionError(List *rstates, Oid subid, char *slotname,
* accommodate that.
*/
static void
-parse_subscription_options(List *options,
+parse_subscription_options(ParseState *pstate,
+ List *options,
bool *connect,
bool *enabled_given, bool *enabled,
bool *create_slot,
@@ -76,6 +77,7 @@ parse_subscription_options(List *options,
bool create_slot_given = false;
bool copy_data_given = false;
bool refresh_given = false;
+ DefElem *defel;
/* If connect is specified, the others also need to be. */
Assert(!connect || (enabled && create_slot && copy_data));
@@ -114,14 +116,12 @@ parse_subscription_options(List *options,
/* Parse options */
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "connect") == 0 && connect)
{
if (connect_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
connect_given = true;
*connect = defGetBoolean(defel);
@@ -129,9 +129,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "enabled") == 0 && enabled)
{
if (*enabled_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*enabled_given = true;
*enabled = defGetBoolean(defel);
@@ -139,9 +137,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "create_slot") == 0 && create_slot)
{
if (create_slot_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
create_slot_given = true;
*create_slot = defGetBoolean(defel);
@@ -149,9 +145,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "slot_name") == 0 && slot_name)
{
if (*slot_name_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*slot_name_given = true;
*slot_name = defGetString(defel);
@@ -163,9 +157,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "copy_data") == 0 && copy_data)
{
if (copy_data_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
copy_data_given = true;
*copy_data = defGetBoolean(defel);
@@ -174,9 +166,7 @@ parse_subscription_options(List *options,
synchronous_commit)
{
if (*synchronous_commit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*synchronous_commit = defGetString(defel);
@@ -188,9 +178,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "refresh") == 0 && refresh)
{
if (refresh_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
refresh_given = true;
*refresh = defGetBoolean(defel);
@@ -198,9 +186,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "binary") == 0 && binary)
{
if (*binary_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*binary_given = true;
*binary = defGetBoolean(defel);
@@ -208,9 +194,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "streaming") == 0 && streaming)
{
if (*streaming_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
*streaming_given = true;
*streaming = defGetBoolean(defel);
@@ -285,6 +269,15 @@ parse_subscription_options(List *options,
errmsg("subscription with %s must also set %s",
"slot_name = NONE", "create_slot = false")));
}
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return;
}
/*
@@ -322,7 +315,8 @@ publicationListToArray(List *publist)
* Create new subscription.
*/
ObjectAddress
-CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
+CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -352,7 +346,8 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
*
* Connection and publication should not be specified here.
*/
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
&connect,
&enabled_given, &enabled,
&create_slot,
@@ -750,7 +745,8 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data)
* Alter the existing subscription.
*/
ObjectAddress
-AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
+AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -805,7 +801,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool streaming_given;
bool streaming;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -862,7 +859,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool enabled,
enabled_given;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
&enabled_given, &enabled,
NULL, /* no "create_slot" */
@@ -907,7 +905,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool copy_data;
bool refresh;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -953,7 +952,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
publist = merge_publications(sub->publications, stmt->publication, isadd, stmt->subname);
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -1000,7 +1000,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions")));
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 591bf01189..4feaa44fe3 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7511,7 +7511,7 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmod
if (generatedEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 036fa69d17..9297f05cea 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -332,7 +332,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
if (*defelp != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
+ errmsg("option \"%s\" specified more than once", defel->defname),
parser_errposition(pstate, defel->location)));
*defelp = defel;
}
@@ -1336,7 +1336,7 @@ checkEnumOwner(HeapTuple tup)
* and users might have queries with that same assumption.
*/
ObjectAddress
-DefineRange(CreateRangeStmt *stmt)
+DefineRange(ParseState *pstate, CreateRangeStmt *stmt)
{
char *typeName;
Oid typeNamespace;
@@ -1366,6 +1366,7 @@ DefineRange(CreateRangeStmt *stmt)
ObjectAddress address;
ObjectAddress mltrngaddress PG_USED_FOR_ASSERTS_ONLY;
Oid castFuncOid;
+ DefElem *defel;
/* Convert list of names to a name and namespace */
typeNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
@@ -1406,55 +1407,43 @@ DefineRange(CreateRangeStmt *stmt)
/* Extract the parameters from the parameter list */
foreach(lc, stmt->params)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "subtype") == 0)
{
if (OidIsValid(rangeSubtype))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
else if (strcmp(defel->defname, "subtype_opclass") == 0)
{
if (rangeSubOpclassName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
{
if (rangeCollationName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
{
if (rangeCanonicalName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
{
if (rangeSubtypeDiffName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
{
if (multirangeTypeName != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
@@ -1726,6 +1715,13 @@ DefineRange(CreateRangeStmt *stmt)
pfree(multirangeArrayName);
return address;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return InvalidObjectAddress;
}
/*
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 65bb733958..19bf87ddd0 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -106,6 +106,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
DefElem *dadminmembers = NULL;
DefElem *dvalidUntil = NULL;
DefElem *dbypassRLS = NULL;
+ DefElem *defel;
/* The defaults can vary depending on the original statement type */
switch (stmt->stmt_type)
@@ -123,15 +124,12 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dpassword = defel;
}
else if (strcmp(defel->defname, "sysid") == 0)
@@ -142,109 +140,73 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dconnlimit = defel;
}
else if (strcmp(defel->defname, "addroleto") == 0)
{
if (daddroleto)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
daddroleto = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
drolemembers = defel;
}
else if (strcmp(defel->defname, "adminmembers") == 0)
{
if (dadminmembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dadminmembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ goto duplicate_error;
dbypassRLS = defel;
}
else
@@ -517,6 +479,13 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
table_close(pg_authid_rel, NoLock);
return roleid;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return InvalidOid;
}
@@ -528,7 +497,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
* "ALTER ROLE role ROLE rolenames", we don't document it.
*/
Oid
-AlterRole(AlterRoleStmt *stmt)
+AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
{
Datum new_record[Natts_pg_authid];
bool new_record_nulls[Natts_pg_authid];
@@ -564,6 +533,7 @@ AlterRole(AlterRoleStmt *stmt)
DefElem *drolemembers = NULL;
DefElem *dvalidUntil = NULL;
DefElem *dbypassRLS = NULL;
+ DefElem *defel;
Oid roleid;
check_rolespec_name(stmt->role,
@@ -572,95 +542,73 @@ AlterRole(AlterRoleStmt *stmt)
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
stmt->action != 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
dbypassRLS = defel;
}
else
@@ -905,6 +853,13 @@ AlterRole(AlterRoleStmt *stmt)
table_close(pg_authid_rel, NoLock);
return roleid;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+ return InvalidOid;
}
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 48cce4567b..4b01e11da0 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -404,7 +404,7 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (nameEl)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("option \"%s\" specified more than once", defel->defname)));
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index f68348dcf4..b8b1f48206 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -165,6 +165,7 @@ static void
parse_output_parameters(List *options, PGOutputData *data)
{
ListCell *lc;
+ DefElem *defel;
bool protocol_version_given = false;
bool publication_names_given = false;
bool binary_option_given = false;
@@ -177,7 +178,7 @@ parse_output_parameters(List *options, PGOutputData *data)
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
Assert(defel->arg == NULL || IsA(defel->arg, String));
@@ -187,9 +188,7 @@ parse_output_parameters(List *options, PGOutputData *data)
int64 parsed;
if (protocol_version_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -208,9 +207,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "publication_names") == 0)
{
if (publication_names_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -222,9 +219,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "binary") == 0)
{
if (binary_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -232,9 +227,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "messages") == 0)
{
if (messages_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -242,9 +235,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "streaming") == 0)
{
if (streaming_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
streaming_given = true;
data->streaming = defGetBoolean(defel);
@@ -252,6 +243,14 @@ parse_output_parameters(List *options, PGOutputData *data)
else
elog(ERROR, "unrecognized pgoutput option: %s", defel->defname);
}
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname)));
+ return;
}
/*
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 628c8d49d9..c2bb535bcb 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -868,18 +868,17 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
ListCell *lc;
bool snapshot_action_given = false;
bool reserve_wal_given = false;
+ DefElem *defel;
/* Parse options */
foreach(lc, cmd->options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "export_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
snapshot_action_given = true;
*snapshot_action = defGetBoolean(defel) ? CRS_EXPORT_SNAPSHOT :
@@ -888,9 +887,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else if (strcmp(defel->defname, "use_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
snapshot_action_given = true;
*snapshot_action = CRS_USE_SNAPSHOT;
@@ -898,9 +895,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else if (strcmp(defel->defname, "reserve_wal") == 0)
{
if (reserve_wal_given || cmd->kind != REPLICATION_KIND_PHYSICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ goto duplicate_error;
reserve_wal_given = true;
*reserve_wal = true;
@@ -908,6 +903,14 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else
elog(ERROR, "unrecognized option: %s", defel->defname);
}
+
+ return;
+
+duplicate_error:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname)));
+ return;
}
/*
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 1a8fc16773..865c59dfe4 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -693,7 +693,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
break;
case T_DoStmt:
- ExecuteDoStmt((DoStmt *) parsetree, isAtomicContext);
+ ExecuteDoStmt(pstate, (DoStmt *) parsetree, isAtomicContext);
break;
case T_CreateTableSpaceStmt:
@@ -873,7 +873,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
case T_AlterRoleStmt:
/* no event triggers for global objects */
- AlterRole((AlterRoleStmt *) parsetree);
+ AlterRole(pstate, (AlterRoleStmt *) parsetree);
break;
case T_AlterRoleSetStmt:
@@ -1536,11 +1536,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateFdwStmt:
- address = CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
+ address = CreateForeignDataWrapper(pstate, (CreateFdwStmt *) parsetree);
break;
case T_AlterFdwStmt:
- address = AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
+ address = AlterForeignDataWrapper(pstate, (AlterFdwStmt *) parsetree);
break;
case T_CreateForeignServerStmt:
@@ -1585,7 +1585,7 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
- address = DefineRange((CreateRangeStmt *) parsetree);
+ address = DefineRange(pstate, (CreateRangeStmt *) parsetree);
break;
case T_AlterEnumStmt: /* ALTER TYPE (enum) */
@@ -1786,11 +1786,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreatePublicationStmt:
- address = CreatePublication((CreatePublicationStmt *) parsetree);
+ address = CreatePublication(pstate, (CreatePublicationStmt *) parsetree);
break;
case T_AlterPublicationStmt:
- AlterPublication((AlterPublicationStmt *) parsetree);
+ AlterPublication(pstate, (AlterPublicationStmt *) parsetree);
/*
* AlterPublication calls EventTriggerCollectSimpleCommand
@@ -1800,12 +1800,14 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateSubscriptionStmt:
- address = CreateSubscription((CreateSubscriptionStmt *) parsetree,
+ address = CreateSubscription(pstate,
+ (CreateSubscriptionStmt *) parsetree,
isTopLevel);
break;
case T_AlterSubscriptionStmt:
- address = AlterSubscription((AlterSubscriptionStmt *) parsetree,
+ address = AlterSubscription(pstate,
+ (AlterSubscriptionStmt *) parsetree,
isTopLevel);
break;
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 6bce4d76fe..2a317257ea 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -56,7 +56,7 @@ extern ObjectAddress CreateCast(CreateCastStmt *stmt);
extern ObjectAddress CreateTransform(CreateTransformStmt *stmt);
extern void IsThereFunctionInNamespace(const char *proname, int pronargs,
oidvector *proargtypes, Oid nspOid);
-extern void ExecuteDoStmt(DoStmt *stmt, bool atomic);
+extern void ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic);
extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest);
extern TupleDesc CallStmtResultDesc(CallStmt *stmt);
extern Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok);
@@ -121,8 +121,8 @@ extern ObjectAddress AlterForeignServerOwner(const char *name, Oid newOwnerId);
extern void AlterForeignServerOwner_oid(Oid, Oid newOwnerId);
extern ObjectAddress AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId);
extern void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId);
-extern ObjectAddress CreateForeignDataWrapper(CreateFdwStmt *stmt);
-extern ObjectAddress AlterForeignDataWrapper(AlterFdwStmt *stmt);
+extern ObjectAddress CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt);
+extern ObjectAddress AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt);
extern ObjectAddress CreateForeignServer(CreateForeignServerStmt *stmt);
extern ObjectAddress AlterForeignServer(AlterForeignServerStmt *stmt);
extern ObjectAddress CreateUserMapping(CreateUserMappingStmt *stmt);
diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h
index 00e2e626e6..efea01f2a9 100644
--- a/src/include/commands/publicationcmds.h
+++ b/src/include/commands/publicationcmds.h
@@ -18,8 +18,8 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreatePublication(CreatePublicationStmt *stmt);
-extern void AlterPublication(AlterPublicationStmt *stmt);
+extern ObjectAddress CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt);
+extern void AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt);
extern void RemovePublicationRelById(Oid proid);
extern ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/subscriptioncmds.h b/src/include/commands/subscriptioncmds.h
index 3b926f35d7..8bf25ee66c 100644
--- a/src/include/commands/subscriptioncmds.h
+++ b/src/include/commands/subscriptioncmds.h
@@ -18,9 +18,9 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreateSubscription(CreateSubscriptionStmt *stmt,
+extern ObjectAddress CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
bool isTopLevel);
-extern ObjectAddress AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel);
+extern ObjectAddress AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, bool isTopLevel);
extern void DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel);
extern ObjectAddress AlterSubscriptionOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
index 880679127b..d5e22811d0 100644
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -25,7 +25,7 @@ extern ObjectAddress DefineType(ParseState *pstate, List *names, List *parameter
extern void RemoveTypeById(Oid typeOid);
extern ObjectAddress DefineDomain(CreateDomainStmt *stmt);
extern ObjectAddress DefineEnum(CreateEnumStmt *stmt);
-extern ObjectAddress DefineRange(CreateRangeStmt *stmt);
+extern ObjectAddress DefineRange(ParseState *pstate, CreateRangeStmt *stmt);
extern ObjectAddress AlterEnum(AlterEnumStmt *stmt);
extern ObjectAddress DefineCompositeType(RangeVar *typevar, List *coldeflist);
extern Oid AssignTypeArrayOid(void);
diff --git a/src/include/commands/user.h b/src/include/commands/user.h
index 028e0dde56..0b7a3cd65f 100644
--- a/src/include/commands/user.h
+++ b/src/include/commands/user.h
@@ -25,7 +25,7 @@ typedef void (*check_password_hook_type) (const char *username, const char *shad
extern PGDLLIMPORT check_password_hook_type check_password_hook;
extern Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt);
-extern Oid AlterRole(AlterRoleStmt *stmt);
+extern Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt);
extern Oid AlterRoleSet(AlterRoleSetStmt *stmt);
extern void DropRole(DropRoleStmt *stmt);
extern void GrantRole(GrantRoleStmt *stmt);
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c64f0719e7..92fe8a121a 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -30,31 +30,31 @@ COPY x (xyz) from stdin;
ERROR: column "xyz" of relation "x" does not exist
-- redundant options
COPY x from stdin (format CSV, FORMAT CSV);
-ERROR: conflicting or redundant options
+ERROR: option "format" specified more than once
LINE 1: COPY x from stdin (format CSV, FORMAT CSV);
^
COPY x from stdin (freeze off, freeze on);
-ERROR: conflicting or redundant options
+ERROR: option "freeze" specified more than once
LINE 1: COPY x from stdin (freeze off, freeze on);
^
COPY x from stdin (delimiter ',', delimiter ',');
-ERROR: conflicting or redundant options
+ERROR: option "delimiter" specified more than once
LINE 1: COPY x from stdin (delimiter ',', delimiter ',');
^
COPY x from stdin (null ' ', null ' ');
-ERROR: conflicting or redundant options
+ERROR: option "null" specified more than once
LINE 1: COPY x from stdin (null ' ', null ' ');
^
COPY x from stdin (header off, header on);
-ERROR: conflicting or redundant options
+ERROR: option "header" specified more than once
LINE 1: COPY x from stdin (header off, header on);
^
COPY x from stdin (quote ':', quote ':');
-ERROR: conflicting or redundant options
+ERROR: option "quote" specified more than once
LINE 1: COPY x from stdin (quote ':', quote ':');
^
COPY x from stdin (escape ':', escape ':');
-ERROR: conflicting or redundant options
+ERROR: option "escape" specified more than once
LINE 1: COPY x from stdin (escape ':', escape ':');
^
COPY x from stdin (force_quote (a), force_quote *);
@@ -62,17 +62,19 @@ ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (force_quote (a), force_quote *);
^
COPY x from stdin (force_not_null (a), force_not_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_not_null" specified more than once
LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
COPY x from stdin (force_null (a), force_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_null" specified more than once
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
-ERROR: conflicting or redundant options
+ERROR: option "convert_selectively" specified more than once
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
^
COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
-ERROR: conflicting or redundant options
+ERROR: option "encoding" specified more than once
LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
^
-- too many columns in column list: should fail
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 5385f98a0f..03d6eca747 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -94,7 +94,9 @@ CREATE FUNCTION invalid_fdw_handler() RETURNS int LANGUAGE SQL AS 'SELECT 1;';
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...GN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER in...
+ ^
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -200,7 +202,9 @@ ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo;
ALTER FOREIGN DATA WRAPPER foo HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER an...
+ ^
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 63d6ab7a4e..0f5cbe2e99 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -26,7 +26,9 @@ ERROR: unrecognized publication parameter: "foo"
CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
-ERROR: conflicting or redundant options
+ERROR: option "publish_via_partition_root" specified more than once
+LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi...
+ ^
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
--
2.25.1
On 2021-May-10, vignesh C wrote:
That sounds fine to me, Attached v6 patch which has the changes for the same.
What about defining a function (maybe a static inline function in
defrem.h) that is marked noreturn and receives the DefElem and
optionally pstate, and throws the error? I think that would avoid the
patch's need to have half a dozen copies of the "duplicate_error:" label
and ereport stanza.
--
�lvaro Herrera 39�49'30"S 73�17'W
On Tue, May 11, 2021 at 2:47 AM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2021-May-10, vignesh C wrote:
That sounds fine to me, Attached v6 patch which has the changes for the same.
What about defining a function (maybe a static inline function in
defrem.h) that is marked noreturn and receives the DefElem and
optionally pstate, and throws the error? I think that would avoid the
patch's need to have half a dozen copies of the "duplicate_error:" label
and ereport stanza.
+1 to have a static inline function which just reports the error.
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
On Tue, May 11, 2021 at 2:47 AM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2021-May-10, vignesh C wrote:
That sounds fine to me, Attached v6 patch which has the changes for the same.
What about defining a function (maybe a static inline function in
defrem.h) that is marked noreturn and receives the DefElem and
optionally pstate, and throws the error? I think that would avoid the
patch's need to have half a dozen copies of the "duplicate_error:" label
and ereport stanza.
Thanks for the comment, this reduces a significant amount of code.
Attached patch has the changes incorporated.
Regards,
Vignesh
Attachments:
v7-0001-Enhance-error-message.patchapplication/x-patch; name=v7-0001-Enhance-error-message.patchDownload
From 9b325d6d85fca39ec0ff3f39735281f8a9fa647c Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Mon, 26 Apr 2021 18:40:36 +0530
Subject: [PATCH v7] Enhance error message.
Enhanced error message, so that the user can easily identify the error.
---
contrib/file_fdw/file_fdw.c | 13 +--
src/backend/catalog/aclchk.c | 14 +--
src/backend/commands/copy.c | 57 +++-------
src/backend/commands/dbcommands.c | 76 +++----------
src/backend/commands/extension.c | 23 +---
src/backend/commands/foreigncmds.c | 21 ++--
src/backend/commands/functioncmds.c | 59 ++++------
src/backend/commands/publicationcmds.c | 30 ++---
src/backend/commands/sequence.c | 48 ++------
src/backend/commands/subscriptioncmds.c | 66 +++++------
src/backend/commands/tablecmds.c | 4 +-
src/backend/commands/typecmds.c | 34 ++----
src/backend/commands/user.c | 118 +++++---------------
src/backend/parser/parse_utilcmd.c | 4 +-
src/backend/replication/pgoutput/pgoutput.c | 23 ++--
src/backend/replication/walsender.c | 15 +--
src/backend/tcop/utility.c | 20 ++--
src/include/commands/defrem.h | 20 +++-
src/include/commands/publicationcmds.h | 4 +-
src/include/commands/subscriptioncmds.h | 4 +-
src/include/commands/typecmds.h | 2 +-
src/include/commands/user.h | 2 +-
src/test/regress/expected/copy2.out | 24 ++--
src/test/regress/expected/foreign_data.out | 8 +-
src/test/regress/expected/publication.out | 4 +-
25 files changed, 239 insertions(+), 454 deletions(-)
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 2c2f149fb0..f49dd47930 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -200,6 +200,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
char *filename = NULL;
DefElem *force_not_null = NULL;
DefElem *force_null = NULL;
+ DefElem *def;
List *other_options = NIL;
ListCell *cell;
@@ -209,7 +210,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
*/
foreach(cell, options_list)
{
- DefElem *def = (DefElem *) lfirst(cell);
+ def = (DefElem *) lfirst(cell);
if (!is_valid_option(def->defname, catalog))
{
@@ -290,10 +291,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_not_null") == 0)
{
if (force_not_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_not_null\" supplied more than once for a column.")));
+ ReportDuplicateOptionError(def, NULL);
force_not_null = def;
/* Don't care what the value is, as long as it's a legal boolean */
(void) defGetBoolean(def);
@@ -302,10 +300,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_null") == 0)
{
if (force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_null\" supplied more than once for a column.")));
+ ReportDuplicateOptionError(def, NULL);
force_null = def;
(void) defGetBoolean(def);
}
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index e1573eb398..3933aba716 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -59,6 +59,7 @@
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
#include "commands/proclang.h"
@@ -910,30 +911,25 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
List *nspnames = NIL;
DefElem *drolespecs = NULL;
DefElem *dnspnames = NULL;
+ DefElem *defel;
AclMode all_privileges;
const char *errormsg;
/* Deconstruct the "options" part of the statement */
foreach(cell, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(cell);
+ defel = (DefElem *) lfirst(cell);
if (strcmp(defel->defname, "schemas") == 0)
{
if (dnspnames)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dnspnames = defel;
}
else if (strcmp(defel->defname, "roles") == 0)
{
if (drolespecs)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
drolespecs = defel;
}
else
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 8265b981eb..0d13daab4c 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -340,6 +340,7 @@ ProcessCopyOptions(ParseState *pstate,
bool freeze_specified = false;
bool header_specified = false;
ListCell *option;
+ DefElem *defel;
/* Support external use for option sanity checking */
if (opts_out == NULL)
@@ -350,17 +351,14 @@ ProcessCopyOptions(ParseState *pstate,
/* Extract options from the statement node tree */
foreach(option, options)
{
- DefElem *defel = lfirst_node(DefElem, option);
+ defel = lfirst_node(DefElem, option);
if (strcmp(defel->defname, "format") == 0)
{
char *fmt = defGetString(defel);
if (format_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
format_specified = true;
if (strcmp(fmt, "text") == 0)
/* default format */ ;
@@ -377,57 +375,39 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "freeze") == 0)
{
if (freeze_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
freeze_specified = true;
opts_out->freeze = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "delimiter") == 0)
{
if (opts_out->delim)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->delim = defGetString(defel);
}
else if (strcmp(defel->defname, "null") == 0)
{
if (opts_out->null_print)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->null_print = defGetString(defel);
}
else if (strcmp(defel->defname, "header") == 0)
{
if (header_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
header_specified = true;
opts_out->header_line = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "quote") == 0)
{
if (opts_out->quote)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->quote = defGetString(defel);
}
else if (strcmp(defel->defname, "escape") == 0)
{
if (opts_out->escape)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->escape = defGetString(defel);
}
else if (strcmp(defel->defname, "force_quote") == 0)
@@ -451,10 +431,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_not_null") == 0)
{
if (opts_out->force_notnull)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
if (defel->arg && IsA(defel->arg, List))
opts_out->force_notnull = castNode(List, defel->arg);
else
@@ -467,9 +444,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_null") == 0)
{
if (opts_out->force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
@@ -487,10 +462,7 @@ ProcessCopyOptions(ParseState *pstate,
* allowed for the column list to be NIL.
*/
if (opts_out->convert_selectively)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->convert_selectively = true;
if (defel->arg == NULL || IsA(defel->arg, List))
opts_out->convert_select = castNode(List, defel->arg);
@@ -504,10 +476,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "encoding") == 0)
{
if (opts_out->file_encoding >= 0)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
if (opts_out->file_encoding < 0)
ereport(ERROR,
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 2b159b60eb..0aa2311ad2 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -143,100 +143,71 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
int notherbackends;
int npreparedxacts;
createdb_failure_params fparms;
+ DefElem *defel;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespacename)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtablespacename = defel;
}
else if (strcmp(defel->defname, "owner") == 0)
{
if (downer)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
downer = defel;
}
else if (strcmp(defel->defname, "template") == 0)
{
if (dtemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtemplate = defel;
}
else if (strcmp(defel->defname, "encoding") == 0)
{
if (dencoding)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dencoding = defel;
}
else if (strcmp(defel->defname, "locale") == 0)
{
if (dlocale)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dlocale = defel;
}
else if (strcmp(defel->defname, "lc_collate") == 0)
{
if (dcollate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcollate = defel;
}
else if (strcmp(defel->defname, "lc_ctype") == 0)
{
if (dctype)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dctype = defel;
}
else if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "location") == 0)
@@ -1488,46 +1459,35 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
Datum new_record[Natts_pg_database];
bool new_record_nulls[Natts_pg_database];
bool new_record_repl[Natts_pg_database];
+ DefElem *defel;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespace)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtablespace = defel;
}
else
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 19db329fe6..32941005bd 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1682,6 +1682,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
DefElem *d_schema = NULL;
DefElem *d_new_version = NULL;
DefElem *d_cascade = NULL;
+ DefElem *defel;
char *schemaName = NULL;
char *versionName = NULL;
bool cascade = false;
@@ -1725,35 +1726,26 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
/* Deconstruct the statement option list */
foreach(lc, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "schema") == 0)
{
if (d_schema)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_schema = defel;
schemaName = defGetString(d_schema);
}
else if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_new_version = defel;
versionName = defGetString(d_new_version);
}
else if (strcmp(defel->defname, "cascade") == 0)
{
if (d_cascade)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_cascade = defel;
cascade = defGetBoolean(d_cascade);
}
@@ -3050,10 +3042,7 @@ ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_new_version = defel;
}
else
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index eb7103fd3b..dd3db3627e 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -515,11 +515,12 @@ lookup_fdw_validator_func(DefElem *validator)
* Process function options of CREATE/ALTER FDW
*/
static void
-parse_func_options(List *func_options,
+parse_func_options(ParseState *pstate, List *func_options,
bool *handler_given, Oid *fdwhandler,
bool *validator_given, Oid *fdwvalidator)
{
ListCell *cell;
+ DefElem *def;
*handler_given = false;
*validator_given = false;
@@ -529,23 +530,19 @@ parse_func_options(List *func_options,
foreach(cell, func_options)
{
- DefElem *def = (DefElem *) lfirst(cell);
+ def = (DefElem *) lfirst(cell);
if (strcmp(def->defname, "handler") == 0)
{
if (*handler_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(def, pstate);
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
else if (strcmp(def->defname, "validator") == 0)
{
if (*validator_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(def, pstate);
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
@@ -559,7 +556,7 @@ parse_func_options(List *func_options,
* Create a foreign-data wrapper
*/
ObjectAddress
-CreateForeignDataWrapper(CreateFdwStmt *stmt)
+CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt)
{
Relation rel;
Datum values[Natts_pg_foreign_data_wrapper];
@@ -611,7 +608,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
/* Lookup handler and validator functions, if given */
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
@@ -675,7 +672,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
* Alter foreign-data wrapper
*/
ObjectAddress
-AlterForeignDataWrapper(AlterFdwStmt *stmt)
+AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt)
{
Relation rel;
HeapTuple tp;
@@ -717,7 +714,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
memset(repl_null, false, sizeof(repl_null));
memset(repl_repl, false, sizeof(repl_repl));
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9548287217..12af901f56 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -497,7 +497,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*volatility_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*volatility_item = defel;
}
@@ -506,14 +506,14 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*strict_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*strict_item = defel;
}
else if (strcmp(defel->defname, "security") == 0)
{
if (*security_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*security_item = defel;
}
@@ -522,7 +522,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*leakproof_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*leakproof_item = defel;
}
@@ -535,7 +535,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*cost_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*cost_item = defel;
}
@@ -544,7 +544,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*rows_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*rows_item = defel;
}
@@ -553,7 +553,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*support_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*support_item = defel;
}
@@ -562,7 +562,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*parallel_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*parallel_item = defel;
}
@@ -572,13 +572,6 @@ compute_common_attribute(ParseState *pstate,
/* Recognized an option */
return true;
-duplicate_error:
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
- return false; /* keep compiler quiet */
-
procedure_error:
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -731,45 +724,34 @@ compute_function_attributes(ParseState *pstate,
DefElem *rows_item = NULL;
DefElem *support_item = NULL;
DefElem *parallel_item = NULL;
+ DefElem *defel;
foreach(option, options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
language_item = defel;
}
else if (strcmp(defel->defname, "transform") == 0)
{
if (transform_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
transform_item = defel;
}
else if (strcmp(defel->defname, "window") == 0)
{
if (windowfunc_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
if (is_procedure)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -2044,12 +2026,13 @@ IsThereFunctionInNamespace(const char *proname, int pronargs,
* See at ExecuteCallStmt() about the atomic argument.
*/
void
-ExecuteDoStmt(DoStmt *stmt, bool atomic)
+ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
{
InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
ListCell *arg;
DefElem *as_item = NULL;
DefElem *language_item = NULL;
+ DefElem *defel;
char *language;
Oid laninline;
HeapTuple languageTuple;
@@ -2058,22 +2041,18 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
/* Process options we got from gram.y */
foreach(arg, stmt->args)
{
- DefElem *defel = (DefElem *) lfirst(arg);
+ defel = (DefElem *) lfirst(arg);
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
language_item = defel;
}
else
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 95c253c8e0..93ad657c02 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -55,13 +55,15 @@ static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
static void
-parse_publication_options(List *options,
+parse_publication_options(ParseState *pstate,
+ List *options,
bool *publish_given,
PublicationActions *pubactions,
bool *publish_via_partition_root_given,
bool *publish_via_partition_root)
{
ListCell *lc;
+ DefElem *defel;
*publish_given = false;
*publish_via_partition_root_given = false;
@@ -76,7 +78,7 @@ parse_publication_options(List *options,
/* Parse options */
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "publish") == 0)
{
@@ -85,9 +87,7 @@ parse_publication_options(List *options,
ListCell *lc;
if (*publish_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/*
* If publish option was given only the explicitly listed actions
@@ -128,9 +128,7 @@ parse_publication_options(List *options,
else if (strcmp(defel->defname, "publish_via_partition_root") == 0)
{
if (*publish_via_partition_root_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
@@ -145,7 +143,7 @@ parse_publication_options(List *options,
* Create new publication.
*/
ObjectAddress
-CreatePublication(CreatePublicationStmt *stmt)
+CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
{
Relation rel;
ObjectAddress myself;
@@ -192,7 +190,8 @@ CreatePublication(CreatePublicationStmt *stmt)
DirectFunctionCall1(namein, CStringGetDatum(stmt->pubname));
values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId());
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -256,8 +255,8 @@ CreatePublication(CreatePublicationStmt *stmt)
* Change options of a publication.
*/
static void
-AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
- HeapTuple tup)
+AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
+ Relation rel, HeapTuple tup)
{
bool nulls[Natts_pg_publication];
bool replaces[Natts_pg_publication];
@@ -269,7 +268,8 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
ObjectAddress obj;
Form_pg_publication pubform;
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -434,7 +434,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
* AlterPublicationTables.
*/
void
-AlterPublication(AlterPublicationStmt *stmt)
+AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
{
Relation rel;
HeapTuple tup;
@@ -459,7 +459,7 @@ AlterPublication(AlterPublicationStmt *stmt)
stmt->pubname);
if (stmt->options)
- AlterPublicationOptions(stmt, rel, tup);
+ AlterPublicationOptions(pstate, stmt, rel, tup);
else
AlterPublicationTables(stmt, rel, tup);
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 0415df9ccb..155d332e43 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1247,6 +1247,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
DefElem *min_value = NULL;
DefElem *cache_value = NULL;
DefElem *is_cycled = NULL;
+ DefElem *defel;
ListCell *option;
bool reset_max_value = false;
bool reset_min_value = false;
@@ -1256,95 +1257,68 @@ init_params(ParseState *pstate, List *options, bool for_identity,
foreach(option, options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "as") == 0)
{
if (as_type)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
as_type = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "increment") == 0)
{
if (increment_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
increment_by = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "start") == 0)
{
if (start_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
start_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "restart") == 0)
{
if (restart_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
restart_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "maxvalue") == 0)
{
if (max_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
max_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "minvalue") == 0)
{
if (min_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
min_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cache") == 0)
{
if (cache_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
cache_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cycle") == 0)
{
if (is_cycled)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
is_cycled = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "owned_by") == 0)
{
if (*owned_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
*owned_by = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "sequence_name") == 0)
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index bbb2f5d029..4bae26e250 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -60,7 +60,8 @@ static void ReportSlotConnectionError(List *rstates, Oid subid, char *slotname,
* accommodate that.
*/
static void
-parse_subscription_options(List *options,
+parse_subscription_options(ParseState *pstate,
+ List *options,
bool *connect,
bool *enabled_given, bool *enabled,
bool *create_slot,
@@ -76,6 +77,7 @@ parse_subscription_options(List *options,
bool create_slot_given = false;
bool copy_data_given = false;
bool refresh_given = false;
+ DefElem *defel;
/* If connect is specified, the others also need to be. */
Assert(!connect || (enabled && create_slot && copy_data));
@@ -114,14 +116,12 @@ parse_subscription_options(List *options,
/* Parse options */
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "connect") == 0 && connect)
{
if (connect_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
connect_given = true;
*connect = defGetBoolean(defel);
@@ -129,9 +129,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "enabled") == 0 && enabled)
{
if (*enabled_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*enabled_given = true;
*enabled = defGetBoolean(defel);
@@ -139,9 +137,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "create_slot") == 0 && create_slot)
{
if (create_slot_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
create_slot_given = true;
*create_slot = defGetBoolean(defel);
@@ -149,9 +145,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "slot_name") == 0 && slot_name)
{
if (*slot_name_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*slot_name_given = true;
*slot_name = defGetString(defel);
@@ -163,9 +157,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "copy_data") == 0 && copy_data)
{
if (copy_data_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
copy_data_given = true;
*copy_data = defGetBoolean(defel);
@@ -174,9 +166,7 @@ parse_subscription_options(List *options,
synchronous_commit)
{
if (*synchronous_commit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*synchronous_commit = defGetString(defel);
@@ -188,9 +178,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "refresh") == 0 && refresh)
{
if (refresh_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
refresh_given = true;
*refresh = defGetBoolean(defel);
@@ -198,9 +186,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "binary") == 0 && binary)
{
if (*binary_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*binary_given = true;
*binary = defGetBoolean(defel);
@@ -208,9 +194,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "streaming") == 0 && streaming)
{
if (*streaming_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*streaming_given = true;
*streaming = defGetBoolean(defel);
@@ -322,7 +306,8 @@ publicationListToArray(List *publist)
* Create new subscription.
*/
ObjectAddress
-CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
+CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -352,7 +337,8 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
*
* Connection and publication should not be specified here.
*/
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
&connect,
&enabled_given, &enabled,
&create_slot,
@@ -750,7 +736,8 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data)
* Alter the existing subscription.
*/
ObjectAddress
-AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
+AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -805,7 +792,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool streaming_given;
bool streaming;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -862,7 +850,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool enabled,
enabled_given;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
&enabled_given, &enabled,
NULL, /* no "create_slot" */
@@ -907,7 +896,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool copy_data;
bool refresh;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -953,7 +943,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
publist = merge_publications(sub->publications, stmt->publication, isadd, stmt->subname);
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -1000,7 +991,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions")));
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 591bf01189..852056366f 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7509,9 +7509,7 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmod
if (strcmp(defel->defname, "generated") == 0)
{
if (generatedEl)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 036fa69d17..051f23c009 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -330,10 +330,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
continue;
}
if (*defelp != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
*defelp = defel;
}
@@ -1336,7 +1333,7 @@ checkEnumOwner(HeapTuple tup)
* and users might have queries with that same assumption.
*/
ObjectAddress
-DefineRange(CreateRangeStmt *stmt)
+DefineRange(ParseState *pstate, CreateRangeStmt *stmt)
{
char *typeName;
Oid typeNamespace;
@@ -1366,6 +1363,7 @@ DefineRange(CreateRangeStmt *stmt)
ObjectAddress address;
ObjectAddress mltrngaddress PG_USED_FOR_ASSERTS_ONLY;
Oid castFuncOid;
+ DefElem *defel;
/* Convert list of names to a name and namespace */
typeNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
@@ -1406,55 +1404,43 @@ DefineRange(CreateRangeStmt *stmt)
/* Extract the parameters from the parameter list */
foreach(lc, stmt->params)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "subtype") == 0)
{
if (OidIsValid(rangeSubtype))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
else if (strcmp(defel->defname, "subtype_opclass") == 0)
{
if (rangeSubOpclassName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
{
if (rangeCollationName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
{
if (rangeCanonicalName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
{
if (rangeSubtypeDiffName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
{
if (multirangeTypeName != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 65bb733958..5045ae3daf 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -27,6 +27,7 @@
#include "catalog/pg_db_role_setting.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/seclabel.h"
#include "commands/user.h"
#include "libpq/crypt.h"
@@ -106,6 +107,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
DefElem *dadminmembers = NULL;
DefElem *dvalidUntil = NULL;
DefElem *dbypassRLS = NULL;
+ DefElem *defel;
/* The defaults can vary depending on the original statement type */
switch (stmt->stmt_type)
@@ -123,15 +125,12 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dpassword = defel;
}
else if (strcmp(defel->defname, "sysid") == 0)
@@ -142,109 +141,73 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "addroleto") == 0)
{
if (daddroleto)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
daddroleto = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
drolemembers = defel;
}
else if (strcmp(defel->defname, "adminmembers") == 0)
{
if (dadminmembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dadminmembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dbypassRLS = defel;
}
else
@@ -528,7 +491,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
* "ALTER ROLE role ROLE rolenames", we don't document it.
*/
Oid
-AlterRole(AlterRoleStmt *stmt)
+AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
{
Datum new_record[Natts_pg_authid];
bool new_record_nulls[Natts_pg_authid];
@@ -564,6 +527,7 @@ AlterRole(AlterRoleStmt *stmt)
DefElem *drolemembers = NULL;
DefElem *dvalidUntil = NULL;
DefElem *dbypassRLS = NULL;
+ DefElem *defel;
Oid roleid;
check_rolespec_name(stmt->role,
@@ -572,95 +536,73 @@ AlterRole(AlterRoleStmt *stmt)
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
stmt->action != 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dbypassRLS = defel;
}
else
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 48cce4567b..832fe392cd 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -402,9 +402,7 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (strcmp(defel->defname, "sequence_name") == 0)
{
if (nameEl)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index f68348dcf4..96131b4420 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -165,6 +165,7 @@ static void
parse_output_parameters(List *options, PGOutputData *data)
{
ListCell *lc;
+ DefElem *defel;
bool protocol_version_given = false;
bool publication_names_given = false;
bool binary_option_given = false;
@@ -177,7 +178,7 @@ parse_output_parameters(List *options, PGOutputData *data)
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
Assert(defel->arg == NULL || IsA(defel->arg, String));
@@ -187,9 +188,7 @@ parse_output_parameters(List *options, PGOutputData *data)
int64 parsed;
if (protocol_version_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -208,9 +207,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "publication_names") == 0)
{
if (publication_names_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -222,9 +219,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "binary") == 0)
{
if (binary_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -232,9 +227,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "messages") == 0)
{
if (messages_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -242,9 +235,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "streaming") == 0)
{
if (streaming_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
streaming_given = true;
data->streaming = defGetBoolean(defel);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 628c8d49d9..3e846981fc 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -868,18 +868,17 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
ListCell *lc;
bool snapshot_action_given = false;
bool reserve_wal_given = false;
+ DefElem *defel;
/* Parse options */
foreach(lc, cmd->options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "export_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
snapshot_action_given = true;
*snapshot_action = defGetBoolean(defel) ? CRS_EXPORT_SNAPSHOT :
@@ -888,9 +887,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else if (strcmp(defel->defname, "use_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
snapshot_action_given = true;
*snapshot_action = CRS_USE_SNAPSHOT;
@@ -898,9 +895,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else if (strcmp(defel->defname, "reserve_wal") == 0)
{
if (reserve_wal_given || cmd->kind != REPLICATION_KIND_PHYSICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
reserve_wal_given = true;
*reserve_wal = true;
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 1a8fc16773..865c59dfe4 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -693,7 +693,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
break;
case T_DoStmt:
- ExecuteDoStmt((DoStmt *) parsetree, isAtomicContext);
+ ExecuteDoStmt(pstate, (DoStmt *) parsetree, isAtomicContext);
break;
case T_CreateTableSpaceStmt:
@@ -873,7 +873,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
case T_AlterRoleStmt:
/* no event triggers for global objects */
- AlterRole((AlterRoleStmt *) parsetree);
+ AlterRole(pstate, (AlterRoleStmt *) parsetree);
break;
case T_AlterRoleSetStmt:
@@ -1536,11 +1536,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateFdwStmt:
- address = CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
+ address = CreateForeignDataWrapper(pstate, (CreateFdwStmt *) parsetree);
break;
case T_AlterFdwStmt:
- address = AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
+ address = AlterForeignDataWrapper(pstate, (AlterFdwStmt *) parsetree);
break;
case T_CreateForeignServerStmt:
@@ -1585,7 +1585,7 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
- address = DefineRange((CreateRangeStmt *) parsetree);
+ address = DefineRange(pstate, (CreateRangeStmt *) parsetree);
break;
case T_AlterEnumStmt: /* ALTER TYPE (enum) */
@@ -1786,11 +1786,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreatePublicationStmt:
- address = CreatePublication((CreatePublicationStmt *) parsetree);
+ address = CreatePublication(pstate, (CreatePublicationStmt *) parsetree);
break;
case T_AlterPublicationStmt:
- AlterPublication((AlterPublicationStmt *) parsetree);
+ AlterPublication(pstate, (AlterPublicationStmt *) parsetree);
/*
* AlterPublication calls EventTriggerCollectSimpleCommand
@@ -1800,12 +1800,14 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateSubscriptionStmt:
- address = CreateSubscription((CreateSubscriptionStmt *) parsetree,
+ address = CreateSubscription(pstate,
+ (CreateSubscriptionStmt *) parsetree,
isTopLevel);
break;
case T_AlterSubscriptionStmt:
- address = AlterSubscription((AlterSubscriptionStmt *) parsetree,
+ address = AlterSubscription(pstate,
+ (AlterSubscriptionStmt *) parsetree,
isTopLevel);
break;
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 6bce4d76fe..46823dab5e 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -56,7 +56,7 @@ extern ObjectAddress CreateCast(CreateCastStmt *stmt);
extern ObjectAddress CreateTransform(CreateTransformStmt *stmt);
extern void IsThereFunctionInNamespace(const char *proname, int pronargs,
oidvector *proargtypes, Oid nspOid);
-extern void ExecuteDoStmt(DoStmt *stmt, bool atomic);
+extern void ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic);
extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest);
extern TupleDesc CallStmtResultDesc(CallStmt *stmt);
extern Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok);
@@ -121,8 +121,8 @@ extern ObjectAddress AlterForeignServerOwner(const char *name, Oid newOwnerId);
extern void AlterForeignServerOwner_oid(Oid, Oid newOwnerId);
extern ObjectAddress AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId);
extern void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId);
-extern ObjectAddress CreateForeignDataWrapper(CreateFdwStmt *stmt);
-extern ObjectAddress AlterForeignDataWrapper(AlterFdwStmt *stmt);
+extern ObjectAddress CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt);
+extern ObjectAddress AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt);
extern ObjectAddress CreateForeignServer(CreateForeignServerStmt *stmt);
extern ObjectAddress AlterForeignServer(AlterForeignServerStmt *stmt);
extern ObjectAddress CreateUserMapping(CreateUserMappingStmt *stmt);
@@ -154,4 +154,18 @@ extern TypeName *defGetTypeName(DefElem *def);
extern int defGetTypeLength(DefElem *def);
extern List *defGetStringList(DefElem *def);
+static inline void
+ReportDuplicateOptionError(DefElem *defel, ParseState *pstate)
+{
+ if (pstate)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser_errposition(pstate, defel->location)));
+
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname)));
+}
+
#endif /* DEFREM_H */
diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h
index 00e2e626e6..efea01f2a9 100644
--- a/src/include/commands/publicationcmds.h
+++ b/src/include/commands/publicationcmds.h
@@ -18,8 +18,8 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreatePublication(CreatePublicationStmt *stmt);
-extern void AlterPublication(AlterPublicationStmt *stmt);
+extern ObjectAddress CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt);
+extern void AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt);
extern void RemovePublicationRelById(Oid proid);
extern ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/subscriptioncmds.h b/src/include/commands/subscriptioncmds.h
index 3b926f35d7..8bf25ee66c 100644
--- a/src/include/commands/subscriptioncmds.h
+++ b/src/include/commands/subscriptioncmds.h
@@ -18,9 +18,9 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreateSubscription(CreateSubscriptionStmt *stmt,
+extern ObjectAddress CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
bool isTopLevel);
-extern ObjectAddress AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel);
+extern ObjectAddress AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, bool isTopLevel);
extern void DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel);
extern ObjectAddress AlterSubscriptionOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
index 880679127b..d5e22811d0 100644
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -25,7 +25,7 @@ extern ObjectAddress DefineType(ParseState *pstate, List *names, List *parameter
extern void RemoveTypeById(Oid typeOid);
extern ObjectAddress DefineDomain(CreateDomainStmt *stmt);
extern ObjectAddress DefineEnum(CreateEnumStmt *stmt);
-extern ObjectAddress DefineRange(CreateRangeStmt *stmt);
+extern ObjectAddress DefineRange(ParseState *pstate, CreateRangeStmt *stmt);
extern ObjectAddress AlterEnum(AlterEnumStmt *stmt);
extern ObjectAddress DefineCompositeType(RangeVar *typevar, List *coldeflist);
extern Oid AssignTypeArrayOid(void);
diff --git a/src/include/commands/user.h b/src/include/commands/user.h
index 028e0dde56..0b7a3cd65f 100644
--- a/src/include/commands/user.h
+++ b/src/include/commands/user.h
@@ -25,7 +25,7 @@ typedef void (*check_password_hook_type) (const char *username, const char *shad
extern PGDLLIMPORT check_password_hook_type check_password_hook;
extern Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt);
-extern Oid AlterRole(AlterRoleStmt *stmt);
+extern Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt);
extern Oid AlterRoleSet(AlterRoleSetStmt *stmt);
extern void DropRole(DropRoleStmt *stmt);
extern void GrantRole(GrantRoleStmt *stmt);
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c64f0719e7..92fe8a121a 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -30,31 +30,31 @@ COPY x (xyz) from stdin;
ERROR: column "xyz" of relation "x" does not exist
-- redundant options
COPY x from stdin (format CSV, FORMAT CSV);
-ERROR: conflicting or redundant options
+ERROR: option "format" specified more than once
LINE 1: COPY x from stdin (format CSV, FORMAT CSV);
^
COPY x from stdin (freeze off, freeze on);
-ERROR: conflicting or redundant options
+ERROR: option "freeze" specified more than once
LINE 1: COPY x from stdin (freeze off, freeze on);
^
COPY x from stdin (delimiter ',', delimiter ',');
-ERROR: conflicting or redundant options
+ERROR: option "delimiter" specified more than once
LINE 1: COPY x from stdin (delimiter ',', delimiter ',');
^
COPY x from stdin (null ' ', null ' ');
-ERROR: conflicting or redundant options
+ERROR: option "null" specified more than once
LINE 1: COPY x from stdin (null ' ', null ' ');
^
COPY x from stdin (header off, header on);
-ERROR: conflicting or redundant options
+ERROR: option "header" specified more than once
LINE 1: COPY x from stdin (header off, header on);
^
COPY x from stdin (quote ':', quote ':');
-ERROR: conflicting or redundant options
+ERROR: option "quote" specified more than once
LINE 1: COPY x from stdin (quote ':', quote ':');
^
COPY x from stdin (escape ':', escape ':');
-ERROR: conflicting or redundant options
+ERROR: option "escape" specified more than once
LINE 1: COPY x from stdin (escape ':', escape ':');
^
COPY x from stdin (force_quote (a), force_quote *);
@@ -62,17 +62,19 @@ ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (force_quote (a), force_quote *);
^
COPY x from stdin (force_not_null (a), force_not_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_not_null" specified more than once
LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
COPY x from stdin (force_null (a), force_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_null" specified more than once
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
-ERROR: conflicting or redundant options
+ERROR: option "convert_selectively" specified more than once
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
^
COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
-ERROR: conflicting or redundant options
+ERROR: option "encoding" specified more than once
LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
^
-- too many columns in column list: should fail
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 5385f98a0f..03d6eca747 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -94,7 +94,9 @@ CREATE FUNCTION invalid_fdw_handler() RETURNS int LANGUAGE SQL AS 'SELECT 1;';
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...GN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER in...
+ ^
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -200,7 +202,9 @@ ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo;
ALTER FOREIGN DATA WRAPPER foo HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER an...
+ ^
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 63d6ab7a4e..0f5cbe2e99 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -26,7 +26,9 @@ ERROR: unrecognized publication parameter: "foo"
CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
-ERROR: conflicting or redundant options
+ERROR: option "publish_via_partition_root" specified more than once
+LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi...
+ ^
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
--
2.25.1
On Tue, May 11, 2021 at 6:54 PM vignesh C <vignesh21@gmail.com> wrote:
On Tue, May 11, 2021 at 2:47 AM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2021-May-10, vignesh C wrote:
That sounds fine to me, Attached v6 patch which has the changes for the same.
What about defining a function (maybe a static inline function in
defrem.h) that is marked noreturn and receives the DefElem and
optionally pstate, and throws the error? I think that would avoid the
patch's need to have half a dozen copies of the "duplicate_error:" label
and ereport stanza.Thanks for the comment, this reduces a significant amount of code.
Yeah, the patch reduces more than 200 LOC which is a pretty good thing.
25 files changed, 239 insertions(+), 454 deletions(-)
With Regards,
Bharath Rupireddy.
EnterpriseDB: http://www.enterprisedb.com
You can avoid duplicating the ereport like this:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser ? parser_errposition(pstate, defel->location) : 0));
... also, since e3a87b4991cc you can now elide the parens around the
auxiliary function calls:
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ parser ? parser_errposition(pstate, defel->location) : 0));
Please do add a pg_attribute_noreturn() decorator. I'm not sure if any
compilers will complain about the code flow if you have that, but I
expect many (all?) will if you don't.
--
�lvaro Herrera Valdivia, Chile
"Java is clearly an example of money oriented programming" (A. Stepanov)
On Thu, May 13, 2021 at 4:58 AM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
You can avoid duplicating the ereport like this:
+ ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("option \"%s\" specified more than once", defel->defname), + parser ? parser_errposition(pstate, defel->location) : 0));... also, since e3a87b4991cc you can now elide the parens around the
auxiliary function calls:
Modified.
+ ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("option \"%s\" specified more than once", defel->defname), + parser ? parser_errposition(pstate, defel->location) : 0));Please do add a pg_attribute_noreturn() decorator. I'm not sure if any
compilers will complain about the code flow if you have that, but I
expect many (all?) will if you don't.
Modified.
Thanks for the comments, Attached patch has the changes for the same.
Regards,
Vignesh
Attachments:
v8-0001-Enhance-error-message.patchtext/x-patch; charset=US-ASCII; name=v8-0001-Enhance-error-message.patchDownload
From c2362f0c7c75675639cba8603b8fb7acd38c506d Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Mon, 26 Apr 2021 18:40:36 +0530
Subject: [PATCH v8] Enhance error message.
Enhanced error message, so that the user can easily identify the error.
---
contrib/file_fdw/file_fdw.c | 13 +--
src/backend/catalog/aclchk.c | 14 +--
src/backend/commands/copy.c | 57 +++-------
src/backend/commands/dbcommands.c | 76 +++----------
src/backend/commands/extension.c | 23 +---
src/backend/commands/foreigncmds.c | 21 ++--
src/backend/commands/functioncmds.c | 59 ++++------
src/backend/commands/publicationcmds.c | 30 ++---
src/backend/commands/sequence.c | 48 ++------
src/backend/commands/subscriptioncmds.c | 66 +++++------
src/backend/commands/tablecmds.c | 4 +-
src/backend/commands/typecmds.c | 34 ++----
src/backend/commands/user.c | 118 +++++---------------
src/backend/parser/parse_utilcmd.c | 4 +-
src/backend/replication/pgoutput/pgoutput.c | 23 ++--
src/backend/replication/walsender.c | 15 +--
src/backend/tcop/utility.c | 20 ++--
src/include/commands/defrem.h | 16 ++-
src/include/commands/publicationcmds.h | 4 +-
src/include/commands/subscriptioncmds.h | 4 +-
src/include/commands/typecmds.h | 2 +-
src/include/commands/user.h | 2 +-
src/test/regress/expected/copy2.out | 24 ++--
src/test/regress/expected/foreign_data.out | 8 +-
src/test/regress/expected/publication.out | 4 +-
25 files changed, 235 insertions(+), 454 deletions(-)
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 2c2f149fb0..f49dd47930 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -200,6 +200,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
char *filename = NULL;
DefElem *force_not_null = NULL;
DefElem *force_null = NULL;
+ DefElem *def;
List *other_options = NIL;
ListCell *cell;
@@ -209,7 +210,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
*/
foreach(cell, options_list)
{
- DefElem *def = (DefElem *) lfirst(cell);
+ def = (DefElem *) lfirst(cell);
if (!is_valid_option(def->defname, catalog))
{
@@ -290,10 +291,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_not_null") == 0)
{
if (force_not_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_not_null\" supplied more than once for a column.")));
+ ReportDuplicateOptionError(def, NULL);
force_not_null = def;
/* Don't care what the value is, as long as it's a legal boolean */
(void) defGetBoolean(def);
@@ -302,10 +300,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_null") == 0)
{
if (force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_null\" supplied more than once for a column.")));
+ ReportDuplicateOptionError(def, NULL);
force_null = def;
(void) defGetBoolean(def);
}
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 53392414f1..264cdc2730 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -59,6 +59,7 @@
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
#include "commands/proclang.h"
@@ -910,30 +911,25 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
List *nspnames = NIL;
DefElem *drolespecs = NULL;
DefElem *dnspnames = NULL;
+ DefElem *defel;
AclMode all_privileges;
const char *errormsg;
/* Deconstruct the "options" part of the statement */
foreach(cell, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(cell);
+ defel = (DefElem *) lfirst(cell);
if (strcmp(defel->defname, "schemas") == 0)
{
if (dnspnames)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dnspnames = defel;
}
else if (strcmp(defel->defname, "roles") == 0)
{
if (drolespecs)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
drolespecs = defel;
}
else
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 8265b981eb..0d13daab4c 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -340,6 +340,7 @@ ProcessCopyOptions(ParseState *pstate,
bool freeze_specified = false;
bool header_specified = false;
ListCell *option;
+ DefElem *defel;
/* Support external use for option sanity checking */
if (opts_out == NULL)
@@ -350,17 +351,14 @@ ProcessCopyOptions(ParseState *pstate,
/* Extract options from the statement node tree */
foreach(option, options)
{
- DefElem *defel = lfirst_node(DefElem, option);
+ defel = lfirst_node(DefElem, option);
if (strcmp(defel->defname, "format") == 0)
{
char *fmt = defGetString(defel);
if (format_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
format_specified = true;
if (strcmp(fmt, "text") == 0)
/* default format */ ;
@@ -377,57 +375,39 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "freeze") == 0)
{
if (freeze_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
freeze_specified = true;
opts_out->freeze = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "delimiter") == 0)
{
if (opts_out->delim)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->delim = defGetString(defel);
}
else if (strcmp(defel->defname, "null") == 0)
{
if (opts_out->null_print)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->null_print = defGetString(defel);
}
else if (strcmp(defel->defname, "header") == 0)
{
if (header_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
header_specified = true;
opts_out->header_line = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "quote") == 0)
{
if (opts_out->quote)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->quote = defGetString(defel);
}
else if (strcmp(defel->defname, "escape") == 0)
{
if (opts_out->escape)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->escape = defGetString(defel);
}
else if (strcmp(defel->defname, "force_quote") == 0)
@@ -451,10 +431,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_not_null") == 0)
{
if (opts_out->force_notnull)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
if (defel->arg && IsA(defel->arg, List))
opts_out->force_notnull = castNode(List, defel->arg);
else
@@ -467,9 +444,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_null") == 0)
{
if (opts_out->force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
@@ -487,10 +462,7 @@ ProcessCopyOptions(ParseState *pstate,
* allowed for the column list to be NIL.
*/
if (opts_out->convert_selectively)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->convert_selectively = true;
if (defel->arg == NULL || IsA(defel->arg, List))
opts_out->convert_select = castNode(List, defel->arg);
@@ -504,10 +476,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "encoding") == 0)
{
if (opts_out->file_encoding >= 0)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
if (opts_out->file_encoding < 0)
ereport(ERROR,
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 2b159b60eb..0aa2311ad2 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -143,100 +143,71 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
int notherbackends;
int npreparedxacts;
createdb_failure_params fparms;
+ DefElem *defel;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespacename)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtablespacename = defel;
}
else if (strcmp(defel->defname, "owner") == 0)
{
if (downer)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
downer = defel;
}
else if (strcmp(defel->defname, "template") == 0)
{
if (dtemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtemplate = defel;
}
else if (strcmp(defel->defname, "encoding") == 0)
{
if (dencoding)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dencoding = defel;
}
else if (strcmp(defel->defname, "locale") == 0)
{
if (dlocale)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dlocale = defel;
}
else if (strcmp(defel->defname, "lc_collate") == 0)
{
if (dcollate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcollate = defel;
}
else if (strcmp(defel->defname, "lc_ctype") == 0)
{
if (dctype)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dctype = defel;
}
else if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "location") == 0)
@@ -1488,46 +1459,35 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
Datum new_record[Natts_pg_database];
bool new_record_nulls[Natts_pg_database];
bool new_record_repl[Natts_pg_database];
+ DefElem *defel;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespace)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtablespace = defel;
}
else
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 008505368c..e715f40daf 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1682,6 +1682,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
DefElem *d_schema = NULL;
DefElem *d_new_version = NULL;
DefElem *d_cascade = NULL;
+ DefElem *defel;
char *schemaName = NULL;
char *versionName = NULL;
bool cascade = false;
@@ -1725,35 +1726,26 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
/* Deconstruct the statement option list */
foreach(lc, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "schema") == 0)
{
if (d_schema)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_schema = defel;
schemaName = defGetString(d_schema);
}
else if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_new_version = defel;
versionName = defGetString(d_new_version);
}
else if (strcmp(defel->defname, "cascade") == 0)
{
if (d_cascade)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_cascade = defel;
cascade = defGetBoolean(d_cascade);
}
@@ -3050,10 +3042,7 @@ ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_new_version = defel;
}
else
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index eb7103fd3b..dd3db3627e 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -515,11 +515,12 @@ lookup_fdw_validator_func(DefElem *validator)
* Process function options of CREATE/ALTER FDW
*/
static void
-parse_func_options(List *func_options,
+parse_func_options(ParseState *pstate, List *func_options,
bool *handler_given, Oid *fdwhandler,
bool *validator_given, Oid *fdwvalidator)
{
ListCell *cell;
+ DefElem *def;
*handler_given = false;
*validator_given = false;
@@ -529,23 +530,19 @@ parse_func_options(List *func_options,
foreach(cell, func_options)
{
- DefElem *def = (DefElem *) lfirst(cell);
+ def = (DefElem *) lfirst(cell);
if (strcmp(def->defname, "handler") == 0)
{
if (*handler_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(def, pstate);
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
else if (strcmp(def->defname, "validator") == 0)
{
if (*validator_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(def, pstate);
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
@@ -559,7 +556,7 @@ parse_func_options(List *func_options,
* Create a foreign-data wrapper
*/
ObjectAddress
-CreateForeignDataWrapper(CreateFdwStmt *stmt)
+CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt)
{
Relation rel;
Datum values[Natts_pg_foreign_data_wrapper];
@@ -611,7 +608,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
/* Lookup handler and validator functions, if given */
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
@@ -675,7 +672,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
* Alter foreign-data wrapper
*/
ObjectAddress
-AlterForeignDataWrapper(AlterFdwStmt *stmt)
+AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt)
{
Relation rel;
HeapTuple tp;
@@ -717,7 +714,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
memset(repl_null, false, sizeof(repl_null));
memset(repl_repl, false, sizeof(repl_repl));
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9548287217..12af901f56 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -497,7 +497,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*volatility_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*volatility_item = defel;
}
@@ -506,14 +506,14 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*strict_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*strict_item = defel;
}
else if (strcmp(defel->defname, "security") == 0)
{
if (*security_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*security_item = defel;
}
@@ -522,7 +522,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*leakproof_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*leakproof_item = defel;
}
@@ -535,7 +535,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*cost_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*cost_item = defel;
}
@@ -544,7 +544,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*rows_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*rows_item = defel;
}
@@ -553,7 +553,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*support_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*support_item = defel;
}
@@ -562,7 +562,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*parallel_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*parallel_item = defel;
}
@@ -572,13 +572,6 @@ compute_common_attribute(ParseState *pstate,
/* Recognized an option */
return true;
-duplicate_error:
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
- return false; /* keep compiler quiet */
-
procedure_error:
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -731,45 +724,34 @@ compute_function_attributes(ParseState *pstate,
DefElem *rows_item = NULL;
DefElem *support_item = NULL;
DefElem *parallel_item = NULL;
+ DefElem *defel;
foreach(option, options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
language_item = defel;
}
else if (strcmp(defel->defname, "transform") == 0)
{
if (transform_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
transform_item = defel;
}
else if (strcmp(defel->defname, "window") == 0)
{
if (windowfunc_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
if (is_procedure)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -2044,12 +2026,13 @@ IsThereFunctionInNamespace(const char *proname, int pronargs,
* See at ExecuteCallStmt() about the atomic argument.
*/
void
-ExecuteDoStmt(DoStmt *stmt, bool atomic)
+ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
{
InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
ListCell *arg;
DefElem *as_item = NULL;
DefElem *language_item = NULL;
+ DefElem *defel;
char *language;
Oid laninline;
HeapTuple languageTuple;
@@ -2058,22 +2041,18 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
/* Process options we got from gram.y */
foreach(arg, stmt->args)
{
- DefElem *defel = (DefElem *) lfirst(arg);
+ defel = (DefElem *) lfirst(arg);
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
language_item = defel;
}
else
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 95c253c8e0..93ad657c02 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -55,13 +55,15 @@ static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
static void
-parse_publication_options(List *options,
+parse_publication_options(ParseState *pstate,
+ List *options,
bool *publish_given,
PublicationActions *pubactions,
bool *publish_via_partition_root_given,
bool *publish_via_partition_root)
{
ListCell *lc;
+ DefElem *defel;
*publish_given = false;
*publish_via_partition_root_given = false;
@@ -76,7 +78,7 @@ parse_publication_options(List *options,
/* Parse options */
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "publish") == 0)
{
@@ -85,9 +87,7 @@ parse_publication_options(List *options,
ListCell *lc;
if (*publish_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/*
* If publish option was given only the explicitly listed actions
@@ -128,9 +128,7 @@ parse_publication_options(List *options,
else if (strcmp(defel->defname, "publish_via_partition_root") == 0)
{
if (*publish_via_partition_root_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
@@ -145,7 +143,7 @@ parse_publication_options(List *options,
* Create new publication.
*/
ObjectAddress
-CreatePublication(CreatePublicationStmt *stmt)
+CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
{
Relation rel;
ObjectAddress myself;
@@ -192,7 +190,8 @@ CreatePublication(CreatePublicationStmt *stmt)
DirectFunctionCall1(namein, CStringGetDatum(stmt->pubname));
values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId());
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -256,8 +255,8 @@ CreatePublication(CreatePublicationStmt *stmt)
* Change options of a publication.
*/
static void
-AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
- HeapTuple tup)
+AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
+ Relation rel, HeapTuple tup)
{
bool nulls[Natts_pg_publication];
bool replaces[Natts_pg_publication];
@@ -269,7 +268,8 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
ObjectAddress obj;
Form_pg_publication pubform;
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -434,7 +434,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
* AlterPublicationTables.
*/
void
-AlterPublication(AlterPublicationStmt *stmt)
+AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
{
Relation rel;
HeapTuple tup;
@@ -459,7 +459,7 @@ AlterPublication(AlterPublicationStmt *stmt)
stmt->pubname);
if (stmt->options)
- AlterPublicationOptions(stmt, rel, tup);
+ AlterPublicationOptions(pstate, stmt, rel, tup);
else
AlterPublicationTables(stmt, rel, tup);
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 0415df9ccb..155d332e43 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1247,6 +1247,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
DefElem *min_value = NULL;
DefElem *cache_value = NULL;
DefElem *is_cycled = NULL;
+ DefElem *defel;
ListCell *option;
bool reset_max_value = false;
bool reset_min_value = false;
@@ -1256,95 +1257,68 @@ init_params(ParseState *pstate, List *options, bool for_identity,
foreach(option, options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "as") == 0)
{
if (as_type)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
as_type = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "increment") == 0)
{
if (increment_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
increment_by = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "start") == 0)
{
if (start_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
start_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "restart") == 0)
{
if (restart_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
restart_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "maxvalue") == 0)
{
if (max_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
max_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "minvalue") == 0)
{
if (min_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
min_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cache") == 0)
{
if (cache_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
cache_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cycle") == 0)
{
if (is_cycled)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
is_cycled = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "owned_by") == 0)
{
if (*owned_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
*owned_by = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "sequence_name") == 0)
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 8aa6de1785..a93f4fe159 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -60,7 +60,8 @@ static void ReportSlotConnectionError(List *rstates, Oid subid, char *slotname,
* accommodate that.
*/
static void
-parse_subscription_options(List *options,
+parse_subscription_options(ParseState *pstate,
+ List *options,
bool *connect,
bool *enabled_given, bool *enabled,
bool *create_slot,
@@ -76,6 +77,7 @@ parse_subscription_options(List *options,
bool create_slot_given = false;
bool copy_data_given = false;
bool refresh_given = false;
+ DefElem *defel;
/* If connect is specified, the others also need to be. */
Assert(!connect || (enabled && create_slot && copy_data));
@@ -114,14 +116,12 @@ parse_subscription_options(List *options,
/* Parse options */
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "connect") == 0 && connect)
{
if (connect_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
connect_given = true;
*connect = defGetBoolean(defel);
@@ -129,9 +129,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "enabled") == 0 && enabled)
{
if (*enabled_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*enabled_given = true;
*enabled = defGetBoolean(defel);
@@ -139,9 +137,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "create_slot") == 0 && create_slot)
{
if (create_slot_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
create_slot_given = true;
*create_slot = defGetBoolean(defel);
@@ -149,9 +145,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "slot_name") == 0 && slot_name)
{
if (*slot_name_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*slot_name_given = true;
*slot_name = defGetString(defel);
@@ -163,9 +157,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "copy_data") == 0 && copy_data)
{
if (copy_data_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
copy_data_given = true;
*copy_data = defGetBoolean(defel);
@@ -174,9 +166,7 @@ parse_subscription_options(List *options,
synchronous_commit)
{
if (*synchronous_commit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*synchronous_commit = defGetString(defel);
@@ -188,9 +178,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "refresh") == 0 && refresh)
{
if (refresh_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
refresh_given = true;
*refresh = defGetBoolean(defel);
@@ -198,9 +186,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "binary") == 0 && binary)
{
if (*binary_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*binary_given = true;
*binary = defGetBoolean(defel);
@@ -208,9 +194,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "streaming") == 0 && streaming)
{
if (*streaming_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*streaming_given = true;
*streaming = defGetBoolean(defel);
@@ -322,7 +306,8 @@ publicationListToArray(List *publist)
* Create new subscription.
*/
ObjectAddress
-CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
+CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -352,7 +337,8 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
*
* Connection and publication should not be specified here.
*/
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
&connect,
&enabled_given, &enabled,
&create_slot,
@@ -750,7 +736,8 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data)
* Alter the existing subscription.
*/
ObjectAddress
-AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
+AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -805,7 +792,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool streaming_given;
bool streaming;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -862,7 +850,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool enabled,
enabled_given;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
&enabled_given, &enabled,
NULL, /* no "create_slot" */
@@ -907,7 +896,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool copy_data;
bool refresh;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -953,7 +943,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
publist = merge_publications(sub->publications, stmt->publication, isadd, stmt->subname);
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -1000,7 +991,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions")));
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index ebc62034d2..4b31667f3b 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7509,9 +7509,7 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmod
if (strcmp(defel->defname, "generated") == 0)
{
if (generatedEl)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 58ec65c6af..c65d6d4c32 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -330,10 +330,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
continue;
}
if (*defelp != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
*defelp = defel;
}
@@ -1336,7 +1333,7 @@ checkEnumOwner(HeapTuple tup)
* and users might have queries with that same assumption.
*/
ObjectAddress
-DefineRange(CreateRangeStmt *stmt)
+DefineRange(ParseState *pstate, CreateRangeStmt *stmt)
{
char *typeName;
Oid typeNamespace;
@@ -1366,6 +1363,7 @@ DefineRange(CreateRangeStmt *stmt)
ObjectAddress address;
ObjectAddress mltrngaddress PG_USED_FOR_ASSERTS_ONLY;
Oid castFuncOid;
+ DefElem *defel;
/* Convert list of names to a name and namespace */
typeNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
@@ -1406,55 +1404,43 @@ DefineRange(CreateRangeStmt *stmt)
/* Extract the parameters from the parameter list */
foreach(lc, stmt->params)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "subtype") == 0)
{
if (OidIsValid(rangeSubtype))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
else if (strcmp(defel->defname, "subtype_opclass") == 0)
{
if (rangeSubOpclassName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
{
if (rangeCollationName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
{
if (rangeCanonicalName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
{
if (rangeSubtypeDiffName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
{
if (multirangeTypeName != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 65bb733958..5045ae3daf 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -27,6 +27,7 @@
#include "catalog/pg_db_role_setting.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/seclabel.h"
#include "commands/user.h"
#include "libpq/crypt.h"
@@ -106,6 +107,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
DefElem *dadminmembers = NULL;
DefElem *dvalidUntil = NULL;
DefElem *dbypassRLS = NULL;
+ DefElem *defel;
/* The defaults can vary depending on the original statement type */
switch (stmt->stmt_type)
@@ -123,15 +125,12 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dpassword = defel;
}
else if (strcmp(defel->defname, "sysid") == 0)
@@ -142,109 +141,73 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "addroleto") == 0)
{
if (daddroleto)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
daddroleto = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
drolemembers = defel;
}
else if (strcmp(defel->defname, "adminmembers") == 0)
{
if (dadminmembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dadminmembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dbypassRLS = defel;
}
else
@@ -528,7 +491,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
* "ALTER ROLE role ROLE rolenames", we don't document it.
*/
Oid
-AlterRole(AlterRoleStmt *stmt)
+AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
{
Datum new_record[Natts_pg_authid];
bool new_record_nulls[Natts_pg_authid];
@@ -564,6 +527,7 @@ AlterRole(AlterRoleStmt *stmt)
DefElem *drolemembers = NULL;
DefElem *dvalidUntil = NULL;
DefElem *dbypassRLS = NULL;
+ DefElem *defel;
Oid roleid;
check_rolespec_name(stmt->role,
@@ -572,95 +536,73 @@ AlterRole(AlterRoleStmt *stmt)
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
stmt->action != 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dbypassRLS = defel;
}
else
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index d5b67d48cf..4e100adbdc 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -402,9 +402,7 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (strcmp(defel->defname, "sequence_name") == 0)
{
if (nameEl)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index f68348dcf4..96131b4420 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -165,6 +165,7 @@ static void
parse_output_parameters(List *options, PGOutputData *data)
{
ListCell *lc;
+ DefElem *defel;
bool protocol_version_given = false;
bool publication_names_given = false;
bool binary_option_given = false;
@@ -177,7 +178,7 @@ parse_output_parameters(List *options, PGOutputData *data)
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
Assert(defel->arg == NULL || IsA(defel->arg, String));
@@ -187,9 +188,7 @@ parse_output_parameters(List *options, PGOutputData *data)
int64 parsed;
if (protocol_version_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -208,9 +207,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "publication_names") == 0)
{
if (publication_names_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -222,9 +219,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "binary") == 0)
{
if (binary_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -232,9 +227,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "messages") == 0)
{
if (messages_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -242,9 +235,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "streaming") == 0)
{
if (streaming_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
streaming_given = true;
data->streaming = defGetBoolean(defel);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index e94069c366..c037c14ffd 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -868,18 +868,17 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
ListCell *lc;
bool snapshot_action_given = false;
bool reserve_wal_given = false;
+ DefElem *defel;
/* Parse options */
foreach(lc, cmd->options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "export_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
snapshot_action_given = true;
*snapshot_action = defGetBoolean(defel) ? CRS_EXPORT_SNAPSHOT :
@@ -888,9 +887,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else if (strcmp(defel->defname, "use_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
snapshot_action_given = true;
*snapshot_action = CRS_USE_SNAPSHOT;
@@ -898,9 +895,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else if (strcmp(defel->defname, "reserve_wal") == 0)
{
if (reserve_wal_given || cmd->kind != REPLICATION_KIND_PHYSICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
reserve_wal_given = true;
*reserve_wal = true;
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 1a8fc16773..865c59dfe4 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -693,7 +693,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
break;
case T_DoStmt:
- ExecuteDoStmt((DoStmt *) parsetree, isAtomicContext);
+ ExecuteDoStmt(pstate, (DoStmt *) parsetree, isAtomicContext);
break;
case T_CreateTableSpaceStmt:
@@ -873,7 +873,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
case T_AlterRoleStmt:
/* no event triggers for global objects */
- AlterRole((AlterRoleStmt *) parsetree);
+ AlterRole(pstate, (AlterRoleStmt *) parsetree);
break;
case T_AlterRoleSetStmt:
@@ -1536,11 +1536,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateFdwStmt:
- address = CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
+ address = CreateForeignDataWrapper(pstate, (CreateFdwStmt *) parsetree);
break;
case T_AlterFdwStmt:
- address = AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
+ address = AlterForeignDataWrapper(pstate, (AlterFdwStmt *) parsetree);
break;
case T_CreateForeignServerStmt:
@@ -1585,7 +1585,7 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
- address = DefineRange((CreateRangeStmt *) parsetree);
+ address = DefineRange(pstate, (CreateRangeStmt *) parsetree);
break;
case T_AlterEnumStmt: /* ALTER TYPE (enum) */
@@ -1786,11 +1786,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreatePublicationStmt:
- address = CreatePublication((CreatePublicationStmt *) parsetree);
+ address = CreatePublication(pstate, (CreatePublicationStmt *) parsetree);
break;
case T_AlterPublicationStmt:
- AlterPublication((AlterPublicationStmt *) parsetree);
+ AlterPublication(pstate, (AlterPublicationStmt *) parsetree);
/*
* AlterPublication calls EventTriggerCollectSimpleCommand
@@ -1800,12 +1800,14 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateSubscriptionStmt:
- address = CreateSubscription((CreateSubscriptionStmt *) parsetree,
+ address = CreateSubscription(pstate,
+ (CreateSubscriptionStmt *) parsetree,
isTopLevel);
break;
case T_AlterSubscriptionStmt:
- address = AlterSubscription((AlterSubscriptionStmt *) parsetree,
+ address = AlterSubscription(pstate,
+ (AlterSubscriptionStmt *) parsetree,
isTopLevel);
break;
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 42bf1c7519..0791444682 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -56,7 +56,7 @@ extern ObjectAddress CreateCast(CreateCastStmt *stmt);
extern ObjectAddress CreateTransform(CreateTransformStmt *stmt);
extern void IsThereFunctionInNamespace(const char *proname, int pronargs,
oidvector *proargtypes, Oid nspOid);
-extern void ExecuteDoStmt(DoStmt *stmt, bool atomic);
+extern void ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic);
extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest);
extern TupleDesc CallStmtResultDesc(CallStmt *stmt);
extern Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok);
@@ -121,8 +121,8 @@ extern ObjectAddress AlterForeignServerOwner(const char *name, Oid newOwnerId);
extern void AlterForeignServerOwner_oid(Oid, Oid newOwnerId);
extern ObjectAddress AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId);
extern void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId);
-extern ObjectAddress CreateForeignDataWrapper(CreateFdwStmt *stmt);
-extern ObjectAddress AlterForeignDataWrapper(AlterFdwStmt *stmt);
+extern ObjectAddress CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt);
+extern ObjectAddress AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt);
extern ObjectAddress CreateForeignServer(CreateForeignServerStmt *stmt);
extern ObjectAddress AlterForeignServer(AlterForeignServerStmt *stmt);
extern ObjectAddress CreateUserMapping(CreateUserMappingStmt *stmt);
@@ -154,4 +154,14 @@ extern TypeName *defGetTypeName(DefElem *def);
extern int defGetTypeLength(DefElem *def);
extern List *defGetStringList(DefElem *def);
+static inline void
+pg_attribute_noreturn()
+ReportDuplicateOptionError(DefElem *defel, ParseState *pstate)
+{
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ pstate ? parser_errposition(pstate, defel->location) : 0);
+}
+
#endif /* DEFREM_H */
diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h
index 00e2e626e6..efea01f2a9 100644
--- a/src/include/commands/publicationcmds.h
+++ b/src/include/commands/publicationcmds.h
@@ -18,8 +18,8 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreatePublication(CreatePublicationStmt *stmt);
-extern void AlterPublication(AlterPublicationStmt *stmt);
+extern ObjectAddress CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt);
+extern void AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt);
extern void RemovePublicationRelById(Oid proid);
extern ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/subscriptioncmds.h b/src/include/commands/subscriptioncmds.h
index 3b926f35d7..8bf25ee66c 100644
--- a/src/include/commands/subscriptioncmds.h
+++ b/src/include/commands/subscriptioncmds.h
@@ -18,9 +18,9 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreateSubscription(CreateSubscriptionStmt *stmt,
+extern ObjectAddress CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
bool isTopLevel);
-extern ObjectAddress AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel);
+extern ObjectAddress AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, bool isTopLevel);
extern void DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel);
extern ObjectAddress AlterSubscriptionOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
index 880679127b..d5e22811d0 100644
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -25,7 +25,7 @@ extern ObjectAddress DefineType(ParseState *pstate, List *names, List *parameter
extern void RemoveTypeById(Oid typeOid);
extern ObjectAddress DefineDomain(CreateDomainStmt *stmt);
extern ObjectAddress DefineEnum(CreateEnumStmt *stmt);
-extern ObjectAddress DefineRange(CreateRangeStmt *stmt);
+extern ObjectAddress DefineRange(ParseState *pstate, CreateRangeStmt *stmt);
extern ObjectAddress AlterEnum(AlterEnumStmt *stmt);
extern ObjectAddress DefineCompositeType(RangeVar *typevar, List *coldeflist);
extern Oid AssignTypeArrayOid(void);
diff --git a/src/include/commands/user.h b/src/include/commands/user.h
index 028e0dde56..0b7a3cd65f 100644
--- a/src/include/commands/user.h
+++ b/src/include/commands/user.h
@@ -25,7 +25,7 @@ typedef void (*check_password_hook_type) (const char *username, const char *shad
extern PGDLLIMPORT check_password_hook_type check_password_hook;
extern Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt);
-extern Oid AlterRole(AlterRoleStmt *stmt);
+extern Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt);
extern Oid AlterRoleSet(AlterRoleSetStmt *stmt);
extern void DropRole(DropRoleStmt *stmt);
extern void GrantRole(GrantRoleStmt *stmt);
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c64f0719e7..92fe8a121a 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -30,31 +30,31 @@ COPY x (xyz) from stdin;
ERROR: column "xyz" of relation "x" does not exist
-- redundant options
COPY x from stdin (format CSV, FORMAT CSV);
-ERROR: conflicting or redundant options
+ERROR: option "format" specified more than once
LINE 1: COPY x from stdin (format CSV, FORMAT CSV);
^
COPY x from stdin (freeze off, freeze on);
-ERROR: conflicting or redundant options
+ERROR: option "freeze" specified more than once
LINE 1: COPY x from stdin (freeze off, freeze on);
^
COPY x from stdin (delimiter ',', delimiter ',');
-ERROR: conflicting or redundant options
+ERROR: option "delimiter" specified more than once
LINE 1: COPY x from stdin (delimiter ',', delimiter ',');
^
COPY x from stdin (null ' ', null ' ');
-ERROR: conflicting or redundant options
+ERROR: option "null" specified more than once
LINE 1: COPY x from stdin (null ' ', null ' ');
^
COPY x from stdin (header off, header on);
-ERROR: conflicting or redundant options
+ERROR: option "header" specified more than once
LINE 1: COPY x from stdin (header off, header on);
^
COPY x from stdin (quote ':', quote ':');
-ERROR: conflicting or redundant options
+ERROR: option "quote" specified more than once
LINE 1: COPY x from stdin (quote ':', quote ':');
^
COPY x from stdin (escape ':', escape ':');
-ERROR: conflicting or redundant options
+ERROR: option "escape" specified more than once
LINE 1: COPY x from stdin (escape ':', escape ':');
^
COPY x from stdin (force_quote (a), force_quote *);
@@ -62,17 +62,19 @@ ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (force_quote (a), force_quote *);
^
COPY x from stdin (force_not_null (a), force_not_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_not_null" specified more than once
LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
COPY x from stdin (force_null (a), force_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_null" specified more than once
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
-ERROR: conflicting or redundant options
+ERROR: option "convert_selectively" specified more than once
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
^
COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
-ERROR: conflicting or redundant options
+ERROR: option "encoding" specified more than once
LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
^
-- too many columns in column list: should fail
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 5385f98a0f..03d6eca747 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -94,7 +94,9 @@ CREATE FUNCTION invalid_fdw_handler() RETURNS int LANGUAGE SQL AS 'SELECT 1;';
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...GN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER in...
+ ^
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -200,7 +202,9 @@ ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo;
ALTER FOREIGN DATA WRAPPER foo HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER an...
+ ^
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 63d6ab7a4e..0f5cbe2e99 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -26,7 +26,9 @@ ERROR: unrecognized publication parameter: "foo"
CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
-ERROR: conflicting or redundant options
+ERROR: option "publish_via_partition_root" specified more than once
+LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi...
+ ^
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
--
2.25.1
On Thu, May 13, 2021 at 8:09 PM vignesh C <vignesh21@gmail.com> wrote:
On Thu, May 13, 2021 at 4:58 AM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
Thanks for the comments, Attached patch has the changes for the same.
The Patch was not applying on Head, the attached patch is rebased on
top of Head.
Regards,
Vignesh
Attachments:
v8-0001-Enhance-error-message.patchtext/x-patch; charset=US-ASCII; name=v8-0001-Enhance-error-message.patchDownload
From fde4cfbe59064c890ac1c6c3342cc10398092c3c Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Wed, 30 Jun 2021 19:18:32 +0530
Subject: [PATCH v8] Enhance error message.
Enhanced error message, so that the user can easily identify the error.
---
contrib/file_fdw/file_fdw.c | 13 +--
src/backend/catalog/aclchk.c | 14 +--
src/backend/commands/copy.c | 57 +++-------
src/backend/commands/dbcommands.c | 76 +++----------
src/backend/commands/extension.c | 23 +---
src/backend/commands/foreigncmds.c | 21 ++--
src/backend/commands/functioncmds.c | 59 ++++------
src/backend/commands/publicationcmds.c | 30 ++---
src/backend/commands/sequence.c | 48 ++------
src/backend/commands/subscriptioncmds.c | 66 +++++------
src/backend/commands/tablecmds.c | 4 +-
src/backend/commands/typecmds.c | 34 ++----
src/backend/commands/user.c | 118 +++++---------------
src/backend/parser/parse_utilcmd.c | 4 +-
src/backend/replication/pgoutput/pgoutput.c | 23 ++--
src/backend/replication/walsender.c | 15 +--
src/backend/tcop/utility.c | 20 ++--
src/include/commands/defrem.h | 16 ++-
src/include/commands/publicationcmds.h | 4 +-
src/include/commands/subscriptioncmds.h | 4 +-
src/include/commands/typecmds.h | 2 +-
src/include/commands/user.h | 2 +-
src/test/regress/expected/copy2.out | 24 ++--
src/test/regress/expected/foreign_data.out | 8 +-
src/test/regress/expected/publication.out | 4 +-
25 files changed, 235 insertions(+), 454 deletions(-)
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 2c2f149fb0..f49dd47930 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -200,6 +200,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
char *filename = NULL;
DefElem *force_not_null = NULL;
DefElem *force_null = NULL;
+ DefElem *def;
List *other_options = NIL;
ListCell *cell;
@@ -209,7 +210,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
*/
foreach(cell, options_list)
{
- DefElem *def = (DefElem *) lfirst(cell);
+ def = (DefElem *) lfirst(cell);
if (!is_valid_option(def->defname, catalog))
{
@@ -290,10 +291,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_not_null") == 0)
{
if (force_not_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_not_null\" supplied more than once for a column.")));
+ ReportDuplicateOptionError(def, NULL);
force_not_null = def;
/* Don't care what the value is, as long as it's a legal boolean */
(void) defGetBoolean(def);
@@ -302,10 +300,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_null") == 0)
{
if (force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_null\" supplied more than once for a column.")));
+ ReportDuplicateOptionError(def, NULL);
force_null = def;
(void) defGetBoolean(def);
}
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 53392414f1..264cdc2730 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -59,6 +59,7 @@
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
#include "commands/proclang.h"
@@ -910,30 +911,25 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
List *nspnames = NIL;
DefElem *drolespecs = NULL;
DefElem *dnspnames = NULL;
+ DefElem *defel;
AclMode all_privileges;
const char *errormsg;
/* Deconstruct the "options" part of the statement */
foreach(cell, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(cell);
+ defel = (DefElem *) lfirst(cell);
if (strcmp(defel->defname, "schemas") == 0)
{
if (dnspnames)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dnspnames = defel;
}
else if (strcmp(defel->defname, "roles") == 0)
{
if (drolespecs)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
drolespecs = defel;
}
else
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 8265b981eb..0d13daab4c 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -340,6 +340,7 @@ ProcessCopyOptions(ParseState *pstate,
bool freeze_specified = false;
bool header_specified = false;
ListCell *option;
+ DefElem *defel;
/* Support external use for option sanity checking */
if (opts_out == NULL)
@@ -350,17 +351,14 @@ ProcessCopyOptions(ParseState *pstate,
/* Extract options from the statement node tree */
foreach(option, options)
{
- DefElem *defel = lfirst_node(DefElem, option);
+ defel = lfirst_node(DefElem, option);
if (strcmp(defel->defname, "format") == 0)
{
char *fmt = defGetString(defel);
if (format_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
format_specified = true;
if (strcmp(fmt, "text") == 0)
/* default format */ ;
@@ -377,57 +375,39 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "freeze") == 0)
{
if (freeze_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
freeze_specified = true;
opts_out->freeze = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "delimiter") == 0)
{
if (opts_out->delim)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->delim = defGetString(defel);
}
else if (strcmp(defel->defname, "null") == 0)
{
if (opts_out->null_print)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->null_print = defGetString(defel);
}
else if (strcmp(defel->defname, "header") == 0)
{
if (header_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
header_specified = true;
opts_out->header_line = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "quote") == 0)
{
if (opts_out->quote)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->quote = defGetString(defel);
}
else if (strcmp(defel->defname, "escape") == 0)
{
if (opts_out->escape)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->escape = defGetString(defel);
}
else if (strcmp(defel->defname, "force_quote") == 0)
@@ -451,10 +431,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_not_null") == 0)
{
if (opts_out->force_notnull)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
if (defel->arg && IsA(defel->arg, List))
opts_out->force_notnull = castNode(List, defel->arg);
else
@@ -467,9 +444,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_null") == 0)
{
if (opts_out->force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
@@ -487,10 +462,7 @@ ProcessCopyOptions(ParseState *pstate,
* allowed for the column list to be NIL.
*/
if (opts_out->convert_selectively)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->convert_selectively = true;
if (defel->arg == NULL || IsA(defel->arg, List))
opts_out->convert_select = castNode(List, defel->arg);
@@ -504,10 +476,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "encoding") == 0)
{
if (opts_out->file_encoding >= 0)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
if (opts_out->file_encoding < 0)
ereport(ERROR,
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 2b159b60eb..0aa2311ad2 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -143,100 +143,71 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
int notherbackends;
int npreparedxacts;
createdb_failure_params fparms;
+ DefElem *defel;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespacename)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtablespacename = defel;
}
else if (strcmp(defel->defname, "owner") == 0)
{
if (downer)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
downer = defel;
}
else if (strcmp(defel->defname, "template") == 0)
{
if (dtemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtemplate = defel;
}
else if (strcmp(defel->defname, "encoding") == 0)
{
if (dencoding)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dencoding = defel;
}
else if (strcmp(defel->defname, "locale") == 0)
{
if (dlocale)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dlocale = defel;
}
else if (strcmp(defel->defname, "lc_collate") == 0)
{
if (dcollate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcollate = defel;
}
else if (strcmp(defel->defname, "lc_ctype") == 0)
{
if (dctype)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dctype = defel;
}
else if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "location") == 0)
@@ -1488,46 +1459,35 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
Datum new_record[Natts_pg_database];
bool new_record_nulls[Natts_pg_database];
bool new_record_repl[Natts_pg_database];
+ DefElem *defel;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespace)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtablespace = defel;
}
else
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 41857feda9..962ddb5ffe 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1683,6 +1683,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
DefElem *d_schema = NULL;
DefElem *d_new_version = NULL;
DefElem *d_cascade = NULL;
+ DefElem *defel;
char *schemaName = NULL;
char *versionName = NULL;
bool cascade = false;
@@ -1726,35 +1727,26 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
/* Deconstruct the statement option list */
foreach(lc, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "schema") == 0)
{
if (d_schema)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_schema = defel;
schemaName = defGetString(d_schema);
}
else if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_new_version = defel;
versionName = defGetString(d_new_version);
}
else if (strcmp(defel->defname, "cascade") == 0)
{
if (d_cascade)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_cascade = defel;
cascade = defGetBoolean(d_cascade);
}
@@ -3051,10 +3043,7 @@ ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_new_version = defel;
}
else
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index bc36311d38..26a6a473ec 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -515,11 +515,12 @@ lookup_fdw_validator_func(DefElem *validator)
* Process function options of CREATE/ALTER FDW
*/
static void
-parse_func_options(List *func_options,
+parse_func_options(ParseState *pstate, List *func_options,
bool *handler_given, Oid *fdwhandler,
bool *validator_given, Oid *fdwvalidator)
{
ListCell *cell;
+ DefElem *def;
*handler_given = false;
*validator_given = false;
@@ -529,23 +530,19 @@ parse_func_options(List *func_options,
foreach(cell, func_options)
{
- DefElem *def = (DefElem *) lfirst(cell);
+ def = (DefElem *) lfirst(cell);
if (strcmp(def->defname, "handler") == 0)
{
if (*handler_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(def, pstate);
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
else if (strcmp(def->defname, "validator") == 0)
{
if (*validator_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(def, pstate);
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
@@ -559,7 +556,7 @@ parse_func_options(List *func_options,
* Create a foreign-data wrapper
*/
ObjectAddress
-CreateForeignDataWrapper(CreateFdwStmt *stmt)
+CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt)
{
Relation rel;
Datum values[Natts_pg_foreign_data_wrapper];
@@ -611,7 +608,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
/* Lookup handler and validator functions, if given */
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
@@ -675,7 +672,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
* Alter foreign-data wrapper
*/
ObjectAddress
-AlterForeignDataWrapper(AlterFdwStmt *stmt)
+AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt)
{
Relation rel;
HeapTuple tp;
@@ -717,7 +714,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
memset(repl_null, false, sizeof(repl_null));
memset(repl_repl, false, sizeof(repl_repl));
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 736d04780a..c3ca5cdfac 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -523,7 +523,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*volatility_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*volatility_item = defel;
}
@@ -532,14 +532,14 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*strict_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*strict_item = defel;
}
else if (strcmp(defel->defname, "security") == 0)
{
if (*security_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*security_item = defel;
}
@@ -548,7 +548,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*leakproof_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*leakproof_item = defel;
}
@@ -561,7 +561,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*cost_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*cost_item = defel;
}
@@ -570,7 +570,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*rows_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*rows_item = defel;
}
@@ -579,7 +579,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*support_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*support_item = defel;
}
@@ -588,7 +588,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*parallel_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*parallel_item = defel;
}
@@ -598,13 +598,6 @@ compute_common_attribute(ParseState *pstate,
/* Recognized an option */
return true;
-duplicate_error:
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
- return false; /* keep compiler quiet */
-
procedure_error:
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -757,45 +750,34 @@ compute_function_attributes(ParseState *pstate,
DefElem *rows_item = NULL;
DefElem *support_item = NULL;
DefElem *parallel_item = NULL;
+ DefElem *defel;
foreach(option, options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
language_item = defel;
}
else if (strcmp(defel->defname, "transform") == 0)
{
if (transform_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
transform_item = defel;
}
else if (strcmp(defel->defname, "window") == 0)
{
if (windowfunc_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
if (is_procedure)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -2070,12 +2052,13 @@ IsThereFunctionInNamespace(const char *proname, int pronargs,
* See at ExecuteCallStmt() about the atomic argument.
*/
void
-ExecuteDoStmt(DoStmt *stmt, bool atomic)
+ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
{
InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
ListCell *arg;
DefElem *as_item = NULL;
DefElem *language_item = NULL;
+ DefElem *defel;
char *language;
Oid laninline;
HeapTuple languageTuple;
@@ -2084,22 +2067,18 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
/* Process options we got from gram.y */
foreach(arg, stmt->args)
{
- DefElem *defel = (DefElem *) lfirst(arg);
+ defel = (DefElem *) lfirst(arg);
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
language_item = defel;
}
else
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 95c253c8e0..93ad657c02 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -55,13 +55,15 @@ static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
static void
-parse_publication_options(List *options,
+parse_publication_options(ParseState *pstate,
+ List *options,
bool *publish_given,
PublicationActions *pubactions,
bool *publish_via_partition_root_given,
bool *publish_via_partition_root)
{
ListCell *lc;
+ DefElem *defel;
*publish_given = false;
*publish_via_partition_root_given = false;
@@ -76,7 +78,7 @@ parse_publication_options(List *options,
/* Parse options */
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "publish") == 0)
{
@@ -85,9 +87,7 @@ parse_publication_options(List *options,
ListCell *lc;
if (*publish_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/*
* If publish option was given only the explicitly listed actions
@@ -128,9 +128,7 @@ parse_publication_options(List *options,
else if (strcmp(defel->defname, "publish_via_partition_root") == 0)
{
if (*publish_via_partition_root_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
@@ -145,7 +143,7 @@ parse_publication_options(List *options,
* Create new publication.
*/
ObjectAddress
-CreatePublication(CreatePublicationStmt *stmt)
+CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
{
Relation rel;
ObjectAddress myself;
@@ -192,7 +190,8 @@ CreatePublication(CreatePublicationStmt *stmt)
DirectFunctionCall1(namein, CStringGetDatum(stmt->pubname));
values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId());
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -256,8 +255,8 @@ CreatePublication(CreatePublicationStmt *stmt)
* Change options of a publication.
*/
static void
-AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
- HeapTuple tup)
+AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
+ Relation rel, HeapTuple tup)
{
bool nulls[Natts_pg_publication];
bool replaces[Natts_pg_publication];
@@ -269,7 +268,8 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
ObjectAddress obj;
Form_pg_publication pubform;
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -434,7 +434,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
* AlterPublicationTables.
*/
void
-AlterPublication(AlterPublicationStmt *stmt)
+AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
{
Relation rel;
HeapTuple tup;
@@ -459,7 +459,7 @@ AlterPublication(AlterPublicationStmt *stmt)
stmt->pubname);
if (stmt->options)
- AlterPublicationOptions(stmt, rel, tup);
+ AlterPublicationOptions(pstate, stmt, rel, tup);
else
AlterPublicationTables(stmt, rel, tup);
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 0415df9ccb..155d332e43 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1247,6 +1247,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
DefElem *min_value = NULL;
DefElem *cache_value = NULL;
DefElem *is_cycled = NULL;
+ DefElem *defel;
ListCell *option;
bool reset_max_value = false;
bool reset_min_value = false;
@@ -1256,95 +1257,68 @@ init_params(ParseState *pstate, List *options, bool for_identity,
foreach(option, options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "as") == 0)
{
if (as_type)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
as_type = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "increment") == 0)
{
if (increment_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
increment_by = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "start") == 0)
{
if (start_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
start_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "restart") == 0)
{
if (restart_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
restart_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "maxvalue") == 0)
{
if (max_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
max_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "minvalue") == 0)
{
if (min_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
min_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cache") == 0)
{
if (cache_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
cache_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cycle") == 0)
{
if (is_cycled)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
is_cycled = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "owned_by") == 0)
{
if (*owned_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
*owned_by = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "sequence_name") == 0)
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index b862e59f1d..7ff36374db 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -60,7 +60,8 @@ static void ReportSlotConnectionError(List *rstates, Oid subid, char *slotname,
* accommodate that.
*/
static void
-parse_subscription_options(List *options,
+parse_subscription_options(ParseState *pstate,
+ List *options,
bool *connect,
bool *enabled_given, bool *enabled,
bool *create_slot,
@@ -76,6 +77,7 @@ parse_subscription_options(List *options,
bool create_slot_given = false;
bool copy_data_given = false;
bool refresh_given = false;
+ DefElem *defel;
/* If connect is specified, the others also need to be. */
Assert(!connect || (enabled && create_slot && copy_data));
@@ -114,14 +116,12 @@ parse_subscription_options(List *options,
/* Parse options */
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "connect") == 0 && connect)
{
if (connect_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
connect_given = true;
*connect = defGetBoolean(defel);
@@ -129,9 +129,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "enabled") == 0 && enabled)
{
if (*enabled_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*enabled_given = true;
*enabled = defGetBoolean(defel);
@@ -139,9 +137,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "create_slot") == 0 && create_slot)
{
if (create_slot_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
create_slot_given = true;
*create_slot = defGetBoolean(defel);
@@ -149,9 +145,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "slot_name") == 0 && slot_name)
{
if (*slot_name_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*slot_name_given = true;
*slot_name = defGetString(defel);
@@ -163,9 +157,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "copy_data") == 0 && copy_data)
{
if (copy_data_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
copy_data_given = true;
*copy_data = defGetBoolean(defel);
@@ -174,9 +166,7 @@ parse_subscription_options(List *options,
synchronous_commit)
{
if (*synchronous_commit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*synchronous_commit = defGetString(defel);
@@ -188,9 +178,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "refresh") == 0 && refresh)
{
if (refresh_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
refresh_given = true;
*refresh = defGetBoolean(defel);
@@ -198,9 +186,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "binary") == 0 && binary)
{
if (*binary_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*binary_given = true;
*binary = defGetBoolean(defel);
@@ -208,9 +194,7 @@ parse_subscription_options(List *options,
else if (strcmp(defel->defname, "streaming") == 0 && streaming)
{
if (*streaming_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*streaming_given = true;
*streaming = defGetBoolean(defel);
@@ -322,7 +306,8 @@ publicationListToArray(List *publist)
* Create new subscription.
*/
ObjectAddress
-CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
+CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -352,7 +337,8 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
*
* Connection and publication should not be specified here.
*/
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
&connect,
&enabled_given, &enabled,
&create_slot,
@@ -752,7 +738,8 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data)
* Alter the existing subscription.
*/
ObjectAddress
-AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
+AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -807,7 +794,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool streaming_given;
bool streaming;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -864,7 +852,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool enabled,
enabled_given;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
&enabled_given, &enabled,
NULL, /* no "create_slot" */
@@ -909,7 +898,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool copy_data;
bool refresh;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -953,7 +943,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool refresh;
List *publist;
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
@@ -1002,7 +993,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions")));
- parse_subscription_options(stmt->options,
+ parse_subscription_options(pstate,
+ stmt->options,
NULL, /* no "connect" */
NULL, NULL, /* no "enabled" */
NULL, /* no "create_slot" */
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 97a9725df7..b3717d110e 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7494,9 +7494,7 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmod
if (strcmp(defel->defname, "generated") == 0)
{
if (generatedEl)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 58ec65c6af..c65d6d4c32 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -330,10 +330,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
continue;
}
if (*defelp != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
*defelp = defel;
}
@@ -1336,7 +1333,7 @@ checkEnumOwner(HeapTuple tup)
* and users might have queries with that same assumption.
*/
ObjectAddress
-DefineRange(CreateRangeStmt *stmt)
+DefineRange(ParseState *pstate, CreateRangeStmt *stmt)
{
char *typeName;
Oid typeNamespace;
@@ -1366,6 +1363,7 @@ DefineRange(CreateRangeStmt *stmt)
ObjectAddress address;
ObjectAddress mltrngaddress PG_USED_FOR_ASSERTS_ONLY;
Oid castFuncOid;
+ DefElem *defel;
/* Convert list of names to a name and namespace */
typeNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
@@ -1406,55 +1404,43 @@ DefineRange(CreateRangeStmt *stmt)
/* Extract the parameters from the parameter list */
foreach(lc, stmt->params)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "subtype") == 0)
{
if (OidIsValid(rangeSubtype))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
else if (strcmp(defel->defname, "subtype_opclass") == 0)
{
if (rangeSubOpclassName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
{
if (rangeCollationName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
{
if (rangeCanonicalName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
{
if (rangeSubtypeDiffName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
{
if (multirangeTypeName != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 65bb733958..5045ae3daf 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -27,6 +27,7 @@
#include "catalog/pg_db_role_setting.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/seclabel.h"
#include "commands/user.h"
#include "libpq/crypt.h"
@@ -106,6 +107,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
DefElem *dadminmembers = NULL;
DefElem *dvalidUntil = NULL;
DefElem *dbypassRLS = NULL;
+ DefElem *defel;
/* The defaults can vary depending on the original statement type */
switch (stmt->stmt_type)
@@ -123,15 +125,12 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dpassword = defel;
}
else if (strcmp(defel->defname, "sysid") == 0)
@@ -142,109 +141,73 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "addroleto") == 0)
{
if (daddroleto)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
daddroleto = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
drolemembers = defel;
}
else if (strcmp(defel->defname, "adminmembers") == 0)
{
if (dadminmembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dadminmembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dbypassRLS = defel;
}
else
@@ -528,7 +491,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
* "ALTER ROLE role ROLE rolenames", we don't document it.
*/
Oid
-AlterRole(AlterRoleStmt *stmt)
+AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
{
Datum new_record[Natts_pg_authid];
bool new_record_nulls[Natts_pg_authid];
@@ -564,6 +527,7 @@ AlterRole(AlterRoleStmt *stmt)
DefElem *drolemembers = NULL;
DefElem *dvalidUntil = NULL;
DefElem *dbypassRLS = NULL;
+ DefElem *defel;
Oid roleid;
check_rolespec_name(stmt->role,
@@ -572,95 +536,73 @@ AlterRole(AlterRoleStmt *stmt)
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
stmt->action != 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dbypassRLS = defel;
}
else
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 81d3e7990c..9bf0c9ad53 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -392,9 +392,7 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (strcmp(defel->defname, "sequence_name") == 0)
{
if (nameEl)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index abd5217ab1..e6becc7a17 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -162,6 +162,7 @@ static void
parse_output_parameters(List *options, PGOutputData *data)
{
ListCell *lc;
+ DefElem *defel;
bool protocol_version_given = false;
bool publication_names_given = false;
bool binary_option_given = false;
@@ -174,7 +175,7 @@ parse_output_parameters(List *options, PGOutputData *data)
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
Assert(defel->arg == NULL || IsA(defel->arg, String));
@@ -184,9 +185,7 @@ parse_output_parameters(List *options, PGOutputData *data)
int64 parsed;
if (protocol_version_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -205,9 +204,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "publication_names") == 0)
{
if (publication_names_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -219,9 +216,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "binary") == 0)
{
if (binary_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -229,9 +224,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "messages") == 0)
{
if (messages_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -239,9 +232,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "streaming") == 0)
{
if (streaming_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
streaming_given = true;
data->streaming = defGetBoolean(defel);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 92c755f346..3ca75f6fec 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -870,18 +870,17 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
bool snapshot_action_given = false;
bool reserve_wal_given = false;
bool two_phase_given = false;
+ DefElem *defel;
/* Parse options */
foreach(lc, cmd->options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "export_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
snapshot_action_given = true;
*snapshot_action = defGetBoolean(defel) ? CRS_EXPORT_SNAPSHOT :
@@ -890,9 +889,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else if (strcmp(defel->defname, "use_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
snapshot_action_given = true;
*snapshot_action = CRS_USE_SNAPSHOT;
@@ -900,9 +897,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else if (strcmp(defel->defname, "reserve_wal") == 0)
{
if (reserve_wal_given || cmd->kind != REPLICATION_KIND_PHYSICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
reserve_wal_given = true;
*reserve_wal = true;
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 7a2da9dab4..27fbf1f3aa 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -708,7 +708,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
break;
case T_DoStmt:
- ExecuteDoStmt((DoStmt *) parsetree, isAtomicContext);
+ ExecuteDoStmt(pstate, (DoStmt *) parsetree, isAtomicContext);
break;
case T_CreateTableSpaceStmt:
@@ -888,7 +888,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
case T_AlterRoleStmt:
/* no event triggers for global objects */
- AlterRole((AlterRoleStmt *) parsetree);
+ AlterRole(pstate, (AlterRoleStmt *) parsetree);
break;
case T_AlterRoleSetStmt:
@@ -1552,11 +1552,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateFdwStmt:
- address = CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
+ address = CreateForeignDataWrapper(pstate, (CreateFdwStmt *) parsetree);
break;
case T_AlterFdwStmt:
- address = AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
+ address = AlterForeignDataWrapper(pstate, (AlterFdwStmt *) parsetree);
break;
case T_CreateForeignServerStmt:
@@ -1601,7 +1601,7 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
- address = DefineRange((CreateRangeStmt *) parsetree);
+ address = DefineRange(pstate, (CreateRangeStmt *) parsetree);
break;
case T_AlterEnumStmt: /* ALTER TYPE (enum) */
@@ -1802,11 +1802,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreatePublicationStmt:
- address = CreatePublication((CreatePublicationStmt *) parsetree);
+ address = CreatePublication(pstate, (CreatePublicationStmt *) parsetree);
break;
case T_AlterPublicationStmt:
- AlterPublication((AlterPublicationStmt *) parsetree);
+ AlterPublication(pstate, (AlterPublicationStmt *) parsetree);
/*
* AlterPublication calls EventTriggerCollectSimpleCommand
@@ -1816,12 +1816,14 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateSubscriptionStmt:
- address = CreateSubscription((CreateSubscriptionStmt *) parsetree,
+ address = CreateSubscription(pstate,
+ (CreateSubscriptionStmt *) parsetree,
isTopLevel);
break;
case T_AlterSubscriptionStmt:
- address = AlterSubscription((AlterSubscriptionStmt *) parsetree,
+ address = AlterSubscription(pstate,
+ (AlterSubscriptionStmt *) parsetree,
isTopLevel);
break;
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 42bf1c7519..0791444682 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -56,7 +56,7 @@ extern ObjectAddress CreateCast(CreateCastStmt *stmt);
extern ObjectAddress CreateTransform(CreateTransformStmt *stmt);
extern void IsThereFunctionInNamespace(const char *proname, int pronargs,
oidvector *proargtypes, Oid nspOid);
-extern void ExecuteDoStmt(DoStmt *stmt, bool atomic);
+extern void ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic);
extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest);
extern TupleDesc CallStmtResultDesc(CallStmt *stmt);
extern Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok);
@@ -121,8 +121,8 @@ extern ObjectAddress AlterForeignServerOwner(const char *name, Oid newOwnerId);
extern void AlterForeignServerOwner_oid(Oid, Oid newOwnerId);
extern ObjectAddress AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId);
extern void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId);
-extern ObjectAddress CreateForeignDataWrapper(CreateFdwStmt *stmt);
-extern ObjectAddress AlterForeignDataWrapper(AlterFdwStmt *stmt);
+extern ObjectAddress CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt);
+extern ObjectAddress AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt);
extern ObjectAddress CreateForeignServer(CreateForeignServerStmt *stmt);
extern ObjectAddress AlterForeignServer(AlterForeignServerStmt *stmt);
extern ObjectAddress CreateUserMapping(CreateUserMappingStmt *stmt);
@@ -154,4 +154,14 @@ extern TypeName *defGetTypeName(DefElem *def);
extern int defGetTypeLength(DefElem *def);
extern List *defGetStringList(DefElem *def);
+static inline void
+pg_attribute_noreturn()
+ReportDuplicateOptionError(DefElem *defel, ParseState *pstate)
+{
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ pstate ? parser_errposition(pstate, defel->location) : 0);
+}
+
#endif /* DEFREM_H */
diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h
index 00e2e626e6..efea01f2a9 100644
--- a/src/include/commands/publicationcmds.h
+++ b/src/include/commands/publicationcmds.h
@@ -18,8 +18,8 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreatePublication(CreatePublicationStmt *stmt);
-extern void AlterPublication(AlterPublicationStmt *stmt);
+extern ObjectAddress CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt);
+extern void AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt);
extern void RemovePublicationRelById(Oid proid);
extern ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/subscriptioncmds.h b/src/include/commands/subscriptioncmds.h
index 3b926f35d7..8bf25ee66c 100644
--- a/src/include/commands/subscriptioncmds.h
+++ b/src/include/commands/subscriptioncmds.h
@@ -18,9 +18,9 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreateSubscription(CreateSubscriptionStmt *stmt,
+extern ObjectAddress CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
bool isTopLevel);
-extern ObjectAddress AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel);
+extern ObjectAddress AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, bool isTopLevel);
extern void DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel);
extern ObjectAddress AlterSubscriptionOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
index 880679127b..d5e22811d0 100644
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -25,7 +25,7 @@ extern ObjectAddress DefineType(ParseState *pstate, List *names, List *parameter
extern void RemoveTypeById(Oid typeOid);
extern ObjectAddress DefineDomain(CreateDomainStmt *stmt);
extern ObjectAddress DefineEnum(CreateEnumStmt *stmt);
-extern ObjectAddress DefineRange(CreateRangeStmt *stmt);
+extern ObjectAddress DefineRange(ParseState *pstate, CreateRangeStmt *stmt);
extern ObjectAddress AlterEnum(AlterEnumStmt *stmt);
extern ObjectAddress DefineCompositeType(RangeVar *typevar, List *coldeflist);
extern Oid AssignTypeArrayOid(void);
diff --git a/src/include/commands/user.h b/src/include/commands/user.h
index 028e0dde56..0b7a3cd65f 100644
--- a/src/include/commands/user.h
+++ b/src/include/commands/user.h
@@ -25,7 +25,7 @@ typedef void (*check_password_hook_type) (const char *username, const char *shad
extern PGDLLIMPORT check_password_hook_type check_password_hook;
extern Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt);
-extern Oid AlterRole(AlterRoleStmt *stmt);
+extern Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt);
extern Oid AlterRoleSet(AlterRoleSetStmt *stmt);
extern void DropRole(DropRoleStmt *stmt);
extern void GrantRole(GrantRoleStmt *stmt);
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c64f0719e7..92fe8a121a 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -30,31 +30,31 @@ COPY x (xyz) from stdin;
ERROR: column "xyz" of relation "x" does not exist
-- redundant options
COPY x from stdin (format CSV, FORMAT CSV);
-ERROR: conflicting or redundant options
+ERROR: option "format" specified more than once
LINE 1: COPY x from stdin (format CSV, FORMAT CSV);
^
COPY x from stdin (freeze off, freeze on);
-ERROR: conflicting or redundant options
+ERROR: option "freeze" specified more than once
LINE 1: COPY x from stdin (freeze off, freeze on);
^
COPY x from stdin (delimiter ',', delimiter ',');
-ERROR: conflicting or redundant options
+ERROR: option "delimiter" specified more than once
LINE 1: COPY x from stdin (delimiter ',', delimiter ',');
^
COPY x from stdin (null ' ', null ' ');
-ERROR: conflicting or redundant options
+ERROR: option "null" specified more than once
LINE 1: COPY x from stdin (null ' ', null ' ');
^
COPY x from stdin (header off, header on);
-ERROR: conflicting or redundant options
+ERROR: option "header" specified more than once
LINE 1: COPY x from stdin (header off, header on);
^
COPY x from stdin (quote ':', quote ':');
-ERROR: conflicting or redundant options
+ERROR: option "quote" specified more than once
LINE 1: COPY x from stdin (quote ':', quote ':');
^
COPY x from stdin (escape ':', escape ':');
-ERROR: conflicting or redundant options
+ERROR: option "escape" specified more than once
LINE 1: COPY x from stdin (escape ':', escape ':');
^
COPY x from stdin (force_quote (a), force_quote *);
@@ -62,17 +62,19 @@ ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (force_quote (a), force_quote *);
^
COPY x from stdin (force_not_null (a), force_not_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_not_null" specified more than once
LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
COPY x from stdin (force_null (a), force_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_null" specified more than once
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
-ERROR: conflicting or redundant options
+ERROR: option "convert_selectively" specified more than once
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
^
COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
-ERROR: conflicting or redundant options
+ERROR: option "encoding" specified more than once
LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
^
-- too many columns in column list: should fail
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 5385f98a0f..03d6eca747 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -94,7 +94,9 @@ CREATE FUNCTION invalid_fdw_handler() RETURNS int LANGUAGE SQL AS 'SELECT 1;';
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...GN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER in...
+ ^
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -200,7 +202,9 @@ ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo;
ALTER FOREIGN DATA WRAPPER foo HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER an...
+ ^
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 63d6ab7a4e..0f5cbe2e99 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -26,7 +26,9 @@ ERROR: unrecognized publication parameter: "foo"
CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
-ERROR: conflicting or redundant options
+ERROR: option "publish_via_partition_root" specified more than once
+LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi...
+ ^
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
--
2.25.1
On Wed, Jun 30, 2021 at 7:48 PM vignesh C <vignesh21@gmail.com> wrote:
On Thu, May 13, 2021 at 8:09 PM vignesh C <vignesh21@gmail.com> wrote:
On Thu, May 13, 2021 at 4:58 AM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
Thanks for the comments, Attached patch has the changes for the same.
The Patch was not applying on Head, the attached patch is rebased on
top of Head.
The patch was not applying on the head because of the recent commit
"8aafb02616753f5c6c90bbc567636b73c0cbb9d4", attached patch which is
rebased on HEAD.
Regards,
Vignesh
Attachments:
v8-0001-Enhance-error-message-to-include-option-name-in-c.patchtext/x-patch; charset=US-ASCII; name=v8-0001-Enhance-error-message-to-include-option-name-in-c.patchDownload
From 5ccc262d895d688fbca42d795ea01c7c16c09b54 Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Tue, 6 Jul 2021 20:22:45 +0530
Subject: [PATCH v8] Enhance error message to include option name in case of
duplicate option error.
Enhanced error message to include option name in case of duplication
option error, so that the user can easily identify the error.
---
contrib/file_fdw/file_fdw.c | 13 +--
src/backend/catalog/aclchk.c | 14 +--
src/backend/commands/copy.c | 57 +++-------
src/backend/commands/dbcommands.c | 76 +++----------
src/backend/commands/extension.c | 23 +---
src/backend/commands/foreigncmds.c | 21 ++--
src/backend/commands/functioncmds.c | 59 ++++------
src/backend/commands/publicationcmds.c | 30 ++---
src/backend/commands/sequence.c | 48 ++------
src/backend/commands/subscriptioncmds.c | 62 +++++-----
src/backend/commands/tablecmds.c | 4 +-
src/backend/commands/typecmds.c | 34 ++----
src/backend/commands/user.c | 118 +++++---------------
src/backend/parser/parse_utilcmd.c | 4 +-
src/backend/replication/pgoutput/pgoutput.c | 23 ++--
src/backend/replication/walsender.c | 15 +--
src/backend/tcop/utility.c | 20 ++--
src/include/commands/defrem.h | 16 ++-
src/include/commands/publicationcmds.h | 4 +-
src/include/commands/subscriptioncmds.h | 4 +-
src/include/commands/typecmds.h | 2 +-
src/include/commands/user.h | 2 +-
src/test/regress/expected/copy2.out | 24 ++--
src/test/regress/expected/foreign_data.out | 8 +-
src/test/regress/expected/publication.out | 4 +-
25 files changed, 232 insertions(+), 453 deletions(-)
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 2c2f149fb0..f49dd47930 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -200,6 +200,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
char *filename = NULL;
DefElem *force_not_null = NULL;
DefElem *force_null = NULL;
+ DefElem *def;
List *other_options = NIL;
ListCell *cell;
@@ -209,7 +210,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
*/
foreach(cell, options_list)
{
- DefElem *def = (DefElem *) lfirst(cell);
+ def = (DefElem *) lfirst(cell);
if (!is_valid_option(def->defname, catalog))
{
@@ -290,10 +291,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_not_null") == 0)
{
if (force_not_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_not_null\" supplied more than once for a column.")));
+ ReportDuplicateOptionError(def, NULL);
force_not_null = def;
/* Don't care what the value is, as long as it's a legal boolean */
(void) defGetBoolean(def);
@@ -302,10 +300,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_null") == 0)
{
if (force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_null\" supplied more than once for a column.")));
+ ReportDuplicateOptionError(def, NULL);
force_null = def;
(void) defGetBoolean(def);
}
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 53392414f1..264cdc2730 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -59,6 +59,7 @@
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
#include "commands/proclang.h"
@@ -910,30 +911,25 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
List *nspnames = NIL;
DefElem *drolespecs = NULL;
DefElem *dnspnames = NULL;
+ DefElem *defel;
AclMode all_privileges;
const char *errormsg;
/* Deconstruct the "options" part of the statement */
foreach(cell, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(cell);
+ defel = (DefElem *) lfirst(cell);
if (strcmp(defel->defname, "schemas") == 0)
{
if (dnspnames)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dnspnames = defel;
}
else if (strcmp(defel->defname, "roles") == 0)
{
if (drolespecs)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
drolespecs = defel;
}
else
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 8265b981eb..0d13daab4c 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -340,6 +340,7 @@ ProcessCopyOptions(ParseState *pstate,
bool freeze_specified = false;
bool header_specified = false;
ListCell *option;
+ DefElem *defel;
/* Support external use for option sanity checking */
if (opts_out == NULL)
@@ -350,17 +351,14 @@ ProcessCopyOptions(ParseState *pstate,
/* Extract options from the statement node tree */
foreach(option, options)
{
- DefElem *defel = lfirst_node(DefElem, option);
+ defel = lfirst_node(DefElem, option);
if (strcmp(defel->defname, "format") == 0)
{
char *fmt = defGetString(defel);
if (format_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
format_specified = true;
if (strcmp(fmt, "text") == 0)
/* default format */ ;
@@ -377,57 +375,39 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "freeze") == 0)
{
if (freeze_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
freeze_specified = true;
opts_out->freeze = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "delimiter") == 0)
{
if (opts_out->delim)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->delim = defGetString(defel);
}
else if (strcmp(defel->defname, "null") == 0)
{
if (opts_out->null_print)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->null_print = defGetString(defel);
}
else if (strcmp(defel->defname, "header") == 0)
{
if (header_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
header_specified = true;
opts_out->header_line = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "quote") == 0)
{
if (opts_out->quote)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->quote = defGetString(defel);
}
else if (strcmp(defel->defname, "escape") == 0)
{
if (opts_out->escape)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->escape = defGetString(defel);
}
else if (strcmp(defel->defname, "force_quote") == 0)
@@ -451,10 +431,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_not_null") == 0)
{
if (opts_out->force_notnull)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
if (defel->arg && IsA(defel->arg, List))
opts_out->force_notnull = castNode(List, defel->arg);
else
@@ -467,9 +444,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_null") == 0)
{
if (opts_out->force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
@@ -487,10 +462,7 @@ ProcessCopyOptions(ParseState *pstate,
* allowed for the column list to be NIL.
*/
if (opts_out->convert_selectively)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->convert_selectively = true;
if (defel->arg == NULL || IsA(defel->arg, List))
opts_out->convert_select = castNode(List, defel->arg);
@@ -504,10 +476,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "encoding") == 0)
{
if (opts_out->file_encoding >= 0)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
if (opts_out->file_encoding < 0)
ereport(ERROR,
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 2b159b60eb..0aa2311ad2 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -143,100 +143,71 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
int notherbackends;
int npreparedxacts;
createdb_failure_params fparms;
+ DefElem *defel;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespacename)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtablespacename = defel;
}
else if (strcmp(defel->defname, "owner") == 0)
{
if (downer)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
downer = defel;
}
else if (strcmp(defel->defname, "template") == 0)
{
if (dtemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtemplate = defel;
}
else if (strcmp(defel->defname, "encoding") == 0)
{
if (dencoding)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dencoding = defel;
}
else if (strcmp(defel->defname, "locale") == 0)
{
if (dlocale)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dlocale = defel;
}
else if (strcmp(defel->defname, "lc_collate") == 0)
{
if (dcollate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcollate = defel;
}
else if (strcmp(defel->defname, "lc_ctype") == 0)
{
if (dctype)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dctype = defel;
}
else if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "location") == 0)
@@ -1488,46 +1459,35 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
Datum new_record[Natts_pg_database];
bool new_record_nulls[Natts_pg_database];
bool new_record_repl[Natts_pg_database];
+ DefElem *defel;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespace)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtablespace = defel;
}
else
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 41857feda9..962ddb5ffe 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1683,6 +1683,7 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
DefElem *d_schema = NULL;
DefElem *d_new_version = NULL;
DefElem *d_cascade = NULL;
+ DefElem *defel;
char *schemaName = NULL;
char *versionName = NULL;
bool cascade = false;
@@ -1726,35 +1727,26 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
/* Deconstruct the statement option list */
foreach(lc, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "schema") == 0)
{
if (d_schema)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_schema = defel;
schemaName = defGetString(d_schema);
}
else if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_new_version = defel;
versionName = defGetString(d_new_version);
}
else if (strcmp(defel->defname, "cascade") == 0)
{
if (d_cascade)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_cascade = defel;
cascade = defGetBoolean(d_cascade);
}
@@ -3051,10 +3043,7 @@ ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_new_version = defel;
}
else
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index bc36311d38..26a6a473ec 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -515,11 +515,12 @@ lookup_fdw_validator_func(DefElem *validator)
* Process function options of CREATE/ALTER FDW
*/
static void
-parse_func_options(List *func_options,
+parse_func_options(ParseState *pstate, List *func_options,
bool *handler_given, Oid *fdwhandler,
bool *validator_given, Oid *fdwvalidator)
{
ListCell *cell;
+ DefElem *def;
*handler_given = false;
*validator_given = false;
@@ -529,23 +530,19 @@ parse_func_options(List *func_options,
foreach(cell, func_options)
{
- DefElem *def = (DefElem *) lfirst(cell);
+ def = (DefElem *) lfirst(cell);
if (strcmp(def->defname, "handler") == 0)
{
if (*handler_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(def, pstate);
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
else if (strcmp(def->defname, "validator") == 0)
{
if (*validator_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(def, pstate);
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
@@ -559,7 +556,7 @@ parse_func_options(List *func_options,
* Create a foreign-data wrapper
*/
ObjectAddress
-CreateForeignDataWrapper(CreateFdwStmt *stmt)
+CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt)
{
Relation rel;
Datum values[Natts_pg_foreign_data_wrapper];
@@ -611,7 +608,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
/* Lookup handler and validator functions, if given */
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
@@ -675,7 +672,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
* Alter foreign-data wrapper
*/
ObjectAddress
-AlterForeignDataWrapper(AlterFdwStmt *stmt)
+AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt)
{
Relation rel;
HeapTuple tp;
@@ -717,7 +714,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
memset(repl_null, false, sizeof(repl_null));
memset(repl_repl, false, sizeof(repl_repl));
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 736d04780a..c3ca5cdfac 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -523,7 +523,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*volatility_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*volatility_item = defel;
}
@@ -532,14 +532,14 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*strict_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*strict_item = defel;
}
else if (strcmp(defel->defname, "security") == 0)
{
if (*security_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*security_item = defel;
}
@@ -548,7 +548,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*leakproof_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*leakproof_item = defel;
}
@@ -561,7 +561,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*cost_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*cost_item = defel;
}
@@ -570,7 +570,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*rows_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*rows_item = defel;
}
@@ -579,7 +579,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*support_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*support_item = defel;
}
@@ -588,7 +588,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*parallel_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*parallel_item = defel;
}
@@ -598,13 +598,6 @@ compute_common_attribute(ParseState *pstate,
/* Recognized an option */
return true;
-duplicate_error:
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
- return false; /* keep compiler quiet */
-
procedure_error:
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -757,45 +750,34 @@ compute_function_attributes(ParseState *pstate,
DefElem *rows_item = NULL;
DefElem *support_item = NULL;
DefElem *parallel_item = NULL;
+ DefElem *defel;
foreach(option, options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
language_item = defel;
}
else if (strcmp(defel->defname, "transform") == 0)
{
if (transform_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
transform_item = defel;
}
else if (strcmp(defel->defname, "window") == 0)
{
if (windowfunc_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
if (is_procedure)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -2070,12 +2052,13 @@ IsThereFunctionInNamespace(const char *proname, int pronargs,
* See at ExecuteCallStmt() about the atomic argument.
*/
void
-ExecuteDoStmt(DoStmt *stmt, bool atomic)
+ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
{
InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
ListCell *arg;
DefElem *as_item = NULL;
DefElem *language_item = NULL;
+ DefElem *defel;
char *language;
Oid laninline;
HeapTuple languageTuple;
@@ -2084,22 +2067,18 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
/* Process options we got from gram.y */
foreach(arg, stmt->args)
{
- DefElem *defel = (DefElem *) lfirst(arg);
+ defel = (DefElem *) lfirst(arg);
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
language_item = defel;
}
else
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 95c253c8e0..93ad657c02 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -55,13 +55,15 @@ static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
static void
-parse_publication_options(List *options,
+parse_publication_options(ParseState *pstate,
+ List *options,
bool *publish_given,
PublicationActions *pubactions,
bool *publish_via_partition_root_given,
bool *publish_via_partition_root)
{
ListCell *lc;
+ DefElem *defel;
*publish_given = false;
*publish_via_partition_root_given = false;
@@ -76,7 +78,7 @@ parse_publication_options(List *options,
/* Parse options */
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "publish") == 0)
{
@@ -85,9 +87,7 @@ parse_publication_options(List *options,
ListCell *lc;
if (*publish_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/*
* If publish option was given only the explicitly listed actions
@@ -128,9 +128,7 @@ parse_publication_options(List *options,
else if (strcmp(defel->defname, "publish_via_partition_root") == 0)
{
if (*publish_via_partition_root_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
@@ -145,7 +143,7 @@ parse_publication_options(List *options,
* Create new publication.
*/
ObjectAddress
-CreatePublication(CreatePublicationStmt *stmt)
+CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
{
Relation rel;
ObjectAddress myself;
@@ -192,7 +190,8 @@ CreatePublication(CreatePublicationStmt *stmt)
DirectFunctionCall1(namein, CStringGetDatum(stmt->pubname));
values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId());
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -256,8 +255,8 @@ CreatePublication(CreatePublicationStmt *stmt)
* Change options of a publication.
*/
static void
-AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
- HeapTuple tup)
+AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
+ Relation rel, HeapTuple tup)
{
bool nulls[Natts_pg_publication];
bool replaces[Natts_pg_publication];
@@ -269,7 +268,8 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
ObjectAddress obj;
Form_pg_publication pubform;
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -434,7 +434,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
* AlterPublicationTables.
*/
void
-AlterPublication(AlterPublicationStmt *stmt)
+AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
{
Relation rel;
HeapTuple tup;
@@ -459,7 +459,7 @@ AlterPublication(AlterPublicationStmt *stmt)
stmt->pubname);
if (stmt->options)
- AlterPublicationOptions(stmt, rel, tup);
+ AlterPublicationOptions(pstate, stmt, rel, tup);
else
AlterPublicationTables(stmt, rel, tup);
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 0415df9ccb..155d332e43 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1247,6 +1247,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
DefElem *min_value = NULL;
DefElem *cache_value = NULL;
DefElem *is_cycled = NULL;
+ DefElem *defel;
ListCell *option;
bool reset_max_value = false;
bool reset_min_value = false;
@@ -1256,95 +1257,68 @@ init_params(ParseState *pstate, List *options, bool for_identity,
foreach(option, options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "as") == 0)
{
if (as_type)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
as_type = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "increment") == 0)
{
if (increment_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
increment_by = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "start") == 0)
{
if (start_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
start_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "restart") == 0)
{
if (restart_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
restart_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "maxvalue") == 0)
{
if (max_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
max_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "minvalue") == 0)
{
if (min_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
min_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cache") == 0)
{
if (cache_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
cache_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cycle") == 0)
{
if (is_cycled)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
is_cycled = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "owned_by") == 0)
{
if (*owned_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
*owned_by = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "sequence_name") == 0)
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index eb88d877a5..e064b90e3a 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -96,7 +96,8 @@ static void ReportSlotConnectionError(List *rstates, Oid subid, char *slotname,
* Caller is expected to have cleared 'opts'.
*/
static void
-parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *opts)
+parse_subscription_options(ParseState *pstate, List *stmt_options,
+ bits32 supported_opts, SubOpts *opts)
{
ListCell *lc;
@@ -133,9 +134,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "connect") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_CONNECT))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_CONNECT;
opts->connect = defGetBoolean(defel);
@@ -144,9 +143,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "enabled") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_ENABLED))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_ENABLED;
opts->enabled = defGetBoolean(defel);
@@ -155,9 +152,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "create_slot") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_CREATE_SLOT))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_CREATE_SLOT;
opts->create_slot = defGetBoolean(defel);
@@ -166,9 +161,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "slot_name") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_SLOT_NAME))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_SLOT_NAME;
opts->slot_name = defGetString(defel);
@@ -181,9 +174,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "copy_data") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_COPY_DATA))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_COPY_DATA;
opts->copy_data = defGetBoolean(defel);
@@ -192,9 +183,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "synchronous_commit") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_SYNCHRONOUS_COMMIT))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_SYNCHRONOUS_COMMIT;
opts->synchronous_commit = defGetString(defel);
@@ -208,9 +197,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "refresh") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_REFRESH))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_REFRESH;
opts->refresh = defGetBoolean(defel);
@@ -219,9 +206,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "binary") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_BINARY))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_BINARY;
opts->binary = defGetBoolean(defel);
@@ -230,9 +215,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "streaming") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_STREAMING))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_STREAMING;
opts->streaming = defGetBoolean(defel);
@@ -362,7 +345,8 @@ publicationListToArray(List *publist)
* Create new subscription.
*/
ObjectAddress
-CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
+CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -386,7 +370,7 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
SUBOPT_SLOT_NAME | SUBOPT_COPY_DATA |
SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
SUBOPT_STREAMING);
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options, supported_opts, &opts);
/*
* Since creating a replication slot is not transactional, rolling back
@@ -778,7 +762,8 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data)
* Alter the existing subscription.
*/
ObjectAddress
-AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
+AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -831,7 +816,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
SUBOPT_STREAMING);
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ supported_opts, &opts);
if (IsSet(opts.specified_opts, SUBOPT_SLOT_NAME))
{
@@ -876,7 +862,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
case ALTER_SUBSCRIPTION_ENABLED:
{
- parse_subscription_options(stmt->options, SUBOPT_ENABLED, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ SUBOPT_ENABLED, &opts);
Assert(IsSet(opts.specified_opts, SUBOPT_ENABLED));
if (!sub->slotname && opts.enabled)
@@ -910,7 +897,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
case ALTER_SUBSCRIPTION_SET_PUBLICATION:
{
supported_opts = SUBOPT_COPY_DATA | SUBOPT_REFRESH;
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ supported_opts, &opts);
values[Anum_pg_subscription_subpublications - 1] =
publicationListToArray(stmt->publication);
@@ -948,7 +936,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
if (isadd)
supported_opts |= SUBOPT_COPY_DATA;
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ supported_opts, &opts);
publist = merge_publications(sub->publications, stmt->publication, isadd, stmt->subname);
values[Anum_pg_subscription_subpublications - 1] =
@@ -984,7 +973,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions")));
- parse_subscription_options(stmt->options, SUBOPT_COPY_DATA, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ SUBOPT_COPY_DATA, &opts);
PreventInTransactionBlock(isTopLevel, "ALTER SUBSCRIPTION ... REFRESH");
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 97a9725df7..b3717d110e 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7494,9 +7494,7 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmod
if (strcmp(defel->defname, "generated") == 0)
{
if (generatedEl)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 58ec65c6af..c65d6d4c32 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -330,10 +330,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
continue;
}
if (*defelp != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
*defelp = defel;
}
@@ -1336,7 +1333,7 @@ checkEnumOwner(HeapTuple tup)
* and users might have queries with that same assumption.
*/
ObjectAddress
-DefineRange(CreateRangeStmt *stmt)
+DefineRange(ParseState *pstate, CreateRangeStmt *stmt)
{
char *typeName;
Oid typeNamespace;
@@ -1366,6 +1363,7 @@ DefineRange(CreateRangeStmt *stmt)
ObjectAddress address;
ObjectAddress mltrngaddress PG_USED_FOR_ASSERTS_ONLY;
Oid castFuncOid;
+ DefElem *defel;
/* Convert list of names to a name and namespace */
typeNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
@@ -1406,55 +1404,43 @@ DefineRange(CreateRangeStmt *stmt)
/* Extract the parameters from the parameter list */
foreach(lc, stmt->params)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "subtype") == 0)
{
if (OidIsValid(rangeSubtype))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
else if (strcmp(defel->defname, "subtype_opclass") == 0)
{
if (rangeSubOpclassName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
{
if (rangeCollationName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
{
if (rangeCanonicalName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
{
if (rangeSubtypeDiffName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
{
if (multirangeTypeName != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 65bb733958..5045ae3daf 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -27,6 +27,7 @@
#include "catalog/pg_db_role_setting.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/seclabel.h"
#include "commands/user.h"
#include "libpq/crypt.h"
@@ -106,6 +107,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
DefElem *dadminmembers = NULL;
DefElem *dvalidUntil = NULL;
DefElem *dbypassRLS = NULL;
+ DefElem *defel;
/* The defaults can vary depending on the original statement type */
switch (stmt->stmt_type)
@@ -123,15 +125,12 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dpassword = defel;
}
else if (strcmp(defel->defname, "sysid") == 0)
@@ -142,109 +141,73 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "addroleto") == 0)
{
if (daddroleto)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
daddroleto = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
drolemembers = defel;
}
else if (strcmp(defel->defname, "adminmembers") == 0)
{
if (dadminmembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dadminmembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dbypassRLS = defel;
}
else
@@ -528,7 +491,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
* "ALTER ROLE role ROLE rolenames", we don't document it.
*/
Oid
-AlterRole(AlterRoleStmt *stmt)
+AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
{
Datum new_record[Natts_pg_authid];
bool new_record_nulls[Natts_pg_authid];
@@ -564,6 +527,7 @@ AlterRole(AlterRoleStmt *stmt)
DefElem *drolemembers = NULL;
DefElem *dvalidUntil = NULL;
DefElem *dbypassRLS = NULL;
+ DefElem *defel;
Oid roleid;
check_rolespec_name(stmt->role,
@@ -572,95 +536,73 @@ AlterRole(AlterRoleStmt *stmt)
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
stmt->action != 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dbypassRLS = defel;
}
else
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 81d3e7990c..9bf0c9ad53 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -392,9 +392,7 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (strcmp(defel->defname, "sequence_name") == 0)
{
if (nameEl)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index abd5217ab1..e6becc7a17 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -162,6 +162,7 @@ static void
parse_output_parameters(List *options, PGOutputData *data)
{
ListCell *lc;
+ DefElem *defel;
bool protocol_version_given = false;
bool publication_names_given = false;
bool binary_option_given = false;
@@ -174,7 +175,7 @@ parse_output_parameters(List *options, PGOutputData *data)
foreach(lc, options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
Assert(defel->arg == NULL || IsA(defel->arg, String));
@@ -184,9 +185,7 @@ parse_output_parameters(List *options, PGOutputData *data)
int64 parsed;
if (protocol_version_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -205,9 +204,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "publication_names") == 0)
{
if (publication_names_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -219,9 +216,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "binary") == 0)
{
if (binary_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -229,9 +224,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "messages") == 0)
{
if (messages_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -239,9 +232,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "streaming") == 0)
{
if (streaming_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
streaming_given = true;
data->streaming = defGetBoolean(defel);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 92c755f346..3ca75f6fec 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -870,18 +870,17 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
bool snapshot_action_given = false;
bool reserve_wal_given = false;
bool two_phase_given = false;
+ DefElem *defel;
/* Parse options */
foreach(lc, cmd->options)
{
- DefElem *defel = (DefElem *) lfirst(lc);
+ defel = (DefElem *) lfirst(lc);
if (strcmp(defel->defname, "export_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
snapshot_action_given = true;
*snapshot_action = defGetBoolean(defel) ? CRS_EXPORT_SNAPSHOT :
@@ -890,9 +889,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else if (strcmp(defel->defname, "use_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
snapshot_action_given = true;
*snapshot_action = CRS_USE_SNAPSHOT;
@@ -900,9 +897,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else if (strcmp(defel->defname, "reserve_wal") == 0)
{
if (reserve_wal_given || cmd->kind != REPLICATION_KIND_PHYSICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
reserve_wal_given = true;
*reserve_wal = true;
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 7a2da9dab4..27fbf1f3aa 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -708,7 +708,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
break;
case T_DoStmt:
- ExecuteDoStmt((DoStmt *) parsetree, isAtomicContext);
+ ExecuteDoStmt(pstate, (DoStmt *) parsetree, isAtomicContext);
break;
case T_CreateTableSpaceStmt:
@@ -888,7 +888,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
case T_AlterRoleStmt:
/* no event triggers for global objects */
- AlterRole((AlterRoleStmt *) parsetree);
+ AlterRole(pstate, (AlterRoleStmt *) parsetree);
break;
case T_AlterRoleSetStmt:
@@ -1552,11 +1552,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateFdwStmt:
- address = CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
+ address = CreateForeignDataWrapper(pstate, (CreateFdwStmt *) parsetree);
break;
case T_AlterFdwStmt:
- address = AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
+ address = AlterForeignDataWrapper(pstate, (AlterFdwStmt *) parsetree);
break;
case T_CreateForeignServerStmt:
@@ -1601,7 +1601,7 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
- address = DefineRange((CreateRangeStmt *) parsetree);
+ address = DefineRange(pstate, (CreateRangeStmt *) parsetree);
break;
case T_AlterEnumStmt: /* ALTER TYPE (enum) */
@@ -1802,11 +1802,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreatePublicationStmt:
- address = CreatePublication((CreatePublicationStmt *) parsetree);
+ address = CreatePublication(pstate, (CreatePublicationStmt *) parsetree);
break;
case T_AlterPublicationStmt:
- AlterPublication((AlterPublicationStmt *) parsetree);
+ AlterPublication(pstate, (AlterPublicationStmt *) parsetree);
/*
* AlterPublication calls EventTriggerCollectSimpleCommand
@@ -1816,12 +1816,14 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateSubscriptionStmt:
- address = CreateSubscription((CreateSubscriptionStmt *) parsetree,
+ address = CreateSubscription(pstate,
+ (CreateSubscriptionStmt *) parsetree,
isTopLevel);
break;
case T_AlterSubscriptionStmt:
- address = AlterSubscription((AlterSubscriptionStmt *) parsetree,
+ address = AlterSubscription(pstate,
+ (AlterSubscriptionStmt *) parsetree,
isTopLevel);
break;
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 42bf1c7519..0791444682 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -56,7 +56,7 @@ extern ObjectAddress CreateCast(CreateCastStmt *stmt);
extern ObjectAddress CreateTransform(CreateTransformStmt *stmt);
extern void IsThereFunctionInNamespace(const char *proname, int pronargs,
oidvector *proargtypes, Oid nspOid);
-extern void ExecuteDoStmt(DoStmt *stmt, bool atomic);
+extern void ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic);
extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest);
extern TupleDesc CallStmtResultDesc(CallStmt *stmt);
extern Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok);
@@ -121,8 +121,8 @@ extern ObjectAddress AlterForeignServerOwner(const char *name, Oid newOwnerId);
extern void AlterForeignServerOwner_oid(Oid, Oid newOwnerId);
extern ObjectAddress AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId);
extern void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId);
-extern ObjectAddress CreateForeignDataWrapper(CreateFdwStmt *stmt);
-extern ObjectAddress AlterForeignDataWrapper(AlterFdwStmt *stmt);
+extern ObjectAddress CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt);
+extern ObjectAddress AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt);
extern ObjectAddress CreateForeignServer(CreateForeignServerStmt *stmt);
extern ObjectAddress AlterForeignServer(AlterForeignServerStmt *stmt);
extern ObjectAddress CreateUserMapping(CreateUserMappingStmt *stmt);
@@ -154,4 +154,14 @@ extern TypeName *defGetTypeName(DefElem *def);
extern int defGetTypeLength(DefElem *def);
extern List *defGetStringList(DefElem *def);
+static inline void
+pg_attribute_noreturn()
+ReportDuplicateOptionError(DefElem *defel, ParseState *pstate)
+{
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ pstate ? parser_errposition(pstate, defel->location) : 0);
+}
+
#endif /* DEFREM_H */
diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h
index 00e2e626e6..efea01f2a9 100644
--- a/src/include/commands/publicationcmds.h
+++ b/src/include/commands/publicationcmds.h
@@ -18,8 +18,8 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreatePublication(CreatePublicationStmt *stmt);
-extern void AlterPublication(AlterPublicationStmt *stmt);
+extern ObjectAddress CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt);
+extern void AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt);
extern void RemovePublicationRelById(Oid proid);
extern ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/subscriptioncmds.h b/src/include/commands/subscriptioncmds.h
index 3b926f35d7..8bf25ee66c 100644
--- a/src/include/commands/subscriptioncmds.h
+++ b/src/include/commands/subscriptioncmds.h
@@ -18,9 +18,9 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreateSubscription(CreateSubscriptionStmt *stmt,
+extern ObjectAddress CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
bool isTopLevel);
-extern ObjectAddress AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel);
+extern ObjectAddress AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, bool isTopLevel);
extern void DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel);
extern ObjectAddress AlterSubscriptionOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
index 880679127b..d5e22811d0 100644
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -25,7 +25,7 @@ extern ObjectAddress DefineType(ParseState *pstate, List *names, List *parameter
extern void RemoveTypeById(Oid typeOid);
extern ObjectAddress DefineDomain(CreateDomainStmt *stmt);
extern ObjectAddress DefineEnum(CreateEnumStmt *stmt);
-extern ObjectAddress DefineRange(CreateRangeStmt *stmt);
+extern ObjectAddress DefineRange(ParseState *pstate, CreateRangeStmt *stmt);
extern ObjectAddress AlterEnum(AlterEnumStmt *stmt);
extern ObjectAddress DefineCompositeType(RangeVar *typevar, List *coldeflist);
extern Oid AssignTypeArrayOid(void);
diff --git a/src/include/commands/user.h b/src/include/commands/user.h
index 028e0dde56..0b7a3cd65f 100644
--- a/src/include/commands/user.h
+++ b/src/include/commands/user.h
@@ -25,7 +25,7 @@ typedef void (*check_password_hook_type) (const char *username, const char *shad
extern PGDLLIMPORT check_password_hook_type check_password_hook;
extern Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt);
-extern Oid AlterRole(AlterRoleStmt *stmt);
+extern Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt);
extern Oid AlterRoleSet(AlterRoleSetStmt *stmt);
extern void DropRole(DropRoleStmt *stmt);
extern void GrantRole(GrantRoleStmt *stmt);
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c64f0719e7..92fe8a121a 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -30,31 +30,31 @@ COPY x (xyz) from stdin;
ERROR: column "xyz" of relation "x" does not exist
-- redundant options
COPY x from stdin (format CSV, FORMAT CSV);
-ERROR: conflicting or redundant options
+ERROR: option "format" specified more than once
LINE 1: COPY x from stdin (format CSV, FORMAT CSV);
^
COPY x from stdin (freeze off, freeze on);
-ERROR: conflicting or redundant options
+ERROR: option "freeze" specified more than once
LINE 1: COPY x from stdin (freeze off, freeze on);
^
COPY x from stdin (delimiter ',', delimiter ',');
-ERROR: conflicting or redundant options
+ERROR: option "delimiter" specified more than once
LINE 1: COPY x from stdin (delimiter ',', delimiter ',');
^
COPY x from stdin (null ' ', null ' ');
-ERROR: conflicting or redundant options
+ERROR: option "null" specified more than once
LINE 1: COPY x from stdin (null ' ', null ' ');
^
COPY x from stdin (header off, header on);
-ERROR: conflicting or redundant options
+ERROR: option "header" specified more than once
LINE 1: COPY x from stdin (header off, header on);
^
COPY x from stdin (quote ':', quote ':');
-ERROR: conflicting or redundant options
+ERROR: option "quote" specified more than once
LINE 1: COPY x from stdin (quote ':', quote ':');
^
COPY x from stdin (escape ':', escape ':');
-ERROR: conflicting or redundant options
+ERROR: option "escape" specified more than once
LINE 1: COPY x from stdin (escape ':', escape ':');
^
COPY x from stdin (force_quote (a), force_quote *);
@@ -62,17 +62,19 @@ ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (force_quote (a), force_quote *);
^
COPY x from stdin (force_not_null (a), force_not_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_not_null" specified more than once
LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
COPY x from stdin (force_null (a), force_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_null" specified more than once
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
-ERROR: conflicting or redundant options
+ERROR: option "convert_selectively" specified more than once
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
^
COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
-ERROR: conflicting or redundant options
+ERROR: option "encoding" specified more than once
LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
^
-- too many columns in column list: should fail
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 5385f98a0f..03d6eca747 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -94,7 +94,9 @@ CREATE FUNCTION invalid_fdw_handler() RETURNS int LANGUAGE SQL AS 'SELECT 1;';
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...GN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER in...
+ ^
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -200,7 +202,9 @@ ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo;
ALTER FOREIGN DATA WRAPPER foo HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER an...
+ ^
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 63d6ab7a4e..0f5cbe2e99 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -26,7 +26,9 @@ ERROR: unrecognized publication parameter: "foo"
CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
-ERROR: conflicting or redundant options
+ERROR: option "publish_via_partition_root" specified more than once
+LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi...
+ ^
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
--
2.25.1
On 6 Jul 2021, at 17:08, vignesh C <vignesh21@gmail.com> wrote:
The patch was not applying on the head because of the recent commit
"8aafb02616753f5c6c90bbc567636b73c0cbb9d4", attached patch which is
rebased on HEAD.
I sort of like the visual cue of seeing ereport(ERROR .. since it makes it
clear it will break execution then and there, this will require a lookup for
anyone who don't know the function by heart. That being said, reducing
duplicated boilerplate has clear value and this reduce the risk of introducing
strings which are complicated to translate. On the whole I think this is a net
win, and the patch looks pretty good.
- DefElem *defel = (DefElem *) lfirst(option);
+ defel = (DefElem *) lfirst(option);
Any particular reason to include this in the patch?
--
Daniel Gustafsson https://vmware.com/
On Thu, Jul 8, 2021 at 1:52 AM Daniel Gustafsson <daniel@yesql.se> wrote:
On 6 Jul 2021, at 17:08, vignesh C <vignesh21@gmail.com> wrote:
The patch was not applying on the head because of the recent commit
"8aafb02616753f5c6c90bbc567636b73c0cbb9d4", attached patch which is
rebased on HEAD.I sort of like the visual cue of seeing ereport(ERROR .. since it makes it
clear it will break execution then and there, this will require a lookup for
anyone who don't know the function by heart. That being said, reducing
duplicated boilerplate has clear value and this reduce the risk of introducing
strings which are complicated to translate. On the whole I think this is a net
win, and the patch looks pretty good.- DefElem *defel = (DefElem *) lfirst(option); + defel = (DefElem *) lfirst(option); Any particular reason to include this in the patch?
Thanks for identifying this, this change is not needed, this was
required in my previous solution based on goto label. As we have made
these changes into a common function. This change is not required,
Attached v9 patch which removes these changes.
Regards,
Vignesh
Attachments:
v9-0001-Enhance-error-message-to-include-option-name-in-c.patchapplication/x-patch; name=v9-0001-Enhance-error-message-to-include-option-name-in-c.patchDownload
From a9935ebd58596772f2fdb7b641e90cfee071d98b Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Tue, 6 Jul 2021 20:22:45 +0530
Subject: [PATCH v9] Enhance error message to include option name in case of
duplicate option error.
Enhanced error message to include option name in case of duplication
option error, so that the user can easily identify the error.
---
contrib/file_fdw/file_fdw.c | 10 +-
src/backend/catalog/aclchk.c | 11 +-
src/backend/commands/copy.c | 54 ++--------
src/backend/commands/dbcommands.c | 70 +++---------
src/backend/commands/extension.c | 20 +---
src/backend/commands/foreigncmds.c | 18 ++--
src/backend/commands/functioncmds.c | 53 +++------
src/backend/commands/publicationcmds.c | 27 +++--
src/backend/commands/sequence.c | 45 ++------
src/backend/commands/subscriptioncmds.c | 62 +++++------
src/backend/commands/tablecmds.c | 4 +-
src/backend/commands/typecmds.c | 31 ++----
src/backend/commands/user.c | 112 +++++---------------
src/backend/parser/parse_utilcmd.c | 4 +-
src/backend/replication/pgoutput/pgoutput.c | 20 +---
src/backend/replication/walsender.c | 12 +--
src/backend/tcop/utility.c | 20 ++--
src/include/commands/defrem.h | 16 ++-
src/include/commands/publicationcmds.h | 4 +-
src/include/commands/subscriptioncmds.h | 4 +-
src/include/commands/typecmds.h | 2 +-
src/include/commands/user.h | 2 +-
src/test/regress/expected/copy2.out | 24 +++--
src/test/regress/expected/foreign_data.out | 8 +-
src/test/regress/expected/publication.out | 4 +-
25 files changed, 200 insertions(+), 437 deletions(-)
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 2c2f149fb0..0014a4d49d 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -290,10 +290,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_not_null") == 0)
{
if (force_not_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_not_null\" supplied more than once for a column.")));
+ ReportDuplicateOptionError(def, NULL);
force_not_null = def;
/* Don't care what the value is, as long as it's a legal boolean */
(void) defGetBoolean(def);
@@ -302,10 +299,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_null") == 0)
{
if (force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_null\" supplied more than once for a column.")));
+ ReportDuplicateOptionError(def, NULL);
force_null = def;
(void) defGetBoolean(def);
}
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 53392414f1..2968085916 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -59,6 +59,7 @@
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
#include "commands/proclang.h"
@@ -921,19 +922,13 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
if (strcmp(defel->defname, "schemas") == 0)
{
if (dnspnames)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dnspnames = defel;
}
else if (strcmp(defel->defname, "roles") == 0)
{
if (drolespecs)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
drolespecs = defel;
}
else
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 8265b981eb..5c7a3952d8 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -357,10 +357,7 @@ ProcessCopyOptions(ParseState *pstate,
char *fmt = defGetString(defel);
if (format_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
format_specified = true;
if (strcmp(fmt, "text") == 0)
/* default format */ ;
@@ -377,57 +374,39 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "freeze") == 0)
{
if (freeze_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
freeze_specified = true;
opts_out->freeze = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "delimiter") == 0)
{
if (opts_out->delim)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->delim = defGetString(defel);
}
else if (strcmp(defel->defname, "null") == 0)
{
if (opts_out->null_print)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->null_print = defGetString(defel);
}
else if (strcmp(defel->defname, "header") == 0)
{
if (header_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
header_specified = true;
opts_out->header_line = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "quote") == 0)
{
if (opts_out->quote)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->quote = defGetString(defel);
}
else if (strcmp(defel->defname, "escape") == 0)
{
if (opts_out->escape)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->escape = defGetString(defel);
}
else if (strcmp(defel->defname, "force_quote") == 0)
@@ -451,10 +430,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_not_null") == 0)
{
if (opts_out->force_notnull)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
if (defel->arg && IsA(defel->arg, List))
opts_out->force_notnull = castNode(List, defel->arg);
else
@@ -467,9 +443,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_null") == 0)
{
if (opts_out->force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
@@ -487,10 +461,7 @@ ProcessCopyOptions(ParseState *pstate,
* allowed for the column list to be NIL.
*/
if (opts_out->convert_selectively)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->convert_selectively = true;
if (defel->arg == NULL || IsA(defel->arg, List))
opts_out->convert_select = castNode(List, defel->arg);
@@ -504,10 +475,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "encoding") == 0)
{
if (opts_out->file_encoding >= 0)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
if (opts_out->file_encoding < 0)
ereport(ERROR,
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 2b159b60eb..fc22a195c4 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -152,91 +152,61 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespacename)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtablespacename = defel;
}
else if (strcmp(defel->defname, "owner") == 0)
{
if (downer)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
downer = defel;
}
else if (strcmp(defel->defname, "template") == 0)
{
if (dtemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtemplate = defel;
}
else if (strcmp(defel->defname, "encoding") == 0)
{
if (dencoding)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dencoding = defel;
}
else if (strcmp(defel->defname, "locale") == 0)
{
if (dlocale)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dlocale = defel;
}
else if (strcmp(defel->defname, "lc_collate") == 0)
{
if (dcollate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcollate = defel;
}
else if (strcmp(defel->defname, "lc_ctype") == 0)
{
if (dctype)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dctype = defel;
}
else if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "location") == 0)
@@ -1497,37 +1467,25 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespace)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dtablespace = defel;
}
else
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 41857feda9..6cdc8e76c8 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1731,30 +1731,21 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
if (strcmp(defel->defname, "schema") == 0)
{
if (d_schema)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_schema = defel;
schemaName = defGetString(d_schema);
}
else if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_new_version = defel;
versionName = defGetString(d_new_version);
}
else if (strcmp(defel->defname, "cascade") == 0)
{
if (d_cascade)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_cascade = defel;
cascade = defGetBoolean(d_cascade);
}
@@ -3051,10 +3042,7 @@ ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
d_new_version = defel;
}
else
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index bc36311d38..2d01ad4113 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -515,7 +515,7 @@ lookup_fdw_validator_func(DefElem *validator)
* Process function options of CREATE/ALTER FDW
*/
static void
-parse_func_options(List *func_options,
+parse_func_options(ParseState *pstate, List *func_options,
bool *handler_given, Oid *fdwhandler,
bool *validator_given, Oid *fdwvalidator)
{
@@ -534,18 +534,14 @@ parse_func_options(List *func_options,
if (strcmp(def->defname, "handler") == 0)
{
if (*handler_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(def, pstate);
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
else if (strcmp(def->defname, "validator") == 0)
{
if (*validator_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(def, pstate);
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
@@ -559,7 +555,7 @@ parse_func_options(List *func_options,
* Create a foreign-data wrapper
*/
ObjectAddress
-CreateForeignDataWrapper(CreateFdwStmt *stmt)
+CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt)
{
Relation rel;
Datum values[Natts_pg_foreign_data_wrapper];
@@ -611,7 +607,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
/* Lookup handler and validator functions, if given */
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
@@ -675,7 +671,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
* Alter foreign-data wrapper
*/
ObjectAddress
-AlterForeignDataWrapper(AlterFdwStmt *stmt)
+AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt)
{
Relation rel;
HeapTuple tp;
@@ -717,7 +713,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
memset(repl_null, false, sizeof(repl_null));
memset(repl_repl, false, sizeof(repl_repl));
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 736d04780a..f56801c5d0 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -523,7 +523,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*volatility_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*volatility_item = defel;
}
@@ -532,14 +532,14 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*strict_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*strict_item = defel;
}
else if (strcmp(defel->defname, "security") == 0)
{
if (*security_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*security_item = defel;
}
@@ -548,7 +548,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*leakproof_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*leakproof_item = defel;
}
@@ -561,7 +561,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*cost_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*cost_item = defel;
}
@@ -570,7 +570,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*rows_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*rows_item = defel;
}
@@ -579,7 +579,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*support_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*support_item = defel;
}
@@ -588,7 +588,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*parallel_item)
- goto duplicate_error;
+ ReportDuplicateOptionError(defel, pstate);
*parallel_item = defel;
}
@@ -598,13 +598,6 @@ compute_common_attribute(ParseState *pstate,
/* Recognized an option */
return true;
-duplicate_error:
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
- return false; /* keep compiler quiet */
-
procedure_error:
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -765,37 +758,25 @@ compute_function_attributes(ParseState *pstate,
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
language_item = defel;
}
else if (strcmp(defel->defname, "transform") == 0)
{
if (transform_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
transform_item = defel;
}
else if (strcmp(defel->defname, "window") == 0)
{
if (windowfunc_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
if (is_procedure)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -2070,7 +2051,7 @@ IsThereFunctionInNamespace(const char *proname, int pronargs,
* See at ExecuteCallStmt() about the atomic argument.
*/
void
-ExecuteDoStmt(DoStmt *stmt, bool atomic)
+ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
{
InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
ListCell *arg;
@@ -2089,17 +2070,13 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
language_item = defel;
}
else
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 95c253c8e0..c3667cca66 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -55,7 +55,8 @@ static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
static void
-parse_publication_options(List *options,
+parse_publication_options(ParseState *pstate,
+ List *options,
bool *publish_given,
PublicationActions *pubactions,
bool *publish_via_partition_root_given,
@@ -85,9 +86,7 @@ parse_publication_options(List *options,
ListCell *lc;
if (*publish_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/*
* If publish option was given only the explicitly listed actions
@@ -128,9 +127,7 @@ parse_publication_options(List *options,
else if (strcmp(defel->defname, "publish_via_partition_root") == 0)
{
if (*publish_via_partition_root_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
@@ -145,7 +142,7 @@ parse_publication_options(List *options,
* Create new publication.
*/
ObjectAddress
-CreatePublication(CreatePublicationStmt *stmt)
+CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
{
Relation rel;
ObjectAddress myself;
@@ -192,7 +189,8 @@ CreatePublication(CreatePublicationStmt *stmt)
DirectFunctionCall1(namein, CStringGetDatum(stmt->pubname));
values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId());
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -256,8 +254,8 @@ CreatePublication(CreatePublicationStmt *stmt)
* Change options of a publication.
*/
static void
-AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
- HeapTuple tup)
+AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
+ Relation rel, HeapTuple tup)
{
bool nulls[Natts_pg_publication];
bool replaces[Natts_pg_publication];
@@ -269,7 +267,8 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
ObjectAddress obj;
Form_pg_publication pubform;
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -434,7 +433,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
* AlterPublicationTables.
*/
void
-AlterPublication(AlterPublicationStmt *stmt)
+AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
{
Relation rel;
HeapTuple tup;
@@ -459,7 +458,7 @@ AlterPublication(AlterPublicationStmt *stmt)
stmt->pubname);
if (stmt->options)
- AlterPublicationOptions(stmt, rel, tup);
+ AlterPublicationOptions(pstate, stmt, rel, tup);
else
AlterPublicationTables(stmt, rel, tup);
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index e3f9f6d53d..67e27d666d 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1261,90 +1261,63 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (strcmp(defel->defname, "as") == 0)
{
if (as_type)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
as_type = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "increment") == 0)
{
if (increment_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
increment_by = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "start") == 0)
{
if (start_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
start_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "restart") == 0)
{
if (restart_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
restart_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "maxvalue") == 0)
{
if (max_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
max_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "minvalue") == 0)
{
if (min_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
min_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cache") == 0)
{
if (cache_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
cache_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cycle") == 0)
{
if (is_cycled)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
is_cycled = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "owned_by") == 0)
{
if (*owned_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
*owned_by = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "sequence_name") == 0)
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index eb88d877a5..e064b90e3a 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -96,7 +96,8 @@ static void ReportSlotConnectionError(List *rstates, Oid subid, char *slotname,
* Caller is expected to have cleared 'opts'.
*/
static void
-parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *opts)
+parse_subscription_options(ParseState *pstate, List *stmt_options,
+ bits32 supported_opts, SubOpts *opts)
{
ListCell *lc;
@@ -133,9 +134,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "connect") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_CONNECT))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_CONNECT;
opts->connect = defGetBoolean(defel);
@@ -144,9 +143,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "enabled") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_ENABLED))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_ENABLED;
opts->enabled = defGetBoolean(defel);
@@ -155,9 +152,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "create_slot") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_CREATE_SLOT))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_CREATE_SLOT;
opts->create_slot = defGetBoolean(defel);
@@ -166,9 +161,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "slot_name") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_SLOT_NAME))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_SLOT_NAME;
opts->slot_name = defGetString(defel);
@@ -181,9 +174,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "copy_data") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_COPY_DATA))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_COPY_DATA;
opts->copy_data = defGetBoolean(defel);
@@ -192,9 +183,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "synchronous_commit") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_SYNCHRONOUS_COMMIT))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_SYNCHRONOUS_COMMIT;
opts->synchronous_commit = defGetString(defel);
@@ -208,9 +197,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "refresh") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_REFRESH))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_REFRESH;
opts->refresh = defGetBoolean(defel);
@@ -219,9 +206,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "binary") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_BINARY))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_BINARY;
opts->binary = defGetBoolean(defel);
@@ -230,9 +215,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "streaming") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_STREAMING))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
opts->specified_opts |= SUBOPT_STREAMING;
opts->streaming = defGetBoolean(defel);
@@ -362,7 +345,8 @@ publicationListToArray(List *publist)
* Create new subscription.
*/
ObjectAddress
-CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
+CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -386,7 +370,7 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
SUBOPT_SLOT_NAME | SUBOPT_COPY_DATA |
SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
SUBOPT_STREAMING);
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options, supported_opts, &opts);
/*
* Since creating a replication slot is not transactional, rolling back
@@ -778,7 +762,8 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data)
* Alter the existing subscription.
*/
ObjectAddress
-AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
+AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -831,7 +816,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
SUBOPT_STREAMING);
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ supported_opts, &opts);
if (IsSet(opts.specified_opts, SUBOPT_SLOT_NAME))
{
@@ -876,7 +862,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
case ALTER_SUBSCRIPTION_ENABLED:
{
- parse_subscription_options(stmt->options, SUBOPT_ENABLED, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ SUBOPT_ENABLED, &opts);
Assert(IsSet(opts.specified_opts, SUBOPT_ENABLED));
if (!sub->slotname && opts.enabled)
@@ -910,7 +897,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
case ALTER_SUBSCRIPTION_SET_PUBLICATION:
{
supported_opts = SUBOPT_COPY_DATA | SUBOPT_REFRESH;
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ supported_opts, &opts);
values[Anum_pg_subscription_subpublications - 1] =
publicationListToArray(stmt->publication);
@@ -948,7 +936,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
if (isadd)
supported_opts |= SUBOPT_COPY_DATA;
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ supported_opts, &opts);
publist = merge_publications(sub->publications, stmt->publication, isadd, stmt->subname);
values[Anum_pg_subscription_subpublications - 1] =
@@ -984,7 +973,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions")));
- parse_subscription_options(stmt->options, SUBOPT_COPY_DATA, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ SUBOPT_COPY_DATA, &opts);
PreventInTransactionBlock(isTopLevel, "ALTER SUBSCRIPTION ... REFRESH");
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 03dfd2e7fa..d0613bb37e 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7587,9 +7587,7 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmod
if (strcmp(defel->defname, "generated") == 0)
{
if (generatedEl)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 58ec65c6af..b7ef44e73f 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -330,10 +330,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
continue;
}
if (*defelp != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
*defelp = defel;
}
@@ -1336,7 +1333,7 @@ checkEnumOwner(HeapTuple tup)
* and users might have queries with that same assumption.
*/
ObjectAddress
-DefineRange(CreateRangeStmt *stmt)
+DefineRange(ParseState *pstate, CreateRangeStmt *stmt)
{
char *typeName;
Oid typeNamespace;
@@ -1411,50 +1408,38 @@ DefineRange(CreateRangeStmt *stmt)
if (strcmp(defel->defname, "subtype") == 0)
{
if (OidIsValid(rangeSubtype))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
else if (strcmp(defel->defname, "subtype_opclass") == 0)
{
if (rangeSubOpclassName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
{
if (rangeCollationName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
{
if (rangeCanonicalName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
{
if (rangeSubtypeDiffName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
{
if (multirangeTypeName != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 65bb733958..84e8a46a6e 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -27,6 +27,7 @@
#include "catalog/pg_db_role_setting.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/seclabel.h"
#include "commands/user.h"
#include "libpq/crypt.h"
@@ -128,10 +129,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dpassword = defel;
}
else if (strcmp(defel->defname, "sysid") == 0)
@@ -142,109 +140,73 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "addroleto") == 0)
{
if (daddroleto)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
daddroleto = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
drolemembers = defel;
}
else if (strcmp(defel->defname, "adminmembers") == 0)
{
if (dadminmembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dadminmembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ ReportDuplicateOptionError(defel, pstate);
dbypassRLS = defel;
}
else
@@ -528,7 +490,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
* "ALTER ROLE role ROLE rolenames", we don't document it.
*/
Oid
-AlterRole(AlterRoleStmt *stmt)
+AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
{
Datum new_record[Natts_pg_authid];
bool new_record_nulls[Natts_pg_authid];
@@ -577,90 +539,68 @@ AlterRole(AlterRoleStmt *stmt)
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
stmt->action != 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, pstate);
dbypassRLS = defel;
}
else
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 3afcd6b511..f3f54a6417 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -392,9 +392,7 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (strcmp(defel->defname, "sequence_name") == 0)
{
if (nameEl)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index abd5217ab1..f670a1b3f0 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -184,9 +184,7 @@ parse_output_parameters(List *options, PGOutputData *data)
int64 parsed;
if (protocol_version_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -205,9 +203,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "publication_names") == 0)
{
if (publication_names_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -219,9 +215,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "binary") == 0)
{
if (binary_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -229,9 +223,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "messages") == 0)
{
if (messages_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -239,9 +231,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "streaming") == 0)
{
if (streaming_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
streaming_given = true;
data->streaming = defGetBoolean(defel);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 92c755f346..1291f1cd3e 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -879,9 +879,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
if (strcmp(defel->defname, "export_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
snapshot_action_given = true;
*snapshot_action = defGetBoolean(defel) ? CRS_EXPORT_SNAPSHOT :
@@ -890,9 +888,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else if (strcmp(defel->defname, "use_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
snapshot_action_given = true;
*snapshot_action = CRS_USE_SNAPSHOT;
@@ -900,9 +896,7 @@ parseCreateReplSlotOptions(CreateReplicationSlotCmd *cmd,
else if (strcmp(defel->defname, "reserve_wal") == 0)
{
if (reserve_wal_given || cmd->kind != REPLICATION_KIND_PHYSICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ ReportDuplicateOptionError(defel, NULL);
reserve_wal_given = true;
*reserve_wal = true;
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 7a2da9dab4..27fbf1f3aa 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -708,7 +708,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
break;
case T_DoStmt:
- ExecuteDoStmt((DoStmt *) parsetree, isAtomicContext);
+ ExecuteDoStmt(pstate, (DoStmt *) parsetree, isAtomicContext);
break;
case T_CreateTableSpaceStmt:
@@ -888,7 +888,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
case T_AlterRoleStmt:
/* no event triggers for global objects */
- AlterRole((AlterRoleStmt *) parsetree);
+ AlterRole(pstate, (AlterRoleStmt *) parsetree);
break;
case T_AlterRoleSetStmt:
@@ -1552,11 +1552,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateFdwStmt:
- address = CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
+ address = CreateForeignDataWrapper(pstate, (CreateFdwStmt *) parsetree);
break;
case T_AlterFdwStmt:
- address = AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
+ address = AlterForeignDataWrapper(pstate, (AlterFdwStmt *) parsetree);
break;
case T_CreateForeignServerStmt:
@@ -1601,7 +1601,7 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
- address = DefineRange((CreateRangeStmt *) parsetree);
+ address = DefineRange(pstate, (CreateRangeStmt *) parsetree);
break;
case T_AlterEnumStmt: /* ALTER TYPE (enum) */
@@ -1802,11 +1802,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreatePublicationStmt:
- address = CreatePublication((CreatePublicationStmt *) parsetree);
+ address = CreatePublication(pstate, (CreatePublicationStmt *) parsetree);
break;
case T_AlterPublicationStmt:
- AlterPublication((AlterPublicationStmt *) parsetree);
+ AlterPublication(pstate, (AlterPublicationStmt *) parsetree);
/*
* AlterPublication calls EventTriggerCollectSimpleCommand
@@ -1816,12 +1816,14 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateSubscriptionStmt:
- address = CreateSubscription((CreateSubscriptionStmt *) parsetree,
+ address = CreateSubscription(pstate,
+ (CreateSubscriptionStmt *) parsetree,
isTopLevel);
break;
case T_AlterSubscriptionStmt:
- address = AlterSubscription((AlterSubscriptionStmt *) parsetree,
+ address = AlterSubscription(pstate,
+ (AlterSubscriptionStmt *) parsetree,
isTopLevel);
break;
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 42bf1c7519..0791444682 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -56,7 +56,7 @@ extern ObjectAddress CreateCast(CreateCastStmt *stmt);
extern ObjectAddress CreateTransform(CreateTransformStmt *stmt);
extern void IsThereFunctionInNamespace(const char *proname, int pronargs,
oidvector *proargtypes, Oid nspOid);
-extern void ExecuteDoStmt(DoStmt *stmt, bool atomic);
+extern void ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic);
extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest);
extern TupleDesc CallStmtResultDesc(CallStmt *stmt);
extern Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok);
@@ -121,8 +121,8 @@ extern ObjectAddress AlterForeignServerOwner(const char *name, Oid newOwnerId);
extern void AlterForeignServerOwner_oid(Oid, Oid newOwnerId);
extern ObjectAddress AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId);
extern void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId);
-extern ObjectAddress CreateForeignDataWrapper(CreateFdwStmt *stmt);
-extern ObjectAddress AlterForeignDataWrapper(AlterFdwStmt *stmt);
+extern ObjectAddress CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt);
+extern ObjectAddress AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt);
extern ObjectAddress CreateForeignServer(CreateForeignServerStmt *stmt);
extern ObjectAddress AlterForeignServer(AlterForeignServerStmt *stmt);
extern ObjectAddress CreateUserMapping(CreateUserMappingStmt *stmt);
@@ -154,4 +154,14 @@ extern TypeName *defGetTypeName(DefElem *def);
extern int defGetTypeLength(DefElem *def);
extern List *defGetStringList(DefElem *def);
+static inline void
+pg_attribute_noreturn()
+ReportDuplicateOptionError(DefElem *defel, ParseState *pstate)
+{
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ pstate ? parser_errposition(pstate, defel->location) : 0);
+}
+
#endif /* DEFREM_H */
diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h
index 00e2e626e6..efea01f2a9 100644
--- a/src/include/commands/publicationcmds.h
+++ b/src/include/commands/publicationcmds.h
@@ -18,8 +18,8 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreatePublication(CreatePublicationStmt *stmt);
-extern void AlterPublication(AlterPublicationStmt *stmt);
+extern ObjectAddress CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt);
+extern void AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt);
extern void RemovePublicationRelById(Oid proid);
extern ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/subscriptioncmds.h b/src/include/commands/subscriptioncmds.h
index 3b926f35d7..8bf25ee66c 100644
--- a/src/include/commands/subscriptioncmds.h
+++ b/src/include/commands/subscriptioncmds.h
@@ -18,9 +18,9 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreateSubscription(CreateSubscriptionStmt *stmt,
+extern ObjectAddress CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
bool isTopLevel);
-extern ObjectAddress AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel);
+extern ObjectAddress AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, bool isTopLevel);
extern void DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel);
extern ObjectAddress AlterSubscriptionOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
index 880679127b..d5e22811d0 100644
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -25,7 +25,7 @@ extern ObjectAddress DefineType(ParseState *pstate, List *names, List *parameter
extern void RemoveTypeById(Oid typeOid);
extern ObjectAddress DefineDomain(CreateDomainStmt *stmt);
extern ObjectAddress DefineEnum(CreateEnumStmt *stmt);
-extern ObjectAddress DefineRange(CreateRangeStmt *stmt);
+extern ObjectAddress DefineRange(ParseState *pstate, CreateRangeStmt *stmt);
extern ObjectAddress AlterEnum(AlterEnumStmt *stmt);
extern ObjectAddress DefineCompositeType(RangeVar *typevar, List *coldeflist);
extern Oid AssignTypeArrayOid(void);
diff --git a/src/include/commands/user.h b/src/include/commands/user.h
index 028e0dde56..0b7a3cd65f 100644
--- a/src/include/commands/user.h
+++ b/src/include/commands/user.h
@@ -25,7 +25,7 @@ typedef void (*check_password_hook_type) (const char *username, const char *shad
extern PGDLLIMPORT check_password_hook_type check_password_hook;
extern Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt);
-extern Oid AlterRole(AlterRoleStmt *stmt);
+extern Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt);
extern Oid AlterRoleSet(AlterRoleSetStmt *stmt);
extern void DropRole(DropRoleStmt *stmt);
extern void GrantRole(GrantRoleStmt *stmt);
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c64f0719e7..92fe8a121a 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -30,31 +30,31 @@ COPY x (xyz) from stdin;
ERROR: column "xyz" of relation "x" does not exist
-- redundant options
COPY x from stdin (format CSV, FORMAT CSV);
-ERROR: conflicting or redundant options
+ERROR: option "format" specified more than once
LINE 1: COPY x from stdin (format CSV, FORMAT CSV);
^
COPY x from stdin (freeze off, freeze on);
-ERROR: conflicting or redundant options
+ERROR: option "freeze" specified more than once
LINE 1: COPY x from stdin (freeze off, freeze on);
^
COPY x from stdin (delimiter ',', delimiter ',');
-ERROR: conflicting or redundant options
+ERROR: option "delimiter" specified more than once
LINE 1: COPY x from stdin (delimiter ',', delimiter ',');
^
COPY x from stdin (null ' ', null ' ');
-ERROR: conflicting or redundant options
+ERROR: option "null" specified more than once
LINE 1: COPY x from stdin (null ' ', null ' ');
^
COPY x from stdin (header off, header on);
-ERROR: conflicting or redundant options
+ERROR: option "header" specified more than once
LINE 1: COPY x from stdin (header off, header on);
^
COPY x from stdin (quote ':', quote ':');
-ERROR: conflicting or redundant options
+ERROR: option "quote" specified more than once
LINE 1: COPY x from stdin (quote ':', quote ':');
^
COPY x from stdin (escape ':', escape ':');
-ERROR: conflicting or redundant options
+ERROR: option "escape" specified more than once
LINE 1: COPY x from stdin (escape ':', escape ':');
^
COPY x from stdin (force_quote (a), force_quote *);
@@ -62,17 +62,19 @@ ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (force_quote (a), force_quote *);
^
COPY x from stdin (force_not_null (a), force_not_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_not_null" specified more than once
LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
COPY x from stdin (force_null (a), force_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_null" specified more than once
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
-ERROR: conflicting or redundant options
+ERROR: option "convert_selectively" specified more than once
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
^
COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
-ERROR: conflicting or redundant options
+ERROR: option "encoding" specified more than once
LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
^
-- too many columns in column list: should fail
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 809d40a79a..7d39d2a4d5 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -94,7 +94,9 @@ CREATE FUNCTION invalid_fdw_handler() RETURNS int LANGUAGE SQL AS 'SELECT 1;';
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...GN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER in...
+ ^
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -200,7 +202,9 @@ ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo;
ALTER FOREIGN DATA WRAPPER foo HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER an...
+ ^
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 63d6ab7a4e..0f5cbe2e99 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -26,7 +26,9 @@ ERROR: unrecognized publication parameter: "foo"
CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
-ERROR: conflicting or redundant options
+ERROR: option "publish_via_partition_root" specified more than once
+LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi...
+ ^
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
--
2.25.1
On Thu, 8 Jul 2021 at 14:40, vignesh C <vignesh21@gmail.com> wrote:
On Thu, Jul 8, 2021 at 1:52 AM Daniel Gustafsson <daniel@yesql.se> wrote:
I sort of like the visual cue of seeing ereport(ERROR .. since it makes it
clear it will break execution then and there, this will require a lookup for
anyone who don't know the function by heart. That being said, reducing
duplicated boilerplate has clear value and this reduce the risk of introducing
strings which are complicated to translate. On the whole I think this is a net
win, and the patch looks pretty good.
Bikeshedding the function name, there are several similar examples in
the existing code, but the closest analogs are probably
errorMissingColumn() and errorMissingRTE(). So I think
errorConflictingDefElem() would be better, since it's slightly more
obviously an error.
Also, I don't think this function should be marked inline -- using a
normal function ought to help make the compiled code smaller.
A bigger problem is that the patch replaces about 100 instances of the
error "conflicting or redundant options" with "option \"%s\" specified
more than once", but that's not always the appropriate thing to do.
For example, in the walsender code, the error isn't necessarily due to
the option being specified more than once.
Also, there are cases where def->defname isn't actually the name of
the option specified, so including it in the error is misleading. For
example:
CREATE OR REPLACE FUNCTION foo() RETURNS int
AS $$ SELECT 1 $$ STABLE IMMUTABLE;
ERROR: option "volatility" specified more than once
LINE 2: AS $$ SELECT 1 $$ STABLE IMMUTABLE;
^
and in this case "volatility" is an internal string, so it won't get translated.
I'm inclined to think that it isn't worth the effort trying to
distinguish between conflicting options, options specified more than
once and faked-up options that weren't really specified. If we just
make errorConflictingDefElem() report "conflicting or redundant
options", then it's much easier to update calling code without making
mistakes. The benefit then comes from the reduced code size and the
fact that the patch includes pstate in more places, so the
parser_errposition() indicator helps the user identify the problem.
In file_fdw_validator(), where there is no pstate, it's already using
"specified more than once" as a hint to clarify the "conflicting or
redundant options" error, so I think we should leave that alone.
Regards,
Dean
On Sat, 10 Jul 2021 at 11:44, Dean Rasheed <dean.a.rasheed@gmail.com> wrote:
I'm inclined to think that it isn't worth the effort trying to
distinguish between conflicting options, options specified more than
once and faked-up options that weren't really specified. If we just
make errorConflictingDefElem() report "conflicting or redundant
options", then it's much easier to update calling code without making
mistakes. The benefit then comes from the reduced code size and the
fact that the patch includes pstate in more places, so the
parser_errposition() indicator helps the user identify the problem.In file_fdw_validator(), where there is no pstate, it's already using
"specified more than once" as a hint to clarify the "conflicting or
redundant options" error, so I think we should leave that alone.
Another possibility would be to pass the option list to
errorConflictingDefElem() and it could work out whether or not to
include the "option \%s\" specified more than once" hint, since that
hint probably is useful, and working out whether to include it is
probably less error-prone if it's done there.
Regards,
Dean
On Sat, Jul 10, 2021 at 4:14 PM Dean Rasheed <dean.a.rasheed@gmail.com> wrote:
On Thu, 8 Jul 2021 at 14:40, vignesh C <vignesh21@gmail.com> wrote:
On Thu, Jul 8, 2021 at 1:52 AM Daniel Gustafsson <daniel@yesql.se> wrote:
I sort of like the visual cue of seeing ereport(ERROR .. since it makes it
clear it will break execution then and there, this will require a lookup for
anyone who don't know the function by heart. That being said, reducing
duplicated boilerplate has clear value and this reduce the risk of introducing
strings which are complicated to translate. On the whole I think this is a net
win, and the patch looks pretty good.Bikeshedding the function name, there are several similar examples in
the existing code, but the closest analogs are probably
errorMissingColumn() and errorMissingRTE(). So I think
errorConflictingDefElem() would be better, since it's slightly more
obviously an error.
Ok, I will change it to keep it similar.
Also, I don't think this function should be marked inline -- using a
normal function ought to help make the compiled code smaller.
inline instructs the compiler to attempt to embed the function content
into the calling code instead of executing an actual call. I think we
should keep it inline to reduce the function call.
A bigger problem is that the patch replaces about 100 instances of the
error "conflicting or redundant options" with "option \"%s\" specified
more than once", but that's not always the appropriate thing to do.
For example, in the walsender code, the error isn't necessarily due to
the option being specified more than once.
This patch intended to change "conflicting or redundant options" to
"option \"%s\" specified more than once" only in case that error is
for option specified more than once. This change is not required. I
will remove it.
Also, there are cases where def->defname isn't actually the name of
the option specified, so including it in the error is misleading. For
example:CREATE OR REPLACE FUNCTION foo() RETURNS int
AS $$ SELECT 1 $$ STABLE IMMUTABLE;ERROR: option "volatility" specified more than once
LINE 2: AS $$ SELECT 1 $$ STABLE IMMUTABLE;
^and in this case "volatility" is an internal string, so it won't get translated.
I'm inclined to think that it isn't worth the effort trying to
distinguish between conflicting options, options specified more than
once and faked-up options that weren't really specified. If we just
make errorConflictingDefElem() report "conflicting or redundant
options", then it's much easier to update calling code without making
mistakes. The benefit then comes from the reduced code size and the
fact that the patch includes pstate in more places, so the
parser_errposition() indicator helps the user identify the problem.In file_fdw_validator(), where there is no pstate, it's already using
"specified more than once" as a hint to clarify the "conflicting or
redundant options" error, so I think we should leave that alone.
This patch intended to change "conflicting or redundant options" to
"option \"%s\" specified more than once" only in case that error is
for option specified more than once. Thanks for pointing out a few
places where the actual error "conflicting or redundant options"
should be left as it is. I will post a new patch which will remove the
conflicting options error scenarios, which were not targeted in this
patch.
Regards,
Vignesh
On Sat, Jul 10, 2021 at 4:31 PM Dean Rasheed <dean.a.rasheed@gmail.com> wrote:
On Sat, 10 Jul 2021 at 11:44, Dean Rasheed <dean.a.rasheed@gmail.com> wrote:
I'm inclined to think that it isn't worth the effort trying to
distinguish between conflicting options, options specified more than
once and faked-up options that weren't really specified. If we just
make errorConflictingDefElem() report "conflicting or redundant
options", then it's much easier to update calling code without making
mistakes. The benefit then comes from the reduced code size and the
fact that the patch includes pstate in more places, so the
parser_errposition() indicator helps the user identify the problem.In file_fdw_validator(), where there is no pstate, it's already using
"specified more than once" as a hint to clarify the "conflicting or
redundant options" error, so I think we should leave that alone.Another possibility would be to pass the option list to
errorConflictingDefElem() and it could work out whether or not to
include the "option \%s\" specified more than once" hint, since that
hint probably is useful, and working out whether to include it is
probably less error-prone if it's done there.
I'm planning to handle conflicting errors separately after this
current work is done, once the patch is changed to have just the valid
scenarios(removing the scenarios you have pointed out) existing
function can work as is without any changes. Thoughts?
Regards,
Vignesh
On Sat, 10 Jul 2021 at 17:03, vignesh C <vignesh21@gmail.com> wrote:
Also, I don't think this function should be marked inline -- using a
normal function ought to help make the compiled code smaller.inline instructs the compiler to attempt to embed the function content
into the calling code instead of executing an actual call. I think we
should keep it inline to reduce the function call.
Hmm, I'd say that inline should generally be used sparingly, and only
for small functions that are called very often, to avoid the function
call overhead, and generate a faster and possibly smaller executable.
(Though I think sometimes it can still be faster if the executable is
larger.)
In this case, it's a function that is only called under error
conditions, so it's not commonly called, and we don't care so much
about performance when we're about to throw an error.
Also, if you look at an ereport() such as
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options"),
parser_errposition(pstate, defel->location)));
This is a macro that's actually expanded into 5 separate function calls:
- errstart() / errstart_cold()
- errcode()
- errmsg()
- parser_errposition()
- errfinish()
so it's a non-trivial amount of code. Whereas, if it's not inlined, it
becomes just one function call at each call-site, making for smaller,
faster code in the typical case where an error is not being raised.
Of course, it's possible the compiler might still decide to inline the
function, if it thinks that's preferable. In some cases, we explicitly
mark this type of function with pg_noinline, to avoid that, and reduce
code bloat where it's used in lots of small, fast functions (see, for
example, float_overflow_error()).
In general though, I think inline and noinline should be reserved for
special cases where they give a clear, measurable benefit, and that in
general it's better to not mark the function and just let the compiler
decide.
Regards,
Dean
On Sat, 10 Jul 2021 at 18:09, vignesh C <vignesh21@gmail.com> wrote:
I'm planning to handle conflicting errors separately after this
current work is done, once the patch is changed to have just the valid
scenarios(removing the scenarios you have pointed out) existing
function can work as is without any changes. Thoughts?
Ah OK, that might be reasonable. Perhaps, then errorDuplicateDefElem()
and errorConflictingDefElem() would be better than what I originally
suggested.
BTW, another case I spotted was this:
copy (select 1) to stdout csv csv header;
ERROR: option "format" specified more than once
LINE 1: copy (select 1) to stdout csv csv header;
^
which isn't good because there is no option called "format".
Regards,
Dean
.On Sun, Jul 11, 2021 at 2:57 PM Dean Rasheed <dean.a.rasheed@gmail.com> wrote:
On Sat, 10 Jul 2021 at 17:03, vignesh C <vignesh21@gmail.com> wrote:
Also, I don't think this function should be marked inline -- using a
normal function ought to help make the compiled code smaller.inline instructs the compiler to attempt to embed the function content
into the calling code instead of executing an actual call. I think we
should keep it inline to reduce the function call.Hmm, I'd say that inline should generally be used sparingly, and only
for small functions that are called very often, to avoid the function
call overhead, and generate a faster and possibly smaller executable.
(Though I think sometimes it can still be faster if the executable is
larger.)In this case, it's a function that is only called under error
conditions, so it's not commonly called, and we don't care so much
about performance when we're about to throw an error.Also, if you look at an ereport() such as
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options"),
parser_errposition(pstate, defel->location)));This is a macro that's actually expanded into 5 separate function calls:
- errstart() / errstart_cold()
- errcode()
- errmsg()
- parser_errposition()
- errfinish()so it's a non-trivial amount of code. Whereas, if it's not inlined, it
becomes just one function call at each call-site, making for smaller,
faster code in the typical case where an error is not being raised.Of course, it's possible the compiler might still decide to inline the
function, if it thinks that's preferable. In some cases, we explicitly
mark this type of function with pg_noinline, to avoid that, and reduce
code bloat where it's used in lots of small, fast functions (see, for
example, float_overflow_error()).In general though, I think inline and noinline should be reserved for
special cases where they give a clear, measurable benefit, and that in
general it's better to not mark the function and just let the compiler
decide.
Ok, that makes sense. As this flow is mainly in the error part it is
ok. I will change it.
Regards,
Vignesh
On Sun, Jul 11, 2021 at 3:23 PM Dean Rasheed <dean.a.rasheed@gmail.com> wrote:
On Sat, 10 Jul 2021 at 18:09, vignesh C <vignesh21@gmail.com> wrote:
I'm planning to handle conflicting errors separately after this
current work is done, once the patch is changed to have just the valid
scenarios(removing the scenarios you have pointed out) existing
function can work as is without any changes. Thoughts?Ah OK, that might be reasonable. Perhaps, then errorDuplicateDefElem()
and errorConflictingDefElem() would be better than what I originally
suggested.BTW, another case I spotted was this:
copy (select 1) to stdout csv csv header;
ERROR: option "format" specified more than once
LINE 1: copy (select 1) to stdout csv csv header;
^
Thanks for your comments, I have made the changes for the same in the
V10 patch attached.
Thoughts?
Regards,
Vignesh
Attachments:
v10-0001-Enhance-error-message-to-include-option-name-in-.patchapplication/x-patch; name=v10-0001-Enhance-error-message-to-include-option-name-in-.patchDownload
From c882bd3f8ebc7a8a21b8481234286aa8e2c9aee1 Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Mon, 12 Jul 2021 09:12:34 +0530
Subject: [PATCH v10] Enhance error message to include option name in case of
duplicate option error.
Enhanced error message to include option name in case of duplication
option error, so that the user can easily identify the error.
---
contrib/file_fdw/file_fdw.c | 10 +-
src/backend/catalog/aclchk.c | 11 +-
src/backend/commands/copy.c | 54 ++--------
src/backend/commands/dbcommands.c | 70 +++---------
src/backend/commands/define.c | 20 ++++
src/backend/commands/extension.c | 20 +---
src/backend/commands/foreigncmds.c | 18 ++--
src/backend/commands/functioncmds.c | 53 +++------
src/backend/commands/publicationcmds.c | 27 +++--
src/backend/commands/sequence.c | 45 ++------
src/backend/commands/subscriptioncmds.c | 62 +++++------
src/backend/commands/tablecmds.c | 4 +-
src/backend/commands/typecmds.c | 31 ++----
src/backend/commands/user.c | 112 +++++---------------
src/backend/parser/parse_utilcmd.c | 4 +-
src/backend/replication/pgoutput/pgoutput.c | 20 +---
src/backend/tcop/utility.c | 20 ++--
src/include/commands/defrem.h | 8 +-
src/include/commands/publicationcmds.h | 4 +-
src/include/commands/subscriptioncmds.h | 4 +-
src/include/commands/typecmds.h | 2 +-
src/include/commands/user.h | 2 +-
src/test/regress/expected/copy2.out | 24 +++--
src/test/regress/expected/foreign_data.out | 8 +-
src/test/regress/expected/publication.out | 4 +-
25 files changed, 209 insertions(+), 428 deletions(-)
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 2c2f149fb0..eb7edb695b 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -290,10 +290,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_not_null") == 0)
{
if (force_not_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_not_null\" supplied more than once for a column.")));
+ errorDuplicateDefElem(def, NULL);
force_not_null = def;
/* Don't care what the value is, as long as it's a legal boolean */
(void) defGetBoolean(def);
@@ -302,10 +299,7 @@ file_fdw_validator(PG_FUNCTION_ARGS)
else if (strcmp(def->defname, "force_null") == 0)
{
if (force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- errhint("Option \"force_null\" supplied more than once for a column.")));
+ errorDuplicateDefElem(def, NULL);
force_null = def;
(void) defGetBoolean(def);
}
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 53392414f1..c5b9f3cf70 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -59,6 +59,7 @@
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
#include "commands/proclang.h"
@@ -921,19 +922,13 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
if (strcmp(defel->defname, "schemas") == 0)
{
if (dnspnames)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dnspnames = defel;
}
else if (strcmp(defel->defname, "roles") == 0)
{
if (drolespecs)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
drolespecs = defel;
}
else
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 8265b981eb..f13a9fa6d7 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -357,10 +357,7 @@ ProcessCopyOptions(ParseState *pstate,
char *fmt = defGetString(defel);
if (format_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorRedundantDefElem(defel, pstate);
format_specified = true;
if (strcmp(fmt, "text") == 0)
/* default format */ ;
@@ -377,57 +374,39 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "freeze") == 0)
{
if (freeze_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
freeze_specified = true;
opts_out->freeze = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "delimiter") == 0)
{
if (opts_out->delim)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
opts_out->delim = defGetString(defel);
}
else if (strcmp(defel->defname, "null") == 0)
{
if (opts_out->null_print)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
opts_out->null_print = defGetString(defel);
}
else if (strcmp(defel->defname, "header") == 0)
{
if (header_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
header_specified = true;
opts_out->header_line = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "quote") == 0)
{
if (opts_out->quote)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
opts_out->quote = defGetString(defel);
}
else if (strcmp(defel->defname, "escape") == 0)
{
if (opts_out->escape)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
opts_out->escape = defGetString(defel);
}
else if (strcmp(defel->defname, "force_quote") == 0)
@@ -451,10 +430,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_not_null") == 0)
{
if (opts_out->force_notnull)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
if (defel->arg && IsA(defel->arg, List))
opts_out->force_notnull = castNode(List, defel->arg);
else
@@ -467,9 +443,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_null") == 0)
{
if (opts_out->force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
@@ -487,10 +461,7 @@ ProcessCopyOptions(ParseState *pstate,
* allowed for the column list to be NIL.
*/
if (opts_out->convert_selectively)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
opts_out->convert_selectively = true;
if (defel->arg == NULL || IsA(defel->arg, List))
opts_out->convert_select = castNode(List, defel->arg);
@@ -504,10 +475,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "encoding") == 0)
{
if (opts_out->file_encoding >= 0)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
if (opts_out->file_encoding < 0)
ereport(ERROR,
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 2b159b60eb..c2ae4de776 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -152,91 +152,61 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespacename)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dtablespacename = defel;
}
else if (strcmp(defel->defname, "owner") == 0)
{
if (downer)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
downer = defel;
}
else if (strcmp(defel->defname, "template") == 0)
{
if (dtemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dtemplate = defel;
}
else if (strcmp(defel->defname, "encoding") == 0)
{
if (dencoding)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dencoding = defel;
}
else if (strcmp(defel->defname, "locale") == 0)
{
if (dlocale)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dlocale = defel;
}
else if (strcmp(defel->defname, "lc_collate") == 0)
{
if (dcollate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dcollate = defel;
}
else if (strcmp(defel->defname, "lc_ctype") == 0)
{
if (dctype)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dctype = defel;
}
else if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "location") == 0)
@@ -1497,37 +1467,25 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespace)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dtablespace = defel;
}
else
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
index 84487b7d4b..7804326f2b 100644
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -347,3 +347,23 @@ defGetStringList(DefElem *def)
return (List *) def->arg;
}
+
+void
+pg_attribute_noreturn()
+errorDuplicateDefElem(DefElem *defel, ParseState *pstate)
+{
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option \"%s\" specified more than once", defel->defname),
+ pstate ? parser_errposition(pstate, defel->location) : 0);
+}
+
+void
+pg_attribute_noreturn()
+errorRedundantDefElem(DefElem *defel, ParseState *pstate)
+{
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("redundant options specified"),
+ pstate ? parser_errposition(pstate, defel->location) : 0);
+}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index b37009bfec..77764e2457 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1731,30 +1731,21 @@ CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
if (strcmp(defel->defname, "schema") == 0)
{
if (d_schema)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
d_schema = defel;
schemaName = defGetString(d_schema);
}
else if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
d_new_version = defel;
versionName = defGetString(d_new_version);
}
else if (strcmp(defel->defname, "cascade") == 0)
{
if (d_cascade)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
d_cascade = defel;
cascade = defGetBoolean(d_cascade);
}
@@ -3051,10 +3042,7 @@ ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
d_new_version = defel;
}
else
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index bc36311d38..0cb4a02811 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -515,7 +515,7 @@ lookup_fdw_validator_func(DefElem *validator)
* Process function options of CREATE/ALTER FDW
*/
static void
-parse_func_options(List *func_options,
+parse_func_options(ParseState *pstate, List *func_options,
bool *handler_given, Oid *fdwhandler,
bool *validator_given, Oid *fdwvalidator)
{
@@ -534,18 +534,14 @@ parse_func_options(List *func_options,
if (strcmp(def->defname, "handler") == 0)
{
if (*handler_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(def, pstate);
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
else if (strcmp(def->defname, "validator") == 0)
{
if (*validator_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(def, pstate);
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
@@ -559,7 +555,7 @@ parse_func_options(List *func_options,
* Create a foreign-data wrapper
*/
ObjectAddress
-CreateForeignDataWrapper(CreateFdwStmt *stmt)
+CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt)
{
Relation rel;
Datum values[Natts_pg_foreign_data_wrapper];
@@ -611,7 +607,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
/* Lookup handler and validator functions, if given */
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
@@ -675,7 +671,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
* Alter foreign-data wrapper
*/
ObjectAddress
-AlterForeignDataWrapper(AlterFdwStmt *stmt)
+AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt)
{
Relation rel;
HeapTuple tp;
@@ -717,7 +713,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
memset(repl_null, false, sizeof(repl_null));
memset(repl_repl, false, sizeof(repl_repl));
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 736d04780a..194bf4772b 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -523,7 +523,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*volatility_item)
- goto duplicate_error;
+ errorRedundantDefElem(defel, pstate);
*volatility_item = defel;
}
@@ -532,14 +532,14 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*strict_item)
- goto duplicate_error;
+ errorRedundantDefElem(defel, pstate);
*strict_item = defel;
}
else if (strcmp(defel->defname, "security") == 0)
{
if (*security_item)
- goto duplicate_error;
+ errorRedundantDefElem(defel, pstate);
*security_item = defel;
}
@@ -548,7 +548,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*leakproof_item)
- goto duplicate_error;
+ errorRedundantDefElem(defel, pstate);
*leakproof_item = defel;
}
@@ -561,7 +561,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*cost_item)
- goto duplicate_error;
+ errorRedundantDefElem(defel, pstate);
*cost_item = defel;
}
@@ -570,7 +570,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*rows_item)
- goto duplicate_error;
+ errorRedundantDefElem(defel, pstate);
*rows_item = defel;
}
@@ -579,7 +579,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*support_item)
- goto duplicate_error;
+ errorRedundantDefElem(defel, pstate);
*support_item = defel;
}
@@ -588,7 +588,7 @@ compute_common_attribute(ParseState *pstate,
if (is_procedure)
goto procedure_error;
if (*parallel_item)
- goto duplicate_error;
+ errorRedundantDefElem(defel, pstate);
*parallel_item = defel;
}
@@ -598,13 +598,6 @@ compute_common_attribute(ParseState *pstate,
/* Recognized an option */
return true;
-duplicate_error:
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
- return false; /* keep compiler quiet */
-
procedure_error:
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -765,37 +758,25 @@ compute_function_attributes(ParseState *pstate,
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorRedundantDefElem(defel, pstate);
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorRedundantDefElem(defel, pstate);
language_item = defel;
}
else if (strcmp(defel->defname, "transform") == 0)
{
if (transform_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorRedundantDefElem(defel, pstate);
transform_item = defel;
}
else if (strcmp(defel->defname, "window") == 0)
{
if (windowfunc_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorRedundantDefElem(defel, pstate);
if (is_procedure)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -2070,7 +2051,7 @@ IsThereFunctionInNamespace(const char *proname, int pronargs,
* See at ExecuteCallStmt() about the atomic argument.
*/
void
-ExecuteDoStmt(DoStmt *stmt, bool atomic)
+ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
{
InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
ListCell *arg;
@@ -2089,17 +2070,13 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorRedundantDefElem(defel, pstate);
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorRedundantDefElem(defel, pstate);
language_item = defel;
}
else
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 95c253c8e0..89398c5ccd 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -55,7 +55,8 @@ static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
static void
-parse_publication_options(List *options,
+parse_publication_options(ParseState *pstate,
+ List *options,
bool *publish_given,
PublicationActions *pubactions,
bool *publish_via_partition_root_given,
@@ -85,9 +86,7 @@ parse_publication_options(List *options,
ListCell *lc;
if (*publish_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
/*
* If publish option was given only the explicitly listed actions
@@ -128,9 +127,7 @@ parse_publication_options(List *options,
else if (strcmp(defel->defname, "publish_via_partition_root") == 0)
{
if (*publish_via_partition_root_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
@@ -145,7 +142,7 @@ parse_publication_options(List *options,
* Create new publication.
*/
ObjectAddress
-CreatePublication(CreatePublicationStmt *stmt)
+CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
{
Relation rel;
ObjectAddress myself;
@@ -192,7 +189,8 @@ CreatePublication(CreatePublicationStmt *stmt)
DirectFunctionCall1(namein, CStringGetDatum(stmt->pubname));
values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId());
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -256,8 +254,8 @@ CreatePublication(CreatePublicationStmt *stmt)
* Change options of a publication.
*/
static void
-AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
- HeapTuple tup)
+AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
+ Relation rel, HeapTuple tup)
{
bool nulls[Natts_pg_publication];
bool replaces[Natts_pg_publication];
@@ -269,7 +267,8 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
ObjectAddress obj;
Form_pg_publication pubform;
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -434,7 +433,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
* AlterPublicationTables.
*/
void
-AlterPublication(AlterPublicationStmt *stmt)
+AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
{
Relation rel;
HeapTuple tup;
@@ -459,7 +458,7 @@ AlterPublication(AlterPublicationStmt *stmt)
stmt->pubname);
if (stmt->options)
- AlterPublicationOptions(stmt, rel, tup);
+ AlterPublicationOptions(pstate, stmt, rel, tup);
else
AlterPublicationTables(stmt, rel, tup);
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index e3f9f6d53d..e987294706 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1261,90 +1261,63 @@ init_params(ParseState *pstate, List *options, bool for_identity,
if (strcmp(defel->defname, "as") == 0)
{
if (as_type)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
as_type = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "increment") == 0)
{
if (increment_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
increment_by = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "start") == 0)
{
if (start_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
start_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "restart") == 0)
{
if (restart_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
restart_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "maxvalue") == 0)
{
if (max_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
max_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "minvalue") == 0)
{
if (min_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
min_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cache") == 0)
{
if (cache_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
cache_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cycle") == 0)
{
if (is_cycled)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
is_cycled = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "owned_by") == 0)
{
if (*owned_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
*owned_by = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "sequence_name") == 0)
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index eb88d877a5..02fd3d6750 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -96,7 +96,8 @@ static void ReportSlotConnectionError(List *rstates, Oid subid, char *slotname,
* Caller is expected to have cleared 'opts'.
*/
static void
-parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *opts)
+parse_subscription_options(ParseState *pstate, List *stmt_options,
+ bits32 supported_opts, SubOpts *opts)
{
ListCell *lc;
@@ -133,9 +134,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "connect") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_CONNECT))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_CONNECT;
opts->connect = defGetBoolean(defel);
@@ -144,9 +143,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "enabled") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_ENABLED))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_ENABLED;
opts->enabled = defGetBoolean(defel);
@@ -155,9 +152,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "create_slot") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_CREATE_SLOT))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_CREATE_SLOT;
opts->create_slot = defGetBoolean(defel);
@@ -166,9 +161,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "slot_name") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_SLOT_NAME))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_SLOT_NAME;
opts->slot_name = defGetString(defel);
@@ -181,9 +174,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "copy_data") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_COPY_DATA))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_COPY_DATA;
opts->copy_data = defGetBoolean(defel);
@@ -192,9 +183,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "synchronous_commit") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_SYNCHRONOUS_COMMIT))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_SYNCHRONOUS_COMMIT;
opts->synchronous_commit = defGetString(defel);
@@ -208,9 +197,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "refresh") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_REFRESH))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_REFRESH;
opts->refresh = defGetBoolean(defel);
@@ -219,9 +206,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "binary") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_BINARY))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_BINARY;
opts->binary = defGetBoolean(defel);
@@ -230,9 +215,7 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
strcmp(defel->defname, "streaming") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_STREAMING))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_STREAMING;
opts->streaming = defGetBoolean(defel);
@@ -362,7 +345,8 @@ publicationListToArray(List *publist)
* Create new subscription.
*/
ObjectAddress
-CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
+CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -386,7 +370,7 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
SUBOPT_SLOT_NAME | SUBOPT_COPY_DATA |
SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
SUBOPT_STREAMING);
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options, supported_opts, &opts);
/*
* Since creating a replication slot is not transactional, rolling back
@@ -778,7 +762,8 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data)
* Alter the existing subscription.
*/
ObjectAddress
-AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
+AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -831,7 +816,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
SUBOPT_STREAMING);
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ supported_opts, &opts);
if (IsSet(opts.specified_opts, SUBOPT_SLOT_NAME))
{
@@ -876,7 +862,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
case ALTER_SUBSCRIPTION_ENABLED:
{
- parse_subscription_options(stmt->options, SUBOPT_ENABLED, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ SUBOPT_ENABLED, &opts);
Assert(IsSet(opts.specified_opts, SUBOPT_ENABLED));
if (!sub->slotname && opts.enabled)
@@ -910,7 +897,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
case ALTER_SUBSCRIPTION_SET_PUBLICATION:
{
supported_opts = SUBOPT_COPY_DATA | SUBOPT_REFRESH;
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ supported_opts, &opts);
values[Anum_pg_subscription_subpublications - 1] =
publicationListToArray(stmt->publication);
@@ -948,7 +936,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
if (isadd)
supported_opts |= SUBOPT_COPY_DATA;
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ supported_opts, &opts);
publist = merge_publications(sub->publications, stmt->publication, isadd, stmt->subname);
values[Anum_pg_subscription_subpublications - 1] =
@@ -984,7 +973,8 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions")));
- parse_subscription_options(stmt->options, SUBOPT_COPY_DATA, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ SUBOPT_COPY_DATA, &opts);
PreventInTransactionBlock(isTopLevel, "ALTER SUBSCRIPTION ... REFRESH");
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 03dfd2e7fa..2bf70cc8ad 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7587,9 +7587,7 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmod
if (strcmp(defel->defname, "generated") == 0)
{
if (generatedEl)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, NULL);
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 58ec65c6af..db20e6dc47 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -330,10 +330,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
continue;
}
if (*defelp != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
*defelp = defel;
}
@@ -1336,7 +1333,7 @@ checkEnumOwner(HeapTuple tup)
* and users might have queries with that same assumption.
*/
ObjectAddress
-DefineRange(CreateRangeStmt *stmt)
+DefineRange(ParseState *pstate, CreateRangeStmt *stmt)
{
char *typeName;
Oid typeNamespace;
@@ -1411,50 +1408,38 @@ DefineRange(CreateRangeStmt *stmt)
if (strcmp(defel->defname, "subtype") == 0)
{
if (OidIsValid(rangeSubtype))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
else if (strcmp(defel->defname, "subtype_opclass") == 0)
{
if (rangeSubOpclassName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
{
if (rangeCollationName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
{
if (rangeCanonicalName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
{
if (rangeSubtypeDiffName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
{
if (multirangeTypeName != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 65bb733958..2a2465531a 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -27,6 +27,7 @@
#include "catalog/pg_db_role_setting.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/seclabel.h"
#include "commands/user.h"
#include "libpq/crypt.h"
@@ -128,10 +129,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dpassword = defel;
}
else if (strcmp(defel->defname, "sysid") == 0)
@@ -142,109 +140,73 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "addroleto") == 0)
{
if (daddroleto)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
daddroleto = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
drolemembers = defel;
}
else if (strcmp(defel->defname, "adminmembers") == 0)
{
if (dadminmembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dadminmembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorDuplicateDefElem(defel, pstate);
dbypassRLS = defel;
}
else
@@ -528,7 +490,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
* "ALTER ROLE role ROLE rolenames", we don't document it.
*/
Oid
-AlterRole(AlterRoleStmt *stmt)
+AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
{
Datum new_record[Natts_pg_authid];
bool new_record_nulls[Natts_pg_authid];
@@ -577,90 +539,68 @@ AlterRole(AlterRoleStmt *stmt)
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
stmt->action != 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, pstate);
dbypassRLS = defel;
}
else
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 3afcd6b511..75cf566dfe 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -392,9 +392,7 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (strcmp(defel->defname, "sequence_name") == 0)
{
if (nameEl)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorRedundantDefElem(defel, NULL);
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index abd5217ab1..3229d5d2c3 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -184,9 +184,7 @@ parse_output_parameters(List *options, PGOutputData *data)
int64 parsed;
if (protocol_version_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, NULL);
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -205,9 +203,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "publication_names") == 0)
{
if (publication_names_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, NULL);
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -219,9 +215,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "binary") == 0)
{
if (binary_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, NULL);
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -229,9 +223,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "messages") == 0)
{
if (messages_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, NULL);
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -239,9 +231,7 @@ parse_output_parameters(List *options, PGOutputData *data)
else if (strcmp(defel->defname, "streaming") == 0)
{
if (streaming_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorDuplicateDefElem(defel, NULL);
streaming_given = true;
data->streaming = defGetBoolean(defel);
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 7a2da9dab4..27fbf1f3aa 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -708,7 +708,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
break;
case T_DoStmt:
- ExecuteDoStmt((DoStmt *) parsetree, isAtomicContext);
+ ExecuteDoStmt(pstate, (DoStmt *) parsetree, isAtomicContext);
break;
case T_CreateTableSpaceStmt:
@@ -888,7 +888,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
case T_AlterRoleStmt:
/* no event triggers for global objects */
- AlterRole((AlterRoleStmt *) parsetree);
+ AlterRole(pstate, (AlterRoleStmt *) parsetree);
break;
case T_AlterRoleSetStmt:
@@ -1552,11 +1552,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateFdwStmt:
- address = CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
+ address = CreateForeignDataWrapper(pstate, (CreateFdwStmt *) parsetree);
break;
case T_AlterFdwStmt:
- address = AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
+ address = AlterForeignDataWrapper(pstate, (AlterFdwStmt *) parsetree);
break;
case T_CreateForeignServerStmt:
@@ -1601,7 +1601,7 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
- address = DefineRange((CreateRangeStmt *) parsetree);
+ address = DefineRange(pstate, (CreateRangeStmt *) parsetree);
break;
case T_AlterEnumStmt: /* ALTER TYPE (enum) */
@@ -1802,11 +1802,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreatePublicationStmt:
- address = CreatePublication((CreatePublicationStmt *) parsetree);
+ address = CreatePublication(pstate, (CreatePublicationStmt *) parsetree);
break;
case T_AlterPublicationStmt:
- AlterPublication((AlterPublicationStmt *) parsetree);
+ AlterPublication(pstate, (AlterPublicationStmt *) parsetree);
/*
* AlterPublication calls EventTriggerCollectSimpleCommand
@@ -1816,12 +1816,14 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateSubscriptionStmt:
- address = CreateSubscription((CreateSubscriptionStmt *) parsetree,
+ address = CreateSubscription(pstate,
+ (CreateSubscriptionStmt *) parsetree,
isTopLevel);
break;
case T_AlterSubscriptionStmt:
- address = AlterSubscription((AlterSubscriptionStmt *) parsetree,
+ address = AlterSubscription(pstate,
+ (AlterSubscriptionStmt *) parsetree,
isTopLevel);
break;
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 42bf1c7519..0a9fc38f17 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -56,7 +56,7 @@ extern ObjectAddress CreateCast(CreateCastStmt *stmt);
extern ObjectAddress CreateTransform(CreateTransformStmt *stmt);
extern void IsThereFunctionInNamespace(const char *proname, int pronargs,
oidvector *proargtypes, Oid nspOid);
-extern void ExecuteDoStmt(DoStmt *stmt, bool atomic);
+extern void ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic);
extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest);
extern TupleDesc CallStmtResultDesc(CallStmt *stmt);
extern Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok);
@@ -121,8 +121,8 @@ extern ObjectAddress AlterForeignServerOwner(const char *name, Oid newOwnerId);
extern void AlterForeignServerOwner_oid(Oid, Oid newOwnerId);
extern ObjectAddress AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId);
extern void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId);
-extern ObjectAddress CreateForeignDataWrapper(CreateFdwStmt *stmt);
-extern ObjectAddress AlterForeignDataWrapper(AlterFdwStmt *stmt);
+extern ObjectAddress CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt);
+extern ObjectAddress AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt);
extern ObjectAddress CreateForeignServer(CreateForeignServerStmt *stmt);
extern ObjectAddress AlterForeignServer(AlterForeignServerStmt *stmt);
extern ObjectAddress CreateUserMapping(CreateUserMappingStmt *stmt);
@@ -153,5 +153,7 @@ extern List *defGetQualifiedName(DefElem *def);
extern TypeName *defGetTypeName(DefElem *def);
extern int defGetTypeLength(DefElem *def);
extern List *defGetStringList(DefElem *def);
+extern void pg_attribute_noreturn() errorDuplicateDefElem(DefElem *defel, ParseState *pstate);
+extern void pg_attribute_noreturn() errorRedundantDefElem(DefElem *defel, ParseState *pstate);
#endif /* DEFREM_H */
diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h
index 00e2e626e6..efea01f2a9 100644
--- a/src/include/commands/publicationcmds.h
+++ b/src/include/commands/publicationcmds.h
@@ -18,8 +18,8 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreatePublication(CreatePublicationStmt *stmt);
-extern void AlterPublication(AlterPublicationStmt *stmt);
+extern ObjectAddress CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt);
+extern void AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt);
extern void RemovePublicationRelById(Oid proid);
extern ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/subscriptioncmds.h b/src/include/commands/subscriptioncmds.h
index 3b926f35d7..8bf25ee66c 100644
--- a/src/include/commands/subscriptioncmds.h
+++ b/src/include/commands/subscriptioncmds.h
@@ -18,9 +18,9 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreateSubscription(CreateSubscriptionStmt *stmt,
+extern ObjectAddress CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
bool isTopLevel);
-extern ObjectAddress AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel);
+extern ObjectAddress AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, bool isTopLevel);
extern void DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel);
extern ObjectAddress AlterSubscriptionOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
index 880679127b..d5e22811d0 100644
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -25,7 +25,7 @@ extern ObjectAddress DefineType(ParseState *pstate, List *names, List *parameter
extern void RemoveTypeById(Oid typeOid);
extern ObjectAddress DefineDomain(CreateDomainStmt *stmt);
extern ObjectAddress DefineEnum(CreateEnumStmt *stmt);
-extern ObjectAddress DefineRange(CreateRangeStmt *stmt);
+extern ObjectAddress DefineRange(ParseState *pstate, CreateRangeStmt *stmt);
extern ObjectAddress AlterEnum(AlterEnumStmt *stmt);
extern ObjectAddress DefineCompositeType(RangeVar *typevar, List *coldeflist);
extern Oid AssignTypeArrayOid(void);
diff --git a/src/include/commands/user.h b/src/include/commands/user.h
index 028e0dde56..0b7a3cd65f 100644
--- a/src/include/commands/user.h
+++ b/src/include/commands/user.h
@@ -25,7 +25,7 @@ typedef void (*check_password_hook_type) (const char *username, const char *shad
extern PGDLLIMPORT check_password_hook_type check_password_hook;
extern Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt);
-extern Oid AlterRole(AlterRoleStmt *stmt);
+extern Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt);
extern Oid AlterRoleSet(AlterRoleSetStmt *stmt);
extern void DropRole(DropRoleStmt *stmt);
extern void GrantRole(GrantRoleStmt *stmt);
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c64f0719e7..b047d85b5a 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -30,31 +30,31 @@ COPY x (xyz) from stdin;
ERROR: column "xyz" of relation "x" does not exist
-- redundant options
COPY x from stdin (format CSV, FORMAT CSV);
-ERROR: conflicting or redundant options
+ERROR: redundant options specified
LINE 1: COPY x from stdin (format CSV, FORMAT CSV);
^
COPY x from stdin (freeze off, freeze on);
-ERROR: conflicting or redundant options
+ERROR: option "freeze" specified more than once
LINE 1: COPY x from stdin (freeze off, freeze on);
^
COPY x from stdin (delimiter ',', delimiter ',');
-ERROR: conflicting or redundant options
+ERROR: option "delimiter" specified more than once
LINE 1: COPY x from stdin (delimiter ',', delimiter ',');
^
COPY x from stdin (null ' ', null ' ');
-ERROR: conflicting or redundant options
+ERROR: option "null" specified more than once
LINE 1: COPY x from stdin (null ' ', null ' ');
^
COPY x from stdin (header off, header on);
-ERROR: conflicting or redundant options
+ERROR: option "header" specified more than once
LINE 1: COPY x from stdin (header off, header on);
^
COPY x from stdin (quote ':', quote ':');
-ERROR: conflicting or redundant options
+ERROR: option "quote" specified more than once
LINE 1: COPY x from stdin (quote ':', quote ':');
^
COPY x from stdin (escape ':', escape ':');
-ERROR: conflicting or redundant options
+ERROR: option "escape" specified more than once
LINE 1: COPY x from stdin (escape ':', escape ':');
^
COPY x from stdin (force_quote (a), force_quote *);
@@ -62,17 +62,19 @@ ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (force_quote (a), force_quote *);
^
COPY x from stdin (force_not_null (a), force_not_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_not_null" specified more than once
LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
COPY x from stdin (force_null (a), force_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_null" specified more than once
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
-ERROR: conflicting or redundant options
+ERROR: option "convert_selectively" specified more than once
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
^
COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
-ERROR: conflicting or redundant options
+ERROR: option "encoding" specified more than once
LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
^
-- too many columns in column list: should fail
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 809d40a79a..7d39d2a4d5 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -94,7 +94,9 @@ CREATE FUNCTION invalid_fdw_handler() RETURNS int LANGUAGE SQL AS 'SELECT 1;';
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...GN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER in...
+ ^
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -200,7 +202,9 @@ ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo;
ALTER FOREIGN DATA WRAPPER foo HANDLER invalid_fdw_handler; -- ERROR
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
-ERROR: conflicting or redundant options
+ERROR: option "handler" specified more than once
+LINE 1: ...FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER an...
+ ^
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 63d6ab7a4e..0f5cbe2e99 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -26,7 +26,9 @@ ERROR: unrecognized publication parameter: "foo"
CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
-ERROR: conflicting or redundant options
+ERROR: option "publish_via_partition_root" specified more than once
+LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi...
+ ^
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
--
2.25.1
On Mon, 12 Jul 2021 at 17:39, vignesh C <vignesh21@gmail.com> wrote:
Thanks for your comments, I have made the changes for the same in the
V10 patch attached.
Thoughts?
I'm still not happy about changing so many error messages.
Some of the changes might be OK, but aren't strictly necessary. For example:
COPY x from stdin (force_not_null (a), force_not_null (b));
-ERROR: conflicting or redundant options
+ERROR: option "force_not_null" specified more than once
LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b));
^
I actually prefer the original primary error message, for consistency
with other similar cases, and I think the error position indicator is
sufficient to identify the problem. If it were to include the
"specified more than once" text, I would put that in DETAIL.
Other changes are wrong though. For example:
COPY x from stdin (format CSV, FORMAT CSV);
-ERROR: conflicting or redundant options
+ERROR: redundant options specified
LINE 1: COPY x from stdin (format CSV, FORMAT CSV);
^
The problem here is that the code that throws this error throws the
same error if the second format is different, which would make it a
conflicting option, not a redundant one. And I don't think we should
add more code to test whether it's conflicting or redundant, so again,
I think we should just keep the original error message.
Similarly, this error is wrong:
CREATE OR REPLACE FUNCTION foo() RETURNS int AS $$ SELECT 1 $$ STABLE IMMUTABLE;
ERROR: redundant options specified
LINE 1: ...NCTION foo() RETURNS int AS $$ SELECT 1 $$ STABLE IMMUTABLE;
^
And even this error:
CREATE OR REPLACE FUNCTION foo() RETURNS int AS $$ SELECT 1 $$ STRICT STRICT;
ERROR: redundant options specified
LINE 1: ... FUNCTION foo() RETURNS int AS $$ SELECT 1 $$ STRICT STRICT;
^
which looks OK, is actually problematic because the same code also
handles the alternate syntax, which leads to this (which is now wrong
because it's conflicting not redundant):
CREATE OR REPLACE FUNCTION foo() RETURNS int AS $$ SELECT 1 $$ STRICT
CALLED ON NULL INPUT;
ERROR: redundant options specified
LINE 1: ...NCTION foo() RETURNS int AS $$ SELECT 1 $$ STRICT CALLED ON ...
^
The problem is it's actually quite hard to decide in each case whether
the option is redundant or conflicting. Sometimes, it might look
obvious in the code, but actually be much more subtle, due to an
earlier transformation of the grammar. Likewise redundant doesn't
necessarily mean literally specified more than once.
Also, most of these don't have regression test cases, and I'm very
reluctant to change them without proper testing, and that would make
the patch much bigger. To me, this patch is already attempting to
change too much in one go, which is causing problems.
So I suggest a more incremental approach, starting by keeping the
original error message, but improving it where possible with the error
position. Then maybe move on to look at specific cases that can be
further improved with additional detail (keeping the same primary
error message, for consistency).
Here is an updated version, following that approach. It does the following:
1). Keeps the same primary error message ("conflicting or redundant
options") in all cases.
2). Uses errorConflictingDefElem() to throw it, to ensure consistency
and reduce the executable size.
3). Includes your enhancements to make the ParseState available in
more places, so that the error position indicator is shown to indicate
the cause of the error.
IMO, this makes for a much safer incremental change, that is more committable.
As it turns out, there are 110 cases of this error that now use
errorConflictingDefElem(), and of those, just 10 (in 3 functions)
don't have a ParseState readily available to them:
- ATExecSetIdentity()
- parse_output_parameters() x5
- parseCreateReplSlotOptions() x4
It might be possible to improve those (and possibly some of the others
too) by adding some appropriate DETAIL to the error, but as I said, I
suggest doing that in a separate follow-on patch, and only with
careful analysis and testing of each case.
As it stands, the improvements from (3) seem quite worthwhile. Also,
the patch saves a couple of hundred lines of code, and for me an
optimised executable is around 30 kB smaller, which is more than I
expected.
Thoughts?
Regards,
Dean
Attachments:
v11-Enhance-conflicting-or-redundant-error-messages.patchtext/x-patch; charset=US-ASCII; name=v11-Enhance-conflicting-or-redundant-error-messages.patchDownload
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
new file mode 100644
index 5339241..89792b1
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -59,6 +59,7 @@
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
#include "commands/proclang.h"
@@ -921,19 +922,13 @@ ExecAlterDefaultPrivilegesStmt(ParseStat
if (strcmp(defel->defname, "schemas") == 0)
{
if (dnspnames)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dnspnames = defel;
}
else if (strcmp(defel->defname, "roles") == 0)
{
if (drolespecs)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
drolespecs = defel;
}
else
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
new file mode 100644
index 8265b98..6b33951
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -357,10 +357,7 @@ ProcessCopyOptions(ParseState *pstate,
char *fmt = defGetString(defel);
if (format_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
format_specified = true;
if (strcmp(fmt, "text") == 0)
/* default format */ ;
@@ -377,66 +374,45 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "freeze") == 0)
{
if (freeze_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
freeze_specified = true;
opts_out->freeze = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "delimiter") == 0)
{
if (opts_out->delim)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
opts_out->delim = defGetString(defel);
}
else if (strcmp(defel->defname, "null") == 0)
{
if (opts_out->null_print)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
opts_out->null_print = defGetString(defel);
}
else if (strcmp(defel->defname, "header") == 0)
{
if (header_specified)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
header_specified = true;
opts_out->header_line = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "quote") == 0)
{
if (opts_out->quote)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
opts_out->quote = defGetString(defel);
}
else if (strcmp(defel->defname, "escape") == 0)
{
if (opts_out->escape)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
opts_out->escape = defGetString(defel);
}
else if (strcmp(defel->defname, "force_quote") == 0)
{
if (opts_out->force_quote || opts_out->force_quote_all)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
if (defel->arg && IsA(defel->arg, A_Star))
opts_out->force_quote_all = true;
else if (defel->arg && IsA(defel->arg, List))
@@ -451,10 +427,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_not_null") == 0)
{
if (opts_out->force_notnull)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
if (defel->arg && IsA(defel->arg, List))
opts_out->force_notnull = castNode(List, defel->arg);
else
@@ -467,9 +440,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "force_null") == 0)
{
if (opts_out->force_null)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
if (defel->arg && IsA(defel->arg, List))
opts_out->force_null = castNode(List, defel->arg);
else
@@ -487,10 +458,7 @@ ProcessCopyOptions(ParseState *pstate,
* allowed for the column list to be NIL.
*/
if (opts_out->convert_selectively)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
opts_out->convert_selectively = true;
if (defel->arg == NULL || IsA(defel->arg, List))
opts_out->convert_select = castNode(List, defel->arg);
@@ -504,10 +472,7 @@ ProcessCopyOptions(ParseState *pstate,
else if (strcmp(defel->defname, "encoding") == 0)
{
if (opts_out->file_encoding >= 0)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
if (opts_out->file_encoding < 0)
ereport(ERROR,
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
new file mode 100644
index 2b159b6..029fab4
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -152,91 +152,61 @@ createdb(ParseState *pstate, const Creat
if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespacename)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dtablespacename = defel;
}
else if (strcmp(defel->defname, "owner") == 0)
{
if (downer)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
downer = defel;
}
else if (strcmp(defel->defname, "template") == 0)
{
if (dtemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dtemplate = defel;
}
else if (strcmp(defel->defname, "encoding") == 0)
{
if (dencoding)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dencoding = defel;
}
else if (strcmp(defel->defname, "locale") == 0)
{
if (dlocale)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dlocale = defel;
}
else if (strcmp(defel->defname, "lc_collate") == 0)
{
if (dcollate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dcollate = defel;
}
else if (strcmp(defel->defname, "lc_ctype") == 0)
{
if (dctype)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dctype = defel;
}
else if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "location") == 0)
@@ -1497,37 +1467,25 @@ AlterDatabase(ParseState *pstate, AlterD
if (strcmp(defel->defname, "is_template") == 0)
{
if (distemplate)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
{
if (dallowconnections)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "tablespace") == 0)
{
if (dtablespace)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dtablespace = defel;
}
else
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
new file mode 100644
index 84487b7..e900a17
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -347,3 +347,15 @@ defGetStringList(DefElem *def)
return (List *) def->arg;
}
+
+/*
+ * Raise an error about a conflicting DefElem.
+ */
+void
+errorConflictingDefElem(DefElem *defel, ParseState *pstate)
+{
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options"),
+ pstate ? parser_errposition(pstate, defel->location) : 0);
+}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
new file mode 100644
index b37009b..eaa76af
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1731,30 +1731,21 @@ CreateExtension(ParseState *pstate, Crea
if (strcmp(defel->defname, "schema") == 0)
{
if (d_schema)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
d_schema = defel;
schemaName = defGetString(d_schema);
}
else if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
d_new_version = defel;
versionName = defGetString(d_new_version);
}
else if (strcmp(defel->defname, "cascade") == 0)
{
if (d_cascade)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
d_cascade = defel;
cascade = defGetBoolean(d_cascade);
}
@@ -3051,10 +3042,7 @@ ExecAlterExtensionStmt(ParseState *pstat
if (strcmp(defel->defname, "new_version") == 0)
{
if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
d_new_version = defel;
}
else
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
new file mode 100644
index bc36311..9b71beb
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -515,7 +515,7 @@ lookup_fdw_validator_func(DefElem *valid
* Process function options of CREATE/ALTER FDW
*/
static void
-parse_func_options(List *func_options,
+parse_func_options(ParseState *pstate, List *func_options,
bool *handler_given, Oid *fdwhandler,
bool *validator_given, Oid *fdwvalidator)
{
@@ -534,18 +534,14 @@ parse_func_options(List *func_options,
if (strcmp(def->defname, "handler") == 0)
{
if (*handler_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(def, pstate);
*handler_given = true;
*fdwhandler = lookup_fdw_handler_func(def);
}
else if (strcmp(def->defname, "validator") == 0)
{
if (*validator_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(def, pstate);
*validator_given = true;
*fdwvalidator = lookup_fdw_validator_func(def);
}
@@ -559,7 +555,7 @@ parse_func_options(List *func_options,
* Create a foreign-data wrapper
*/
ObjectAddress
-CreateForeignDataWrapper(CreateFdwStmt *stmt)
+CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt)
{
Relation rel;
Datum values[Natts_pg_foreign_data_wrapper];
@@ -611,7 +607,7 @@ CreateForeignDataWrapper(CreateFdwStmt *
values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
/* Lookup handler and validator functions, if given */
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
@@ -675,7 +671,7 @@ CreateForeignDataWrapper(CreateFdwStmt *
* Alter foreign-data wrapper
*/
ObjectAddress
-AlterForeignDataWrapper(AlterFdwStmt *stmt)
+AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt)
{
Relation rel;
HeapTuple tp;
@@ -717,7 +713,7 @@ AlterForeignDataWrapper(AlterFdwStmt *st
memset(repl_null, false, sizeof(repl_null));
memset(repl_repl, false, sizeof(repl_repl));
- parse_func_options(stmt->func_options,
+ parse_func_options(pstate, stmt->func_options,
&handler_given, &fdwhandler,
&validator_given, &fdwvalidator);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
new file mode 100644
index 736d047..79d875a
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -523,7 +523,7 @@ compute_common_attribute(ParseState *pst
if (is_procedure)
goto procedure_error;
if (*volatility_item)
- goto duplicate_error;
+ errorConflictingDefElem(defel, pstate);
*volatility_item = defel;
}
@@ -532,14 +532,14 @@ compute_common_attribute(ParseState *pst
if (is_procedure)
goto procedure_error;
if (*strict_item)
- goto duplicate_error;
+ errorConflictingDefElem(defel, pstate);
*strict_item = defel;
}
else if (strcmp(defel->defname, "security") == 0)
{
if (*security_item)
- goto duplicate_error;
+ errorConflictingDefElem(defel, pstate);
*security_item = defel;
}
@@ -548,7 +548,7 @@ compute_common_attribute(ParseState *pst
if (is_procedure)
goto procedure_error;
if (*leakproof_item)
- goto duplicate_error;
+ errorConflictingDefElem(defel, pstate);
*leakproof_item = defel;
}
@@ -561,7 +561,7 @@ compute_common_attribute(ParseState *pst
if (is_procedure)
goto procedure_error;
if (*cost_item)
- goto duplicate_error;
+ errorConflictingDefElem(defel, pstate);
*cost_item = defel;
}
@@ -570,7 +570,7 @@ compute_common_attribute(ParseState *pst
if (is_procedure)
goto procedure_error;
if (*rows_item)
- goto duplicate_error;
+ errorConflictingDefElem(defel, pstate);
*rows_item = defel;
}
@@ -579,7 +579,7 @@ compute_common_attribute(ParseState *pst
if (is_procedure)
goto procedure_error;
if (*support_item)
- goto duplicate_error;
+ errorConflictingDefElem(defel, pstate);
*support_item = defel;
}
@@ -588,7 +588,7 @@ compute_common_attribute(ParseState *pst
if (is_procedure)
goto procedure_error;
if (*parallel_item)
- goto duplicate_error;
+ errorConflictingDefElem(defel, pstate);
*parallel_item = defel;
}
@@ -598,13 +598,6 @@ compute_common_attribute(ParseState *pst
/* Recognized an option */
return true;
-duplicate_error:
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
- return false; /* keep compiler quiet */
-
procedure_error:
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -765,37 +758,25 @@ compute_function_attributes(ParseState *
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
language_item = defel;
}
else if (strcmp(defel->defname, "transform") == 0)
{
if (transform_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
transform_item = defel;
}
else if (strcmp(defel->defname, "window") == 0)
{
if (windowfunc_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
if (is_procedure)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -2070,7 +2051,7 @@ IsThereFunctionInNamespace(const char *p
* See at ExecuteCallStmt() about the atomic argument.
*/
void
-ExecuteDoStmt(DoStmt *stmt, bool atomic)
+ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
{
InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
ListCell *arg;
@@ -2089,17 +2070,13 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
if (strcmp(defel->defname, "as") == 0)
{
if (as_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
{
if (language_item)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
language_item = defel;
}
else
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
new file mode 100644
index 95c253c..12f9f8b
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -55,7 +55,8 @@ static void PublicationAddTables(Oid pub
static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
static void
-parse_publication_options(List *options,
+parse_publication_options(ParseState *pstate,
+ List *options,
bool *publish_given,
PublicationActions *pubactions,
bool *publish_via_partition_root_given,
@@ -85,9 +86,7 @@ parse_publication_options(List *options,
ListCell *lc;
if (*publish_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
/*
* If publish option was given only the explicitly listed actions
@@ -128,9 +127,7 @@ parse_publication_options(List *options,
else if (strcmp(defel->defname, "publish_via_partition_root") == 0)
{
if (*publish_via_partition_root_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
*publish_via_partition_root_given = true;
*publish_via_partition_root = defGetBoolean(defel);
}
@@ -145,7 +142,7 @@ parse_publication_options(List *options,
* Create new publication.
*/
ObjectAddress
-CreatePublication(CreatePublicationStmt *stmt)
+CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
{
Relation rel;
ObjectAddress myself;
@@ -192,7 +189,8 @@ CreatePublication(CreatePublicationStmt
DirectFunctionCall1(namein, CStringGetDatum(stmt->pubname));
values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId());
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -256,8 +254,8 @@ CreatePublication(CreatePublicationStmt
* Change options of a publication.
*/
static void
-AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
- HeapTuple tup)
+AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
+ Relation rel, HeapTuple tup)
{
bool nulls[Natts_pg_publication];
bool replaces[Natts_pg_publication];
@@ -269,7 +267,8 @@ AlterPublicationOptions(AlterPublication
ObjectAddress obj;
Form_pg_publication pubform;
- parse_publication_options(stmt->options,
+ parse_publication_options(pstate,
+ stmt->options,
&publish_given, &pubactions,
&publish_via_partition_root_given,
&publish_via_partition_root);
@@ -434,7 +433,7 @@ AlterPublicationTables(AlterPublicationS
* AlterPublicationTables.
*/
void
-AlterPublication(AlterPublicationStmt *stmt)
+AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
{
Relation rel;
HeapTuple tup;
@@ -459,7 +458,7 @@ AlterPublication(AlterPublicationStmt *s
stmt->pubname);
if (stmt->options)
- AlterPublicationOptions(stmt, rel, tup);
+ AlterPublicationOptions(pstate, stmt, rel, tup);
else
AlterPublicationTables(stmt, rel, tup);
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
new file mode 100644
index d22d767..72bfdc0
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1261,90 +1261,63 @@ init_params(ParseState *pstate, List *op
if (strcmp(defel->defname, "as") == 0)
{
if (as_type)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
as_type = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "increment") == 0)
{
if (increment_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
increment_by = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "start") == 0)
{
if (start_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
start_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "restart") == 0)
{
if (restart_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
restart_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "maxvalue") == 0)
{
if (max_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
max_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "minvalue") == 0)
{
if (min_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
min_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cache") == 0)
{
if (cache_value)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
cache_value = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "cycle") == 0)
{
if (is_cycled)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
is_cycled = defel;
*need_seq_rewrite = true;
}
else if (strcmp(defel->defname, "owned_by") == 0)
{
if (*owned_by)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
*owned_by = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "sequence_name") == 0)
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
new file mode 100644
index eb88d87..2983599
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -96,7 +96,8 @@ static void ReportSlotConnectionError(Li
* Caller is expected to have cleared 'opts'.
*/
static void
-parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *opts)
+parse_subscription_options(ParseState *pstate, List *stmt_options,
+ bits32 supported_opts, SubOpts *opts)
{
ListCell *lc;
@@ -133,9 +134,7 @@ parse_subscription_options(List *stmt_op
strcmp(defel->defname, "connect") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_CONNECT))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_CONNECT;
opts->connect = defGetBoolean(defel);
@@ -144,9 +143,7 @@ parse_subscription_options(List *stmt_op
strcmp(defel->defname, "enabled") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_ENABLED))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_ENABLED;
opts->enabled = defGetBoolean(defel);
@@ -155,9 +152,7 @@ parse_subscription_options(List *stmt_op
strcmp(defel->defname, "create_slot") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_CREATE_SLOT))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_CREATE_SLOT;
opts->create_slot = defGetBoolean(defel);
@@ -166,9 +161,7 @@ parse_subscription_options(List *stmt_op
strcmp(defel->defname, "slot_name") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_SLOT_NAME))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_SLOT_NAME;
opts->slot_name = defGetString(defel);
@@ -181,9 +174,7 @@ parse_subscription_options(List *stmt_op
strcmp(defel->defname, "copy_data") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_COPY_DATA))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_COPY_DATA;
opts->copy_data = defGetBoolean(defel);
@@ -192,9 +183,7 @@ parse_subscription_options(List *stmt_op
strcmp(defel->defname, "synchronous_commit") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_SYNCHRONOUS_COMMIT))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_SYNCHRONOUS_COMMIT;
opts->synchronous_commit = defGetString(defel);
@@ -208,9 +197,7 @@ parse_subscription_options(List *stmt_op
strcmp(defel->defname, "refresh") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_REFRESH))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_REFRESH;
opts->refresh = defGetBoolean(defel);
@@ -219,9 +206,7 @@ parse_subscription_options(List *stmt_op
strcmp(defel->defname, "binary") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_BINARY))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_BINARY;
opts->binary = defGetBoolean(defel);
@@ -230,9 +215,7 @@ parse_subscription_options(List *stmt_op
strcmp(defel->defname, "streaming") == 0)
{
if (IsSet(opts->specified_opts, SUBOPT_STREAMING))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
opts->specified_opts |= SUBOPT_STREAMING;
opts->streaming = defGetBoolean(defel);
@@ -362,7 +345,8 @@ publicationListToArray(List *publist)
* Create new subscription.
*/
ObjectAddress
-CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
+CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -386,7 +370,7 @@ CreateSubscription(CreateSubscriptionStm
SUBOPT_SLOT_NAME | SUBOPT_COPY_DATA |
SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
SUBOPT_STREAMING);
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options, supported_opts, &opts);
/*
* Since creating a replication slot is not transactional, rolling back
@@ -778,7 +762,8 @@ AlterSubscription_refresh(Subscription *
* Alter the existing subscription.
*/
ObjectAddress
-AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
+AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
+ bool isTopLevel)
{
Relation rel;
ObjectAddress myself;
@@ -831,7 +816,8 @@ AlterSubscription(AlterSubscriptionStmt
SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
SUBOPT_STREAMING);
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ supported_opts, &opts);
if (IsSet(opts.specified_opts, SUBOPT_SLOT_NAME))
{
@@ -876,7 +862,8 @@ AlterSubscription(AlterSubscriptionStmt
case ALTER_SUBSCRIPTION_ENABLED:
{
- parse_subscription_options(stmt->options, SUBOPT_ENABLED, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ SUBOPT_ENABLED, &opts);
Assert(IsSet(opts.specified_opts, SUBOPT_ENABLED));
if (!sub->slotname && opts.enabled)
@@ -910,7 +897,8 @@ AlterSubscription(AlterSubscriptionStmt
case ALTER_SUBSCRIPTION_SET_PUBLICATION:
{
supported_opts = SUBOPT_COPY_DATA | SUBOPT_REFRESH;
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ supported_opts, &opts);
values[Anum_pg_subscription_subpublications - 1] =
publicationListToArray(stmt->publication);
@@ -948,7 +936,8 @@ AlterSubscription(AlterSubscriptionStmt
if (isadd)
supported_opts |= SUBOPT_COPY_DATA;
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ supported_opts, &opts);
publist = merge_publications(sub->publications, stmt->publication, isadd, stmt->subname);
values[Anum_pg_subscription_subpublications - 1] =
@@ -984,7 +973,8 @@ AlterSubscription(AlterSubscriptionStmt
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions")));
- parse_subscription_options(stmt->options, SUBOPT_COPY_DATA, &opts);
+ parse_subscription_options(pstate, stmt->options,
+ SUBOPT_COPY_DATA, &opts);
PreventInTransactionBlock(isTopLevel, "ALTER SUBSCRIPTION ... REFRESH");
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
new file mode 100644
index dcf14b9..406e36d
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7587,9 +7587,7 @@ ATExecSetIdentity(Relation rel, const ch
if (strcmp(defel->defname, "generated") == 0)
{
if (generatedEl)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, NULL);
generatedEl = defel;
}
else
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
new file mode 100644
index 58ec65c..93eeff9
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -330,10 +330,7 @@ DefineType(ParseState *pstate, List *nam
continue;
}
if (*defelp != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
*defelp = defel;
}
@@ -1336,7 +1333,7 @@ checkEnumOwner(HeapTuple tup)
* and users might have queries with that same assumption.
*/
ObjectAddress
-DefineRange(CreateRangeStmt *stmt)
+DefineRange(ParseState *pstate, CreateRangeStmt *stmt)
{
char *typeName;
Oid typeNamespace;
@@ -1411,50 +1408,38 @@ DefineRange(CreateRangeStmt *stmt)
if (strcmp(defel->defname, "subtype") == 0)
{
if (OidIsValid(rangeSubtype))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
/* we can look up the subtype name immediately */
rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
}
else if (strcmp(defel->defname, "subtype_opclass") == 0)
{
if (rangeSubOpclassName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
rangeSubOpclassName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "collation") == 0)
{
if (rangeCollationName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
rangeCollationName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "canonical") == 0)
{
if (rangeCanonicalName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
rangeCanonicalName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "subtype_diff") == 0)
{
if (rangeSubtypeDiffName != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
rangeSubtypeDiffName = defGetQualifiedName(defel);
}
else if (strcmp(defel->defname, "multirange_type_name") == 0)
{
if (multirangeTypeName != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
&multirangeTypeName);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
new file mode 100644
index 65bb733..aa69821
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -27,6 +27,7 @@
#include "catalog/pg_db_role_setting.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
+#include "commands/defrem.h"
#include "commands/seclabel.h"
#include "commands/user.h"
#include "libpq/crypt.h"
@@ -128,10 +129,7 @@ CreateRole(ParseState *pstate, CreateRol
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dpassword = defel;
}
else if (strcmp(defel->defname, "sysid") == 0)
@@ -142,109 +140,73 @@ CreateRole(ParseState *pstate, CreateRol
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "addroleto") == 0)
{
if (daddroleto)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
daddroleto = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
drolemembers = defel;
}
else if (strcmp(defel->defname, "adminmembers") == 0)
{
if (dadminmembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dadminmembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options"),
- parser_errposition(pstate, defel->location)));
+ errorConflictingDefElem(defel, pstate);
dbypassRLS = defel;
}
else
@@ -528,7 +490,7 @@ CreateRole(ParseState *pstate, CreateRol
* "ALTER ROLE role ROLE rolenames", we don't document it.
*/
Oid
-AlterRole(AlterRoleStmt *stmt)
+AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
{
Datum new_record[Natts_pg_authid];
bool new_record_nulls[Natts_pg_authid];
@@ -577,90 +539,68 @@ AlterRole(AlterRoleStmt *stmt)
if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
dpassword = defel;
}
else if (strcmp(defel->defname, "superuser") == 0)
{
if (dissuper)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
{
if (dinherit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
if (dcreatedb)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
{
if (dcanlogin)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
{
if (disreplication)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
dconnlimit = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0 &&
stmt->action != 0)
{
if (drolemembers)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
drolemembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
if (dvalidUntil)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
{
if (dbypassRLS)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, pstate);
dbypassRLS = defel;
}
else
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
new file mode 100644
index 3afcd6b..9edd1f8
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -392,9 +392,7 @@ generateSerialExtraStmts(CreateStmtConte
if (strcmp(defel->defname, "sequence_name") == 0)
{
if (nameEl)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, cxt->pstate);
nameEl = defel;
nameEl_idx = foreach_current_index(option);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
new file mode 100644
index abd5217..9a79412
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -184,9 +184,7 @@ parse_output_parameters(List *options, P
int64 parsed;
if (protocol_version_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, NULL);
protocol_version_given = true;
if (!scanint8(strVal(defel->arg), true, &parsed))
@@ -205,9 +203,7 @@ parse_output_parameters(List *options, P
else if (strcmp(defel->defname, "publication_names") == 0)
{
if (publication_names_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, NULL);
publication_names_given = true;
if (!SplitIdentifierString(strVal(defel->arg), ',',
@@ -219,9 +215,7 @@ parse_output_parameters(List *options, P
else if (strcmp(defel->defname, "binary") == 0)
{
if (binary_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, NULL);
binary_option_given = true;
data->binary = defGetBoolean(defel);
@@ -229,9 +223,7 @@ parse_output_parameters(List *options, P
else if (strcmp(defel->defname, "messages") == 0)
{
if (messages_option_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, NULL);
messages_option_given = true;
data->messages = defGetBoolean(defel);
@@ -239,9 +231,7 @@ parse_output_parameters(List *options, P
else if (strcmp(defel->defname, "streaming") == 0)
{
if (streaming_given)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, NULL);
streaming_given = true;
data->streaming = defGetBoolean(defel);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
new file mode 100644
index 3ca2a11..7202f91
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -875,9 +875,7 @@ parseCreateReplSlotOptions(CreateReplica
if (strcmp(defel->defname, "export_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, NULL);
snapshot_action_given = true;
*snapshot_action = defGetBoolean(defel) ? CRS_EXPORT_SNAPSHOT :
@@ -886,9 +884,7 @@ parseCreateReplSlotOptions(CreateReplica
else if (strcmp(defel->defname, "use_snapshot") == 0)
{
if (snapshot_action_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, NULL);
snapshot_action_given = true;
*snapshot_action = CRS_USE_SNAPSHOT;
@@ -896,9 +892,7 @@ parseCreateReplSlotOptions(CreateReplica
else if (strcmp(defel->defname, "reserve_wal") == 0)
{
if (reserve_wal_given || cmd->kind != REPLICATION_KIND_PHYSICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, NULL);
reserve_wal_given = true;
*reserve_wal = true;
@@ -906,9 +900,8 @@ parseCreateReplSlotOptions(CreateReplica
else if (strcmp(defel->defname, "two_phase") == 0)
{
if (two_phase_given || cmd->kind != REPLICATION_KIND_LOGICAL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errorConflictingDefElem(defel, NULL);
+
two_phase_given = true;
*two_phase = true;
}
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
new file mode 100644
index 7a2da9d..27fbf1f
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -708,7 +708,7 @@ standard_ProcessUtility(PlannedStmt *pst
break;
case T_DoStmt:
- ExecuteDoStmt((DoStmt *) parsetree, isAtomicContext);
+ ExecuteDoStmt(pstate, (DoStmt *) parsetree, isAtomicContext);
break;
case T_CreateTableSpaceStmt:
@@ -888,7 +888,7 @@ standard_ProcessUtility(PlannedStmt *pst
case T_AlterRoleStmt:
/* no event triggers for global objects */
- AlterRole((AlterRoleStmt *) parsetree);
+ AlterRole(pstate, (AlterRoleStmt *) parsetree);
break;
case T_AlterRoleSetStmt:
@@ -1552,11 +1552,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateFdwStmt:
- address = CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
+ address = CreateForeignDataWrapper(pstate, (CreateFdwStmt *) parsetree);
break;
case T_AlterFdwStmt:
- address = AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
+ address = AlterForeignDataWrapper(pstate, (AlterFdwStmt *) parsetree);
break;
case T_CreateForeignServerStmt:
@@ -1601,7 +1601,7 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
- address = DefineRange((CreateRangeStmt *) parsetree);
+ address = DefineRange(pstate, (CreateRangeStmt *) parsetree);
break;
case T_AlterEnumStmt: /* ALTER TYPE (enum) */
@@ -1802,11 +1802,11 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreatePublicationStmt:
- address = CreatePublication((CreatePublicationStmt *) parsetree);
+ address = CreatePublication(pstate, (CreatePublicationStmt *) parsetree);
break;
case T_AlterPublicationStmt:
- AlterPublication((AlterPublicationStmt *) parsetree);
+ AlterPublication(pstate, (AlterPublicationStmt *) parsetree);
/*
* AlterPublication calls EventTriggerCollectSimpleCommand
@@ -1816,12 +1816,14 @@ ProcessUtilitySlow(ParseState *pstate,
break;
case T_CreateSubscriptionStmt:
- address = CreateSubscription((CreateSubscriptionStmt *) parsetree,
+ address = CreateSubscription(pstate,
+ (CreateSubscriptionStmt *) parsetree,
isTopLevel);
break;
case T_AlterSubscriptionStmt:
- address = AlterSubscription((AlterSubscriptionStmt *) parsetree,
+ address = AlterSubscription(pstate,
+ (AlterSubscriptionStmt *) parsetree,
isTopLevel);
break;
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
new file mode 100644
index 42bf1c7..f84d099
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -56,7 +56,7 @@ extern ObjectAddress CreateCast(CreateCa
extern ObjectAddress CreateTransform(CreateTransformStmt *stmt);
extern void IsThereFunctionInNamespace(const char *proname, int pronargs,
oidvector *proargtypes, Oid nspOid);
-extern void ExecuteDoStmt(DoStmt *stmt, bool atomic);
+extern void ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic);
extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest);
extern TupleDesc CallStmtResultDesc(CallStmt *stmt);
extern Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok);
@@ -121,8 +121,8 @@ extern ObjectAddress AlterForeignServerO
extern void AlterForeignServerOwner_oid(Oid, Oid newOwnerId);
extern ObjectAddress AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId);
extern void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId);
-extern ObjectAddress CreateForeignDataWrapper(CreateFdwStmt *stmt);
-extern ObjectAddress AlterForeignDataWrapper(AlterFdwStmt *stmt);
+extern ObjectAddress CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt);
+extern ObjectAddress AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt);
extern ObjectAddress CreateForeignServer(CreateForeignServerStmt *stmt);
extern ObjectAddress AlterForeignServer(AlterForeignServerStmt *stmt);
extern ObjectAddress CreateUserMapping(CreateUserMappingStmt *stmt);
@@ -153,5 +153,6 @@ extern List *defGetQualifiedName(DefElem
extern TypeName *defGetTypeName(DefElem *def);
extern int defGetTypeLength(DefElem *def);
extern List *defGetStringList(DefElem *def);
+extern void errorConflictingDefElem(DefElem *defel, ParseState *pstate) pg_attribute_noreturn();
#endif /* DEFREM_H */
diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h
new file mode 100644
index 00e2e62..efea01f
--- a/src/include/commands/publicationcmds.h
+++ b/src/include/commands/publicationcmds.h
@@ -18,8 +18,8 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreatePublication(CreatePublicationStmt *stmt);
-extern void AlterPublication(AlterPublicationStmt *stmt);
+extern ObjectAddress CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt);
+extern void AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt);
extern void RemovePublicationRelById(Oid proid);
extern ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/subscriptioncmds.h b/src/include/commands/subscriptioncmds.h
new file mode 100644
index 3b926f3..8bf25ee
--- a/src/include/commands/subscriptioncmds.h
+++ b/src/include/commands/subscriptioncmds.h
@@ -18,9 +18,9 @@
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
-extern ObjectAddress CreateSubscription(CreateSubscriptionStmt *stmt,
+extern ObjectAddress CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
bool isTopLevel);
-extern ObjectAddress AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel);
+extern ObjectAddress AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, bool isTopLevel);
extern void DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel);
extern ObjectAddress AlterSubscriptionOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
new file mode 100644
index 8806791..d5e2281
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -25,7 +25,7 @@ extern ObjectAddress DefineType(ParseSta
extern void RemoveTypeById(Oid typeOid);
extern ObjectAddress DefineDomain(CreateDomainStmt *stmt);
extern ObjectAddress DefineEnum(CreateEnumStmt *stmt);
-extern ObjectAddress DefineRange(CreateRangeStmt *stmt);
+extern ObjectAddress DefineRange(ParseState *pstate, CreateRangeStmt *stmt);
extern ObjectAddress AlterEnum(AlterEnumStmt *stmt);
extern ObjectAddress DefineCompositeType(RangeVar *typevar, List *coldeflist);
extern Oid AssignTypeArrayOid(void);
diff --git a/src/include/commands/user.h b/src/include/commands/user.h
new file mode 100644
index 028e0dd..0b7a3cd
--- a/src/include/commands/user.h
+++ b/src/include/commands/user.h
@@ -25,7 +25,7 @@ typedef void (*check_password_hook_type)
extern PGDLLIMPORT check_password_hook_type check_password_hook;
extern Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt);
-extern Oid AlterRole(AlterRoleStmt *stmt);
+extern Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt);
extern Oid AlterRoleSet(AlterRoleSetStmt *stmt);
extern void DropRole(DropRoleStmt *stmt);
extern void GrantRole(GrantRoleStmt *stmt);
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
new file mode 100644
index c64f071..5f3685e
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -67,6 +67,8 @@ LINE 1: COPY x from stdin (force_not_nul
^
COPY x from stdin (force_null (a), force_null (b));
ERROR: conflicting or redundant options
+LINE 1: COPY x from stdin (force_null (a), force_null (b));
+ ^
COPY x from stdin (convert_selectively (a), convert_selectively (b));
ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (convert_selectively (a), convert_selectiv...
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
new file mode 100644
index 809d40a..426080a
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -95,6 +95,8 @@ CREATE FOREIGN DATA WRAPPER test_fdw HAN
ERROR: function invalid_fdw_handler must return type fdw_handler
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER invalid_fdw_handler; -- ERROR
ERROR: conflicting or redundant options
+LINE 1: ...GN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER in...
+ ^
CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler;
DROP FOREIGN DATA WRAPPER test_fdw;
-- ALTER FOREIGN DATA WRAPPER
@@ -201,6 +203,8 @@ ALTER FOREIGN DATA WRAPPER foo HANDLER i
ERROR: function invalid_fdw_handler must return type fdw_handler
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER anything; -- ERROR
ERROR: conflicting or redundant options
+LINE 1: ...FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler HANDLER an...
+ ^
ALTER FOREIGN DATA WRAPPER foo HANDLER test_fdw_handler;
WARNING: changing the foreign-data wrapper handler can change behavior of existing foreign tables
DROP FUNCTION invalid_fdw_handler();
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
new file mode 100644
index 63d6ab7..b5b065a
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -27,6 +27,8 @@ CREATE PUBLICATION testpub_xxx WITH (pub
ERROR: unrecognized "publish" value: "cluster"
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
ERROR: conflicting or redundant options
+LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi...
+ ^
\dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
On Tue, Jul 13, 2021 at 4:25 PM Dean Rasheed <dean.a.rasheed@gmail.com> wrote:
On Mon, 12 Jul 2021 at 17:39, vignesh C <vignesh21@gmail.com> wrote:
Thanks for your comments, I have made the changes for the same in the
V10 patch attached.
Thoughts?I'm still not happy about changing so many error messages.
Some of the changes might be OK, but aren't strictly necessary. For example:
COPY x from stdin (force_not_null (a), force_not_null (b)); -ERROR: conflicting or redundant options +ERROR: option "force_not_null" specified more than once LINE 1: COPY x from stdin (force_not_null (a), force_not_null (b)); ^I actually prefer the original primary error message, for consistency
with other similar cases, and I think the error position indicator is
sufficient to identify the problem. If it were to include the
"specified more than once" text, I would put that in DETAIL.Other changes are wrong though. For example:
COPY x from stdin (format CSV, FORMAT CSV); -ERROR: conflicting or redundant options +ERROR: redundant options specified LINE 1: COPY x from stdin (format CSV, FORMAT CSV); ^The problem here is that the code that throws this error throws the
same error if the second format is different, which would make it a
conflicting option, not a redundant one. And I don't think we should
add more code to test whether it's conflicting or redundant, so again,
I think we should just keep the original error message.Similarly, this error is wrong:
CREATE OR REPLACE FUNCTION foo() RETURNS int AS $$ SELECT 1 $$ STABLE IMMUTABLE;
ERROR: redundant options specified
LINE 1: ...NCTION foo() RETURNS int AS $$ SELECT 1 $$ STABLE IMMUTABLE;
^And even this error:
CREATE OR REPLACE FUNCTION foo() RETURNS int AS $$ SELECT 1 $$ STRICT STRICT;
ERROR: redundant options specified
LINE 1: ... FUNCTION foo() RETURNS int AS $$ SELECT 1 $$ STRICT STRICT;
^which looks OK, is actually problematic because the same code also
handles the alternate syntax, which leads to this (which is now wrong
because it's conflicting not redundant):CREATE OR REPLACE FUNCTION foo() RETURNS int AS $$ SELECT 1 $$ STRICT
CALLED ON NULL INPUT;
ERROR: redundant options specified
LINE 1: ...NCTION foo() RETURNS int AS $$ SELECT 1 $$ STRICT CALLED ON ...
^The problem is it's actually quite hard to decide in each case whether
the option is redundant or conflicting. Sometimes, it might look
obvious in the code, but actually be much more subtle, due to an
earlier transformation of the grammar. Likewise redundant doesn't
necessarily mean literally specified more than once.Also, most of these don't have regression test cases, and I'm very
reluctant to change them without proper testing, and that would make
the patch much bigger. To me, this patch is already attempting to
change too much in one go, which is causing problems.So I suggest a more incremental approach, starting by keeping the
original error message, but improving it where possible with the error
position. Then maybe move on to look at specific cases that can be
further improved with additional detail (keeping the same primary
error message, for consistency).
I'm fine with this approach as we do not have tests to cover all the
error conditions, also I'm not sure if it is worth adding tests for
all the error conditions and as the patch changes a large number of
error conditions, an incremental approach is better.
Here is an updated version, following that approach. It does the following:
1). Keeps the same primary error message ("conflicting or redundant
options") in all cases.2). Uses errorConflictingDefElem() to throw it, to ensure consistency
and reduce the executable size.3). Includes your enhancements to make the ParseState available in
more places, so that the error position indicator is shown to indicate
the cause of the error.IMO, this makes for a much safer incremental change, that is more committable.
As it turns out, there are 110 cases of this error that now use
errorConflictingDefElem(), and of those, just 10 (in 3 functions)
don't have a ParseState readily available to them:- ATExecSetIdentity()
- parse_output_parameters() x5
- parseCreateReplSlotOptions() x4It might be possible to improve those (and possibly some of the others
too) by adding some appropriate DETAIL to the error, but as I said, I
suggest doing that in a separate follow-on patch, and only with
careful analysis and testing of each case.As it stands, the improvements from (3) seem quite worthwhile. Also,
the patch saves a couple of hundred lines of code, and for me an
optimised executable is around 30 kB smaller, which is more than I
expected.
Agreed, it can be handled as part of the 2nd patch. The changes you
made apply neatly and the test passes.
Regards,
Vignesh
On Tue, 13 Jul 2021 at 15:30, vignesh C <vignesh21@gmail.com> wrote:
On Tue, Jul 13, 2021 at 4:25 PM Dean Rasheed <dean.a.rasheed@gmail.com> wrote:
As it stands, the improvements from (3) seem quite worthwhile. Also,
the patch saves a couple of hundred lines of code, and for me an
optimised executable is around 30 kB smaller, which is more than I
expected.Agreed, it can be handled as part of the 2nd patch. The changes you
made apply neatly and the test passes.
Pushed.
I noticed that it's actually safe to call parser_errposition() with a
null ParseState, so I simplified the ereport() code to just call it
unconditionally. Also, I decided to not bother using the new function
in cases with a null ParseState anyway since it doesn't provide any
meaningful benefit in those cases, and those are the cases most likely
to targeted next, so it didn't seem sensible to change that code, only
for it to be changed again later.
Probably the thing to think about next is the few remaining cases that
throw this error directly and don't have any errdetail or errhint to
help the user identify the offending option. My preference remains to
leave the primary error text unchanged, but just add some suitable
errdetail. Also, it's probably not worth adding a new function for
those remaining errors, since there are only a handful of them.
Regards,
Dean
On Thu, Jul 15, 2021 at 1:40 PM Dean Rasheed <dean.a.rasheed@gmail.com> wrote:
On Tue, 13 Jul 2021 at 15:30, vignesh C <vignesh21@gmail.com> wrote:
On Tue, Jul 13, 2021 at 4:25 PM Dean Rasheed <dean.a.rasheed@gmail.com> wrote:
As it stands, the improvements from (3) seem quite worthwhile. Also,
the patch saves a couple of hundred lines of code, and for me an
optimised executable is around 30 kB smaller, which is more than I
expected.Agreed, it can be handled as part of the 2nd patch. The changes you
made apply neatly and the test passes.Pushed.
I noticed that it's actually safe to call parser_errposition() with a
null ParseState, so I simplified the ereport() code to just call it
unconditionally. Also, I decided to not bother using the new function
in cases with a null ParseState anyway since it doesn't provide any
meaningful benefit in those cases, and those are the cases most likely
to targeted next, so it didn't seem sensible to change that code, only
for it to be changed again later.Probably the thing to think about next is the few remaining cases that
throw this error directly and don't have any errdetail or errhint to
help the user identify the offending option. My preference remains to
leave the primary error text unchanged, but just add some suitable
errdetail. Also, it's probably not worth adding a new function for
those remaining errors, since there are only a handful of them.
Thanks for pushing this patch. I have changed the commitfest status to
"waiting for author" till 0002 patch is posted.
Regards,
Vignesh
On Thu, Jul 15, 2021 at 5:12 PM vignesh C <vignesh21@gmail.com> wrote:
On Thu, Jul 15, 2021 at 1:40 PM Dean Rasheed <dean.a.rasheed@gmail.com> wrote:
On Tue, 13 Jul 2021 at 15:30, vignesh C <vignesh21@gmail.com> wrote:
On Tue, Jul 13, 2021 at 4:25 PM Dean Rasheed <dean.a.rasheed@gmail.com> wrote:
As it stands, the improvements from (3) seem quite worthwhile. Also,
the patch saves a couple of hundred lines of code, and for me an
optimised executable is around 30 kB smaller, which is more than I
expected.Agreed, it can be handled as part of the 2nd patch. The changes you
made apply neatly and the test passes.Pushed.
I noticed that it's actually safe to call parser_errposition() with a
null ParseState, so I simplified the ereport() code to just call it
unconditionally. Also, I decided to not bother using the new function
in cases with a null ParseState anyway since it doesn't provide any
meaningful benefit in those cases, and those are the cases most likely
to targeted next, so it didn't seem sensible to change that code, only
for it to be changed again later.Probably the thing to think about next is the few remaining cases that
throw this error directly and don't have any errdetail or errhint to
help the user identify the offending option. My preference remains to
leave the primary error text unchanged, but just add some suitable
errdetail. Also, it's probably not worth adding a new function for
those remaining errors, since there are only a handful of them.Thanks for pushing this patch. I have changed the commitfest status to
"waiting for author" till 0002 patch is posted.
I'm marking this entry in commitfest as committed, I'm planning to
work on the other comments later once I finish my current project
works.
Regards,
Vignesh