From 528be70e7d64ecbe29ef0a5ed357abddeeb672bf 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/sql/aggregates.sql      |  4 +--
 23 files changed, 141 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 425bc5d06e..b037802a53 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;
 
 			/*
@@ -1081,8 +1080,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);
@@ -1555,9 +1553,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 15378a9d4d..ced80fb155 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 6c6877395f..35fd0c64e2 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 12ab33f418..8eed5a0166 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 81ef532184..70090b9b97 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 f2a928b823..2e10b5c7ee 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -10449,7 +10449,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 bf06ed9318..4642c9fe8a 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 a40b3cf752..94d6a17ed3 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 e42b7caff6..e1197dea50 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -5823,14 +5823,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/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'
 );
 
-- 
2.14.1.145.gb3622a4ee

