@@ -114,19 +114,13 @@ typedef struct _outputContext
114114
115115static const char * modulename = gettext_noop ("archiver" );
116116
117- /* index array created by fix_dependencies -- only used in parallel restore */
118- static TocEntry * * tocsByDumpId ;/* index by dumpId - 1 */
119- static DumpId maxDumpId ;/* length of above array */
120-
121117
122118static ArchiveHandle * _allocAH (const char * FileSpec ,const ArchiveFormat fmt ,
123119const int compression ,ArchiveMode mode );
124120static void _getObjectDescription (PQExpBuffer buf ,TocEntry * te ,
125121ArchiveHandle * AH );
126122static void _printTocEntry (ArchiveHandle * AH ,TocEntry * te ,RestoreOptions * ropt ,bool isData ,bool acl_pass );
127123static char * replace_line_endings (const char * str );
128-
129-
130124static void _doSetFixedOutputState (ArchiveHandle * AH );
131125static void _doSetSessionAuth (ArchiveHandle * AH ,const char * user );
132126static void _doSetWithOids (ArchiveHandle * AH ,const bool withOids );
@@ -141,6 +135,7 @@ static teReqs _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include
141135static bool _tocEntryIsACL (TocEntry * te );
142136static void _disableTriggersIfNecessary (ArchiveHandle * AH ,TocEntry * te ,RestoreOptions * ropt );
143137static void _enableTriggersIfNecessary (ArchiveHandle * AH ,TocEntry * te ,RestoreOptions * ropt );
138+ static void buildTocEntryArrays (ArchiveHandle * AH );
144139static TocEntry * getTocEntryByDumpId (ArchiveHandle * AH ,DumpId id );
145140static void _moveBefore (ArchiveHandle * AH ,TocEntry * pos ,TocEntry * te );
146141static int _discoverArchiveFormat (ArchiveHandle * AH );
@@ -171,9 +166,8 @@ static void mark_work_done(ArchiveHandle *AH, TocEntry *ready_list,
171166ParallelSlot * slots ,int n_slots );
172167static void fix_dependencies (ArchiveHandle * AH );
173168static bool has_lock_conflicts (TocEntry * te1 ,TocEntry * te2 );
174- static void repoint_table_dependencies (ArchiveHandle * AH ,
175- DumpId tableId ,DumpId tableDataId );
176- static void identify_locking_dependencies (TocEntry * te );
169+ static void repoint_table_dependencies (ArchiveHandle * AH );
170+ static void identify_locking_dependencies (ArchiveHandle * AH ,TocEntry * te );
177171static void reduce_dependencies (ArchiveHandle * AH ,TocEntry * te ,
178172TocEntry * ready_list );
179173static void mark_create_done (ArchiveHandle * AH ,TocEntry * te );
@@ -305,6 +299,13 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
305299}
306300#endif
307301
302+ /*
303+ * Prepare index arrays, so we can assume we have them throughout restore.
304+ * It's possible we already did this, though.
305+ */
306+ if (AH -> tocsByDumpId == NULL )
307+ buildTocEntryArrays (AH );
308+
308309/*
309310 * If we're using a DB connection, then connect it.
310311 */
@@ -1524,16 +1525,68 @@ _moveBefore(ArchiveHandle *AH, TocEntry *pos, TocEntry *te)
15241525pos -> prev = te ;
15251526}
15261527
1527- static TocEntry *
1528- getTocEntryByDumpId (ArchiveHandle * AH ,DumpId id )
1528+ /*
1529+ * Build index arrays for the TOC list
1530+ *
1531+ * This should be invoked only after we have created or read in all the TOC
1532+ * items.
1533+ *
1534+ * The arrays are indexed by dump ID (so entry zero is unused). Note that the
1535+ * array entries run only up to maxDumpId. We might see dependency dump IDs
1536+ * beyond that (if the dump was partial); so always check the array bound
1537+ * before trying to touch an array entry.
1538+ */
1539+ static void
1540+ buildTocEntryArrays (ArchiveHandle * AH )
15291541{
1542+ DumpId maxDumpId = AH -> maxDumpId ;
15301543TocEntry * te ;
15311544
1545+ AH -> tocsByDumpId = (TocEntry * * )pg_calloc (maxDumpId + 1 ,sizeof (TocEntry * ));
1546+ AH -> tableDataId = (DumpId * )pg_calloc (maxDumpId + 1 ,sizeof (DumpId ));
1547+
15321548for (te = AH -> toc -> next ;te != AH -> toc ;te = te -> next )
15331549{
1534- if (te -> dumpId == id )
1535- return te ;
1550+ /* this check is purely paranoia, maxDumpId should be correct */
1551+ if (te -> dumpId <=0 || te -> dumpId > maxDumpId )
1552+ exit_horribly (modulename ,"bad dumpId" );
1553+
1554+ /* tocsByDumpId indexes all TOCs by their dump ID */
1555+ AH -> tocsByDumpId [te -> dumpId ]= te ;
1556+
1557+ /*
1558+ * tableDataId provides the TABLE DATA item's dump ID for each TABLE
1559+ * TOC entry that has a DATA item. We compute this by reversing the
1560+ * TABLE DATA item's dependency, knowing that a TABLE DATA item has
1561+ * just one dependency and it is the TABLE item.
1562+ */
1563+ if (strcmp (te -> desc ,"TABLE DATA" )== 0 && te -> nDeps > 0 )
1564+ {
1565+ DumpId tableId = te -> dependencies [0 ];
1566+
1567+ /*
1568+ * The TABLE item might not have been in the archive, if this was
1569+ * a data-only dump; but its dump ID should be less than its data
1570+ * item's dump ID, so there should be a place for it in the array.
1571+ */
1572+ if (tableId <=0 || tableId > maxDumpId )
1573+ exit_horribly (modulename ,"bad table dumpId for TABLE DATA item" );
1574+
1575+ AH -> tableDataId [tableId ]= te -> dumpId ;
1576+ }
15361577}
1578+ }
1579+
1580+ static TocEntry *
1581+ getTocEntryByDumpId (ArchiveHandle * AH ,DumpId id )
1582+ {
1583+ /* build index arrays if we didn't already */
1584+ if (AH -> tocsByDumpId == NULL )
1585+ buildTocEntryArrays (AH );
1586+
1587+ if (id > 0 && id <=AH -> maxDumpId )
1588+ return AH -> tocsByDumpId [id ];
1589+
15371590return NULL ;
15381591}
15391592
@@ -3978,9 +4031,8 @@ mark_work_done(ArchiveHandle *AH, TocEntry *ready_list,
39784031 * This function takes care of fixing up some missing or badly designed
39794032 * dependencies, and then prepares subsidiary data structures that will be
39804033 * used in the main parallel-restore logic, including:
3981- * 1. We build the tocsByDumpId[] index array.
3982- * 2. We build the revDeps[] arrays of incoming dependency dumpIds.
3983- * 3. We set up depCount fields that are the number of as-yet-unprocessed
4034+ * 1. We build the revDeps[] arrays of incoming dependency dumpIds.
4035+ * 2. We set up depCount fields that are the number of as-yet-unprocessed
39844036 * dependencies for each TOC entry.
39854037 *
39864038 * We also identify locking dependencies so that we can avoid trying to
@@ -3993,22 +4045,11 @@ fix_dependencies(ArchiveHandle *AH)
39934045int i ;
39944046
39954047/*
3996- * It is convenient to have an array that indexes the TOC entries by dump
3997- * ID, rather than searching the TOC list repeatedly. Entries for dump
3998- * IDs not present in the TOC will be NULL.
3999- *
4000- * NOTE: because maxDumpId is just the highest dump ID defined in the
4001- * archive, there might be dependencies for IDs > maxDumpId. All uses of
4002- * this array must guard against out-of-range dependency numbers.
4003- *
4004- * Also, initialize the depCount/revDeps/nRevDeps fields, and make sure
4005- * the TOC items are marked as not being in any parallel-processing list.
4048+ * Initialize the depCount/revDeps/nRevDeps fields, and make sure the TOC
4049+ * items are marked as not being in any parallel-processing list.
40064050 */
4007- maxDumpId = AH -> maxDumpId ;
4008- tocsByDumpId = (TocEntry * * )pg_calloc (maxDumpId ,sizeof (TocEntry * ));
40094051for (te = AH -> toc -> next ;te != AH -> toc ;te = te -> next )
40104052{
4011- tocsByDumpId [te -> dumpId - 1 ]= te ;
40124053te -> depCount = te -> nDeps ;
40134054te -> revDeps = NULL ;
40144055te -> nRevDeps = 0 ;
@@ -4019,34 +4060,9 @@ fix_dependencies(ArchiveHandle *AH)
40194060/*
40204061 * POST_DATA items that are shown as depending on a table need to be
40214062 * re-pointed to depend on that table's data, instead. This ensures they
4022- * won't get scheduled until the data has been loaded. We handle this by
4023- * first finding TABLE/TABLE DATA pairs and then scanning all the
4024- * dependencies.
4025- *
4026- * Note: currently, a TABLE DATA should always have exactly one
4027- * dependency, on its TABLE item. So we don't bother to search, but look
4028- * just at the first dependency. We do trouble to make sure that it's a
4029- * TABLE, if possible.However, if the dependency isn't in the archive
4030- * then just assume it was a TABLE; this is to cover cases where the table
4031- * was suppressed but we have the data and some dependent post-data items.
4032- *
4033- * XXX this is O(N^2) if there are a lot of tables. We ought to fix
4034- * pg_dump to produce correctly-linked dependencies in the first place.
4063+ * won't get scheduled until the data has been loaded.
40354064 */
4036- for (te = AH -> toc -> next ;te != AH -> toc ;te = te -> next )
4037- {
4038- if (strcmp (te -> desc ,"TABLE DATA" )== 0 && te -> nDeps > 0 )
4039- {
4040- DumpId tableId = te -> dependencies [0 ];
4041-
4042- if (tableId > maxDumpId ||
4043- tocsByDumpId [tableId - 1 ]== NULL ||
4044- strcmp (tocsByDumpId [tableId - 1 ]-> desc ,"TABLE" )== 0 )
4045- {
4046- repoint_table_dependencies (AH ,tableId ,te -> dumpId );
4047- }
4048- }
4049- }
4065+ repoint_table_dependencies (AH );
40504066
40514067/*
40524068 * Pre-8.4 versions of pg_dump neglected to set up a dependency from BLOB
@@ -4093,8 +4109,8 @@ fix_dependencies(ArchiveHandle *AH)
40934109{
40944110DumpId depid = te -> dependencies [i ];
40954111
4096- if (depid <=maxDumpId && tocsByDumpId [depid - 1 ]!= NULL )
4097- tocsByDumpId [depid - 1 ]-> nRevDeps ++ ;
4112+ if (depid <=AH -> maxDumpId && AH -> tocsByDumpId [depid ]!= NULL )
4113+ AH -> tocsByDumpId [depid ]-> nRevDeps ++ ;
40984114else
40994115te -> depCount -- ;
41004116}
@@ -4121,9 +4137,9 @@ fix_dependencies(ArchiveHandle *AH)
41214137{
41224138DumpId depid = te -> dependencies [i ];
41234139
4124- if (depid <=maxDumpId && tocsByDumpId [depid - 1 ]!= NULL )
4140+ if (depid <=AH -> maxDumpId && AH -> tocsByDumpId [depid ]!= NULL )
41254141{
4126- TocEntry * otherte = tocsByDumpId [depid - 1 ];
4142+ TocEntry * otherte = AH -> tocsByDumpId [depid ];
41274143
41284144otherte -> revDeps [otherte -> nRevDeps ++ ]= te -> dumpId ;
41294145}
@@ -4137,32 +4153,34 @@ fix_dependencies(ArchiveHandle *AH)
41374153{
41384154te -> lockDeps = NULL ;
41394155te -> nLockDeps = 0 ;
4140- identify_locking_dependencies (te );
4156+ identify_locking_dependencies (AH , te );
41414157}
41424158}
41434159
41444160/*
4145- * Change dependencies ontableId to depend ontableDataId instead,
4161+ * Change dependencies ontable items to depend ontable data items instead,
41464162 * but only in POST_DATA items.
41474163 */
41484164static void
4149- repoint_table_dependencies (ArchiveHandle * AH ,
4150- DumpId tableId ,DumpId tableDataId )
4165+ repoint_table_dependencies (ArchiveHandle * AH )
41514166{
41524167TocEntry * te ;
41534168int i ;
4169+ DumpId olddep ;
41544170
41554171for (te = AH -> toc -> next ;te != AH -> toc ;te = te -> next )
41564172{
41574173if (te -> section != SECTION_POST_DATA )
41584174continue ;
41594175for (i = 0 ;i < te -> nDeps ;i ++ )
41604176{
4161- if (te -> dependencies [i ]== tableId )
4177+ olddep = te -> dependencies [i ];
4178+ if (olddep <=AH -> maxDumpId &&
4179+ AH -> tableDataId [olddep ]!= 0 )
41624180{
4163- te -> dependencies [i ]= tableDataId ;
4181+ te -> dependencies [i ]= AH -> tableDataId [ olddep ] ;
41644182ahlog (AH ,2 ,"transferring dependency %d -> %d to %d\n" ,
4165- te -> dumpId ,tableId , tableDataId );
4183+ te -> dumpId ,olddep , AH -> tableDataId [ olddep ] );
41664184}
41674185}
41684186}
@@ -4174,7 +4192,7 @@ repoint_table_dependencies(ArchiveHandle *AH,
41744192 * itself). Record their dump IDs in the entry's lockDeps[] array.
41754193 */
41764194static void
4177- identify_locking_dependencies (TocEntry * te )
4195+ identify_locking_dependencies (ArchiveHandle * AH , TocEntry * te )
41784196{
41794197DumpId * lockids ;
41804198int nlockids ;
@@ -4205,8 +4223,8 @@ identify_locking_dependencies(TocEntry *te)
42054223{
42064224DumpId depid = te -> dependencies [i ];
42074225
4208- if (depid <=maxDumpId && tocsByDumpId [depid - 1 ] &&
4209- strcmp (tocsByDumpId [depid - 1 ]-> desc ,"TABLE DATA" )== 0 )
4226+ if (depid <=AH -> maxDumpId && AH -> tocsByDumpId [depid ] != NULL &&
4227+ strcmp (AH -> tocsByDumpId [depid ]-> desc ,"TABLE DATA" )== 0 )
42104228lockids [nlockids ++ ]= depid ;
42114229}
42124230
@@ -4234,7 +4252,7 @@ reduce_dependencies(ArchiveHandle *AH, TocEntry *te, TocEntry *ready_list)
42344252
42354253for (i = 0 ;i < te -> nRevDeps ;i ++ )
42364254{
4237- TocEntry * otherte = tocsByDumpId [te -> revDeps [i ]- 1 ];
4255+ TocEntry * otherte = AH -> tocsByDumpId [te -> revDeps [i ]];
42384256
42394257otherte -> depCount -- ;
42404258if (otherte -> depCount == 0 && otherte -> par_prev != NULL )
@@ -4254,18 +4272,11 @@ reduce_dependencies(ArchiveHandle *AH, TocEntry *te, TocEntry *ready_list)
42544272static void
42554273mark_create_done (ArchiveHandle * AH ,TocEntry * te )
42564274{
4257- TocEntry * tes ;
4258-
4259- for (tes = AH -> toc -> next ;tes != AH -> toc ;tes = tes -> next )
4275+ if (AH -> tableDataId [te -> dumpId ]!= 0 )
42604276{
4261- if (strcmp (tes -> desc ,"TABLE DATA" )== 0 &&
4262- strcmp (tes -> tag ,te -> tag )== 0 &&
4263- strcmp (tes -> namespace ?tes -> namespace :"" ,
4264- te -> namespace ?te -> namespace :"" )== 0 )
4265- {
4266- tes -> created = true;
4267- break ;
4268- }
4277+ TocEntry * ted = AH -> tocsByDumpId [AH -> tableDataId [te -> dumpId ]];
4278+
4279+ ted -> created = true;
42694280}
42704281}
42714282
@@ -4277,22 +4288,14 @@ static void
42774288inhibit_data_for_failed_table (ArchiveHandle * AH ,TocEntry * te )
42784289{
42794290RestoreOptions * ropt = AH -> ropt ;
4280- TocEntry * tes ;
42814291
42824292ahlog (AH ,1 ,"table \"%s\" could not be created, will not restore its data\n" ,
42834293te -> tag );
42844294
4285- for ( tes = AH -> toc -> next ; tes != AH -> toc ; tes = tes -> next )
4295+ if ( AH -> tableDataId [ te -> dumpId ] != 0 )
42864296{
4287- if (strcmp (tes -> desc ,"TABLE DATA" )== 0 &&
4288- strcmp (tes -> tag ,te -> tag )== 0 &&
4289- strcmp (tes -> namespace ?tes -> namespace :"" ,
4290- te -> namespace ?te -> namespace :"" )== 0 )
4291- {
4292- /* mark it unwanted; we assume idWanted array already exists */
4293- ropt -> idWanted [tes -> dumpId - 1 ]= false;
4294- break ;
4295- }
4297+ /* mark it unwanted; we assume idWanted array already exists */
4298+ ropt -> idWanted [AH -> tableDataId [te -> dumpId ]- 1 ]= false;
42964299}
42974300}
42984301