Skip to content

Commit 51c5881

Browse files
committed
Dump comments for large objects.
1 parent 4714984 commit 51c5881

File tree

3 files changed

+162
-35
lines changed

3 files changed

+162
-35
lines changed

src/bin/pg_dump/pg_dump.c

Lines changed: 139 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* by PostgreSQL
1313
*
1414
* IDENTIFICATION
15-
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.410 2005/06/21 20:45:44 tgl Exp $
15+
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.411 2005/06/30 03:02:56 tgl Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -163,7 +163,9 @@ static void selectSourceSchema(const char *schemaName);
163163
static char *getFormattedTypeName(Oid oid, OidOptions opts);
164164
static char *myFormatType(const char *typname, int32 typmod);
165165
static const char *fmtQualifiedId(const char *schema, const char *id);
166+
static bool hasBlobs(Archive *AH);
166167
static int dumpBlobs(Archive *AH, void *arg);
168+
static int dumpBlobComments(Archive *AH, void *arg);
167169
static void dumpDatabase(Archive *AH);
168170
static void dumpEncoding(Archive *AH);
169171
static const char *getAttrName(int attrnum, TableInfo *tblInfo);
@@ -344,6 +346,7 @@ main(int argc, char **argv)
344346

345347
case 's': /* dump schema only */
346348
schemaOnly = true;
349+
outputBlobs = false;
347350
break;
348351

349352
case 'S': /* Username for superuser in plain text
@@ -539,16 +542,22 @@ main(int argc, char **argv)
539542
if (!schemaOnly)
540543
getTableData(tblinfo, numTables, oids);
541544

542-
if (outputBlobs)
545+
if (outputBlobs && hasBlobs(g_fout))
543546
{
544-
/* This is just a placeholder to allow correct sorting of blobs */
547+
/* Add placeholders to allow correct sorting of blobs */
545548
DumpableObject *blobobj;
546549

547550
blobobj = (DumpableObject *) malloc(sizeof(DumpableObject));
548551
blobobj->objType = DO_BLOBS;
549552
blobobj->catId = nilCatalogId;
550553
AssignDumpId(blobobj);
551554
blobobj->name = strdup("BLOBS");
555+
556+
blobobj = (DumpableObject *) malloc(sizeof(DumpableObject));
557+
blobobj->objType = DO_BLOB_COMMENTS;
558+
blobobj->catId = nilCatalogId;
559+
AssignDumpId(blobobj);
560+
blobobj->name = strdup("BLOB COMMENTS");
552561
}
553562

554563
/*
@@ -1313,52 +1322,82 @@ dumpEncoding(Archive *AH)
13131322
}
13141323

13151324

1325+
/*
1326+
* hasBlobs:
1327+
* Test whether database contains any large objects
1328+
*/
1329+
static bool
1330+
hasBlobs(Archive *AH)
1331+
{
1332+
bool result;
1333+
const char *blobQry;
1334+
PGresult *res;
1335+
1336+
/* Make sure we are in proper schema */
1337+
selectSourceSchema("pg_catalog");
1338+
1339+
/* Check for BLOB OIDs */
1340+
if (AH->remoteVersion >= 70100)
1341+
blobQry = "SELECT loid FROM pg_largeobject LIMIT 1";
1342+
else
1343+
blobQry = "SELECT oid FROM pg_class WHERE relkind = 'l' LIMIT 1";
1344+
1345+
res = PQexec(g_conn, blobQry);
1346+
check_sql_result(res, g_conn, blobQry, PGRES_TUPLES_OK);
1347+
1348+
result = PQntuples(res) > 0;
1349+
1350+
PQclear(res);
1351+
1352+
return result;
1353+
}
1354+
13161355
/*
13171356
* dumpBlobs:
13181357
* dump all blobs
1319-
*
13201358
*/
13211359
static int
13221360
dumpBlobs(Archive *AH, void *arg)
13231361
{
1324-
PQExpBuffer oidQry = createPQExpBuffer();
1325-
PQExpBuffer oidFetchQry = createPQExpBuffer();
1362+
const char *blobQry;
1363+
const char *blobFetchQry;
13261364
PGresult *res;
1327-
int i;
1328-
int loFd;
13291365
char buf[LOBBUFSIZE];
1366+
int i;
13301367
int cnt;
1331-
Oid blobOid;
13321368

13331369
if (g_verbose)
13341370
write_msg(NULL, "saving large objects\n");
13351371

13361372
/* Make sure we are in proper schema */
13371373
selectSourceSchema("pg_catalog");
13381374

1339-
/* Cursor to get all BLOB tables */
1375+
/* Cursor to get all BLOB OIDs */
13401376
if (AH->remoteVersion >= 70100)
1341-
appendPQExpBuffer(oidQry, "DECLARE bloboid CURSOR FOR SELECT DISTINCT loid FROM pg_largeobject");
1377+
blobQry = "DECLARE bloboid CURSOR FOR SELECT DISTINCT loid FROM pg_largeobject";
13421378
else
1343-
appendPQExpBuffer(oidQry, "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_class WHERE relkind = 'l'");
1379+
blobQry = "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_class WHERE relkind = 'l'";
13441380

1345-
res = PQexec(g_conn, oidQry->data);
1346-
check_sql_result(res, g_conn, oidQry->data, PGRES_COMMAND_OK);
1381+
res = PQexec(g_conn, blobQry);
1382+
check_sql_result(res, g_conn, blobQry, PGRES_COMMAND_OK);
13471383

1348-
/* Fetch for cursor */
1349-
appendPQExpBuffer(oidFetchQry, "FETCH 1000 IN bloboid");
1384+
/* Command to fetch from cursor */
1385+
blobFetchQry = "FETCH 1000 IN bloboid";
13501386

13511387
do
13521388
{
13531389
PQclear(res);
13541390

13551391
/* Do a fetch */
1356-
res = PQexec(g_conn, oidFetchQry->data);
1357-
check_sql_result(res, g_conn, oidFetchQry->data, PGRES_TUPLES_OK);
1392+
res = PQexec(g_conn, blobFetchQry);
1393+
check_sql_result(res, g_conn, blobFetchQry, PGRES_TUPLES_OK);
13581394

13591395
/* Process the tuples, if any */
13601396
for (i = 0; i < PQntuples(res); i++)
13611397
{
1398+
Oid blobOid;
1399+
int loFd;
1400+
13621401
blobOid = atooid(PQgetvalue(res, i, 0));
13631402
/* Open the BLOB */
13641403
loFd = lo_open(g_conn, blobOid, INV_READ);
@@ -1393,8 +1432,81 @@ dumpBlobs(Archive *AH, void *arg)
13931432

13941433
PQclear(res);
13951434

1396-
destroyPQExpBuffer(oidQry);
1397-
destroyPQExpBuffer(oidFetchQry);
1435+
return 1;
1436+
}
1437+
1438+
/*
1439+
* dumpBlobComments
1440+
* dump all blob comments
1441+
*
1442+
* Since we don't provide any way to be selective about dumping blobs,
1443+
* there's no need to be selective about their comments either. We put
1444+
* all the comments into one big TOC entry.
1445+
*/
1446+
static int
1447+
dumpBlobComments(Archive *AH, void *arg)
1448+
{
1449+
const char *blobQry;
1450+
const char *blobFetchQry;
1451+
PQExpBuffer commentcmd = createPQExpBuffer();
1452+
PGresult *res;
1453+
int i;
1454+
1455+
if (g_verbose)
1456+
write_msg(NULL, "saving large object comments\n");
1457+
1458+
/* Make sure we are in proper schema */
1459+
selectSourceSchema("pg_catalog");
1460+
1461+
/* Cursor to get all BLOB comments */
1462+
if (AH->remoteVersion >= 70200)
1463+
blobQry = "DECLARE blobcmt CURSOR FOR SELECT DISTINCT loid, obj_description(loid, 'pg_largeobject') FROM pg_largeobject";
1464+
else if (AH->remoteVersion >= 70100)
1465+
blobQry = "DECLARE blobcmt CURSOR FOR SELECT DISTINCT loid, obj_description(loid) FROM pg_largeobject";
1466+
else
1467+
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'";
1468+
1469+
res = PQexec(g_conn, blobQry);
1470+
check_sql_result(res, g_conn, blobQry, PGRES_COMMAND_OK);
1471+
1472+
/* Command to fetch from cursor */
1473+
blobFetchQry = "FETCH 100 IN blobcmt";
1474+
1475+
do
1476+
{
1477+
PQclear(res);
1478+
1479+
/* Do a fetch */
1480+
res = PQexec(g_conn, blobFetchQry);
1481+
check_sql_result(res, g_conn, blobFetchQry, PGRES_TUPLES_OK);
1482+
1483+
/* Process the tuples, if any */
1484+
for (i = 0; i < PQntuples(res); i++)
1485+
{
1486+
Oid blobOid;
1487+
char *comment;
1488+
1489+
/* ignore blobs without comments */
1490+
if (PQgetisnull(res, i, 1))
1491+
continue;
1492+
1493+
blobOid = atooid(PQgetvalue(res, i, 0));
1494+
comment = PQgetvalue(res, i, 1);
1495+
1496+
printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ",
1497+
blobOid);
1498+
appendStringLiteral(commentcmd, comment, false);
1499+
appendPQExpBuffer(commentcmd, ";\n");
1500+
1501+
archputs(commentcmd->data, AH);
1502+
}
1503+
} while (PQntuples(res) > 0);
1504+
1505+
PQclear(res);
1506+
1507+
archputs("\n", AH);
1508+
1509+
destroyPQExpBuffer(commentcmd);
13981510

13991511
return 1;
14001512
}
@@ -4356,6 +4468,13 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
43564468
NULL, 0,
43574469
dumpBlobs, NULL);
43584470
break;
4471+
case DO_BLOB_COMMENTS:
4472+
ArchiveEntry(fout, dobj->catId, dobj->dumpId,
4473+
dobj->name, NULL, NULL, "",
4474+
false, "BLOB COMMENTS", "", "", NULL,
4475+
NULL, 0,
4476+
dumpBlobComments, NULL);
4477+
break;
43594478
}
43604479
}
43614480

src/bin/pg_dump/pg_dump.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.115 2004/12/31 22:03:08 pgsql Exp $
9+
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.116 2005/06/30 03:03:02 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -78,7 +78,8 @@ typedef enum
7878
DO_CAST,
7979
DO_TABLE_DATA,
8080
DO_TABLE_TYPE,
81-
DO_BLOBS
81+
DO_BLOBS,
82+
DO_BLOB_COMMENTS
8283
} DumpableObjectType;
8384

8485
typedef struct _dumpableObject

src/bin/pg_dump/pg_dump_sort.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump_sort.c,v 1.9 2005/02/03 23:38:58 tgl Exp $
12+
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump_sort.c,v 1.10 2005/06/30 03:03:04 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -36,16 +36,17 @@ static const int oldObjectTypePriority[] =
3636
5, /* DO_CONVERSION */
3737
6, /* DO_TABLE */
3838
8, /* DO_ATTRDEF */
39-
12, /* DO_INDEX */
40-
13, /* DO_RULE */
41-
14, /* DO_TRIGGER */
42-
11, /* DO_CONSTRAINT */
43-
15, /* DO_FK_CONSTRAINT */
39+
13, /* DO_INDEX */
40+
14, /* DO_RULE */
41+
15, /* DO_TRIGGER */
42+
12, /* DO_CONSTRAINT */
43+
16, /* DO_FK_CONSTRAINT */
4444
2, /* DO_PROCLANG */
4545
2, /* DO_CAST */
4646
9, /* DO_TABLE_DATA */
4747
7, /* DO_TABLE_TYPE */
48-
10 /* DO_BLOBS */
48+
10, /* DO_BLOBS */
49+
11 /* DO_BLOB_COMMENTS */
4950
};
5051

5152
/*
@@ -63,16 +64,17 @@ static const int newObjectTypePriority[] =
6364
9, /* DO_CONVERSION */
6465
10, /* DO_TABLE */
6566
12, /* DO_ATTRDEF */
66-
16, /* DO_INDEX */
67-
17, /* DO_RULE */
68-
18, /* DO_TRIGGER */
69-
15, /* DO_CONSTRAINT */
70-
19, /* DO_FK_CONSTRAINT */
67+
17, /* DO_INDEX */
68+
18, /* DO_RULE */
69+
19, /* DO_TRIGGER */
70+
16, /* DO_CONSTRAINT */
71+
20, /* DO_FK_CONSTRAINT */
7172
2, /* DO_PROCLANG */
7273
8, /* DO_CAST */
7374
13, /* DO_TABLE_DATA */
7475
11, /* DO_TABLE_TYPE */
75-
14 /* DO_BLOBS */
76+
14, /* DO_BLOBS */
77+
15 /* DO_BLOB_COMMENTS */
7678
};
7779

7880

@@ -1072,6 +1074,11 @@ describeDumpableObject(DumpableObject *obj, char *buf, int bufsize)
10721074
"BLOBS (ID %d)",
10731075
obj->dumpId);
10741076
return;
1077+
case DO_BLOB_COMMENTS:
1078+
snprintf(buf, bufsize,
1079+
"BLOB COMMENTS (ID %d)",
1080+
obj->dumpId);
1081+
return;
10751082
}
10761083
/* shouldn't get here */
10771084
snprintf(buf, bufsize,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy