Re: pg_restore -1 vs -C and -c - Mailing list pgsql-hackers

From Magnus Hagander
Subject Re: pg_restore -1 vs -C and -c
Date
Msg-id 497746E5.5040507@hagander.net
Whole thread Raw
In response to Re: pg_restore -1 vs -C and -c  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
Tom Lane wrote:
> Magnus Hagander <magnus@hagander.net> writes:
>>>> As for -c, the solution would be to issue DROP IF EXISTS
>>>> statements. Is there any particular reason why we don't?
>>> I think we did that to avoid damaging portability and backwards
>>> compatibility of the dump files.  The backwards compatibility argument
>>> is pretty weak by now, but the "it's not standard SQL" argument still
>>> has force.
>
>> IIRC the drop statements are generated by pg_restore and not stored in
>> the archive. So we could do the if exists by default and have a switch
>> to turn it off for a compatible dump, perhaps?
>
> No, the text of the statements is in the archive; though it might not be
> too painful to have pg_restore edit them to insert "IF EXISTS".  You
> don't need an extra switch, just do this if -1 is in use (and document
> that that switch reduces the standard-ness of the output...)

Something along the line of this?

(This is for the actual injection, I still haven't implemented
switch/decided when to actually include it, so this is not for
application yet - just for a comment on the general method..)

//Magnus

*** a/src/bin/pg_dump/pg_backup_archiver.c
--- b/src/bin/pg_dump/pg_backup_archiver.c
***************
*** 123,128 **** CloseArchive(Archive *AHX)
--- 123,144 ----
                       strerror(errno));
  }

+ /*
+  * List all objects that can be DROPped that are made up of more
+  * than a single word.
+  */
+ static const char *multiword_drops[] = {
+     "FOREIGN DATA WRAPPER",
+     "OPERATOR CLASS",
+     "OPERATOR FAMILY",
+     "TEXT SEARCH CONFIGURATION",
+     "TEXT SEARCH DICTIONARY",
+     "TEXT SEARCH PARSER",
+     "TEXT SEARCH TEMPLATE",
+     "USER MAPPING",
+     NULL
+ };
+
  /* Public */
  void
  RestoreArchive(Archive *AHX, RestoreOptions *ropt)
***************
*** 249,256 **** RestoreArchive(Archive *AHX, RestoreOptions *ropt)
                  /* Select owner and schema as necessary */
                  _becomeOwner(AH, te);
                  _selectOutputSchema(AH, te->namespace);
!                 /* Drop it */
!                 ahprintf(AH, "%s", te->dropStmt);
              }
          }

--- 265,308 ----
                  /* Select owner and schema as necessary */
                  _becomeOwner(AH, te);
                  _selectOutputSchema(AH, te->namespace);
!                 /*
!                  * Figure out if it's something we can do DROP IF EXISTS on.
!                  * Check for "DROP " just to be sure.
!                  */
!                 if (strncmp(te->dropStmt, "DROP ", 5) == 0)
!                 {
!                     char   *cp = te->dropStmt + 5;
!                     char   *insertpoint = NULL;
!                     char   *newstr = NULL;
!                     int        i;
!
!                     /*
!                      * Assume that all objects can be DROP IF EXISTS:ed. However,
!                      * some have more than one word in them, so we need to figure
!                      * out exactly where to insert the IF EXISTS.
!                      */
!                     for (i = 0; multiword_drops[i] != NULL; i++)
!                     {
!                         if (strncmp(cp, multiword_drops[i], strlen(multiword_drops[i])) == 0)
!                         {
!                             insertpoint = cp + strlen(multiword_drops[i]);
!                             break;
!                         }
!                     }
!                     if (insertpoint == NULL)
!                         insertpoint = strchr(cp, ' ');
!                     if (insertpoint == NULL)
!                         die_horribly(AH,modulename,"malformatted DROP statement: %s", te->dropStmt);
!
!                     newstr = calloc(strlen(te->dropStmt) + 11, 1); /* "IF EXISTS " + terminator */
!                     strncpy(newstr, te->dropStmt, insertpoint - te->dropStmt);
!                     strcat(newstr, " IF EXISTS");
!                     strcat(newstr, insertpoint);
!                     ahprintf(AH, "%s", newstr);
!                     free(newstr);
!                 }
!                 else
!                     ahprintf(AH, "%s", te->dropStmt);
              }
          }


pgsql-hackers by date:

Previous
From: "Todd A. Cook"
Date:
Subject: Re: is 8.4 array_agg() supposed to work with array values?
Next
From: Gregory Stark
Date:
Subject: Re: rmgr hooks (v2)