Commit 41b8c2c8 authored by Marc G. Fournier's avatar Marc G. Fournier

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)
parent 2bdded35
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.17 1996/11/10 03:06:36 momjian Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.18 1996/11/11 12:16:54 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -192,6 +192,7 @@ PQconnectdb(const char *conninfo)
conn->Pfdebug = NULL;
conn->port = NULL;
conn->notifyList = DLNewList();
conn->lobjfuncs = NULL;
conn->pghost = strdup(conninfo_getval("host"));
conn->pgport = strdup(conninfo_getval("port"));
......@@ -299,6 +300,7 @@ PQsetdb(const char *pghost, const char* pgport, const char* pgoptions, const cha
conn->Pfdebug = NULL;
conn->port = NULL;
conn->notifyList = DLNewList();
conn->lobjfuncs = NULL;
if (!pghost || pghost[0] == '\0') {
if (!(tmp = getenv("PGHOST"))) {
......@@ -519,6 +521,7 @@ freePGconn(PGconn *conn)
if (conn->dbName) free(conn->dbName);
if (conn->pguser) free(conn->pguser);
if (conn->notifyList) DLFreeList(conn->notifyList);
if (conn->lobjfuncs) free(conn->lobjfuncs);
free(conn);
}
......
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.3 1996/11/08 06:02:28 momjian Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.4 1996/11/11 12:16:56 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -18,7 +18,6 @@
#include <sys/types.h>
#include "postgres.h"
#include "libpq-fe.h"
#include "fmgr.h"
#include "libpq/libpq-fs.h"
#ifndef MAXPATHLEN
......@@ -27,6 +26,8 @@
#define LO_BUFSIZE 1024
static int lo_initialize(PGconn *conn);
/*
* lo_open
* opens an existing large object
......@@ -49,8 +50,14 @@ lo_open(PGconn* conn, Oid lobjId, int mode)
argv[1].isint = 1;
argv[1].len = 4;
argv[1].u.integer = mode;
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
if(lo_initialize(conn) < 0) {
return -1;
}
}
res = PQfn(conn, F_LO_OPEN,&fd,&result_len,1,argv,2);
res = PQfn(conn, conn->lobjfuncs->fn_lo_open,&fd,&result_len,1,argv,2);
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
PQclear(res);
......@@ -78,10 +85,17 @@ lo_close(PGconn *conn, int fd)
int retval;
int result_len;
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
if(lo_initialize(conn) < 0) {
return -1;
}
}
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = fd;
res = PQfn(conn, F_LO_CLOSE,&retval,&result_len,1,argv,1);
res = PQfn(conn, conn->lobjfuncs->fn_lo_close,
&retval,&result_len,1,argv,1);
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
PQclear(res);
return retval;
......@@ -104,6 +118,12 @@ lo_read(PGconn *conn, int fd, char *buf, int len)
PGresult *res;
int result_len;
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
if(lo_initialize(conn) < 0) {
return -1;
}
}
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = fd;
......@@ -112,7 +132,8 @@ lo_read(PGconn *conn, int fd, char *buf, int len)
argv[1].len = 4;
argv[1].u.integer = len;
res = PQfn(conn, F_LOREAD,(int*)buf,&result_len,0,argv,2);
res = PQfn(conn, conn->lobjfuncs->fn_lo_read,
(int*)buf,&result_len,0,argv,2);
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
PQclear(res);
return result_len;
......@@ -133,6 +154,12 @@ lo_write(PGconn *conn, int fd, char *buf, int len)
int result_len;
int retval;
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
if(lo_initialize(conn) < 0) {
return -1;
}
}
if (len <= 0)
return 0;
......@@ -144,7 +171,8 @@ lo_write(PGconn *conn, int fd, char *buf, int len)
argv[1].len = len;
argv[1].u.ptr = (int*)buf;
res = PQfn(conn, F_LOWRITE,&retval,&result_len,1,argv,2);
res = PQfn(conn, conn->lobjfuncs->fn_lo_write,
&retval,&result_len,1,argv,2);
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
PQclear(res);
return retval;
......@@ -167,6 +195,12 @@ lo_lseek(PGconn *conn, int fd, int offset, int whence)
int retval;
int result_len;
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
if(lo_initialize(conn) < 0) {
return -1;
}
}
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = fd;
......@@ -179,7 +213,8 @@ lo_lseek(PGconn *conn, int fd, int offset, int whence)
argv[2].len = 4;
argv[2].u.integer = whence;
res = PQfn(conn, F_LO_LSEEK,&retval,&result_len,1,argv,3);
res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek,
&retval,&result_len,1,argv,3);
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
PQclear(res);
return retval;
......@@ -204,10 +239,17 @@ lo_creat(PGconn *conn, int mode)
int retval;
int result_len;
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
if(lo_initialize(conn) < 0) {
return -1;
}
}
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = mode;
res = PQfn(conn, F_LO_CREAT,&retval,&result_len,1,argv,1);
res = PQfn(conn, conn->lobjfuncs->fn_lo_creat,
&retval,&result_len,1,argv,1);
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
PQclear(res);
return (Oid)retval;
......@@ -230,11 +272,18 @@ lo_tell(PGconn *conn, int fd)
PGresult *res;
int result_len;
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
if(lo_initialize(conn) < 0) {
return -1;
}
}
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = fd;
res = PQfn(conn, F_LO_TELL,&retval,&result_len,1,argv,1);
res = PQfn(conn, conn->lobjfuncs->fn_lo_tell,
&retval,&result_len,1,argv,1);
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
PQclear(res);
return retval;
......@@ -256,11 +305,18 @@ lo_unlink(PGconn *conn, Oid lobjId)
int result_len;
int retval;
if(conn->lobjfuncs == (PGlobjfuncs *)NULL) {
if(lo_initialize(conn) < 0) {
return -1;
}
}
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = lobjId;
res = PQfn(conn, F_LO_UNLINK,&retval,&result_len,1,argv,1);
res = PQfn(conn, conn->lobjfuncs->fn_lo_unlink,
&retval,&result_len,1,argv,1);
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
PQclear(res);
return retval;
......@@ -380,3 +436,157 @@ lo_export(PGconn *conn, Oid lobjId, char *filename)
return 1;
}
/* ----------------
* lo_initialize
*
* Initialize the large object interface for an existing connection.
* We ask the backend about the functions OID's in pg_proc for all
* functions that are required for large object operations.
* ----------------
*/
static int lo_initialize(PGconn *conn)
{
PGresult *res;
PGlobjfuncs *lobjfuncs;
int n;
char *fname;
Oid foid;
/* ----------------
* Allocate the structure to hold the functions OID's
* ----------------
*/
lobjfuncs = (PGlobjfuncs *)malloc(sizeof(PGlobjfuncs));
if (lobjfuncs == (PGlobjfuncs *)NULL) {
strcpy(conn->errorMessage,
"FATAL: malloc() failed in lo_initialize()\n");
return -1;
}
memset((char *)lobjfuncs, 0, sizeof(PGlobjfuncs));
/* ----------------
* Execute the query to get all the functions at once
* ----------------
*/
res = PQexec(conn, "select proname, oid from pg_proc \
where proname = 'lo_open' \
or proname = 'lo_close' \
or proname = 'lo_creat' \
or proname = 'lo_unlink' \
or proname = 'lo_lseek' \
or proname = 'lo_tell' \
or proname = 'LOread' \
or proname = 'LOwrite'");
if (res == (PGresult *)NULL) {
free(lobjfuncs);
return -1;
}
if (res->resultStatus != PGRES_TUPLES_OK) {
free(lobjfuncs);
PQclear(res);
strcpy(conn->errorMessage,
"ERROR: SELECT didn't return data in lo_initialize()\n");
return -1;
}
/* ----------------
* Examine the result and put the OID's into the struct
* ----------------
*/
for(n = 0; n < PQntuples(res); n++) {
fname = PQgetvalue(res, n, 0);
foid = (Oid)atoi(PQgetvalue(res, n, 1));
if(!strcmp(fname, "lo_open")) {
lobjfuncs->fn_lo_open = foid;
} else
if(!strcmp(fname, "lo_close")) {
lobjfuncs->fn_lo_close = foid;
} else
if(!strcmp(fname, "lo_creat")) {
lobjfuncs->fn_lo_creat = foid;
} else
if(!strcmp(fname, "lo_unlink")) {
lobjfuncs->fn_lo_unlink = foid;
} else
if(!strcmp(fname, "lo_lseek")) {
lobjfuncs->fn_lo_lseek = foid;
} else
if(!strcmp(fname, "lo_tell")) {
lobjfuncs->fn_lo_tell = foid;
} else
if(!strcmp(fname, "LOread")) {
lobjfuncs->fn_lo_read = foid;
} else
if(!strcmp(fname, "LOwrite")) {
lobjfuncs->fn_lo_write = foid;
}
}
PQclear(res);
/* ----------------
* Finally check that we really got all large object
* interface functions.
* ----------------
*/
if(lobjfuncs->fn_lo_open == 0) {
strcpy(conn->errorMessage,
"ERROR: Cannot determine OID for function lo_open\n");
free(lobjfuncs);
return -1;
}
if(lobjfuncs->fn_lo_close == 0) {
strcpy(conn->errorMessage,
"ERROR: Cannot determine OID for function lo_close\n");
free(lobjfuncs);
return -1;
}
if(lobjfuncs->fn_lo_creat == 0) {
strcpy(conn->errorMessage,
"ERROR: Cannot determine OID for function lo_creat\n");
free(lobjfuncs);
return -1;
}
if(lobjfuncs->fn_lo_unlink == 0) {
strcpy(conn->errorMessage,
"ERROR: Cannot determine OID for function lo_unlink\n");
free(lobjfuncs);
return -1;
}
if(lobjfuncs->fn_lo_lseek == 0) {
strcpy(conn->errorMessage,
"ERROR: Cannot determine OID for function lo_lseek\n");
free(lobjfuncs);
return -1;
}
if(lobjfuncs->fn_lo_tell == 0) {
strcpy(conn->errorMessage,
"ERROR: Cannot determine OID for function lo_tell\n");
free(lobjfuncs);
return -1;
}
if(lobjfuncs->fn_lo_read == 0) {
strcpy(conn->errorMessage,
"ERROR: Cannot determine OID for function LOread\n");
free(lobjfuncs);
return -1;
}
if(lobjfuncs->fn_lo_write == 0) {
strcpy(conn->errorMessage,
"ERROR: Cannot determine OID for function LOwrite\n");
free(lobjfuncs);
return -1;
}
/* ----------------
* Put the structure into the connection control
* ----------------
*/
conn->lobjfuncs = lobjfuncs;
return 0;
}
......@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: libpq-fe.h,v 1.11 1996/11/10 03:06:38 momjian Exp $
* $Id: libpq-fe.h,v 1.12 1996/11/11 12:16:57 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -96,6 +96,17 @@ typedef struct pgNotify {
int be_pid; /* process id of backend */
} PGnotify;
typedef struct pgLobjfuncs {
Oid fn_lo_open; /* OID of backend function lo_open */
Oid fn_lo_close; /* OID of backend function lo_close */
Oid fn_lo_creat; /* OID of backend function lo_creat */
Oid fn_lo_unlink; /* OID of backend function lo_unlink */
Oid fn_lo_lseek; /* OID of backend function lo_lseek */
Oid fn_lo_tell; /* OID of backend function lo_tell */
Oid fn_lo_read; /* OID of backend function LOread */
Oid fn_lo_write; /* OID of backend function LOwrite */
} PGlobjfuncs;
/* PGconn encapsulates a connection to the backend */
typedef struct pg_conn{
char *pghost; /* the machine on which the server is running */
......@@ -113,6 +124,7 @@ typedef struct pg_conn{
int asyncNotifyWaiting;
Dllist* notifyList;
char *pguser; /* Postgres username of user who is connected */
PGlobjfuncs *lobjfuncs; /* Backend function OID's for large object access */
} PGconn;
#define CMDSTATUS_LEN 40
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment