void DropBlobIfExists(ArchiveHandle *AH, Oid oid) { /* * If we are not restoring to a direct database connection, we have to * guess about how to detect whether the blob exists. Assume new-style. */ if (AH->connection == NULL || PQserverVersion(AH->connection) >= 90000) { ahprintf(AH, "SELECT pg_catalog.lo_unlink(oid) " "FROM pg_catalog.pg_largeobject_metadata " "WHERE oid = '%u';\n", oid); } else { /* Restoring to pre-9.0 server, so do it the old way */ ahprintf(AH, "SELECT CASE WHEN EXISTS(" "SELECT 1 FROM pg_catalog.pg_largeobject WHERE loid = '%u'" ") THEN pg_catalog.lo_unlink('%u') END;\n", oid, oid); } }
static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te) { lclTocEntry *ctx = (lclTocEntry *) te->formatData; ahprintf(AH, "-- File: %s\n", ctx->filename); }
/* * 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 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 StartBlob. * * Mandatory. * * Must save the passed OID for retrieval at restore-time. */ static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid) { bool old_blob_style = (AH->version < K_VERS_1_12); if (oid == 0) die_horribly(AH, NULL, "invalid OID for large object\n"); /* With an old archive we must do drop and create logic here */ if (old_blob_style && AH->ropt->dropSchema) DropBlobIfExists(AH, oid); if (old_blob_style) ahprintf(AH, "SELECT pg_catalog.lo_open(pg_catalog.lo_create('%u'), %d);\n", oid, INV_WRITE); else ahprintf(AH, "SELECT pg_catalog.lo_open('%u', %d);\n", oid, INV_WRITE); AH->WriteDataPtr = _WriteBlobData; }
/* * 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) { PQExpBuffer buf = createPQExpBuffer(); appendByteaLiteralAHX(buf, (const unsigned char *) data, dLen, AH); ahprintf(AH, "SELECT pg_catalog.lowrite(0, %s);\n", buf->data); destroyPQExpBuffer(buf); } return dLen; }
static void _EndData(ArchiveHandle *AH, TocEntry *te) { ahprintf(AH, "\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 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"); }