v1-0001-Add-appendStringInfoIdentifier-and-use-it-in-a-fe.patch
application/octet-stream
Filename: v1-0001-Add-appendStringInfoIdentifier-and-use-it-in-a-fe.patch
Type: application/octet-stream
Part: 0
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 v1-0001
Subject: Add appendStringInfoIdentifier and use it in a few places
| File | + | − |
|---|---|---|
| src/backend/catalog/objectaddress.c | 7 | 13 |
| src/backend/commands/explain.c | 1 | 2 |
| src/backend/utils/adt/ri_triggers.c | 2 | 6 |
| src/backend/utils/adt/ruleutils.c | 120 | 22 |
| src/include/utils/builtins.h | 6 | 0 |
From c9e86872d98f4bc948fb370f582941d946887156 Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <lic@highgo.com>
Date: Fri, 14 Nov 2025 21:44:29 +0800
Subject: [PATCH v1 1/2] Add appendStringInfoIdentifier and use it in a few
places
Author: Chao Li <lic@highgo.com>
---
src/backend/catalog/objectaddress.c | 20 ++--
src/backend/commands/explain.c | 3 +-
src/backend/utils/adt/ri_triggers.c | 8 +-
src/backend/utils/adt/ruleutils.c | 142 +++++++++++++++++++++++-----
src/include/utils/builtins.h | 6 ++
5 files changed, 136 insertions(+), 43 deletions(-)
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index c75b7131ed7..fbb0b4f30f3 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -3611,9 +3611,9 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok)
else
nspname = get_namespace_name(cfgForm->cfgnamespace);
- appendStringInfo(&buffer, _("text search configuration %s"),
- quote_qualified_identifier(nspname,
- NameStr(cfgForm->cfgname)));
+ appendStringInfoQualifiedIdentifier(&buffer,
+ _("text search configuration "),
+ nspname, NameStr(cfgForm->cfgname), NULL);
ReleaseSysCache(tup);
break;
}
@@ -4883,8 +4883,7 @@ getObjectIdentityParts(const ObjectAddress *object,
if (attr)
{
- appendStringInfo(&buffer, ".%s",
- quote_identifier(attr));
+ appendStringInfoIdentifier(&buffer, ".", attr, NULL);
if (objname)
*objname = lappend(*objname, attr);
}
@@ -5395,8 +5394,7 @@ getObjectIdentityParts(const ObjectAddress *object,
object->objectId);
break;
}
- appendStringInfoString(&buffer,
- quote_identifier(nspname));
+ appendStringInfoIdentifier(&buffer, NULL, nspname, NULL);
if (objname)
*objname = list_make1(nspname);
break;
@@ -5739,16 +5737,12 @@ getObjectIdentityParts(const ObjectAddress *object,
defacl = (Form_pg_default_acl) GETSTRUCT(tup);
username = GetUserNameFromId(defacl->defaclrole, false);
- appendStringInfo(&buffer,
- "for role %s",
- quote_identifier(username));
+ appendStringInfoIdentifier(&buffer, "for role ", username, NULL);
if (OidIsValid(defacl->defaclnamespace))
{
schema = get_namespace_name_or_temp(defacl->defaclnamespace);
- appendStringInfo(&buffer,
- " in schema %s",
- quote_identifier(schema));
+ appendStringInfoIdentifier(&buffer, " in schema ", schema, NULL);
}
else
schema = NULL;
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 7e699f8595e..cc979737845 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -1705,8 +1705,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
explain_get_index_name(bitmapindexscan->indexid);
if (es->format == EXPLAIN_FORMAT_TEXT)
- appendStringInfo(es->str, " on %s",
- quote_identifier(indexname));
+ appendStringInfoIdentifier(es->str, " on ", indexname, NULL);
else
ExplainPropertyText("Index Name", indexname, es);
}
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index 059fc5ebf60..9e13f526994 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -395,7 +395,6 @@ RI_FKey_check(TriggerData *trigdata)
{
quoteOneName(attname,
RIAttName(pk_rel, riinfo->pk_attnums[riinfo->nkeys - 1]));
-
appendStringInfo(&querybuf,
"SELECT 1 FROM (SELECT %s AS r FROM %s%s x",
attname, pk_only, pkrelname);
@@ -2095,7 +2094,6 @@ ri_GenerateQualCollation(StringInfo buf, Oid collation)
HeapTuple tp;
Form_pg_collation colltup;
char *collname;
- char onename[MAX_QUOTED_NAME_LEN];
/* Nothing to do if it's a noncollatable data type */
if (!OidIsValid(collation))
@@ -2111,10 +2109,8 @@ ri_GenerateQualCollation(StringInfo buf, Oid collation)
* We qualify the name always, for simplicity and to ensure the query is
* not search-path-dependent.
*/
- quoteOneName(onename, get_namespace_name(colltup->collnamespace));
- appendStringInfo(buf, " COLLATE %s", onename);
- quoteOneName(onename, collname);
- appendStringInfo(buf, ".%s", onename);
+ appendStringInfoIdentifier(buf, " COLLATE ", get_namespace_name(colltup->collnamespace), NULL);
+ appendStringInfoIdentifier(buf, ".", collname, NULL);
ReleaseSysCache(tp);
}
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 556ab057e5a..1d767deb6c4 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -13052,25 +13052,17 @@ printSubscripts(SubscriptingRef *sbsref, deparse_context *context)
}
}
-/*
- * quote_identifier - Quote an identifier only if needed
- *
- * When quotes are needed, we palloc the required space; slightly
- * space-wasteful but well worth it for notational simplicity.
- */
-const char *
-quote_identifier(const char *ident)
+static inline bool
+is_identifier_safe(const char *ident, int *nquotes)
{
/*
* Can avoid quoting if ident starts with a lowercase letter or underscore
* and contains only lowercase letters, digits, and underscores, *and* is
* not any SQL keyword. Otherwise, supply quotes.
*/
- int nquotes = 0;
bool safe;
- const char *ptr;
- char *result;
- char *optr;
+
+ *nquotes = 0;
/*
* would like to use <ctype.h> macros here, but they might yield unwanted
@@ -13078,7 +13070,7 @@ quote_identifier(const char *ident)
*/
safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
- for (ptr = ident; *ptr; ptr++)
+ for (const char *ptr = ident; *ptr; ptr++)
{
char ch = *ptr;
@@ -13092,7 +13084,7 @@ quote_identifier(const char *ident)
{
safe = false;
if (ch == '"')
- nquotes++;
+ (*nquotes)++;
}
}
@@ -13115,14 +13107,20 @@ quote_identifier(const char *ident)
safe = false;
}
- if (safe)
- return ident; /* no change needed */
+ return safe;
+}
- result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
+static inline const char *
+quote_identifier_internal(const char *ident, int nquotes, char **result)
+{
+ char *optr;
- optr = result;
+ if (*result == NULL)
+ *result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
+
+ optr = *result;
*optr++ = '"';
- for (ptr = ident; *ptr; ptr++)
+ for (const char *ptr = ident; *ptr; ptr++)
{
char ch = *ptr;
@@ -13133,7 +13131,107 @@ quote_identifier(const char *ident)
*optr++ = '"';
*optr = '\0';
- return result;
+ return *result;
+}
+
+/*
+ * quote_identifier - Quote an identifier only if needed
+ *
+ * When quotes are needed, we palloc the required space; slightly
+ * space-wasteful but well worth it for notational simplicity.
+ */
+const char *
+quote_identifier(const char *ident)
+{
+ int nquotes;
+ bool safe;
+ char *result = NULL;
+
+ safe = is_identifier_safe(ident, &nquotes);
+ if (safe)
+ return ident; /* no change needed */
+
+ return quote_identifier_internal(ident, nquotes, &result);
+}
+
+/*
+ * appendStringInfoIdentifier
+ * Append an SQL identifier to a StringInfo, quoting if required.
+ *
+ * This behaves like writing prefix + quote_identifier(ident) + suffix into
+ * the StringInfo, but emits the identifier directly into the buffer to avoid
+ * an intermediate palloc. prefix and suffix may be NULL.
+ *
+ * The identifier is copied verbatim if it is safe to leave unquoted; otherwise
+ * it is written with double quotes and embedded double quotes are doubled.
+ * Quoting rules are local to ruleutils, so this helper is defined here rather
+ * than in stringinfo.c.
+ */
+
+void
+appendStringInfoIdentifier(StringInfo str, const char *prefix,
+ const char *ident, const char *suffix)
+{
+ int nquotes;
+ bool safe;
+ int ident_len;
+ int prefix_len = 0;
+ int suffix_len = 0;
+
+ safe = is_identifier_safe(ident, &nquotes);
+ if (safe)
+ ident_len = strlen(ident);
+ else
+ ident_len = strlen(ident) + nquotes + 2; /* quotes + possible
+ * escapes */
+
+ if (prefix != NULL)
+ prefix_len = strlen(prefix);
+
+ if (suffix != NULL)
+ suffix_len = strlen(suffix);
+
+ enlargeStringInfo(str, ident_len + prefix_len + suffix_len + 1); /* +1 for trailing null */
+
+ if (prefix != NULL)
+ appendBinaryStringInfo(str, prefix, prefix_len);
+
+ if (safe)
+ appendBinaryStringInfo(str, ident, ident_len);
+ else
+ {
+ char *result = str->data + str->len;
+
+ (void) quote_identifier_internal(ident, nquotes, &result);
+ str->len += ident_len;
+ str->data[str->len] = '\0';
+ }
+
+ if (suffix != NULL)
+ appendBinaryStringInfo(str, suffix, suffix_len);
+}
+
+/*
+ * appendStringInfoQualifiedIdentifier
+ * Append a (possibly) qualified SQL identifier to a StringInfo.
+ *
+ * Writes prefix + qualifier + '.' + ident + suffix, quoting each identifier
+ * component if needed. If no qualifier is given, only ident (plus optional
+ * prefix/suffix) is appended. prefix and suffix may be NULL.
+ *
+ * This is a convenience wrapper around appendStringInfoIdentifier().
+ */
+void
+appendStringInfoQualifiedIdentifier(StringInfo str, const char *prefix,
+ const char *qualifier, const char *ident,
+ const char *suffix)
+{
+ if (qualifier)
+ {
+ appendStringInfoIdentifier(str, prefix, qualifier, ".");
+ prefix = NULL;
+ }
+ appendStringInfoIdentifier(str, prefix, ident, suffix);
}
/*
@@ -13150,8 +13248,8 @@ quote_qualified_identifier(const char *qualifier,
initStringInfo(&buf);
if (qualifier)
- appendStringInfo(&buf, "%s.", quote_identifier(qualifier));
- appendStringInfoString(&buf, quote_identifier(ident));
+ appendStringInfoIdentifier(&buf, NULL, qualifier, ".");
+ appendStringInfoIdentifier(&buf, NULL, ident, NULL);
return buf.data;
}
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index ce6285a2c03..ff4ba7265c2 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -84,6 +84,12 @@ extern void generate_operator_clause(StringInfo buf,
const char *leftop, Oid leftoptype,
Oid opoid,
const char *rightop, Oid rightoptype);
+extern void appendStringInfoIdentifier(StringInfo str, const char *prefix, const char *ident, const char *suffix);
+extern void appendStringInfoQualifiedIdentifier(StringInfo str,
+ const char *prefix,
+ const char *qualifier,
+ const char *ident,
+ const char *suffix);
/* varchar.c */
extern int bpchartruelen(char *s, int len);
--
2.39.5 (Apple Git-154)