1515 *
1616 *
1717 * IDENTIFICATION
18- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.87 2004/05/19 21:21:26 momjian Exp $
18+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.88 2004/07/13 03:00:17 momjian Exp $
1919 *
2020 *-------------------------------------------------------------------------
2121 */
@@ -47,7 +47,10 @@ static char *modulename = gettext_noop("archiver");
4747
4848static ArchiveHandle * _allocAH (const char * FileSpec , const ArchiveFormat fmt ,
4949 const int compression , ArchiveMode mode );
50- static int _printTocEntry (ArchiveHandle * AH , TocEntry * te , RestoreOptions * ropt , bool isData );
50+ static char * _getObjectFromDropStmt (const char * dropStmt , const char * type );
51+ static void _printTocHeader (ArchiveHandle * AH , TocEntry * te , RestoreOptions * ropt , bool isData );
52+ static int _printTocEntry (ArchiveHandle * AH , TocEntry * te , RestoreOptions * ropt , bool isData , bool ownerAndACL );
53+
5154
5255static void fixPriorBlobRefs (ArchiveHandle * AH , TocEntry * blobte ,
5356 RestoreOptions * ropt );
@@ -59,7 +62,7 @@ static void _becomeUser(ArchiveHandle *AH, const char *user);
5962static void _becomeOwner (ArchiveHandle * AH , TocEntry * te );
6063static void _selectOutputSchema (ArchiveHandle * AH , const char * schemaName );
6164
62- static teReqs _tocEntryRequired (TocEntry * te , RestoreOptions * ropt );
65+ static teReqs _tocEntryRequired (TocEntry * te , RestoreOptions * ropt , bool ownerAndACL );
6366static void _disableTriggersIfNecessary (ArchiveHandle * AH , TocEntry * te , RestoreOptions * ropt );
6467static void _enableTriggersIfNecessary (ArchiveHandle * AH , TocEntry * te , RestoreOptions * ropt );
6568static TocEntry * getTocEntryByDumpId (ArchiveHandle * AH , DumpId id );
@@ -181,7 +184,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
181184 impliedDataOnly = 1 ;
182185 while (te != AH -> toc )
183186 {
184- reqs = _tocEntryRequired (te , ropt );
187+ reqs = _tocEntryRequired (te , ropt , false );
185188 if ((reqs & REQ_SCHEMA ) != 0 )
186189 { /* It's schema, and it's wanted */
187190 impliedDataOnly = 0 ;
@@ -217,7 +220,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
217220 te = AH -> toc -> prev ;
218221 while (te != AH -> toc )
219222 {
220- reqs = _tocEntryRequired (te , ropt );
223+ reqs = _tocEntryRequired (te , ropt , false );
221224 if (((reqs & REQ_SCHEMA ) != 0 ) && te -> dropStmt )
222225 {
223226 /* We want the schema */
@@ -239,7 +242,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
239242 while (te != AH -> toc )
240243 {
241244 /* Work out what, if anything, we want from this entry */
242- reqs = _tocEntryRequired (te , ropt );
245+ reqs = _tocEntryRequired (te , ropt , false );
243246
244247 /* Dump any relevant dump warnings to stderr */
245248 if (!ropt -> suppressDumpWarnings && strcmp (te -> desc , "WARNING" ) == 0 )
@@ -256,7 +259,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
256259 {
257260 ahlog (AH , 1 , "creating %s %s\n" , te -> desc , te -> tag );
258261
259- _printTocEntry (AH , te , ropt , false);
262+ _printTocEntry (AH , te , ropt , false, false );
260263 defnDumped = true;
261264
262265 /* If we created a DB, connect to it... */
@@ -290,7 +293,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
290293 die_horribly (AH , modulename , "cannot restore from compressed archive (not configured for compression support)\n" );
291294#endif
292295
293- _printTocEntry (AH , te , ropt , true);
296+ _printTocEntry (AH , te , ropt , true, false );
294297
295298 /*
296299 * Maybe we can't do BLOBS, so check if this node is
@@ -361,12 +364,34 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
361364 {
362365 /* If we haven't already dumped the defn part, do so now */
363366 ahlog (AH , 1 , "executing %s %s\n" , te -> desc , te -> tag );
364- _printTocEntry (AH , te , ropt , false);
367+ _printTocEntry (AH , te , ropt , false, false );
365368 }
366369 }
367370 te = te -> next ;
368371 } /* end loop over TOC entries */
369372
373+ /*
374+ * Scan TOC again to output ownership commands and ACLs
375+ */
376+ te = AH -> toc -> next ;
377+ while (te != AH -> toc )
378+ {
379+ /* Work out what, if anything, we want from this entry */
380+ reqs = _tocEntryRequired (te , ropt , true);
381+
382+ defnDumped = false;
383+
384+ if ((reqs & REQ_SCHEMA ) != 0 ) /* We want the schema */
385+ {
386+ ahlog (AH , 1 , "setting owner and acl for %s %s\n" , te -> desc , te -> tag );
387+
388+ _printTocEntry (AH , te , ropt , false, true);
389+ defnDumped = true;
390+ }
391+
392+ te = te -> next ;
393+ }
394+
370395 /*
371396 * Clean up & we're done.
372397 */
@@ -408,7 +433,7 @@ fixPriorBlobRefs(ArchiveHandle *AH, TocEntry *blobte, RestoreOptions *ropt)
408433 {
409434 if (strcmp (te -> desc , "TABLE DATA" ) == 0 )
410435 {
411- reqs = _tocEntryRequired (te , ropt );
436+ reqs = _tocEntryRequired (te , ropt , false );
412437
413438 if ((reqs & REQ_DATA ) != 0 ) /* We loaded the data */
414439 {
@@ -659,7 +684,7 @@ PrintTOCSummary(Archive *AHX, RestoreOptions *ropt)
659684
660685 while (te != AH -> toc )
661686 {
662- if (_tocEntryRequired (te , ropt ) != 0 )
687+ if (_tocEntryRequired (te , ropt , false ) != 0 )
663688 ahprintf (AH , "%d; %u %u %s %s %s\n" , te -> dumpId ,
664689 te -> catalogId .tableoid , te -> catalogId .oid ,
665690 te -> desc , te -> tag , te -> owner );
@@ -1270,7 +1295,7 @@ TocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt)
12701295 if (!te )
12711296 return 0 ;
12721297
1273- return _tocEntryRequired (te , ropt );
1298+ return _tocEntryRequired (te , ropt , false );
12741299}
12751300
12761301size_t
@@ -1888,7 +1913,7 @@ ReadToc(ArchiveHandle *AH)
18881913}
18891914
18901915static teReqs
1891- _tocEntryRequired (TocEntry * te , RestoreOptions * ropt )
1916+ _tocEntryRequired (TocEntry * te , RestoreOptions * ropt , bool ownerAndACL )
18921917{
18931918 teReqs res = 3 ; /* Schema = 1, Data = 2, Both = 3 */
18941919
@@ -1897,7 +1922,7 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt)
18971922 return 0 ;
18981923
18991924 /* If it's an ACL, maybe ignore it */
1900- if (ropt -> aclsSkip && strcmp (te -> desc , "ACL" ) == 0 )
1925+ if ((! ownerAndACL || ropt -> aclsSkip ) && strcmp (te -> desc , "ACL" ) == 0 )
19011926 return 0 ;
19021927
19031928 if (!ropt -> create && strcmp (te -> desc , "DATABASE" ) == 0 )
@@ -2159,7 +2184,7 @@ _becomeUser(ArchiveHandle *AH, const char *user)
21592184static void
21602185_becomeOwner (ArchiveHandle * AH , TocEntry * te )
21612186{
2162- if (AH -> ropt && AH -> ropt -> noOwner )
2187+ if (AH -> ropt && ( AH -> ropt -> noOwner || ! AH -> ropt -> use_setsessauth ) )
21632188 return ;
21642189
21652190 _becomeUser (AH , te -> owner );
@@ -2224,18 +2249,65 @@ _selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
22242249}
22252250
22262251
2252+ /**
2253+ * Parses the dropStmt part of a TOC entry and returns
2254+ * a newly allocated string that is the object identifier
2255+ * The caller must free the result.
2256+ */
2257+ static char *
2258+ _getObjectFromDropStmt (const char * dropStmt , const char * type )
2259+ {
2260+ /* Chop "DROP" off the front and make a copy */
2261+ char * first = strdup (dropStmt + 5 );
2262+ char * last = first + strlen (first ) - 1 ; /* Points to the last real char in extract */
2263+ char * buf = NULL ;
2264+
2265+ /* Loop from the end of the string until last char is no longer '\n' or ';' */
2266+ while (last >= first && (* last == '\n' || * last == ';' )) {
2267+ last -- ;
2268+ }
2269+
2270+ /* Insert end of string one place after last */
2271+ * (last + 1 ) = '\0' ;
22272272
2228- static int
2229- _printTocEntry (ArchiveHandle * AH , TocEntry * te , RestoreOptions * ropt , bool isData )
2273+ /* Take off CASCADE if necessary. Only TYPEs seem to have this, but may
2274+ * as well check for all */
2275+ if ((last - first ) >= 8 ) {
2276+ if (strcmp (last - 7 , " CASCADE" ) == 0 )
2277+ last -= 8 ;
2278+ }
2279+
2280+ /* Insert end of string one place after last */
2281+ * (last + 1 ) = '\0' ;
2282+
2283+ /* Special case VIEWs and SEQUENCEs. They must use ALTER TABLE. */
2284+ if (strcmp (type , "VIEW" ) == 0 && (last - first ) >= 5 )
2285+ {
2286+ int len = 6 + strlen (first + 5 ) + 1 ;
2287+ buf = malloc (len );
2288+ snprintf (buf , len , "TABLE %s" , first + 5 );
2289+ free (first );
2290+ }
2291+ else if (strcmp (type , "SEQUENCE" ) == 0 && (last - first ) >= 9 )
2292+ {
2293+ int len = 6 + strlen (first + 9 ) + 1 ;
2294+ buf = malloc (len );
2295+ snprintf (buf , len , "TABLE %s" , first + 9 );
2296+ free (first );
2297+ }
2298+ else
2299+ {
2300+ buf = first ;
2301+ }
2302+
2303+ return buf ;
2304+ }
2305+
2306+ static void
2307+ _printTocHeader (ArchiveHandle * AH , TocEntry * te , RestoreOptions * ropt , bool isData )
22302308{
22312309 const char * pfx ;
22322310
2233- /* Select owner and schema as necessary */
2234- _becomeOwner (AH , te );
2235- _selectOutputSchema (AH , te -> namespace );
2236- if (strcmp (te -> desc , "TABLE" ) == 0 )
2237- _setWithOids (AH , te );
2238-
22392311 if (isData )
22402312 pfx = "Data for " ;
22412313 else
@@ -2263,21 +2335,60 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
22632335 if (AH -> PrintExtraTocPtr != NULL )
22642336 (* AH -> PrintExtraTocPtr ) (AH , te );
22652337 ahprintf (AH , "--\n\n" );
2338+ }
22662339
2267- /*
2268- * Really crude hack for suppressing AUTHORIZATION clause of CREATE SCHEMA
2269- * when --no-owner mode is selected. This is ugly, but I see no other
2270- * good way ...
2271- */
2272- if (AH -> ropt && AH -> ropt -> noOwner && strcmp (te -> desc , "SCHEMA" ) == 0 )
2340+ static int
2341+ _printTocEntry (ArchiveHandle * AH , TocEntry * te , RestoreOptions * ropt , bool isData , bool ownerAndACL )
2342+ {
2343+ /* Select schema as necessary */
2344+ _becomeOwner (AH , te );
2345+ _selectOutputSchema (AH , te -> namespace );
2346+ if (strcmp (te -> desc , "TABLE" ) == 0 && !ownerAndACL )
2347+ _setWithOids (AH , te );
2348+
2349+ if (!ropt -> noOwner && !ropt -> use_setsessauth && ownerAndACL && strlen (te -> owner ) > 0 && strlen (te -> dropStmt ) > 0 && (
2350+ strcmp (te -> desc , "AGGREGATE" ) == 0 ||
2351+ strcmp (te -> desc , "CONVERSION" ) == 0 ||
2352+ strcmp (te -> desc , "DOMAIN" ) == 0 ||
2353+ strcmp (te -> desc , "FUNCTION" ) == 0 ||
2354+ strcmp (te -> desc , "OPERATOR" ) == 0 ||
2355+ strcmp (te -> desc , "OPERATOR CLASS" ) == 0 ||
2356+ strcmp (te -> desc , "TABLE" ) == 0 ||
2357+ strcmp (te -> desc , "TYPE" ) == 0 ||
2358+ strcmp (te -> desc , "VIEW" ) == 0 ||
2359+ strcmp (te -> desc , "SEQUENCE" ) == 0
2360+ ))
22732361 {
2274- ahprintf (AH , "CREATE SCHEMA %s;\n\n\n" , te -> tag );
2362+ char * temp = _getObjectFromDropStmt (te -> dropStmt , te -> desc );
2363+ _printTocHeader (AH , te , ropt , isData );
2364+ ahprintf (AH , "ALTER %s OWNER TO %s;\n\n" , temp , fmtId (te -> owner ));
2365+ free (temp );
2366+ }
2367+ else if (ownerAndACL && strcmp (te -> desc , "ACL" ) == 0 )
2368+ {
2369+ _printTocHeader (AH , te , ropt , isData );
2370+ ahprintf (AH , "%s\n\n" , te -> defn );
22752371 }
2276- else
2372+ else if (! ownerAndACL && strlen ( te -> defn ) > 0 )
22772373 {
2278- /* normal case */
2279- if (strlen (te -> defn ) > 0 )
2374+ _printTocHeader (AH , te , ropt , isData );
2375+
2376+ /*
2377+ * Really crude hack for suppressing AUTHORIZATION clause of CREATE SCHEMA
2378+ * when --no-owner mode is selected. This is ugly, but I see no other
2379+ * good way ...
2380+ */
2381+ if (AH -> ropt && AH -> ropt -> noOwner && strcmp (te -> desc , "SCHEMA" ) == 0 )
2382+ {
2383+ ahprintf (AH , "CREATE SCHEMA %s;\n\n\n" , te -> tag );
2384+ }
2385+ else
2386+ {
22802387 ahprintf (AH , "%s\n\n" , te -> defn );
2388+ }
2389+ }
2390+ else if (isData ) {
2391+ _printTocHeader (AH , te , ropt , isData );
22812392 }
22822393
22832394 return 1 ;
0 commit comments