15
15
*
16
16
*
17
17
* 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 $
19
19
*
20
20
*-------------------------------------------------------------------------
21
21
*/
@@ -98,6 +98,7 @@ static void _selectTablespace(ArchiveHandle *AH, const char *tablespace);
98
98
static void processEncodingEntry (ArchiveHandle * AH ,TocEntry * te );
99
99
static void processStdStringsEntry (ArchiveHandle * AH ,TocEntry * te );
100
100
static teReqs _tocEntryRequired (TocEntry * te ,RestoreOptions * ropt ,bool include_acls );
101
+ static bool _tocEntryIsACL (TocEntry * te );
101
102
static void _disableTriggersIfNecessary (ArchiveHandle * AH ,TocEntry * te ,RestoreOptions * ropt );
102
103
static void _enableTriggersIfNecessary (ArchiveHandle * AH ,TocEntry * te ,RestoreOptions * ropt );
103
104
static TocEntry * getTocEntryByDumpId (ArchiveHandle * AH ,DumpId id );
@@ -329,9 +330,9 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
329
330
AH -> currentTE = te ;
330
331
331
332
reqs = _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 )
333
335
{
334
- /* We want the schema */
335
336
ahlog (AH ,1 ,"dropping %s %s\n" ,te -> desc ,te -> tag );
336
337
/* Select owner and schema as necessary */
337
338
_becomeOwner (AH ,te );
@@ -381,7 +382,8 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
381
382
/* Work out what, if anything, we want from this entry */
382
383
reqs = _tocEntryRequired (te ,ropt , true);
383
384
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 )
385
387
{
386
388
ahlog (AH ,1 ,"setting owner and privileges for %s %s\n" ,
387
389
te -> desc ,te -> tag );
@@ -905,6 +907,7 @@ EndRestoreBlobs(ArchiveHandle *AH)
905
907
void
906
908
StartRestoreBlob (ArchiveHandle * AH ,Oid oid ,bool drop )
907
909
{
910
+ bool old_blob_style = (AH -> version < K_VERS_1_12 );
908
911
Oid loOid ;
909
912
910
913
AH -> blobCount ++ ;
@@ -914,24 +917,32 @@ StartRestoreBlob(ArchiveHandle *AH, Oid oid, bool drop)
914
917
915
918
ahlog (AH ,2 ,"restoring large object with OID %u\n" ,oid );
916
919
917
- if (drop )
920
+ /* With an old archive we must do drop and create logic here */
921
+ if (old_blob_style && drop )
918
922
DropBlobIfExists (AH ,oid );
919
923
920
924
if (AH -> connection )
921
925
{
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
+ }
927
933
AH -> loFd = lo_open (AH -> connection ,oid ,INV_WRITE );
928
934
if (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 );
930
937
}
931
938
else
932
939
{
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 );
935
946
}
936
947
937
948
AH -> writingBlob = 1 ;
@@ -1829,6 +1840,9 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
1829
1840
AH -> vmin = K_VERS_MINOR ;
1830
1841
AH -> vrev = K_VERS_REV ;
1831
1842
1843
+ /* Make a convenient integer <maj><min><rev>00 */
1844
+ AH -> version = ((AH -> vmaj * 256 + AH -> vmin )* 256 + AH -> vrev )* 256 + 0 ;
1845
+
1832
1846
/* initialize for backwards compatible string processing */
1833
1847
AH -> public .encoding = 0 ;/* PG_SQL_ASCII */
1834
1848
AH -> public .std_strings = false;
@@ -2068,12 +2082,13 @@ ReadToc(ArchiveHandle *AH)
2068
2082
else
2069
2083
{
2070
2084
/*
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.
2073
2088
*/
2074
2089
if (strcmp (te -> desc ,"COMMENT" )== 0 ||
2075
2090
strcmp (te -> desc ,"ACL" )== 0 ||
2076
- strcmp (te -> desc ,"DEFAULT ACL" )== 0 )
2091
+ strcmp (te -> desc ,"ACL LANGUAGE " )== 0 )
2077
2092
te -> section = SECTION_NONE ;
2078
2093
else if (strcmp (te -> desc ,"TABLE DATA" )== 0 ||
2079
2094
strcmp (te -> desc ,"BLOBS" )== 0 ||
@@ -2228,10 +2243,10 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
2228
2243
return 0 ;
2229
2244
2230
2245
/* 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 ))
2233
2247
return 0 ;
2234
2248
2249
+ /* Ignore DATABASE entry unless we should create it */
2235
2250
if (!ropt -> create && strcmp (te -> desc ,"DATABASE" )== 0 )
2236
2251
return 0 ;
2237
2252
@@ -2286,9 +2301,18 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
2286
2301
if (!te -> hadDumper )
2287
2302
{
2288
2303
/*
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.
2290
2309
*/
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 ))
2292
2316
res = res & REQ_DATA ;
2293
2317
else
2294
2318
res = res & ~REQ_DATA ;
@@ -2320,6 +2344,20 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
2320
2344
return res ;
2321
2345
}
2322
2346
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
+
2323
2361
/*
2324
2362
* Issue SET commands for parameters that we want to have set the same way
2325
2363
* at all times during execution of a restore script.
@@ -2685,6 +2723,13 @@ _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH)
2685
2723
return ;
2686
2724
}
2687
2725
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
+
2688
2733
/*
2689
2734
* These object types require additional decoration. Fortunately, the
2690
2735
* information needed is exactly what's in the DROP command.
@@ -2723,14 +2768,12 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
2723
2768
/* ACLs are dumped only during acl pass */
2724
2769
if (acl_pass )
2725
2770
{
2726
- if (!(strcmp (te -> desc ,"ACL" )== 0 ||
2727
- strcmp (te -> desc ,"DEFAULT ACL" )== 0 ))
2771
+ if (!_tocEntryIsACL (te ))
2728
2772
return ;
2729
2773
}
2730
2774
else
2731
2775
{
2732
- if (strcmp (te -> desc ,"ACL" )== 0 ||
2733
- strcmp (te -> desc ,"DEFAULT ACL" )== 0 )
2776
+ if (_tocEntryIsACL (te ))
2734
2777
return ;
2735
2778
}
2736
2779
@@ -2824,6 +2867,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
2824
2867
strlen (te -> owner )> 0 && strlen (te -> dropStmt )> 0 )
2825
2868
{
2826
2869
if (strcmp (te -> desc ,"AGGREGATE" )== 0 ||
2870
+ strcmp (te -> desc ,"BLOB" )== 0 ||
2827
2871
strcmp (te -> desc ,"CONVERSION" )== 0 ||
2828
2872
strcmp (te -> desc ,"DATABASE" )== 0 ||
2829
2873
strcmp (te -> desc ,"DOMAIN" )== 0 ||
@@ -2873,7 +2917,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
2873
2917
* If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
2874
2918
* commands, so we can no longer assume we know the current auth setting.
2875
2919
*/
2876
- if (strncmp ( te -> desc , "ACL" , 3 ) == 0 )
2920
+ if (acl_pass )
2877
2921
{
2878
2922
if (AH -> currUser )
2879
2923
free (AH -> currUser );