diff options
author | Tom Lane | 2007-10-13 20:18:42 +0000 |
---|---|---|
committer | Tom Lane | 2007-10-13 20:18:42 +0000 |
commit | d13241956c1578d5855471fd88b3c0ba4bab5ee9 (patch) | |
tree | 115779e006cf5fa638cf0c4da5e0e5767e4018b0 | |
parent | 13b9427817de426bfda7c1e30043d1f70b4e9ddd (diff) |
Fix the inadvertent libpq ABI breakage discovered by Martin Pitt: the
renumbering of encoding IDs done between 8.2 and 8.3 turns out to break 8.2
initdb and psql if they are run with an 8.3beta1 libpq.so. For the moment
we can rearrange the order of enum pg_enc to keep the same number for
everything except PG_JOHAB, which isn't a problem since there are no direct
references to it in the 8.2 programs anyway. (This does force initdb
unfortunately.)
Going forward, we want to fix things so that encoding IDs can be changed
without an ABI break, and this commit includes the changes needed to allow
libpq's encoding IDs to be treated as fully independent of the backend's.
The main issue is that libpq clients should not include pg_wchar.h or
otherwise assume they know the specific values of libpq's encoding IDs,
since they might encounter version skew between pg_wchar.h and the libpq.so
they are using. To fix, have libpq officially export functions needed for
encoding name<=>ID conversion and validity checking; it was doing this
anyway unofficially.
It's still the case that we can't renumber backend encoding IDs until the
next bump in libpq's major version number, since doing so will break the
8.2-era client programs. However the code is now prepared to avoid this
type of problem in future.
Note that initdb is no longer a libpq client: we just pull in the two
source files we need directly. The patch also fixes a few places that
were being sloppy about checking for an unrecognized encoding name.
-rw-r--r-- | src/backend/commands/dbcommands.c | 4 | ||||
-rw-r--r-- | src/backend/utils/adt/ascii.c | 13 | ||||
-rw-r--r-- | src/backend/utils/adt/xml.c | 28 | ||||
-rw-r--r-- | src/backend/utils/mb/encnames.c | 27 | ||||
-rw-r--r-- | src/backend/utils/mb/mbutils.c | 6 | ||||
-rw-r--r-- | src/bin/initdb/Makefile | 22 | ||||
-rw-r--r-- | src/bin/initdb/initdb.c | 4 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_backup_archiver.c | 3 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 1 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dumpall.c | 1 | ||||
-rw-r--r-- | src/bin/psql/command.c | 3 | ||||
-rw-r--r-- | src/bin/psql/common.c | 1 | ||||
-rw-r--r-- | src/bin/psql/mbprint.c | 34 | ||||
-rw-r--r-- | src/bin/psql/psqlscan.l | 4 | ||||
-rw-r--r-- | src/bin/scripts/createdb.c | 4 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 2 | ||||
-rw-r--r-- | src/include/mb/pg_wchar.h | 62 | ||||
-rw-r--r-- | src/interfaces/libpq/exports.txt | 1 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-exec.c | 5 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-misc.c | 4 | ||||
-rw-r--r-- | src/interfaces/libpq/libpq-fe.h | 6 |
21 files changed, 174 insertions, 61 deletions
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index c43b664237..a275fd3350 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -178,12 +178,12 @@ createdb(const CreatedbStmt *stmt) else if (IsA(dencoding->arg, String)) { encoding_name = strVal(dencoding->arg); - if (pg_valid_server_encoding(encoding_name) < 0) + encoding = pg_valid_server_encoding(encoding_name); + if (encoding < 0) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("%s is not a valid encoding name", encoding_name))); - encoding = pg_char_to_encoding(encoding_name); } else elog(ERROR, "unrecognized node type: %d", diff --git a/src/backend/utils/adt/ascii.c b/src/backend/utils/adt/ascii.c index 9e592e0204..736a02337e 100644 --- a/src/backend/utils/adt/ascii.c +++ b/src/backend/utils/adt/ascii.c @@ -117,7 +117,13 @@ Datum to_ascii_encname(PG_FUNCTION_ARGS) { text *data = PG_GETARG_TEXT_P_COPY(0); - int enc = pg_char_to_encoding(NameStr(*PG_GETARG_NAME(1))); + char *encname = NameStr(*PG_GETARG_NAME(1)); + int enc = pg_char_to_encoding(encname); + + if (enc < 0) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("%s is not a valid encoding name", encname))); PG_RETURN_TEXT_P(encode_to_ascii(data, enc)); } @@ -132,6 +138,11 @@ to_ascii_enc(PG_FUNCTION_ARGS) text *data = PG_GETARG_TEXT_P_COPY(0); int enc = PG_GETARG_INT32(1); + if (!PG_VALID_ENCODING(enc)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("%d is not a valid encoding code", enc))); + PG_RETURN_TEXT_P(encode_to_ascii(data, enc)); } diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 86a9aad198..2a5dfb2690 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -127,6 +127,24 @@ XmlOptionType xmloption; #define NAMESPACE_SQLXML "http://standards.iso.org/iso/9075/2003/sqlxml" +#ifdef USE_LIBXML + +static int +xmlChar_to_encoding(xmlChar *encoding_name) +{ + int encoding = pg_char_to_encoding((char *) encoding_name); + + if (encoding < 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid encoding name \"%s\"", + (char *) encoding_name))); + return encoding; +} + +#endif + + Datum xml_in(PG_FUNCTION_ARGS) { @@ -263,7 +281,9 @@ xml_recv(PG_FUNCTION_ARGS) /* Now that we know what we're dealing with, convert to server encoding */ newstr = (char *) pg_do_encoding_conversion((unsigned char *) str, nbytes, - encoding ? pg_char_to_encoding((char *) encoding) : PG_UTF8, + encoding ? + xmlChar_to_encoding(encoding) : + PG_UTF8, GetDatabaseEncoding()); if (newstr != str) @@ -1084,9 +1104,9 @@ xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace, xml utf8string = pg_do_encoding_conversion(string, len, - encoding - ? pg_char_to_encoding((char *) encoding) - : GetDatabaseEncoding(), + encoding ? + xmlChar_to_encoding(encoding) : + GetDatabaseEncoding(), PG_UTF8); xml_init(); diff --git a/src/backend/utils/mb/encnames.c b/src/backend/utils/mb/encnames.c index 07a96dac2c..79c6840775 100644 --- a/src/backend/utils/mb/encnames.c +++ b/src/backend/utils/mb/encnames.c @@ -12,10 +12,11 @@ #include "utils/builtins.h" #endif +#include <ctype.h> #include <unistd.h> #include "mb/pg_wchar.h" -#include <ctype.h> + /* ---------- * All encoding names, sorted: *** A L P H A B E T I C *** @@ -314,6 +315,9 @@ pg_enc2name pg_enc2name_tbl[] = "EUC_TW", PG_EUC_TW }, { + "EUC_JIS_2004", PG_EUC_JIS_2004 + }, + { "UTF8", PG_UTF8 }, { @@ -398,9 +402,6 @@ pg_enc2name pg_enc2name_tbl[] = "WIN1257", PG_WIN1257 }, { - "EUC_JIS_2004", PG_EUC_JIS_2004 - }, - { "SJIS", PG_SJIS }, { @@ -413,10 +414,10 @@ pg_enc2name pg_enc2name_tbl[] = "UHC", PG_UHC }, { - "JOHAB", PG_JOHAB + "GB18030", PG_GB18030 }, { - "GB18030", PG_GB18030 + "JOHAB", PG_JOHAB }, { "SHIFT_JIS_2004", PG_SHIFT_JIS_2004 @@ -455,6 +456,12 @@ pg_valid_server_encoding(const char *name) return enc; } +int +pg_valid_server_encoding_id(int encoding) +{ + return PG_VALID_BE_ENCODING(encoding); +} + /* ---------- * Remove irrelevant chars from encoding name * ---------- @@ -533,14 +540,14 @@ pg_char_to_encname_struct(const char *name) * Returns encoding or -1 for error */ int -pg_char_to_encoding(const char *s) +pg_char_to_encoding(const char *name) { - pg_encname *p = NULL; + pg_encname *p; - if (!s) + if (!name) return -1; - p = pg_char_to_encname_struct(s); + p = pg_char_to_encname_struct(name); return p ? p->encoding : -1; } diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c index b67e5fac87..58917845d0 100644 --- a/src/backend/utils/mb/mbutils.c +++ b/src/backend/utils/mb/mbutils.c @@ -421,6 +421,12 @@ length_in_encoding(PG_FUNCTION_ARGS) int len = VARSIZE(string) - VARHDRSZ; int retval; + if (src_encoding < 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid encoding name \"%s\"", + src_encoding_name))); + retval = pg_verify_mbstr_len(src_encoding, VARDATA(string), len, false); PG_RETURN_INT32(retval); diff --git a/src/bin/initdb/Makefile b/src/bin/initdb/Makefile index 6401a50e13..c83b195756 100644 --- a/src/bin/initdb/Makefile +++ b/src/bin/initdb/Makefile @@ -14,14 +14,24 @@ subdir = src/bin/initdb top_builddir = ../../.. include $(top_builddir)/src/Makefile.global -override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) +override CPPFLAGS := -DFRONTEND -I$(libpq_srcdir) $(CPPFLAGS) -OBJS= initdb.o $(WIN32RES) +OBJS= initdb.o encnames.o pqsignal.o $(WIN32RES) -all: submake-libpq submake-libpgport initdb +all: submake-libpgport initdb -initdb: $(OBJS) $(libpq_builddir)/libpq.a - $(CC) $(CFLAGS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LIBS) -o $@$(X) +initdb: $(OBJS) + $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(LIBS) -o $@$(X) + +# We used to pull in all of libpq to get encnames and pqsignal, but that +# exposes us to risks of version skew if we link to a shared library. +# Do it the hard way, instead, so that we're statically linked. + +encnames.c: % : $(top_srcdir)/src/backend/utils/mb/% + rm -f $@ && $(LN_S) $< . + +pqsignal.c: % : $(libpq_srcdir)/% + rm -f $@ && $(LN_S) $< . install: all installdirs $(INSTALL_PROGRAM) initdb$(X) '$(DESTDIR)$(bindir)/initdb$(X)' @@ -33,7 +43,7 @@ uninstall: rm -f '$(DESTDIR)$(bindir)/initdb$(X)' clean distclean maintainer-clean: - rm -f initdb$(X) $(OBJS) + rm -f initdb$(X) $(OBJS) encnames.c pqsignal.c # ensure that changes in datadir propagate into object file diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 59442eb1f5..eef03cb280 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -2808,7 +2808,7 @@ main(int argc, char *argv[]) progname); exit(1); } - else if (!PG_VALID_BE_ENCODING(ctype_enc)) + else if (!pg_valid_server_encoding_id(ctype_enc)) { /* We recognized it, but it's not a legal server encoding */ fprintf(stderr, @@ -2968,7 +2968,7 @@ main(int argc, char *argv[]) { char *linkloc; - linkloc = (char *) palloc(strlen(pg_data) + 8 + 2); + linkloc = (char *) pg_malloc(strlen(pg_data) + 8 + 2); sprintf(linkloc, "%s/pg_xlog", pg_data); /* check if the specified xlog directory is empty */ diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 3c429565c7..9a733fc483 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -32,7 +32,6 @@ #endif #include "libpq/libpq-fs.h" -#include "mb/pg_wchar.h" const char *progname; @@ -1639,7 +1638,7 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt, AH->vrev = K_VERS_REV; /* initialize for backwards compatible string processing */ - AH->public.encoding = PG_SQL_ASCII; + AH->public.encoding = 0; /* PG_SQL_ASCII */ AH->public.std_strings = false; /* sql error handling */ diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index a99d23214d..c572c5069e 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -47,7 +47,6 @@ int optreset; #include "catalog/pg_type.h" #include "commands/sequence.h" #include "libpq/libpq-fs.h" -#include "mb/pg_wchar.h" #include "pg_backup_archiver.h" #include "dumputils.h" diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 77148136e4..eb111549ee 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -27,7 +27,6 @@ int optreset; #endif #include "dumputils.h" -#include "mb/pg_wchar.h" /* version string we expect back from pg_dump */ diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 12fbb3fb99..09a9350790 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -45,7 +45,6 @@ #include "psqlscan.h" #include "settings.h" #include "variables.h" -#include "mb/pg_wchar.h" /* functions for use in this file */ @@ -295,7 +294,7 @@ exec_command(const char *cmd, } if (pset.dirname) - pfree(pset.dirname); + free(pset.dirname); pset.dirname = pg_strdup(dir); canonicalize_path(pset.dirname); diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index 25273ccc99..4f2ad359d7 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -22,7 +22,6 @@ #include "settings.h" #include "command.h" #include "copy.h" -#include "mb/pg_wchar.h" #include "mbprint.h" diff --git a/src/bin/psql/mbprint.c b/src/bin/psql/mbprint.c index e0cd1b1b61..0e05b3b280 100644 --- a/src/bin/psql/mbprint.c +++ b/src/bin/psql/mbprint.c @@ -4,14 +4,44 @@ * Copyright (c) 2000-2007, PostgreSQL Global Development Group * * $PostgreSQL$ + * + * XXX this file does not really belong in psql/. Perhaps move to libpq? + * It also seems that the mbvalidate function is redundant with existing + * functionality. */ #include "postgres_fe.h" +#include "mbprint.h" +#include "libpq-fe.h" #ifndef PGSCRIPTS #include "settings.h" #endif -#include "mbprint.h" -#include "mb/pg_wchar.h" + +/* + * To avoid version-skew problems, this file must not use declarations + * from pg_wchar.h: the encoding IDs we are dealing with are determined + * by the libpq.so we are linked with, and that might not match the + * numbers we see at compile time. (If this file were inside libpq, + * the problem would go away...) + * + * Hence, we have our own definition of pg_wchar, and we get the values + * of any needed encoding IDs on-the-fly. + */ + +typedef unsigned int pg_wchar; + +static int +get_utf8_id(void) +{ + static int utf8_id = -1; + + if (utf8_id < 0) + utf8_id = pg_char_to_encoding("utf8"); + return utf8_id; +} + +#define PG_UTF8 get_utf8_id() + static pg_wchar utf2ucs(const unsigned char *c) diff --git a/src/bin/psql/psqlscan.l b/src/bin/psql/psqlscan.l index dfb409ed99..4b835eeddd 100644 --- a/src/bin/psql/psqlscan.l +++ b/src/bin/psql/psqlscan.l @@ -43,8 +43,6 @@ #include <ctype.h> -#include "mb/pg_wchar.h" - #include "common.h" #include "settings.h" #include "variables.h" @@ -1021,7 +1019,7 @@ psql_scan_setup(PsqlScanState state, /* Do we need to hack the character set encoding? */ state->encoding = pset.encoding; - state->safe_encoding = PG_VALID_BE_ENCODING(state->encoding); + state->safe_encoding = pg_valid_server_encoding_id(state->encoding); /* needed for prepare_buffer */ cur_state = state; diff --git a/src/bin/scripts/createdb.c b/src/bin/scripts/createdb.c index 8a8bcd8504..a12a8b3ce0 100644 --- a/src/bin/scripts/createdb.c +++ b/src/bin/scripts/createdb.c @@ -9,13 +9,11 @@ * *------------------------------------------------------------------------- */ - #include "postgres_fe.h" + #include "common.h" #include "dumputils.h" -#include "mb/pg_wchar.h" - static void help(const char *progname); diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index c29d7b073b..75a32e5730 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200709301 +#define CATALOG_VERSION_NO 200710131 #endif diff --git a/src/include/mb/pg_wchar.h b/src/include/mb/pg_wchar.h index 8d151749e6..cb4c57b73c 100644 --- a/src/include/mb/pg_wchar.h +++ b/src/include/mb/pg_wchar.h @@ -1,19 +1,28 @@ -/* $PostgreSQL$ */ - +/*------------------------------------------------------------------------- + * + * pg_wchar.h + * multibyte-character support + * + * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * $PostgreSQL$ + * + * NOTES + * This is used both by the backend and by libpq, but should not be + * included by libpq client programs. In particular, a libpq client + * should not assume that the encoding IDs used by the version of libpq + * it's linked to match up with the IDs declared here. + * + *------------------------------------------------------------------------- + */ #ifndef PG_WCHAR_H #define PG_WCHAR_H #include <sys/types.h> -#ifdef FRONTEND -#undef palloc -#define palloc malloc -#undef pfree -#define pfree free -#endif - /* - * The pg_wchar + * The pg_wchar type */ typedef unsigned int pg_wchar; @@ -149,7 +158,12 @@ typedef unsigned int pg_wchar; * If you add some encoding don't forget to check * PG_ENCODING_BE_LAST macro. * - * The PG_SQL_ASCII is default encoding and must be = 0. + * PG_SQL_ASCII is default encoding and must be = 0. + * + * XXX We must avoid renumbering any backend encoding until libpq's major + * version number is increased beyond 5; it turns out that the backend + * encoding IDs are effectively part of libpq's ABI as far as 8.2 initdb and + * psql are concerned. */ typedef enum pg_enc { @@ -158,6 +172,7 @@ typedef enum pg_enc PG_EUC_CN, /* EUC for Chinese */ PG_EUC_KR, /* EUC for Korean */ PG_EUC_TW, /* EUC for Taiwan */ + PG_EUC_JIS_2004, /* EUC-JIS-2004 */ PG_UTF8, /* Unicode UTF8 */ PG_MULE_INTERNAL, /* Mule internal code */ PG_LATIN1, /* ISO-8859-1 Latin 1 */ @@ -186,7 +201,6 @@ typedef enum pg_enc PG_WIN1254, /* windows-1254 */ PG_WIN1255, /* windows-1255 */ PG_WIN1257, /* windows-1257 */ - PG_EUC_JIS_2004, /* EUC-JIS-2004 */ /* PG_ENCODING_BE_LAST points to the above entry */ /* followings are for client encoding only */ @@ -194,14 +208,14 @@ typedef enum pg_enc PG_BIG5, /* Big5 (Windows-950) */ PG_GBK, /* GBK (Windows-936) */ PG_UHC, /* UHC (Windows-949) */ - PG_JOHAB, /* EUC for Korean JOHAB */ PG_GB18030, /* GB18030 */ + PG_JOHAB, /* EUC for Korean JOHAB */ PG_SHIFT_JIS_2004, /* Shift-JIS-2004 */ _PG_LAST_ENCODING_ /* mark only */ } pg_enc; -#define PG_ENCODING_BE_LAST PG_EUC_JIS_2004 +#define PG_ENCODING_BE_LAST PG_WIN1257 /* * Please use these tests before access to pg_encconv_tbl[] @@ -245,11 +259,6 @@ typedef struct pg_enc2name extern pg_enc2name pg_enc2name_tbl[]; -extern pg_encname *pg_char_to_encname_struct(const char *name); - -extern int pg_char_to_encoding(const char *s); -extern const char *pg_encoding_to_char(int encoding); - /* * pg_wchar stuff */ @@ -315,6 +324,21 @@ typedef struct uint32 utf2; /* UTF-8 code 2 */ } pg_local_to_utf_combined; + +/* + * These functions are considered part of libpq's exported API and + * are also declared in libpq-fe.h. + */ +extern int pg_char_to_encoding(const char *name); +extern const char *pg_encoding_to_char(int encoding); +extern int pg_valid_server_encoding_id(int encoding); + +/* + * Remaining functions are not considered part of libpq's API, though many + * of them do exist inside libpq. + */ +extern pg_encname *pg_char_to_encname_struct(const char *name); + extern int pg_mb2wchar(const char *from, pg_wchar *to); extern int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len); extern int pg_encoding_mb2wchar_with_len(int encoding, diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt index bc453c1197..fa82432e16 100644 --- a/src/interfaces/libpq/exports.txt +++ b/src/interfaces/libpq/exports.txt @@ -138,3 +138,4 @@ PQsendDescribePrepared 135 PQsendDescribePortal 136 lo_truncate 137 PQconnectionUsedPassword 138 +pg_valid_server_encoding_id 139 diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index b639205f14..85b96bdf1a 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -630,11 +630,14 @@ pqSaveParameterStatus(PGconn *conn, const char *name, const char *value) * standard_conforming_strings, and convert server version to a numeric * form. We keep the first two of these in static variables as well, so * that PQescapeString and PQescapeBytea can behave somewhat sanely (at - * least in single- connection-using programs). + * least in single-connection-using programs). */ if (strcmp(name, "client_encoding") == 0) { conn->client_encoding = pg_char_to_encoding(value); + /* if we don't recognize the encoding name, fall back to SQL_ASCII */ + if (conn->client_encoding < 0) + conn->client_encoding = PG_SQL_ASCII; static_client_encoding = conn->client_encoding; } else if (strcmp(name, "standard_conforming_strings") == 0) diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index 71e6b56667..7c48ae5c55 100644 --- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -1112,7 +1112,11 @@ PQenv2encoding(void) str = getenv("PGCLIENTENCODING"); if (str && *str != '\0') + { encoding = pg_char_to_encoding(str); + if (encoding < 0) + encoding = PG_SQL_ASCII; + } return encoding; } diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h index b8ef5387ab..ecd7de9797 100644 --- a/src/interfaces/libpq/libpq-fe.h +++ b/src/interfaces/libpq/libpq-fe.h @@ -511,6 +511,12 @@ extern int PQenv2encoding(void); extern char *PQencryptPassword(const char *passwd, const char *user); +/* === in encnames.c === */ + +extern int pg_char_to_encoding(const char *name); +extern const char *pg_encoding_to_char(int encoding); +extern int pg_valid_server_encoding_id(int encoding); + #ifdef __cplusplus } #endif |