1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-23 14:01:44 +03:00

Fix up pg_dump to do string escaping fully correctly for client encoding

and standard_conforming_strings; likewise for the other client programs
that need it.  As per previous discussion, a pg_dump dump now conforms
to the standard_conforming_strings setting of the source database.
We don't use E'' syntax in the dump, thereby improving portability of
the SQL.  I added a SET escape_strings_warning = off command to keep
the dumps from getting a lot of back-chatter from that.
This commit is contained in:
Tom Lane
2006-05-28 21:13:54 +00:00
parent 117d73a9e7
commit 134b463f02
15 changed files with 382 additions and 308 deletions

View File

@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.130 2006/05/26 23:48:54 momjian Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.131 2006/05/28 21:13:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -38,6 +38,7 @@
#include "pqexpbuffer.h"
#include "libpq/libpq-fs.h"
#include "mb/pg_wchar.h"
const char *progname;
@ -60,7 +61,8 @@ static void _becomeUser(ArchiveHandle *AH, const char *user);
static void _becomeOwner(ArchiveHandle *AH, TocEntry *te);
static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName);
static void _selectTablespace(ArchiveHandle *AH, const char *tablespace);
static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te);
static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te);
static teReqs _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls);
static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
@ -1589,6 +1591,14 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
AH->vmin = K_VERS_MINOR;
AH->vrev = K_VERS_REV;
/* initialize for backwards compatible string processing */
AH->public.encoding = PG_SQL_ASCII;
AH->public.std_strings = false;
/* sql error handling */
AH->public.exit_on_error = true;
AH->public.n_errors = 0;
AH->createDate = time(NULL);
AH->intSize = sizeof(int);
@ -1676,10 +1686,6 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
die_horribly(AH, modulename, "unrecognized file format \"%d\"\n", fmt);
}
/* sql error handling */
AH->public.exit_on_error = true;
AH->public.n_errors = 0;
return AH;
}
@ -1888,22 +1894,72 @@ ReadToc(ArchiveHandle *AH)
ahlog(AH, 3, "read TOC entry %d (ID %d) for %s %s\n",
i, te->dumpId, te->desc, te->tag);
/* link completed entry into TOC circular list */
te->prev = AH->toc->prev;
AH->toc->prev->next = te;
AH->toc->prev = te;
te->next = AH->toc;
/* special processing immediately upon read for some items */
if (strcmp(te->desc, "ENCODING") == 0)
processEncodingEntry(AH, te);
else if (strcmp(te->desc, "STDSTRINGS") == 0)
processStdStringsEntry(AH, te);
}
}
static void
processEncodingEntry(ArchiveHandle *AH, TocEntry *te)
{
/* te->defn should have the form SET client_encoding = 'foo'; */
char *defn = strdup(te->defn);
char *ptr1;
char *ptr2 = NULL;
int encoding;
ptr1 = strchr(defn, '\'');
if (ptr1)
ptr2 = strchr(++ptr1, '\'');
if (ptr2)
{
*ptr2 = '\0';
encoding = pg_char_to_encoding(ptr1);
if (encoding < 0)
die_horribly(AH, modulename, "unrecognized encoding \"%s\"\n",
ptr1);
AH->public.encoding = encoding;
}
else
die_horribly(AH, modulename, "invalid ENCODING item: %s\n",
te->defn);
free(defn);
}
static void
processStdStringsEntry(ArchiveHandle *AH, TocEntry *te)
{
/* te->defn should have the form SET standard_conforming_strings = 'x'; */
char *ptr1;
ptr1 = strchr(te->defn, '\'');
if (ptr1 && strncmp(ptr1, "'on'", 4) == 0)
AH->public.std_strings = true;
else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
AH->public.std_strings = false;
else
die_horribly(AH, modulename, "invalid STDSTRINGS item: %s\n",
te->defn);
}
static teReqs
_tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
{
teReqs res = REQ_ALL;
/* ENCODING and STDSTRINGS objects are dumped specially, so always reject */
if (strcmp(te->desc, "ENCODING") == 0)
return 0;
if (strcmp(te->desc, "STDSTRINGS") == 0)
/* ENCODING and STDSTRINGS items are dumped specially, so always reject */
if (strcmp(te->desc, "ENCODING") == 0 ||
strcmp(te->desc, "STDSTRINGS") == 0)
return 0;
/* If it's an ACL, maybe ignore it */
@ -2005,24 +2061,21 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
static void
_doSetFixedOutputState(ArchiveHandle *AH)
{
TocEntry *te;
/* Select the correct character set encoding */
ahprintf(AH, "SET client_encoding = '%s';\n",
pg_encoding_to_char(AH->public.encoding));
/* If we have an encoding or std_strings setting, emit that */
te = AH->toc->next;
while (te != AH->toc)
{
if (strcmp(te->desc, "ENCODING") == 0)
ahprintf(AH, "%s", te->defn);
if (strcmp(te->desc, "STDSTRINGS") == 0)
ahprintf(AH, "%s", te->defn);
te = te->next;
}
/* Select the correct string literal syntax */
ahprintf(AH, "SET standard_conforming_strings = %s;\n",
AH->public.std_strings ? "on" : "off");
/* Make sure function checking is disabled */
ahprintf(AH, "SET check_function_bodies = false;\n");
/* Avoid annoying notices etc */
ahprintf(AH, "SET client_min_messages = warning;\n");
if (!AH->public.std_strings)
ahprintf(AH, "SET escape_string_warning = off;\n");
ahprintf(AH, "\n");
}
@ -2043,7 +2096,7 @@ _doSetSessionAuth(ArchiveHandle *AH, const char *user)
* SQL requires a string literal here. Might as well be correct.
*/
if (user && *user)
appendStringLiteral(cmd, user, false, true);
appendStringLiteralAHX(cmd, user, AH);
else
appendPQExpBuffer(cmd, "DEFAULT");
appendPQExpBuffer(cmd, ";");