diff options
author | Robert Haas <rhaas@postgresql.org> | 2010-12-11 09:27:37 -0500 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2010-12-11 09:27:37 -0500 |
commit | d3d414696f39e2b57072fab3dd4fa11e465be4ed (patch) | |
tree | f99e5cd6209d2462424d22bcee41e036741b45f5 /src/interfaces/libpq/fe-exec.c | |
parent | 20f396429186a35a81fc7ef3ad34c3134ead2992 (diff) | |
download | postgresql-d3d414696f39e2b57072fab3dd4fa11e465be4ed.tar.gz postgresql-d3d414696f39e2b57072fab3dd4fa11e465be4ed.zip |
Allow bidirectional copy messages in streaming replication mode.
Fujii Masao. Review by Alvaro Herrera, Tom Lane, and myself.
Diffstat (limited to 'src/interfaces/libpq/fe-exec.c')
-rw-r--r-- | src/interfaces/libpq/fe-exec.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index 8f25f5eb27c..9858faeaa64 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -35,6 +35,7 @@ char *const pgresStatus[] = { "PGRES_TUPLES_OK", "PGRES_COPY_OUT", "PGRES_COPY_IN", + "PGRES_COPY_BOTH", "PGRES_BAD_RESPONSE", "PGRES_NONFATAL_ERROR", "PGRES_FATAL_ERROR" @@ -174,6 +175,7 @@ PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status) case PGRES_TUPLES_OK: case PGRES_COPY_OUT: case PGRES_COPY_IN: + case PGRES_COPY_BOTH: /* non-error cases */ break; default: @@ -1591,6 +1593,12 @@ PQgetResult(PGconn *conn) else res = PQmakeEmptyPGresult(conn, PGRES_COPY_OUT); break; + case PGASYNC_COPY_BOTH: + if (conn->result && conn->result->resultStatus == PGRES_COPY_BOTH) + res = pqPrepareAsyncResult(conn); + else + res = PQmakeEmptyPGresult(conn, PGRES_COPY_BOTH); + break; default: printfPQExpBuffer(&conn->errorMessage, libpq_gettext("unexpected asyncStatus: %d\n"), @@ -1775,6 +1783,13 @@ PQexecStart(PGconn *conn) return false; } } + else if (resultStatus == PGRES_COPY_BOTH) + { + /* We don't allow PQexec during COPY BOTH */ + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("PQexec not allowed during COPY BOTH\n")); + return false; + } /* check for loss of connection, too */ if (conn->status == CONNECTION_BAD) return false; @@ -1798,7 +1813,7 @@ PQexecFinish(PGconn *conn) * than one --- but merge error messages if we get more than one error * result. * - * We have to stop if we see copy in/out, however. We will resume parsing + * We have to stop if we see copy in/out/both, however. We will resume parsing * after application performs the data transfer. * * Also stop if the connection is lost (else we'll loop infinitely). @@ -1827,6 +1842,7 @@ PQexecFinish(PGconn *conn) lastResult = result; if (result->resultStatus == PGRES_COPY_IN || result->resultStatus == PGRES_COPY_OUT || + result->resultStatus == PGRES_COPY_BOTH || conn->status == CONNECTION_BAD) break; } @@ -2000,7 +2016,7 @@ PQnotifies(PGconn *conn) } /* - * PQputCopyData - send some data to the backend during COPY IN + * PQputCopyData - send some data to the backend during COPY IN or COPY BOTH * * Returns 1 if successful, 0 if data could not be sent (only possible * in nonblock mode), or -1 if an error occurs. @@ -2010,7 +2026,8 @@ PQputCopyData(PGconn *conn, const char *buffer, int nbytes) { if (!conn) return -1; - if (conn->asyncStatus != PGASYNC_COPY_IN) + if (conn->asyncStatus != PGASYNC_COPY_IN && + conn->asyncStatus != PGASYNC_COPY_BOTH) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("no COPY in progress\n")); @@ -2148,6 +2165,7 @@ PQputCopyEnd(PGconn *conn, const char *errormsg) /* * PQgetCopyData - read a row of data from the backend during COPY OUT + * or COPY BOTH * * If successful, sets *buffer to point to a malloc'd row of data, and * returns row length (always > 0) as result. @@ -2161,7 +2179,8 @@ PQgetCopyData(PGconn *conn, char **buffer, int async) *buffer = NULL; /* for all failure cases */ if (!conn) return -2; - if (conn->asyncStatus != PGASYNC_COPY_OUT) + if (conn->asyncStatus != PGASYNC_COPY_OUT && + conn->asyncStatus != PGASYNC_COPY_BOTH) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("no COPY in progress\n")); |