aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/copyfrom.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/copyfrom.c')
-rw-r--r--src/backend/commands/copyfrom.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c
index 37836a769c7..46b23e345b8 100644
--- a/src/backend/commands/copyfrom.c
+++ b/src/backend/commands/copyfrom.c
@@ -42,6 +42,7 @@
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
+#include "nodes/miscnodes.h"
#include "optimizer/optimizer.h"
#include "pgstat.h"
#include "rewrite/rewriteHandler.h"
@@ -656,6 +657,9 @@ CopyFrom(CopyFromState cstate)
Assert(cstate->rel);
Assert(list_length(cstate->range_table) == 1);
+ if (cstate->opts.save_error_to != COPY_SAVE_ERROR_TO_ERROR)
+ Assert(cstate->escontext);
+
/*
* The target must be a plain, foreign, or partitioned relation, or have
* an INSTEAD OF INSERT row trigger. (Currently, such triggers are only
@@ -992,6 +996,25 @@ CopyFrom(CopyFromState cstate)
if (!NextCopyFrom(cstate, econtext, myslot->tts_values, myslot->tts_isnull))
break;
+ if (cstate->opts.save_error_to != COPY_SAVE_ERROR_TO_ERROR &&
+ cstate->escontext->error_occurred)
+ {
+ /*
+ * Soft error occured, skip this tuple and save error information
+ * according to SAVE_ERROR_TO.
+ */
+ if (cstate->opts.save_error_to == COPY_SAVE_ERROR_TO_NONE)
+
+ /*
+ * Just make ErrorSaveContext ready for the next NextCopyFrom.
+ * Since we don't set details_wanted and error_data is not to
+ * be filled, just resetting error_occurred is enough.
+ */
+ cstate->escontext->error_occurred = false;
+
+ continue;
+ }
+
ExecStoreVirtualTuple(myslot);
/*
@@ -1284,6 +1307,14 @@ CopyFrom(CopyFromState cstate)
/* Done, clean up */
error_context_stack = errcallback.previous;
+ if (cstate->opts.save_error_to != COPY_SAVE_ERROR_TO_ERROR &&
+ cstate->num_errors > 0)
+ ereport(NOTICE,
+ errmsg_plural("%zd row were skipped due to data type incompatibility",
+ "%zd rows were skipped due to data type incompatibility",
+ cstate->num_errors,
+ cstate->num_errors));
+
if (bistate != NULL)
FreeBulkInsertState(bistate);
@@ -1419,6 +1450,23 @@ BeginCopyFrom(ParseState *pstate,
}
}
+ /* Set up soft error handler for SAVE_ERROR_TO */
+ if (cstate->opts.save_error_to != COPY_SAVE_ERROR_TO_ERROR)
+ {
+ cstate->escontext = makeNode(ErrorSaveContext);
+ cstate->escontext->type = T_ErrorSaveContext;
+ cstate->escontext->error_occurred = false;
+
+ /*
+ * Currently we only support COPY_SAVE_ERROR_TO_NONE. We'll add other
+ * options later
+ */
+ if (cstate->opts.save_error_to == COPY_SAVE_ERROR_TO_NONE)
+ cstate->escontext->details_wanted = false;
+ }
+ else
+ cstate->escontext = NULL;
+
/* Convert FORCE_NULL name list to per-column flags, check validity */
cstate->opts.force_null_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
if (cstate->opts.force_null_all)