1515 *
1616 *
1717 * IDENTIFICATION
18- *$PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.178 2010/01/19 18:39:19 tgl Exp $
18+ *$PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.179 2010/02/18 01:29:10 tgl Exp $
1919 *
2020 *-------------------------------------------------------------------------
2121 */
@@ -98,6 +98,7 @@ static void _selectTablespace(ArchiveHandle *AH, const char *tablespace);
9898static void processEncodingEntry (ArchiveHandle * AH ,TocEntry * te );
9999static void processStdStringsEntry (ArchiveHandle * AH ,TocEntry * te );
100100static teReqs _tocEntryRequired (TocEntry * te ,RestoreOptions * ropt ,bool include_acls );
101+ static bool _tocEntryIsACL (TocEntry * te );
101102static void _disableTriggersIfNecessary (ArchiveHandle * AH ,TocEntry * te ,RestoreOptions * ropt );
102103static void _enableTriggersIfNecessary (ArchiveHandle * AH ,TocEntry * te ,RestoreOptions * ropt );
103104static TocEntry * getTocEntryByDumpId (ArchiveHandle * AH ,DumpId id );
@@ -329,9 +330,9 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
329330AH -> currentTE = te ;
330331
331332reqs = _tocEntryRequired (te ,ropt , false/* needn't drop ACLs */ );
332- if (((reqs & REQ_SCHEMA )!= 0 )&& te -> dropStmt )
333+ /* We want anything that's selected and has a dropStmt */
334+ if (((reqs & (REQ_SCHEMA |REQ_DATA ))!= 0 )&& te -> dropStmt )
333335{
334- /* We want the schema */
335336ahlog (AH ,1 ,"dropping %s %s\n" ,te -> desc ,te -> tag );
336337/* Select owner and schema as necessary */
337338_becomeOwner (AH ,te );
@@ -381,7 +382,8 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
381382/* Work out what, if anything, we want from this entry */
382383reqs = _tocEntryRequired (te ,ropt , true);
383384
384- if ((reqs & REQ_SCHEMA )!= 0 )/* We want the schema */
385+ /* Both schema and data objects might now have ownership/ACLs */
386+ if ((reqs & (REQ_SCHEMA |REQ_DATA ))!= 0 )
385387{
386388ahlog (AH ,1 ,"setting owner and privileges for %s %s\n" ,
387389te -> desc ,te -> tag );
@@ -905,6 +907,7 @@ EndRestoreBlobs(ArchiveHandle *AH)
905907void
906908StartRestoreBlob (ArchiveHandle * AH ,Oid oid ,bool drop )
907909{
910+ bool old_blob_style = (AH -> version < K_VERS_1_12 );
908911Oid loOid ;
909912
910913AH -> blobCount ++ ;
@@ -914,24 +917,32 @@ StartRestoreBlob(ArchiveHandle *AH, Oid oid, bool drop)
914917
915918ahlog (AH ,2 ,"restoring large object with OID %u\n" ,oid );
916919
917- if (drop )
920+ /* With an old archive we must do drop and create logic here */
921+ if (old_blob_style && drop )
918922DropBlobIfExists (AH ,oid );
919923
920924if (AH -> connection )
921925{
922- loOid = lo_create (AH -> connection ,oid );
923- if (loOid == 0 || loOid != oid )
924- die_horribly (AH ,modulename ,"could not create large object %u\n" ,
925- oid );
926-
926+ if (old_blob_style )
927+ {
928+ loOid = lo_create (AH -> connection ,oid );
929+ if (loOid == 0 || loOid != oid )
930+ die_horribly (AH ,modulename ,"could not create large object %u\n" ,
931+ oid );
932+ }
927933AH -> loFd = lo_open (AH -> connection ,oid ,INV_WRITE );
928934if (AH -> loFd == -1 )
929- die_horribly (AH ,modulename ,"could not open large object\n" );
935+ die_horribly (AH ,modulename ,"could not open large object %u\n" ,
936+ oid );
930937}
931938else
932939{
933- ahprintf (AH ,"SELECT pg_catalog.lo_open(pg_catalog.lo_create('%u'), %d);\n" ,
934- oid ,INV_WRITE );
940+ if (old_blob_style )
941+ ahprintf (AH ,"SELECT pg_catalog.lo_open(pg_catalog.lo_create('%u'), %d);\n" ,
942+ oid ,INV_WRITE );
943+ else
944+ ahprintf (AH ,"SELECT pg_catalog.lo_open('%u', %d);\n" ,
945+ oid ,INV_WRITE );
935946}
936947
937948AH -> writingBlob = 1 ;
@@ -1829,6 +1840,9 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
18291840AH -> vmin = K_VERS_MINOR ;
18301841AH -> vrev = K_VERS_REV ;
18311842
1843+ /* Make a convenient integer <maj><min><rev>00 */
1844+ AH -> version = ((AH -> vmaj * 256 + AH -> vmin )* 256 + AH -> vrev )* 256 + 0 ;
1845+
18321846/* initialize for backwards compatible string processing */
18331847AH -> public .encoding = 0 ;/* PG_SQL_ASCII */
18341848AH -> public .std_strings = false;
@@ -2068,12 +2082,13 @@ ReadToc(ArchiveHandle *AH)
20682082else
20692083{
20702084/*
2071- * rules for pre-8.4 archives wherein pg_dump hasn't classified
2072- * the entries into sections
2085+ * Rules for pre-8.4 archives wherein pg_dump hasn't classified
2086+ * the entries into sections. This list need not cover entry
2087+ * types added later than 8.4.
20732088 */
20742089if (strcmp (te -> desc ,"COMMENT" )== 0 ||
20752090strcmp (te -> desc ,"ACL" )== 0 ||
2076- strcmp (te -> desc ,"DEFAULT ACL" )== 0 )
2091+ strcmp (te -> desc ,"ACL LANGUAGE " )== 0 )
20772092te -> section = SECTION_NONE ;
20782093else if (strcmp (te -> desc ,"TABLE DATA" )== 0 ||
20792094strcmp (te -> desc ,"BLOBS" )== 0 ||
@@ -2228,10 +2243,10 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
22282243return 0 ;
22292244
22302245/* If it's an ACL, maybe ignore it */
2231- if ((!include_acls || ropt -> aclsSkip )&&
2232- (strcmp (te -> desc ,"ACL" )== 0 || strcmp (te -> desc ,"DEFAULT ACL" )== 0 ))
2246+ if ((!include_acls || ropt -> aclsSkip )&& _tocEntryIsACL (te ))
22332247return 0 ;
22342248
2249+ /* Ignore DATABASE entry unless we should create it */
22352250if (!ropt -> create && strcmp (te -> desc ,"DATABASE" )== 0 )
22362251return 0 ;
22372252
@@ -2286,9 +2301,18 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
22862301if (!te -> hadDumper )
22872302{
22882303/*
2289- * Special Case: If 'SEQUENCE SET' then it is considered a data entry
2304+ * Special Case: If 'SEQUENCE SET' or anything to do with BLOBs,
2305+ * then it is considered a data entry. We don't need to check for
2306+ * the BLOBS entry or old-style BLOB COMMENTS, because they will
2307+ * have hadDumper = true ... but we do need to check new-style
2308+ * BLOB comments.
22902309 */
2291- if (strcmp (te -> desc ,"SEQUENCE SET" )== 0 )
2310+ if (strcmp (te -> desc ,"SEQUENCE SET" )== 0 ||
2311+ strcmp (te -> desc ,"BLOB" )== 0 ||
2312+ (strcmp (te -> desc ,"ACL" )== 0 &&
2313+ strncmp (te -> tag ,"LARGE OBJECT " ,13 )== 0 )||
2314+ (strcmp (te -> desc ,"COMMENT" )== 0 &&
2315+ strncmp (te -> tag ,"LARGE OBJECT " ,13 )== 0 ))
22922316res = res & REQ_DATA ;
22932317else
22942318res = res & ~REQ_DATA ;
@@ -2320,6 +2344,20 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
23202344return res ;
23212345}
23222346
2347+ /*
2348+ * Identify TOC entries that are ACLs.
2349+ */
2350+ static bool
2351+ _tocEntryIsACL (TocEntry * te )
2352+ {
2353+ /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
2354+ if (strcmp (te -> desc ,"ACL" )== 0 ||
2355+ strcmp (te -> desc ,"ACL LANGUAGE" )== 0 ||
2356+ strcmp (te -> desc ,"DEFAULT ACL" )== 0 )
2357+ return true;
2358+ return false;
2359+ }
2360+
23232361/*
23242362 * Issue SET commands for parameters that we want to have set the same way
23252363 * at all times during execution of a restore script.
@@ -2685,6 +2723,13 @@ _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH)
26852723return ;
26862724}
26872725
2726+ /* BLOBs just have a name, but it's numeric so must not use fmtId */
2727+ if (strcmp (type ,"BLOB" )== 0 )
2728+ {
2729+ appendPQExpBuffer (buf ,"LARGE OBJECT %s" ,te -> tag );
2730+ return ;
2731+ }
2732+
26882733/*
26892734 * These object types require additional decoration. Fortunately, the
26902735 * information needed is exactly what's in the DROP command.
@@ -2723,14 +2768,12 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
27232768/* ACLs are dumped only during acl pass */
27242769if (acl_pass )
27252770{
2726- if (!(strcmp (te -> desc ,"ACL" )== 0 ||
2727- strcmp (te -> desc ,"DEFAULT ACL" )== 0 ))
2771+ if (!_tocEntryIsACL (te ))
27282772return ;
27292773}
27302774else
27312775{
2732- if (strcmp (te -> desc ,"ACL" )== 0 ||
2733- strcmp (te -> desc ,"DEFAULT ACL" )== 0 )
2776+ if (_tocEntryIsACL (te ))
27342777return ;
27352778}
27362779
@@ -2824,6 +2867,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
28242867strlen (te -> owner )> 0 && strlen (te -> dropStmt )> 0 )
28252868{
28262869if (strcmp (te -> desc ,"AGGREGATE" )== 0 ||
2870+ strcmp (te -> desc ,"BLOB" )== 0 ||
28272871strcmp (te -> desc ,"CONVERSION" )== 0 ||
28282872strcmp (te -> desc ,"DATABASE" )== 0 ||
28292873strcmp (te -> desc ,"DOMAIN" )== 0 ||
@@ -2873,7 +2917,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
28732917 * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
28742918 * commands, so we can no longer assume we know the current auth setting.
28752919 */
2876- if (strncmp ( te -> desc , "ACL" , 3 ) == 0 )
2920+ if (acl_pass )
28772921{
28782922if (AH -> currUser )
28792923free (AH -> currUser );