aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2010-09-18 20:10:15 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2010-09-18 20:10:15 +0000
commitf906e0786e27ca5b56a680c16b216ae406fbb1cf (patch)
treeaf6d0540f5eeaf3b1d885af8cd2cd37582c5f2ec /src
parentaf0161e5273a8b81cc76d6267ce9a7079268fe4a (diff)
downloadpostgresql-f906e0786e27ca5b56a680c16b216ae406fbb1cf.tar.gz
postgresql-f906e0786e27ca5b56a680c16b216ae406fbb1cf.zip
Make sure we wait for protocol-level EOF when ending binary COPY IN.
The previous coding just terminated the COPY immediately after seeing the EOF marker (-1 where a row field count is expected). The expected CopyDone or CopyFail message just got thrown away later, since we weren't in COPY mode anymore. This behavior complicated matters for the JDBC driver, and arguably was the wrong thing in any case since a CopyFail message after the marker wouldn't be honored. Note that there is a behavioral change here: extra data after the EOF marker was silently ignored before, but now it will cause an error. Hence not back-patching, although this is arguably a bug. Per report and patch by Kris Jurka.
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/copy.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 19e1b7251e5..472c8828eb5 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.329 2010/08/13 20:10:50 rhaas Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.330 2010/09/18 20:10:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2058,9 +2058,34 @@ CopyFrom(CopyState cstate)
int16 fld_count;
ListCell *cur;
- if (!CopyGetInt16(cstate, &fld_count) ||
- fld_count == -1)
+ if (!CopyGetInt16(cstate, &fld_count))
{
+ /* EOF detected (end of file, or protocol-level EOF) */
+ done = true;
+ break;
+ }
+
+ if (fld_count == -1)
+ {
+ /*
+ * Received EOF marker. In a V3-protocol copy, wait for
+ * the protocol-level EOF, and complain if it doesn't come
+ * immediately. This ensures that we correctly handle
+ * CopyFail, if client chooses to send that now.
+ *
+ * Note that we MUST NOT try to read more data in an
+ * old-protocol copy, since there is no protocol-level EOF
+ * marker then. We could go either way for copy from file,
+ * but choose to throw error if there's data after the EOF
+ * marker, for consistency with the new-protocol case.
+ */
+ char dummy;
+
+ if (cstate->copy_dest != COPY_OLD_FE &&
+ CopyGetData(cstate, &dummy, 1, 1) > 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
+ errmsg("received copy data after EOF marker")));
done = true;
break;
}