OSDN Git Service

Cause pg_dump to emit a 'SET client_encoding' command at the start of
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 24 Feb 2004 03:35:19 +0000 (03:35 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 24 Feb 2004 03:35:19 +0000 (03:35 +0000)
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.

src/bin/pg_dump/pg_backup_archiver.c
src/bin/pg_dump/pg_backup_archiver.h
src/bin/pg_dump/pg_dump.c

index c77382d..c5d9172 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * 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,
                 const int compression, ArchiveMode mode);
 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 _reconnectToDB(ArchiveHandle *AH, const char *dbname, const char *user);
 static void _becomeUser(ArchiveHandle *AH, const char *user);
@@ -201,6 +202,11 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
        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
         */
        if (ropt->dropSchema)
@@ -1568,7 +1574,6 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
        AH->currUser = strdup("");      /* So it's valid, but we can free() it
                                                                 * later if necessary */
        AH->currSchema = strdup("");    /* ditto */
-       AH->chk_fn_bodies = true;       /* assumed default state */
 
        AH->toc = (TocEntry *) calloc(1, sizeof(TocEntry));
        if (!AH->toc)
@@ -1826,6 +1831,10 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt)
 {
        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 (ropt->aclsSkip && strcmp(te->desc, "ACL") == 0)
                return 0;
@@ -1911,6 +1920,33 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt)
 }
 
 /*
+ * 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
  * for updating state if appropriate.  If user is NULL or an empty string,
  * the specification DEFAULT will be used.
@@ -1991,7 +2027,8 @@ _reconnectToDB(ArchiveHandle *AH, const char *dbname, const char *user)
                free(AH->currSchema);
        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
        _becomeOwner(AH, te);
        _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)
                pfx = "Data for ";
        else
index 4809989..5e9d69f 100644 (file)
@@ -17,7 +17,7 @@
  *
  *
  * 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
        /* these vars track state to avoid sending redundant SET commands */
        char       *currUser;           /* current username */
        char       *currSchema;         /* current schema */
-       bool            chk_fn_bodies;  /* current state of check_function_bodies */
 
        void       *lo_buf;
        size_t          lo_buf_used;
index 096a175..15e1b2b 100644 (file)
@@ -12,7 +12,7 @@
  *     by PostgreSQL
  *
  * 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);
 static const char *fmtQualifiedId(const char *schema, const char *id);
 static int     dumpBlobs(Archive *AH, void *arg);
 static void dumpDatabase(Archive *AH);
+static void dumpEncoding(Archive *AH);
 static const char *getAttrName(int attrnum, TableInfo *tblInfo);
 static const char *fmtCopyColumnList(const TableInfo *ti);
 static void do_sql_command(PGconn *conn, const char *query);
@@ -561,11 +562,14 @@ main(int argc, char **argv)
         * 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)
                dumpDatabase(g_fout);
 
-       /* Max OID is second. */
+       /* Max OID is next. */
        if (oids == true)
                setMaxOid(g_fout);
 
@@ -575,7 +579,7 @@ main(int argc, char **argv)
                dumpDumpableObject(g_fout, dobjs[i]);
        }
 
-       /* BLOBs are always last. */
+       /* BLOBs are always last (XXX is this right?) */
        if (outputBlobs)
                ArchiveEntry(g_fout, nilCatalogId, createDumpId(),
                                         "BLOBS", NULL, "",
@@ -1247,6 +1251,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:
  *     dump all blobs
  *