From 862bac2d223c3c6e21e65bf986d5fc4f9f7ea6f1 Mon Sep 17 00:00:00 2001 From: shihao zhong Date: Tue, 13 Oct 2026 00:08:02 -0400 Subject: [PATCH v2] psql: Don't send hidden query labels the server could reject. The labels are translated, and the translation is in the encoding of the message locale. The server converts the query from the client encoding to the database encoding. Unless all three are the same, send the query without the label if the label is not plain ASCII. The -E output still shows it. --- src/bin/psql/command.c | 4 ++-- src/bin/psql/common.c | 41 ++++++++++++++++++++++++++++++++++++++++- src/bin/psql/common.h | 1 + 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 2fc34b83a5a..5902ab36cc8 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -6246,7 +6246,7 @@ lookup_object_oid(EditableObjectType obj_type, const char *desc, destroyPQExpBuffer(query); return false; } - res = PQexec(pset.db, query->data); + res = PQexec(pset.db, skip_nonascii_label(query->data)); if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1) *obj_oid = atooid(PQgetvalue(res, 0, 0)); else @@ -6314,7 +6314,7 @@ get_create_object_cmd(EditableObjectType obj_type, Oid oid, destroyPQExpBuffer(query); return false; } - res = PQexec(pset.db, query->data); + res = PQexec(pset.db, skip_nonascii_label(query->data)); if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1) { resetPQExpBuffer(buf); diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index f220344daaf..faeedcbe0fe 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -28,6 +28,7 @@ #include "fe_utils/mbprint.h" #include "fe_utils/string_utils.h" #include "mainloop.h" +#include "mb/pg_wchar.h" #include "portability/instr_time.h" #include "settings.h" @@ -643,6 +644,44 @@ PrintTiming(double elapsed_msec) } +/* + * skip_nonascii_label + * + * A hidden query can start with a translated label in a comment. The + * translation is in the encoding of the locale, and the server converts the + * query from the client encoding to the database encoding. A label that is + * not plain ASCII is only sure to survive that if all three encodings are + * the same. Otherwise the query must be sent without the label. Returns the + * place in "query" to send from. + */ +const char * +skip_nonascii_label(const char *query) +{ + const char *end; + + if (strncmp(query, "/* ", 3) != 0 || + (end = strstr(query, " */\n")) == NULL) + return query; + + for (const char *p = query; p < end; p++) + { + if (IS_HIGHBIT_SET(*p)) + { + const char *server_enc; + + server_enc = PQparameterStatus(pset.db, "server_encoding"); + if (server_enc != NULL && + pset.encoding == pg_char_to_encoding(server_enc) && + pset.encoding == pg_get_encoding_from_locale(NULL, false)) + return query; + + return end + 4; + } + } + + return query; +} + /* * PSQLexec * @@ -687,7 +726,7 @@ PSQLexec(const char *query) SetCancelConn(pset.db); - res = PQexec(pset.db, query); + res = PQexec(pset.db, skip_nonascii_label(query)); ResetCancelConn(); diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h index d4b99b42331..352a843eec7 100644 --- a/src/bin/psql/common.h +++ b/src/bin/psql/common.h @@ -31,6 +31,7 @@ extern void psql_setup_cancel_handler(void); extern void SetShellResultVariables(int wait_result); +extern const char *skip_nonascii_label(const char *query); extern PGresult *PSQLexec(const char *query); extern int PSQLexecWatch(const char *query, const printQueryOpt *opt, FILE *printQueryFout, int min_rows); -- 2.37.1 (Apple Git-137.1)