From fd02931a6c83bf3beb2d03f65700600787d569a3 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Tue, 30 Sep 2014 12:06:37 -0300
Subject: [PATCH] Fix pg_dump's --if-exists for large objects
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This was born broken in 9067310cc5dd590e36c2c3219dbf3961d7c9f8cb.

Per trouble report from Joachim Wieland.

Pavel Stěhule and Álvaro Herrera
---
 src/bin/pg_dump/pg_backup_archiver.c | 99 ++++++++++++++++------------
 1 file changed, 57 insertions(+), 42 deletions(-)

diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 32a08b038b0..1303ef6d49b 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -440,60 +440,75 @@ RestoreArchive(Archive *AHX)
 					}
 					else
 					{
-						char		buffer[40];
-						char	   *mark;
-						char	   *dropStmt = pg_strdup(te->dropStmt);
-						char	   *dropStmtPtr = dropStmt;
-						PQExpBuffer ftStmt = createPQExpBuffer();
-
 						/*
-						 * Need to inject IF EXISTS clause after ALTER TABLE
-						 * part in ALTER TABLE .. DROP statement
+						 * Inject an appropriate spelling of "if exists".  For
+						 * large objects, we have a separate routine that
+						 * knows how to do it, without depending on
+						 * te->dropStmt; use that.  For other objects we need
+						 * to parse the command.
+						 *
 						 */
-						if (strncmp(dropStmt, "ALTER TABLE", 11) == 0)
+						if (strncmp(te->desc, "BLOB", 4) == 0)
 						{
-							appendPQExpBuffer(ftStmt,
-											  "ALTER TABLE IF EXISTS");
-							dropStmt = dropStmt + 11;
+							DropBlobIfExists(AH, te->catalogId.oid);
 						}
-
-						/*
-						 * ALTER TABLE..ALTER COLUMN..DROP DEFAULT does not
-						 * support the IF EXISTS clause, and therefore we
-						 * simply emit the original command for such objects.
-						 * For other objects, we need to extract the first
-						 * part of the DROP which includes the object type.
-						 * Most of the time this matches te->desc, so search
-						 * for that; however for the different kinds of
-						 * CONSTRAINTs, we know to search for hardcoded "DROP
-						 * CONSTRAINT" instead.
-						 */
-						if (strcmp(te->desc, "DEFAULT") == 0)
-							appendPQExpBuffer(ftStmt, "%s", dropStmt);
 						else
 						{
-							if (strcmp(te->desc, "CONSTRAINT") == 0 ||
-								strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
-								strcmp(te->desc, "FK CONSTRAINT") == 0)
-								strcpy(buffer, "DROP CONSTRAINT");
+							char		buffer[40];
+							char	   *mark;
+							char	   *dropStmt = pg_strdup(te->dropStmt);
+							char	   *dropStmtPtr = dropStmt;
+							PQExpBuffer ftStmt = createPQExpBuffer();
+
+							/*
+							 * Need to inject IF EXISTS clause after ALTER
+							 * TABLE part in ALTER TABLE .. DROP statement
+							 */
+							if (strncmp(dropStmt, "ALTER TABLE", 11) == 0)
+							{
+								appendPQExpBuffer(ftStmt,
+												  "ALTER TABLE IF EXISTS");
+								dropStmt = dropStmt + 11;
+							}
+
+							/*
+							 * ALTER TABLE..ALTER COLUMN..DROP DEFAULT does
+							 * not support the IF EXISTS clause, and therefore
+							 * we simply emit the original command for such
+							 * objects. For other objects, we need to extract
+							 * the first part of the DROP which includes the
+							 * object type. Most of the time this matches
+							 * te->desc, so search for that; however for the
+							 * different kinds of CONSTRAINTs, we know to
+							 * search for hardcoded "DROP CONSTRAINT" instead.
+							 */
+							if (strcmp(te->desc, "DEFAULT") == 0)
+								appendPQExpBuffer(ftStmt, "%s", dropStmt);
 							else
-								snprintf(buffer, sizeof(buffer), "DROP %s",
-										 te->desc);
+							{
+								if (strcmp(te->desc, "CONSTRAINT") == 0 ||
+								 strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
+									strcmp(te->desc, "FK CONSTRAINT") == 0)
+									strcpy(buffer, "DROP CONSTRAINT");
+								else
+									snprintf(buffer, sizeof(buffer), "DROP %s",
+											 te->desc);
 
-							mark = strstr(dropStmt, buffer);
-							Assert(mark != NULL);
+								mark = strstr(dropStmt, buffer);
+								Assert(mark != NULL);
 
-							*mark = '\0';
-							appendPQExpBuffer(ftStmt, "%s%s IF EXISTS%s",
-											  dropStmt, buffer,
-											  mark + strlen(buffer));
-						}
+								*mark = '\0';
+								appendPQExpBuffer(ftStmt, "%s%s IF EXISTS%s",
+												  dropStmt, buffer,
+												  mark + strlen(buffer));
+							}
 
-						ahprintf(AH, "%s", ftStmt->data);
+							ahprintf(AH, "%s", ftStmt->data);
 
-						destroyPQExpBuffer(ftStmt);
+							destroyPQExpBuffer(ftStmt);
 
-						pg_free(dropStmtPtr);
+							pg_free(dropStmtPtr);
+						}
 					}
 				}
 			}
-- 
GitLab