aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pg_dump/pg_backup_null.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-06-21 20:45:44 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-06-21 20:45:44 +0000
commit7a28de20523bb695e8ec819514df82a18a7656b3 (patch)
tree4427292f4323028cfbcb501c8dcb716caa2a8ddc /src/bin/pg_dump/pg_backup_null.c
parentb49d871f6ac58ff63a3147575494fb8fe9c6a5eb (diff)
downloadpostgresql-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.c115
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;
}
}