Date: Sun, 16 Aug 1998 14:56:48 -0400

From: Tom Lane <tgl@sss.pgh.pa.us>
Attached is a patch for this weekend's work on libpq.  I've dealt
with several issues:

        <for details: see message, in pgsql-patches archive for above data>
This commit is contained in:
Marc G. Fournier 1998-08-17 03:50:43 +00:00
parent 3fa676a74c
commit 9312033071
16 changed files with 375 additions and 365 deletions

View File

@ -1,7 +1,7 @@
/* A lexical scanner generated by flex */ /* A lexical scanner generated by flex */
/* Scanner skeleton version: /* Scanner skeleton version:
* $Header: /cvsroot/pgsql/src/backend/parser/Attic/scan.c,v 1.22 1998/06/16 07:29:25 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/Attic/scan.c,v 1.23 1998/08/17 03:50:15 scrappy Exp $
*/ */
#define FLEX_SCANNER #define FLEX_SCANNER
@ -555,7 +555,7 @@ char *yytext;
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/Attic/scan.c,v 1.22 1998/06/16 07:29:25 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/Attic/scan.c,v 1.23 1998/08/17 03:50:15 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.153 1998/08/10 20:31:38 momjian Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.154 1998/08/17 03:50:17 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -121,8 +121,8 @@ struct winsize
/* declarations for functions in this file */ /* declarations for functions in this file */
static void usage(char *progname); static void usage(char *progname);
static void slashUsage(); static void slashUsage();
static void handleCopyOut(PGresult *res, FILE *copystream); static bool handleCopyOut(PGresult *res, FILE *copystream);
static void static bool
handleCopyIn(PGresult *res, const bool mustprompt, handleCopyIn(PGresult *res, const bool mustprompt,
FILE *copystream); FILE *copystream);
static int static int
@ -1103,23 +1103,23 @@ SendQuery(bool *success_p, PsqlSettings *pset, const char *query,
printf("%s\n", PQcmdStatus(results)); printf("%s\n", PQcmdStatus(results));
break; break;
case PGRES_COPY_OUT: case PGRES_COPY_OUT:
*success_p = true;
if (copy_out) if (copy_out)
handleCopyOut(results, copystream); *success_p = handleCopyOut(results, copystream);
else else
{ {
if (!pset->quiet) if (!pset->quiet)
printf("Copy command returns...\n"); printf("Copy command returns...\n");
handleCopyOut(results, stdout); *success_p = handleCopyOut(results, stdout);
} }
break; break;
case PGRES_COPY_IN: case PGRES_COPY_IN:
*success_p = true;
if (copy_in) if (copy_in)
handleCopyIn(results, false, copystream); *success_p = handleCopyIn(results, false, copystream);
else else
handleCopyIn(results, !pset->quiet && !pset->notty, stdin); *success_p = handleCopyIn(results,
!pset->quiet && !pset->notty,
stdin);
break; break;
case PGRES_NONFATAL_ERROR: case PGRES_NONFATAL_ERROR:
case PGRES_FATAL_ERROR: case PGRES_FATAL_ERROR:
@ -2646,7 +2646,6 @@ main(int argc, char **argv)
char *host = NULL; char *host = NULL;
char *port = NULL; char *port = NULL;
char *qfilename = NULL; char *qfilename = NULL;
char errbuf[ERROR_MSG_LENGTH];
PsqlSettings settings; PsqlSettings settings;
@ -2692,7 +2691,9 @@ main(int argc, char **argv)
settings.opt.align = 0; settings.opt.align = 0;
break; break;
case 'a': case 'a':
#if 0 /* this no longer does anything */
fe_setauthsvc(optarg, errbuf); fe_setauthsvc(optarg, errbuf);
#endif
break; break;
case 'c': case 'c':
singleQuery = strdup(optarg); singleQuery = strdup(optarg);
@ -2875,7 +2876,7 @@ main(int argc, char **argv)
#define COPYBUFSIZ 8192 #define COPYBUFSIZ 8192
static void static bool
handleCopyOut(PGresult *res, FILE *copystream) handleCopyOut(PGresult *res, FILE *copystream)
{ {
bool copydone; bool copydone;
@ -2911,12 +2912,12 @@ handleCopyOut(PGresult *res, FILE *copystream)
} }
} }
fflush(copystream); fflush(copystream);
PQendcopy(res->conn); return ! PQendcopy(res->conn);
} }
static void static bool
handleCopyIn(PGresult *res, const bool mustprompt, FILE *copystream) handleCopyIn(PGresult *res, const bool mustprompt, FILE *copystream)
{ {
bool copydone = false; bool copydone = false;
@ -2967,7 +2968,7 @@ handleCopyIn(PGresult *res, const bool mustprompt, FILE *copystream)
} }
PQputline(res->conn, "\n"); PQputline(res->conn, "\n");
} }
PQendcopy(res->conn); return ! PQendcopy(res->conn);
} }

View File

@ -7,14 +7,21 @@
# #
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/interfaces/Makefile,v 1.10 1998/05/29 17:00:29 momjian Exp $ # $Header: /cvsroot/pgsql/src/interfaces/Makefile,v 1.11 1998/08/17 03:50:19 scrappy Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
SRCDIR= .. SRCDIR= ..
include $(SRCDIR)/Makefile.global include $(SRCDIR)/Makefile.global
.DEFAULT all:
perl-makefile-dep :=
ifeq ($(USE_PERL), true)
perl-makefile-dep := perl5/Makefile
endif
.DEFAULT all: $(perl-makefile-dep)
$(MAKE) -C libpq $@ $(MAKE) -C libpq $@
# $(MAKE) -C ecpg $@ # $(MAKE) -C ecpg $@
ifeq ($(HAVE_Cplusplus), true) ifeq ($(HAVE_Cplusplus), true)
@ -26,6 +33,8 @@ ifeq ($(USE_TCL), true)
$(MAKE) -C libpgtcl $@ $(MAKE) -C libpgtcl $@
endif endif
ifeq ($(USE_PERL), true) ifeq ($(USE_PERL), true)
cd perl5 && perl Makefile.PL
$(MAKE) -C perl5 $@ $(MAKE) -C perl5 $@
endif endif
perl5/Makefile: perl5/Makefile.PL
cd perl5 && perl Makefile.PL

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.28 1998/07/09 03:32:09 scrappy Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.29 1998/08/17 03:50:22 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -485,9 +485,8 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
char *opt; char *opt;
int i; int i;
int tupno; int tupno;
char prearrayInd[MAX_MESSAGE_LEN];
char arrayInd[MAX_MESSAGE_LEN];
char *arrVar; char *arrVar;
char nameBuffer[256];
if (argc < 3 || argc > 5) { if (argc < 3 || argc > 5) {
Tcl_AppendResult(interp, "Wrong # of arguments\n",0); Tcl_AppendResult(interp, "Wrong # of arguments\n",0);
@ -522,6 +521,10 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
sprintf(interp->result, "%d", PQntuples(result)); sprintf(interp->result, "%d", PQntuples(result));
return TCL_OK; return TCL_OK;
} }
else if (strcmp(opt, "-numAttrs") == 0) {
sprintf(interp->result, "%d", PQnfields(result));
return TCL_OK;
}
else if (strcmp(opt, "-assign") == 0) { else if (strcmp(opt, "-assign") == 0) {
if (argc != 4) { if (argc != 4) {
Tcl_AppendResult(interp, "-assign option must be followed by a variable name",0); Tcl_AppendResult(interp, "-assign option must be followed by a variable name",0);
@ -530,17 +533,21 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
arrVar = argv[3]; arrVar = argv[3];
/* this assignment assigns the table of result tuples into a giant /* this assignment assigns the table of result tuples into a giant
array with the name given in the argument, array with the name given in the argument,
the indices of the array or (tupno,attrName)*/ the indices of the array or (tupno,attrName).
Note we expect field names not to exceed a few dozen characters,
so truncating to prevent buffer overflow shouldn't be a problem.
*/
for (tupno = 0; tupno<PQntuples(result); tupno++) { for (tupno = 0; tupno<PQntuples(result); tupno++) {
for (i=0;i<PQnfields(result);i++) { for (i=0;i<PQnfields(result);i++) {
sprintf(arrayInd, "%d,%s", tupno, PQfname(result,i)); sprintf(nameBuffer, "%d,%.200s", tupno, PQfname(result,i));
Tcl_SetVar2(interp, arrVar, arrayInd, if (Tcl_SetVar2(interp, arrVar, nameBuffer,
#ifdef TCL_ARRAYS #ifdef TCL_ARRAYS
tcl_value(PQgetvalue(result,tupno,i)), tcl_value(PQgetvalue(result,tupno,i)),
#else #else
PQgetvalue(result,tupno,i), PQgetvalue(result,tupno,i),
#endif #endif
TCL_LEAVE_ERR_MSG); TCL_LEAVE_ERR_MSG) == NULL)
return TCL_ERROR;
} }
} }
Tcl_AppendResult(interp, arrVar, 0); Tcl_AppendResult(interp, arrVar, 0);
@ -554,16 +561,24 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
arrVar = argv[3]; arrVar = argv[3];
/* this assignment assigns the table of result tuples into a giant /* this assignment assigns the table of result tuples into a giant
array with the name given in the argument, array with the name given in the argument,
the indices of the array or (tupno,attrName)*/ the indices of the array or (tupno,attrName).
Here, we still assume PQfname won't exceed 200 characters,
but we dare not make the same assumption about the data in field 0.
*/
for (tupno = 0; tupno<PQntuples(result); tupno++) { for (tupno = 0; tupno<PQntuples(result); tupno++) {
sprintf(prearrayInd,"%s",PQgetvalue(result,tupno,0)); const char *field0 = PQgetvalue(result,tupno,0);
char * workspace = malloc(strlen(field0) + 210);
for (i=1;i<PQnfields(result);i++) { for (i=1;i<PQnfields(result);i++) {
sprintf(arrayInd, "%s,%s", prearrayInd, PQfname(result,i)); sprintf(workspace, "%s,%.200s", field0, PQfname(result,i));
Tcl_SetVar2(interp, arrVar, arrayInd, if (Tcl_SetVar2(interp, arrVar, workspace,
PQgetvalue(result,tupno,i), PQgetvalue(result,tupno,i),
TCL_LEAVE_ERR_MSG); TCL_LEAVE_ERR_MSG) == NULL) {
free(workspace);
return TCL_ERROR;
} }
} }
free(workspace);
}
Tcl_AppendResult(interp, arrVar, 0); Tcl_AppendResult(interp, arrVar, 0);
return TCL_OK; return TCL_OK;
} }
@ -573,25 +588,13 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
return TCL_ERROR; return TCL_ERROR;
} }
tupno = atoi(argv[3]); tupno = atoi(argv[3]);
if (tupno < 0 || tupno >= PQntuples(result)) {
if (tupno >= PQntuples(result)) {
Tcl_AppendResult(interp, "argument to getTuple cannot exceed number of tuples - 1",0); Tcl_AppendResult(interp, "argument to getTuple cannot exceed number of tuples - 1",0);
return TCL_ERROR; return TCL_ERROR;
} }
#ifdef TCL_ARRAYS
for (i=0; i<PQnfields(result); i++) { for (i=0; i<PQnfields(result); i++) {
Tcl_AppendElement(interp, tcl_value(PQgetvalue(result,tupno,i)));
}
#else
/* Tcl_AppendResult(interp, PQgetvalue(result,tupno,0),NULL); */
Tcl_AppendElement(interp, PQgetvalue(result,tupno,0));
for (i=1;i<PQnfields(result);i++) {
/* Tcl_AppendResult(interp, " ", PQgetvalue(result,tupno,i),NULL);*/
Tcl_AppendElement(interp, PQgetvalue(result,tupno,i)); Tcl_AppendElement(interp, PQgetvalue(result,tupno,i));
} }
#endif
return TCL_OK; return TCL_OK;
} }
else if (strcmp(opt, "-tupleArray") == 0) { else if (strcmp(opt, "-tupleArray") == 0) {
@ -600,41 +603,42 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
return TCL_ERROR; return TCL_ERROR;
} }
tupno = atoi(argv[3]); tupno = atoi(argv[3]);
if (tupno < 0 || tupno >= PQntuples(result)) {
if (tupno >= PQntuples(result)) {
Tcl_AppendResult(interp, "argument to tupleArray cannot exceed number of tuples - 1",0); Tcl_AppendResult(interp, "argument to tupleArray cannot exceed number of tuples - 1",0);
return TCL_ERROR; return TCL_ERROR;
} }
for ( i = 0; i < PQnfields(result); i++) { for ( i = 0; i < PQnfields(result); i++) {
if (Tcl_SetVar2(interp, argv[4], PQfname(result, i), PQgetvalue(result, tupno, i), TCL_LEAVE_ERR_MSG) == NULL) { if (Tcl_SetVar2(interp, argv[4], PQfname(result, i),
PQgetvalue(result, tupno, i),
TCL_LEAVE_ERR_MSG) == NULL) {
return TCL_ERROR; return TCL_ERROR;
} }
} }
return TCL_OK; return TCL_OK;
} }
else if (strcmp(opt, "-attributes") == 0) { else if (strcmp(opt, "-attributes") == 0) {
Tcl_AppendResult(interp, PQfname(result,0),NULL); for (i=0;i<PQnfields(result);i++) {
for (i=1;i<PQnfields(result);i++) { Tcl_AppendElement(interp, PQfname(result,i));
Tcl_AppendResult(interp, " ", PQfname(result,i), NULL);
} }
return TCL_OK; return TCL_OK;
} }
else if (strcmp(opt, "-lAttributes") == 0) { else if (strcmp(opt, "-lAttributes") == 0) {
char buf[512];
Tcl_ResetResult(interp);
for (i = 0; i < PQnfields(result); i++) { for (i = 0; i < PQnfields(result); i++) {
sprintf(buf, "{%s} %ld %d", PQfname(result, i), /* start a sublist */
(long) PQftype(result, i), if (i > 0)
PQfsize(result, i)); Tcl_AppendResult(interp, " {", 0);
Tcl_AppendElement(interp, buf); else
Tcl_AppendResult(interp, "{", 0);
Tcl_AppendElement(interp, PQfname(result, i));
sprintf(nameBuffer, "%ld", (long) PQftype(result, i));
Tcl_AppendElement(interp, nameBuffer);
sprintf(nameBuffer, "%ld", (long) PQfsize(result, i));
Tcl_AppendElement(interp, nameBuffer);
/* end the sublist */
Tcl_AppendResult(interp, "}", 0);
} }
return TCL_OK; return TCL_OK;
} }
else if (strcmp(opt, "-numAttrs") == 0) {
sprintf(interp->result, "%d", PQnfields(result));
return TCL_OK;
}
else { else {
Tcl_AppendResult(interp, "Invalid option",0); Tcl_AppendResult(interp, "Invalid option",0);
goto Pg_result_errReturn; goto Pg_result_errReturn;
@ -649,9 +653,9 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
"\t-assign arrayVarName\n", "\t-assign arrayVarName\n",
"\t-assignbyidx arrayVarName\n", "\t-assignbyidx arrayVarName\n",
"\t-numTuples\n", "\t-numTuples\n",
"\t-numAttrs\n"
"\t-attributes\n" "\t-attributes\n"
"\t-lAttributes\n" "\t-lAttributes\n"
"\t-numAttrs\n"
"\t-getTuple tupleNumber\n", "\t-getTuple tupleNumber\n",
"\t-tupleArray tupleNumber arrayVarName\n", "\t-tupleArray tupleNumber arrayVarName\n",
"\t-clear\n", "\t-clear\n",

View File

@ -12,7 +12,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.11 1998/06/16 04:10:17 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.12 1998/08/17 03:50:26 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -43,7 +43,10 @@ static int PgEndCopy(Pg_ConnectionId *connid, int *errorCodePtr)
} }
/* /*
* Called when reading data (via gets) for a copy <rel> to stdout * Called when reading data (via gets) for a copy <rel> to stdout.
*
* NOTE: this routine knows way more than it ought to about libpq's
* internal buffering mechanisms.
*/ */
int PgInputProc(DRIVER_INPUT_PROTO) int PgInputProc(DRIVER_INPUT_PROTO)
{ {
@ -62,10 +65,10 @@ int PgInputProc(DRIVER_INPUT_PROTO)
} }
/* Try to load any newly arrived data */ /* Try to load any newly arrived data */
errno = 0; conn->errorMessage[0] = '\0';
PQconsumeInput(conn);
if (pqReadData(conn) < 0) { if (conn->errorMessage[0]) {
*errorCodePtr = errno ? errno : EIO; *errorCodePtr = EIO;
return -1; return -1;
} }
@ -80,8 +83,8 @@ int PgInputProc(DRIVER_INPUT_PROTO)
conn->inCursor = conn->inStart; conn->inCursor = conn->inStart;
avail = bufSize; avail = bufSize;
while (avail > 0 && while (avail > 0 && conn->inCursor < conn->inEnd) {
pqGetc(&c, conn) == 0) { c = conn->inBuffer[conn->inCursor++];
*buf++ = c; *buf++ = c;
--avail; --avail;
if (c == '\n') { if (c == '\n') {
@ -130,10 +133,12 @@ int PgOutputProc(DRIVER_OUTPUT_PROTO)
return -1; return -1;
} }
errno = 0; conn->errorMessage[0] = '\0';
if (pqPutnchar(buf, bufSize, conn)) { PQputnbytes(conn, buf, bufSize);
*errorCodePtr = errno ? errno : EIO;
if (conn->errorMessage[0]) {
*errorCodePtr = EIO;
return -1; return -1;
} }
@ -141,7 +146,6 @@ int PgOutputProc(DRIVER_OUTPUT_PROTO)
* in a single operation; maybe not such a good assumption? * in a single operation; maybe not such a good assumption?
*/ */
if (bufSize >= 3 && strncmp(&buf[bufSize-3], "\\.\n", 3) == 0) { if (bufSize >= 3 && strncmp(&buf[bufSize-3], "\\.\n", 3) == 0) {
(void) pqFlush(conn);
if (PgEndCopy(connid, errorCodePtr) == -1) if (PgEndCopy(connid, errorCodePtr) == -1)
return -1; return -1;
} }
@ -423,7 +427,7 @@ PgGetConnByResultId(Tcl_Interp *interp, char *resid_c)
*mark = '\0'; *mark = '\0';
conn_chan = Tcl_GetChannel(interp, resid_c, 0); conn_chan = Tcl_GetChannel(interp, resid_c, 0);
*mark = '.'; *mark = '.';
if(conn_chan && Tcl_GetChannelType(conn_chan) != &Pg_ConnType) { if(conn_chan && Tcl_GetChannelType(conn_chan) == &Pg_ConnType) {
Tcl_SetResult(interp, Tcl_GetChannelName(conn_chan), TCL_VOLATILE); Tcl_SetResult(interp, Tcl_GetChannelName(conn_chan), TCL_VOLATILE);
return TCL_OK; return TCL_OK;
} }

View File

@ -7,7 +7,7 @@
# #
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/interfaces/libpq/Attic/Makefile.in,v 1.25 1998/07/26 04:31:35 scrappy Exp $ # $Header: /cvsroot/pgsql/src/interfaces/libpq/Attic/Makefile.in,v 1.26 1998/08/17 03:50:29 scrappy Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -87,7 +87,7 @@ ifeq ($(PORTNAME), hpux)
CFLAGS += $(CFLAGS_SL) CFLAGS += $(CFLAGS_SL)
endif endif
all: libpq.a $(shlib) c.h all: libpq.a $(shlib)
libpq.a: $(OBJS) libpq.a: $(OBJS)
ifdef MK_NO_LORDER ifdef MK_NO_LORDER
@ -97,8 +97,6 @@ else
endif endif
$(RANLIB) libpq.a $(RANLIB) libpq.a
fe-lobj.o: $(SRCDIR)/backend/fmgr.h
# We need to compile this with special options for shared libs, # We need to compile this with special options for shared libs,
# so we can't use the object in $(SRCDIR)/backend # so we can't use the object in $(SRCDIR)/backend
dllist.c: $(SRCDIR)/backend/lib/dllist.c dllist.c: $(SRCDIR)/backend/lib/dllist.c
@ -120,6 +118,8 @@ endif
# The following rules cause dependencies in the backend directory to # The following rules cause dependencies in the backend directory to
# get made if they don't exist, but don't cause them to get remade if they # get made if they don't exist, but don't cause them to get remade if they
# are out of date. # are out of date.
fe-lobj.o: $(SRCDIR)/backend/fmgr.h
$(SRCDIR)/backend/fmgr.h: $(SRCDIR)/backend/fmgr.h:
$(MAKE) -C $(SRCDIR)/backend fmgr.h $(MAKE) -C $(SRCDIR)/backend fmgr.h
@ -128,12 +128,6 @@ $(shlib): $(OBJS)
ln -sf $@ libpq.so ln -sf $@ libpq.so
c.h: $(SRCDIR)/include/c.h
rm -f c.h
echo "#undef PORTNAME" > c.h
echo "#define PORTNAME $(PORTNAME)" >> c.h
cat $(SRCDIR)/include/c.h >> c.h
.PHONY: beforeinstall-headers install-headers .PHONY: beforeinstall-headers install-headers
.PHONY: install install-libpq install-shlib-dep .PHONY: install install-libpq install-shlib-dep
@ -142,15 +136,17 @@ install: install-headers install-libpq $(install-shlib-dep)
# Many of the headers we install below have nothing to do with libpq, # Many of the headers we install below have nothing to do with libpq,
# so should be installed by someone else. # so should be installed by someone else.
# #
install-headers: beforeinstall-headers c.h \ install-headers: beforeinstall-headers $(SRCDIR)/include/c.h \
$(SRCDIR)/include/postgres.h $(SRCDIR)/include/postgres_ext.h \ $(SRCDIR)/include/postgres.h $(SRCDIR)/include/postgres_ext.h \
$(SRCDIR)/include/config.h $(SRCDIR)/include/libpq/pqcomm.h \ $(SRCDIR)/include/config.h $(SRCDIR)/include/libpq/pqcomm.h \
$(SRCDIR)/include/libpq/libpq-fs.h $(SRCDIR)/include/lib/dllist.h \ $(SRCDIR)/include/libpq/libpq-fs.h $(SRCDIR)/include/lib/dllist.h \
$(SRCDIR)/include/utils/geo_decls.h libpq-fe.h $(SRCDIR)/include/utils/geo_decls.h libpq-fe.h libpq-int.h
$(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/os.h \ $(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/os.h \
$(HEADERDIR)/os.h $(HEADERDIR)/os.h
$(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/config.h \ $(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/config.h \
$(HEADERDIR)/config.h $(HEADERDIR)/config.h
$(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/c.h \
$(HEADERDIR)/c.h
$(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/postgres.h \ $(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/postgres.h \
$(HEADERDIR)/postgres.h $(HEADERDIR)/postgres.h
$(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/postgres_ext.h \ $(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/postgres_ext.h \
@ -174,19 +170,17 @@ install-headers: beforeinstall-headers c.h \
$(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/commands/trigger.h \ $(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/commands/trigger.h \
$(HEADERDIR)/commands/trigger.h $(HEADERDIR)/commands/trigger.h
$(INSTALL) $(INSTLOPTS) libpq-fe.h $(HEADERDIR)/libpq-fe.h $(INSTALL) $(INSTLOPTS) libpq-fe.h $(HEADERDIR)/libpq-fe.h
$(INSTALL) $(INSTLOPTS) libpq-int.h $(HEADERDIR)/libpq-int.h
ifeq ($(PORTNAME), hpux) ifeq ($(PORTNAME), hpux)
$(INSTALL) $(INSTLOPTS) $(SRCDIR)/backend/port/hpux/fixade.h \ $(INSTALL) $(INSTLOPTS) $(SRCDIR)/backend/port/hpux/fixade.h \
$(HEADERDIR)/port/hpux/fixade.h $(HEADERDIR)/port/hpux/fixade.h
endif endif
$(INSTALL) $(INSTLOPTS) c.h $(HEADERDIR)/c.h
beforeinstall-headers: beforeinstall-headers:
@if [ ! -d $(HEADERDIR) ]; then mkdir $(HEADERDIR); fi @if [ ! -d $(HEADERDIR) ]; then mkdir $(HEADERDIR); fi
@if [ ! -d $(HEADERDIR)/port ]; then mkdir $(HEADERDIR)/port; fi @if [ ! -d $(HEADERDIR)/port ]; then mkdir $(HEADERDIR)/port; fi
@if [ ! -d $(HEADERDIR)/port/$(PORTNAME) ]; \ @if [ ! -d $(HEADERDIR)/port/$(PORTNAME) ]; \
then mkdir $(HEADERDIR)/port/$(PORTNAME); fi then mkdir $(HEADERDIR)/port/$(PORTNAME); fi
@if [ ! -d $(HEADERDIR)/include ]; \
then mkdir $(HEADERDIR)/include; fi
@if [ ! -d $(HEADERDIR)/lib ]; \ @if [ ! -d $(HEADERDIR)/lib ]; \
then mkdir $(HEADERDIR)/lib; fi then mkdir $(HEADERDIR)/lib; fi
@if [ ! -d $(HEADERDIR)/libpq ]; \ @if [ ! -d $(HEADERDIR)/libpq ]; \
@ -213,7 +207,8 @@ depend dep:
.PHONY: clean .PHONY: clean
clean: clean:
rm -f libpq.a $(shlib) $(OBJS) c.h dllist.c libpq.so rm -f libpq.a $(shlib) libpq.so $(OBJS)
rm -f dllist.c common.c wchar.c conv.c
ifeq (depend,$(wildcard depend)) ifeq (depend,$(wildcard depend))
include depend include depend

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.21 1998/08/09 02:59:25 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.22 1998/08/17 03:50:31 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -24,28 +24,26 @@
* *
* *
*/ */
#include "libpq-fe.h"
#include "libpq-int.h"
#include "fe-auth.h"
#include "postgres.h"
#ifdef WIN32 #ifdef WIN32
#include "win32.h" #include "win32.h"
#else #else
#include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/param.h> /* for MAXHOSTNAMELEN on most */ #include <sys/param.h> /* for MAXHOSTNAMELEN on most */
#include <sys/types.h>
#ifndef MAXHOSTNAMELEN #ifndef MAXHOSTNAMELEN
#include <netdb.h> /* for MAXHOSTNAMELEN on some */ #include <netdb.h> /* for MAXHOSTNAMELEN on some */
#endif #endif
#if !defined(NO_UNISTD_H)
#include <unistd.h> #include <unistd.h>
#endif
#include <pwd.h> #include <pwd.h>
#endif /* WIN32 */ #endif /* WIN32 */
#include "postgres.h"
#include "libpq/pqcomm.h"
#include "libpq-fe.h"
#include "fe-auth.h"
#include "fe-connect.h"
#ifdef HAVE_CRYPT_H #ifdef HAVE_CRYPT_H
#include <crypt.h> #include <crypt.h>
#endif #endif
@ -469,7 +467,7 @@ pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
if (areq == AUTH_REQ_CRYPT) if (areq == AUTH_REQ_CRYPT)
password = crypt(password, conn->salt); password = crypt(password, conn->salt);
return packetSend(conn, password, strlen(password) + 1); return pqPacketSend(conn, password, strlen(password) + 1);
} }
/* /*

View File

@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: fe-auth.h,v 1.8 1998/01/29 03:24:21 scrappy Exp $ * $Id: fe-auth.h,v 1.9 1998/08/17 03:50:33 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -14,6 +14,7 @@
#define FE_AUTH_H #define FE_AUTH_H
#include "libpq-fe.h" #include "libpq-fe.h"
#include "libpq-int.h"
/*---------------------------------------------------------------- /*----------------------------------------------------------------
@ -33,8 +34,10 @@
extern int extern int
fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname, fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
const char *password, char *PQerromsg); const char *password, char *PQerrormsg);
extern MsgType fe_getauthsvc(char *PQerrormsg);
extern void fe_setauthsvc(const char *name, char *PQerrormsg); extern void fe_setauthsvc(const char *name, char *PQerrormsg);
extern char *fe_getauthname(char *PQerrormsg);
#define PG_KRB4_VERSION "PGVER4.1" /* at most KRB_SENDAUTH_VLEN chars */ #define PG_KRB4_VERSION "PGVER4.1" /* at most KRB_SENDAUTH_VLEN chars */
#define PG_KRB5_VERSION "PGVER5.1" #define PG_KRB5_VERSION "PGVER5.1"

View File

@ -7,35 +7,31 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.78 1998/08/09 02:59:26 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.79 1998/08/17 03:50:34 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "libpq-fe.h"
#include "libpq-int.h"
#include "fe-auth.h"
#include "postgres.h"
#include <stdlib.h> #include <stdlib.h>
#include <sys/types.h>
#ifdef WIN32 #ifdef WIN32
#include "win32.h" #include "win32.h"
#else #else
#include <sys/socket.h> #if !defined(NO_UNISTD_H)
#include <unistd.h> #include <unistd.h>
#endif
#include <netdb.h> #include <netdb.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#endif #endif
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <ctype.h> /* for isspace() */ #include <ctype.h> /* for isspace() */
#include "postgres.h"
#include "fe-auth.h"
#include "fe-connect.h"
#include "libpq-fe.h"
#ifndef HAVE_STRDUP #ifndef HAVE_STRDUP
#include "strdup.h" #include "strdup.h"
#endif #endif
@ -113,7 +109,7 @@ static PQconninfoOption PQconninfoOptions[] = {
NULL, NULL, 0} NULL, NULL, 0}
}; };
struct EnvironmentOptions static struct EnvironmentOptions
{ {
const char *envName, const char *envName,
*pgName; *pgName;
@ -496,7 +492,7 @@ connectDB(PGconn *conn)
struct hostent *hp; struct hostent *hp;
StartupPacket sp; StartupPacket sp;
AuthRequest areq; AuthRequest areq;
int laddrlen = sizeof(SockAddr); int laddrlen;
int portno, int portno,
family; family;
char beresp; char beresp;
@ -514,7 +510,7 @@ connectDB(PGconn *conn)
MemSet((char *) &sp, 0, sizeof(StartupPacket)); MemSet((char *) &sp, 0, sizeof(StartupPacket));
sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_LATEST); sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_LIBPQ);
strncpy(sp.user, conn->pguser, SM_USER); strncpy(sp.user, conn->pguser, SM_USER);
strncpy(sp.database, conn->dbName, SM_DATABASE); strncpy(sp.database, conn->dbName, SM_DATABASE);
@ -626,6 +622,7 @@ connectDB(PGconn *conn)
} }
/* Fill in the client address */ /* Fill in the client address */
laddrlen = sizeof(conn->laddr);
if (getsockname(conn->sock, &conn->laddr.sa, &laddrlen) < 0) if (getsockname(conn->sock, &conn->laddr.sa, &laddrlen) < 0)
{ {
(void) sprintf(conn->errorMessage, (void) sprintf(conn->errorMessage,
@ -640,7 +637,7 @@ connectDB(PGconn *conn)
/* Send the startup packet. */ /* Send the startup packet. */
if (packetSend(conn, (char *) &sp, sizeof(StartupPacket)) != STATUS_OK) if (pqPacketSend(conn, (char *) &sp, sizeof(StartupPacket)) != STATUS_OK)
{ {
sprintf(conn->errorMessage, sprintf(conn->errorMessage,
"connectDB() -- couldn't send startup packet: errno=%d\n%s\n", "connectDB() -- couldn't send startup packet: errno=%d\n%s\n",
@ -786,7 +783,7 @@ PQsetenv(PGconn *conn)
char setQuery[80]; /* mjl: size okay? XXX */ char setQuery[80]; /* mjl: size okay? XXX */
#ifdef MULTIBYTE #ifdef MULTIBYTE
char *envname = "PGCLIENTENCODING"; char *envname = "PGCLIENTENCODING";
char envbuf[64]; static char envbuf[64]; /* big enough? */
char *env; char *env;
char *encoding = 0; char *encoding = 0;
PGresult *rtn; PGresult *rtn;
@ -875,7 +872,7 @@ freePGconn(PGconn *conn)
{ {
if (!conn) if (!conn)
return; return;
PQclearAsyncResult(conn); /* deallocate result and curTuple */ pqClearAsyncResult(conn); /* deallocate result and curTuple */
if (conn->sock >= 0) if (conn->sock >= 0)
#ifdef WIN32 #ifdef WIN32
closesocket(conn->sock); closesocket(conn->sock);
@ -919,20 +916,14 @@ closePGconn(PGconn *conn)
{ {
/* /*
* Try to send "close connection" message to backend. * Try to send "close connection" message to backend.
* BUT: backend might have already closed connection. * Ignore any error.
* To avoid being killed by SIGPIPE, we need to detect this before * Note: this routine used to go to substantial lengths to avoid
* writing. Check for "read ready" condition which indicates EOF. * getting SIGPIPE'd if the connection were already closed.
* Now we rely on pqFlush to avoid the signal.
*/ */
while (pqReadReady(conn)) {
if (pqReadData(conn) < 0)
break;
}
if (conn->sock >= 0) {
/* Should be safe now... */
(void) pqPuts("X", conn); (void) pqPuts("X", conn);
(void) pqFlush(conn); (void) pqFlush(conn);
} }
}
/* /*
* Close the connection, reset all transient state, flush I/O buffers. * Close the connection, reset all transient state, flush I/O buffers.
@ -947,7 +938,7 @@ closePGconn(PGconn *conn)
conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just
* absent */ * absent */
conn->asyncStatus = PGASYNC_IDLE; conn->asyncStatus = PGASYNC_IDLE;
PQclearAsyncResult(conn); /* deallocate result and curTuple */ pqClearAsyncResult(conn); /* deallocate result and curTuple */
if (conn->lobjfuncs) if (conn->lobjfuncs)
free(conn->lobjfuncs); free(conn->lobjfuncs);
conn->lobjfuncs = NULL; conn->lobjfuncs = NULL;
@ -1080,14 +1071,14 @@ cancel_errReturn:
/* /*
* PacketSend() -- send a single-packet message. * pqPacketSend() -- send a single-packet message.
* this is like PacketSend(), defined in backend/libpq/pqpacket.c * this is like PacketSend(), defined in backend/libpq/pqpacket.c
* *
* RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise. * RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise.
* SIDE_EFFECTS: may block. * SIDE_EFFECTS: may block.
*/ */
int int
packetSend(PGconn *conn, const char *buf, size_t len) pqPacketSend(PGconn *conn, const char *buf, size_t len)
{ {
/* Send the total packet size. */ /* Send the total packet size. */

View File

@ -7,24 +7,25 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.61 1998/08/09 02:59:27 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.62 1998/08/17 03:50:35 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "libpq-fe.h"
#include "libpq-int.h"
#include "postgres.h"
#ifdef WIN32 #ifdef WIN32
#include "win32.h" #include "win32.h"
#endif #else
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#if !defined(NO_UNISTD_H) #if !defined(NO_UNISTD_H)
#include <unistd.h> #include <unistd.h>
#endif #endif
#include "postgres.h" #endif
#include "libpq/pqcomm.h" #include <stdlib.h>
#include "libpq-fe.h" #include <string.h>
#include <errno.h>
#include <ctype.h>
/* the rows array in a PGresGroup has to grow to accommodate the rows */ /* the rows array in a PGresGroup has to grow to accommodate the rows */
@ -32,7 +33,7 @@
#define TUPARR_GROW_BY 100 #define TUPARR_GROW_BY 100
/* keep this in same order as ExecStatusType in libpq-fe.h */ /* keep this in same order as ExecStatusType in libpq-fe.h */
const char *pgresStatus[] = { const char * const pgresStatus[] = {
"PGRES_EMPTY_QUERY", "PGRES_EMPTY_QUERY",
"PGRES_COMMAND_OK", "PGRES_COMMAND_OK",
"PGRES_TUPLES_OK", "PGRES_TUPLES_OK",
@ -144,7 +145,7 @@ freeTuple(PGresAttValue *tuple, int numAttributes)
*/ */
void void
PQclearAsyncResult(PGconn *conn) pqClearAsyncResult(PGconn *conn)
{ {
/* Get rid of incomplete result and any not-yet-added tuple */ /* Get rid of incomplete result and any not-yet-added tuple */
if (conn->result) if (conn->result)
@ -210,25 +211,6 @@ PQsendQuery(PGconn *conn, const char *query)
return 0; return 0;
} }
if (conn->asyncStatus != PGASYNC_IDLE)
{
sprintf(conn->errorMessage,
"PQsendQuery() -- another query already in progress.");
return 0;
}
/* Check for pending input (asynchronous Notice or Notify messages);
* also detect the case that the backend just closed the connection.
* Note: we have to loop if the first call to pqReadData successfully
* reads some data, since in that case pqReadData won't notice whether
* the connection is now closed.
*/
while (pqReadReady(conn)) {
if (pqReadData(conn) < 0)
return 0; /* errorMessage already set */
parseInput(conn); /* deal with Notice or Notify, if any */
}
/* Don't try to send if we know there's no live connection. */ /* Don't try to send if we know there's no live connection. */
if (conn->status != CONNECTION_OK) if (conn->status != CONNECTION_OK)
{ {
@ -236,6 +218,13 @@ PQsendQuery(PGconn *conn, const char *query)
"to the backend.\n"); "to the backend.\n");
return 0; return 0;
} }
/* Can't send while already busy, either. */
if (conn->asyncStatus != PGASYNC_IDLE)
{
sprintf(conn->errorMessage,
"PQsendQuery() -- another query already in progress.");
return 0;
}
/* clear the error string */ /* clear the error string */
conn->errorMessage[0] = '\0'; conn->errorMessage[0] = '\0';
@ -361,7 +350,7 @@ parseInput(PGconn *conn)
if (pqGets(conn->asyncErrorMessage,ERROR_MSG_LENGTH,conn)) if (pqGets(conn->asyncErrorMessage,ERROR_MSG_LENGTH,conn))
return; return;
/* delete any partially constructed result */ /* delete any partially constructed result */
PQclearAsyncResult(conn); pqClearAsyncResult(conn);
/* we leave result NULL while setting asyncStatus=READY; /* we leave result NULL while setting asyncStatus=READY;
* this signals an error condition to PQgetResult. * this signals an error condition to PQgetResult.
*/ */
@ -468,7 +457,7 @@ parseInput(PGconn *conn)
/* Discard the unexpected message; good idea?? */ /* Discard the unexpected message; good idea?? */
conn->inStart = conn->inEnd; conn->inStart = conn->inEnd;
/* delete any partially constructed result */ /* delete any partially constructed result */
PQclearAsyncResult(conn); pqClearAsyncResult(conn);
conn->asyncStatus = PGASYNC_READY; conn->asyncStatus = PGASYNC_READY;
return; return;
} /* switch on protocol character */ } /* switch on protocol character */
@ -583,7 +572,7 @@ getAnotherTuple(PGconn *conn, int binary)
{ {
sprintf(conn->asyncErrorMessage, sprintf(conn->asyncErrorMessage,
"getAnotherTuple() -- null-values bitmap is too large\n"); "getAnotherTuple() -- null-values bitmap is too large\n");
PQclearAsyncResult(conn); pqClearAsyncResult(conn);
conn->asyncStatus = PGASYNC_READY; conn->asyncStatus = PGASYNC_READY;
/* Discard the broken message */ /* Discard the broken message */
conn->inStart = conn->inEnd; conn->inStart = conn->inEnd;
@ -688,7 +677,7 @@ PQgetResult(PGconn *conn)
if (pqWait(TRUE, FALSE, conn) || if (pqWait(TRUE, FALSE, conn) ||
pqReadData(conn) < 0) pqReadData(conn) < 0)
{ {
PQclearAsyncResult(conn); pqClearAsyncResult(conn);
conn->asyncStatus = PGASYNC_IDLE; conn->asyncStatus = PGASYNC_IDLE;
/* conn->errorMessage has been set by pqWait or pqReadData. */ /* conn->errorMessage has been set by pqWait or pqReadData. */
return makeEmptyPGresult(conn, PGRES_FATAL_ERROR); return makeEmptyPGresult(conn, PGRES_FATAL_ERROR);
@ -939,6 +928,16 @@ PQputline(PGconn *conn, const char *s)
(void) pqPutnchar(s, strlen(s), conn); (void) pqPutnchar(s, strlen(s), conn);
} }
/*
* PQputnbytes -- like PQputline, but buffer need not be null-terminated.
*/
void
PQputnbytes(PGconn *conn, const char *buffer, int nbytes)
{
if (conn && conn->sock >= 0)
(void) pqPutnchar(buffer, nbytes, conn);
}
/* /*
* PQendcopy * PQendcopy
* After completing the data transfer portion of a copy in/out, * After completing the data transfer portion of a copy in/out,
@ -968,6 +967,7 @@ PQendcopy(PGconn *conn)
/* Return to active duty */ /* Return to active duty */
conn->asyncStatus = PGASYNC_BUSY; conn->asyncStatus = PGASYNC_BUSY;
conn->errorMessage[0] = '\0';
/* Wait for the completion response */ /* Wait for the completion response */
result = PQgetResult(conn); result = PQgetResult(conn);
@ -986,9 +986,11 @@ PQendcopy(PGconn *conn)
*/ */
PQclear(result); PQclear(result);
sprintf(conn->errorMessage, "PQendcopy: resetting connection\n"); if (conn->errorMessage[0])
DONOTICE(conn, conn->errorMessage); DONOTICE(conn, conn->errorMessage);
DONOTICE(conn, "PQendcopy: resetting connection\n");
PQreset(conn); PQreset(conn);
return 1; return 1;
@ -1344,23 +1346,40 @@ PQcmdStatus(PGresult *res)
const char * const char *
PQoidStatus(PGresult *res) PQoidStatus(PGresult *res)
{ {
static char oidStatus[32] = {0}; char *p, *e, *scan;
int slen, olen;
if (!res) if (!res)
return ""; return "";
oidStatus[0] = 0; if (strncmp(res->cmdStatus, "INSERT ", 7) != 0)
return "";
if (strncmp(res->cmdStatus, "INSERT ", 7) == 0) /* The cmdStatus string looks like
{ * INSERT oid count\0
char *p = res->cmdStatus + 7; * In order to be able to return an ordinary C string without
char *e; * damaging the result for PQcmdStatus or PQcmdTuples, we copy
* the oid part of the string to just after the null, so that
* cmdStatus looks like
* INSERT oid count\0oid\0
* ^ our return value points here
* Pretty klugy eh? This routine should've just returned an Oid value.
*/
for (e = p; *e != ' ' && *e;) slen = strlen(res->cmdStatus);
e++; p = res->cmdStatus + 7; /* where oid is now */
sprintf(oidStatus, "%.*s", e - p, p); e = res->cmdStatus + slen + 1; /* where to put the oid string */
}
return oidStatus; for (scan = p; *scan && *scan != ' '; )
scan++;
olen = scan - p;
if (slen + olen + 2 > sizeof(res->cmdStatus))
return ""; /* something very wrong if it doesn't fit */
strncpy(e, p, olen);
e[olen] = '\0';
return e;
} }
/* /*

View File

@ -7,24 +7,29 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.14 1998/07/03 04:24:14 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.15 1998/08/17 03:50:37 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "libpq-fe.h"
#include "libpq-int.h"
#include "postgres.h"
#ifdef WIN32 #ifdef WIN32
#include "win32.h" #include "win32.h"
#include <io.h> #include <io.h>
#else #else
#if !defined(NO_UNISTD_H)
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <stdio.h> #endif
#include <string.h> #include <string.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h>
#include "postgres.h" #include "libpq/libpq-fs.h" /* must come after sys/stat.h */
#include "libpq-fe.h"
#include "libpq/libpq-fs.h"
#define LO_BUFSIZE 1024 #define LO_BUFSIZE 1024

View File

@ -24,15 +24,20 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.17 1998/08/09 02:59:29 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.18 1998/08/17 03:50:38 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "libpq-fe.h"
#include "libpq-int.h"
#include "postgres.h"
#include "pqsignal.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <signal.h>
#include <time.h> #include <time.h>
#ifdef WIN32 #ifdef WIN32
#include "win32.h" #include "win32.h"
@ -42,13 +47,11 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#endif /* WIN32 */ #endif /* WIN32 */
#include <sys/types.h> /* for fd_set stuff */
#ifdef HAVE_SYS_SELECT_H #ifdef HAVE_SYS_SELECT_H
#include <sys/select.h> #include <sys/select.h>
#endif #endif
#include "postgres.h"
#include "libpq-fe.h"
#define DONOTICE(conn,message) \ #define DONOTICE(conn,message) \
((*(conn)->noticeHook) ((conn)->noticeArg, (message))) ((*(conn)->noticeHook) ((conn)->noticeArg, (message)))
@ -273,7 +276,7 @@ pqPutInt(int value, int bytes, PGconn *conn)
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
/* pqReadReady: is select() saying the file is ready to read? /* pqReadReady: is select() saying the file is ready to read?
*/ */
int static int
pqReadReady(PGconn *conn) pqReadReady(PGconn *conn)
{ {
fd_set input_mask; fd_set input_mask;
@ -451,7 +454,17 @@ pqFlush(PGconn *conn)
while (len > 0) while (len > 0)
{ {
/* Prevent being SIGPIPEd if backend has closed the connection. */
#ifndef WIN32
pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
#endif
int sent = send(conn->sock, ptr, len, 0); int sent = send(conn->sock, ptr, len, 0);
#ifndef WIN32
pqsignal(SIGPIPE, oldsighandler);
#endif
if (sent < 0) if (sent < 0)
{ {
/* Anything except EAGAIN or EWOULDBLOCK is trouble */ /* Anything except EAGAIN or EWOULDBLOCK is trouble */

View File

@ -9,31 +9,31 @@
* didn't really belong there. * didn't really belong there.
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-print.c,v 1.9 1998/08/09 02:59:30 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-print.c,v 1.10 1998/08/17 03:50:39 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "libpq-fe.h"
#include "libpq-int.h"
#include "postgres.h"
#include "pqsignal.h"
#ifdef WIN32 #ifdef WIN32
#include "win32.h" #include "win32.h"
#endif #else
#include <postgres.h> #if !defined(NO_UNISTD_H)
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#ifndef WIN32
#include <unistd.h> #include <unistd.h>
#include <sys/ioctl.h>
#endif #endif
#include "libpq/pqsignal.h" #include <sys/ioctl.h>
#include "libpq-fe.h"
#ifndef WIN32
#ifndef HAVE_TERMIOS_H #ifndef HAVE_TERMIOS_H
#include <sys/termios.h> #include <sys/termios.h>
#else #else
#include <termios.h> #include <termios.h>
#endif #endif
#endif /* WIN32 */ #endif /* WIN32 */
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#ifdef MULTIBYTE #ifdef MULTIBYTE
#include "mb/pg_wchar.h" #include "mb/pg_wchar.h"

View File

@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: libpq-fe.h,v 1.37 1998/08/09 02:59:31 momjian Exp $ * $Id: libpq-fe.h,v 1.38 1998/08/17 03:50:40 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -20,12 +20,15 @@ extern "C"
#endif #endif
#include <stdio.h> #include <stdio.h>
/* these wouldn't need to be included if PGSockAddr weren't exported: */
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
/* ---------------- /* ----------------
* include stuff common to fe and be * include stuff common to fe and be
* ---------------- * ----------------
*/ */
#include "postgres_ext.h" #include "postgres_ext.h"
#include "libpq/pqcomm.h"
#include "lib/dllist.h" #include "lib/dllist.h"
/* Application-visible enum types */ /* Application-visible enum types */
@ -53,7 +56,7 @@ extern "C"
} ExecStatusType; } ExecStatusType;
/* string descriptions of the ExecStatusTypes */ /* string descriptions of the ExecStatusTypes */
extern const char *pgresStatus[]; extern const char * const pgresStatus[];
/* /*
* POSTGRES backend dependent Constants. * POSTGRES backend dependent Constants.
@ -61,9 +64,6 @@ extern "C"
/* ERROR_MSG_LENGTH should really be the same as ELOG_MAXLEN in utils/elog.h*/ /* ERROR_MSG_LENGTH should really be the same as ELOG_MAXLEN in utils/elog.h*/
#define ERROR_MSG_LENGTH 4096 #define ERROR_MSG_LENGTH 4096
#define COMMAND_LENGTH 20
#define REMARK_LENGTH 80
#define PORTAL_NAME_LENGTH 16
#define CMDSTATUS_LEN 40 #define CMDSTATUS_LEN 40
/* PGresult and the subsidiary types PGresAttDesc, PGresAttValue /* PGresult and the subsidiary types PGresAttDesc, PGresAttValue
@ -85,7 +85,8 @@ extern "C"
ASCII tuples are guaranteed to be null-terminated ASCII tuples are guaranteed to be null-terminated
For binary tuples, the first four bytes of the value is the size, For binary tuples, the first four bytes of the value is the size,
and the bytes afterwards are the value. The binary value is and the bytes afterwards are the value. The binary value is
not guaranteed to be null-terminated. In fact, it can have embedded nulls*/ not guaranteed to be null-terminated. In fact, it can have embedded nulls
*/
#define NULL_LEN (-1) /* pg_result len for NULL value */ #define NULL_LEN (-1) /* pg_result len for NULL value */
@ -134,6 +135,15 @@ extern "C"
PGASYNC_COPY_OUT /* Copy Out data transfer in progress */ PGASYNC_COPY_OUT /* Copy Out data transfer in progress */
} PGAsyncStatusType; } PGAsyncStatusType;
/* generic socket address type for PGconn connection information.
* Really shouldn't be visible to users */
typedef union PGSockAddr
{
struct sockaddr sa;
struct sockaddr_in in;
struct sockaddr_un un;
} PGSockAddr;
/* large-object-access data ... allocated only if large-object code is used. /* large-object-access data ... allocated only if large-object code is used.
* Really shouldn't be visible to users */ * Really shouldn't be visible to users */
typedef struct pgLobjfuncs typedef struct pgLobjfuncs
@ -150,7 +160,9 @@ extern "C"
} PGlobjfuncs; } PGlobjfuncs;
/* PGconn encapsulates a connection to the backend. /* PGconn encapsulates a connection to the backend.
* XXX contents of this struct really shouldn't be visible to applications * XXX contents of this struct really shouldn't be visible to applications,
* but we might break some existing applications if we tried to make it
* completely opaque.
*/ */
typedef struct pg_conn typedef struct pg_conn
{ {
@ -179,8 +191,8 @@ extern "C"
/* Connection data */ /* Connection data */
int sock; /* Unix FD for socket, -1 if not connected */ int sock; /* Unix FD for socket, -1 if not connected */
SockAddr laddr; /* Local address */ PGSockAddr laddr; /* Local address */
SockAddr raddr; /* Remote address */ PGSockAddr raddr; /* Remote address */
int raddr_len; /* Length of remote address */ int raddr_len; /* Length of remote address */
/* Miscellaneous stuff */ /* Miscellaneous stuff */
@ -213,14 +225,14 @@ extern "C"
char asyncErrorMessage[ERROR_MSG_LENGTH]; char asyncErrorMessage[ERROR_MSG_LENGTH];
} PGconn; } PGconn;
typedef char pqbool;
/* /*
* We can't use the conventional "bool", because we are designed to be * We can't use the conventional "bool", because we are designed to be
* included in a user's program, and user may already have that type * included in a user's program, and user may already have that type
* defined. Pqbool, on the other hand, is unlikely to be used. * defined. Pqbool, on the other hand, is unlikely to be used.
*/ */
typedef char pqbool;
/* Print options for PQprint() */ /* Print options for PQprint() */
typedef struct _PQprintOpt typedef struct _PQprintOpt
@ -255,7 +267,7 @@ extern "C"
} PQArgBlock; } PQArgBlock;
/* ---------------- /* ----------------
* Structure for the conninfo parameter definitions of PQconnectdb() * Structure for the conninfo parameter definitions returned by PQconndefaults
* ---------------- * ----------------
*/ */
typedef struct _PQconninfoOption typedef struct _PQconninfoOption
@ -274,24 +286,36 @@ extern "C"
int dispsize; /* Field size in characters for dialog */ int dispsize; /* Field size in characters for dialog */
} PQconninfoOption; } PQconninfoOption;
/* ----------------
* Exported functions of libpq
* ----------------
*/
/* === in fe-connect.c === */ /* === in fe-connect.c === */
/* make a new client connection to the backend */ /* make a new client connection to the backend */
extern PGconn *PQconnectdb(const char *conninfo); extern PGconn *PQconnectdb(const char *conninfo);
extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport,
const char *pgoptions, const char *pgtty,
const char *dbName,
const char *login, const char *pwd);
#define PQsetdb(M_PGHOST,M_PGPORT,M_PGOPT,M_PGTTY,M_DBNAME) \
PQsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, NULL, NULL)
/* get info about connection options known to PQconnectdb */
extern PQconninfoOption *PQconndefaults(void); extern PQconninfoOption *PQconndefaults(void);
extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
const char *pgtty, const char *dbName, const char *login, const char *pwd);
#define PQsetdb(M_PGHOST,M_PGPORT,M_PGOPT,M_PGTTY,M_DBNAME) PQsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, NULL, NULL)
/* close the current connection and free the PGconn data structure */ /* close the current connection and free the PGconn data structure */
extern void PQfinish(PGconn *conn); extern void PQfinish(PGconn *conn);
/* issue a cancel request */
extern int PQrequestCancel(PGconn *conn);
/* /*
* close the current connection and restablish a new one with the same * close the current connection and restablish a new one with the same
* parameters * parameters
*/ */
extern void PQreset(PGconn *conn); extern void PQreset(PGconn *conn);
/* issue a cancel request */
extern int PQrequestCancel(PGconn *conn);
/* Accessor functions for PGconn objects */ /* Accessor functions for PGconn objects */
extern char *PQdb(PGconn *conn); extern char *PQdb(PGconn *conn);
extern char *PQuser(PGconn *conn); extern char *PQuser(PGconn *conn);
@ -313,20 +337,26 @@ extern "C"
void *arg); void *arg);
/* === in fe-exec.c === */ /* === in fe-exec.c === */
/* Simple synchronous query */ /* Simple synchronous query */
extern PGresult *PQexec(PGconn *conn, const char *query); extern PGresult *PQexec(PGconn *conn, const char *query);
extern PGnotify *PQnotifies(PGconn *conn); extern PGnotify *PQnotifies(PGconn *conn);
/* Interface for multiple-result or asynchronous queries */ /* Interface for multiple-result or asynchronous queries */
extern int PQsendQuery(PGconn *conn, const char *query); extern int PQsendQuery(PGconn *conn, const char *query);
extern PGresult *PQgetResult(PGconn *conn); extern PGresult *PQgetResult(PGconn *conn);
/* Routines for managing an asychronous query */ /* Routines for managing an asychronous query */
extern int PQisBusy(PGconn *conn); extern int PQisBusy(PGconn *conn);
extern void PQconsumeInput(PGconn *conn); extern void PQconsumeInput(PGconn *conn);
/* Routines for copy in/out */ /* Routines for copy in/out */
extern int PQgetline(PGconn *conn, char *string, int length); extern int PQgetline(PGconn *conn, char *string, int length);
extern void PQputline(PGconn *conn, const char *string); extern void PQputline(PGconn *conn, const char *string);
extern void PQputnbytes(PGconn *conn, const char *buffer, int nbytes);
extern int PQendcopy(PGconn *conn); extern int PQendcopy(PGconn *conn);
/* Not really meant for application use: */
/* "Fast path" interface --- not really recommended for application use */
extern PGresult *PQfn(PGconn *conn, extern PGresult *PQfn(PGconn *conn,
int fnid, int fnid,
int *result_buf, int *result_buf,
@ -334,7 +364,6 @@ extern "C"
int result_is_int, int result_is_int,
PQArgBlock *args, PQArgBlock *args,
int nargs); int nargs);
extern void PQclearAsyncResult(PGconn *conn);
/* Accessor functions for PGresult objects */ /* Accessor functions for PGresult objects */
extern ExecStatusType PQresultStatus(PGresult *res); extern ExecStatusType PQresultStatus(PGresult *res);
@ -351,14 +380,16 @@ extern "C"
extern char *PQgetvalue(PGresult *res, int tup_num, int field_num); extern char *PQgetvalue(PGresult *res, int tup_num, int field_num);
extern int PQgetlength(PGresult *res, int tup_num, int field_num); extern int PQgetlength(PGresult *res, int tup_num, int field_num);
extern int PQgetisnull(PGresult *res, int tup_num, int field_num); extern int PQgetisnull(PGresult *res, int tup_num, int field_num);
/* Delete a PGresult */ /* Delete a PGresult */
extern void PQclear(PGresult *res); extern void PQclear(PGresult *res);
/* === in fe-print.c === */ /* === in fe-print.c === */
extern void PQprint(FILE *fout, /* output stream */ extern void PQprint(FILE *fout, /* output stream */
PGresult *res, PGresult *res,
PQprintOpt *ps /* option structure */ PQprintOpt *ps); /* option structure */
);
/* PQdisplayTuples() is a better version of PQprintTuples(), /* PQdisplayTuples() is a better version of PQprintTuples(),
* but both are obsoleted by PQprint(). * but both are obsoleted by PQprint().
*/ */
@ -376,37 +407,16 @@ extern "C"
* or not */ * or not */
int terseOutput, /* delimiter bars or int terseOutput, /* delimiter bars or
* not? */ * not? */
int width /* width of column, if int width); /* width of column, if
* 0, use variable width */ * 0, use variable width */
);
#ifdef MULTIBYTE #ifdef MULTIBYTE
extern int PQmblen(unsigned char *s); extern int PQmblen(unsigned char *s);
#endif #endif
/* === in fe-auth.c === */
extern MsgType fe_getauthsvc(char *PQerrormsg);
extern void fe_setauthsvc(const char *name, char *PQerrormsg);
extern char *fe_getauthname(char *PQerrormsg);
/* === in fe-misc.c === */
/* "Get" and "Put" routines return 0 if successful, EOF if not.
* Note that for Get, EOF merely means the buffer is exhausted,
* not that there is necessarily any error.
*/
extern int pqGetc(char *result, PGconn *conn);
extern int pqGets(char *s, int maxlen, PGconn *conn);
extern int pqPuts(const char *s, PGconn *conn);
extern int pqGetnchar(char *s, int len, PGconn *conn);
extern int pqPutnchar(const char *s, int len, PGconn *conn);
extern int pqGetInt(int *result, int bytes, PGconn *conn);
extern int pqPutInt(int value, int bytes, PGconn *conn);
extern int pqReadData(PGconn *conn);
extern int pqReadReady(PGconn *conn);
extern int pqFlush(PGconn *conn);
extern int pqWait(int forRead, int forWrite, PGconn *conn);
/* === in fe-lobj.c === */ /* === in fe-lobj.c === */
/* Large-object access routines */
extern int lo_open(PGconn *conn, Oid lobjId, int mode); extern int lo_open(PGconn *conn, Oid lobjId, int mode);
extern int lo_close(PGconn *conn, int fd); extern int lo_close(PGconn *conn, int fd);
extern int lo_read(PGconn *conn, int fd, char *buf, int len); extern int lo_read(PGconn *conn, int fd, char *buf, int len);
@ -418,36 +428,8 @@ extern "C"
extern Oid lo_import(PGconn *conn, char *filename); extern Oid lo_import(PGconn *conn, char *filename);
extern int lo_export(PGconn *conn, Oid lobjId, char *filename); extern int lo_export(PGconn *conn, Oid lobjId, char *filename);
/* max length of message to send */
#define MAX_MESSAGE_LEN 8193
/* maximum number of fields in a tuple */
#define MAX_FIELDS 512
/* bits in a byte */
#define BYTELEN 8
/* fall back options if they are not specified by arguments or defined
by environment variables */
#define DefaultHost "localhost"
#define DefaultTty ""
#define DefaultOption ""
#define DefaultAuthtype ""
#define DefaultPassword ""
typedef void *TUPLE;
#define palloc malloc
#define pfree free
#if defined(sun) && defined(sparc) && !defined(__SVR4)
extern char *sys_errlist[];
#define strerror(A) (sys_errlist[(A)])
#endif /* sunos4 */
#ifdef __cplusplus #ifdef __cplusplus
}; };
#endif #endif
#endif /* LIBPQ_FE_H */ #endif /* LIBPQ_FE_H */

View File

@ -2,72 +2,59 @@ LIBRARY LIBPQ
DESCRIPTION "Postgres Client Access Library" DESCRIPTION "Postgres Client Access Library"
EXPORTS EXPORTS
PQconnectdb @ 1 PQconnectdb @ 1
PQconndefaults @ 2 PQsetdbLogin @ 2
PQsetdbLogin @ 3 PQconndefaults @ 3
PQfinish @ 4 PQfinish @ 4
PQreset @ 5 PQreset @ 5
PQdb @ 6 PQrequestCancel @ 6
PQuser @ 7 PQdb @ 7
PQhost @ 8 PQuser @ 8
PQoptions @ 9 PQhost @ 9
PQport @ 10 PQoptions @ 10
PQtty @ 11 PQport @ 11
PQstatus @ 12 PQtty @ 12
PQerrorMessage @ 13 PQstatus @ 13
PQsocket @ 14 PQerrorMessage @ 14
PQtrace @ 15 PQsocket @ 15
PQuntrace @ 16 PQtrace @ 16
PQexec @ 17 PQuntrace @ 17
PQnotifies @ 18 PQsetNoticeProcessor @ 18
PQsendQuery @ 19 PQexec @ 19
PQgetResult @ 20 PQnotifies @ 20
PQisBusy @ 21 PQsendQuery @ 21
PQconsumeInput @ 22 PQgetResult @ 22
PQrequestCancel @ 23 PQisBusy @ 23
PQgetline @ 24 PQconsumeInput @ 24
PQputline @ 25 PQgetline @ 25
PQendcopy @ 26 PQputline @ 26
PQfn @ 27 PQputnbytes @ 27
PQclearAsyncResult @ 28 PQendcopy @ 28
PQresultStatus @ 29 PQfn @ 29
PQntuples @ 30 PQresultStatus @ 30
PQnfields @ 31 PQntuples @ 31
PQfname @ 32 PQnfields @ 32
PQfnumber @ 33 PQfname @ 33
PQftype @ 34 PQfnumber @ 34
PQfsize @ 35 PQftype @ 35
PQfmod @ 36 PQfsize @ 36
PQcmdStatus @ 37 PQfmod @ 37
PQoidStatus @ 38 PQcmdStatus @ 38
PQcmdTuples @ 39 PQoidStatus @ 39
PQgetvalue @ 40 PQcmdTuples @ 40
PQgetlength @ 41 PQgetvalue @ 41
PQgetisnull @ 42 PQgetlength @ 42
PQclear @ 43 PQgetisnull @ 43
PQprint @ 44 PQclear @ 44
PQdisplayTuples @ 45 PQprint @ 45
PQprintTuples @ 46 PQdisplayTuples @ 46
fe_getauthsvc @ 47 PQprintTuples @ 47
fe_setauthsvc @ 48 lo_open @ 48
fe_getauthname @ 49 lo_close @ 49
pqGetc @ 50 lo_read @ 50
pqGets @ 51 lo_write @ 51
pqPuts @ 52 lo_lseek @ 52
pqGetnchar @ 53 lo_creat @ 53
pqPutnchar @ 54 lo_tell @ 54
pqGetInt @ 55 lo_unlink @ 55
pqPutInt @ 56 lo_import @ 56
pqReadData @ 57 lo_export @ 57
pqFlush @ 58
pqWait @ 59
lo_open @ 60
lo_close @ 61
lo_read @ 62
lo_write @ 63
lo_lseek @ 64
lo_creat @ 65
lo_tell @ 66
lo_unlink @ 67
lo_import @ 68
lo_export @ 69

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/pqsignal.c,v 1.6 1998/06/15 19:30:26 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/pqsignal.c,v 1.7 1998/08/17 03:50:43 scrappy Exp $
* *
* NOTES * NOTES
* This shouldn't be in libpq, but the monitor and some other * This shouldn't be in libpq, but the monitor and some other
@ -17,10 +17,9 @@
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <signal.h> #include <signal.h>
#include "libpq/pqsignal.h" #include "pqsignal.h"
pqsigfunc pqsigfunc
pqsignal(int signo, pqsigfunc func) pqsignal(int signo, pqsigfunc func)