]> granicus.if.org Git - postgresql/blob - src/bin/psql/large_obj.c
pgindent run. Make it all clean.
[postgresql] / src / bin / psql / large_obj.c
1 /*
2  * psql - the PostgreSQL interactive terminal
3  *
4  * Copyright 2000 by PostgreSQL Global Development Group
5  *
6  * $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.14 2001/03/22 04:00:20 momjian Exp $
7  */
8 #include "postgres_fe.h"
9 #include "large_obj.h"
10
11 #include "libpq-fe.h"
12
13 #include "settings.h"
14 #include "variables.h"
15 #include "common.h"
16 #include "print.h"
17
18
19 /*
20  * Since all large object ops must be in a transaction, we must do some magic
21  * here. You can set the variable lo_transaction to one of commit|rollback|
22  * nothing to get your favourite behaviour regarding any transaction in
23  * progress. Rollback is default.
24  */
25
26 static char notice[80];
27
28 static void
29 _my_notice_handler(void *arg, const char *message)
30 {
31         (void) arg;
32         strncpy(notice, message, 79);
33         notice[79] = '\0';
34 }
35
36
37 static bool
38 handle_transaction(void)
39 {
40         const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
41         PGresult   *res;
42         bool            commit;
43         PQnoticeProcessor old_notice_hook;
44
45         if (var && strcmp(var, "nothing") == 0)
46                 return true;
47
48         commit = (var && strcmp(var, "commit") == 0);
49
50         notice[0] = '\0';
51         old_notice_hook = PQsetNoticeProcessor(pset.db, _my_notice_handler, NULL);
52
53         res = PSQLexec(commit ? "COMMIT" : "ROLLBACK");
54         if (!res)
55                 return false;
56
57         if (notice[0])
58         {
59                 if ((!commit && strcmp(notice, "NOTICE:  ROLLBACK: no transaction in progress\n") != 0) ||
60                         (commit && strcmp(notice, "NOTICE:  COMMIT: no transaction in progress\n") != 0))
61                         fputs(notice, stderr);
62         }
63         else if (!QUIET())
64         {
65                 if (commit)
66                         puts("Warning: Your transaction in progress has been committed.");
67                 else
68                         puts("Warning: Your transaction in progress has been rolled back.");
69         }
70
71         PQsetNoticeProcessor(pset.db, old_notice_hook, NULL);
72         return true;
73 }
74
75
76
77 /*
78  * do_lo_export()
79  *
80  * Write a large object to a file
81  */
82 bool
83 do_lo_export(const char *loid_arg, const char *filename_arg)
84 {
85         PGresult   *res;
86         int                     status;
87         bool            own_transaction = true;
88         const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
89
90         if (var && strcmp(var, "nothing") == 0)
91                 own_transaction = false;
92
93         if (!pset.db)
94         {
95                 if (!pset.cur_cmd_interactive)
96                         fprintf(stderr, "%s: ", pset.progname);
97                 fputs("\\lo_export: not connected to a database\n", stderr);
98                 return false;
99         }
100
101         if (own_transaction)
102         {
103                 if (!handle_transaction())
104                         return false;
105
106                 if (!(res = PSQLexec("BEGIN")))
107                         return false;
108
109                 PQclear(res);
110         }
111
112         status = lo_export(pset.db, atol(loid_arg), filename_arg);
113         if (status != 1)
114         {                                                       /* of course this status is documented
115                                                                  * nowhere :( */
116                 fputs(PQerrorMessage(pset.db), stderr);
117                 if (own_transaction)
118                 {
119                         res = PQexec(pset.db, "ROLLBACK");
120                         PQclear(res);
121                 }
122                 return false;
123         }
124
125         if (own_transaction)
126         {
127                 if (!(res = PSQLexec("COMMIT")))
128                 {
129                         res = PQexec(pset.db, "ROLLBACK");
130                         PQclear(res);
131                         return false;
132                 }
133
134                 PQclear(res);
135         }
136
137         fprintf(pset.queryFout, "lo_export\n");
138
139         return true;
140 }
141
142
143
144 /*
145  * do_lo_import()
146  *
147  * Copy large object from file to database
148  */
149 bool
150 do_lo_import(const char *filename_arg, const char *comment_arg)
151 {
152         PGresult   *res;
153         Oid                     loid;
154         char            buf[1024];
155         unsigned int i;
156         bool            own_transaction = true;
157         const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
158
159         if (var && strcmp(var, "nothing") == 0)
160                 own_transaction = false;
161
162         if (!pset.db)
163         {
164                 if (!pset.cur_cmd_interactive)
165                         fprintf(stderr, "%s: ", pset.progname);
166                 fputs("\\lo_import: not connected to a database\n", stderr);
167                 return false;
168         }
169
170         if (own_transaction)
171         {
172                 if (!handle_transaction())
173                         return false;
174
175                 if (!(res = PSQLexec("BEGIN")))
176                         return false;
177
178                 PQclear(res);
179         }
180
181         loid = lo_import(pset.db, filename_arg);
182         if (loid == InvalidOid)
183         {
184                 fputs(PQerrorMessage(pset.db), stderr);
185                 if (own_transaction)
186                 {
187                         res = PQexec(pset.db, "ROLLBACK");
188                         PQclear(res);
189                 }
190                 return false;
191         }
192
193         /* insert description if given */
194         if (comment_arg)
195         {
196                 sprintf(buf, "INSERT INTO pg_description VALUES (%u, '", loid);
197                 for (i = 0; i < strlen(comment_arg); i++)
198                         if (comment_arg[i] == '\'')
199                                 strcat(buf, "\\'");
200                         else
201                                 strncat(buf, &comment_arg[i], 1);
202                 strcat(buf, "')");
203
204                 if (!(res = PSQLexec(buf)))
205                 {
206                         if (own_transaction)
207                         {
208                                 res = PQexec(pset.db, "ROLLBACK");
209                                 PQclear(res);
210                         }
211                         return false;
212                 }
213         }
214
215         if (own_transaction)
216         {
217                 if (!(res = PSQLexec("COMMIT")))
218                 {
219                         res = PQexec(pset.db, "ROLLBACK");
220                         PQclear(res);
221                         return false;
222                 }
223
224                 PQclear(res);
225         }
226
227
228         fprintf(pset.queryFout, "lo_import %d\n", loid);
229         sprintf(buf, "%u", (unsigned int) loid);
230         SetVariable(pset.vars, "LASTOID", buf);
231
232         return true;
233 }
234
235
236
237 /*
238  * do_lo_unlink()
239  *
240  * removes a large object out of the database
241  */
242 bool
243 do_lo_unlink(const char *loid_arg)
244 {
245         PGresult   *res;
246         int                     status;
247         Oid                     loid = (Oid) atol(loid_arg);
248         char            buf[256];
249         bool            own_transaction = true;
250         const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
251
252         if (var && strcmp(var, "nothing") == 0)
253                 own_transaction = false;
254
255         if (!pset.db)
256         {
257                 if (!pset.cur_cmd_interactive)
258                         fprintf(stderr, "%s: ", pset.progname);
259                 fputs("\\lo_unlink: not connected to a database\n", stderr);
260                 return false;
261         }
262
263         if (own_transaction)
264         {
265                 if (!handle_transaction())
266                         return false;
267
268                 if (!(res = PSQLexec("BEGIN")))
269                         return false;
270
271                 PQclear(res);
272         }
273
274         status = lo_unlink(pset.db, loid);
275         if (status == -1)
276         {
277                 fputs(PQerrorMessage(pset.db), stderr);
278                 if (own_transaction)
279                 {
280                         res = PQexec(pset.db, "ROLLBACK");
281                         PQclear(res);
282                 }
283                 return false;
284         }
285
286         /* remove the comment as well */
287         sprintf(buf, "DELETE FROM pg_description WHERE objoid = %u", loid);
288         if (!(res = PSQLexec(buf)))
289         {
290                 if (own_transaction)
291                 {
292                         res = PQexec(pset.db, "ROLLBACK");
293                         PQclear(res);
294                 }
295                 return false;
296         }
297
298
299         if (own_transaction)
300         {
301                 if (!(res = PSQLexec("COMMIT")))
302                 {
303                         res = PQexec(pset.db, "ROLLBACK");
304                         PQclear(res);
305                         return false;
306                 }
307                 PQclear(res);
308         }
309
310
311         fprintf(pset.queryFout, "lo_unlink %d\n", loid);
312
313         return true;
314 }
315
316
317
318 /*
319  * do_lo_list()
320  *
321  * Show all large objects in database with comments
322  */
323 bool
324 do_lo_list(void)
325 {
326         PGresult   *res;
327         char            buf[1024];
328         printQueryOpt myopt = pset.popt;
329
330         strcpy(buf,
331           "SELECT loid as \"ID\", obj_description(loid) as \"Description\"\n"
332                    "FROM (SELECT DISTINCT loid FROM pg_largeobject) x\n"
333                    "ORDER BY \"ID\"");
334
335         res = PSQLexec(buf);
336         if (!res)
337                 return false;
338
339         myopt.topt.tuples_only = false;
340         myopt.nullPrint = NULL;
341         myopt.title = "Large objects";
342
343         printQuery(res, &myopt, pset.queryFout);
344
345         PQclear(res);
346         return true;
347 }