1 /*-------------------------------------------------------------------------
2 *
3 * pg_backup_null.c
4 *
5 * Implementation of an archive that is never saved; it is used by
6 * pg_dump to output a plain text SQL script instead of saving
7 * a real archive.
8 *
9 * See the headers to pg_restore for more details.
10 *
11 * Copyright (c) 2000, Philip Warner
12 * Rights are granted to use this software in any way so long
13 * as this notice is not removed.
14 *
15 * The author is not responsible for loss or damages that may
16 * result from its use.
17 *
18 *
19 * IDENTIFICATION
20 * src/bin/pg_dump/pg_backup_null.c
21 *
22 *-------------------------------------------------------------------------
23 */
24 #include "postgres_fe.h"
25
26 #include "fe_utils/string_utils.h"
27 #include "libpq/libpq-fs.h"
28 #include "pg_backup_archiver.h"
29 #include "pg_backup_utils.h"
30
31 static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen);
32 static void _WriteBlobData(ArchiveHandle *AH, const void *data, size_t dLen);
33 static void _EndData(ArchiveHandle *AH, TocEntry *te);
34 static int _WriteByte(ArchiveHandle *AH, const int i);
35 static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
36 static void _CloseArchive(ArchiveHandle *AH);
37 static void _PrintTocData(ArchiveHandle *AH, TocEntry *te);
38 static void _StartBlobs(ArchiveHandle *AH, TocEntry *te);
39 static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
40 static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
41 static void _EndBlobs(ArchiveHandle *AH, TocEntry *te);
42
43
44 /*
45 * Initializer
46 */
47 void
InitArchiveFmt_Null(ArchiveHandle * AH)48 InitArchiveFmt_Null(ArchiveHandle *AH)
49 {
50 /* Assuming static functions, this can be copied for each format. */
51 AH->WriteDataPtr = _WriteData;
52 AH->EndDataPtr = _EndData;
53 AH->WriteBytePtr = _WriteByte;
54 AH->WriteBufPtr = _WriteBuf;
55 AH->ClosePtr = _CloseArchive;
56 AH->ReopenPtr = NULL;
57 AH->PrintTocDataPtr = _PrintTocData;
58
59 AH->StartBlobsPtr = _StartBlobs;
60 AH->StartBlobPtr = _StartBlob;
61 AH->EndBlobPtr = _EndBlob;
62 AH->EndBlobsPtr = _EndBlobs;
63 AH->ClonePtr = NULL;
64 AH->DeClonePtr = NULL;
65
66 /* Initialize LO buffering */
67 AH->lo_buf_size = LOBBUFSIZE;
68 AH->lo_buf = (void *) pg_malloc(LOBBUFSIZE);
69
70 /*
71 * Now prevent reading...
72 */
73 if (AH->mode == archModeRead)
74 fatal("this format cannot be read");
75 }
76
77 /*
78 * - Start a new TOC entry
79 */
80
81 /*
82 * Called by dumper via archiver from within a data dump routine
83 */
84 static void
_WriteData(ArchiveHandle * AH,const void * data,size_t dLen)85 _WriteData(ArchiveHandle *AH, const void *data, size_t dLen)
86 {
87 /* Just send it to output, ahwrite() already errors on failure */
88 ahwrite(data, 1, dLen, AH);
89 }
90
91 /*
92 * Called by dumper via archiver from within a data dump routine
93 * We substitute this for _WriteData while emitting a BLOB
94 */
95 static void
_WriteBlobData(ArchiveHandle * AH,const void * data,size_t dLen)96 _WriteBlobData(ArchiveHandle *AH, const void *data, size_t dLen)
97 {
98 if (dLen > 0)
99 {
100 PQExpBuffer buf = createPQExpBuffer();
101
102 appendByteaLiteralAHX(buf,
103 (const unsigned char *) data,
104 dLen,
105 AH);
106
107 ahprintf(AH, "SELECT pg_catalog.lowrite(0, %s);\n", buf->data);
108
109 destroyPQExpBuffer(buf);
110 }
111 }
112
113 static void
_EndData(ArchiveHandle * AH,TocEntry * te)114 _EndData(ArchiveHandle *AH, TocEntry *te)
115 {
116 ahprintf(AH, "\n\n");
117 }
118
119 /*
120 * Called by the archiver when starting to save all BLOB DATA (not schema).
121 * This routine should save whatever format-specific information is needed
122 * to read the BLOBs back into memory.
123 *
124 * It is called just prior to the dumper's DataDumper routine.
125 *
126 * Optional, but strongly recommended.
127 */
128 static void
_StartBlobs(ArchiveHandle * AH,TocEntry * te)129 _StartBlobs(ArchiveHandle *AH, TocEntry *te)
130 {
131 ahprintf(AH, "BEGIN;\n\n");
132 }
133
134 /*
135 * Called by the archiver when the dumper calls StartBlob.
136 *
137 * Mandatory.
138 *
139 * Must save the passed OID for retrieval at restore-time.
140 */
141 static void
_StartBlob(ArchiveHandle * AH,TocEntry * te,Oid oid)142 _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
143 {
144 bool old_blob_style = (AH->version < K_VERS_1_12);
145
146 if (oid == 0)
147 fatal("invalid OID for large object");
148
149 /* With an old archive we must do drop and create logic here */
150 if (old_blob_style && AH->public.ropt->dropSchema)
151 DropBlobIfExists(AH, oid);
152
153 if (old_blob_style)
154 ahprintf(AH, "SELECT pg_catalog.lo_open(pg_catalog.lo_create('%u'), %d);\n",
155 oid, INV_WRITE);
156 else
157 ahprintf(AH, "SELECT pg_catalog.lo_open('%u', %d);\n",
158 oid, INV_WRITE);
159
160 AH->WriteDataPtr = _WriteBlobData;
161 }
162
163 /*
164 * Called by the archiver when the dumper calls EndBlob.
165 *
166 * Optional.
167 */
168 static void
_EndBlob(ArchiveHandle * AH,TocEntry * te,Oid oid)169 _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
170 {
171 AH->WriteDataPtr = _WriteData;
172
173 ahprintf(AH, "SELECT pg_catalog.lo_close(0);\n\n");
174 }
175
176 /*
177 * Called by the archiver when finishing saving all BLOB DATA.
178 *
179 * Optional.
180 */
181 static void
_EndBlobs(ArchiveHandle * AH,TocEntry * te)182 _EndBlobs(ArchiveHandle *AH, TocEntry *te)
183 {
184 ahprintf(AH, "COMMIT;\n\n");
185 }
186
187 /*------
188 * Called as part of a RestoreArchive call; for the NULL archive, this
189 * just sends the data for a given TOC entry to the output.
190 *------
191 */
192 static void
_PrintTocData(ArchiveHandle * AH,TocEntry * te)193 _PrintTocData(ArchiveHandle *AH, TocEntry *te)
194 {
195 if (te->dataDumper)
196 {
197 AH->currToc = te;
198
199 if (strcmp(te->desc, "BLOBS") == 0)
200 _StartBlobs(AH, te);
201
202 te->dataDumper((Archive *) AH, te->dataDumperArg);
203
204 if (strcmp(te->desc, "BLOBS") == 0)
205 _EndBlobs(AH, te);
206
207 AH->currToc = NULL;
208 }
209 }
210
211 static int
_WriteByte(ArchiveHandle * AH,const int i)212 _WriteByte(ArchiveHandle *AH, const int i)
213 {
214 /* Don't do anything */
215 return 0;
216 }
217
218 static void
_WriteBuf(ArchiveHandle * AH,const void * buf,size_t len)219 _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
220 {
221 /* Don't do anything */
222 }
223
224 static void
_CloseArchive(ArchiveHandle * AH)225 _CloseArchive(ArchiveHandle *AH)
226 {
227 /* Nothing to do */
228 }
229