From f32fc17c5f8c1b54c81d05953930c9dce0ad7781 Mon Sep 17 00:00:00 2001 From: Franck Verrot Date: Sun, 23 Aug 2015 11:53:28 +0200 Subject: [PATCH] Report column for which type coercion fails This commit pushes a new `error_context_stack` callback that helps users understanding which column type coercion fails during INSERTs: # create table foo(bar varchar(2), baz int4); CREATE TABLE # insert into foo values('ok', 1234); INSERT 0 1 # insert into foo values('ko', 'abcd'); ERROR: invalid input syntax for integer: "abcd" LINE 1: insert into foo values('ko', 'abcd'); ^ DETAIL: Coercion failed for column "baz" of type integer. --- src/backend/parser/parse_target.c | 23 +++++++++++++++++++++++ src/include/parser/parse_target.h | 7 +++++++ 2 files changed, 30 insertions(+) diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 1b3fcd6..c03ce7c 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -389,6 +389,17 @@ markTargetListOrigin(ParseState *pstate, TargetEntry *tle, * omits the column name list. So we should usually prefer to use * exprLocation(expr) for errors that can happen in a default INSERT. */ + +void +TransformExprCallback(void *arg) +{ + TransformExprState *state = (TransformExprState *) arg; + + errdetail("Coercion failed for column \"%s\" of type %s.", + state->column_name, + format_type_be(state->expected_type)); +} + Expr * transformAssignedExpr(ParseState *pstate, Expr *expr, @@ -405,6 +416,14 @@ transformAssignedExpr(ParseState *pstate, Oid attrcollation; /* collation of target column */ ParseExprKind sv_expr_kind; + ErrorContextCallback errcallback; + TransformExprState testate; + + /* Set up callback to identify error line number. */ + errcallback.callback = TransformExprCallback; + errcallback.arg = (void *) &testate; + errcallback.previous = error_context_stack; + error_context_stack = &errcallback; /* * Save and restore identity of expression type we're parsing. We must * set p_expr_kind here because we can parse subscripts without going @@ -425,6 +444,9 @@ transformAssignedExpr(ParseState *pstate, attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod; attrcollation = rd->rd_att->attrs[attrno - 1]->attcollation; + testate.column_name = colname; + testate.expected_type = attrtype; + /* * If the expression is a DEFAULT placeholder, insert the attribute's * type/typmod/collation into it so that exprType etc will report the @@ -529,6 +551,7 @@ transformAssignedExpr(ParseState *pstate, parser_errposition(pstate, exprLocation(orig_expr)))); } + error_context_stack = errcallback.previous; pstate->p_expr_kind = sv_expr_kind; return expr; diff --git a/src/include/parser/parse_target.h b/src/include/parser/parse_target.h index a86b79d..5e12c12 100644 --- a/src/include/parser/parse_target.h +++ b/src/include/parser/parse_target.h @@ -42,4 +42,11 @@ extern TupleDesc expandRecordVariable(ParseState *pstate, Var *var, extern char *FigureColname(Node *node); extern char *FigureIndexColname(Node *node); +/* Support for TransformExprCallback */ +typedef struct TransformExprState +{ + const char *column_name; + Oid expected_type; +} TransformExprState; + #endif /* PARSE_TARGET_H */ -- 2.4.6