From bb080400f8756724ef5b4098ff4fcdbf6d784fb6 Mon Sep 17 00:00:00 2001 From: Philip Warner Date: Mon, 24 Jul 2000 06:24:26 +0000 Subject: [PATCH] - no longer put ACLs at end of dump - connect as appropriate user in pg_restore with db connection - dump owner of rule in pg_dump --- src/bin/pg_dump/Makefile | 2 +- src/bin/pg_dump/pg_backup_archiver.c | 44 ++++++++-- src/bin/pg_dump/pg_backup_archiver.h | 2 + src/bin/pg_dump/pg_backup_db.c | 93 ++++++++++++++++---- src/bin/pg_dump/pg_backup_plain_text.c | 115 ------------------------- src/bin/pg_dump/pg_dump.c | 13 +-- 6 files changed, 122 insertions(+), 147 deletions(-) diff --git a/src/bin/pg_dump/Makefile b/src/bin/pg_dump/Makefile index 6b104028615..6bbef564c5f 100644 --- a/src/bin/pg_dump/Makefile +++ b/src/bin/pg_dump/Makefile @@ -4,7 +4,7 @@ # # Copyright (c) 1994, Regents of the University of California # -# $Header: /cvsroot/pgsql/src/bin/pg_dump/Makefile,v 1.20 2000/07/21 11:40:08 pjw Exp $ +# $Header: /cvsroot/pgsql/src/bin/pg_dump/Makefile,v 1.21 2000/07/24 06:24:26 pjw Exp $ # #------------------------------------------------------------------------- diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index e210780196b..55fb0f742f1 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -43,6 +43,8 @@ static int _tocSortCompareByIDNum(const void *p1, const void *p2); static ArchiveHandle* _allocAH(const char* FileSpec, const ArchiveFormat fmt, int compression, ArchiveMode mode); static int _printTocEntry(ArchiveHandle* AH, TocEntry* te, RestoreOptions *ropt); +static void _reconnectAsOwner(ArchiveHandle* AH, TocEntry* te); + static int _tocEntryRequired(TocEntry* te, RestoreOptions *ropt); static void _disableTriggers(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt); static void _enableTriggers(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt); @@ -153,6 +155,12 @@ void RestoreArchive(Archive* AHX, RestoreOptions *ropt) /* Work out what, if anything, we want from this entry */ reqs = _tocEntryRequired(te, ropt); + /* Reconnect if necessary */ + if (reqs != 0) + { + _reconnectAsOwner(AH, te); + } + if ( (reqs & 1) != 0) /* We want the schema */ { ahlog(AH, 1, "Creating %s %s\n", te->desc, te->name); @@ -772,6 +780,14 @@ void ahlog(ArchiveHandle* AH, int level, const char *fmt, ...) va_end(ap); } +/* + * Single place for logic which says 'We are restoring to a direct DB connection'. + */ +int RestoringToDB(ArchiveHandle* AH) +{ + return (AH->ropt && AH->ropt->useDB && AH->connection); +} + /* * Write buffer to the output file (usually stdout). This is user for * outputting 'restore' scripts etc. It is even possible for an archive @@ -798,7 +814,7 @@ int ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle* AH) * If we're doing a restore, and it's direct to DB, and we're connected * then send it to the DB. */ - if (AH->ropt && AH->ropt->useDB && AH->connection) + if (RestoringToDB(AH)) return ExecuteSqlCommandBuf(AH, (void*)ptr, size*nmemb); else return fwrite((void*)ptr, size, nmemb, AH->OF); @@ -1335,22 +1351,32 @@ static int _tocEntryRequired(TocEntry* te, RestoreOptions *ropt) return res; } +static void _reconnectAsOwner(ArchiveHandle* AH, TocEntry* te) +{ + if (te->owner && strlen(te->owner) != 0 && strcmp(AH->currUser, te->owner) != 0) { + if (RestoringToDB(AH)) + { + ReconnectDatabase(AH, te->owner); + //todo pjw - ???? fix for db connection... + } + else + { + ahprintf(AH, "\\connect - %s\n", te->owner); + } + AH->currUser = te->owner; + } +} + static int _printTocEntry(ArchiveHandle* AH, TocEntry* te, RestoreOptions *ropt) { ahprintf(AH, "--\n-- TOC Entry ID %d (OID %s)\n--\n-- Name: %s Type: %s Owner: %s\n", te->id, te->oid, te->name, te->desc, te->owner); if (AH->PrintExtraTocPtr != NULL) { - (*AH->PrintExtraTocPtr)(AH, te); + (*AH->PrintExtraTocPtr)(AH, te); } ahprintf(AH, "--\n\n"); - if (te->owner && strlen(te->owner) != 0 && strcmp(AH->currUser, te->owner) != 0) { - //todo pjw - fix for db connection... - //ahprintf(AH, "\\connect - %s\n", te->owner); - AH->currUser = te->owner; - } - - ahprintf(AH, "%s\n", te->defn); + ahprintf(AH, "%s\n", te->defn); return 1; } diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h index f3b0ba53858..326cb4df7f1 100644 --- a/src/bin/pg_dump/pg_backup_archiver.h +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -264,6 +264,8 @@ extern int isValidTarHeader(char *header); extern OutputContext SetOutput(ArchiveHandle* AH, char *filename, int compression); extern void ResetOutput(ArchiveHandle* AH, OutputContext savedContext); +extern int RestoringToDB(ArchiveHandle* AH); +extern int ReconnectDatabase(ArchiveHandle *AH, char *newUser); int ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle* AH); int ahprintf(ArchiveHandle* AH, const char *fmt, ...); diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c index 62e4c2b0dd8..17f025ab9fb 100644 --- a/src/bin/pg_dump/pg_backup_db.c +++ b/src/bin/pg_dump/pg_backup_db.c @@ -48,20 +48,26 @@ _prompt_for_password(char *username, char *password) t; #endif - fprintf(stderr, "Username: "); - fflush(stderr); - fgets(username, 100, stdin); - length = strlen(username); - /* skip rest of the line */ - if (length > 0 && username[length - 1] != '\n') + /* + * Allow for forcing a specific username + */ + if (strlen(username) == 0) { - do + fprintf(stderr, "Username: "); + fflush(stderr); + fgets(username, 100, stdin); + length = strlen(username); + /* skip rest of the line */ + if (length > 0 && username[length - 1] != '\n') { - fgets(buf, 512, stdin); - } while (buf[strlen(buf) - 1] != '\n'); + do + { + fgets(buf, 512, stdin); + } while (buf[strlen(buf) - 1] != '\n'); + } + if (length > 0 && username[length - 1] == '\n') + username[length - 1] = '\0'; } - if (length > 0 && username[length - 1] == '\n') - username[length - 1] = '\0'; #ifdef HAVE_TERMIOS_H tcgetattr(0, &t); @@ -125,17 +131,69 @@ _check_database_version(ArchiveHandle *AH, bool ignoreVersion) PQclear(res); } +int ReconnectDatabase(ArchiveHandle *AH, char *newUser) +{ + int need_pass; + PGconn *newConn; + char password[100]; + char *pwparam = NULL; + int badPwd = 0; + int noPwd = 0; + + ahlog(AH, 1, "Connecting as %s\n", newUser); + + do + { + need_pass = false; + newConn = PQsetdbLogin(PQhost(AH->connection), PQport(AH->connection), + NULL, NULL, PQdb(AH->connection), + newUser, pwparam); + if (!newConn) + die_horribly(AH, "%s: Failed to reconnect (PQsetdbLogin failed).\n", progname); + + if (PQstatus(newConn) == CONNECTION_BAD) + { + noPwd = (strcmp(PQerrorMessage(newConn), "fe_sendauth: no password supplied\n") == 0); + badPwd = (strncmp(PQerrorMessage(newConn), "Password authentication failed for user", 39) + == 0); + + if (noPwd || badPwd) + { + + if (badPwd) + fprintf(stderr, "Password incorrect\n"); + + fprintf(stderr, "Connecting to %s as %s\n", PQdb(AH->connection), newUser); + + need_pass = true; + _prompt_for_password(newUser, password); + pwparam = password; + } + else + die_horribly(AH, "%s: Could not reconnect. %s\n", progname, PQerrorMessage(newConn)); + } + + } while (need_pass); + + PQfinish(AH->connection); + AH->connection = newConn; + strcpy(AH->username, newUser); + + return 1; +} + + PGconn* ConnectDatabase(Archive *AHX, const char* dbname, const char* pghost, const char* pgport, - const int reqPwd, - const int ignoreVersion) + const int reqPwd, + const int ignoreVersion) { ArchiveHandle *AH = (ArchiveHandle*)AHX; - char connect_string[512] = ""; - char tmp_string[128]; - char password[100]; + char connect_string[512] = ""; + char tmp_string[128]; + char password[100]; if (AH->connection) die_horribly(AH, "%s: already connected to database\n", progname); @@ -168,6 +226,7 @@ PGconn* ConnectDatabase(Archive *AHX, if (reqPwd) { + AH->username[0] = '\0'; _prompt_for_password(AH->username, password); strcat(connect_string, "authtype=password "); sprintf(tmp_string, "user=%s ", AH->username); @@ -188,6 +247,8 @@ PGconn* ConnectDatabase(Archive *AHX, /* check for version mismatch */ _check_database_version(AH, ignoreVersion); + AH->currUser = PQuser(AH->connection); + return AH->connection; } diff --git a/src/bin/pg_dump/pg_backup_plain_text.c b/src/bin/pg_dump/pg_backup_plain_text.c index 56866f10368..e69de29bb2d 100644 --- a/src/bin/pg_dump/pg_backup_plain_text.c +++ b/src/bin/pg_dump/pg_backup_plain_text.c @@ -1,115 +0,0 @@ -/*------------------------------------------------------------------------- - * - * pg_backup_plain_text.c - * - * This file is copied from the 'custom' format file, but dumps data into - * directly to a text file, and the TOC into the 'main' file. - * - * See the headers to pg_restore for more details. - * - * Copyright (c) 2000, Philip Warner - * Rights are granted to use this software in any way so long - * as this notice is not removed. - * - * The author is not responsible for loss or damages that may - * result from it's use. - * - * - * IDENTIFICATION - * - * Modifications - 01-Jul-2000 - pjw@rhyme.com.au - * - * Initial version. - * - *------------------------------------------------------------------------- - */ - -#include -#include -#include /* for dup */ -#include "pg_backup.h" -#include "pg_backup_archiver.h" - -static void _ArchiveEntry(ArchiveHandle* AH, TocEntry* te); -static void _StartData(ArchiveHandle* AH, TocEntry* te); -static int _WriteData(ArchiveHandle* AH, const void* data, int dLen); -static void _EndData(ArchiveHandle* AH, TocEntry* te); -static int _WriteByte(ArchiveHandle* AH, const int i); -static int _WriteBuf(ArchiveHandle* AH, const void* buf, int len); -static void _CloseArchive(ArchiveHandle* AH); -static void _PrintTocData(ArchiveHandle* AH, TocEntry* te, RestoreOptions *ropt); - -/* - * Initializer - */ -void InitArchiveFmt_PlainText(ArchiveHandle* AH) -{ - /* Assuming static functions, this can be copied for each format. */ - AH->ArchiveEntryPtr = _ArchiveEntry; - AH->StartDataPtr = _StartData; - AH->WriteDataPtr = _WriteData; - AH->EndDataPtr = _EndData; - AH->WriteBytePtr = _WriteByte; - AH->WriteBufPtr = _WriteBuf; - AH->ClosePtr = _CloseArchive; - AH->PrintTocDataPtr = _PrintTocData; - - /* - * Now prevent reading... - */ - if (AH->mode == archModeRead) - die_horribly("%s: This format can not be read\n"); - -} - -/* - * - Start a new TOC entry - */ -static void _ArchiveEntry(ArchiveHandle* AH, TocEntry* te) -{ - /* Don't need to do anything */ -} - -static void _StartData(ArchiveHandle* AH, TocEntry* te) -{ - ahprintf(AH, "--\n-- Data for TOC Entry ID %d (OID %s) %s %s\n--\n\n", - te->id, te->oid, te->desc, te->name); -} - -static int _WriteData(ArchiveHandle* AH, const void* data, int dLen) -{ - ahwrite(data, 1, dLen, AH); - return dLen; -} - -static void _EndData(ArchiveHandle* AH, TocEntry* te) -{ - ahprintf(AH, "\n\n"); -} - -/* - * Print data for a given TOC entry -*/ -static void _PrintTocData(ArchiveHandle* AH, TocEntry* te, RestoreOptions *ropt) -{ - if (*te->dataDumper) - (*te->dataDumper)((Archive*)AH, te->oid, te->dataDumperArg); -} - -static int _WriteByte(ArchiveHandle* AH, const int i) -{ - /* Don't do anything */ - return 0; -} - -static int _WriteBuf(ArchiveHandle* AH, const void* buf, int len) -{ - /* Don't do anything */ - return len; -} - -static void _CloseArchive(ArchiveHandle* AH) -{ - /* Nothing to do */ -} - diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index e4a47b9ef10..7c89573e291 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -22,7 +22,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.160 2000/07/21 11:40:08 pjw Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.161 2000/07/24 06:24:26 pjw Exp $ * * Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb * @@ -883,7 +883,6 @@ main(int argc, char **argv) MoveToEnd(g_fout, "INDEX"); MoveToEnd(g_fout, "TRIGGER"); MoveToEnd(g_fout, "RULE"); - MoveToEnd(g_fout, "ACL"); if (plainText) { @@ -3819,6 +3818,7 @@ dumpRules(Archive *fout, const char *tablename, int i_definition; int i_oid; + int i_owner; int i_rulename; if (g_verbose) @@ -3837,8 +3837,9 @@ dumpRules(Archive *fout, const char *tablename, * Get all rules defined for this table */ resetPQExpBuffer(query); - appendPQExpBuffer(query, "SELECT pg_get_ruledef(pg_rewrite.rulename) " - "AS definition, pg_rewrite.oid, pg_rewrite.rulename FROM pg_rewrite, pg_class " + appendPQExpBuffer(query, "SELECT pg_get_ruledef(pg_rewrite.rulename) AS definition," + "pg_get_userbyid(pg_class.relowner) AS viewowner, " + "pg_rewrite.oid, pg_rewrite.rulename FROM pg_rewrite, pg_class " "WHERE pg_class.relname = '%s' " "AND pg_rewrite.ev_class = pg_class.oid " "ORDER BY pg_rewrite.oid", @@ -3854,6 +3855,7 @@ dumpRules(Archive *fout, const char *tablename, nrules = PQntuples(res); i_definition = PQfnumber(res, "definition"); + i_owner = PQfnumber(res, "viewowner"); i_oid = PQfnumber(res, "oid"); i_rulename = PQfnumber(res, "rulename"); @@ -3863,10 +3865,9 @@ dumpRules(Archive *fout, const char *tablename, for (i = 0; i < nrules; i++) { - ArchiveEntry(fout, PQgetvalue(res, i, i_oid), PQgetvalue(res, i, i_rulename), "RULE", NULL, PQgetvalue(res, i, i_definition), - "", "", "", NULL, NULL); + "", "", PQgetvalue(res, i, i_owner), NULL, NULL); /* Dump rule comments */