v3-0002-Use-appendStringInfoIdentifier-throughout-ri_trig.patch
application/octet-stream
Filename: v3-0002-Use-appendStringInfoIdentifier-throughout-ri_trig.patch
Type: application/octet-stream
Part: 3
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v3-0002
Subject: Use appendStringInfoIdentifier() throughout ri_triggers.c
| File | + | − |
|---|---|---|
| src/backend/commands/matview.c | 2 | 2 |
| src/backend/utils/adt/ri_triggers.c | 87 | 101 |
| src/backend/utils/adt/ruleutils.c | 24 | 7 |
| src/include/utils/builtins.h | 2 | 2 |
From 8043be01f1883ff419c1a732be73cbe05021dbf3 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 v3 2/4] Use appendStringInfoIdentifier() throughout
ri_triggers.c
Replace most uses of quoteOneName() and manual stack buffers in
ri_triggers.c with appendStringInfoIdentifier() and related infrastructure.
This simplifies the construction of SQL queries generated by RI triggers and
eliminates the need for MAX_QUOTED_NAME_LEN / stack-allocated intermediate
buffers. It also removes several code paths where identifiers were quoted
manually, making the quoting rules consistent with ruleutils.c and the GUC
quote_all_identifiers.
This commit also adjusts generate_operator_clause() to support prefixed
arguments and identifier quoting directly, reducing the number of places
where callers need to inject string concatenation logic.
No user-visible behavior change is intended; the generated SQL should be
equivalent to the previous version.
Author: Chao Li <lic@highgo.com>
Discussion: https://postgr.es/m/CAEoWx2=g2RVkxXB=JzWphgfg4QGV+spaA3PQ1rBM2iMehrVvjg@mail.gmail.com
---
src/backend/commands/matview.c | 4 +-
src/backend/utils/adt/ri_triggers.c | 188 +++++++++++++---------------
src/backend/utils/adt/ruleutils.c | 31 +++--
src/include/utils/builtins.h | 4 +-
4 files changed, 115 insertions(+), 112 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..b212a28d9be 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;
@@ -13585,15 +13585,32 @@ generate_operator_clause(StringInfo buf,
operform = (Form_pg_operator) GETSTRUCT(opertup);
Assert(operform->oprkind == 'b');
oprname = NameStr(operform->oprname);
-
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);
+ }
+
if (leftoptype != operform->oprleft)
add_cast_to(buf, operform->oprleft);
- appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname));
- appendStringInfoString(buf, oprname);
- appendStringInfo(buf, ") %s", rightop);
+
+ appendStringInfoIdentifier(buf, " OPERATOR(", nspname, ".");
+ appendStringInfo(buf, "%s) ", oprname);
+
+ if (quoterightop)
+ appendStringInfoIdentifier(buf, rightopprefix, rightop, NULL);
+ else
+ {
+ if (rightopprefix)
+ appendStringInfoString(buf, rightopprefix);
+ appendStringInfoString(buf, 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..4bd04e1a57a 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -81,9 +81,9 @@ 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,
+ 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)