From bb080400f8756724ef5b4098ff4fcdbf6d784fb6 Mon Sep 17 00:00:00 2001
From: Philip Warner <pjw@rhyme.com.au>
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 <stdlib.h>
-#include <string.h>
-#include <unistd.h> /* 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 */
 
-- 
GitLab