aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-exec.c
diff options
context:
space:
mode:
authorMarc G. Fournier <scrappy@hub.org>1998-08-17 03:50:43 +0000
committerMarc G. Fournier <scrappy@hub.org>1998-08-17 03:50:43 +0000
commit93120330713916c28f87deb3466010b1f23a213e (patch)
treefc56a3e099f78a8f4d3b10a1c4fbfc1aba594099 /src/interfaces/libpq/fe-exec.c
parent3fa676a74cd7f4e010610e1da1bf17395b1d05c7 (diff)
downloadpostgresql-93120330713916c28f87deb3466010b1f23a213e.tar.gz
postgresql-93120330713916c28f87deb3466010b1f23a213e.zip
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>
Diffstat (limited to 'src/interfaces/libpq/fe-exec.c')
-rw-r--r--src/interfaces/libpq/fe-exec.c111
1 files changed, 65 insertions, 46 deletions
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 89790183144..c909c424468 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -7,24 +7,25 @@
*
*
* 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
#include "win32.h"
+#else
+#if !defined(NO_UNISTD_H)
+#include <unistd.h>
+#endif
#endif
#include <stdlib.h>
-#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
-#if !defined(NO_UNISTD_H)
-#include <unistd.h>
-#endif
-#include "postgres.h"
-#include "libpq/pqcomm.h"
-#include "libpq-fe.h"
/* the rows array in a PGresGroup has to grow to accommodate the rows */
@@ -32,7 +33,7 @@
#define TUPARR_GROW_BY 100
/* keep this in same order as ExecStatusType in libpq-fe.h */
-const char *pgresStatus[] = {
+const char * const pgresStatus[] = {
"PGRES_EMPTY_QUERY",
"PGRES_COMMAND_OK",
"PGRES_TUPLES_OK",
@@ -144,7 +145,7 @@ freeTuple(PGresAttValue *tuple, int numAttributes)
*/
void
-PQclearAsyncResult(PGconn *conn)
+pqClearAsyncResult(PGconn *conn)
{
/* Get rid of incomplete result and any not-yet-added tuple */
if (conn->result)
@@ -210,25 +211,6 @@ PQsendQuery(PGconn *conn, const char *query)
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. */
if (conn->status != CONNECTION_OK)
{
@@ -236,6 +218,13 @@ PQsendQuery(PGconn *conn, const char *query)
"to the backend.\n");
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 */
conn->errorMessage[0] = '\0';
@@ -361,7 +350,7 @@ parseInput(PGconn *conn)
if (pqGets(conn->asyncErrorMessage,ERROR_MSG_LENGTH,conn))
return;
/* delete any partially constructed result */
- PQclearAsyncResult(conn);
+ pqClearAsyncResult(conn);
/* we leave result NULL while setting asyncStatus=READY;
* this signals an error condition to PQgetResult.
*/
@@ -468,7 +457,7 @@ parseInput(PGconn *conn)
/* Discard the unexpected message; good idea?? */
conn->inStart = conn->inEnd;
/* delete any partially constructed result */
- PQclearAsyncResult(conn);
+ pqClearAsyncResult(conn);
conn->asyncStatus = PGASYNC_READY;
return;
} /* switch on protocol character */
@@ -583,7 +572,7 @@ getAnotherTuple(PGconn *conn, int binary)
{
sprintf(conn->asyncErrorMessage,
"getAnotherTuple() -- null-values bitmap is too large\n");
- PQclearAsyncResult(conn);
+ pqClearAsyncResult(conn);
conn->asyncStatus = PGASYNC_READY;
/* Discard the broken message */
conn->inStart = conn->inEnd;
@@ -688,7 +677,7 @@ PQgetResult(PGconn *conn)
if (pqWait(TRUE, FALSE, conn) ||
pqReadData(conn) < 0)
{
- PQclearAsyncResult(conn);
+ pqClearAsyncResult(conn);
conn->asyncStatus = PGASYNC_IDLE;
/* conn->errorMessage has been set by pqWait or pqReadData. */
return makeEmptyPGresult(conn, PGRES_FATAL_ERROR);
@@ -940,6 +929,16 @@ PQputline(PGconn *conn, const char *s)
}
/*
+ * 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
* After completing the data transfer portion of a copy in/out,
* the application must call this routine to finish the command protocol.
@@ -968,6 +967,7 @@ PQendcopy(PGconn *conn)
/* Return to active duty */
conn->asyncStatus = PGASYNC_BUSY;
+ conn->errorMessage[0] = '\0';
/* Wait for the completion response */
result = PQgetResult(conn);
@@ -986,8 +986,10 @@ PQendcopy(PGconn *conn)
*/
PQclear(result);
- sprintf(conn->errorMessage, "PQendcopy: resetting connection\n");
- DONOTICE(conn, conn->errorMessage);
+ if (conn->errorMessage[0])
+ DONOTICE(conn, conn->errorMessage);
+
+ DONOTICE(conn, "PQendcopy: resetting connection\n");
PQreset(conn);
@@ -1344,23 +1346,40 @@ PQcmdStatus(PGresult *res)
const char *
PQoidStatus(PGresult *res)
{
- static char oidStatus[32] = {0};
+ char *p, *e, *scan;
+ int slen, olen;
if (!res)
return "";
- oidStatus[0] = 0;
+ if (strncmp(res->cmdStatus, "INSERT ", 7) != 0)
+ return "";
- if (strncmp(res->cmdStatus, "INSERT ", 7) == 0)
- {
- char *p = res->cmdStatus + 7;
- char *e;
+ /* The cmdStatus string looks like
+ * INSERT oid count\0
+ * In order to be able to return an ordinary C string without
+ * 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;)
- e++;
- sprintf(oidStatus, "%.*s", e - p, p);
- }
- return oidStatus;
+ slen = strlen(res->cmdStatus);
+ p = res->cmdStatus + 7; /* where oid is now */
+ e = res->cmdStatus + slen + 1; /* where to put the oid string */
+
+ 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;
}
/*