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 ,
4949const 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 ,
5356RestoreOptions * 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)
181184impliedDataOnly = 1 ;
182185while (te != AH -> toc )
183186{
184- reqs = _tocEntryRequired (te ,ropt );
187+ reqs = _tocEntryRequired (te ,ropt , false );
185188if ((reqs & REQ_SCHEMA )!= 0 )
186189{/* It's schema, and it's wanted */
187190impliedDataOnly = 0 ;
@@ -217,7 +220,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
217220te = AH -> toc -> prev ;
218221while (te != AH -> toc )
219222{
220- reqs = _tocEntryRequired (te ,ropt );
223+ reqs = _tocEntryRequired (te ,ropt , false );
221224if (((reqs & REQ_SCHEMA )!= 0 )&& te -> dropStmt )
222225{
223226/* We want the schema */
@@ -239,7 +242,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
239242while (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 */
245248if (!ropt -> suppressDumpWarnings && strcmp (te -> desc ,"WARNING" )== 0 )
@@ -256,7 +259,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
256259{
257260ahlog (AH ,1 ,"creating %s %s\n" ,te -> desc ,te -> tag );
258261
259- _printTocEntry (AH ,te ,ropt , false);
262+ _printTocEntry (AH ,te ,ropt , false, false );
260263defnDumped = true;
261264
262265/* If we created a DB, connect to it... */
@@ -290,7 +293,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
290293die_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 */
363366ahlog (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}
367370te = 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{
409434if (strcmp (te -> desc ,"TABLE DATA" )== 0 )
410435{
411- reqs = _tocEntryRequired (te ,ropt );
436+ reqs = _tocEntryRequired (te ,ropt , false );
412437
413438if ((reqs & REQ_DATA )!= 0 )/* We loaded the data */
414439{
@@ -659,7 +684,7 @@ PrintTOCSummary(Archive *AHX, RestoreOptions *ropt)
659684
660685while (te != AH -> toc )
661686{
662- if (_tocEntryRequired (te ,ropt )!= 0 )
687+ if (_tocEntryRequired (te ,ropt , false )!= 0 )
663688ahprintf (AH ,"%d; %u %u %s %s %s\n" ,te -> dumpId ,
664689te -> catalogId .tableoid ,te -> catalogId .oid ,
665690te -> desc ,te -> tag ,te -> owner );
@@ -1270,7 +1295,7 @@ TocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt)
12701295if (!te )
12711296return 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{
18931918teReqs res = 3 ;/* Schema = 1, Data = 2, Both = 3 */
18941919
@@ -1897,7 +1922,7 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt)
18971922return 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 )
19011926return 0 ;
19021927
19031928if (!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 ) )
21632188return ;
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{
22312309const 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-
22392311if (isData )
22402312pfx = "Data for " ;
22412313else
@@ -2263,21 +2335,60 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
22632335if (AH -> PrintExtraTocPtr != NULL )
22642336(* AH -> PrintExtraTocPtr ) (AH ,te );
22652337ahprintf (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+ {
22802387ahprintf (AH ,"%s\n\n" ,te -> defn );
2388+ }
2389+ }
2390+ else if (isData ) {
2391+ _printTocHeader (AH ,te ,ropt ,isData );
22812392}
22822393
22832394return 1 ;