7
7
*
8
8
*
9
9
* IDENTIFICATION
10
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.3 1996/11/08 06:02:28 momjian Exp $
10
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.4 1996/11/11 12:16:56 scrappy Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
18
18
#include <sys/types.h>
19
19
#include "postgres.h"
20
20
#include "libpq-fe.h"
21
- #include "fmgr.h"
22
21
#include "libpq/libpq-fs.h"
23
22
24
23
#ifndef MAXPATHLEN
27
26
28
27
#define LO_BUFSIZE 1024
29
28
29
+ static int lo_initialize (PGconn * conn );
30
+
30
31
/*
31
32
* lo_open
32
33
* opens an existing large object
@@ -49,8 +50,14 @@ lo_open(PGconn* conn, Oid lobjId, int mode)
49
50
argv [1 ].isint = 1 ;
50
51
argv [1 ].len = 4 ;
51
52
argv [1 ].u .integer = mode ;
53
+
54
+ if (conn -> lobjfuncs == (PGlobjfuncs * )NULL ) {
55
+ if (lo_initialize (conn ) < 0 ) {
56
+ return -1 ;
57
+ }
58
+ }
52
59
53
- res = PQfn (conn , F_LO_OPEN ,& fd ,& result_len ,1 ,argv ,2 );
60
+ res = PQfn (conn , conn -> lobjfuncs -> fn_lo_open ,& fd ,& result_len ,1 ,argv ,2 );
54
61
if (PQresultStatus (res ) == PGRES_COMMAND_OK ) {
55
62
PQclear (res );
56
63
@@ -78,10 +85,17 @@ lo_close(PGconn *conn, int fd)
78
85
int retval ;
79
86
int result_len ;
80
87
88
+ if (conn -> lobjfuncs == (PGlobjfuncs * )NULL ) {
89
+ if (lo_initialize (conn ) < 0 ) {
90
+ return -1 ;
91
+ }
92
+ }
93
+
81
94
argv [0 ].isint = 1 ;
82
95
argv [0 ].len = 4 ;
83
96
argv [0 ].u .integer = fd ;
84
- res = PQfn (conn , F_LO_CLOSE ,& retval ,& result_len ,1 ,argv ,1 );
97
+ res = PQfn (conn , conn -> lobjfuncs -> fn_lo_close ,
98
+ & retval ,& result_len ,1 ,argv ,1 );
85
99
if (PQresultStatus (res ) == PGRES_COMMAND_OK ) {
86
100
PQclear (res );
87
101
return retval ;
@@ -104,6 +118,12 @@ lo_read(PGconn *conn, int fd, char *buf, int len)
104
118
PGresult * res ;
105
119
int result_len ;
106
120
121
+ if (conn -> lobjfuncs == (PGlobjfuncs * )NULL ) {
122
+ if (lo_initialize (conn ) < 0 ) {
123
+ return -1 ;
124
+ }
125
+ }
126
+
107
127
argv [0 ].isint = 1 ;
108
128
argv [0 ].len = 4 ;
109
129
argv [0 ].u .integer = fd ;
@@ -112,7 +132,8 @@ lo_read(PGconn *conn, int fd, char *buf, int len)
112
132
argv [1 ].len = 4 ;
113
133
argv [1 ].u .integer = len ;
114
134
115
- res = PQfn (conn , F_LOREAD ,(int * )buf ,& result_len ,0 ,argv ,2 );
135
+ res = PQfn (conn , conn -> lobjfuncs -> fn_lo_read ,
136
+ (int * )buf ,& result_len ,0 ,argv ,2 );
116
137
if (PQresultStatus (res ) == PGRES_COMMAND_OK ) {
117
138
PQclear (res );
118
139
return result_len ;
@@ -133,6 +154,12 @@ lo_write(PGconn *conn, int fd, char *buf, int len)
133
154
int result_len ;
134
155
int retval ;
135
156
157
+ if (conn -> lobjfuncs == (PGlobjfuncs * )NULL ) {
158
+ if (lo_initialize (conn ) < 0 ) {
159
+ return -1 ;
160
+ }
161
+ }
162
+
136
163
if (len <= 0 )
137
164
return 0 ;
138
165
@@ -144,7 +171,8 @@ lo_write(PGconn *conn, int fd, char *buf, int len)
144
171
argv [1 ].len = len ;
145
172
argv [1 ].u .ptr = (int * )buf ;
146
173
147
- res = PQfn (conn , F_LOWRITE ,& retval ,& result_len ,1 ,argv ,2 );
174
+ res = PQfn (conn , conn -> lobjfuncs -> fn_lo_write ,
175
+ & retval ,& result_len ,1 ,argv ,2 );
148
176
if (PQresultStatus (res ) == PGRES_COMMAND_OK ) {
149
177
PQclear (res );
150
178
return retval ;
@@ -167,6 +195,12 @@ lo_lseek(PGconn *conn, int fd, int offset, int whence)
167
195
int retval ;
168
196
int result_len ;
169
197
198
+ if (conn -> lobjfuncs == (PGlobjfuncs * )NULL ) {
199
+ if (lo_initialize (conn ) < 0 ) {
200
+ return -1 ;
201
+ }
202
+ }
203
+
170
204
argv [0 ].isint = 1 ;
171
205
argv [0 ].len = 4 ;
172
206
argv [0 ].u .integer = fd ;
@@ -179,7 +213,8 @@ lo_lseek(PGconn *conn, int fd, int offset, int whence)
179
213
argv [2 ].len = 4 ;
180
214
argv [2 ].u .integer = whence ;
181
215
182
- res = PQfn (conn , F_LO_LSEEK ,& retval ,& result_len ,1 ,argv ,3 );
216
+ res = PQfn (conn , conn -> lobjfuncs -> fn_lo_lseek ,
217
+ & retval ,& result_len ,1 ,argv ,3 );
183
218
if (PQresultStatus (res ) == PGRES_COMMAND_OK ) {
184
219
PQclear (res );
185
220
return retval ;
@@ -204,10 +239,17 @@ lo_creat(PGconn *conn, int mode)
204
239
int retval ;
205
240
int result_len ;
206
241
242
+ if (conn -> lobjfuncs == (PGlobjfuncs * )NULL ) {
243
+ if (lo_initialize (conn ) < 0 ) {
244
+ return -1 ;
245
+ }
246
+ }
247
+
207
248
argv [0 ].isint = 1 ;
208
249
argv [0 ].len = 4 ;
209
250
argv [0 ].u .integer = mode ;
210
- res = PQfn (conn , F_LO_CREAT ,& retval ,& result_len ,1 ,argv ,1 );
251
+ res = PQfn (conn , conn -> lobjfuncs -> fn_lo_creat ,
252
+ & retval ,& result_len ,1 ,argv ,1 );
211
253
if (PQresultStatus (res ) == PGRES_COMMAND_OK ) {
212
254
PQclear (res );
213
255
return (Oid )retval ;
@@ -230,11 +272,18 @@ lo_tell(PGconn *conn, int fd)
230
272
PGresult * res ;
231
273
int result_len ;
232
274
275
+ if (conn -> lobjfuncs == (PGlobjfuncs * )NULL ) {
276
+ if (lo_initialize (conn ) < 0 ) {
277
+ return -1 ;
278
+ }
279
+ }
280
+
233
281
argv [0 ].isint = 1 ;
234
282
argv [0 ].len = 4 ;
235
283
argv [0 ].u .integer = fd ;
236
284
237
- res = PQfn (conn , F_LO_TELL ,& retval ,& result_len ,1 ,argv ,1 );
285
+ res = PQfn (conn , conn -> lobjfuncs -> fn_lo_tell ,
286
+ & retval ,& result_len ,1 ,argv ,1 );
238
287
if (PQresultStatus (res ) == PGRES_COMMAND_OK ) {
239
288
PQclear (res );
240
289
return retval ;
@@ -256,11 +305,18 @@ lo_unlink(PGconn *conn, Oid lobjId)
256
305
int result_len ;
257
306
int retval ;
258
307
308
+ if (conn -> lobjfuncs == (PGlobjfuncs * )NULL ) {
309
+ if (lo_initialize (conn ) < 0 ) {
310
+ return -1 ;
311
+ }
312
+ }
313
+
259
314
argv [0 ].isint = 1 ;
260
315
argv [0 ].len = 4 ;
261
316
argv [0 ].u .integer = lobjId ;
262
317
263
- res = PQfn (conn , F_LO_UNLINK ,& retval ,& result_len ,1 ,argv ,1 );
318
+ res = PQfn (conn , conn -> lobjfuncs -> fn_lo_unlink ,
319
+ & retval ,& result_len ,1 ,argv ,1 );
264
320
if (PQresultStatus (res ) == PGRES_COMMAND_OK ) {
265
321
PQclear (res );
266
322
return retval ;
@@ -380,3 +436,157 @@ lo_export(PGconn *conn, Oid lobjId, char *filename)
380
436
381
437
return 1 ;
382
438
}
439
+
440
+
441
+ /* ----------------
442
+ * lo_initialize
443
+ *
444
+ * Initialize the large object interface for an existing connection.
445
+ * We ask the backend about the functions OID's in pg_proc for all
446
+ * functions that are required for large object operations.
447
+ * ----------------
448
+ */
449
+ static int lo_initialize (PGconn * conn )
450
+ {
451
+ PGresult * res ;
452
+ PGlobjfuncs * lobjfuncs ;
453
+ int n ;
454
+ char * fname ;
455
+ Oid foid ;
456
+
457
+ /* ----------------
458
+ * Allocate the structure to hold the functions OID's
459
+ * ----------------
460
+ */
461
+ lobjfuncs = (PGlobjfuncs * )malloc (sizeof (PGlobjfuncs ));
462
+ if (lobjfuncs == (PGlobjfuncs * )NULL ) {
463
+ strcpy (conn -> errorMessage ,
464
+ "FATAL: malloc() failed in lo_initialize()\n" );
465
+ return -1 ;
466
+ }
467
+ memset ((char * )lobjfuncs , 0 , sizeof (PGlobjfuncs ));
468
+
469
+ /* ----------------
470
+ * Execute the query to get all the functions at once
471
+ * ----------------
472
+ */
473
+ res = PQexec (conn , "select proname, oid from pg_proc \
474
+ where proname = 'lo_open' \
475
+ or proname = 'lo_close' \
476
+ or proname = 'lo_creat' \
477
+ or proname = 'lo_unlink' \
478
+ or proname = 'lo_lseek' \
479
+ or proname = 'lo_tell' \
480
+ or proname = 'LOread' \
481
+ or proname = 'LOwrite'" );
482
+ if (res == (PGresult * )NULL ) {
483
+ free (lobjfuncs );
484
+ return -1 ;
485
+ }
486
+
487
+ if (res -> resultStatus != PGRES_TUPLES_OK ) {
488
+ free (lobjfuncs );
489
+ PQclear (res );
490
+ strcpy (conn -> errorMessage ,
491
+ "ERROR: SELECT didn't return data in lo_initialize()\n" );
492
+ return -1 ;
493
+ }
494
+
495
+ /* ----------------
496
+ * Examine the result and put the OID's into the struct
497
+ * ----------------
498
+ */
499
+ for (n = 0 ; n < PQntuples (res ); n ++ ) {
500
+ fname = PQgetvalue (res , n , 0 );
501
+ foid = (Oid )atoi (PQgetvalue (res , n , 1 ));
502
+ if (!strcmp (fname , "lo_open" )) {
503
+ lobjfuncs -> fn_lo_open = foid ;
504
+ } else
505
+ if (!strcmp (fname , "lo_close" )) {
506
+ lobjfuncs -> fn_lo_close = foid ;
507
+ } else
508
+ if (!strcmp (fname , "lo_creat" )) {
509
+ lobjfuncs -> fn_lo_creat = foid ;
510
+ } else
511
+ if (!strcmp (fname , "lo_unlink" )) {
512
+ lobjfuncs -> fn_lo_unlink = foid ;
513
+ } else
514
+ if (!strcmp (fname , "lo_lseek" )) {
515
+ lobjfuncs -> fn_lo_lseek = foid ;
516
+ } else
517
+ if (!strcmp (fname , "lo_tell" )) {
518
+ lobjfuncs -> fn_lo_tell = foid ;
519
+ } else
520
+ if (!strcmp (fname , "LOread" )) {
521
+ lobjfuncs -> fn_lo_read = foid ;
522
+ } else
523
+ if (!strcmp (fname , "LOwrite" )) {
524
+ lobjfuncs -> fn_lo_write = foid ;
525
+ }
526
+ }
527
+
528
+ PQclear (res );
529
+
530
+ /* ----------------
531
+ * Finally check that we really got all large object
532
+ * interface functions.
533
+ * ----------------
534
+ */
535
+ if (lobjfuncs -> fn_lo_open == 0 ) {
536
+ strcpy (conn -> errorMessage ,
537
+ "ERROR: Cannot determine OID for function lo_open\n" );
538
+ free (lobjfuncs );
539
+ return -1 ;
540
+ }
541
+ if (lobjfuncs -> fn_lo_close == 0 ) {
542
+ strcpy (conn -> errorMessage ,
543
+ "ERROR: Cannot determine OID for function lo_close\n" );
544
+ free (lobjfuncs );
545
+ return -1 ;
546
+ }
547
+ if (lobjfuncs -> fn_lo_creat == 0 ) {
548
+ strcpy (conn -> errorMessage ,
549
+ "ERROR: Cannot determine OID for function lo_creat\n" );
550
+ free (lobjfuncs );
551
+ return -1 ;
552
+ }
553
+ if (lobjfuncs -> fn_lo_unlink == 0 ) {
554
+ strcpy (conn -> errorMessage ,
555
+ "ERROR: Cannot determine OID for function lo_unlink\n" );
556
+ free (lobjfuncs );
557
+ return -1 ;
558
+ }
559
+ if (lobjfuncs -> fn_lo_lseek == 0 ) {
560
+ strcpy (conn -> errorMessage ,
561
+ "ERROR: Cannot determine OID for function lo_lseek\n" );
562
+ free (lobjfuncs );
563
+ return -1 ;
564
+ }
565
+ if (lobjfuncs -> fn_lo_tell == 0 ) {
566
+ strcpy (conn -> errorMessage ,
567
+ "ERROR: Cannot determine OID for function lo_tell\n" );
568
+ free (lobjfuncs );
569
+ return -1 ;
570
+ }
571
+ if (lobjfuncs -> fn_lo_read == 0 ) {
572
+ strcpy (conn -> errorMessage ,
573
+ "ERROR: Cannot determine OID for function LOread\n" );
574
+ free (lobjfuncs );
575
+ return -1 ;
576
+ }
577
+ if (lobjfuncs -> fn_lo_write == 0 ) {
578
+ strcpy (conn -> errorMessage ,
579
+ "ERROR: Cannot determine OID for function LOwrite\n" );
580
+ free (lobjfuncs );
581
+ return -1 ;
582
+ }
583
+
584
+ /* ----------------
585
+ * Put the structure into the connection control
586
+ * ----------------
587
+ */
588
+ conn -> lobjfuncs = lobjfuncs ;
589
+ return 0 ;
590
+ }
591
+
592
+
0 commit comments