aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/copy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/copy.c')
-rw-r--r--src/backend/commands/copy.c45
1 files changed, 29 insertions, 16 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 6b5bcd83c5b..95fec8d3864 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -3243,7 +3243,17 @@ CopyReadAttributesText(CopyState cstate)
start_ptr = cur_ptr;
cstate->raw_fields[fieldno] = output_ptr;
- /* Scan data for field */
+ /*
+ * Scan data for field.
+ *
+ * Note that in this loop, we are scanning to locate the end of field
+ * and also speculatively performing de-escaping. Once we find the
+ * end-of-field, we can match the raw field contents against the null
+ * marker string. Only after that comparison fails do we know that
+ * de-escaping is actually the right thing to do; therefore we *must
+ * not* throw any syntax errors before we've done the null-marker
+ * check.
+ */
for (;;)
{
char c;
@@ -3356,26 +3366,29 @@ CopyReadAttributesText(CopyState cstate)
*output_ptr++ = c;
}
- /* Terminate attribute value in output area */
- *output_ptr++ = '\0';
-
- /*
- * If we de-escaped a non-7-bit-ASCII char, make sure we still have
- * valid data for the db encoding. Avoid calling strlen here for the
- * sake of efficiency.
- */
- if (saw_non_ascii)
- {
- char *fld = cstate->raw_fields[fieldno];
-
- pg_verifymbstr(fld, output_ptr - (fld + 1), false);
- }
-
/* Check whether raw input matched null marker */
input_len = end_ptr - start_ptr;
if (input_len == cstate->null_print_len &&
strncmp(start_ptr, cstate->null_print, input_len) == 0)
cstate->raw_fields[fieldno] = NULL;
+ else
+ {
+ /*
+ * At this point we know the field is supposed to contain data.
+ *
+ * If we de-escaped any non-7-bit-ASCII chars, make sure the
+ * resulting string is valid data for the db encoding.
+ */
+ if (saw_non_ascii)
+ {
+ char *fld = cstate->raw_fields[fieldno];
+
+ pg_verifymbstr(fld, output_ptr - fld, false);
+ }
+ }
+
+ /* Terminate attribute value in output area */
+ *output_ptr++ = '\0';
fieldno++;
/* Done if we hit EOL instead of a delim */