*
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.216 2001/07/29 22:12:23 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.217 2001/08/03 19:43:05 tgl Exp $
  *
  *
    /* only checks for 'opts == CONV_ALL' anyway. */
 } formatLiteralOptions;
 
-static void dumpComment(Archive *outfile, const char *target, const char *oid);
+static void dumpComment(Archive *outfile, const char *target, const char *oid,
+                       const char *((*deps)[]));
 static void dumpSequence(Archive *fout, TableInfo tbinfo, const bool schemaOnly, const bool dataOnly);
 static void dumpACL(Archive *fout, TableInfo tbinfo);
 static void dumpTriggers(Archive *fout, const char *tablename,
        archprintf(fout, ");\n");
    }
    PQclear(res);
+   destroyPQExpBuffer(q);
    return 1;
 }
 
 
    PQclear(res);
 
+   destroyPQExpBuffer(dbQry);
+   destroyPQExpBuffer(delQry);
+   destroyPQExpBuffer(creaQry);
+
    return 1;
 }
 
        }
    } while (PQntuples(res) > 0);
 
+   destroyPQExpBuffer(oidQry);
+   destroyPQExpBuffer(oidFetchQry);
+
    return 1;
 }
 
    int         i_typdelim;
    int         i_typdefault;
    int         i_typrelid;
+   int         i_typalign;
+   int         i_typstorage;
    int         i_typbyval;
+   int         i_typisdefined;
    int         i_usename;
    int         i_typedefn;
 
    /*
     * we include even the built-in types because those may be used as
     * array elements by user-defined types
-    */
-
-   /*
+    *
     * we filter out the built-in types when we dump out the types
     */
 
    {
        appendPQExpBuffer(query, "SELECT pg_type.oid, typowner, typname, typlen, typprtlen, "
                        "typinput, typoutput, typreceive, typsend, typelem, typdelim, "
-                       "typdefault, typrelid, typbyval, "
+                       "typdefault, typrelid, typalign, 'p'::char as typstorage, typbyval, typisdefined, "
                        "(select usename from pg_user where typowner = usesysid) as usename, "
                        "typname as typedefn "
                        "from pg_type");
    } else {
        appendPQExpBuffer(query, "SELECT pg_type.oid, typowner, typname, typlen, typprtlen, "
                        "typinput, typoutput, typreceive, typsend, typelem, typdelim, "
-                       "typdefault, typrelid, typbyval, "
+                       "typdefault, typrelid, typalign, typstorage, typbyval, typisdefined, "
                        "(select usename from pg_user where typowner = usesysid) as usename, "
                        "format_type(pg_type.oid, NULL) as typedefn "
                        "from pg_type");
    i_typdelim = PQfnumber(res, "typdelim");
    i_typdefault = PQfnumber(res, "typdefault");
    i_typrelid = PQfnumber(res, "typrelid");
+   i_typalign = PQfnumber(res, "typalign");
+   i_typstorage = PQfnumber(res, "typstorage");
    i_typbyval = PQfnumber(res, "typbyval");
+   i_typisdefined = PQfnumber(res, "typisdefined");
    i_usename = PQfnumber(res, "usename");
    i_typedefn = PQfnumber(res, "typedefn");
 
        tinfo[i].typdelim = strdup(PQgetvalue(res, i, i_typdelim));
        tinfo[i].typdefault = strdup(PQgetvalue(res, i, i_typdefault));
        tinfo[i].typrelid = strdup(PQgetvalue(res, i, i_typrelid));
+       tinfo[i].typalign = strdup(PQgetvalue(res, i, i_typalign));
+       tinfo[i].typstorage = strdup(PQgetvalue(res, i, i_typstorage));
        tinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
        tinfo[i].typedefn = strdup(PQgetvalue(res, i, i_typedefn));
 
            tinfo[i].isArray = 1;
        else
            tinfo[i].isArray = 0;
+
+       if (strcmp(PQgetvalue(res, i, i_typisdefined), "f") == 0)
+           tinfo[i].isDefined = 0;
+       else
+           tinfo[i].isDefined = 1;
    }
 
    *numTypes = ntups;
 
    PQclear(res);
 
+   destroyPQExpBuffer(query);
+
    return tinfo;
 }
 
 
    PQclear(res);
 
+   destroyPQExpBuffer(query);
+
    return oprinfo;
 }
 
            free(tp[i].typdefault);
        if (tp[i].typrelid)
            free(tp[i].typrelid);
+       if (tp[i].typalign)
+           free(tp[i].typalign);
+       if (tp[i].typstorage)
+           free(tp[i].typstorage);
        if (tp[i].usename)
            free(tp[i].usename);
+       if (tp[i].typedefn)
+           free(tp[i].typedefn);
    }
    free(tp);
 }
 
    PQclear(res);
 
+   destroyPQExpBuffer(query);
+
    return agginfo;
 }
 
 
    PQclear(res);
 
-   return finfo;
+   destroyPQExpBuffer(query);
 
+   return finfo;
 }
 
 /*
 
    PQclear(res);
 
-   return tblinfo;
+   destroyPQExpBuffer(query);
+   destroyPQExpBuffer(delqry);
 
+   return tblinfo;
 }
 
 /*
    }
 
    PQclear(res);
+
+   destroyPQExpBuffer(query);
+
    return inhinfo;
 }
 
 
    for (i = 0; i < numTables; i++)
    {
-
        if (tblinfo[i].sequence)
            continue;
 
        }
        PQclear(res);
    }
+
+   destroyPQExpBuffer(q);
 }
 
 
        indinfo[i].indhaspred = strdup(PQgetvalue(res, i, i_indhaspred));
    }
    PQclear(res);
+
+   destroyPQExpBuffer(query);
+
    return indinfo;
 }
 
  * oid handed to this routine. The routine takes a constant character
  * string for the target part of the object and the oid of the object
  * whose comments are to be dumped. It is perfectly acceptable
- * to hand an oid to this routine which has not been commented. In
- * addition, the routine takes the stdio FILE handle to which the
- * output should be written.
+ * to hand an oid to this routine which has not been commented.  Additional
+ * dependencies can be passed for the comment, too --- this is needed for
+ * VIEWs, whose comments are filed under the table OID but which are dumped
+ * in order by their rule OID.
  *------------------------------------------------------------------
 */
 
 static void
-dumpComment(Archive *fout, const char *target, const char *oid)
+dumpComment(Archive *fout, const char *target, const char *oid,
+           const char *((*deps)[]))
 {
-
    PGresult   *res;
    PQExpBuffer query;
    int         i_description;
        formatStringLiteral(query, PQgetvalue(res, 0, i_description), PASS_LFTAB);
        appendPQExpBuffer(query, ";\n");
 
-       ArchiveEntry(fout, oid, target, "COMMENT", NULL, query->data, "" /* Del */ ,
+       ArchiveEntry(fout, oid, target, "COMMENT", deps,
+                    query->data, "" /* Del */ ,
                     "" /* Copy */ , "" /* Owner */ , NULL, NULL);
 
    }
    /*** Clear the statement buffer and return ***/
 
    PQclear(res);
-
+   destroyPQExpBuffer(query);
 }
 
 /*------------------------------------------------------------------
 void
 dumpDBComment(Archive *fout)
 {
-
    PGresult   *res;
    PQExpBuffer query;
    int         i_oid;
        i_oid = PQfnumber(res, "oid");
        resetPQExpBuffer(query);
        appendPQExpBuffer(query, "DATABASE %s", fmtId(PQdb(g_conn), force_quotes));
-       dumpComment(fout, query->data, PQgetvalue(res, 0, i_oid));
+       dumpComment(fout, query->data, PQgetvalue(res, 0, i_oid), NULL);
    }
 
    /*** Clear the statement buffer and return ***/
 
    PQclear(res);
-
+   destroyPQExpBuffer(query);
 }
 
 /*
    PQExpBuffer delq = createPQExpBuffer();
    int         funcInd;
    const char *((*deps)[]);
-   int         depIdx = 0;
-
-   deps = malloc(sizeof(char*) * 10);
+   int         depIdx;
 
    for (i = 0; i < numTypes; i++)
    {
-
        /* skip all the builtin types */
        if (atooid(tinfo[i].oid) <= g_last_builtin_oid)
            continue;
        if (atoi(tinfo[i].typrelid) != 0)
            continue;
 
+       /* skip undefined placeholder types */
+       if (!tinfo[i].isDefined)
+           continue;
+
        /* skip all array types that start w/ underscore */
        if ((tinfo[i].typname[0] == '_') &&
            (strcmp(tinfo[i].typinput, "array_in") == 0))
            continue;
 
+       deps = malloc(sizeof(char*) * 10);
+       depIdx = 0;
+
        /*
         * before we create a type, we need to create the input and output
         * functions for it, if they haven't been created already
            dumpOneFunc(fout, finfo, funcInd, tinfo, numTypes);
        }
 
+       resetPQExpBuffer(delq);
        appendPQExpBuffer(delq, "DROP TYPE %s;\n", fmtId(tinfo[i].typname, force_quotes));
 
        resetPQExpBuffer(q);
            {
                write_msg(NULL, "notice: array type %s - type for elements (oid %s) is not dumped\n",
                          tinfo[i].typname, tinfo[i].typelem);
-               resetPQExpBuffer(q);
-               resetPQExpBuffer(delq);
                continue;
            }
 
 
            (*deps)[depIdx++] = strdup(tinfo[i].typelem);
        }
+
+       /* XXX these are all the aligns currently handled by DefineType */
+       if (strcmp(tinfo[i].typalign, "i") == 0)
+           appendPQExpBuffer(q, ", alignment = int4");
+       else if (strcmp(tinfo[i].typalign, "d") == 0)
+           appendPQExpBuffer(q, ", alignment = double");
+
+       if (strcmp(tinfo[i].typstorage, "p") == 0)
+           appendPQExpBuffer(q, ", storage = plain");
+       if (strcmp(tinfo[i].typstorage, "e") == 0)
+           appendPQExpBuffer(q, ", storage = external");
+       if (strcmp(tinfo[i].typstorage, "x") == 0)
+           appendPQExpBuffer(q, ", storage = extended");
+       if (strcmp(tinfo[i].typstorage, "m") == 0)
+           appendPQExpBuffer(q, ", storage = main");
+
        if (tinfo[i].passedbyvalue)
-           appendPQExpBuffer(q, ",passedbyvalue);\n");
+           appendPQExpBuffer(q, ", passedbyvalue);\n");
        else
            appendPQExpBuffer(q, ");\n");
 
        /*** Dump Type Comments ***/
 
        resetPQExpBuffer(q);
-       resetPQExpBuffer(delq);
 
        appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo[i].typname, force_quotes));
-       dumpComment(fout, q->data, tinfo[i].oid);
-
-       resetPQExpBuffer(q);
+       dumpComment(fout, q->data, tinfo[i].oid, NULL);
    }
+
+   destroyPQExpBuffer(q);
+   destroyPQExpBuffer(delq);
 }
 
 /*
 
    PQclear(res);
 
+   destroyPQExpBuffer(query);
+   destroyPQExpBuffer(defqry);
+   destroyPQExpBuffer(delqry);
 }
 
 /*
    PQExpBuffer fn = createPQExpBuffer();
    PQExpBuffer delqry = createPQExpBuffer();
    PQExpBuffer fnlist = createPQExpBuffer();
-   int         j;
    PQExpBuffer asPart = createPQExpBuffer();
    char        func_lang[NAMEDATALEN + 1];
    PGresult   *res;
    int         nlangs;
+   int         j;
    int         i_lanname;
    char        query[256];
 
    char       *rettypename;
 
    if (finfo[i].dumped)
-       return;
-   else
-       finfo[i].dumped = 1;
+       goto done;
+
+   finfo[i].dumped = 1;
 
    /* becomeUser(fout, finfo[i].usename); */
 
 
            write_msg(NULL, "reason: data type name of argument %d (oid %s) not found\n",
                       j, finfo[i].argtypes[j]);
-           resetPQExpBuffer(q);
-           resetPQExpBuffer(fn);
-           resetPQExpBuffer(delqry);
-           resetPQExpBuffer(fnlist);
-           resetPQExpBuffer(asPart);
-           return;
+           goto done;
        }
 
        appendPQExpBuffer(fn, "%s%s",
 
        write_msg(NULL, "reason: name of return data type (oid %s) not found\n",
                  finfo[i].prorettype);
-       resetPQExpBuffer(q);
-       resetPQExpBuffer(fn);
-       resetPQExpBuffer(delqry);
-       resetPQExpBuffer(fnlist);
-       resetPQExpBuffer(asPart);
-       return;
+       goto done;
    }
 
    resetPQExpBuffer(q);
    appendPQExpBuffer(q, "FUNCTION %s ",
                      fmtId(finfo[i].proname, force_quotes));
    appendPQExpBuffer(q, "( %s )", fnlist->data);
-   dumpComment(fout, q->data, finfo[i].oid);
-
+   dumpComment(fout, q->data, finfo[i].oid, NULL);
+
+done:
+   destroyPQExpBuffer(q);
+   destroyPQExpBuffer(fn);
+   destroyPQExpBuffer(delqry);
+   destroyPQExpBuffer(fnlist);
+   destroyPQExpBuffer(asPart);
 }
 
 /*
        ArchiveEntry(fout, oprinfo[i].oid, oprinfo[i].oprname, "OPERATOR", NULL,
                q->data, delq->data, "", oprinfo[i].usename, NULL, NULL);
    }
+
+   destroyPQExpBuffer(q);
+   destroyPQExpBuffer(delq);
+   destroyPQExpBuffer(leftarg);
+   destroyPQExpBuffer(rightarg);
+   destroyPQExpBuffer(commutator);
+   destroyPQExpBuffer(negator);
+   destroyPQExpBuffer(restrictor);
+   destroyPQExpBuffer(join);
+   destroyPQExpBuffer(sort1);
+   destroyPQExpBuffer(sort2);
 }
 
 /*
        resetPQExpBuffer(q);
        appendPQExpBuffer(q, "AGGREGATE %s %s", agginfo[i].aggname,
                          findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype, zeroAsOpaque + useBaseTypeName));
-       dumpComment(fout, q->data, agginfo[i].oid);
-
+       dumpComment(fout, q->data, agginfo[i].oid, NULL);
    }
+
+   destroyPQExpBuffer(q);
+   destroyPQExpBuffer(delq);
+   destroyPQExpBuffer(aggSig);
+   destroyPQExpBuffer(details);
 }
 
 /*
    int         actual_atts;    /* number of attrs in this CREATE statment */
    char       *reltypename;
    char       *objoid;
+   const char *((*commentDeps)[]);
 
    /* First - dump SEQUENCEs */
    if (tablename && strlen(tablename) > 0)
                objoid = tblinfo[i].viewoid;
                appendPQExpBuffer(delq, "DROP VIEW %s;\n", fmtId(tblinfo[i].relname, force_quotes));
                appendPQExpBuffer(q, "CREATE VIEW %s as %s\n", fmtId(tblinfo[i].relname, force_quotes), tblinfo[i].viewdef);
-
+               commentDeps = malloc(sizeof(char*) * 2);
+               (*commentDeps)[0] = strdup(objoid);
+               (*commentDeps)[1] = NULL; /* end of list */
            }
            else
            {
                reltypename = "TABLE";
                objoid = tblinfo[i].oid;
+               commentDeps = NULL;
                parentRels = tblinfo[i].parentRels;
                numParents = tblinfo[i].numParents;
 
                appendPQExpBuffer(q, "COLUMN %s", fmtId(tblinfo[i].relname, force_quotes));
                appendPQExpBuffer(q, ".");
                appendPQExpBuffer(q, "%s", fmtId(tblinfo[i].attnames[j], force_quotes));
-               dumpComment(fout, q->data, tblinfo[i].attoids[j]);
+               dumpComment(fout, q->data, tblinfo[i].attoids[j], NULL);
            }
 
            /* Dump Table Comments */
 
            resetPQExpBuffer(q);
            appendPQExpBuffer(q, "%s %s", reltypename, fmtId(tblinfo[i].relname, force_quotes));
-           dumpComment(fout, q->data, tblinfo[i].oid);
+           dumpComment(fout, q->data, tblinfo[i].oid, commentDeps);
 
        }
    }
+
+   destroyPQExpBuffer(q);
+   destroyPQExpBuffer(delq);
 }
 
 static PQExpBuffer
                k;
    int         tableInd;
    PQExpBuffer attlist = createPQExpBuffer();
+   PQExpBuffer q = createPQExpBuffer();
+   PQExpBuffer delq = createPQExpBuffer();
+   PQExpBuffer id1 = createPQExpBuffer();
+   PQExpBuffer id2 = createPQExpBuffer();
    char       *classname[INDEX_MAX_KEYS];
    char       *funcname;       /* the name of the function to comput the
                                 * index key from */
    int         indclass;
    int         nclass;
-
-   PQExpBuffer q = createPQExpBuffer(),
-               delq = createPQExpBuffer(),
-               id1 = createPQExpBuffer(),
-               id2 = createPQExpBuffer();
    PGresult   *res;
 
    for (i = 0; i < numIndexes; i++)
            /* Dump Index Comments */
            resetPQExpBuffer(q);
            appendPQExpBuffer(q, "INDEX %s", id1->data);
-           dumpComment(fout, q->data, indinfo[i].indexreloid);
+           dumpComment(fout, q->data, indinfo[i].indexreloid, NULL);
 
        }
    }
 
+   destroyPQExpBuffer(attlist);
+   destroyPQExpBuffer(q);
+   destroyPQExpBuffer(delq);
+   destroyPQExpBuffer(id1);
+   destroyPQExpBuffer(id2);
 }
 
 /*
    }
    last_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "datlastsysoid")));
    PQclear(res);
+   destroyPQExpBuffer(query);
    return last_oid;
 }
 
        exit_nicely();
    }
 
-
    last = atoi(PQgetvalue(res, 0, 1));
    incby = atoi(PQgetvalue(res, 0, 2));
    maxv = atoi(PQgetvalue(res, 0, 3));
 
        resetPQExpBuffer(query);
        appendPQExpBuffer(query, "SEQUENCE %s", fmtId(tbinfo.relname, force_quotes));
-       dumpComment(fout, query->data, tbinfo.oid);
+       dumpComment(fout, query->data, tbinfo.oid, NULL);
    }
+
+   destroyPQExpBuffer(query);
+   destroyPQExpBuffer(delqry);
 }
 
 
            ArchiveEntry(fout, tblinfo[i].triggers[j].oid, tblinfo[i].triggers[j].tgname,
                   "TRIGGER", NULL, tblinfo[i].triggers[j].tgsrc, "", "",
                         tblinfo[i].usename, NULL, NULL);
-           dumpComment(fout, tblinfo[i].triggers[j].tgcomment, tblinfo[i].triggers[j].oid);
+           dumpComment(fout, tblinfo[i].triggers[j].tgcomment, tblinfo[i].triggers[j].oid, NULL);
        }
    }
 }
 
            resetPQExpBuffer(query);
            appendPQExpBuffer(query, "RULE %s", fmtId(PQgetvalue(res, i, i_rulename), force_quotes));
-           dumpComment(fout, query->data, PQgetvalue(res, i, i_oid));
+           dumpComment(fout, query->data, PQgetvalue(res, i, i_oid), NULL);
 
        }
 
        PQclear(res);
    }
+
+   destroyPQExpBuffer(query);
 }