Commit 92bec9a0 authored by Tom Lane's avatar Tom Lane

Cause pg_dump to emit a 'SET client_encoding' command at the start of

any restore operation, thereby ensuring that dumped data is interpreted
the same way it was dumped even if the target database has a different
encoding.  Per suggestions from Pavel Stehule and others.  Also,
simplify scheme for handling check_function_bodies ... we may as well
just set that at the head of the script.
parent 55fb1727
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.82 2004/01/04 04:02:15 tgl Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.83 2004/02/24 03:35:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -49,6 +49,7 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt, ...@@ -49,6 +49,7 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
const int compression, ArchiveMode mode); const int compression, ArchiveMode mode);
static int _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData); static int _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData);
static void _doSetFixedOutputState(ArchiveHandle *AH);
static void _doSetSessionAuth(ArchiveHandle *AH, const char *user); static void _doSetSessionAuth(ArchiveHandle *AH, const char *user);
static void _reconnectToDB(ArchiveHandle *AH, const char *dbname, const char *user); static void _reconnectToDB(ArchiveHandle *AH, const char *dbname, const char *user);
static void _becomeUser(ArchiveHandle *AH, const char *user); static void _becomeUser(ArchiveHandle *AH, const char *user);
...@@ -200,6 +201,11 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt) ...@@ -200,6 +201,11 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
ahprintf(AH, "--\n-- PostgreSQL database dump\n--\n\n"); ahprintf(AH, "--\n-- PostgreSQL database dump\n--\n\n");
/*
* Establish important parameter values right away.
*/
_doSetFixedOutputState(AH);
/* /*
* Drop the items at the start, in reverse order * Drop the items at the start, in reverse order
*/ */
...@@ -1568,7 +1574,6 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt, ...@@ -1568,7 +1574,6 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
AH->currUser = strdup(""); /* So it's valid, but we can free() it AH->currUser = strdup(""); /* So it's valid, but we can free() it
* later if necessary */ * later if necessary */
AH->currSchema = strdup(""); /* ditto */ AH->currSchema = strdup(""); /* ditto */
AH->chk_fn_bodies = true; /* assumed default state */
AH->toc = (TocEntry *) calloc(1, sizeof(TocEntry)); AH->toc = (TocEntry *) calloc(1, sizeof(TocEntry));
if (!AH->toc) if (!AH->toc)
...@@ -1826,6 +1831,10 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt) ...@@ -1826,6 +1831,10 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt)
{ {
teReqs res = 3; /* Schema = 1, Data = 2, Both = 3 */ teReqs res = 3; /* Schema = 1, Data = 2, Both = 3 */
/* ENCODING objects are dumped specially, so always reject here */
if (strcmp(te->desc, "ENCODING") == 0)
return 0;
/* If it's an ACL, maybe ignore it */ /* If it's an ACL, maybe ignore it */
if (ropt->aclsSkip && strcmp(te->desc, "ACL") == 0) if (ropt->aclsSkip && strcmp(te->desc, "ACL") == 0)
return 0; return 0;
...@@ -1910,6 +1919,33 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt) ...@@ -1910,6 +1919,33 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt)
return res; return res;
} }
/*
* Issue SET commands for parameters that we want to have set the same way
* at all times during execution of a restore script.
*/
static void
_doSetFixedOutputState(ArchiveHandle *AH)
{
TocEntry *te;
/* If we have an encoding setting, emit that */
te = AH->toc->next;
while (te != AH->toc)
{
if (strcmp(te->desc, "ENCODING") == 0)
{
ahprintf(AH, "%s", te->defn);
break;
}
te = te->next;
}
/* Make sure function checking is disabled */
ahprintf(AH, "SET check_function_bodies = false;\n");
ahprintf(AH, "\n");
}
/* /*
* Issue a SET SESSION AUTHORIZATION command. Caller is responsible * Issue a SET SESSION AUTHORIZATION command. Caller is responsible
* for updating state if appropriate. If user is NULL or an empty string, * for updating state if appropriate. If user is NULL or an empty string,
...@@ -1991,7 +2027,8 @@ _reconnectToDB(ArchiveHandle *AH, const char *dbname, const char *user) ...@@ -1991,7 +2027,8 @@ _reconnectToDB(ArchiveHandle *AH, const char *dbname, const char *user)
free(AH->currSchema); free(AH->currSchema);
AH->currSchema = strdup(""); AH->currSchema = strdup("");
AH->chk_fn_bodies = true; /* assumed default state */ /* re-establish fixed state */
_doSetFixedOutputState(AH);
} }
/* /*
...@@ -2087,13 +2124,6 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat ...@@ -2087,13 +2124,6 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
_becomeOwner(AH, te); _becomeOwner(AH, te);
_selectOutputSchema(AH, te->namespace); _selectOutputSchema(AH, te->namespace);
/* If it's a function, make sure function checking is disabled */
if (AH->chk_fn_bodies && strcmp(te->desc, "FUNCTION") == 0)
{
ahprintf(AH, "SET check_function_bodies = false;\n\n");
AH->chk_fn_bodies = false;
}
if (isData) if (isData)
pfx = "Data for "; pfx = "Data for ";
else else
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.55 2003/12/08 16:39:05 tgl Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.56 2004/02/24 03:35:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -245,7 +245,6 @@ typedef struct _archiveHandle ...@@ -245,7 +245,6 @@ typedef struct _archiveHandle
/* these vars track state to avoid sending redundant SET commands */ /* these vars track state to avoid sending redundant SET commands */
char *currUser; /* current username */ char *currUser; /* current username */
char *currSchema; /* current schema */ char *currSchema; /* current schema */
bool chk_fn_bodies; /* current state of check_function_bodies */
void *lo_buf; void *lo_buf;
size_t lo_buf_used; size_t lo_buf_used;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* by PostgreSQL * by PostgreSQL
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.364 2004/02/12 23:41:03 tgl Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.365 2004/02/24 03:35:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -148,6 +148,7 @@ static char *myFormatType(const char *typname, int32 typmod); ...@@ -148,6 +148,7 @@ static char *myFormatType(const char *typname, int32 typmod);
static const char *fmtQualifiedId(const char *schema, const char *id); static const char *fmtQualifiedId(const char *schema, const char *id);
static int dumpBlobs(Archive *AH, void *arg); static int dumpBlobs(Archive *AH, void *arg);
static void dumpDatabase(Archive *AH); static void dumpDatabase(Archive *AH);
static void dumpEncoding(Archive *AH);
static const char *getAttrName(int attrnum, TableInfo *tblInfo); static const char *getAttrName(int attrnum, TableInfo *tblInfo);
static const char *fmtCopyColumnList(const TableInfo *ti); static const char *fmtCopyColumnList(const TableInfo *ti);
static void do_sql_command(PGconn *conn, const char *query); static void do_sql_command(PGconn *conn, const char *query);
...@@ -561,11 +562,14 @@ main(int argc, char **argv) ...@@ -561,11 +562,14 @@ main(int argc, char **argv)
* in a safe order. * in a safe order.
*/ */
/* The database item is always first. */ /* First the special encoding entry. */
dumpEncoding(g_fout);
/* The database item is always second. */
if (!dataOnly) if (!dataOnly)
dumpDatabase(g_fout); dumpDatabase(g_fout);
/* Max OID is second. */ /* Max OID is next. */
if (oids == true) if (oids == true)
setMaxOid(g_fout); setMaxOid(g_fout);
...@@ -575,7 +579,7 @@ main(int argc, char **argv) ...@@ -575,7 +579,7 @@ main(int argc, char **argv)
dumpDumpableObject(g_fout, dobjs[i]); dumpDumpableObject(g_fout, dobjs[i]);
} }
/* BLOBs are always last. */ /* BLOBs are always last (XXX is this right?) */
if (outputBlobs) if (outputBlobs)
ArchiveEntry(g_fout, nilCatalogId, createDumpId(), ArchiveEntry(g_fout, nilCatalogId, createDumpId(),
"BLOBS", NULL, "", "BLOBS", NULL, "",
...@@ -1246,6 +1250,48 @@ dumpDatabase(Archive *AH) ...@@ -1246,6 +1250,48 @@ dumpDatabase(Archive *AH)
} }
/*
* dumpEncoding: put the correct encoding into the archive
*/
static void
dumpEncoding(Archive *AH)
{
PQExpBuffer qry;
PGresult *res;
/* Can't read the encoding from pre-7.3 servers (SHOW isn't a query) */
if (AH->remoteVersion < 70300)
return;
if (g_verbose)
write_msg(NULL, "saving encoding\n");
qry = createPQExpBuffer();
appendPQExpBuffer(qry, "SHOW client_encoding");
res = PQexec(g_conn, qry->data);
check_sql_result(res, g_conn, qry->data, PGRES_TUPLES_OK);
resetPQExpBuffer(qry);
appendPQExpBuffer(qry, "SET client_encoding = ");
appendStringLiteral(qry, PQgetvalue(res, 0, 0), true);
appendPQExpBuffer(qry, ";\n");
ArchiveEntry(AH, nilCatalogId, createDumpId(),
"ENCODING", NULL, "",
"ENCODING", qry->data, "", NULL,
NULL, 0,
NULL, NULL);
PQclear(res);
destroyPQExpBuffer(qry);
}
/* /*
* dumpBlobs: * dumpBlobs:
* dump all blobs * dump all blobs
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment