v5-0002-Use-appendStringInfoIdentifier-throughout-ri_trig.patch
application/octet-stream
Filename: v5-0002-Use-appendStringInfoIdentifier-throughout-ri_trig.patch
Type: application/octet-stream
Part: 1
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 v5-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 10f4505cb302df59e74446104e21bf6ca2e72609 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 v5 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 f7d8007f796..96aa4553168 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 dc8f40eff12..e55fa8c6574 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -274,9 +274,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);
@@ -491,7 +491,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];
@@ -526,11 +526,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
{
@@ -543,13 +543,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;
}
@@ -561,9 +560,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)");
}
@@ -661,7 +660,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;
@@ -696,11 +695,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
{
@@ -712,13 +711,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;
}
@@ -730,9 +728,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)");
}
@@ -890,7 +888,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;
@@ -917,13 +915,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;
}
@@ -961,7 +958,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(");
@@ -970,9 +967,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 */
@@ -990,22 +987,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)");
}
@@ -1077,7 +1073,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];
@@ -1102,13 +1098,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;
}
@@ -1183,7 +1178,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;
@@ -1214,16 +1209,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;
@@ -1372,7 +1366,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;
@@ -1430,11 +1424,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 = ",";
}
@@ -1447,14 +1440,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;
}
@@ -1652,8 +1644,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;
@@ -1748,9 +1740,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 = ", ";
}
@@ -1764,8 +1756,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++)
{
@@ -1774,14 +1764,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";
@@ -1791,16 +1779,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:
@@ -1947,8 +1934,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;
@@ -1985,9 +1972,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 = ", ";
}
@@ -1998,8 +1985,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++)
{
@@ -2008,14 +1995,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";
@@ -2036,10 +2021,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:
@@ -2197,13 +2181,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 af4a56f7bd7..8dcab752ca5 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -14190,9 +14190,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;
@@ -14205,15 +14205,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 7dbbb4c7c7f..adb1f51768f 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -82,9 +82,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.50.1 (Apple Git-155)