1515 *
1616 *
1717 * IDENTIFICATION
18- *$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.22 2001/03/22 04:00:11 momjian Exp $
18+ *$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.23 2001/04/01 05:42:50 pjw Exp $
1919 *
2020 * Modifications - 28-Jun-2000 - pjw@rhyme.com.au
2121 *
4141 * Modifications - 6-Mar-2001 - pjw@rhyme.com.au
4242 * - Only disable triggers in DataOnly (or implied data-only) restores.
4343 *
44+ * Modifications - 31-Mar-2001 - pjw@rhyme.com.au
45+ *
46+ * - Rudimentary support for dependencies in archives. Current implementation
47+ *uses dependencies to modify the OID used in sorting TOC entries.
48+ *This will NOT handle multi-level dependencies, but will manage simple
49+ *relationships like UDTs & their functions.
50+ *
51+ * - Treat OIDs with more respect (avoid using ints, use macros for
52+ *conversion & comparison).
53+ *
4454 *-------------------------------------------------------------------------
4555 */
4656
@@ -75,6 +85,8 @@ static TocEntry *_getTocEntry(ArchiveHandle *AH, int id);
7585static void _moveAfter (ArchiveHandle * AH ,TocEntry * pos ,TocEntry * te );
7686static void _moveBefore (ArchiveHandle * AH ,TocEntry * pos ,TocEntry * te );
7787static int _discoverArchiveFormat (ArchiveHandle * AH );
88+ static void _fixupOidInfo (TocEntry * te );
89+ static Oid _findMaxOID (const char * ((* deps )[]));
7890
7991static char * progname = "Archiver" ;
8092
@@ -557,7 +569,7 @@ WriteData(Archive *AHX, const void *data, int dLen)
557569/* Public */
558570void
559571ArchiveEntry (Archive * AHX ,const char * oid ,const char * name ,
560- const char * desc ,const char * (deps []),const char * defn ,
572+ const char * desc ,const char * (( * deps ) []),const char * defn ,
561573const char * dropStmt ,const char * copyStmt ,const char * owner ,
562574DataDumperPtr dumpFn ,void * dumpArg )
563575{
@@ -577,10 +589,15 @@ ArchiveEntry(Archive *AHX, const char *oid, const char *name,
577589AH -> toc -> prev = newToc ;
578590
579591newToc -> id = AH -> lastID ;
580- newToc -> oid = strdup (oid );
581- newToc -> oidVal = atoi (oid );
592+
582593newToc -> name = strdup (name );
583594newToc -> desc = strdup (desc );
595+
596+ newToc -> oid = strdup (oid );
597+ newToc -> depOid = deps ;
598+ _fixupOidInfo (newToc );
599+
600+
584601newToc -> defn = strdup (defn );
585602newToc -> dropStmt = strdup (dropStmt );
586603newToc -> copyStmt = copyStmt ?strdup (copyStmt ) :NULL ;
@@ -654,7 +671,7 @@ PrintTOCSummary(Archive *AHX, RestoreOptions *ropt)
654671
655672/* Called by a dumper to signal start of a BLOB */
656673int
657- StartBlob (Archive * AHX ,int oid )
674+ StartBlob (Archive * AHX ,Oid oid )
658675{
659676ArchiveHandle * AH = (ArchiveHandle * )AHX ;
660677
@@ -668,7 +685,7 @@ StartBlob(Archive *AHX, int oid)
668685
669686/* Called by a dumper to signal end of a BLOB */
670687int
671- EndBlob (Archive * AHX ,int oid )
688+ EndBlob (Archive * AHX ,Oid oid )
672689{
673690ArchiveHandle * AH = (ArchiveHandle * )AHX ;
674691
@@ -714,7 +731,7 @@ EndRestoreBlobs(ArchiveHandle *AH)
714731 * Called by a format handler to initiate restoration of a blob
715732 */
716733void
717- StartRestoreBlob (ArchiveHandle * AH ,int oid )
734+ StartRestoreBlob (ArchiveHandle * AH ,Oid oid )
718735{
719736int loOid ;
720737
@@ -756,7 +773,7 @@ StartRestoreBlob(ArchiveHandle *AH, int oid)
756773}
757774
758775void
759- EndRestoreBlob (ArchiveHandle * AH ,int oid )
776+ EndRestoreBlob (ArchiveHandle * AH ,Oid oid )
760777{
761778lo_close (AH -> connection ,AH -> loFd );
762779AH -> writingBlob = 0 ;
@@ -1331,7 +1348,7 @@ ReadInt(ArchiveHandle *AH)
13311348}
13321349
13331350int
1334- WriteStr (ArchiveHandle * AH ,char * c )
1351+ WriteStr (ArchiveHandle * AH ,const char * c )
13351352{
13361353int res ;
13371354
@@ -1630,6 +1647,8 @@ void
16301647WriteToc (ArchiveHandle * AH )
16311648{
16321649TocEntry * te = AH -> toc -> next ;
1650+ const char * dep ;
1651+ int i ;
16331652
16341653/* printf("%d TOC Entries to save\n", AH->tocCount); */
16351654
@@ -1639,12 +1658,25 @@ WriteToc(ArchiveHandle *AH)
16391658WriteInt (AH ,te -> id );
16401659WriteInt (AH ,te -> dataDumper ?1 :0 );
16411660WriteStr (AH ,te -> oid );
1661+
16421662WriteStr (AH ,te -> name );
16431663WriteStr (AH ,te -> desc );
16441664WriteStr (AH ,te -> defn );
16451665WriteStr (AH ,te -> dropStmt );
16461666WriteStr (AH ,te -> copyStmt );
16471667WriteStr (AH ,te -> owner );
1668+
1669+ /* Dump list of dependencies */
1670+ if (te -> depOid != NULL )
1671+ {
1672+ i = 0 ;
1673+ while ( (dep = (* te -> depOid )[i ++ ])!= NULL )
1674+ {
1675+ WriteStr (AH ,dep );
1676+ }
1677+ }
1678+ WriteStr (AH ,NULL );/* Terminate List */
1679+
16481680if (AH -> WriteExtraTocPtr )
16491681(* AH -> WriteExtraTocPtr ) (AH ,te );
16501682te = te -> next ;
@@ -1655,6 +1687,9 @@ void
16551687ReadToc (ArchiveHandle * AH )
16561688{
16571689int i ;
1690+ char * ((* deps )[]);
1691+ int depIdx ;
1692+ int depSize ;
16581693
16591694TocEntry * te = AH -> toc -> next ;
16601695
@@ -1672,7 +1707,8 @@ ReadToc(ArchiveHandle *AH)
16721707
16731708te -> hadDumper = ReadInt (AH );
16741709te -> oid = ReadStr (AH );
1675- te -> oidVal = atoi (te -> oid );
1710+ te -> oidVal = atooid (te -> oid );
1711+
16761712te -> name = ReadStr (AH );
16771713te -> desc = ReadStr (AH );
16781714te -> defn = ReadStr (AH );
@@ -1683,6 +1719,40 @@ ReadToc(ArchiveHandle *AH)
16831719
16841720te -> owner = ReadStr (AH );
16851721
1722+ /* Read TOC entry dependencies */
1723+ if (AH -> version >=K_VERS_1_5 )
1724+ {
1725+ depSize = 100 ;
1726+ deps = malloc (sizeof (char * )* depSize );
1727+ depIdx = 0 ;
1728+ do
1729+ {
1730+ if (depIdx > depSize )
1731+ {
1732+ depSize *=2 ;
1733+ deps = realloc (deps ,sizeof (char * )* depSize );
1734+ }
1735+ (* deps )[depIdx ]= ReadStr (AH );
1736+ /*
1737+ * if ((*deps)[depIdx])
1738+ * fprintf(stderr, "Read Dependency for %s -> %s\n", te->name, (*deps)[depIdx]);
1739+ */
1740+ }while ( (* deps )[depIdx ++ ]!= NULL );
1741+
1742+ if (depIdx > 1 )/* We have a non-null entry */
1743+ {
1744+ /* Trim it */
1745+ te -> depOid = realloc (deps ,sizeof (char * )* depIdx );
1746+ }else {/* No deps */
1747+ te -> depOid = NULL ;
1748+ }
1749+ }else {
1750+ te -> depOid = NULL ;
1751+ }
1752+
1753+ /* Set maxOidVal etc for use in sorting */
1754+ _fixupOidInfo (te );
1755+
16861756if (AH -> ReadExtraTocPtr )
16871757(* AH -> ReadExtraTocPtr ) (AH ,te );
16881758
@@ -1984,17 +2054,50 @@ _tocSortCompareByOIDNum(const void *p1, const void *p2)
19842054{
19852055TocEntry * te1 = * (TocEntry * * )p1 ;
19862056TocEntry * te2 = * (TocEntry * * )p2 ;
1987- int id1 = te1 -> oidVal ;
1988- int id2 = te2 -> oidVal ;
2057+ Oid id1 = te1 -> maxOidVal ;
2058+ Oid id2 = te2 -> maxOidVal ;
2059+ int cmpval ;
19892060
19902061/* printf("Comparing %d to %d\n", id1, id2); */
19912062
1992- if (id1 < id2 )
1993- return -1 ;
1994- else if (id1 > id2 )
1995- return 1 ;
1996- else
1997- return _tocSortCompareByIDNum (te1 ,te2 );
2063+ cmpval = oidcmp (id1 ,id2 );
2064+
2065+ /* If we have a deterministic answer, return it. */
2066+ if (cmpval != 0 )
2067+ return cmpval ;
2068+
2069+ /* More comparisons required */
2070+ if (oideq (id1 ,te1 -> maxDepOidVal ) )/* maxOid1 came from deps */
2071+ {
2072+ if (oideq (id2 ,te2 -> maxDepOidVal ) )/* maxOid2 also came from deps */
2073+ {
2074+ cmpval = oidcmp (te1 -> oidVal ,te2 -> oidVal );/* Just compare base OIDs */
2075+ }
2076+ else /* MaxOid2 was entry OID */
2077+ {
2078+ return 1 ;/* entry1 > entry2 */
2079+ };
2080+ }
2081+ else /* must have oideq(id1, te1->oidVal) => maxOid1 = Oid1 */
2082+ {
2083+ if (oideq (id2 ,te2 -> maxDepOidVal ) )/* maxOid2 came from deps */
2084+ {
2085+ return -1 ;/* entry1 < entry2 */
2086+ }
2087+ else /* MaxOid2 was entry OID - deps don't matter */
2088+ {
2089+ cmpval = 0 ;
2090+ };
2091+ };
2092+
2093+ /* If we get here, then we've done another comparison
2094+ * Once again, a 0 result means we require even more
2095+ */
2096+ if (cmpval != 0 )
2097+ return cmpval ;
2098+
2099+ /* Entire OID details match, so use ID number (ie. original pg_dump order) */
2100+ return _tocSortCompareByIDNum (te1 ,te2 );
19982101}
19992102
20002103static int
@@ -2015,6 +2118,48 @@ _tocSortCompareByIDNum(const void *p1, const void *p2)
20152118return 0 ;
20162119}
20172120
2121+ /*
2122+ * Assuming Oid and depOid are set, work out the various
2123+ * Oid values used in sorting.
2124+ */
2125+ static void
2126+ _fixupOidInfo (TocEntry * te )
2127+ {
2128+ te -> oidVal = atooid (te -> oid );
2129+ te -> maxDepOidVal = _findMaxOID (te -> depOid );
2130+
2131+ /* For the purpose of sorting, find the max OID. */
2132+ if (oidcmp (te -> oidVal ,te -> maxDepOidVal ) >=0 )
2133+ te -> maxOidVal = te -> oidVal ;
2134+ else
2135+ te -> maxOidVal = te -> maxDepOidVal ;
2136+ }
2137+
2138+ /*
2139+ * Find the max OID value for a given list of string Oid values
2140+ */
2141+ static Oid
2142+ _findMaxOID (const char * ((* deps )[]))
2143+ {
2144+ const char * dep ;
2145+ int i ;
2146+ Oid maxOid = (Oid )0 ;
2147+ Oid currOid ;
2148+
2149+ if (!deps )
2150+ return maxOid ;
2151+
2152+ i = 0 ;
2153+ while ( (dep = (* deps )[i ++ ])!= NULL )
2154+ {
2155+ currOid = atooid (dep );
2156+ if (oidcmp (maxOid ,currOid )< 0 )
2157+ maxOid = currOid ;
2158+ }
2159+
2160+ return maxOid ;
2161+ }
2162+
20182163/*
20192164 * Maybe I can use this somewhere...
20202165 *