Dump comments for large objects.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 30 Jun 2005 03:03:04 +0000 (03:03 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 30 Jun 2005 03:03:04 +0000 (03:03 +0000)
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.h
src/bin/pg_dump/pg_dump_sort.c

index fa290040c4eb8f0bee0907026fa398954b15400f..d40b01a266d7077a661fd55396f2658dd3ec479c 100644 (file)
@@ -12,7 +12,7 @@
  *     by PostgreSQL
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.410 2005/06/21 20:45:44 tgl Exp $
+ *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.411 2005/06/30 03:02:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -163,7 +163,9 @@ static void selectSourceSchema(const char *schemaName);
 static char *getFormattedTypeName(Oid oid, OidOptions opts);
 static char *myFormatType(const char *typname, int32 typmod);
 static const char *fmtQualifiedId(const char *schema, const char *id);
+static bool hasBlobs(Archive *AH);
 static int     dumpBlobs(Archive *AH, void *arg);
+static int     dumpBlobComments(Archive *AH, void *arg);
 static void dumpDatabase(Archive *AH);
 static void dumpEncoding(Archive *AH);
 static const char *getAttrName(int attrnum, TableInfo *tblInfo);
@@ -344,6 +346,7 @@ main(int argc, char **argv)
 
                        case 's':                       /* dump schema only */
                                schemaOnly = true;
+                               outputBlobs = false;
                                break;
 
                        case 'S':                       /* Username for superuser in plain text
@@ -539,9 +542,9 @@ main(int argc, char **argv)
        if (!schemaOnly)
                getTableData(tblinfo, numTables, oids);
 
-       if (outputBlobs)
+       if (outputBlobs && hasBlobs(g_fout))
        {
-               /* This is just a placeholder to allow correct sorting of blobs */
+               /* Add placeholders to allow correct sorting of blobs */
                DumpableObject *blobobj;
 
                blobobj = (DumpableObject *) malloc(sizeof(DumpableObject));
@@ -549,6 +552,12 @@ main(int argc, char **argv)
                blobobj->catId = nilCatalogId;
                AssignDumpId(blobobj);
                blobobj->name = strdup("BLOBS");
+
+               blobobj = (DumpableObject *) malloc(sizeof(DumpableObject));
+               blobobj->objType = DO_BLOB_COMMENTS;
+               blobobj->catId = nilCatalogId;
+               AssignDumpId(blobobj);
+               blobobj->name = strdup("BLOB COMMENTS");
        }
 
        /*
@@ -1313,22 +1322,49 @@ dumpEncoding(Archive *AH)
 }
 
 
+/*
+ * hasBlobs:
+ *     Test whether database contains any large objects
+ */
+static bool
+hasBlobs(Archive *AH)
+{
+       bool            result;
+       const char *blobQry;
+       PGresult   *res;
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       /* Check for BLOB OIDs */
+       if (AH->remoteVersion >= 70100)
+               blobQry = "SELECT loid FROM pg_largeobject LIMIT 1";
+       else
+               blobQry = "SELECT oid FROM pg_class WHERE relkind = 'l' LIMIT 1";
+
+       res = PQexec(g_conn, blobQry);
+       check_sql_result(res, g_conn, blobQry, PGRES_TUPLES_OK);
+
+       result = PQntuples(res) > 0;
+
+       PQclear(res);
+
+       return result;
+}
+
 /*
  * dumpBlobs:
  *     dump all blobs
- *
  */
 static int
 dumpBlobs(Archive *AH, void *arg)
 {
-       PQExpBuffer oidQry = createPQExpBuffer();
-       PQExpBuffer oidFetchQry = createPQExpBuffer();
+       const char *blobQry;
+       const char *blobFetchQry;
        PGresult   *res;
-       int                     i;
-       int                     loFd;
        char            buf[LOBBUFSIZE];
+       int                     i;
        int                     cnt;
-       Oid                     blobOid;
 
        if (g_verbose)
                write_msg(NULL, "saving large objects\n");
@@ -1336,29 +1372,32 @@ dumpBlobs(Archive *AH, void *arg)
        /* Make sure we are in proper schema */
        selectSourceSchema("pg_catalog");
 
-       /* Cursor to get all BLOB tables */
+       /* Cursor to get all BLOB OIDs */
        if (AH->remoteVersion >= 70100)
-               appendPQExpBuffer(oidQry, "DECLARE bloboid CURSOR FOR SELECT DISTINCT loid FROM pg_largeobject");
+               blobQry = "DECLARE bloboid CURSOR FOR SELECT DISTINCT loid FROM pg_largeobject";
        else
-               appendPQExpBuffer(oidQry, "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_class WHERE relkind = 'l'");
+               blobQry = "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_class WHERE relkind = 'l'";
 
-       res = PQexec(g_conn, oidQry->data);
-       check_sql_result(res, g_conn, oidQry->data, PGRES_COMMAND_OK);
+       res = PQexec(g_conn, blobQry);
+       check_sql_result(res, g_conn, blobQry, PGRES_COMMAND_OK);
 
-       /* Fetch for cursor */
-       appendPQExpBuffer(oidFetchQry, "FETCH 1000 IN bloboid");
+       /* Command to fetch from cursor */
+       blobFetchQry = "FETCH 1000 IN bloboid";
 
        do
        {
                PQclear(res);
 
                /* Do a fetch */
-               res = PQexec(g_conn, oidFetchQry->data);
-               check_sql_result(res, g_conn, oidFetchQry->data, PGRES_TUPLES_OK);
+               res = PQexec(g_conn, blobFetchQry);
+               check_sql_result(res, g_conn, blobFetchQry, PGRES_TUPLES_OK);
 
                /* Process the tuples, if any */
                for (i = 0; i < PQntuples(res); i++)
                {
+                       Oid                     blobOid;
+                       int                     loFd;
+
                        blobOid = atooid(PQgetvalue(res, i, 0));
                        /* Open the BLOB */
                        loFd = lo_open(g_conn, blobOid, INV_READ);
@@ -1393,8 +1432,81 @@ dumpBlobs(Archive *AH, void *arg)
 
        PQclear(res);
 
-       destroyPQExpBuffer(oidQry);
-       destroyPQExpBuffer(oidFetchQry);
+       return 1;
+}
+
+/*
+ * dumpBlobComments
+ *     dump all blob comments
+ *
+ * Since we don't provide any way to be selective about dumping blobs,
+ * there's no need to be selective about their comments either.  We put
+ * all the comments into one big TOC entry.
+ */
+static int
+dumpBlobComments(Archive *AH, void *arg)
+{
+       const char *blobQry;
+       const char *blobFetchQry;
+       PQExpBuffer commentcmd = createPQExpBuffer();
+       PGresult   *res;
+       int                     i;
+
+       if (g_verbose)
+               write_msg(NULL, "saving large object comments\n");
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       /* Cursor to get all BLOB comments */
+       if (AH->remoteVersion >= 70200)
+               blobQry = "DECLARE blobcmt CURSOR FOR SELECT DISTINCT loid, obj_description(loid, 'pg_largeobject') FROM pg_largeobject";
+       else if (AH->remoteVersion >= 70100)
+               blobQry = "DECLARE blobcmt CURSOR FOR SELECT DISTINCT loid, obj_description(loid) FROM pg_largeobject";
+       else
+               blobQry = "DECLARE blobcmt CURSOR FOR SELECT oid, (SELECT description FROM pg_description pd WHERE pd.objoid=pc.oid) FROM pg_class pc WHERE relkind = 'l'";
+
+       res = PQexec(g_conn, blobQry);
+       check_sql_result(res, g_conn, blobQry, PGRES_COMMAND_OK);
+
+       /* Command to fetch from cursor */
+       blobFetchQry = "FETCH 100 IN blobcmt";
+
+       do
+       {
+               PQclear(res);
+
+               /* Do a fetch */
+               res = PQexec(g_conn, blobFetchQry);
+               check_sql_result(res, g_conn, blobFetchQry, PGRES_TUPLES_OK);
+
+               /* Process the tuples, if any */
+               for (i = 0; i < PQntuples(res); i++)
+               {
+                       Oid             blobOid;
+                       char    *comment;
+
+                       /* ignore blobs without comments */
+                       if (PQgetisnull(res, i, 1))
+                               continue;
+
+                       blobOid = atooid(PQgetvalue(res, i, 0));
+                       comment = PQgetvalue(res, i, 1);
+
+                       printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ",
+                                                         blobOid);
+                       appendStringLiteral(commentcmd, comment, false);
+                       appendPQExpBuffer(commentcmd, ";\n");
+
+                       archputs(commentcmd->data, AH);
+               }
+       } while (PQntuples(res) > 0);
+
+       PQclear(res);
+
+       archputs("\n", AH);
+
+       destroyPQExpBuffer(commentcmd);
 
        return 1;
 }
@@ -4356,6 +4468,13 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
                                                 NULL, 0,
                                                 dumpBlobs, NULL);
                        break;
+               case DO_BLOB_COMMENTS:
+                       ArchiveEntry(fout, dobj->catId, dobj->dumpId,
+                                                dobj->name, NULL, NULL, "",
+                                                false, "BLOB COMMENTS", "", "", NULL,
+                                                NULL, 0,
+                                                dumpBlobComments, NULL);
+                       break;
        }
 }
 
index 77709f22ba9a53839b3a2c8d937ee5ca955b9c9e..7b0c51aa4ff57387d3dc52455126bc69bfa6b55d 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.115 2004/12/31 22:03:08 pgsql Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.116 2005/06/30 03:03:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -78,7 +78,8 @@ typedef enum
        DO_CAST,
        DO_TABLE_DATA,
        DO_TABLE_TYPE,
-       DO_BLOBS
+       DO_BLOBS,
+       DO_BLOB_COMMENTS
 } DumpableObjectType;
 
 typedef struct _dumpableObject
index 3d40a0044ef1ecc09eb2912d294abd183892ed23..b3029988a44d68d2c818092b6c2c61ef09a85881 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump_sort.c,v 1.9 2005/02/03 23:38:58 tgl Exp $
+ *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump_sort.c,v 1.10 2005/06/30 03:03:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,16 +36,17 @@ static const int oldObjectTypePriority[] =
        5,                                                      /* DO_CONVERSION */
        6,                                                      /* DO_TABLE */
        8,                                                      /* DO_ATTRDEF */
-       12,                                                     /* DO_INDEX */
-       13,                                                     /* DO_RULE */
-       14,                                                     /* DO_TRIGGER */
-       11,                                                     /* DO_CONSTRAINT */
-       15,                                                     /* DO_FK_CONSTRAINT */
+       13,                                                     /* DO_INDEX */
+       14,                                                     /* DO_RULE */
+       15,                                                     /* DO_TRIGGER */
+       12,                                                     /* DO_CONSTRAINT */
+       16,                                                     /* DO_FK_CONSTRAINT */
        2,                                                      /* DO_PROCLANG */
        2,                                                      /* DO_CAST */
        9,                                                      /* DO_TABLE_DATA */
        7,                                                      /* DO_TABLE_TYPE */
-       10                                                      /* DO_BLOBS */
+       10,                                                     /* DO_BLOBS */
+       11                                                      /* DO_BLOB_COMMENTS */
 };
 
 /*
@@ -63,16 +64,17 @@ static const int newObjectTypePriority[] =
        9,                                                      /* DO_CONVERSION */
        10,                                                     /* DO_TABLE */
        12,                                                     /* DO_ATTRDEF */
-       16,                                                     /* DO_INDEX */
-       17,                                                     /* DO_RULE */
-       18,                                                     /* DO_TRIGGER */
-       15,                                                     /* DO_CONSTRAINT */
-       19,                                                     /* DO_FK_CONSTRAINT */
+       17,                                                     /* DO_INDEX */
+       18,                                                     /* DO_RULE */
+       19,                                                     /* DO_TRIGGER */
+       16,                                                     /* DO_CONSTRAINT */
+       20,                                                     /* DO_FK_CONSTRAINT */
        2,                                                      /* DO_PROCLANG */
        8,                                                      /* DO_CAST */
        13,                                                     /* DO_TABLE_DATA */
        11,                                                     /* DO_TABLE_TYPE */
-       14                                                      /* DO_BLOBS */
+       14,                                                     /* DO_BLOBS */
+       15                                                      /* DO_BLOB_COMMENTS */
 };
 
 
@@ -1072,6 +1074,11 @@ describeDumpableObject(DumpableObject *obj, char *buf, int bufsize)
                                         "BLOBS  (ID %d)",
                                         obj->dumpId);
                        return;
+               case DO_BLOB_COMMENTS:
+                       snprintf(buf, bufsize,
+                                        "BLOB COMMENTS  (ID %d)",
+                                        obj->dumpId);
+                       return;
        }
        /* shouldn't get here */
        snprintf(buf, bufsize,