*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.9 1998/05/06 23:51:00 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.10 1998/05/06 23:53:30 momjian Exp $
*
*-------------------------------------------------------------------------
*/
return -1;
}
- if (connid->res_copyStatus == RES_COPY_FIN) {
- return PgEndCopy(connid, errorCodePtr);
- }
-
/* Try to load any newly arrived data */
errno = 0;
if (pqReadData(conn) < 0) {
- *errorCodePtr = errno ? errno : EIO;
- return -1;
+ *errorCodePtr = errno ? errno : EIO;
+ return -1;
}
- /* Move data from libpq's buffer to tcl's */
+ /* Move data from libpq's buffer to Tcl's.
+ * We want to accept data only in units of whole lines,
+ * not partial lines. This ensures that we can recognize
+ * the terminator line "\\.\n". (Otherwise, if it happened
+ * to cross a packet/buffer boundary, we might hand the first
+ * one or two characters off to Tcl, which we shouldn't.)
+ */
conn->inCursor = conn->inStart;
pqGetc(&c, conn) == 0) {
*buf++ = c;
--avail;
- if (c == '\n' && bufSize-avail >= 3) {
- if ((bufSize-avail == 3 || buf[-4] == '\n') &&
- buf[-3] == '\\' && buf[-2] == '.') {
- avail += 3;
- connid->res_copyStatus = RES_COPY_FIN;
- break;
+ if (c == '\n') {
+ /* Got a complete line; mark the data removed from libpq */
+ conn->inStart = conn->inCursor;
+ /* Is it the endmarker line? */
+ if (bufSize-avail == 3 && buf[-3] == '\\' && buf[-2] == '.') {
+ /* Yes, change state and return 0 */
+ return PgEndCopy(connid, errorCodePtr);
}
+ /* No, return the data to Tcl */
+ /* fprintf(stderr, "returning %d chars\n", bufSize - avail); */
+ return bufSize - avail;
}
}
- /* Accept the data permanently */
- conn->inStart = conn->inCursor;
- /* fprintf(stderr, "returning %d chars\n", bufSize - avail); */
- return bufSize - avail;
+
+ /* We don't have a complete line.
+ * We'd prefer to leave it in libpq's buffer until the rest arrives,
+ * but there is a special case: what if the line is longer than the
+ * buffer Tcl is offering us? In that case we'd better hand over
+ * a partial line, else we'd get into an infinite loop.
+ * Do this in a way that ensures we can't misrecognize a terminator
+ * line later: leave last 3 characters in libpq buffer.
+ */
+ if (avail == 0 && bufSize > 3) {
+ conn->inStart = conn->inCursor - 3;
+ return bufSize - 3;
+ }
+ return 0;
}
/*
errno = 0;
if (pqPutnchar(buf, bufSize, conn)) {
- *errorCodePtr = errno ? errno : EIO;
- return -1;
+ *errorCodePtr = errno ? errno : EIO;
+ return -1;
}
+ /* This assumes Tcl script will write the terminator line
+ * in a single operation; maybe not such a good assumption?
+ */
if (bufSize >= 3 && strncmp(&buf[bufSize-3], "\\.\n", 3) == 0) {
(void) pqFlush(conn);
if (PgEndCopy(connid, errorCodePtr) == -1)
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.50 1998/05/06 23:51:13 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.51 1998/05/06 23:53:38 momjian Exp $
*
*-------------------------------------------------------------------------
*/
return NULL;
/* For backwards compatibility, return the last result if there are
- * more than one.
+ * more than one. We have to stop if we see copy in/out, however.
+ * We will resume parsing when application calls PQendcopy.
*/
lastResult = NULL;
while ((result = PQgetResult(conn)) != NULL)
if (lastResult)
PQclear(lastResult);
lastResult = result;
+ if (result->resultStatus == PGRES_COPY_IN ||
+ result->resultStatus == PGRES_COPY_OUT)
+ break;
}
return lastResult;
}
{
if (conn && conn->sock >= 0)
{
- (void) pqPuts(s, conn);
+ (void) pqPutnchar(s, strlen(s), conn);
}
}
result = PQgetResult(conn);
/* Expecting a successful result */
- if (result->resultStatus == PGRES_COMMAND_OK)
+ if (result && result->resultStatus == PGRES_COMMAND_OK)
{
PQclear(result);
return 0;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.11 1998/05/06 23:51:14 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.12 1998/05/06 23:53:48 momjian Exp $
*
*-------------------------------------------------------------------------
*/
{
if (errno == EINTR)
goto tryAgain;
+ /* Some systems return EAGAIN/EWOULDBLOCK for no data */
+#ifdef EAGAIN
+ if (errno == EAGAIN)
+ return 0;
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ if (errno == EWOULDBLOCK)
+ return 0;
+#endif
sprintf(conn->errorMessage,
"pqReadData() -- read() failed: errno=%d\n%s\n",
errno, strerror(errno));
{
if (errno == EINTR)
goto tryAgain2;
+ /* Some systems return EAGAIN/EWOULDBLOCK for no data */
+#ifdef EAGAIN
+ if (errno == EAGAIN)
+ return 0;
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ if (errno == EWOULDBLOCK)
+ return 0;
+#endif
sprintf(conn->errorMessage,
"pqReadData() -- read() failed: errno=%d\n%s\n",
errno, strerror(errno));