Hi Hackers,== Background ==While reviewing a patch, I noticed that quoteOneName() duplicates the logic of quote_identifier() for adding double quotes to identifiers. The main difference is that quoteOneName() does *not* honor the GUC `quote_all_identifiers`.The typical usage pattern of quoteOneName() looks like this:```// Define a local buffer with size MAX_QUOTED_NAME_LEN// MAX_QUOTED_NAME_LEN = MAX_NAMELEN * 2 + 3 to ensure no overflowchar attname[MAX_QUOTED_NAME_LEN];// Add quotes and copy into the stack bufferquoteOneName(attname, RIAttName(pk_rel, riinfo->pk_attnums[riinfo->nkeys - 1]));// Copy the quoted identifier into a StringInfoappendStringInfoString(&querybuf, attname);```This pattern is expensive because:* it allocates a larger-than-necessary buffer on the stack* it incurs two pallocs and two data copiesLooking further, the common pattern around quote_identifier() is similar:```appendStringInfoString(&relations, quote_identifier(relname));```This also incurs two pallocs and two copies: quote_identifier() allocates a temporary buffer and copies the quoted identifier into it, and then appendStringInfoString() may allocate and copy again.== Idea ==I'd like to propose introducing `appendStringInfoIdentifier()`, which adds the quoting logic directly to StringInfo. The goals are:* eventually deprecate quoteOneName() — I'm not aware of a reason why it should ignore the GUC `quote_all_identifiers`* simplify the usage patterns for quoting identifiers* avoid unnecessary intermediate buffers, pallocs, and data copies== About the attached patch ==Attached v1 is not intended to be the final version — it is mainly to demonstrate the idea and get feedback on the design direction.* 0001 implements `appendStringInfoIdentifier()` and uses it in a few places* 0002 switches ri_triggers.c to use it, resolving a complicated usage pattern and showing a path toward removing quoteOneName()Comments and suggestions on the overall direction would be very welcome.
Hi,
> - 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;
> }
This doesn't work from a i18n point of view. In the original
formulation, the translator is free to place the %s wherever it suits
the language. In the new one there's no such freedom: the name will be
appended at the end. Some existing translations:
ko.po:msgid "text search configuration %s"
ko.po-msgstr "%s 전문 검색 구성"
tr.po:msgid "text search configuration %s"
tr.po-msgstr "%s metin arama yapılandırması"
--
Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/
"I must say, I am absolutely impressed with what pgsql's implementation of
VALUES allows me to do. It's kind of ridiculous how much "work" goes away in
my code. Too bad I can't do this at work (Oracle 8/9)." (Tom Allison)
http://archives.postgresql.org/pgsql-general/2007-06/msg00016.php
Hi,
> - 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;
> }
This doesn't work from a i18n point of view. In the original
formulation, the translator is free to place the %s wherever it suits
the language. In the new one there's no such freedom: the name will be
appended at the end. Some existing translations:
ko.po:msgid "text search configuration %s"
ko.po-msgstr "%s 전문 검색 구성"
tr.po:msgid "text search configuration %s"
tr.po-msgstr "%s metin arama yapılandırması"
On Thu, Nov 20, 2025 at 8:28 PM Álvaro Herrera <alvherre@kurilemu.de> wrote:Hi,
> - 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;
> }
This doesn't work from a i18n point of view. In the original
formulation, the translator is free to place the %s wherever it suits
the language. In the new one there's no such freedom: the name will be
appended at the end. Some existing translations:
ko.po:msgid "text search configuration %s"
ko.po-msgstr "%s 전문 검색 구성"
tr.po:msgid "text search configuration %s"
tr.po-msgstr "%s metin arama yapılandırması"Thanks for the feedback. I reverted that piece of change in v3.Best regards,Chao Li (Evan)---------------------HighGo Software Co., Ltd.
Сайт использует файлы cookie для корректной работы и повышения удобства. Нажимая кнопку «Принять» или продолжая пользоваться сайтом, вы соглашаетесь на их использование в соответствии с Политикой в отношении обработки cookie ООО «ППГ», в том числе на передачу данных из файлов cookie сторонним статистическим и рекламным службам. Вы можете управлять настройками cookie через параметры вашего браузера