From 05b67f72a8fc0b4578fed6fb7f82b8a423a7dd1d Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <lic@highgo.com>
Date: Mon, 17 Nov 2025 12:09:12 +0800
Subject: [PATCH v1 2/2] Apply appendStringInfoIdentifier in ri_triggers.c

Author: Chao Li <lic@highgo.com>
---
 src/backend/commands/matview.c      |   4 +-
 src/backend/utils/adt/ri_triggers.c | 188 +++++++++++++---------------
 src/backend/utils/adt/ruleutils.c   |  28 ++++-
 src/include/utils/builtins.h        |   9 +-
 4 files changed, 119 insertions(+), 110 deletions(-)

diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index ef7c0d624f1..f1ad5a8e059 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -797,9 +797,9 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
 													 NameStr(attr->attname));
 
 				generate_operator_clause(&querybuf,
-										 leftop, attrtype,
+										 NULL, leftop, attrtype, false,
 										 op,
-										 rightop, attrtype);
+										 NULL, rightop, attrtype, false);
 
 				foundUniqueIndex = true;
 			}
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index 9e13f526994..3cc4dc2b7c8 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -196,9 +196,9 @@ static void quoteOneName(char *buffer, const char *name);
 static void quoteRelationName(char *buffer, Relation rel);
 static void ri_GenerateQual(StringInfo buf,
 							const char *sep,
-							const char *leftop, Oid leftoptype,
+							const char *leftopprefix, const char *leftop, Oid leftoptype, bool quoteleftop,
 							Oid opoid,
-							const char *rightop, Oid rightoptype);
+							const char *rightopprefix, const char *rightop, Oid rightoptype, bool quoterightop);
 static void ri_GenerateQualCollation(StringInfo buf, Oid collation);
 static int	ri_NullCheck(TupleDesc tupDesc, TupleTableSlot *slot,
 						 const RI_ConstraintInfo *riinfo, bool rel_is_pk);
@@ -358,7 +358,7 @@ RI_FKey_check(TriggerData *trigdata)
 	{
 		StringInfoData querybuf;
 		char		pkrelname[MAX_QUOTED_REL_NAME_LEN];
-		char		attname[MAX_QUOTED_NAME_LEN];
+		const char *attname;
 		char		paramname[16];
 		const char *querysep;
 		Oid			queryoids[RI_MAX_NUMKEYS];
@@ -393,11 +393,11 @@ RI_FKey_check(TriggerData *trigdata)
 		quoteRelationName(pkrelname, pk_rel);
 		if (riinfo->hasperiod)
 		{
-			quoteOneName(attname,
-						 RIAttName(pk_rel, riinfo->pk_attnums[riinfo->nkeys - 1]));
+			attname = RIAttName(pk_rel, riinfo->pk_attnums[riinfo->nkeys - 1]);
+			appendStringInfoIdentifier(&querybuf, "SELECT 1 FROM (SELECT ", attname, " AS r FROM ");
 			appendStringInfo(&querybuf,
-							 "SELECT 1 FROM (SELECT %s AS r FROM %s%s x",
-							 attname, pk_only, pkrelname);
+							 "%s%s x",
+							 pk_only, pkrelname);
 		}
 		else
 		{
@@ -410,13 +410,12 @@ RI_FKey_check(TriggerData *trigdata)
 			Oid			pk_type = RIAttType(pk_rel, riinfo->pk_attnums[i]);
 			Oid			fk_type = RIAttType(fk_rel, riinfo->fk_attnums[i]);
 
-			quoteOneName(attname,
-						 RIAttName(pk_rel, riinfo->pk_attnums[i]));
+			attname = RIAttName(pk_rel, riinfo->pk_attnums[i]);
 			sprintf(paramname, "$%d", i + 1);
 			ri_GenerateQual(&querybuf, querysep,
-							attname, pk_type,
+							NULL, attname, pk_type, true,
 							riinfo->pf_eq_oprs[i],
-							paramname, fk_type);
+							NULL, paramname, fk_type, false);
 			querysep = "AND";
 			queryoids[i] = fk_type;
 		}
@@ -428,9 +427,9 @@ RI_FKey_check(TriggerData *trigdata)
 			appendStringInfoString(&querybuf, ") x1 HAVING ");
 			sprintf(paramname, "$%d", riinfo->nkeys);
 			ri_GenerateQual(&querybuf, "",
-							paramname, fk_type,
+							NULL, paramname, fk_type, false,
 							riinfo->agged_period_contained_by_oper,
-							"pg_catalog.range_agg", ANYMULTIRANGEOID);
+							NULL, "pg_catalog.range_agg", ANYMULTIRANGEOID, false);
 			appendStringInfoString(&querybuf, "(x1.r)");
 		}
 
@@ -528,7 +527,7 @@ ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel,
 	{
 		StringInfoData querybuf;
 		char		pkrelname[MAX_QUOTED_REL_NAME_LEN];
-		char		attname[MAX_QUOTED_NAME_LEN];
+		const char *attname;
 		char		paramname[16];
 		const char *querysep;
 		const char *pk_only;
@@ -563,11 +562,11 @@ ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel,
 		quoteRelationName(pkrelname, pk_rel);
 		if (riinfo->hasperiod)
 		{
-			quoteOneName(attname, RIAttName(pk_rel, riinfo->pk_attnums[riinfo->nkeys - 1]));
-
+			attname = RIAttName(pk_rel, riinfo->pk_attnums[riinfo->nkeys - 1]);
+			appendStringInfoIdentifier(&querybuf, "SELECT 1 FROM (SELECT ", attname, " AS r FROM ");
 			appendStringInfo(&querybuf,
-							 "SELECT 1 FROM (SELECT %s AS r FROM %s%s x",
-							 attname, pk_only, pkrelname);
+							 "%s%s x",
+							 pk_only, pkrelname);
 		}
 		else
 		{
@@ -579,13 +578,12 @@ ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel,
 		{
 			Oid			pk_type = RIAttType(pk_rel, riinfo->pk_attnums[i]);
 
-			quoteOneName(attname,
-						 RIAttName(pk_rel, riinfo->pk_attnums[i]));
+			attname = RIAttName(pk_rel, riinfo->pk_attnums[i]);
 			sprintf(paramname, "$%d", i + 1);
 			ri_GenerateQual(&querybuf, querysep,
-							attname, pk_type,
+							NULL, attname, pk_type, true,
 							riinfo->pp_eq_oprs[i],
-							paramname, pk_type);
+							NULL, paramname, pk_type, false);
 			querysep = "AND";
 			queryoids[i] = pk_type;
 		}
@@ -597,9 +595,9 @@ ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel,
 			appendStringInfoString(&querybuf, ") x1 HAVING ");
 			sprintf(paramname, "$%d", riinfo->nkeys);
 			ri_GenerateQual(&querybuf, "",
-							paramname, fk_type,
+							NULL, paramname, fk_type, false,
 							riinfo->agged_period_contained_by_oper,
-							"pg_catalog.range_agg", ANYMULTIRANGEOID);
+							NULL, "pg_catalog.range_agg", ANYMULTIRANGEOID, false);
 			appendStringInfoString(&querybuf, "(x1.r)");
 		}
 
@@ -757,7 +755,7 @@ ri_restrict(TriggerData *trigdata, bool is_no_action)
 		StringInfoData querybuf;
 		char		pkrelname[MAX_QUOTED_REL_NAME_LEN];
 		char		fkrelname[MAX_QUOTED_REL_NAME_LEN];
-		char		attname[MAX_QUOTED_NAME_LEN];
+		const char *attname;
 		char		periodattname[MAX_QUOTED_NAME_LEN];
 		char		paramname[16];
 		const char *querysep;
@@ -784,13 +782,12 @@ ri_restrict(TriggerData *trigdata, bool is_no_action)
 			Oid			pk_type = RIAttType(pk_rel, riinfo->pk_attnums[i]);
 			Oid			fk_type = RIAttType(fk_rel, riinfo->fk_attnums[i]);
 
-			quoteOneName(attname,
-						 RIAttName(fk_rel, riinfo->fk_attnums[i]));
+			attname = RIAttName(fk_rel, riinfo->fk_attnums[i]);
 			sprintf(paramname, "$%d", i + 1);
 			ri_GenerateQual(&querybuf, querysep,
-							paramname, pk_type,
+							NULL, paramname, pk_type, false,
 							riinfo->pf_eq_oprs[i],
-							attname, fk_type);
+							NULL, attname, fk_type, true);
 			querysep = "AND";
 			queryoids[i] = pk_type;
 		}
@@ -828,7 +825,7 @@ ri_restrict(TriggerData *trigdata, bool is_no_action)
 			char	   *pk_only = pk_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ?
 				"" : "ONLY ";
 
-			quoteOneName(attname, RIAttName(fk_rel, riinfo->fk_attnums[riinfo->nkeys - 1]));
+			attname = RIAttName(fk_rel, riinfo->fk_attnums[riinfo->nkeys - 1]);
 			sprintf(paramname, "$%d", riinfo->nkeys);
 
 			appendStringInfoString(&querybuf, " AND NOT coalesce(");
@@ -837,9 +834,9 @@ ri_restrict(TriggerData *trigdata, bool is_no_action)
 			initStringInfo(&intersectbuf);
 			appendStringInfoChar(&intersectbuf, '(');
 			ri_GenerateQual(&intersectbuf, "",
-							attname, fk_period_type,
+							NULL, attname, fk_period_type, true,
 							riinfo->period_intersect_oper,
-							paramname, pk_period_type);
+							NULL, paramname, pk_period_type, false);
 			appendStringInfoChar(&intersectbuf, ')');
 
 			/* Find the remaining history */
@@ -857,22 +854,21 @@ ri_restrict(TriggerData *trigdata, bool is_no_action)
 			{
 				Oid			pk_type = RIAttType(pk_rel, riinfo->pk_attnums[i]);
 
-				quoteOneName(attname,
-							 RIAttName(pk_rel, riinfo->pk_attnums[i]));
+				attname = RIAttName(pk_rel, riinfo->pk_attnums[i]);
 				sprintf(paramname, "$%d", i + 1);
 				ri_GenerateQual(&replacementsbuf, querysep,
-								paramname, pk_type,
+								NULL, paramname, pk_type, false,
 								riinfo->pp_eq_oprs[i],
-								attname, pk_type);
+								NULL, attname, pk_type, true);
 				querysep = "AND";
 				queryoids[i] = pk_type;
 			}
 			appendStringInfoString(&replacementsbuf, " FOR KEY SHARE OF y) y2)");
 
 			ri_GenerateQual(&querybuf, "",
-							intersectbuf.data, fk_period_type,
+							NULL, intersectbuf.data, fk_period_type, false,
 							riinfo->agged_period_contained_by_oper,
-							replacementsbuf.data, ANYMULTIRANGEOID);
+							NULL, replacementsbuf.data, ANYMULTIRANGEOID, false);
 			/* end of coalesce: */
 			appendStringInfoString(&querybuf, ", false)");
 		}
@@ -944,7 +940,7 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
 	{
 		StringInfoData querybuf;
 		char		fkrelname[MAX_QUOTED_REL_NAME_LEN];
-		char		attname[MAX_QUOTED_NAME_LEN];
+		const char *attname;
 		char		paramname[16];
 		const char *querysep;
 		Oid			queryoids[RI_MAX_NUMKEYS];
@@ -969,13 +965,12 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
 			Oid			pk_type = RIAttType(pk_rel, riinfo->pk_attnums[i]);
 			Oid			fk_type = RIAttType(fk_rel, riinfo->fk_attnums[i]);
 
-			quoteOneName(attname,
-						 RIAttName(fk_rel, riinfo->fk_attnums[i]));
+			attname = RIAttName(fk_rel, riinfo->fk_attnums[i]);
 			sprintf(paramname, "$%d", i + 1);
 			ri_GenerateQual(&querybuf, querysep,
-							paramname, pk_type,
+							NULL, paramname, pk_type, false,
 							riinfo->pf_eq_oprs[i],
-							attname, fk_type);
+							NULL, attname, fk_type, true);
 			querysep = "AND";
 			queryoids[i] = pk_type;
 		}
@@ -1050,7 +1045,7 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
 		StringInfoData querybuf;
 		StringInfoData qualbuf;
 		char		fkrelname[MAX_QUOTED_REL_NAME_LEN];
-		char		attname[MAX_QUOTED_NAME_LEN];
+		const char *attname;
 		char		paramname[16];
 		const char *querysep;
 		const char *qualsep;
@@ -1081,16 +1076,15 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
 			Oid			pk_type = RIAttType(pk_rel, riinfo->pk_attnums[i]);
 			Oid			fk_type = RIAttType(fk_rel, riinfo->fk_attnums[i]);
 
-			quoteOneName(attname,
-						 RIAttName(fk_rel, riinfo->fk_attnums[i]));
-			appendStringInfo(&querybuf,
-							 "%s %s = $%d",
-							 querysep, attname, i + 1);
+			attname = RIAttName(fk_rel, riinfo->fk_attnums[i]);
+			appendStringInfoString(&querybuf, querysep);
+			appendStringInfoIdentifier(&querybuf, " ", attname, " = ");
+			appendStringInfo(&querybuf, "$%d", i + 1);
 			sprintf(paramname, "$%d", j + 1);
 			ri_GenerateQual(&qualbuf, qualsep,
-							paramname, pk_type,
+							NULL, paramname, pk_type, false,
 							riinfo->pf_eq_oprs[i],
-							attname, fk_type);
+							NULL, attname, fk_type, true);
 			querysep = ",";
 			qualsep = "AND";
 			queryoids[i] = pk_type;
@@ -1239,7 +1233,7 @@ ri_set(TriggerData *trigdata, bool is_set_null, int tgkind)
 	{
 		StringInfoData querybuf;
 		char		fkrelname[MAX_QUOTED_REL_NAME_LEN];
-		char		attname[MAX_QUOTED_NAME_LEN];
+		const char *attname;
 		char		paramname[16];
 		const char *querysep;
 		const char *qualsep;
@@ -1297,11 +1291,10 @@ ri_set(TriggerData *trigdata, bool is_set_null, int tgkind)
 		querysep = "";
 		for (int i = 0; i < num_cols_to_set; i++)
 		{
-			quoteOneName(attname, RIAttName(fk_rel, set_cols[i]));
-			appendStringInfo(&querybuf,
-							 "%s %s = %s",
-							 querysep, attname,
-							 is_set_null ? "NULL" : "DEFAULT");
+			attname = RIAttName(fk_rel, set_cols[i]);
+			appendStringInfoString(&querybuf, querysep);
+			appendStringInfoIdentifier(&querybuf, " ", attname, " = ");
+			appendStringInfoString(&querybuf, is_set_null ? "NULL" : "DEFAULT");
 			querysep = ",";
 		}
 
@@ -1314,14 +1307,13 @@ ri_set(TriggerData *trigdata, bool is_set_null, int tgkind)
 			Oid			pk_type = RIAttType(pk_rel, riinfo->pk_attnums[i]);
 			Oid			fk_type = RIAttType(fk_rel, riinfo->fk_attnums[i]);
 
-			quoteOneName(attname,
-						 RIAttName(fk_rel, riinfo->fk_attnums[i]));
+			attname = RIAttName(fk_rel, riinfo->fk_attnums[i]);
 
 			sprintf(paramname, "$%d", i + 1);
 			ri_GenerateQual(&querybuf, qualsep,
-							paramname, pk_type,
+							NULL, paramname, pk_type, false,
 							riinfo->pf_eq_oprs[i],
-							attname, fk_type);
+							NULL, attname, fk_type, true);
 			qualsep = "AND";
 			queryoids[i] = pk_type;
 		}
@@ -1519,8 +1511,8 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
 	StringInfoData querybuf;
 	char		pkrelname[MAX_QUOTED_REL_NAME_LEN];
 	char		fkrelname[MAX_QUOTED_REL_NAME_LEN];
-	char		pkattname[MAX_QUOTED_NAME_LEN + 3];
-	char		fkattname[MAX_QUOTED_NAME_LEN + 3];
+	const char *pkattname;
+	const char *fkattname;
 	RangeTblEntry *rte;
 	RTEPermissionInfo *pk_perminfo;
 	RTEPermissionInfo *fk_perminfo;
@@ -1615,9 +1607,9 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
 	sep = "";
 	for (int i = 0; i < riinfo->nkeys; i++)
 	{
-		quoteOneName(fkattname,
-					 RIAttName(fk_rel, riinfo->fk_attnums[i]));
-		appendStringInfo(&querybuf, "%sfk.%s", sep, fkattname);
+		fkattname = RIAttName(fk_rel, riinfo->fk_attnums[i]);
+		appendStringInfoString(&querybuf, sep);
+		appendStringInfoIdentifier(&querybuf, "fk.", fkattname, NULL);
 		sep = ", ";
 	}
 
@@ -1631,8 +1623,6 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
 					 " FROM %s%s fk LEFT OUTER JOIN %s%s pk ON",
 					 fk_only, fkrelname, pk_only, pkrelname);
 
-	strcpy(pkattname, "pk.");
-	strcpy(fkattname, "fk.");
 	sep = "(";
 	for (int i = 0; i < riinfo->nkeys; i++)
 	{
@@ -1641,14 +1631,12 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
 		Oid			pk_coll = RIAttCollation(pk_rel, riinfo->pk_attnums[i]);
 		Oid			fk_coll = RIAttCollation(fk_rel, riinfo->fk_attnums[i]);
 
-		quoteOneName(pkattname + 3,
-					 RIAttName(pk_rel, riinfo->pk_attnums[i]));
-		quoteOneName(fkattname + 3,
-					 RIAttName(fk_rel, riinfo->fk_attnums[i]));
+		pkattname = RIAttName(pk_rel, riinfo->pk_attnums[i]);
+		fkattname = RIAttName(fk_rel, riinfo->fk_attnums[i]);
 		ri_GenerateQual(&querybuf, sep,
-						pkattname, pk_type,
+						"pk.", pkattname, pk_type, true,
 						riinfo->pf_eq_oprs[i],
-						fkattname, fk_type);
+						"fk.", fkattname, fk_type, true);
 		if (pk_coll != fk_coll)
 			ri_GenerateQualCollation(&querybuf, pk_coll);
 		sep = "AND";
@@ -1658,16 +1646,15 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
 	 * It's sufficient to test any one pk attribute for null to detect a join
 	 * failure.
 	 */
-	quoteOneName(pkattname, RIAttName(pk_rel, riinfo->pk_attnums[0]));
-	appendStringInfo(&querybuf, ") WHERE pk.%s IS NULL AND (", pkattname);
+	pkattname = RIAttName(pk_rel, riinfo->pk_attnums[0]);
+	appendStringInfoIdentifier(&querybuf, ") WHERE pk.", pkattname, " IS NULL AND (");
 
 	sep = "";
 	for (int i = 0; i < riinfo->nkeys; i++)
 	{
-		quoteOneName(fkattname, RIAttName(fk_rel, riinfo->fk_attnums[i]));
-		appendStringInfo(&querybuf,
-						 "%sfk.%s IS NOT NULL",
-						 sep, fkattname);
+		fkattname = RIAttName(fk_rel, riinfo->fk_attnums[i]);
+		appendStringInfoString(&querybuf, sep);
+		appendStringInfoIdentifier(&querybuf, "fk.", fkattname, " IS NOT NULL");
 		switch (riinfo->confmatchtype)
 		{
 			case FKCONSTR_MATCH_SIMPLE:
@@ -1814,8 +1801,8 @@ RI_PartitionRemove_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
 	char	   *constraintDef;
 	char		pkrelname[MAX_QUOTED_REL_NAME_LEN];
 	char		fkrelname[MAX_QUOTED_REL_NAME_LEN];
-	char		pkattname[MAX_QUOTED_NAME_LEN + 3];
-	char		fkattname[MAX_QUOTED_NAME_LEN + 3];
+	const char *pkattname;
+	const char *fkattname;
 	const char *sep;
 	const char *fk_only;
 	int			save_nestlevel;
@@ -1852,9 +1839,9 @@ RI_PartitionRemove_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
 	sep = "";
 	for (i = 0; i < riinfo->nkeys; i++)
 	{
-		quoteOneName(fkattname,
-					 RIAttName(fk_rel, riinfo->fk_attnums[i]));
-		appendStringInfo(&querybuf, "%sfk.%s", sep, fkattname);
+		fkattname = RIAttName(fk_rel, riinfo->fk_attnums[i]);
+		appendStringInfoString(&querybuf, sep);
+		appendStringInfoIdentifier(&querybuf, "fk.", fkattname, NULL);
 		sep = ", ";
 	}
 
@@ -1865,8 +1852,8 @@ RI_PartitionRemove_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
 	appendStringInfo(&querybuf,
 					 " FROM %s%s fk JOIN %s pk ON",
 					 fk_only, fkrelname, pkrelname);
-	strcpy(pkattname, "pk.");
-	strcpy(fkattname, "fk.");
+	/* strcpy(pkattname, "pk."); */
+	/* strcpy(fkattname, "fk."); */
 	sep = "(";
 	for (i = 0; i < riinfo->nkeys; i++)
 	{
@@ -1875,14 +1862,12 @@ RI_PartitionRemove_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
 		Oid			pk_coll = RIAttCollation(pk_rel, riinfo->pk_attnums[i]);
 		Oid			fk_coll = RIAttCollation(fk_rel, riinfo->fk_attnums[i]);
 
-		quoteOneName(pkattname + 3,
-					 RIAttName(pk_rel, riinfo->pk_attnums[i]));
-		quoteOneName(fkattname + 3,
-					 RIAttName(fk_rel, riinfo->fk_attnums[i]));
+		pkattname = RIAttName(pk_rel, riinfo->pk_attnums[i]);
+		fkattname = RIAttName(fk_rel, riinfo->fk_attnums[i]);
 		ri_GenerateQual(&querybuf, sep,
-						pkattname, pk_type,
+						"pk.", pkattname, pk_type, true,
 						riinfo->pf_eq_oprs[i],
-						fkattname, fk_type);
+						"fk.", fkattname, fk_type, true);
 		if (pk_coll != fk_coll)
 			ri_GenerateQualCollation(&querybuf, pk_coll);
 		sep = "AND";
@@ -1903,10 +1888,9 @@ RI_PartitionRemove_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
 	sep = "";
 	for (i = 0; i < riinfo->nkeys; i++)
 	{
-		quoteOneName(fkattname, RIAttName(fk_rel, riinfo->fk_attnums[i]));
-		appendStringInfo(&querybuf,
-						 "%sfk.%s IS NOT NULL",
-						 sep, fkattname);
+		fkattname = RIAttName(fk_rel, riinfo->fk_attnums[i]);
+		appendStringInfoString(&querybuf, sep);
+		appendStringInfoIdentifier(&querybuf, "fk.", fkattname, " IS NOT NULL");
 		switch (riinfo->confmatchtype)
 		{
 			case FKCONSTR_MATCH_SIMPLE:
@@ -2064,13 +2048,15 @@ quoteRelationName(char *buffer, Relation rel)
 static void
 ri_GenerateQual(StringInfo buf,
 				const char *sep,
-				const char *leftop, Oid leftoptype,
+				const char *leftopprefix, const char *leftop, Oid leftoptype, bool quoteleftop,
 				Oid opoid,
-				const char *rightop, Oid rightoptype)
+				const char *rightopprefix, const char *rightop, Oid rightoptype, bool quoterightop)
 {
 	appendStringInfo(buf, " %s ", sep);
-	generate_operator_clause(buf, leftop, leftoptype, opoid,
-							 rightop, rightoptype);
+	generate_operator_clause(buf,
+							 leftopprefix, leftop, leftoptype, quoteleftop,
+							 opoid,
+							 rightopprefix, rightop, rightoptype, quoterightop);
 }
 
 /*
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 1d767deb6c4..035e8441e61 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -13570,9 +13570,9 @@ generate_operator_name(Oid operid, Oid arg1, Oid arg2)
  */
 void
 generate_operator_clause(StringInfo buf,
-						 const char *leftop, Oid leftoptype,
+						 const char *leftopprefix, const char *leftop, Oid leftoptype, bool quoteleftop,
 						 Oid opoid,
-						 const char *rightop, Oid rightoptype)
+						 const char *rightopprefix, const char *rightop, Oid rightoptype, bool quoterightop)
 {
 	HeapTuple	opertup;
 	Form_pg_operator operform;
@@ -13588,12 +13588,30 @@ generate_operator_clause(StringInfo buf,
 
 	nspname = get_namespace_name(operform->oprnamespace);
 
-	appendStringInfoString(buf, leftop);
+	if (quoteleftop)
+		appendStringInfoIdentifier(buf, leftopprefix, leftop, NULL);
+	else
+	{
+		if (leftopprefix)
+			appendStringInfoString(buf, leftopprefix);
+		appendStringInfoString(buf, leftop);
+	}
+	/* appendStringInfoString(buf, leftop); */
 	if (leftoptype != operform->oprleft)
 		add_cast_to(buf, operform->oprleft);
-	appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname));
+	/* appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname)); */
+	appendStringInfoIdentifier(buf, " OPERATOR(", nspname, ".");
 	appendStringInfoString(buf, oprname);
-	appendStringInfo(buf, ") %s", rightop);
+	appendStringInfoString(buf, ") ");
+	if (quoterightop)
+		appendStringInfoIdentifier(buf, rightopprefix, rightop, NULL);
+	else
+	{
+		if (rightopprefix)
+			appendStringInfoString(buf, rightopprefix);
+		appendStringInfoString(buf, rightop);
+	}
+	/* appendStringInfo(buf, ") %s", rightop); */
 	if (rightoptype != operform->oprright)
 		add_cast_to(buf, operform->oprright);
 
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index ff4ba7265c2..fc4de4446ac 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -80,10 +80,15 @@ extern PGDLLIMPORT bool quote_all_identifiers;
 extern const char *quote_identifier(const char *ident);
 extern char *quote_qualified_identifier(const char *qualifier,
 										const char *ident);
+
+/* extern void generate_operator_clause(StringInfo buf, */
+/* 									 const char *leftop, Oid leftoptype, */
+/* 									 Oid opoid, */
+/* 									 const char *rightop, Oid rightoptype); */
 extern void generate_operator_clause(StringInfo buf,
-									 const char *leftop, Oid leftoptype,
+									 const char *leftopprefix, const char *leftop, Oid leftoptype, bool quoteleftop,
 									 Oid opoid,
-									 const char *rightop, Oid rightoptype);
+									 const char *rightopprefix, const char *rightop, Oid rightoptype, bool quoterightop);
 extern void appendStringInfoIdentifier(StringInfo str, const char *prefix, const char *ident, const char *suffix);
 extern void appendStringInfoQualifiedIdentifier(StringInfo str,
 												const char *prefix,
-- 
2.39.5 (Apple Git-154)

