diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/copy.c | 32 | ||||
-rw-r--r-- | src/backend/commands/copyfrom.c | 10 | ||||
-rw-r--r-- | src/backend/commands/copyfromparse.c | 35 |
3 files changed, 71 insertions, 6 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 28cf8b040ab..f75e1d700d9 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -423,6 +423,30 @@ defGetCopyOnErrorChoice(DefElem *def, ParseState *pstate, bool is_from) } /* + * Extract a CopyLogVerbosityChoice value from a DefElem. + */ +static CopyLogVerbosityChoice +defGetCopyLogVerbosityChoice(DefElem *def, ParseState *pstate) +{ + char *sval; + + /* + * Allow "default", or "verbose" values. + */ + sval = defGetString(def); + if (pg_strcasecmp(sval, "default") == 0) + return COPY_LOG_VERBOSITY_DEFAULT; + if (pg_strcasecmp(sval, "verbose") == 0) + return COPY_LOG_VERBOSITY_VERBOSE; + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("COPY LOG_VERBOSITY \"%s\" not recognized", sval), + parser_errposition(pstate, def->location))); + return COPY_LOG_VERBOSITY_DEFAULT; /* keep compiler quiet */ +} + +/* * Process the statement option list for COPY. * * Scan the options list (a list of DefElem) and transpose the information @@ -448,6 +472,7 @@ ProcessCopyOptions(ParseState *pstate, bool freeze_specified = false; bool header_specified = false; bool on_error_specified = false; + bool log_verbosity_specified = false; ListCell *option; /* Support external use for option sanity checking */ @@ -607,6 +632,13 @@ ProcessCopyOptions(ParseState *pstate, on_error_specified = true; opts_out->on_error = defGetCopyOnErrorChoice(defel, pstate, is_from); } + else if (strcmp(defel->defname, "log_verbosity") == 0) + { + if (log_verbosity_specified) + errorConflictingDefElem(defel, pstate); + log_verbosity_specified = true; + opts_out->log_verbosity = defGetCopyLogVerbosityChoice(defel, pstate); + } else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c index b6736369771..9d2900041e6 100644 --- a/src/backend/commands/copyfrom.c +++ b/src/backend/commands/copyfrom.c @@ -101,8 +101,6 @@ typedef struct CopyMultiInsertInfo /* non-export function prototypes */ -static char *limit_printout_length(const char *str); - static void ClosePipeFromProgram(CopyFromState cstate); /* @@ -141,7 +139,7 @@ CopyFromErrorCallback(void *arg) /* error is relevant to a particular column */ char *attval; - attval = limit_printout_length(cstate->cur_attval); + attval = CopyLimitPrintoutLength(cstate->cur_attval); errcontext("COPY %s, line %llu, column %s: \"%s\"", cstate->cur_relname, (unsigned long long) cstate->cur_lineno, @@ -168,7 +166,7 @@ CopyFromErrorCallback(void *arg) { char *lineval; - lineval = limit_printout_length(cstate->line_buf.data); + lineval = CopyLimitPrintoutLength(cstate->line_buf.data); errcontext("COPY %s, line %llu: \"%s\"", cstate->cur_relname, (unsigned long long) cstate->cur_lineno, lineval); @@ -189,8 +187,8 @@ CopyFromErrorCallback(void *arg) * * Returns a pstrdup'd copy of the input. */ -static char * -limit_printout_length(const char *str) +char * +CopyLimitPrintoutLength(const char *str) { #define MAX_COPY_DATA_DISPLAY 100 diff --git a/src/backend/commands/copyfromparse.c b/src/backend/commands/copyfromparse.c index 5682d5d054b..7ddd27f5c6e 100644 --- a/src/backend/commands/copyfromparse.c +++ b/src/backend/commands/copyfromparse.c @@ -967,7 +967,42 @@ NextCopyFrom(CopyFromState cstate, ExprContext *econtext, (Node *) cstate->escontext, &values[m])) { + Assert(cstate->opts.on_error != COPY_ON_ERROR_STOP); + cstate->num_errors++; + + if (cstate->opts.log_verbosity == COPY_LOG_VERBOSITY_VERBOSE) + { + /* + * Since we emit line number and column info in the below + * notice message, we suppress error context information + * other than the relation name. + */ + Assert(!cstate->relname_only); + cstate->relname_only = true; + + if (cstate->cur_attval) + { + char *attval; + + attval = CopyLimitPrintoutLength(cstate->cur_attval); + ereport(NOTICE, + errmsg("skipping row due to data type incompatibility at line %llu for column %s: \"%s\"", + (unsigned long long) cstate->cur_lineno, + cstate->cur_attname, + attval)); + pfree(attval); + } + else + ereport(NOTICE, + errmsg("skipping row due to data type incompatibility at line %llu for column %s: null input", + (unsigned long long) cstate->cur_lineno, + cstate->cur_attname)); + + /* reset relname_only */ + cstate->relname_only = false; + } + return true; } |