aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/commands/copy.c40
-rw-r--r--src/backend/tcop/fastpath.c36
-rw-r--r--src/backend/tcop/postgres.c56
3 files changed, 84 insertions, 48 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 98a0fb92439..a25dc0b8a69 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -6,7 +6,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.85 1999/07/17 20:16:51 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.86 1999/07/22 02:40:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -54,15 +54,19 @@ static void GetIndexRelations(Oid main_relation_oid,
#ifdef COPY_PATCH
static void CopyReadNewline(FILE *fp, int *newline);
static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline);
-
#else
static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim);
-
#endif
+
static void CopyAttributeOut(FILE *fp, char *string, char *delim, int is_array);
static int CountTuples(Relation relation);
+/*
+ * Static communication variables ... pretty grotty, but COPY has
+ * never been reentrant...
+ */
static int lineno;
+static bool fe_eof;
/*
* Internal communications functions
@@ -90,7 +94,10 @@ static void
CopySendData(void *databuf, int datasize, FILE *fp)
{
if (!fp)
- pq_putbytes((char *) databuf, datasize);
+ {
+ if (pq_putbytes((char *) databuf, datasize))
+ fe_eof = true;
+ }
else
fwrite(databuf, datasize, 1, fp);
}
@@ -121,7 +128,10 @@ static void
CopyGetData(void *databuf, int datasize, FILE *fp)
{
if (!fp)
- pq_getbytes((char *) databuf, datasize);
+ {
+ if (pq_getbytes((char *) databuf, datasize))
+ fe_eof = true;
+ }
else
fread(databuf, datasize, 1, fp);
}
@@ -134,7 +144,10 @@ CopyGetChar(FILE *fp)
unsigned char ch;
if (pq_getbytes((char *) &ch, 1))
+ {
+ fe_eof = true;
return EOF;
+ }
return ch;
}
else
@@ -145,8 +158,7 @@ static int
CopyGetEof(FILE *fp)
{
if (!fp)
- return 0; /* Never return EOF when talking to
- * frontend ? */
+ return fe_eof;
else
return feof(fp);
}
@@ -154,7 +166,7 @@ CopyGetEof(FILE *fp)
/*
* CopyPeekChar reads a byte in "peekable" mode.
* after each call to CopyPeekChar, a call to CopyDonePeek _must_
- * follow.
+ * follow, unless EOF was returned.
* CopyDonePeek will either take the peeked char off the steam
* (if pickup is != 0) or leave it on the stream (if pickup == 0)
*/
@@ -162,7 +174,12 @@ static int
CopyPeekChar(FILE *fp)
{
if (!fp)
- return pq_peekbyte();
+ {
+ int ch = pq_peekbyte();
+ if (ch == EOF)
+ fe_eof = true;
+ return ch;
+ }
else
return getc(fp);
}
@@ -668,6 +685,8 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
}
lineno = 0;
+ fe_eof = false;
+
while (!done)
{
if (!binary)
@@ -1193,10 +1212,7 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
else
{
if (CopyGetEof(fp))
- {
- CopyDonePeek(fp, c, 1); /* pick up */
return NULL;
- }
CopyDonePeek(fp, c, 0); /* Return to stream! */
}
}
diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c
index 8bc5b28ee92..aed201e36d6 100644
--- a/src/backend/tcop/fastpath.c
+++ b/src/backend/tcop/fastpath.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.29 1999/07/17 20:17:50 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.30 1999/07/22 02:40:07 tgl Exp $
*
* NOTES
* This cruft is the server side of PQfn.
@@ -265,8 +265,11 @@ update_fp_info(Oid func_id, struct fp_info * fip)
* This corresponds to the libpq protocol symbol "F".
*
* RETURNS:
- * nothing of significance.
- * All errors result in elog(ERROR,...).
+ * 0 if successful completion, EOF if frontend connection lost.
+ *
+ * Note: All ordinary errors result in elog(ERROR,...). However,
+ * if we lose the frontend connection there is no one to elog to,
+ * and no use in proceeding...
*/
int
HandleFunctionRequest()
@@ -282,9 +285,11 @@ HandleFunctionRequest()
char *p;
struct fp_info *fip;
- pq_getint(&tmp, 4); /* function oid */
+ if (pq_getint(&tmp, 4)) /* function oid */
+ return EOF;
fid = (Oid) tmp;
- pq_getint(&nargs, 4); /* # of arguments */
+ if (pq_getint(&nargs, 4)) /* # of arguments */
+ return EOF;
/*
* This is where the one-back caching is done. If you want to save
@@ -294,6 +299,13 @@ HandleFunctionRequest()
if (!valid_fp_info(fid, fip))
update_fp_info(fid, fip);
+ /*
+ * XXX FIXME: elog() here means we lose sync with the frontend,
+ * since we have not swallowed all of its input message. What
+ * should happen is we absorb all of the input message per protocol
+ * syntax, and *then* do error checking and elog if appropriate.
+ */
+
if (fip->nargs != nargs)
{
elog(ERROR, "HandleFunctionRequest: actual arguments (%d) != registered arguments (%d)",
@@ -311,13 +323,15 @@ HandleFunctionRequest()
arg[i] = (char *) NULL;
else
{
- pq_getint(&argsize, 4);
+ if (pq_getint(&argsize, 4))
+ return EOF;
Assert(argsize > 0);
if (fip->argbyval[i])
{ /* by-value */
Assert(argsize <= 4);
- pq_getint(&tmp, argsize);
+ if (pq_getint(&tmp, argsize))
+ return EOF;
arg[i] = (char *) tmp;
}
else
@@ -329,14 +343,16 @@ HandleFunctionRequest()
* 98 Jan 6 */
elog(ERROR, "HandleFunctionRequest: palloc failed");
VARSIZE(p) = argsize + VARHDRSZ;
- pq_getbytes(VARDATA(p), argsize);
+ if (pq_getbytes(VARDATA(p), argsize))
+ return EOF;
}
else
{ /* ... fixed */
/* XXX cross our fingers and trust "argsize" */
if (!(p = palloc(argsize + 1)))
elog(ERROR, "HandleFunctionRequest: palloc failed");
- pq_getbytes(p, argsize);
+ if (pq_getbytes(p, argsize))
+ return EOF;
}
palloced |= (1 << i);
arg[i] = p;
@@ -374,7 +390,5 @@ HandleFunctionRequest()
if (!fip->retbyval)
pfree(retval);
-
-
return 0;
}
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index ea357ba613a..a667fa70c40 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.126 1999/07/19 02:27:06 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.127 1999/07/22 02:40:07 tgl Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@@ -158,9 +158,9 @@ int _exec_repeat_ = 1;
* decls for routines only used in this file
* ----------------------------------------------------------------
*/
-static char InteractiveBackend(char *inBuf);
-static char SocketBackend(char *inBuf);
-static char ReadCommand(char *inBuf);
+static int InteractiveBackend(char *inBuf);
+static int SocketBackend(char *inBuf);
+static int ReadCommand(char *inBuf);
static void pg_exec_query(char *query_string);
@@ -172,10 +172,12 @@ static void pg_exec_query(char *query_string);
/* ----------------
* InteractiveBackend() is called for user interactive connections
* the string entered by the user is placed in its parameter inBuf.
+ *
+ * EOF is returned if end-of-file input is seen; time to shut down.
* ----------------
*/
-static char
+static int
InteractiveBackend(char *inBuf)
{
char *stuff = inBuf; /* current place in input buffer */
@@ -244,8 +246,7 @@ InteractiveBackend(char *inBuf)
{
if (Verbose)
puts("EOF");
- IsEmptyQuery = true;
- proc_exit(0);
+ return EOF;
}
/* ----------------
@@ -274,11 +275,13 @@ InteractiveBackend(char *inBuf)
*
* If the input is a fastpath function call (case 'F') then
* the function call is processed in HandleFunctionRequest().
- * (now called from PostgresMain())
+ * (now called from PostgresMain()).
+ *
+ * EOF is returned if the connection is lost.
* ----------------
*/
-static char
+static int
SocketBackend(char *inBuf)
{
char qtype;
@@ -290,13 +293,7 @@ SocketBackend(char *inBuf)
*/
qtype = '?';
if (pq_getbytes(&qtype, 1) == EOF)
- {
- /* ------------
- * when front-end applications quits/dies
- * ------------
- */
- proc_exit(0);
- }
+ return EOF;
switch (qtype)
{
@@ -305,7 +302,8 @@ SocketBackend(char *inBuf)
* ----------------
*/
case 'Q':
- pq_getstr(inBuf, MAX_PARSE_BUFFER);
+ if (pq_getstr(inBuf, MAX_PARSE_BUFFER))
+ return EOF;
result = 'Q';
break;
@@ -314,8 +312,8 @@ SocketBackend(char *inBuf)
* ----------------
*/
case 'F':
- pq_getstr(inBuf, MAX_PARSE_BUFFER); /* ignore the rest of the
- * line */
+ if (pq_getstr(inBuf, MAX_PARSE_BUFFER))
+ return EOF; /* ignore "string" at start of F message */
result = 'F';
break;
@@ -345,10 +343,10 @@ SocketBackend(char *inBuf)
* ReadCommand reads a command from either the frontend or
* standard input, places it in inBuf, and returns a char
* representing whether the string is a 'Q'uery or a 'F'astpath
- * call.
+ * call. EOF is returned if end of file.
* ----------------
*/
-static char
+static int
ReadCommand(char *inBuf)
{
if (IsUnderPostmaster)
@@ -890,7 +888,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
bool secure = true;
int errs = 0;
- char firstchar;
+ int firstchar;
char parser_input[MAX_PARSE_BUFFER];
char *userName;
@@ -1494,7 +1492,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
if (!IsUnderPostmaster)
{
puts("\nPOSTGRES backend interactive interface ");
- puts("$Revision: 1.126 $ $Date: 1999/07/19 02:27:06 $\n");
+ puts("$Revision: 1.127 $ $Date: 1999/07/22 02:40:07 $\n");
}
/* ----------------
@@ -1581,7 +1579,12 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
TPRINTF(TRACE_VERBOSE, "StartTransactionCommand");
StartTransactionCommand();
- HandleFunctionRequest();
+ if (HandleFunctionRequest() == EOF)
+ {
+ /* lost frontend connection during F message input */
+ pq_close();
+ proc_exit(0);
+ }
break;
/* ----------------
@@ -1621,10 +1624,13 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
break;
/* ----------------
- * 'X' means that the frontend is closing down the socket
+ * 'X' means that the frontend is closing down the socket.
+ * EOF means unexpected loss of frontend connection.
+ * Either way, perform normal shutdown.
* ----------------
*/
case 'X':
+ case EOF:
pq_close();
proc_exit(0);
break;