From 3df6b46c313333f897dec3e2455a6fe1b75893b2 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <daniel@yesql.se>
Date: Wed, 10 Jan 2018 23:26:45 +0100
Subject: [PATCH 1/2] Use strcmp() instead of pg_strcasecmp() for identifier
 matching

Since these option values are parsed using either the IDENT rule,
via keyword rules, or are created in lowercase with makeString(),
using strcmp() is the correct approach here.  While not wrong per
se, using case insensitive matching can hide subtle bugs in case
defnames are created with mixed-case as these options otherwise
are assumed to always be lowercased.

The parsing of the PARALLEL option in the old style syntax for
CREATE AGGREGATE was fixed to allow using strcmp as well.

Reorder a few checks while in there such that all checks are in
the same order to make it easier to grep/read.

Also remove comment in tsearchcmds.c:getTokenTypes() regarding
strcmp/pg_strcasecmp as the code is correct. token_type is parsed
using the IDENT rule and will always be in lowercase.
---
 contrib/dict_int/dict_int.c                    |  4 +-
 contrib/dict_xsyn/dict_xsyn.c                  | 10 ++---
 contrib/unaccent/unaccent.c                    |  2 +-
 doc/src/sgml/ref/create_aggregate.sgml         |  1 +
 doc/src/sgml/ref/create_function.sgml          |  1 -
 src/backend/access/common/reloptions.c         | 18 ++++-----
 src/backend/commands/aggregatecmds.c           | 56 +++++++++++++-------------
 src/backend/commands/collationcmds.c           | 12 +++---
 src/backend/commands/functioncmds.c            |  6 +++
 src/backend/commands/operatorcmds.c            | 44 ++++++++++----------
 src/backend/commands/tablecmds.c               |  2 +-
 src/backend/commands/tsearchcmds.c             | 23 +++++------
 src/backend/commands/typecmds.c                | 48 +++++++++++-----------
 src/backend/commands/view.c                    |  6 +--
 src/backend/parser/gram.y                      | 10 +++--
 src/backend/parser/parse_clause.c              |  2 +-
 src/backend/snowball/dict_snowball.c           |  4 +-
 src/backend/tsearch/dict_ispell.c              |  6 +--
 src/backend/tsearch/dict_simple.c              |  4 +-
 src/backend/tsearch/dict_synonym.c             |  4 +-
 src/backend/tsearch/dict_thesaurus.c           |  4 +-
 src/test/regress/expected/aggregates.out       |  4 +-
 src/test/regress/expected/alter_generic.out    |  6 +++
 src/test/regress/expected/alter_operator.out   |  3 ++
 src/test/regress/expected/collate.out          |  5 +++
 src/test/regress/expected/create_aggregate.out | 30 ++++++++++++++
 src/test/regress/expected/create_operator.out  | 23 +++++++++++
 src/test/regress/expected/create_table.out     |  3 ++
 src/test/regress/expected/create_type.out      | 28 +++++++++++++
 src/test/regress/expected/tsdicts.out          | 10 +++++
 src/test/regress/sql/aggregates.sql            |  4 +-
 src/test/regress/sql/alter_generic.sql         |  6 +++
 src/test/regress/sql/alter_operator.sql        |  3 ++
 src/test/regress/sql/collate.sql               |  2 +
 src/test/regress/sql/create_aggregate.sql      | 19 +++++++++
 src/test/regress/sql/create_operator.sql       | 14 +++++++
 src/test/regress/sql/create_table.sql          |  3 ++
 src/test/regress/sql/create_type.sql           | 11 +++++
 src/test/regress/sql/tsdicts.sql               | 10 +++++
 39 files changed, 317 insertions(+), 134 deletions(-)

diff --git a/contrib/dict_int/dict_int.c b/contrib/dict_int/dict_int.c
index 8b45532938..56ede37089 100644
--- a/contrib/dict_int/dict_int.c
+++ b/contrib/dict_int/dict_int.c
@@ -42,11 +42,11 @@ dintdict_init(PG_FUNCTION_ARGS)
 	{
 		DefElem    *defel = (DefElem *) lfirst(l);
 
-		if (pg_strcasecmp(defel->defname, "MAXLEN") == 0)
+		if (strcmp(defel->defname, "maxlen") == 0)
 		{
 			d->maxlen = atoi(defGetString(defel));
 		}
-		else if (pg_strcasecmp(defel->defname, "REJECTLONG") == 0)
+		else if (strcmp(defel->defname, "rejectlong") == 0)
 		{
 			d->rejectlong = defGetBoolean(defel);
 		}
diff --git a/contrib/dict_xsyn/dict_xsyn.c b/contrib/dict_xsyn/dict_xsyn.c
index 8a3abf7e3c..a79ece240c 100644
--- a/contrib/dict_xsyn/dict_xsyn.c
+++ b/contrib/dict_xsyn/dict_xsyn.c
@@ -157,23 +157,23 @@ dxsyn_init(PG_FUNCTION_ARGS)
 	{
 		DefElem    *defel = (DefElem *) lfirst(l);
 
-		if (pg_strcasecmp(defel->defname, "MATCHORIG") == 0)
+		if (strcmp(defel->defname, "matchorig") == 0)
 		{
 			d->matchorig = defGetBoolean(defel);
 		}
-		else if (pg_strcasecmp(defel->defname, "KEEPORIG") == 0)
+		else if (strcmp(defel->defname, "keeporig") == 0)
 		{
 			d->keeporig = defGetBoolean(defel);
 		}
-		else if (pg_strcasecmp(defel->defname, "MATCHSYNONYMS") == 0)
+		else if (strcmp(defel->defname, "matchsynonyms") == 0)
 		{
 			d->matchsynonyms = defGetBoolean(defel);
 		}
-		else if (pg_strcasecmp(defel->defname, "KEEPSYNONYMS") == 0)
+		else if (strcmp(defel->defname, "keepsynonyms") == 0)
 		{
 			d->keepsynonyms = defGetBoolean(defel);
 		}
-		else if (pg_strcasecmp(defel->defname, "RULES") == 0)
+		else if (strcmp(defel->defname, "rules") == 0)
 		{
 			/* we can't read the rules before parsing all options! */
 			filename = defGetString(defel);
diff --git a/contrib/unaccent/unaccent.c b/contrib/unaccent/unaccent.c
index 82f9c7fcfe..247c202755 100644
--- a/contrib/unaccent/unaccent.c
+++ b/contrib/unaccent/unaccent.c
@@ -276,7 +276,7 @@ unaccent_init(PG_FUNCTION_ARGS)
 	{
 		DefElem    *defel = (DefElem *) lfirst(l);
 
-		if (pg_strcasecmp("Rules", defel->defname) == 0)
+		if (strcmp(defel->defname, "rules") == 0)
 		{
 			if (fileloaded)
 				ereport(ERROR,
diff --git a/doc/src/sgml/ref/create_aggregate.sgml b/doc/src/sgml/ref/create_aggregate.sgml
index a4aaae876e..c46491991b 100644
--- a/doc/src/sgml/ref/create_aggregate.sgml
+++ b/doc/src/sgml/ref/create_aggregate.sgml
@@ -80,6 +80,7 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> (
     [ , MFINALFUNC_MODIFY = { READ_ONLY | SHARABLE | READ_WRITE } ]
     [ , MINITCOND = <replaceable class="parameter">minitial_condition</replaceable> ]
     [ , SORTOP = <replaceable class="parameter">sort_operator</replaceable> ]
+    [ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ]
 )
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/create_function.sgml b/doc/src/sgml/ref/create_function.sgml
index fd229d1193..869b8b396c 100644
--- a/doc/src/sgml/ref/create_function.sgml
+++ b/doc/src/sgml/ref/create_function.sgml
@@ -590,7 +590,6 @@ CREATE [ OR REPLACE ] FUNCTION
 
       </variablelist>
 
-      Attribute names are not case-sensitive.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 274f7aa8e9..a6de891eec 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -796,7 +796,7 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
 				}
 				else if (def->defnamespace == NULL)
 					continue;
-				else if (pg_strcasecmp(def->defnamespace, namspace) != 0)
+				else if (strcmp(def->defnamespace, namspace) != 0)
 					continue;
 
 				kw_len = strlen(def->defname);
@@ -849,8 +849,7 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
 				{
 					for (i = 0; validnsps[i]; i++)
 					{
-						if (pg_strcasecmp(def->defnamespace,
-										  validnsps[i]) == 0)
+						if (strcmp(def->defnamespace, validnsps[i]) == 0)
 						{
 							valid = true;
 							break;
@@ -865,7 +864,7 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
 									def->defnamespace)));
 			}
 
-			if (ignoreOids && pg_strcasecmp(def->defname, "oids") == 0)
+			if (ignoreOids && strcmp(def->defname, "oids") == 0)
 				continue;
 
 			/* ignore if not in the same namespace */
@@ -876,7 +875,7 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
 			}
 			else if (def->defnamespace == NULL)
 				continue;
-			else if (pg_strcasecmp(def->defnamespace, namspace) != 0)
+			else if (strcmp(def->defnamespace, namspace) != 0)
 				continue;
 
 			/*
@@ -1082,8 +1081,7 @@ parseRelOptions(Datum options, bool validate, relopt_kind kind,
 				int			kw_len = reloptions[j].gen->namelen;
 
 				if (text_len > kw_len && text_str[kw_len] == '=' &&
-					pg_strncasecmp(text_str, reloptions[j].gen->name,
-								   kw_len) == 0)
+					strncmp(text_str, reloptions[j].gen->name, kw_len) == 0)
 				{
 					parse_one_reloption(&reloptions[j], text_str, text_len,
 										validate);
@@ -1556,9 +1554,9 @@ AlterTableGetRelOptionsLockLevel(List *defList)
 
 		for (i = 0; relOpts[i]; i++)
 		{
-			if (pg_strncasecmp(relOpts[i]->name,
-							   def->defname,
-							   relOpts[i]->namelen + 1) == 0)
+			if (strncmp(relOpts[i]->name,
+						def->defname,
+						relOpts[i]->namelen + 1) == 0)
 			{
 				if (lockmode < relOpts[i]->lockmode)
 					lockmode = relOpts[i]->lockmode;
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index 1779ba7bcb..a48c3ac572 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -127,37 +127,37 @@ DefineAggregate(ParseState *pstate, List *name, List *args, bool oldstyle, List
 		 * sfunc1, stype1, and initcond1 are accepted as obsolete spellings
 		 * for sfunc, stype, initcond.
 		 */
-		if (pg_strcasecmp(defel->defname, "sfunc") == 0)
+		if (strcmp(defel->defname, "sfunc") == 0)
 			transfuncName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "sfunc1") == 0)
+		else if (strcmp(defel->defname, "sfunc1") == 0)
 			transfuncName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "finalfunc") == 0)
+		else if (strcmp(defel->defname, "finalfunc") == 0)
 			finalfuncName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "combinefunc") == 0)
+		else if (strcmp(defel->defname, "combinefunc") == 0)
 			combinefuncName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "serialfunc") == 0)
+		else if (strcmp(defel->defname, "serialfunc") == 0)
 			serialfuncName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "deserialfunc") == 0)
+		else if (strcmp(defel->defname, "deserialfunc") == 0)
 			deserialfuncName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "msfunc") == 0)
+		else if (strcmp(defel->defname, "msfunc") == 0)
 			mtransfuncName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "minvfunc") == 0)
+		else if (strcmp(defel->defname, "minvfunc") == 0)
 			minvtransfuncName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "mfinalfunc") == 0)
+		else if (strcmp(defel->defname, "mfinalfunc") == 0)
 			mfinalfuncName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "finalfunc_extra") == 0)
+		else if (strcmp(defel->defname, "finalfunc_extra") == 0)
 			finalfuncExtraArgs = defGetBoolean(defel);
-		else if (pg_strcasecmp(defel->defname, "mfinalfunc_extra") == 0)
+		else if (strcmp(defel->defname, "mfinalfunc_extra") == 0)
 			mfinalfuncExtraArgs = defGetBoolean(defel);
-		else if (pg_strcasecmp(defel->defname, "finalfunc_modify") == 0)
+		else if (strcmp(defel->defname, "finalfunc_modify") == 0)
 			finalfuncModify = extractModify(defel);
-		else if (pg_strcasecmp(defel->defname, "mfinalfunc_modify") == 0)
+		else if (strcmp(defel->defname, "mfinalfunc_modify") == 0)
 			mfinalfuncModify = extractModify(defel);
-		else if (pg_strcasecmp(defel->defname, "sortop") == 0)
+		else if (strcmp(defel->defname, "sortop") == 0)
 			sortoperatorName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "basetype") == 0)
+		else if (strcmp(defel->defname, "basetype") == 0)
 			baseType = defGetTypeName(defel);
-		else if (pg_strcasecmp(defel->defname, "hypothetical") == 0)
+		else if (strcmp(defel->defname, "hypothetical") == 0)
 		{
 			if (defGetBoolean(defel))
 			{
@@ -168,23 +168,23 @@ DefineAggregate(ParseState *pstate, List *name, List *args, bool oldstyle, List
 				aggKind = AGGKIND_HYPOTHETICAL;
 			}
 		}
-		else if (pg_strcasecmp(defel->defname, "stype") == 0)
+		else if (strcmp(defel->defname, "stype") == 0)
 			transType = defGetTypeName(defel);
-		else if (pg_strcasecmp(defel->defname, "stype1") == 0)
+		else if (strcmp(defel->defname, "stype1") == 0)
 			transType = defGetTypeName(defel);
-		else if (pg_strcasecmp(defel->defname, "sspace") == 0)
+		else if (strcmp(defel->defname, "sspace") == 0)
 			transSpace = defGetInt32(defel);
-		else if (pg_strcasecmp(defel->defname, "mstype") == 0)
+		else if (strcmp(defel->defname, "mstype") == 0)
 			mtransType = defGetTypeName(defel);
-		else if (pg_strcasecmp(defel->defname, "msspace") == 0)
+		else if (strcmp(defel->defname, "msspace") == 0)
 			mtransSpace = defGetInt32(defel);
-		else if (pg_strcasecmp(defel->defname, "initcond") == 0)
+		else if (strcmp(defel->defname, "initcond") == 0)
 			initval = defGetString(defel);
-		else if (pg_strcasecmp(defel->defname, "initcond1") == 0)
+		else if (strcmp(defel->defname, "initcond1") == 0)
 			initval = defGetString(defel);
-		else if (pg_strcasecmp(defel->defname, "minitcond") == 0)
+		else if (strcmp(defel->defname, "minitcond") == 0)
 			minitval = defGetString(defel);
-		else if (pg_strcasecmp(defel->defname, "parallel") == 0)
+		else if (strcmp(defel->defname, "parallel") == 0)
 			parallel = defGetString(defel);
 		else
 			ereport(WARNING,
@@ -420,11 +420,11 @@ DefineAggregate(ParseState *pstate, List *name, List *args, bool oldstyle, List
 
 	if (parallel)
 	{
-		if (pg_strcasecmp(parallel, "safe") == 0)
+		if (strcmp(parallel, "safe") == 0)
 			proparallel = PROPARALLEL_SAFE;
-		else if (pg_strcasecmp(parallel, "restricted") == 0)
+		else if (strcmp(parallel, "restricted") == 0)
 			proparallel = PROPARALLEL_RESTRICTED;
-		else if (pg_strcasecmp(parallel, "unsafe") == 0)
+		else if (strcmp(parallel, "unsafe") == 0)
 			proparallel = PROPARALLEL_UNSAFE;
 		else
 			ereport(ERROR,
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index fdfb3dcd2c..d0b5cdb69a 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -82,17 +82,17 @@ DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_e
 		DefElem    *defel = lfirst_node(DefElem, pl);
 		DefElem   **defelp;
 
-		if (pg_strcasecmp(defel->defname, "from") == 0)
+		if (strcmp(defel->defname, "from") == 0)
 			defelp = &fromEl;
-		else if (pg_strcasecmp(defel->defname, "locale") == 0)
+		else if (strcmp(defel->defname, "locale") == 0)
 			defelp = &localeEl;
-		else if (pg_strcasecmp(defel->defname, "lc_collate") == 0)
+		else if (strcmp(defel->defname, "lc_collate") == 0)
 			defelp = &lccollateEl;
-		else if (pg_strcasecmp(defel->defname, "lc_ctype") == 0)
+		else if (strcmp(defel->defname, "lc_ctype") == 0)
 			defelp = &lcctypeEl;
-		else if (pg_strcasecmp(defel->defname, "provider") == 0)
+		else if (strcmp(defel->defname, "provider") == 0)
 			defelp = &providerEl;
-		else if (pg_strcasecmp(defel->defname, "version") == 0)
+		else if (strcmp(defel->defname, "version") == 0)
 			defelp = &versionEl;
 		else
 		{
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index ea08c3237c..3ede99ef67 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -811,6 +811,12 @@ compute_attributes_with_style(ParseState *pstate, bool is_procedure, List *param
 	{
 		DefElem    *param = (DefElem *) lfirst(pl);
 
+		/*
+		 * Attribute names from the parser should always be in casefolded into
+		 * lowercase, but for the old attributes isStrict and isCachable the
+		 * manual has since 7.3 stated that they are not case-sensitive so for
+		 * now use pg_strcasecmp().
+		 */
 		if (pg_strcasecmp(param->defname, "isstrict") == 0)
 		{
 			if (is_procedure)
diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c
index 35404ac39a..585382d758 100644
--- a/src/backend/commands/operatorcmds.c
+++ b/src/backend/commands/operatorcmds.c
@@ -105,7 +105,7 @@ DefineOperator(List *names, List *parameters)
 	{
 		DefElem    *defel = (DefElem *) lfirst(pl);
 
-		if (pg_strcasecmp(defel->defname, "leftarg") == 0)
+		if (strcmp(defel->defname, "leftarg") == 0)
 		{
 			typeName1 = defGetTypeName(defel);
 			if (typeName1->setof)
@@ -113,7 +113,7 @@ DefineOperator(List *names, List *parameters)
 						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
 						 errmsg("SETOF type not allowed for operator argument")));
 		}
-		else if (pg_strcasecmp(defel->defname, "rightarg") == 0)
+		else if (strcmp(defel->defname, "rightarg") == 0)
 		{
 			typeName2 = defGetTypeName(defel);
 			if (typeName2->setof)
@@ -121,28 +121,28 @@ DefineOperator(List *names, List *parameters)
 						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
 						 errmsg("SETOF type not allowed for operator argument")));
 		}
-		else if (pg_strcasecmp(defel->defname, "procedure") == 0)
+		else if (strcmp(defel->defname, "procedure") == 0)
 			functionName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "commutator") == 0)
+		else if (strcmp(defel->defname, "commutator") == 0)
 			commutatorName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "negator") == 0)
+		else if (strcmp(defel->defname, "negator") == 0)
 			negatorName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "restrict") == 0)
+		else if (strcmp(defel->defname, "restrict") == 0)
 			restrictionName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "join") == 0)
+		else if (strcmp(defel->defname, "join") == 0)
 			joinName = defGetQualifiedName(defel);
-		else if (pg_strcasecmp(defel->defname, "hashes") == 0)
+		else if (strcmp(defel->defname, "hashes") == 0)
 			canHash = defGetBoolean(defel);
-		else if (pg_strcasecmp(defel->defname, "merges") == 0)
+		else if (strcmp(defel->defname, "merges") == 0)
 			canMerge = defGetBoolean(defel);
 		/* These obsolete options are taken as meaning canMerge */
-		else if (pg_strcasecmp(defel->defname, "sort1") == 0)
+		else if (strcmp(defel->defname, "sort1") == 0)
 			canMerge = true;
-		else if (pg_strcasecmp(defel->defname, "sort2") == 0)
+		else if (strcmp(defel->defname, "sort2") == 0)
 			canMerge = true;
-		else if (pg_strcasecmp(defel->defname, "ltcmp") == 0)
+		else if (strcmp(defel->defname, "ltcmp") == 0)
 			canMerge = true;
-		else if (pg_strcasecmp(defel->defname, "gtcmp") == 0)
+		else if (strcmp(defel->defname, "gtcmp") == 0)
 			canMerge = true;
 		else
 		{
@@ -420,12 +420,12 @@ AlterOperator(AlterOperatorStmt *stmt)
 		else
 			param = defGetQualifiedName(defel);
 
-		if (pg_strcasecmp(defel->defname, "restrict") == 0)
+		if (strcmp(defel->defname, "restrict") == 0)
 		{
 			restrictionName = param;
 			updateRestriction = true;
 		}
-		else if (pg_strcasecmp(defel->defname, "join") == 0)
+		else if (strcmp(defel->defname, "join") == 0)
 		{
 			joinName = param;
 			updateJoin = true;
@@ -435,13 +435,13 @@ AlterOperator(AlterOperatorStmt *stmt)
 		 * The rest of the options that CREATE accepts cannot be changed.
 		 * Check for them so that we can give a meaningful error message.
 		 */
-		else if (pg_strcasecmp(defel->defname, "leftarg") == 0 ||
-				 pg_strcasecmp(defel->defname, "rightarg") == 0 ||
-				 pg_strcasecmp(defel->defname, "procedure") == 0 ||
-				 pg_strcasecmp(defel->defname, "commutator") == 0 ||
-				 pg_strcasecmp(defel->defname, "negator") == 0 ||
-				 pg_strcasecmp(defel->defname, "hashes") == 0 ||
-				 pg_strcasecmp(defel->defname, "merges") == 0)
+		else if (strcmp(defel->defname, "leftarg") == 0 ||
+				 strcmp(defel->defname, "rightarg") == 0 ||
+				 strcmp(defel->defname, "procedure") == 0 ||
+				 strcmp(defel->defname, "commutator") == 0 ||
+				 strcmp(defel->defname, "negator") == 0 ||
+				 strcmp(defel->defname, "hashes") == 0 ||
+				 strcmp(defel->defname, "merges") == 0)
 		{
 			ereport(ERROR,
 					(errcode(ERRCODE_SYNTAX_ERROR),
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 2e768dd5e4..ea03fd2ecf 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -10536,7 +10536,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 		{
 			DefElem    *defel = (DefElem *) lfirst(cell);
 
-			if (pg_strcasecmp(defel->defname, "check_option") == 0)
+			if (strcmp(defel->defname, "check_option") == 0)
 				check_option = true;
 		}
 
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index bdf3857ce4..3a843512d1 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -209,27 +209,27 @@ DefineTSParser(List *names, List *parameters)
 	{
 		DefElem    *defel = (DefElem *) lfirst(pl);
 
-		if (pg_strcasecmp(defel->defname, "start") == 0)
+		if (strcmp(defel->defname, "start") == 0)
 		{
 			values[Anum_pg_ts_parser_prsstart - 1] =
 				get_ts_parser_func(defel, Anum_pg_ts_parser_prsstart);
 		}
-		else if (pg_strcasecmp(defel->defname, "gettoken") == 0)
+		else if (strcmp(defel->defname, "gettoken") == 0)
 		{
 			values[Anum_pg_ts_parser_prstoken - 1] =
 				get_ts_parser_func(defel, Anum_pg_ts_parser_prstoken);
 		}
-		else if (pg_strcasecmp(defel->defname, "end") == 0)
+		else if (strcmp(defel->defname, "end") == 0)
 		{
 			values[Anum_pg_ts_parser_prsend - 1] =
 				get_ts_parser_func(defel, Anum_pg_ts_parser_prsend);
 		}
-		else if (pg_strcasecmp(defel->defname, "headline") == 0)
+		else if (strcmp(defel->defname, "headline") == 0)
 		{
 			values[Anum_pg_ts_parser_prsheadline - 1] =
 				get_ts_parser_func(defel, Anum_pg_ts_parser_prsheadline);
 		}
-		else if (pg_strcasecmp(defel->defname, "lextypes") == 0)
+		else if (strcmp(defel->defname, "lextypes") == 0)
 		{
 			values[Anum_pg_ts_parser_prslextype - 1] =
 				get_ts_parser_func(defel, Anum_pg_ts_parser_prslextype);
@@ -438,7 +438,7 @@ DefineTSDictionary(List *names, List *parameters)
 	{
 		DefElem    *defel = (DefElem *) lfirst(pl);
 
-		if (pg_strcasecmp(defel->defname, "template") == 0)
+		if (strcmp(defel->defname, "template") == 0)
 		{
 			templId = get_ts_template_oid(defGetQualifiedName(defel), false);
 		}
@@ -580,7 +580,7 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt)
 			DefElem    *oldel = (DefElem *) lfirst(cell);
 
 			next = lnext(cell);
-			if (pg_strcasecmp(oldel->defname, defel->defname) == 0)
+			if (strcmp(oldel->defname, defel->defname) == 0)
 				dictoptions = list_delete_cell(dictoptions, cell, prev);
 			else
 				prev = cell;
@@ -765,13 +765,13 @@ DefineTSTemplate(List *names, List *parameters)
 	{
 		DefElem    *defel = (DefElem *) lfirst(pl);
 
-		if (pg_strcasecmp(defel->defname, "init") == 0)
+		if (strcmp(defel->defname, "init") == 0)
 		{
 			values[Anum_pg_ts_template_tmplinit - 1] =
 				get_ts_template_func(defel, Anum_pg_ts_template_tmplinit);
 			nulls[Anum_pg_ts_template_tmplinit - 1] = false;
 		}
-		else if (pg_strcasecmp(defel->defname, "lexize") == 0)
+		else if (strcmp(defel->defname, "lexize") == 0)
 		{
 			values[Anum_pg_ts_template_tmpllexize - 1] =
 				get_ts_template_func(defel, Anum_pg_ts_template_tmpllexize);
@@ -990,9 +990,9 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied)
 	{
 		DefElem    *defel = (DefElem *) lfirst(pl);
 
-		if (pg_strcasecmp(defel->defname, "parser") == 0)
+		if (strcmp(defel->defname, "parser") == 0)
 			prsOid = get_ts_parser_oid(defGetQualifiedName(defel), false);
-		else if (pg_strcasecmp(defel->defname, "copy") == 0)
+		else if (strcmp(defel->defname, "copy") == 0)
 			sourceOid = get_ts_config_oid(defGetQualifiedName(defel), false);
 		else
 			ereport(ERROR,
@@ -1251,7 +1251,6 @@ getTokenTypes(Oid prsId, List *tokennames)
 		j = 0;
 		while (list && list[j].lexid)
 		{
-			/* XXX should we use pg_strcasecmp here? */
 			if (strcmp(strVal(val), list[j].alias) == 0)
 			{
 				res[i] = list[j].lexid;
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 74eb430f96..899a5c4cd4 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -245,42 +245,42 @@ DefineType(ParseState *pstate, List *names, List *parameters)
 		DefElem    *defel = (DefElem *) lfirst(pl);
 		DefElem   **defelp;
 
-		if (pg_strcasecmp(defel->defname, "like") == 0)
+		if (strcmp(defel->defname, "like") == 0)
 			defelp = &likeTypeEl;
-		else if (pg_strcasecmp(defel->defname, "internallength") == 0)
+		else if (strcmp(defel->defname, "internallength") == 0)
 			defelp = &internalLengthEl;
-		else if (pg_strcasecmp(defel->defname, "input") == 0)
+		else if (strcmp(defel->defname, "input") == 0)
 			defelp = &inputNameEl;
-		else if (pg_strcasecmp(defel->defname, "output") == 0)
+		else if (strcmp(defel->defname, "output") == 0)
 			defelp = &outputNameEl;
-		else if (pg_strcasecmp(defel->defname, "receive") == 0)
+		else if (strcmp(defel->defname, "receive") == 0)
 			defelp = &receiveNameEl;
-		else if (pg_strcasecmp(defel->defname, "send") == 0)
+		else if (strcmp(defel->defname, "send") == 0)
 			defelp = &sendNameEl;
-		else if (pg_strcasecmp(defel->defname, "typmod_in") == 0)
+		else if (strcmp(defel->defname, "typmod_in") == 0)
 			defelp = &typmodinNameEl;
-		else if (pg_strcasecmp(defel->defname, "typmod_out") == 0)
+		else if (strcmp(defel->defname, "typmod_out") == 0)
 			defelp = &typmodoutNameEl;
-		else if (pg_strcasecmp(defel->defname, "analyze") == 0 ||
-				 pg_strcasecmp(defel->defname, "analyse") == 0)
+		else if (strcmp(defel->defname, "analyze") == 0 ||
+				 strcmp(defel->defname, "analyse") == 0)
 			defelp = &analyzeNameEl;
-		else if (pg_strcasecmp(defel->defname, "category") == 0)
+		else if (strcmp(defel->defname, "category") == 0)
 			defelp = &categoryEl;
-		else if (pg_strcasecmp(defel->defname, "preferred") == 0)
+		else if (strcmp(defel->defname, "preferred") == 0)
 			defelp = &preferredEl;
-		else if (pg_strcasecmp(defel->defname, "delimiter") == 0)
+		else if (strcmp(defel->defname, "delimiter") == 0)
 			defelp = &delimiterEl;
-		else if (pg_strcasecmp(defel->defname, "element") == 0)
+		else if (strcmp(defel->defname, "element") == 0)
 			defelp = &elemTypeEl;
-		else if (pg_strcasecmp(defel->defname, "default") == 0)
+		else if (strcmp(defel->defname, "default") == 0)
 			defelp = &defaultValueEl;
-		else if (pg_strcasecmp(defel->defname, "passedbyvalue") == 0)
+		else if (strcmp(defel->defname, "passedbyvalue") == 0)
 			defelp = &byValueEl;
-		else if (pg_strcasecmp(defel->defname, "alignment") == 0)
+		else if (strcmp(defel->defname, "alignment") == 0)
 			defelp = &alignmentEl;
-		else if (pg_strcasecmp(defel->defname, "storage") == 0)
+		else if (strcmp(defel->defname, "storage") == 0)
 			defelp = &storageEl;
-		else if (pg_strcasecmp(defel->defname, "collatable") == 0)
+		else if (strcmp(defel->defname, "collatable") == 0)
 			defelp = &collatableEl;
 		else
 		{
@@ -1439,7 +1439,7 @@ DefineRange(CreateRangeStmt *stmt)
 	{
 		DefElem    *defel = (DefElem *) lfirst(lc);
 
-		if (pg_strcasecmp(defel->defname, "subtype") == 0)
+		if (strcmp(defel->defname, "subtype") == 0)
 		{
 			if (OidIsValid(rangeSubtype))
 				ereport(ERROR,
@@ -1448,7 +1448,7 @@ DefineRange(CreateRangeStmt *stmt)
 			/* we can look up the subtype name immediately */
 			rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
 		}
-		else if (pg_strcasecmp(defel->defname, "subtype_opclass") == 0)
+		else if (strcmp(defel->defname, "subtype_opclass") == 0)
 		{
 			if (rangeSubOpclassName != NIL)
 				ereport(ERROR,
@@ -1456,7 +1456,7 @@ DefineRange(CreateRangeStmt *stmt)
 						 errmsg("conflicting or redundant options")));
 			rangeSubOpclassName = defGetQualifiedName(defel);
 		}
-		else if (pg_strcasecmp(defel->defname, "collation") == 0)
+		else if (strcmp(defel->defname, "collation") == 0)
 		{
 			if (rangeCollationName != NIL)
 				ereport(ERROR,
@@ -1464,7 +1464,7 @@ DefineRange(CreateRangeStmt *stmt)
 						 errmsg("conflicting or redundant options")));
 			rangeCollationName = defGetQualifiedName(defel);
 		}
-		else if (pg_strcasecmp(defel->defname, "canonical") == 0)
+		else if (strcmp(defel->defname, "canonical") == 0)
 		{
 			if (rangeCanonicalName != NIL)
 				ereport(ERROR,
@@ -1472,7 +1472,7 @@ DefineRange(CreateRangeStmt *stmt)
 						 errmsg("conflicting or redundant options")));
 			rangeCanonicalName = defGetQualifiedName(defel);
 		}
-		else if (pg_strcasecmp(defel->defname, "subtype_diff") == 0)
+		else if (strcmp(defel->defname, "subtype_diff") == 0)
 		{
 			if (rangeSubtypeDiffName != NIL)
 				ereport(ERROR,
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index 04ad76a210..7d4511c585 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -46,8 +46,8 @@ void
 validateWithCheckOption(const char *value)
 {
 	if (value == NULL ||
-		(pg_strcasecmp(value, "local") != 0 &&
-		 pg_strcasecmp(value, "cascaded") != 0))
+		(strcmp(value, "local") != 0 &&
+		 strcmp(value, "cascaded") != 0))
 	{
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -485,7 +485,7 @@ DefineView(ViewStmt *stmt, const char *queryString,
 	{
 		DefElem    *defel = (DefElem *) lfirst(cell);
 
-		if (pg_strcasecmp(defel->defname, "check_option") == 0)
+		if (strcmp(defel->defname, "check_option") == 0)
 			check_option = true;
 	}
 
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 459a227e57..9fb8a8ee6f 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -5848,14 +5848,18 @@ old_aggr_list: old_aggr_elem						{ $$ = list_make1($1); }
 		;
 
 /*
- * Must use IDENT here to avoid reduce/reduce conflicts; fortunately none of
- * the item names needed in old aggregate definitions are likely to become
- * SQL keywords.
+ * Must use IDENT here to avoid reduce/reduce conflicts; fortunately, with
+ * the exception of PARALLEL, none of the item names needed in old aggregate
+ * definitions are likely to become keywords.
  */
 old_aggr_elem:  IDENT '=' def_arg
 				{
 					$$ = makeDefElem($1, (Node *)$3, @1);
 				}
+				| PARALLEL '=' def_arg
+				{
+					$$ = makeDefElem("parallel", (Node *)$3, @1);
+				}
 		;
 
 opt_enum_val_list:
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 9fbcfd4fa6..406cd1dad0 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -262,7 +262,7 @@ interpretOidsOption(List *defList, bool allowOids)
 		DefElem    *def = (DefElem *) lfirst(cell);
 
 		if (def->defnamespace == NULL &&
-			pg_strcasecmp(def->defname, "oids") == 0)
+			strcmp(def->defname, "oids") == 0)
 		{
 			if (!allowOids)
 				ereport(ERROR,
diff --git a/src/backend/snowball/dict_snowball.c b/src/backend/snowball/dict_snowball.c
index 043681ec2d..78c9f73ef0 100644
--- a/src/backend/snowball/dict_snowball.c
+++ b/src/backend/snowball/dict_snowball.c
@@ -192,7 +192,7 @@ dsnowball_init(PG_FUNCTION_ARGS)
 	{
 		DefElem    *defel = (DefElem *) lfirst(l);
 
-		if (pg_strcasecmp("StopWords", defel->defname) == 0)
+		if (strcmp(defel->defname, "stopwords") == 0)
 		{
 			if (stoploaded)
 				ereport(ERROR,
@@ -201,7 +201,7 @@ dsnowball_init(PG_FUNCTION_ARGS)
 			readstoplist(defGetString(defel), &d->stoplist, lowerstr);
 			stoploaded = true;
 		}
-		else if (pg_strcasecmp("Language", defel->defname) == 0)
+		else if (strcmp(defel->defname, "language") == 0)
 		{
 			if (d->stem)
 				ereport(ERROR,
diff --git a/src/backend/tsearch/dict_ispell.c b/src/backend/tsearch/dict_ispell.c
index 0d706795ad..edc6547700 100644
--- a/src/backend/tsearch/dict_ispell.c
+++ b/src/backend/tsearch/dict_ispell.c
@@ -44,7 +44,7 @@ dispell_init(PG_FUNCTION_ARGS)
 	{
 		DefElem    *defel = (DefElem *) lfirst(l);
 
-		if (pg_strcasecmp(defel->defname, "DictFile") == 0)
+		if (strcmp(defel->defname, "dictfile") == 0)
 		{
 			if (dictloaded)
 				ereport(ERROR,
@@ -55,7 +55,7 @@ dispell_init(PG_FUNCTION_ARGS)
 														   "dict"));
 			dictloaded = true;
 		}
-		else if (pg_strcasecmp(defel->defname, "AffFile") == 0)
+		else if (strcmp(defel->defname, "afffile") == 0)
 		{
 			if (affloaded)
 				ereport(ERROR,
@@ -66,7 +66,7 @@ dispell_init(PG_FUNCTION_ARGS)
 														"affix"));
 			affloaded = true;
 		}
-		else if (pg_strcasecmp(defel->defname, "StopWords") == 0)
+		else if (strcmp(defel->defname, "stopwords") == 0)
 		{
 			if (stoploaded)
 				ereport(ERROR,
diff --git a/src/backend/tsearch/dict_simple.c b/src/backend/tsearch/dict_simple.c
index 268b4e48cf..ac6a24eba5 100644
--- a/src/backend/tsearch/dict_simple.c
+++ b/src/backend/tsearch/dict_simple.c
@@ -41,7 +41,7 @@ dsimple_init(PG_FUNCTION_ARGS)
 	{
 		DefElem    *defel = (DefElem *) lfirst(l);
 
-		if (pg_strcasecmp("StopWords", defel->defname) == 0)
+		if (strcmp(defel->defname, "stopwords") == 0)
 		{
 			if (stoploaded)
 				ereport(ERROR,
@@ -50,7 +50,7 @@ dsimple_init(PG_FUNCTION_ARGS)
 			readstoplist(defGetString(defel), &d->stoplist, lowerstr);
 			stoploaded = true;
 		}
-		else if (pg_strcasecmp("Accept", defel->defname) == 0)
+		else if (strcmp(defel->defname, "accept") == 0)
 		{
 			if (acceptloaded)
 				ereport(ERROR,
diff --git a/src/backend/tsearch/dict_synonym.c b/src/backend/tsearch/dict_synonym.c
index 8ca65f3ded..c011886cb0 100644
--- a/src/backend/tsearch/dict_synonym.c
+++ b/src/backend/tsearch/dict_synonym.c
@@ -108,9 +108,9 @@ dsynonym_init(PG_FUNCTION_ARGS)
 	{
 		DefElem    *defel = (DefElem *) lfirst(l);
 
-		if (pg_strcasecmp("Synonyms", defel->defname) == 0)
+		if (strcmp(defel->defname, "synonyms") == 0)
 			filename = defGetString(defel);
-		else if (pg_strcasecmp("CaseSensitive", defel->defname) == 0)
+		else if (strcmp(defel->defname, "casesensitive") == 0)
 			case_sensitive = defGetBoolean(defel);
 		else
 			ereport(ERROR,
diff --git a/src/backend/tsearch/dict_thesaurus.c b/src/backend/tsearch/dict_thesaurus.c
index 23aaac8d07..24364e646d 100644
--- a/src/backend/tsearch/dict_thesaurus.c
+++ b/src/backend/tsearch/dict_thesaurus.c
@@ -616,7 +616,7 @@ thesaurus_init(PG_FUNCTION_ARGS)
 	{
 		DefElem    *defel = (DefElem *) lfirst(l);
 
-		if (pg_strcasecmp("DictFile", defel->defname) == 0)
+		if (strcmp(defel->defname, "dictfile") == 0)
 		{
 			if (fileloaded)
 				ereport(ERROR,
@@ -625,7 +625,7 @@ thesaurus_init(PG_FUNCTION_ARGS)
 			thesaurusRead(defGetString(defel), d);
 			fileloaded = true;
 		}
-		else if (pg_strcasecmp("Dictionary", defel->defname) == 0)
+		else if (strcmp(defel->defname, "dictionary") == 0)
 		{
 			if (subdictname)
 				ereport(ERROR,
diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out
index dbce7d3e8b..81943f3396 100644
--- a/src/test/regress/expected/aggregates.out
+++ b/src/test/regress/expected/aggregates.out
@@ -2011,7 +2011,7 @@ CREATE AGGREGATE balk(
     BASETYPE = int4,
     SFUNC = balkifnull(int8, int4),
     STYPE = int8,
-    "PARALLEL" = SAFE,
+    PARALLEL = SAFE,
     INITCOND = '0');
 SELECT balk(hundred) FROM tenk1;
  balk 
@@ -2040,7 +2040,7 @@ CREATE AGGREGATE balk(
     SFUNC = int4_sum(int8, int4),
     STYPE = int8,
     COMBINEFUNC = balkifnull(int8, int8),
-    "PARALLEL" = SAFE,
+    PARALLEL = SAFE,
     INITCOND = '0'
 );
 -- force use of parallelism
diff --git a/src/test/regress/expected/alter_generic.out b/src/test/regress/expected/alter_generic.out
index 767c09bec5..10efca6d8c 100644
--- a/src/test/regress/expected/alter_generic.out
+++ b/src/test/regress/expected/alter_generic.out
@@ -644,6 +644,9 @@ SELECT nspname, tmplname
  alt_nsp2 | alt_ts_temp2
 (3 rows)
 
+-- invalid: non-lowercase quoted identifiers
+CREATE TEXT SEARCH TEMPLATE tstemp_case ("Init" = init_function);
+ERROR:  text search template parameter "Init" not recognized
 --
 -- Text Search Parser
 --
@@ -670,6 +673,9 @@ SELECT nspname, prsname
  alt_nsp2 | alt_ts_prs2
 (3 rows)
 
+-- invalid: non-lowercase quoted identifiers
+CREATE TEXT SEARCH PARSER tspars_case ("Start" = start_function);
+ERROR:  text search parser parameter "Start" not recognized
 ---
 --- Cleanup resources
 ---
diff --git a/src/test/regress/expected/alter_operator.out b/src/test/regress/expected/alter_operator.out
index ef47affd7b..96236c38a0 100644
--- a/src/test/regress/expected/alter_operator.out
+++ b/src/test/regress/expected/alter_operator.out
@@ -128,6 +128,9 @@ CREATE USER regress_alter_op_user;
 SET SESSION AUTHORIZATION regress_alter_op_user;
 ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = NONE);
 ERROR:  must be owner of operator ===
+-- invalid: non-lowercase quoted identifiers
+ALTER OPERATOR & (bit, bit) SET ("Restrict" = _int_contsel, "Join" = _int_contjoinsel);
+ERROR:  operator attribute "Restrict" not recognized
 -- Clean up
 RESET SESSION AUTHORIZATION;
 DROP USER regress_alter_op_user;
diff --git a/src/test/regress/expected/collate.out b/src/test/regress/expected/collate.out
index b0025c0a87..64572872d7 100644
--- a/src/test/regress/expected/collate.out
+++ b/src/test/regress/expected/collate.out
@@ -633,6 +633,11 @@ DROP COLLATION mycoll2;  -- fail
 ERROR:  cannot drop collation mycoll2 because other objects depend on it
 DETAIL:  table collate_test23 column f1 depends on collation mycoll2
 HINT:  Use DROP ... CASCADE to drop the dependent objects too.
+-- invalid: non-lowercase identifiers
+CREATE COLLATION case_coll ("Lc_Collate" = "POSIX", "Lc_Ctype" = "POSIX");
+ERROR:  collation attribute "Lc_Collate" not recognized
+LINE 1: CREATE COLLATION case_coll ("Lc_Collate" = "POSIX", "Lc_Ctyp...
+                                    ^
 -- 9.1 bug with useless COLLATE in an expression subject to length coercion
 CREATE TEMP TABLE vctable (f1 varchar(25));
 INSERT INTO vctable VALUES ('foo' COLLATE "C");
diff --git a/src/test/regress/expected/create_aggregate.out b/src/test/regress/expected/create_aggregate.out
index ef65cd54ca..38d4e7994f 100644
--- a/src/test/regress/expected/create_aggregate.out
+++ b/src/test/regress/expected/create_aggregate.out
@@ -195,3 +195,33 @@ CREATE AGGREGATE wrongreturntype (float8)
     minvfunc = float8mi_int
 );
 ERROR:  return type of inverse transition function float8mi_int is not double precision
+-- invalid: non-lowercase identifiers
+CREATE AGGREGATE case_agg ( -- old syntax
+	"Sfunc1" = int4pl,
+	"Basetype" = int4,
+	"Stype1" = int4,
+	"Initcond1" = '0',
+	"Parallel" = safe
+);
+WARNING:  aggregate attribute "Sfunc1" not recognized
+WARNING:  aggregate attribute "Basetype" not recognized
+WARNING:  aggregate attribute "Stype1" not recognized
+WARNING:  aggregate attribute "Initcond1" not recognized
+WARNING:  aggregate attribute "Parallel" not recognized
+ERROR:  aggregate stype must be specified
+CREATE AGGREGATE case_agg(float8)
+(
+	"Stype" = internal,
+	"Sfunc" = ordered_set_transition,
+	"Finalfunc" = percentile_disc_final,
+	"Finalfunc_extra" = true,
+	"Finalfunc_modify" = read_write,
+	"Parallel" = safe
+);
+WARNING:  aggregate attribute "Stype" not recognized
+WARNING:  aggregate attribute "Sfunc" not recognized
+WARNING:  aggregate attribute "Finalfunc" not recognized
+WARNING:  aggregate attribute "Finalfunc_extra" not recognized
+WARNING:  aggregate attribute "Finalfunc_modify" not recognized
+WARNING:  aggregate attribute "Parallel" not recognized
+ERROR:  aggregate stype must be specified
diff --git a/src/test/regress/expected/create_operator.out b/src/test/regress/expected/create_operator.out
index 3a216c2ca8..3c4ccae1e7 100644
--- a/src/test/regress/expected/create_operator.out
+++ b/src/test/regress/expected/create_operator.out
@@ -172,3 +172,26 @@ CREATE OPERATOR #*# (
 );
 ERROR:  permission denied for type type_op6
 ROLLBACK;
+-- invalid: non-lowercase quoted identifiers
+CREATE OPERATOR ===
+(
+	"Leftarg" = box,
+	"Rightarg" = box,
+	"Procedure" = area_equal_procedure,
+	"Commutator" = ===,
+	"Negator" = !==,
+	"Restrict" = area_restriction_procedure,
+	"Join" = area_join_procedure,
+	"Hashes",
+	"Merges"
+);
+WARNING:  operator attribute "Leftarg" not recognized
+WARNING:  operator attribute "Rightarg" not recognized
+WARNING:  operator attribute "Procedure" not recognized
+WARNING:  operator attribute "Commutator" not recognized
+WARNING:  operator attribute "Negator" not recognized
+WARNING:  operator attribute "Restrict" not recognized
+WARNING:  operator attribute "Join" not recognized
+WARNING:  operator attribute "Hashes" not recognized
+WARNING:  operator attribute "Merges" not recognized
+ERROR:  operator procedure must be specified
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index 8e745402ae..552d7b09dc 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -863,3 +863,6 @@ Partition key: LIST (a)
 Number of partitions: 0
 
 DROP TABLE parted_col_comment;
+-- invalid: non-lowercase quoted reloptions identifiers
+CREATE TABLE tas_case WITH ("Fillfactor" = 10) AS SELECT 1 a;
+ERROR:  unrecognized parameter "Fillfactor"
diff --git a/src/test/regress/expected/create_type.out b/src/test/regress/expected/create_type.out
index 5886a1f37f..2139860861 100644
--- a/src/test/regress/expected/create_type.out
+++ b/src/test/regress/expected/create_type.out
@@ -154,3 +154,31 @@ WHERE attrelid = 'mytab'::regclass AND attnum > 0;
  widget(42,13)
 (1 row)
 
+-- invalid: non-lowercase quoted identifiers
+CREATE TYPE case_int42 (
+	"Internallength" = 4,
+	"Input" = int42_in,
+	"Output" = int42_out,
+	"Alignment" = int4,
+	"Default" = 42,
+	"Passedbyvalue"
+);
+WARNING:  type attribute "Internallength" not recognized
+LINE 2:  "Internallength" = 4,
+         ^
+WARNING:  type attribute "Input" not recognized
+LINE 3:  "Input" = int42_in,
+         ^
+WARNING:  type attribute "Output" not recognized
+LINE 4:  "Output" = int42_out,
+         ^
+WARNING:  type attribute "Alignment" not recognized
+LINE 5:  "Alignment" = int4,
+         ^
+WARNING:  type attribute "Default" not recognized
+LINE 6:  "Default" = 42,
+         ^
+WARNING:  type attribute "Passedbyvalue" not recognized
+LINE 7:  "Passedbyvalue"
+         ^
+ERROR:  type input function must be specified
diff --git a/src/test/regress/expected/tsdicts.out b/src/test/regress/expected/tsdicts.out
index 0744ef803b..e01402d42b 100644
--- a/src/test/regress/expected/tsdicts.out
+++ b/src/test/regress/expected/tsdicts.out
@@ -580,3 +580,13 @@ SELECT to_tsvector('thesaurus_tst', 'Booking tickets is looking like a booking a
  'card':3,10 'invit':2,9 'like':6 'look':5 'order':1,8
 (1 row)
 
+-- invalid: non-lowercase quoted identifiers
+CREATE TEXT SEARCH DICTIONARY tsdict_case
+(
+	"Template" = ispell,
+	"DictFile" = ispell_sample,
+	"AffFile" = ispell_sample
+);
+ERROR:  text search template is required
+ALTER TEXT SEARCH DICTIONARY tsdict_case ("Dictfile" = ispell_sample);
+ERROR:  text search dictionary "tsdict_case" does not exist
diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql
index 6c9b86a616..6833b7ffce 100644
--- a/src/test/regress/sql/aggregates.sql
+++ b/src/test/regress/sql/aggregates.sql
@@ -865,7 +865,7 @@ CREATE AGGREGATE balk(
     BASETYPE = int4,
     SFUNC = balkifnull(int8, int4),
     STYPE = int8,
-    "PARALLEL" = SAFE,
+    PARALLEL = SAFE,
     INITCOND = '0');
 
 SELECT balk(hundred) FROM tenk1;
@@ -893,7 +893,7 @@ CREATE AGGREGATE balk(
     SFUNC = int4_sum(int8, int4),
     STYPE = int8,
     COMBINEFUNC = balkifnull(int8, int8),
-    "PARALLEL" = SAFE,
+    PARALLEL = SAFE,
     INITCOND = '0'
 );
 
diff --git a/src/test/regress/sql/alter_generic.sql b/src/test/regress/sql/alter_generic.sql
index 311812e351..63882a3101 100644
--- a/src/test/regress/sql/alter_generic.sql
+++ b/src/test/regress/sql/alter_generic.sql
@@ -548,6 +548,9 @@ SELECT nspname, tmplname
   WHERE t.tmplnamespace = n.oid AND nspname like 'alt_nsp%'
   ORDER BY nspname, tmplname;
 
+-- invalid: non-lowercase quoted identifiers
+CREATE TEXT SEARCH TEMPLATE tstemp_case ("Init" = init_function);
+
 --
 -- Text Search Parser
 --
@@ -570,6 +573,9 @@ SELECT nspname, prsname
   WHERE t.prsnamespace = n.oid AND nspname like 'alt_nsp%'
   ORDER BY nspname, prsname;
 
+-- invalid: non-lowercase quoted identifiers
+CREATE TEXT SEARCH PARSER tspars_case ("Start" = start_function);
+
 ---
 --- Cleanup resources
 ---
diff --git a/src/test/regress/sql/alter_operator.sql b/src/test/regress/sql/alter_operator.sql
index 51ffd7e0e0..bfffba7257 100644
--- a/src/test/regress/sql/alter_operator.sql
+++ b/src/test/regress/sql/alter_operator.sql
@@ -89,6 +89,9 @@ SET SESSION AUTHORIZATION regress_alter_op_user;
 
 ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = NONE);
 
+-- invalid: non-lowercase quoted identifiers
+ALTER OPERATOR & (bit, bit) SET ("Restrict" = _int_contsel, "Join" = _int_contjoinsel);
+
 -- Clean up
 RESET SESSION AUTHORIZATION;
 DROP USER regress_alter_op_user;
diff --git a/src/test/regress/sql/collate.sql b/src/test/regress/sql/collate.sql
index 698f577490..fe53a18881 100644
--- a/src/test/regress/sql/collate.sql
+++ b/src/test/regress/sql/collate.sql
@@ -239,6 +239,8 @@ DROP COLLATION mycoll1;
 CREATE TABLE collate_test23 (f1 text collate mycoll2);
 DROP COLLATION mycoll2;  -- fail
 
+-- invalid: non-lowercase identifiers
+CREATE COLLATION case_coll ("Lc_Collate" = "POSIX", "Lc_Ctype" = "POSIX");
 
 -- 9.1 bug with useless COLLATE in an expression subject to length coercion
 
diff --git a/src/test/regress/sql/create_aggregate.sql b/src/test/regress/sql/create_aggregate.sql
index 46e773bfe3..0b0bd3ed18 100644
--- a/src/test/regress/sql/create_aggregate.sql
+++ b/src/test/regress/sql/create_aggregate.sql
@@ -211,3 +211,22 @@ CREATE AGGREGATE wrongreturntype (float8)
     msfunc = float8pl,
     minvfunc = float8mi_int
 );
+
+-- invalid: non-lowercase identifiers
+CREATE AGGREGATE case_agg ( -- old syntax
+	"Sfunc1" = int4pl,
+	"Basetype" = int4,
+	"Stype1" = int4,
+	"Initcond1" = '0',
+	"Parallel" = safe
+);
+
+CREATE AGGREGATE case_agg(float8)
+(
+	"Stype" = internal,
+	"Sfunc" = ordered_set_transition,
+	"Finalfunc" = percentile_disc_final,
+	"Finalfunc_extra" = true,
+	"Finalfunc_modify" = read_write,
+	"Parallel" = safe
+);
diff --git a/src/test/regress/sql/create_operator.sql b/src/test/regress/sql/create_operator.sql
index 0e5d6356bc..bb9907b3ed 100644
--- a/src/test/regress/sql/create_operator.sql
+++ b/src/test/regress/sql/create_operator.sql
@@ -179,3 +179,17 @@ CREATE OPERATOR #*# (
    procedure = fn_op6
 );
 ROLLBACK;
+
+-- invalid: non-lowercase quoted identifiers
+CREATE OPERATOR ===
+(
+	"Leftarg" = box,
+	"Rightarg" = box,
+	"Procedure" = area_equal_procedure,
+	"Commutator" = ===,
+	"Negator" = !==,
+	"Restrict" = area_restriction_procedure,
+	"Join" = area_join_procedure,
+	"Hashes",
+	"Merges"
+);
diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql
index 8f9991ef18..3142817b22 100644
--- a/src/test/regress/sql/create_table.sql
+++ b/src/test/regress/sql/create_table.sql
@@ -707,3 +707,6 @@ COMMENT ON COLUMN parted_col_comment.a IS 'Partition key';
 SELECT obj_description('parted_col_comment'::regclass);
 \d+ parted_col_comment
 DROP TABLE parted_col_comment;
+
+-- invalid: non-lowercase quoted reloptions identifiers
+CREATE TABLE tas_case WITH ("Fillfactor" = 10) AS SELECT 1 a;
diff --git a/src/test/regress/sql/create_type.sql b/src/test/regress/sql/create_type.sql
index a28303aa6a..ef9acdb4f6 100644
--- a/src/test/regress/sql/create_type.sql
+++ b/src/test/regress/sql/create_type.sql
@@ -134,3 +134,14 @@ CREATE TEMP TABLE mytab (foo widget(42,13));
 
 SELECT format_type(atttypid,atttypmod) FROM pg_attribute
 WHERE attrelid = 'mytab'::regclass AND attnum > 0;
+
+-- invalid: non-lowercase quoted identifiers
+
+CREATE TYPE case_int42 (
+	"Internallength" = 4,
+	"Input" = int42_in,
+	"Output" = int42_out,
+	"Alignment" = int4,
+	"Default" = 42,
+	"Passedbyvalue"
+);
diff --git a/src/test/regress/sql/tsdicts.sql b/src/test/regress/sql/tsdicts.sql
index a5a569e1ad..77ba073cca 100644
--- a/src/test/regress/sql/tsdicts.sql
+++ b/src/test/regress/sql/tsdicts.sql
@@ -188,3 +188,13 @@ ALTER TEXT SEARCH CONFIGURATION thesaurus_tst ALTER MAPPING FOR
 SELECT to_tsvector('thesaurus_tst', 'one postgres one two one two three one');
 SELECT to_tsvector('thesaurus_tst', 'Supernovae star is very new star and usually called supernovae (abbreviation SN)');
 SELECT to_tsvector('thesaurus_tst', 'Booking tickets is looking like a booking a tickets');
+
+-- invalid: non-lowercase quoted identifiers
+CREATE TEXT SEARCH DICTIONARY tsdict_case
+(
+	"Template" = ispell,
+	"DictFile" = ispell_sample,
+	"AffFile" = ispell_sample
+);
+
+ALTER TEXT SEARCH DICTIONARY tsdict_case ("Dictfile" = ispell_sample);
-- 
2.14.1.145.gb3622a4ee

