Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 41b8c2c

Browse files
committed
As proposed,
following is the patch to libpq's large object interface that removes the requirement to include fmgr.h into fe-lobj.c. The large object interface now ask's the backend to tell the OID's of all the required functions in pg_proc. From: wieck@sapserv.debis.de (Jan Wieck)
1 parent 2bdded3 commit 41b8c2c

File tree

3 files changed

+237
-12
lines changed

3 files changed

+237
-12
lines changed

src/interfaces/libpq/fe-connect.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.17 1996/11/10 03:06:36 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.18 1996/11/11 12:16:54 scrappy Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -192,6 +192,7 @@ PQconnectdb(const char *conninfo)
192192
conn->Pfdebug = NULL;
193193
conn->port = NULL;
194194
conn->notifyList = DLNewList();
195+
conn->lobjfuncs = NULL;
195196

196197
conn->pghost = strdup(conninfo_getval("host"));
197198
conn->pgport = strdup(conninfo_getval("port"));
@@ -299,6 +300,7 @@ PQsetdb(const char *pghost, const char* pgport, const char* pgoptions, const cha
299300
conn->Pfdebug = NULL;
300301
conn->port = NULL;
301302
conn->notifyList = DLNewList();
303+
conn->lobjfuncs = NULL;
302304

303305
if (!pghost || pghost[0] == '\0') {
304306
if (!(tmp = getenv("PGHOST"))) {
@@ -519,6 +521,7 @@ freePGconn(PGconn *conn)
519521
if (conn->dbName) free(conn->dbName);
520522
if (conn->pguser) free(conn->pguser);
521523
if (conn->notifyList) DLFreeList(conn->notifyList);
524+
if (conn->lobjfuncs) free(conn->lobjfuncs);
522525
free(conn);
523526
}
524527

src/interfaces/libpq/fe-lobj.c

+220-10
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* 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 $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -18,7 +18,6 @@
1818
#include <sys/types.h>
1919
#include "postgres.h"
2020
#include "libpq-fe.h"
21-
#include "fmgr.h"
2221
#include "libpq/libpq-fs.h"
2322

2423
#ifndef MAXPATHLEN
@@ -27,6 +26,8 @@
2726

2827
#define LO_BUFSIZE 1024
2928

29+
static int lo_initialize(PGconn *conn);
30+
3031
/*
3132
* lo_open
3233
* opens an existing large object
@@ -49,8 +50,14 @@ lo_open(PGconn* conn, Oid lobjId, int mode)
4950
argv[1].isint = 1;
5051
argv[1].len = 4;
5152
argv[1].u.integer = mode;
53+
54+
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
55+
if(lo_initialize(conn) < 0) {
56+
return -1;
57+
}
58+
}
5259

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);
5461
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
5562
PQclear(res);
5663

@@ -78,10 +85,17 @@ lo_close(PGconn *conn, int fd)
7885
int retval;
7986
int result_len;
8087

88+
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
89+
if(lo_initialize(conn) < 0) {
90+
return -1;
91+
}
92+
}
93+
8194
argv[0].isint = 1;
8295
argv[0].len = 4;
8396
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);
8599
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
86100
PQclear(res);
87101
return retval;
@@ -104,6 +118,12 @@ lo_read(PGconn *conn, int fd, char *buf, int len)
104118
PGresult *res;
105119
int result_len;
106120

121+
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
122+
if(lo_initialize(conn) < 0) {
123+
return -1;
124+
}
125+
}
126+
107127
argv[0].isint = 1;
108128
argv[0].len = 4;
109129
argv[0].u.integer = fd;
@@ -112,7 +132,8 @@ lo_read(PGconn *conn, int fd, char *buf, int len)
112132
argv[1].len = 4;
113133
argv[1].u.integer = len;
114134

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);
116137
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
117138
PQclear(res);
118139
return result_len;
@@ -133,6 +154,12 @@ lo_write(PGconn *conn, int fd, char *buf, int len)
133154
int result_len;
134155
int retval;
135156

157+
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
158+
if(lo_initialize(conn) < 0) {
159+
return -1;
160+
}
161+
}
162+
136163
if (len <= 0)
137164
return 0;
138165

@@ -144,7 +171,8 @@ lo_write(PGconn *conn, int fd, char *buf, int len)
144171
argv[1].len = len;
145172
argv[1].u.ptr = (int*)buf;
146173

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);
148176
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
149177
PQclear(res);
150178
return retval;
@@ -167,6 +195,12 @@ lo_lseek(PGconn *conn, int fd, int offset, int whence)
167195
int retval;
168196
int result_len;
169197

198+
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
199+
if(lo_initialize(conn) < 0) {
200+
return -1;
201+
}
202+
}
203+
170204
argv[0].isint = 1;
171205
argv[0].len = 4;
172206
argv[0].u.integer = fd;
@@ -179,7 +213,8 @@ lo_lseek(PGconn *conn, int fd, int offset, int whence)
179213
argv[2].len = 4;
180214
argv[2].u.integer = whence;
181215

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);
183218
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
184219
PQclear(res);
185220
return retval;
@@ -204,10 +239,17 @@ lo_creat(PGconn *conn, int mode)
204239
int retval;
205240
int result_len;
206241

242+
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
243+
if(lo_initialize(conn) < 0) {
244+
return -1;
245+
}
246+
}
247+
207248
argv[0].isint = 1;
208249
argv[0].len = 4;
209250
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);
211253
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
212254
PQclear(res);
213255
return (Oid)retval;
@@ -230,11 +272,18 @@ lo_tell(PGconn *conn, int fd)
230272
PGresult *res;
231273
int result_len;
232274

275+
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
276+
if(lo_initialize(conn) < 0) {
277+
return -1;
278+
}
279+
}
280+
233281
argv[0].isint = 1;
234282
argv[0].len = 4;
235283
argv[0].u.integer = fd;
236284

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);
238287
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
239288
PQclear(res);
240289
return retval;
@@ -256,11 +305,18 @@ lo_unlink(PGconn *conn, Oid lobjId)
256305
int result_len;
257306
int retval;
258307

308+
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
309+
if(lo_initialize(conn) < 0) {
310+
return -1;
311+
}
312+
}
313+
259314
argv[0].isint = 1;
260315
argv[0].len = 4;
261316
argv[0].u.integer = lobjId;
262317

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);
264320
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
265321
PQclear(res);
266322
return retval;
@@ -380,3 +436,157 @@ lo_export(PGconn *conn, Oid lobjId, char *filename)
380436

381437
return 1;
382438
}
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

Comments
 (0)