index 707a3fc844c32638671aa61e8b564fbe6cb2e894..b9d7ab98c3e6f99d0d49ca1960f03027121315b2 100644 (file)
@@ -2822,6 +2822,7 @@ processEncodingEntry(ArchiveHandle *AH, TocEntry *te)
pg_fatal("unrecognized encoding \"%s\"",
ptr1);
AH->public.encoding = encoding;
+ setFmtEncoding(encoding);
}
else
pg_fatal("invalid ENCODING item: %s",
index 520e1338c28b6b188361e55bf31c0c65acf5735b..ca15b40939cb9a433d11098e58d6fcc550793245 100644 (file)
@@ -1281,6 +1281,7 @@ setup_connection(Archive *AH, const char *dumpencoding,
* we know how to escape strings.
*/
AH->encoding = PQclientEncoding(conn);
+ setFmtEncoding(AH->encoding);
std_strings = PQparameterStatus(conn, "standard_conforming_strings");
AH->std_strings = (std_strings && strcmp(std_strings, "on") == 0);
index 396f79781c5e4e93399c9e82c6f2f7acd6c0f8df..64a60a260928dc50704eb54b276c08dc7cca2e01 100644 (file)
* we know how to escape strings.
*/
encoding = PQclientEncoding(conn);
+ setFmtEncoding(encoding);
std_strings = PQparameterStatus(conn, "standard_conforming_strings");
if (!std_strings)
std_strings = "off";
index 6c75c8da6da63c9ba282a905eed1ecc3bb3c099a..26dfdde195a48813d58ccea69b5346d9a1ffd688 100644 (file)
@@ -1450,6 +1450,7 @@ exec_command_encoding(PsqlScanState scan_state, bool active_branch)
/* save encoding info into psql internal data */
pset.encoding = PQclientEncoding(pset.db);
pset.popt.topt.encoding = pset.encoding;
+ setFmtEncoding(pset.encoding);
SetVariable(pset.vars, "ENCODING",
pg_encoding_to_char(pset.encoding));
}
pset.popt.topt.encoding = pset.encoding;
pset.sversion = PQserverVersion(pset.db);
+ setFmtEncoding(pset.encoding);
+
SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
SetVariable(pset.vars, "SERVICE", PQservice(pset.db));
SetVariable(pset.vars, "USER", PQuser(pset.db));
index 343e8618a56c9c04553d11d3565f5045600fdf06..7b8f7d4c52661d42b40e2e789d6c2f23cc7dc8f3 100644 (file)
@@ -111,8 +111,9 @@ appendQualifiedRelation(PQExpBuffer buf, const char *spec,
exit(1);
}
appendPQExpBufferStr(buf,
- fmtQualifiedId(PQgetvalue(res, 0, 1),
- PQgetvalue(res, 0, 0)));
+ fmtQualifiedIdEnc(PQgetvalue(res, 0, 1),
+ PQgetvalue(res, 0, 0),
+ PQclientEncoding(conn)));
appendPQExpBufferStr(buf, columns);
PQclear(res);
termPQExpBuffer(&sql);
index b0e4747786274c02920548bae15769b44a12e1fc..7c0cf32d6a11b0ce7f2ec3705922aa07fc4ee897 100644 (file)
conn = connectMaintenanceDatabase(&cparams, progname, echo);
+ setFmtEncoding(PQclientEncoding(conn));
+
initPQExpBuffer(&sql);
appendPQExpBuffer(&sql, "CREATE DATABASE %s",
index 6aaf8332770445cead915cc3f4c4bf3885b27ff9..81e6abfc46e708dd9ce3b421f4bb96ca4d7462bc 100644 (file)
conn = connectMaintenanceDatabase(&cparams, progname, echo);
+ setFmtEncoding(PQclientEncoding(conn));
+
initPQExpBuffer(&sql);
printfPQExpBuffer(&sql, "CREATE ROLE %s", fmtId(newuser));
index ad762ffd43ab705bb189d0762108845b1d806be5..0b630818277130bf09fd0f48ad4f9402d4244754 100644 (file)
exit(0);
}
- initPQExpBuffer(&sql);
-
- appendPQExpBuffer(&sql, "DROP DATABASE %s%s%s;",
- (if_exists ? "IF EXISTS " : ""),
- fmtId(dbname),
- force ? " WITH (FORCE)" : "");
-
/* Avoid trying to drop postgres db while we are connected to it. */
if (maintenance_db == NULL && strcmp(dbname, "postgres") == 0)
maintenance_db = "template1";
conn = connectMaintenanceDatabase(&cparams, progname, echo);
+ initPQExpBuffer(&sql);
+ appendPQExpBuffer(&sql, "DROP DATABASE %s%s%s;",
+ (if_exists ? "IF EXISTS " : ""),
+ fmtIdEnc(dbname, PQclientEncoding(conn)),
+ force ? " WITH (FORCE)" : "");
+
if (echo)
printf("%s\n", sql.data);
result = PQexec(conn, sql.data);
index 8e5429a5cf1455839e72a665e483ad2e75b394a1..39bb16861736f7a2dc436e6378c0f784c7c1d9e0 100644 (file)
initPQExpBuffer(&sql);
appendPQExpBuffer(&sql, "DROP ROLE %s%s;",
- (if_exists ? "IF EXISTS " : ""), fmtId(dropuser));
+ (if_exists ? "IF EXISTS " : ""),
+ fmtIdEnc(dropuser, PQclientEncoding(conn)));
if (echo)
printf("%s\n", sql.data);
index 076462a62f003b3f09c1c26c55de8eb3129a253b..665864fd22be0fa659445c6bfcc00435647510df 100644 (file)
@@ -511,7 +511,8 @@ run_reindex_command(PGconn *conn, ReindexType type, const char *name,
if (tablespace)
{
- appendPQExpBuffer(&sql, "%sTABLESPACE %s", sep, fmtId(tablespace));
+ appendPQExpBuffer(&sql, "%sTABLESPACE %s", sep,
+ fmtIdEnc(tablespace, PQclientEncoding(conn)));
sep = comma;
}
@@ -551,7 +552,8 @@ run_reindex_command(PGconn *conn, ReindexType type, const char *name,
{
case REINDEX_DATABASE:
case REINDEX_SYSTEM:
- appendPQExpBufferStr(&sql, fmtId(name));
+ appendPQExpBufferStr(&sql,
+ fmtIdEnc(name, PQclientEncoding(conn)));
break;
case REINDEX_INDEX:
case REINDEX_TABLE:
@@ -774,8 +776,9 @@ get_parallel_object_list(PGconn *conn, ReindexType type,
for (i = 0; i < ntups; i++)
{
appendPQExpBufferStr(&buf,
- fmtQualifiedId(PQgetvalue(res, i, 1),
- PQgetvalue(res, i, 0)));
+ fmtQualifiedIdEnc(PQgetvalue(res, i, 1),
+ PQgetvalue(res, i, 0),
+ PQclientEncoding(conn)));
simple_string_list_append(tables, buf.data);
resetPQExpBuffer(&buf);
@@ -787,8 +790,9 @@ get_parallel_object_list(PGconn *conn, ReindexType type,
* the order of tables list.
*/
appendPQExpBufferStr(&buf,
- fmtQualifiedId(PQgetvalue(res, i, 1),
- PQgetvalue(res, i, 2)));
+ fmtQualifiedIdEnc(PQgetvalue(res, i, 1),
+ PQgetvalue(res, i, 2),
+ PQclientEncoding(conn)));
simple_string_list_append(user_list, buf.data);
resetPQExpBuffer(&buf);
index 74fbc7ef0331699db52b1ef30f28179a069a05f3..982bf070be6f2cc543f654a66d8bacda4c258a82 100644 (file)
@@ -784,8 +784,9 @@ vacuum_one_database(ConnParams *cparams,
for (i = 0; i < ntups; i++)
{
appendPQExpBufferStr(&buf,
- fmtQualifiedId(PQgetvalue(res, i, 1),
- PQgetvalue(res, i, 0)));
+ fmtQualifiedIdEnc(PQgetvalue(res, i, 1),
+ PQgetvalue(res, i, 0),
+ PQclientEncoding(conn)));
if (objects_listed && !PQgetisnull(res, i, 2))
appendPQExpBufferStr(&buf, PQgetvalue(res, i, 2));
index 8d5a3b4a6e4ab07112960eee59c1a28b2714c3c4..2945e28a2775c764936ec1392c0bca36e23905f7 100644 (file)
#include "common/keywords.h"
#include "fe_utils/string_utils.h"
+#include "mb/pg_wchar.h"
static PQExpBuffer defaultGetLocalPQExpBuffer(void);
@@ -26,6 +27,8 @@ static PQExpBuffer defaultGetLocalPQExpBuffer(void);
int quote_all_identifiers = 0;
PQExpBuffer (*getLocalPQExpBuffer) (void) = defaultGetLocalPQExpBuffer;
+static int fmtIdEncoding = -1;
+
/*
* Returns a temporary PQExpBuffer, valid until the next call to the function.
return id_return;
}
+/*
+ * Set the encoding that fmtId() and fmtQualifiedId() use.
+ *
+ * This is not safe against multiple connections having different encodings,
+ * but there is no real other way to address the need to know the encoding for
+ * fmtId()/fmtQualifiedId() input for safe escaping. Eventually we should get
+ * rid of fmtId().
+ */
+void
+setFmtEncoding(int encoding)
+{
+ fmtIdEncoding = encoding;
+}
+
+/*
+ * Return the currently configured encoding for fmtId() and fmtQualifiedId().
+ */
+static int
+getFmtEncoding(void)
+{
+ if (fmtIdEncoding != -1)
+ return fmtIdEncoding;
+
+ /*
+ * In assertion builds it seems best to fail hard if the encoding was not
+ * set, to make it easier to find places with missing calls. But in
+ * production builds that seems like a bad idea, thus we instead just
+ * default to UTF-8.
+ */
+ Assert(fmtIdEncoding != -1);
+
+ return PG_UTF8;
+}
+
/*
* Quotes input string if it's not a legitimate SQL identifier as-is.
*
- * Note that the returned string must be used before calling fmtId again,
+ * Note that the returned string must be used before calling fmtIdEnc again,
* since we re-use the same return buffer each time.
*/
const char *
-fmtId(const char *rawid)
+fmtIdEnc(const char *rawid, int encoding)
{
PQExpBuffer id_return = getLocalPQExpBuffer();
}
/*
- * fmtQualifiedId - construct a schema-qualified name, with quoting as needed.
+ * Quotes input string if it's not a legitimate SQL identifier as-is.
+ *
+ * Note that the returned string must be used before calling fmtId again,
+ * since we re-use the same return buffer each time.
+ *
+ * NB: This assumes setFmtEncoding() previously has been called to configure
+ * the encoding of rawid. It is preferable to use fmtIdEnc() with an
+ * explicit encoding.
+ */
+const char *
+fmtId(const char *rawid)
+{
+ return fmtIdEnc(rawid, getFmtEncoding());
+}
+
+/*
+ * fmtQualifiedIdEnc - construct a schema-qualified name, with quoting as
+ * needed.
*
* Like fmtId, use the result before calling again.
*
* use that buffer until we're finished with calling fmtId().
*/
const char *
-fmtQualifiedId(const char *schema, const char *id)
+fmtQualifiedIdEnc(const char *schema, const char *id, int encoding)
{
PQExpBuffer id_return;
PQExpBuffer lcl_pqexp = createPQExpBuffer();
@@ -150,9 +204,9 @@ fmtQualifiedId(const char *schema, const char *id)
/* Some callers might fail to provide a schema name */
if (schema && *schema)
{
- appendPQExpBuffer(lcl_pqexp, "%s.", fmtId(schema));
+ appendPQExpBuffer(lcl_pqexp, "%s.", fmtIdEnc(schema, encoding));
}
- appendPQExpBufferStr(lcl_pqexp, fmtId(id));
+ appendPQExpBufferStr(lcl_pqexp, fmtIdEnc(id, encoding));
id_return = getLocalPQExpBuffer();
@@ -162,6 +216,24 @@ fmtQualifiedId(const char *schema, const char *id)
return id_return->data;
}
+/*
+ * fmtQualifiedId - construct a schema-qualified name, with quoting as needed.
+ *
+ * Like fmtId, use the result before calling again.
+ *
+ * Since we call fmtId and it also uses getLocalPQExpBuffer() we cannot
+ * use that buffer until we're finished with calling fmtId().
+ *
+ * NB: This assumes setFmtEncoding() previously has been called to configure
+ * the encoding of schema/id. It is preferable to use fmtQualifiedIdEnc()
+ * with an explicit encoding.
+ */
+const char *
+fmtQualifiedId(const char *schema, const char *id)
+{
+ return fmtQualifiedIdEnc(schema, id, getFmtEncoding());
+}
+
/*
* Format a Postgres version number (in the PG_VERSION_NUM integer format
index 690195fa9f9c1a6159286fbe2b23efc2dc2fcb44..dc991a932194ab951b7e91f2296bac2c0e10195f 100644 (file)
@@ -25,7 +25,10 @@ extern PQExpBuffer (*getLocalPQExpBuffer) (void);
/* Functions */
extern const char *fmtId(const char *rawid);
+extern const char *fmtIdEnc(const char *rawid, int encoding);
extern const char *fmtQualifiedId(const char *schema, const char *id);
+extern const char *fmtQualifiedIdEnc(const char *schema, const char *id, int encoding);
+extern void setFmtEncoding(int encoding);
extern char *formatPGVersionNumber(int version_number, bool include_minor,
char *buf, size_t buflen);