diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-06-21 20:45:44 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-06-21 20:45:44 +0000 |
commit | 7a28de20523bb695e8ec819514df82a18a7656b3 (patch) | |
tree | 4427292f4323028cfbcb501c8dcb716caa2a8ddc /src/bin/pg_dump/pg_backup_null.c | |
parent | b49d871f6ac58ff63a3147575494fb8fe9c6a5eb (diff) | |
download | postgresql-7a28de20523bb695e8ec819514df82a18a7656b3.tar.gz postgresql-7a28de20523bb695e8ec819514df82a18a7656b3.zip |
pg_dump can now dump large objects even in plain-text output mode, by
using the recently added lo_create() function. The restore logic in
pg_restore is greatly simplified as well, since there's no need anymore
to try to adjust database references to match a new set of blob OIDs.
Diffstat (limited to 'src/bin/pg_dump/pg_backup_null.c')
-rw-r--r-- | src/bin/pg_dump/pg_backup_null.c | 115 |
1 files changed, 110 insertions, 5 deletions
diff --git a/src/bin/pg_dump/pg_backup_null.c b/src/bin/pg_dump/pg_backup_null.c index 82bc5d121fa..7e0b6ffe117 100644 --- a/src/bin/pg_dump/pg_backup_null.c +++ b/src/bin/pg_dump/pg_backup_null.c @@ -3,7 +3,7 @@ * pg_backup_null.c * * Implementation of an archive that is never saved; it is used by - * pg_dump to output a plain text SQL script instead of save + * pg_dump to output a plain text SQL script instead of saving * a real archive. * * See the headers to pg_restore for more details. @@ -17,7 +17,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_null.c,v 1.14 2003/12/08 16:39:05 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_null.c,v 1.15 2005/06/21 20:45:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,12 +27,21 @@ #include <unistd.h> /* for dup */ +#include "libpq/libpq-fs.h" + + static size_t _WriteData(ArchiveHandle *AH, const void *data, size_t dLen); +static size_t _WriteBlobData(ArchiveHandle *AH, const void *data, size_t dLen); static void _EndData(ArchiveHandle *AH, TocEntry *te); static int _WriteByte(ArchiveHandle *AH, const int i); static size_t _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len); static void _CloseArchive(ArchiveHandle *AH); static void _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt); +static void _StartBlobs(ArchiveHandle *AH, TocEntry *te); +static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid); +static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid); +static void _EndBlobs(ArchiveHandle *AH, TocEntry *te); + /* * Initializer @@ -48,6 +57,17 @@ InitArchiveFmt_Null(ArchiveHandle *AH) AH->ClosePtr = _CloseArchive; AH->PrintTocDataPtr = _PrintTocData; + AH->StartBlobsPtr = _StartBlobs; + AH->StartBlobPtr = _StartBlob; + AH->EndBlobPtr = _EndBlob; + AH->EndBlobsPtr = _EndBlobs; + + /* Initialize LO buffering */ + AH->lo_buf_size = LOBBUFSIZE; + AH->lo_buf = (void *) malloc(LOBBUFSIZE); + if (AH->lo_buf == NULL) + die_horribly(AH, NULL, "out of memory\n"); + /* * Now prevent reading... */ @@ -59,10 +79,8 @@ InitArchiveFmt_Null(ArchiveHandle *AH) * - Start a new TOC entry */ -/*------ +/* * Called by dumper via archiver from within a data dump routine - * As at V1.3, this is only called for COPY FROM dfata, and BLOB data - *------ */ static size_t _WriteData(ArchiveHandle *AH, const void *data, size_t dLen) @@ -72,12 +90,91 @@ _WriteData(ArchiveHandle *AH, const void *data, size_t dLen) return dLen; } +/* + * Called by dumper via archiver from within a data dump routine + * We substitute this for _WriteData while emitting a BLOB + */ +static size_t +_WriteBlobData(ArchiveHandle *AH, const void *data, size_t dLen) +{ + if (dLen > 0) + { + unsigned char *str; + size_t len; + + str = PQescapeBytea((const unsigned char *) data, dLen, &len); + if (!str) + die_horribly(AH, NULL, "out of memory\n"); + + ahprintf(AH, "SELECT lowrite(0, '%s');\n", str); + + free(str); + } + return dLen; +} + static void _EndData(ArchiveHandle *AH, TocEntry *te) { ahprintf(AH, "\n\n"); } +/* + * Called by the archiver when starting to save all BLOB DATA (not schema). + * This routine should save whatever format-specific information is needed + * to read the BLOBs back into memory. + * + * It is called just prior to the dumper's DataDumper routine. + * + * Optional, but strongly recommended. + */ +static void +_StartBlobs(ArchiveHandle *AH, TocEntry *te) +{ + ahprintf(AH, "BEGIN;\n\n"); +} + +/* + * Called by the archiver when the dumper calls StartBlob. + * + * Mandatory. + * + * Must save the passed OID for retrieval at restore-time. + */ +static void +_StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid) +{ + if (oid == 0) + die_horribly(AH, NULL, "invalid OID for large object\n"); + + ahprintf(AH, "SELECT lo_open(lo_create(%u), %d);\n", oid, INV_WRITE); + + AH->WriteDataPtr = _WriteBlobData; +} + +/* + * Called by the archiver when the dumper calls EndBlob. + * + * Optional. + */ +static void +_EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid) +{ + AH->WriteDataPtr = _WriteData; + ahprintf(AH, "SELECT lo_close(0);\n\n"); +} + +/* + * Called by the archiver when finishing saving all BLOB DATA. + * + * Optional. + */ +static void +_EndBlobs(ArchiveHandle *AH, TocEntry *te) +{ + ahprintf(AH, "COMMIT;\n\n"); +} + /*------ * Called as part of a RestoreArchive call; for the NULL archive, this * just sends the data for a given TOC entry to the output. @@ -89,7 +186,15 @@ _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt) if (te->dataDumper) { AH->currToc = te; + + if (strcmp(te->desc, "BLOBS") == 0) + _StartBlobs(AH, te); + (*te->dataDumper) ((Archive *) AH, te->dataDumperArg); + + if (strcmp(te->desc, "BLOBS") == 0) + _EndBlobs(AH, te); + AH->currToc = NULL; } } |