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