Mention column name in error messages
Hi all,
As far as I know, there is currently no way to find which column is triggering
an error on an INSERT or ALTER COLUMN statement. Example:
# create table foo(bar varchar(4), baz varchar(2));
CREATE TABLE
# insert into foo values ('foo!', 'ok');
INSERT 0 1
# insert into foo values ('foo2!', 'ok');
ERROR: value too long for type character varying(4)
# insert into foo values ('foo!', 'ok2');
ERROR: value too long for type character varying(2)
I browsed the list and found a conversation from last year
(/messages/by-id/3214.1390155040@sss.pgh.pa.us) that
discussed adding the actual value in the output.
The behavior I am proposing differs in the sense we will be able to see in
the "ERROR: xxxx" what column triggered the error:
# create table foo(bar varchar(4), baz varchar(2));
CREATE TABLE
# insert into foo values ('foo!', 'ok');
INSERT 0 1
# insert into foo values ('foo2!', 'ok');
ERROR: value too long for bar of type character varying(4)
# insert into foo values ('foo!', 'ok2');
ERROR: value too long for baz of type character varying(2)
In that same conversation, Tom Lane said:
[...] People have speculated about ways to
name the target column in the error report, which would probably be
far more useful; but it's not real clear how to do that in our system
structure.
Given my very restricted knowledge of PG's codebase I am not sure whether my
modifications are legitimate or not, so please don't hesitate to comment on
it and pointing where things are subpar to PG's codebase. In any case, it's
to be considered as WIP for the moment.
Thanks in advance,
Franck
--
Franck Verrot
https://github.com/franckverrot
https://twitter.com/franckverrot
Attachments:
verbose-validation.patchapplication/octet-stream; name=verbose-validation.patchDownload
From 43bfffcbc39f540c10ef62dd8afe77e0352bc89b Mon Sep 17 00:00:00 2001
From: Franck Verrot <franck@verrot.fr>
Date: Sun, 28 Jun 2015 11:03:31 +0200
Subject: [PATCH] Provide more into the varchar constraint validator
---
src/backend/catalog/heap.c | 3 +-
src/backend/commands/prepare.c | 3 +-
src/backend/commands/tablecmds.c | 9 ++++--
src/backend/optimizer/prep/preptlist.c | 4 ++-
src/backend/parser/parse_clause.c | 10 +++---
src/backend/parser/parse_coerce.c | 58 ++++++++++++++++++++++------------
src/backend/parser/parse_expr.c | 9 ++++--
src/backend/parser/parse_func.c | 16 ++++++----
src/backend/parser/parse_node.c | 9 ++++--
src/backend/parser/parse_target.c | 9 ++++--
src/backend/rewrite/rewriteHandler.c | 9 ++++--
src/backend/rewrite/rewriteManip.c | 3 +-
src/backend/utils/adt/varchar.c | 8 +++--
src/include/parser/parse_coerce.h | 7 ++--
src/pl/plpgsql/src/pl_exec.c | 6 ++--
15 files changed, 106 insertions(+), 57 deletions(-)
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index d04e94d..19c7a6d 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -2584,7 +2584,8 @@ cookDefault(ParseState *pstate,
atttypid, atttypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ attname);
if (expr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index fb33d30..99a1bb7 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -362,7 +362,8 @@ EvaluateParams(PreparedStatement *pstmt, List *params,
expected_type_id, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
if (expr == NULL)
ereport(ERROR,
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 84dbee0..1dc5f09 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -4919,7 +4919,8 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
typmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
if (defval == NULL) /* should not happen */
elog(ERROR, "failed to coerce base type to domain");
}
@@ -7886,7 +7887,8 @@ ATPrepAlterColumnType(List **wqueue,
targettype, targettypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ colName);
if (transform == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -8060,7 +8062,8 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
targettype, targettypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
if (defaultexpr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index 6b0c689..bc5bd62 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -276,6 +276,7 @@ expand_targetlist(List *tlist, int command_type,
Oid attcollation = att_tup->attcollation;
Node *new_expr;
+ //RelationGetRelationName
switch (command_type)
{
case CMD_INSERT:
@@ -294,7 +295,8 @@ expand_targetlist(List *tlist, int command_type,
COERCE_IMPLICIT_CAST,
-1,
false,
- false);
+ false,
+ NULL);
}
else
{
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index e90e1d6..3b94fe1 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -1232,7 +1232,7 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype,
if (l_colvar->vartype != outcoltype)
l_node = coerce_type(pstate, (Node *) l_colvar, l_colvar->vartype,
outcoltype, outcoltypmod,
- COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1);
+ COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1, NULL);
else if (l_colvar->vartypmod != outcoltypmod)
l_node = (Node *) makeRelabelType((Expr *) l_colvar,
outcoltype, outcoltypmod,
@@ -1244,7 +1244,7 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype,
if (r_colvar->vartype != outcoltype)
r_node = coerce_type(pstate, (Node *) r_colvar, r_colvar->vartype,
outcoltype, outcoltypmod,
- COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1);
+ COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1, NULL);
else if (r_colvar->vartypmod != outcoltypmod)
r_node = (Node *) makeRelabelType((Expr *) r_colvar,
outcoltype, outcoltypmod,
@@ -2871,7 +2871,8 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle,
restype, TEXTOID, -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
restype = TEXTOID;
}
@@ -3014,7 +3015,8 @@ addTargetToGroupList(ParseState *pstate, TargetEntry *tle,
restype, TEXTOID, -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
restype = TEXTOID;
}
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index f6e7be4..184dcab 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -34,14 +34,15 @@
static Node *coerce_type_typmod(Node *node,
Oid targetTypeId, int32 targetTypMod,
CoercionForm cformat, int location,
- bool isExplicit, bool hideInputCoercion);
+ bool isExplicit, bool hideInputCoercion, char *colname);
static void hide_coercion_node(Node *node);
static Node *build_coercion_expression(Node *node,
CoercionPathType pathtype,
Oid funcId,
Oid targetTypeId, int32 targetTypMod,
CoercionForm cformat, int location,
- bool isExplicit);
+ bool isExplicit,
+ char *colname);
static Node *coerce_record_to_complex(ParseState *pstate, Node *node,
Oid targetTypeId,
CoercionContext ccontext,
@@ -77,7 +78,8 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
Oid targettype, int32 targettypmod,
CoercionContext ccontext,
CoercionForm cformat,
- int location)
+ int location,
+ char *colname)
{
Node *result;
Node *origexpr;
@@ -100,7 +102,7 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
result = coerce_type(pstate, expr, exprtype,
targettype, targettypmod,
- ccontext, cformat, location);
+ ccontext, cformat, location, colname);
/*
* If the target is a fixed-length type, it may need a length coercion as
@@ -111,7 +113,8 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
targettype, targettypmod,
cformat, location,
(cformat != COERCE_IMPLICIT_CAST),
- (result != expr && !IsA(result, Const)));
+ (result != expr && !IsA(result, Const)),
+ colname);
if (expr != origexpr)
{
@@ -154,7 +157,7 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
Node *
coerce_type(ParseState *pstate, Node *node,
Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
- CoercionContext ccontext, CoercionForm cformat, int location)
+ CoercionContext ccontext, CoercionForm cformat, int location, char *colname)
{
Node *result;
CoercionPathType pathtype;
@@ -317,7 +320,7 @@ coerce_type(ParseState *pstate, Node *node,
result = coerce_to_domain(result,
baseTypeId, baseTypeMod,
targetTypeId,
- cformat, location, false, false);
+ cformat, location, false, false, colname);
ReleaseSysCache(baseType);
@@ -353,7 +356,7 @@ coerce_type(ParseState *pstate, Node *node,
newcoll->arg = (Expr *)
coerce_type(pstate, (Node *) coll->arg,
inputTypeId, targetTypeId, targetTypeMod,
- ccontext, cformat, location);
+ ccontext, cformat, location, colname);
newcoll->collOid = coll->collOid;
newcoll->location = coll->location;
return (Node *) newcoll;
@@ -380,7 +383,7 @@ coerce_type(ParseState *pstate, Node *node,
result = build_coercion_expression(node, pathtype, funcId,
baseTypeId, baseTypeMod,
cformat, location,
- (cformat != COERCE_IMPLICIT_CAST));
+ (cformat != COERCE_IMPLICIT_CAST), colname);
/*
* If domain, coerce to the domain type and relabel with domain
@@ -391,8 +394,8 @@ coerce_type(ParseState *pstate, Node *node,
result = coerce_to_domain(result, baseTypeId, baseTypeMod,
targetTypeId,
cformat, location, true,
- exprIsLengthCoercion(result,
- NULL));
+ exprIsLengthCoercion(result, NULL),
+ colname);
}
else
{
@@ -406,7 +409,7 @@ coerce_type(ParseState *pstate, Node *node,
* then we won't need a RelabelType node.
*/
result = coerce_to_domain(node, InvalidOid, -1, targetTypeId,
- cformat, location, false, false);
+ cformat, location, false, false, colname);
if (result == node)
{
/*
@@ -610,7 +613,7 @@ Node *
coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod, Oid typeId,
CoercionForm cformat, int location,
bool hideInputCoercion,
- bool lengthCoercionDone)
+ bool lengthCoercionDone, char *colname)
{
CoerceToDomain *result;
@@ -645,7 +648,7 @@ coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod, Oid typeId,
arg = coerce_type_typmod(arg, baseTypeId, baseTypeMod,
COERCE_IMPLICIT_CAST, location,
(cformat != COERCE_IMPLICIT_CAST),
- false);
+ false, colname);
}
/*
@@ -689,7 +692,7 @@ coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod, Oid typeId,
static Node *
coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
CoercionForm cformat, int location,
- bool isExplicit, bool hideInputCoercion)
+ bool isExplicit, bool hideInputCoercion, char *colname)
{
CoercionPathType pathtype;
Oid funcId;
@@ -712,7 +715,8 @@ coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
node = build_coercion_expression(node, pathtype, funcId,
targetTypeId, targetTypMod,
cformat, location,
- isExplicit);
+ isExplicit,
+ colname);
}
return node;
@@ -762,7 +766,8 @@ build_coercion_expression(Node *node,
Oid funcId,
Oid targetTypeId, int32 targetTypMod,
CoercionForm cformat, int location,
- bool isExplicit)
+ bool isExplicit,
+ char *colname)
{
int nargs = 0;
@@ -834,6 +839,17 @@ build_coercion_expression(Node *node,
args = lappend(args, cons);
}
+ /* Pass it the column name for eventual display */
+ cons = makeConst(CSTRINGOID,
+ -1,
+ InvalidOid,
+ strlen(colname),
+ CStringGetDatum(colname),
+ false,
+ true);
+
+ args = lappend(args, cons);
+
fexpr = makeFuncExpr(funcId, targetTypeId, args,
InvalidOid, InvalidOid, cformat);
fexpr->location = location;
@@ -974,7 +990,7 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
tupdesc->attrs[i]->atttypmod,
ccontext,
COERCE_IMPLICIT_CAST,
- -1);
+ -1, NULL);
if (cexpr == NULL)
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
@@ -1034,7 +1050,7 @@ coerce_to_boolean(ParseState *pstate, Node *node,
BOOLOID, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1, NULL);
if (newnode == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -1081,7 +1097,7 @@ coerce_to_specific_type(ParseState *pstate, Node *node,
targetTypeId, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1, NULL);
if (newnode == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -1281,7 +1297,7 @@ coerce_to_common_type(ParseState *pstate, Node *node,
return node; /* no work */
if (can_coerce_type(1, &inputTypeId, &targetTypeId, COERCION_IMPLICIT))
node = coerce_type(pstate, node, inputTypeId, targetTypeId, -1,
- COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1);
+ COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1, NULL);
else
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 0ff46dd..f724efc 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -2007,7 +2007,8 @@ transformArrayExpr(ParseState *pstate, A_ArrayExpr *a,
typmod,
COERCION_EXPLICIT,
COERCE_EXPLICIT_CAST,
- -1);
+ -1,
+ NULL);
if (newe == NULL)
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
@@ -2308,7 +2309,8 @@ transformXmlSerialize(ParseState *pstate, XmlSerialize *xs)
TEXTOID, targetType, targetTypmod,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
if (result == NULL)
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
@@ -2520,7 +2522,8 @@ transformTypeCast(ParseState *pstate, TypeCast *tc)
targetType, targetTypmod,
COERCION_EXPLICIT,
COERCE_EXPLICIT_CAST,
- location);
+ location,
+ NULL);
if (result == NULL)
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index fa9761b..b3d0c54 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -258,7 +258,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
*/
return coerce_type(pstate, linitial(fargs),
actual_arg_types[0], rettype, -1,
- COERCION_EXPLICIT, COERCE_EXPLICIT_CALL, location);
+ COERCION_EXPLICIT, COERCE_EXPLICIT_CALL, location, NULL);
}
else if (fdresult == FUNCDETAIL_NORMAL)
{
@@ -898,7 +898,7 @@ ParseTableSample(ParseState *pstate, char *samplemethod, Node *repeatable,
parser_errposition(pstate, exprLocation(inarg))));
arg = coerce_type(pstate, arg, argtype, init_arg_types[nargs], -1,
- COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1);
+ COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1, NULL);
}
fargs = lappend(fargs, arg);
@@ -1788,7 +1788,8 @@ unify_hypothetical_args(ParseState *pstate,
commontype, -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
actual_arg_types[i] = commontype;
args[aargpos] = coerce_type(pstate,
args[aargpos],
@@ -1796,7 +1797,8 @@ unify_hypothetical_args(ParseState *pstate,
commontype, -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
actual_arg_types[aargpos] = commontype;
}
@@ -1852,7 +1854,8 @@ make_fn_arguments(ParseState *pstate,
declared_arg_types[i], -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
na->arg = (Expr *) node;
}
else
@@ -1863,7 +1866,8 @@ make_fn_arguments(ParseState *pstate,
declared_arg_types[i], -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
lfirst(current_fargs) = node;
}
}
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index 4130cbf..52e3ec1 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -349,7 +349,8 @@ transformArraySubscripts(ParseState *pstate,
INT4OID, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
if (subexpr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -376,7 +377,8 @@ transformArraySubscripts(ParseState *pstate,
INT4OID, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
if (subexpr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -400,7 +402,8 @@ transformArraySubscripts(ParseState *pstate,
typeneeded, arrayTypMod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
if (newFrom == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 1b3fcd6..c14bd5c 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -516,7 +516,8 @@ transformAssignedExpr(ParseState *pstate,
attrtype, attrtypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ colname);
if (expr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -764,7 +765,8 @@ transformAssignmentIndirection(ParseState *pstate,
targetTypeId, targetTypMod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ "foo indirection");
if (result == NULL)
{
if (targetIsArray)
@@ -866,7 +868,8 @@ transformAssignmentSubscripts(ParseState *pstate,
targetTypeId, targetTypMod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ "foo subscript");
/* can fail if we had int2vector/oidvector, but not for true domains */
if (result == NULL)
ereport(ERROR,
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index bbd6b77..e5a55e3 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -811,7 +811,8 @@ rewriteTargetListIU(List *targetList,
COERCE_IMPLICIT_CAST,
-1,
false,
- false);
+ false,
+ NULL);
}
}
@@ -1066,7 +1067,8 @@ build_column_default(Relation rel, int attrno)
atttype, atttypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NameStr(att_tup->attname));
if (expr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -1176,7 +1178,8 @@ rewriteValuesRTE(RangeTblEntry *rte, Relation target_relation, List *attrnos)
COERCE_IMPLICIT_CAST,
-1,
false,
- false);
+ false,
+ NULL);
}
newList = lappend(newList, new_expr);
}
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index 1da90ff..eea17dd 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -1406,7 +1406,8 @@ ReplaceVarsFromTargetList_callback(Var *var,
COERCE_IMPLICIT_CAST,
-1,
false,
- false);
+ false,
+ NULL);
}
elog(ERROR, "could not find replacement targetlist entry for attno %d",
var->varattno);
diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c
index df9a2d7..1a9eec4 100644
--- a/src/backend/utils/adt/varchar.c
+++ b/src/backend/utils/adt/varchar.c
@@ -267,6 +267,7 @@ bpchar(PG_FUNCTION_ARGS)
BpChar *source = PG_GETARG_BPCHAR_PP(0);
int32 maxlen = PG_GETARG_INT32(1);
bool isExplicit = PG_GETARG_BOOL(2);
+ char *colname = PG_GETARG_CSTRING(3);
BpChar *result;
int32 len;
char *r;
@@ -303,7 +304,8 @@ bpchar(PG_FUNCTION_ARGS)
if (s[i] != ' ')
ereport(ERROR,
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
- errmsg("value too long for type character(%d)",
+ errmsg("value too long for %s of type character(%d)",
+ colname,
maxlen)));
}
@@ -594,6 +596,7 @@ varchar(PG_FUNCTION_ARGS)
VarChar *source = PG_GETARG_VARCHAR_PP(0);
int32 typmod = PG_GETARG_INT32(1);
bool isExplicit = PG_GETARG_BOOL(2);
+ char *colname = PG_GETARG_CSTRING(3);
int32 len,
maxlen;
size_t maxmblen;
@@ -619,7 +622,8 @@ varchar(PG_FUNCTION_ARGS)
if (s_data[i] != ' ')
ereport(ERROR,
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
- errmsg("value too long for type character varying(%d)",
+ errmsg("value too long for %s of type character varying(%d)",
+ colname ? colname : "(unknown column)",
maxlen)));
}
diff --git a/src/include/parser/parse_coerce.h b/src/include/parser/parse_coerce.h
index ec0ee14..cb131ce 100644
--- a/src/include/parser/parse_coerce.h
+++ b/src/include/parser/parse_coerce.h
@@ -40,17 +40,18 @@ extern Node *coerce_to_target_type(ParseState *pstate,
Oid targettype, int32 targettypmod,
CoercionContext ccontext,
CoercionForm cformat,
- int location);
+ int location,
+ char *colname);
extern bool can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
CoercionContext ccontext);
extern Node *coerce_type(ParseState *pstate, Node *node,
Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
- CoercionContext ccontext, CoercionForm cformat, int location);
+ CoercionContext ccontext, CoercionForm cformat, int location, char *colname);
extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod,
Oid typeId,
CoercionForm cformat, int location,
bool hideInputCoercion,
- bool lengthCoercionDone);
+ bool lengthCoercionDone, char *colname);
extern Node *coerce_to_boolean(ParseState *pstate, Node *node,
const char *constructName);
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index aac7cda..9677887 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -6022,7 +6022,8 @@ get_cast_expression(PLpgSQL_execstate *estate,
dsttype, dsttypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
/*
* If there's no cast path according to the parser, fall back to using an
@@ -6046,7 +6047,8 @@ get_cast_expression(PLpgSQL_execstate *estate,
dsttype, dsttypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
- -1);
+ -1,
+ NULL);
}
/* Note: we don't bother labeling the expression tree with collation */
Franck Verrot <franck@verrot.fr> writes:
As far as I know, there is currently no way to find which column is triggering
an error on an INSERT or ALTER COLUMN statement. Example:
Indeed ...
Given my very restricted knowledge of PG's codebase I am not sure whether my
modifications are legitimate or not, so please don't hesitate to comment on
it and pointing where things are subpar to PG's codebase. In any case, it's
to be considered as WIP for the moment.
I think the way you're going at this is fundamentally wrong. It amounts
to an (undocumented) change to the API for datatype input functions, and
the only way it can work is to change *every datatype's* input function
to know about it. That's not practical. More, it doesn't cover errors
that are thrown from someplace other than a datatype input function.
Evaluation errors in domain check constraint expressions are an example
that would be very hard to manage this way. And the approach definitely
doesn't scale nicely when you start thinking about other contexts wherein
a datatype input operation or coercion might fail.
What seems more likely to lead to a usable patch is to arrange for the
extra information you want to be emitted as error "context", via an error
context callback that gets installed at the right times. We already have
that set up for datatype-specific errors detected by COPY IN, for example.
If you feed garbage data to COPY you get something like
ERROR: invalid input syntax for integer: "foo"
CONTEXT: COPY int8_tbl, line 2, column q2: "foo"
with no need for int8in to be directly aware of the context. You should
try adapting that methodology for the cases you're worried about.
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Wed, Jul 1, 2015 at 12:30 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
What seems more likely to lead to a usable patch is to arrange for the
extra information you want to be emitted as error "context", via an error
context callback that gets installed at the right times. ...
...
with no need for int8in to be directly aware of the context. You should
try adapting that methodology for the cases you're worried about.
Hi Tom (and others),
Sorry it took so long for me to follow up on this, hopefully I found a
couple
a hours today to try writing another patch.
In any case, thanks for reviewing my first attempt and taking time to write
such a detailed critique... I've learned a lot!
I am now using the error context callback stack. The current column name
and column type are passed to the callback packed inside a new structure
of type "TransformExprState".
Those information are then passed to `errhint` and will be presented to the
user later on (in case of coercion failure).
Please find the WIP patch attached.
(I've pushed the patch on my GH fork[1]https://github.com/franckverrot/postgres/commit/73dd2cd096c91cee1b501d5f94ba81037de30fd1 too).
Thanks again,
Franck
[1]: https://github.com/franckverrot/postgres/commit/73dd2cd096c91cee1b501d5f94ba81037de30fd1
https://github.com/franckverrot/postgres/commit/73dd2cd096c91cee1b501d5f94ba81037de30fd1
Attachments:
0001-Report-column-for-which-type-coercion-fails.patchapplication/octet-stream; name=0001-Report-column-for-which-type-coercion-fails.patchDownload
From 73dd2cd096c91cee1b501d5f94ba81037de30fd1 Mon Sep 17 00:00:00 2001
From: Franck Verrot <franck@verrot.fr>
Date: Sun, 9 Aug 2015 14:37:59 +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');
^
HINT: coercion failed for column "baz" of type integer
---
src/backend/parser/parse_target.c | 23 +++++++++++++++++++++++
src/include/parser/parse_node.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..6915d2c 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;
+
+ errhint("coercion failed for column \"%s\" of type %s\n",
+ 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_node.h b/src/include/parser/parse_node.h
index 5249945..69c77f1 100644
--- a/src/include/parser/parse_node.h
+++ b/src/include/parser/parse_node.h
@@ -233,4 +233,11 @@ extern ArrayRef *transformArraySubscripts(ParseState *pstate,
Node *assignFrom);
extern Const *make_const(ParseState *pstate, Value *value, int location);
+void TransformExprCallback(void *arg);
+typedef struct TransformExprState
+{
+ const char *column_name;
+ Oid expected_type;
+} TransformExprState;
+
#endif /* PARSE_NODE_H */
--
2.4.6
On Sun, Aug 9, 2015 at 11:44 AM, Franck Verrot <franck@verrot.fr> wrote:
On Wed, Jul 1, 2015 at 12:30 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
What seems more likely to lead to a usable patch is to arrange for the
extra information you want to be emitted as error "context", via an error
context callback that gets installed at the right times. ...
...
with no need for int8in to be directly aware of the context. You should
try adapting that methodology for the cases you're worried about.Hi Tom (and others),
Sorry it took so long for me to follow up on this, hopefully I found a
couple
a hours today to try writing another patch.In any case, thanks for reviewing my first attempt and taking time to write
such a detailed critique... I've learned a lot!I am now using the error context callback stack. The current column name
and column type are passed to the callback packed inside a new structure
of type "TransformExprState".
Those information are then passed to `errhint` and will be presented to the
user later on (in case of coercion failure).Please find the WIP patch attached.
(I've pushed the patch on my GH fork[1] too).
To make sure this doesn't get forgotten about, you may want to add it here:
https://commitfest.postgresql.org/action/commitfest_view/open
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Sun, Aug 9, 2015 at 8:44 AM, Franck Verrot <franck@verrot.fr> wrote:
On Wed, Jul 1, 2015 at 12:30 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
What seems more likely to lead to a usable patch is to arrange for the
extra information you want to be emitted as error "context", via an error
context callback that gets installed at the right times. ...
...
with no need for int8in to be directly aware of the context. You should
try adapting that methodology for the cases you're worried about.Hi Tom (and others),
Sorry it took so long for me to follow up on this, hopefully I found a
couple
a hours today to try writing another patch.In any case, thanks for reviewing my first attempt and taking time to write
such a detailed critique... I've learned a lot!I am now using the error context callback stack. The current column name
and column type are passed to the callback packed inside a new structure
of type "TransformExprState".
Those information are then passed to `errhint` and will be presented to the
user later on (in case of coercion failure).Please find the WIP patch attached.
(I've pushed the patch on my GH fork[1] too).
Hi Franck,
I like the idea of having the column name.
I took this for a test drive, and had some comments.on the user visible
parts.
The hints you add end in a new line, which then gives two new lines once
they are emitted. This is contrary to how other HINTs are formatted.
Other HINTs are complete sentences (start with a capital letter, end with a
period).
But I think these belong as CONTEXT or as DETAIL, not as HINT. The
messages are giving me details about where (which column) the error
occured, they aren't giving suggestions to me about what to do about it.
Cheers,
Jeff
Jeff Janes <jeff.janes@gmail.com> writes:
The hints you add end in a new line, which then gives two new lines once
they are emitted. This is contrary to how other HINTs are formatted.
Other HINTs are complete sentences (start with a capital letter, end with a
period).
But I think these belong as CONTEXT or as DETAIL, not as HINT. The
messages are giving me details about where (which column) the error
occured, they aren't giving suggestions to me about what to do about it.
We have specific style guidelines about this:
http://www.postgresql.org/docs/devel/static/error-message-reporting.html
http://www.postgresql.org/docs/devel/static/error-style-guide.html
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Wed, Aug 19, 2015 at 11:31 PM, Jeff Janes <jeff.janes@gmail.com> wrote:
I took this for a test drive, and had some comments.on the user visible
parts.
[...]
But I think these belong as CONTEXT or as DETAIL, not as HINT. The
messages are giving me details about where (which column) the error
occurred, they aren't giving suggestions to me about what to do about it.
Hi Jeff,
Somehow my email never went through. So thank you for the test drive, I've
tried to update my patch (that you will find attached) to reflect what you
said (DETAIL instead of HINT).
Thanks Tom for pointing me at the docs, I clearly wasn't respecting the
guidelines.
Cheers,
Franck
Attachments:
0001-Report-column-for-which-type-coercion-fails.patchapplication/octet-stream; name=0001-Report-column-for-which-type-coercion-fails.patchDownload
From f32fc17c5f8c1b54c81d05953930c9dce0ad7781 Mon Sep 17 00:00:00 2001
From: Franck Verrot <franck@verrot.fr>
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
Franck Verrot wrote:
On Wed, Aug 19, 2015 at 11:31 PM, Jeff Janes <jeff.janes@gmail.com> wrote:
I took this for a test drive, and had some comments.on the user visible
parts.
[...]
But I think these belong as CONTEXT or as DETAIL, not as HINT. The
messages are giving me details about where (which column) the error
occurred, they aren't giving suggestions to me about what to do about it.Hi Jeff,
Somehow my email never went through. So thank you for the test drive, I've
tried to update my patch (that you will find attached) to reflect what you
said (DETAIL instead of HINT).
I think you need errcontext(), not errdetail(). The most important
difference is that you can have multiple CONTEXT lines but only one
DETAIL; I think if you attach a second errdetail(), the first one is
overwritten.
--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Tue, Sep 15, 2015 at 7:12 AM, Alvaro Herrera <alvherre@2ndquadrant.com>
wrote:
I think you need errcontext(), not errdetail(). The most important
difference is that you can have multiple CONTEXT lines but only one
DETAIL; I think if you attach a second errdetail(), the first one is
overwritten.
Indeed, the first errdetail() will be overwritten. Here's another try.
Thanks again for looking at my patches!
--
Franck Verrot
Attachments:
0001-Report-column-for-which-type-coercion-fails.patchapplication/octet-stream; name=0001-Report-column-for-which-type-coercion-fails.patchDownload
From d4cfe80a38cf05aaa0908683cdf0662ba6a07369 Mon Sep 17 00:00:00 2001
From: Franck Verrot <franck@verrot.fr>
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');
^
CONTEXT: 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..78f82cd 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;
+
+ errcontext("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
On 2015-09-15 12:00:25 +0200, Franck Verrot wrote:
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 1b3fcd6..78f82cd 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; + + errcontext("coercion failed for column \"%s\" of type %s", + state->column_name, + format_type_be(state->expected_type)); +}
Why is this not a static function?
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;
Why the newline between the declarations? Why none afterwards?
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;
I see no need for this to be a struct defined in the header. Given that
TransformExprCallback isn't public, and the whole thing is specific to
TransformExprState...
My major complaint though, is that this doesn't contain any tests...
Could you update the patch to address these issues?
Greetings,
Andres Freund
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Sun, Oct 4, 2015 at 12:23 AM, Andres Freund <andres@anarazel.de> wrote:
On 2015-09-15 12:00:25 +0200, Franck Verrot wrote:
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 1b3fcd6..78f82cd 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; + + errcontext("coercion failed for column \"%s\" of type %s", + state->column_name, + format_type_be(state->expected_type)); +}Why is this not a static function?
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;Why the newline between the declarations? Why none afterwards?
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;I see no need for this to be a struct defined in the header. Given that
TransformExprCallback isn't public, and the whole thing is specific to
TransformExprState...My major complaint though, is that this doesn't contain any tests...
Could you update the patch to address these issues?
Patch is marked as returned with feedback, it has been two months
since the last review, and comments have not been addressed.
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Thanks Andres for the review.
Michael, please find attached a revised patch addressing, amongst some
other changes, the testing issue (`make check` passes now) and the
visibility of the ` TransformExprState` struct.
Thanks,
Franck
On Tue, Dec 22, 2015 at 1:49 PM, Michael Paquier <michael.paquier@gmail.com>
wrote:
On Sun, Oct 4, 2015 at 12:23 AM, Andres Freund <andres@anarazel.de> wrote:
On 2015-09-15 12:00:25 +0200, Franck Verrot wrote:
diff --git a/src/backend/parser/parse_target.cb/src/backend/parser/parse_target.c
index 1b3fcd6..78f82cd 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; + + errcontext("coercion failed for column \"%s\" of type %s", + state->column_name, + format_type_be(state->expected_type)); +}Why is this not a static function?
Expr *
transformAssignedExpr(ParseState *pstate,
Expr *expr,
@@ -405,6 +416,14 @@ transformAssignedExpr(ParseState *pstate,
Oid attrcollation; /* collation of targetcolumn */
ParseExprKind sv_expr_kind;
+ ErrorContextCallback errcallback;
+ TransformExprState testate;Why the newline between the declarations? Why none afterwards?
diff --git a/src/include/parser/parse_target.hb/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;I see no need for this to be a struct defined in the header. Given that
TransformExprCallback isn't public, and the whole thing is specific to
TransformExprState...My major complaint though, is that this doesn't contain any tests...
Could you update the patch to address these issues?
Patch is marked as returned with feedback, it has been two months
since the last review, and comments have not been addressed.
--
Michael
--
Franck Verrot
Attachments:
0001-Report-column-for-which-type-coercion-fails.patchapplication/octet-stream; name=0001-Report-column-for-which-type-coercion-fails.patchDownload
From d13629ee08803e045e5e626aff98557130153336 Mon Sep 17 00:00:00 2001
From: Franck Verrot <franck@verrot.fr>
Date: Tue, 4 Oct 2016 22:29:19 -0700
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');
^
CONTEXT: coercion failed for column "baz" of type integer
---
src/backend/parser/parse_target.c | 30 +++++++++++++++++++++++++++++-
src/test/regress/expected/abstime.out | 3 +++
src/test/regress/expected/box.out | 2 ++
src/test/regress/expected/circle.out | 3 +++
src/test/regress/expected/date.out | 1 +
src/test/regress/expected/float4.out | 12 ++++++++++++
src/test/regress/expected/float8.out | 12 ++++++++++++
src/test/regress/expected/inet.out | 2 ++
src/test/regress/expected/insert.out | 2 ++
src/test/regress/expected/int2.out | 8 ++++++++
src/test/regress/expected/int4.out | 8 ++++++++
src/test/regress/expected/int8.out | 7 +++++++
src/test/regress/expected/interval.out | 2 ++
src/test/regress/expected/line.out | 6 ++++++
src/test/regress/expected/lseg.out | 4 ++++
src/test/regress/expected/macaddr.out | 2 ++
src/test/regress/expected/numeric.out | 8 ++++++++
src/test/regress/expected/oid.out | 10 ++++++++++
src/test/regress/expected/path.out | 2 ++
src/test/regress/expected/pg_lsn.out | 5 +++++
src/test/regress/expected/point.out | 3 +++
src/test/regress/expected/polygon.out | 5 +++++
src/test/regress/expected/reltime.out | 2 ++
src/test/regress/expected/rowtypes.out | 1 +
src/test/regress/expected/time.out | 1 +
src/test/regress/expected/timestamp.out | 7 +++++++
src/test/regress/expected/timestamptz.out | 7 +++++++
src/test/regress/expected/timetz.out | 1 +
src/test/regress/expected/tinterval.out | 2 ++
src/test/regress/expected/uuid.out | 6 ++++++
src/test/regress/expected/xml_1.out | 3 +++
31 files changed, 166 insertions(+), 1 deletion(-)
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index b7b82bf..31d000b 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -389,6 +389,23 @@ 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.
*/
+
+typedef struct TransformExprState
+{
+ const char *column_name;
+ Oid expected_type;
+} TransformExprState;
+
+static void
+TransformExprCallback(void *arg)
+{
+ TransformExprState *state = (TransformExprState *) arg;
+
+ errcontext("coercion failed for column \"%s\" of type %s",
+ state->column_name,
+ format_type_be(state->expected_type));
+}
+
Expr *
transformAssignedExpr(ParseState *pstate,
Expr *expr,
@@ -404,7 +421,14 @@ transformAssignedExpr(ParseState *pstate,
int32 attrtypmod;
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 +449,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 +556,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/test/regress/expected/abstime.out b/src/test/regress/expected/abstime.out
index ed48f64..2317b28 100644
--- a/src/test/regress/expected/abstime.out
+++ b/src/test/regress/expected/abstime.out
@@ -32,15 +32,18 @@ ERROR: date/time field value out of range: "Feb 35, 1946 10:00:00"
LINE 1: INSERT INTO ABSTIME_TBL (f1) VALUES ('Feb 35, 1946 10:00:00'...
^
HINT: Perhaps you need a different "datestyle" setting.
+CONTEXT: coercion failed for column "f1" of type abstime
INSERT INTO ABSTIME_TBL (f1) VALUES ('Feb 28, 1984 25:08:10');
ERROR: date/time field value out of range: "Feb 28, 1984 25:08:10"
LINE 1: INSERT INTO ABSTIME_TBL (f1) VALUES ('Feb 28, 1984 25:08:10'...
^
+CONTEXT: coercion failed for column "f1" of type abstime
-- badly formatted abstimes: these should result in invalid abstimes
INSERT INTO ABSTIME_TBL (f1) VALUES ('bad date format');
ERROR: invalid input syntax for type abstime: "bad date format"
LINE 1: INSERT INTO ABSTIME_TBL (f1) VALUES ('bad date format');
^
+CONTEXT: coercion failed for column "f1" of type abstime
INSERT INTO ABSTIME_TBL (f1) VALUES ('Jun 10, 1843');
-- test abstime operators
SELECT '' AS eight, * FROM ABSTIME_TBL;
diff --git a/src/test/regress/expected/box.out b/src/test/regress/expected/box.out
index 5f8b945..5566c84 100644
--- a/src/test/regress/expected/box.out
+++ b/src/test/regress/expected/box.out
@@ -27,10 +27,12 @@ INSERT INTO BOX_TBL (f1) VALUES ('(2.3, 4.5)');
ERROR: invalid input syntax for type box: "(2.3, 4.5)"
LINE 1: INSERT INTO BOX_TBL (f1) VALUES ('(2.3, 4.5)');
^
+CONTEXT: coercion failed for column "f1" of type box
INSERT INTO BOX_TBL (f1) VALUES ('asdfasdf(ad');
ERROR: invalid input syntax for type box: "asdfasdf(ad"
LINE 1: INSERT INTO BOX_TBL (f1) VALUES ('asdfasdf(ad');
^
+CONTEXT: coercion failed for column "f1" of type box
SELECT '' AS four, * FROM BOX_TBL;
four | f1
------+---------------------
diff --git a/src/test/regress/expected/circle.out b/src/test/regress/expected/circle.out
index 9ba4a04..ece0eb8 100644
--- a/src/test/regress/expected/circle.out
+++ b/src/test/regress/expected/circle.out
@@ -13,14 +13,17 @@ INSERT INTO CIRCLE_TBL VALUES ('<(-100,0),-100>');
ERROR: invalid input syntax for type circle: "<(-100,0),-100>"
LINE 1: INSERT INTO CIRCLE_TBL VALUES ('<(-100,0),-100>');
^
+CONTEXT: coercion failed for column "f1" of type circle
INSERT INTO CIRCLE_TBL VALUES ('1abc,3,5');
ERROR: invalid input syntax for type circle: "1abc,3,5"
LINE 1: INSERT INTO CIRCLE_TBL VALUES ('1abc,3,5');
^
+CONTEXT: coercion failed for column "f1" of type circle
INSERT INTO CIRCLE_TBL VALUES ('(3,(1,2),3)');
ERROR: invalid input syntax for type circle: "(3,(1,2),3)"
LINE 1: INSERT INTO CIRCLE_TBL VALUES ('(3,(1,2),3)');
^
+CONTEXT: coercion failed for column "f1" of type circle
SELECT * FROM CIRCLE_TBL;
f1
----------------
diff --git a/src/test/regress/expected/date.out b/src/test/regress/expected/date.out
index 418b146..856374a 100644
--- a/src/test/regress/expected/date.out
+++ b/src/test/regress/expected/date.out
@@ -13,6 +13,7 @@ INSERT INTO DATE_TBL VALUES ('1997-02-29');
ERROR: date/time field value out of range: "1997-02-29"
LINE 1: INSERT INTO DATE_TBL VALUES ('1997-02-29');
^
+CONTEXT: coercion failed for column "f1" of type date
INSERT INTO DATE_TBL VALUES ('1997-03-01');
INSERT INTO DATE_TBL VALUES ('1997-03-02');
INSERT INTO DATE_TBL VALUES ('2000-04-01');
diff --git a/src/test/regress/expected/float4.out b/src/test/regress/expected/float4.out
index fd46a4a..c04176f 100644
--- a/src/test/regress/expected/float4.out
+++ b/src/test/regress/expected/float4.out
@@ -12,51 +12,63 @@ INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
ERROR: value out of range: overflow
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
^
+CONTEXT: coercion failed for column "f1" of type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
ERROR: value out of range: overflow
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
^
+CONTEXT: coercion failed for column "f1" of type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
ERROR: value out of range: underflow
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
^
+CONTEXT: coercion failed for column "f1" of type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
ERROR: value out of range: underflow
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
^
+CONTEXT: coercion failed for column "f1" of type real
-- bad input
INSERT INTO FLOAT4_TBL(f1) VALUES ('');
ERROR: invalid input syntax for type real: ""
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('');
^
+CONTEXT: coercion failed for column "f1" of type real
INSERT INTO FLOAT4_TBL(f1) VALUES (' ');
ERROR: invalid input syntax for type real: " "
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES (' ');
^
+CONTEXT: coercion failed for column "f1" of type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('xyz');
ERROR: invalid input syntax for type real: "xyz"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('xyz');
^
+CONTEXT: coercion failed for column "f1" of type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('5.0.0');
ERROR: invalid input syntax for type real: "5.0.0"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5.0.0');
^
+CONTEXT: coercion failed for column "f1" of type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('5 . 0');
ERROR: invalid input syntax for type real: "5 . 0"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5 . 0');
^
+CONTEXT: coercion failed for column "f1" of type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('5. 0');
ERROR: invalid input syntax for type real: "5. 0"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5. 0');
^
+CONTEXT: coercion failed for column "f1" of type real
INSERT INTO FLOAT4_TBL(f1) VALUES (' - 3.0');
ERROR: invalid input syntax for type real: " - 3.0"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES (' - 3.0');
^
+CONTEXT: coercion failed for column "f1" of type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5');
ERROR: invalid input syntax for type real: "123 5"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5');
^
+CONTEXT: coercion failed for column "f1" of type real
-- special inputs
SELECT 'NaN'::float4;
float4
diff --git a/src/test/regress/expected/float8.out b/src/test/regress/expected/float8.out
index 20c985e..dc52103 100644
--- a/src/test/regress/expected/float8.out
+++ b/src/test/regress/expected/float8.out
@@ -29,34 +29,42 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('');
ERROR: invalid input syntax for type double precision: ""
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('');
^
+CONTEXT: coercion failed for column "f1" of type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES (' ');
ERROR: invalid input syntax for type double precision: " "
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' ');
^
+CONTEXT: coercion failed for column "f1" of type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz');
ERROR: invalid input syntax for type double precision: "xyz"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz');
^
+CONTEXT: coercion failed for column "f1" of type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0');
ERROR: invalid input syntax for type double precision: "5.0.0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0');
^
+CONTEXT: coercion failed for column "f1" of type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0');
ERROR: invalid input syntax for type double precision: "5 . 0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0');
^
+CONTEXT: coercion failed for column "f1" of type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0');
ERROR: invalid input syntax for type double precision: "5. 0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0');
^
+CONTEXT: coercion failed for column "f1" of type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3');
ERROR: invalid input syntax for type double precision: " - 3"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3');
^
+CONTEXT: coercion failed for column "f1" of type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5');
ERROR: invalid input syntax for type double precision: "123 5"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5');
^
+CONTEXT: coercion failed for column "f1" of type double precision
-- special inputs
SELECT 'NaN'::float8;
float8
@@ -414,18 +422,22 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400');
ERROR: "10e400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400');
^
+CONTEXT: coercion failed for column "f1" of type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400');
ERROR: "-10e400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400');
^
+CONTEXT: coercion failed for column "f1" of type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400');
ERROR: "10e-400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400');
^
+CONTEXT: coercion failed for column "f1" of type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400');
ERROR: "-10e-400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400');
^
+CONTEXT: coercion failed for column "f1" of type double precision
-- maintain external table consistency across platforms
-- delete all values and reinsert well-behaved ones
DELETE FROM FLOAT8_TBL;
diff --git a/src/test/regress/expected/inet.out b/src/test/regress/expected/inet.out
index be9427e..fc1fff7 100644
--- a/src/test/regress/expected/inet.out
+++ b/src/test/regress/expected/inet.out
@@ -28,10 +28,12 @@ ERROR: invalid cidr value: "192.168.1.2/30"
LINE 1: INSERT INTO INET_TBL (c, i) VALUES ('192.168.1.2/30', '192.1...
^
DETAIL: Value has bits set to right of mask.
+CONTEXT: coercion failed for column "c" of type cidr
INSERT INTO INET_TBL (c, i) VALUES ('1234::1234::1234', '::1.2.3.4');
ERROR: invalid input syntax for type cidr: "1234::1234::1234"
LINE 1: INSERT INTO INET_TBL (c, i) VALUES ('1234::1234::1234', '::1...
^
+CONTEXT: coercion failed for column "c" of type cidr
-- check that CIDR rejects invalid input when converting from text:
INSERT INTO INET_TBL (c, i) VALUES (cidr('192.168.1.2/30'), '192.168.1.226');
ERROR: invalid cidr value: "192.168.1.2/30"
diff --git a/src/test/regress/expected/insert.out b/src/test/regress/expected/insert.out
index 70107b5..9b599ae 100644
--- a/src/test/regress/expected/insert.out
+++ b/src/test/regress/expected/insert.out
@@ -96,6 +96,7 @@ insert into inserttest (f2[1], f2[2]) values (1,default); -- not supported
ERROR: cannot set an array element to DEFAULT
LINE 1: insert into inserttest (f2[1], f2[2]) values (1,default);
^
+CONTEXT: coercion failed for column "f2" of type integer[]
insert into inserttest (f3.if1, f3.if2) values (1,array['foo']);
insert into inserttest (f3.if1, f3.if2) values (1,'{foo}'), (2,'{bar}');
insert into inserttest (f3.if1, f3.if2) select 3, '{baz,quux}';
@@ -103,6 +104,7 @@ insert into inserttest (f3.if1, f3.if2) values (1,default); -- not supported
ERROR: cannot set a subfield to DEFAULT
LINE 1: insert into inserttest (f3.if1, f3.if2) values (1,default);
^
+CONTEXT: coercion failed for column "f3" of type insert_test_type
insert into inserttest (f3.if2[1], f3.if2[2]) values ('foo', 'bar');
insert into inserttest (f3.if2[1], f3.if2[2]) values ('foo', 'bar'), ('baz', 'quux');
insert into inserttest (f3.if2[1], f3.if2[2]) select 'bear', 'beer';
diff --git a/src/test/regress/expected/int2.out b/src/test/regress/expected/int2.out
index 3ea4ed9..c4ab9d8 100644
--- a/src/test/regress/expected/int2.out
+++ b/src/test/regress/expected/int2.out
@@ -9,6 +9,7 @@ INSERT INTO INT2_TBL(f1) VALUES ('34.5');
ERROR: invalid input syntax for integer: "34.5"
LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('34.5');
^
+CONTEXT: coercion failed for column "f1" of type smallint
-- largest and smallest values
INSERT INTO INT2_TBL(f1) VALUES ('32767');
INSERT INTO INT2_TBL(f1) VALUES ('-32767');
@@ -17,30 +18,37 @@ INSERT INTO INT2_TBL(f1) VALUES ('100000');
ERROR: value "100000" is out of range for type smallint
LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('100000');
^
+CONTEXT: coercion failed for column "f1" of type smallint
INSERT INTO INT2_TBL(f1) VALUES ('asdf');
ERROR: invalid input syntax for integer: "asdf"
LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('asdf');
^
+CONTEXT: coercion failed for column "f1" of type smallint
INSERT INTO INT2_TBL(f1) VALUES (' ');
ERROR: invalid input syntax for integer: " "
LINE 1: INSERT INTO INT2_TBL(f1) VALUES (' ');
^
+CONTEXT: coercion failed for column "f1" of type smallint
INSERT INTO INT2_TBL(f1) VALUES ('- 1234');
ERROR: invalid input syntax for integer: "- 1234"
LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('- 1234');
^
+CONTEXT: coercion failed for column "f1" of type smallint
INSERT INTO INT2_TBL(f1) VALUES ('4 444');
ERROR: invalid input syntax for integer: "4 444"
LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('4 444');
^
+CONTEXT: coercion failed for column "f1" of type smallint
INSERT INTO INT2_TBL(f1) VALUES ('123 dt');
ERROR: invalid input syntax for integer: "123 dt"
LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('123 dt');
^
+CONTEXT: coercion failed for column "f1" of type smallint
INSERT INTO INT2_TBL(f1) VALUES ('');
ERROR: invalid input syntax for integer: ""
LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('');
^
+CONTEXT: coercion failed for column "f1" of type smallint
SELECT '' AS five, * FROM INT2_TBL;
five | f1
------+--------
diff --git a/src/test/regress/expected/int4.out b/src/test/regress/expected/int4.out
index 372fd4d..4bd9cc9 100644
--- a/src/test/regress/expected/int4.out
+++ b/src/test/regress/expected/int4.out
@@ -9,6 +9,7 @@ INSERT INTO INT4_TBL(f1) VALUES ('34.5');
ERROR: invalid input syntax for integer: "34.5"
LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('34.5');
^
+CONTEXT: coercion failed for column "f1" of type integer
-- largest and smallest values
INSERT INTO INT4_TBL(f1) VALUES ('2147483647');
INSERT INTO INT4_TBL(f1) VALUES ('-2147483647');
@@ -17,30 +18,37 @@ INSERT INTO INT4_TBL(f1) VALUES ('1000000000000');
ERROR: value "1000000000000" is out of range for type integer
LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('1000000000000');
^
+CONTEXT: coercion failed for column "f1" of type integer
INSERT INTO INT4_TBL(f1) VALUES ('asdf');
ERROR: invalid input syntax for integer: "asdf"
LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('asdf');
^
+CONTEXT: coercion failed for column "f1" of type integer
INSERT INTO INT4_TBL(f1) VALUES (' ');
ERROR: invalid input syntax for integer: " "
LINE 1: INSERT INTO INT4_TBL(f1) VALUES (' ');
^
+CONTEXT: coercion failed for column "f1" of type integer
INSERT INTO INT4_TBL(f1) VALUES (' asdf ');
ERROR: invalid input syntax for integer: " asdf "
LINE 1: INSERT INTO INT4_TBL(f1) VALUES (' asdf ');
^
+CONTEXT: coercion failed for column "f1" of type integer
INSERT INTO INT4_TBL(f1) VALUES ('- 1234');
ERROR: invalid input syntax for integer: "- 1234"
LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('- 1234');
^
+CONTEXT: coercion failed for column "f1" of type integer
INSERT INTO INT4_TBL(f1) VALUES ('123 5');
ERROR: invalid input syntax for integer: "123 5"
LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('123 5');
^
+CONTEXT: coercion failed for column "f1" of type integer
INSERT INTO INT4_TBL(f1) VALUES ('');
ERROR: invalid input syntax for integer: ""
LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('');
^
+CONTEXT: coercion failed for column "f1" of type integer
SELECT '' AS five, * FROM INT4_TBL;
five | f1
------+-------------
diff --git a/src/test/regress/expected/int8.out b/src/test/regress/expected/int8.out
index ed0bd34..3dfb38d 100644
--- a/src/test/regress/expected/int8.out
+++ b/src/test/regress/expected/int8.out
@@ -13,30 +13,37 @@ INSERT INTO INT8_TBL(q1) VALUES (' ');
ERROR: invalid input syntax for integer: " "
LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' ');
^
+CONTEXT: coercion failed for column "q1" of type bigint
INSERT INTO INT8_TBL(q1) VALUES ('xxx');
ERROR: invalid input syntax for integer: "xxx"
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('xxx');
^
+CONTEXT: coercion failed for column "q1" of type bigint
INSERT INTO INT8_TBL(q1) VALUES ('3908203590239580293850293850329485');
ERROR: value "3908203590239580293850293850329485" is out of range for type bigint
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('39082035902395802938502938...
^
+CONTEXT: coercion failed for column "q1" of type bigint
INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340329840934');
ERROR: value "-1204982019841029840928340329840934" is out of range for type bigint
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340...
^
+CONTEXT: coercion failed for column "q1" of type bigint
INSERT INTO INT8_TBL(q1) VALUES ('- 123');
ERROR: invalid input syntax for integer: "- 123"
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('- 123');
^
+CONTEXT: coercion failed for column "q1" of type bigint
INSERT INTO INT8_TBL(q1) VALUES (' 345 5');
ERROR: invalid input syntax for integer: " 345 5"
LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' 345 5');
^
+CONTEXT: coercion failed for column "q1" of type bigint
INSERT INTO INT8_TBL(q1) VALUES ('');
ERROR: invalid input syntax for integer: ""
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('');
^
+CONTEXT: coercion failed for column "q1" of type bigint
SELECT * FROM INT8_TBL;
q1 | q2
------------------+-------------------
diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out
index c873a99..439272e 100644
--- a/src/test/regress/expected/interval.out
+++ b/src/test/regress/expected/interval.out
@@ -68,10 +68,12 @@ INSERT INTO INTERVAL_TBL (f1) VALUES ('badly formatted interval');
ERROR: invalid input syntax for type interval: "badly formatted interval"
LINE 1: INSERT INTO INTERVAL_TBL (f1) VALUES ('badly formatted inter...
^
+CONTEXT: coercion failed for column "f1" of type interval
INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 30 eons ago');
ERROR: invalid input syntax for type interval: "@ 30 eons ago"
LINE 1: INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 30 eons ago');
^
+CONTEXT: coercion failed for column "f1" of type interval
-- test interval operators
SELECT '' AS ten, * FROM INTERVAL_TBL;
ten | f1
diff --git a/src/test/regress/expected/line.out b/src/test/regress/expected/line.out
index f20abdc..85ae175 100644
--- a/src/test/regress/expected/line.out
+++ b/src/test/regress/expected/line.out
@@ -13,6 +13,7 @@ INSERT INTO LINE_TBL VALUES ('[(1,0),(1,0)]');
ERROR: invalid line specification: must be two distinct points
LINE 1: INSERT INTO LINE_TBL VALUES ('[(1,0),(1,0)]');
^
+CONTEXT: coercion failed for column "s" of type line
-- horizontal
INSERT INTO LINE_TBL VALUES ('[(1,3),(2,3)]');
-- vertical
@@ -22,22 +23,27 @@ INSERT INTO LINE_TBL VALUES ('{0,0,1}');
ERROR: invalid line specification: A and B cannot both be zero
LINE 1: INSERT INTO LINE_TBL VALUES ('{0,0,1}');
^
+CONTEXT: coercion failed for column "s" of type line
INSERT INTO LINE_TBL VALUES ('(3asdf,2 ,3,4r2)');
ERROR: invalid input syntax for type line: "(3asdf,2 ,3,4r2)"
LINE 1: INSERT INTO LINE_TBL VALUES ('(3asdf,2 ,3,4r2)');
^
+CONTEXT: coercion failed for column "s" of type line
INSERT INTO LINE_TBL VALUES ('[1,2,3, 4');
ERROR: invalid input syntax for type line: "[1,2,3, 4"
LINE 1: INSERT INTO LINE_TBL VALUES ('[1,2,3, 4');
^
+CONTEXT: coercion failed for column "s" of type line
INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
ERROR: invalid input syntax for type line: "[(,2),(3,4)]"
LINE 1: INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
^
+CONTEXT: coercion failed for column "s" of type line
INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
ERROR: invalid input syntax for type line: "[(1,2),(3,4)"
LINE 1: INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
^
+CONTEXT: coercion failed for column "s" of type line
select * from LINE_TBL;
s
---------------------------------------------
diff --git a/src/test/regress/expected/lseg.out b/src/test/regress/expected/lseg.out
index bba1f3e..58c79af 100644
--- a/src/test/regress/expected/lseg.out
+++ b/src/test/regress/expected/lseg.out
@@ -14,18 +14,22 @@ INSERT INTO LSEG_TBL VALUES ('(3asdf,2 ,3,4r2)');
ERROR: invalid input syntax for type lseg: "(3asdf,2 ,3,4r2)"
LINE 1: INSERT INTO LSEG_TBL VALUES ('(3asdf,2 ,3,4r2)');
^
+CONTEXT: coercion failed for column "s" of type lseg
INSERT INTO LSEG_TBL VALUES ('[1,2,3, 4');
ERROR: invalid input syntax for type lseg: "[1,2,3, 4"
LINE 1: INSERT INTO LSEG_TBL VALUES ('[1,2,3, 4');
^
+CONTEXT: coercion failed for column "s" of type lseg
INSERT INTO LSEG_TBL VALUES ('[(,2),(3,4)]');
ERROR: invalid input syntax for type lseg: "[(,2),(3,4)]"
LINE 1: INSERT INTO LSEG_TBL VALUES ('[(,2),(3,4)]');
^
+CONTEXT: coercion failed for column "s" of type lseg
INSERT INTO LSEG_TBL VALUES ('[(1,2),(3,4)');
ERROR: invalid input syntax for type lseg: "[(1,2),(3,4)"
LINE 1: INSERT INTO LSEG_TBL VALUES ('[(1,2),(3,4)');
^
+CONTEXT: coercion failed for column "s" of type lseg
select * from LSEG_TBL;
s
-------------------------------
diff --git a/src/test/regress/expected/macaddr.out b/src/test/regress/expected/macaddr.out
index e84ff5f..bd30b5f 100644
--- a/src/test/regress/expected/macaddr.out
+++ b/src/test/regress/expected/macaddr.out
@@ -13,10 +13,12 @@ INSERT INTO macaddr_data VALUES (8, '0800:2b01:0203'); -- invalid
ERROR: invalid input syntax for type macaddr: "0800:2b01:0203"
LINE 1: INSERT INTO macaddr_data VALUES (8, '0800:2b01:0203');
^
+CONTEXT: coercion failed for column "b" of type macaddr
INSERT INTO macaddr_data VALUES (9, 'not even close'); -- invalid
ERROR: invalid input syntax for type macaddr: "not even close"
LINE 1: INSERT INTO macaddr_data VALUES (9, 'not even close');
^
+CONTEXT: coercion failed for column "b" of type macaddr
INSERT INTO macaddr_data VALUES (10, '08:00:2b:01:02:04');
INSERT INTO macaddr_data VALUES (11, '08:00:2b:01:02:02');
INSERT INTO macaddr_data VALUES (12, '08:00:2a:01:02:03');
diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expected/numeric.out
index ae0beb9..a1a03fe 100644
--- a/src/test/regress/expected/numeric.out
+++ b/src/test/regress/expected/numeric.out
@@ -1293,34 +1293,42 @@ INSERT INTO num_input_test(n1) VALUES (' ');
ERROR: invalid input syntax for type numeric: " "
LINE 1: INSERT INTO num_input_test(n1) VALUES (' ');
^
+CONTEXT: coercion failed for column "n1" of type numeric
INSERT INTO num_input_test(n1) VALUES (' 1234 %');
ERROR: invalid input syntax for type numeric: " 1234 %"
LINE 1: INSERT INTO num_input_test(n1) VALUES (' 1234 %');
^
+CONTEXT: coercion failed for column "n1" of type numeric
INSERT INTO num_input_test(n1) VALUES ('xyz');
ERROR: invalid input syntax for type numeric: "xyz"
LINE 1: INSERT INTO num_input_test(n1) VALUES ('xyz');
^
+CONTEXT: coercion failed for column "n1" of type numeric
INSERT INTO num_input_test(n1) VALUES ('- 1234');
ERROR: invalid input syntax for type numeric: "- 1234"
LINE 1: INSERT INTO num_input_test(n1) VALUES ('- 1234');
^
+CONTEXT: coercion failed for column "n1" of type numeric
INSERT INTO num_input_test(n1) VALUES ('5 . 0');
ERROR: invalid input syntax for type numeric: "5 . 0"
LINE 1: INSERT INTO num_input_test(n1) VALUES ('5 . 0');
^
+CONTEXT: coercion failed for column "n1" of type numeric
INSERT INTO num_input_test(n1) VALUES ('5. 0 ');
ERROR: invalid input syntax for type numeric: "5. 0 "
LINE 1: INSERT INTO num_input_test(n1) VALUES ('5. 0 ');
^
+CONTEXT: coercion failed for column "n1" of type numeric
INSERT INTO num_input_test(n1) VALUES ('');
ERROR: invalid input syntax for type numeric: ""
LINE 1: INSERT INTO num_input_test(n1) VALUES ('');
^
+CONTEXT: coercion failed for column "n1" of type numeric
INSERT INTO num_input_test(n1) VALUES (' N aN ');
ERROR: invalid input syntax for type numeric: " N aN "
LINE 1: INSERT INTO num_input_test(n1) VALUES (' N aN ');
^
+CONTEXT: coercion failed for column "n1" of type numeric
SELECT * FROM num_input_test;
n1
---------
diff --git a/src/test/regress/expected/oid.out b/src/test/regress/expected/oid.out
index 1eab9cc..ce8f149 100644
--- a/src/test/regress/expected/oid.out
+++ b/src/test/regress/expected/oid.out
@@ -16,42 +16,52 @@ INSERT INTO OID_TBL(f1) VALUES ('');
ERROR: invalid input syntax for type oid: ""
LINE 1: INSERT INTO OID_TBL(f1) VALUES ('');
^
+CONTEXT: coercion failed for column "f1" of type oid
INSERT INTO OID_TBL(f1) VALUES (' ');
ERROR: invalid input syntax for type oid: " "
LINE 1: INSERT INTO OID_TBL(f1) VALUES (' ');
^
+CONTEXT: coercion failed for column "f1" of type oid
INSERT INTO OID_TBL(f1) VALUES ('asdfasd');
ERROR: invalid input syntax for type oid: "asdfasd"
LINE 1: INSERT INTO OID_TBL(f1) VALUES ('asdfasd');
^
+CONTEXT: coercion failed for column "f1" of type oid
INSERT INTO OID_TBL(f1) VALUES ('99asdfasd');
ERROR: invalid input syntax for type oid: "99asdfasd"
LINE 1: INSERT INTO OID_TBL(f1) VALUES ('99asdfasd');
^
+CONTEXT: coercion failed for column "f1" of type oid
INSERT INTO OID_TBL(f1) VALUES ('5 d');
ERROR: invalid input syntax for type oid: "5 d"
LINE 1: INSERT INTO OID_TBL(f1) VALUES ('5 d');
^
+CONTEXT: coercion failed for column "f1" of type oid
INSERT INTO OID_TBL(f1) VALUES (' 5d');
ERROR: invalid input syntax for type oid: " 5d"
LINE 1: INSERT INTO OID_TBL(f1) VALUES (' 5d');
^
+CONTEXT: coercion failed for column "f1" of type oid
INSERT INTO OID_TBL(f1) VALUES ('5 5');
ERROR: invalid input syntax for type oid: "5 5"
LINE 1: INSERT INTO OID_TBL(f1) VALUES ('5 5');
^
+CONTEXT: coercion failed for column "f1" of type oid
INSERT INTO OID_TBL(f1) VALUES (' - 500');
ERROR: invalid input syntax for type oid: " - 500"
LINE 1: INSERT INTO OID_TBL(f1) VALUES (' - 500');
^
+CONTEXT: coercion failed for column "f1" of type oid
INSERT INTO OID_TBL(f1) VALUES ('32958209582039852935');
ERROR: value "32958209582039852935" is out of range for type oid
LINE 1: INSERT INTO OID_TBL(f1) VALUES ('32958209582039852935');
^
+CONTEXT: coercion failed for column "f1" of type oid
INSERT INTO OID_TBL(f1) VALUES ('-23582358720398502385');
ERROR: value "-23582358720398502385" is out of range for type oid
LINE 1: INSERT INTO OID_TBL(f1) VALUES ('-23582358720398502385');
^
+CONTEXT: coercion failed for column "f1" of type oid
SELECT '' AS six, * FROM OID_TBL;
six | f1
-----+------------
diff --git a/src/test/regress/expected/path.out b/src/test/regress/expected/path.out
index 08d6d61..53a40f9 100644
--- a/src/test/regress/expected/path.out
+++ b/src/test/regress/expected/path.out
@@ -16,10 +16,12 @@ INSERT INTO PATH_TBL VALUES ('[(,2),(3,4)]');
ERROR: invalid input syntax for type path: "[(,2),(3,4)]"
LINE 1: INSERT INTO PATH_TBL VALUES ('[(,2),(3,4)]');
^
+CONTEXT: coercion failed for column "f1" of type path
INSERT INTO PATH_TBL VALUES ('[(1,2),(3,4)');
ERROR: invalid input syntax for type path: "[(1,2),(3,4)"
LINE 1: INSERT INTO PATH_TBL VALUES ('[(1,2),(3,4)');
^
+CONTEXT: coercion failed for column "f1" of type path
SELECT f1 FROM PATH_TBL;
f1
---------------------------
diff --git a/src/test/regress/expected/pg_lsn.out b/src/test/regress/expected/pg_lsn.out
index 2854cfd..869929e 100644
--- a/src/test/regress/expected/pg_lsn.out
+++ b/src/test/regress/expected/pg_lsn.out
@@ -10,22 +10,27 @@ INSERT INTO PG_LSN_TBL VALUES ('G/0');
ERROR: invalid input syntax for type pg_lsn: "G/0"
LINE 1: INSERT INTO PG_LSN_TBL VALUES ('G/0');
^
+CONTEXT: coercion failed for column "f1" of type pg_lsn
INSERT INTO PG_LSN_TBL VALUES ('-1/0');
ERROR: invalid input syntax for type pg_lsn: "-1/0"
LINE 1: INSERT INTO PG_LSN_TBL VALUES ('-1/0');
^
+CONTEXT: coercion failed for column "f1" of type pg_lsn
INSERT INTO PG_LSN_TBL VALUES (' 0/12345678');
ERROR: invalid input syntax for type pg_lsn: " 0/12345678"
LINE 1: INSERT INTO PG_LSN_TBL VALUES (' 0/12345678');
^
+CONTEXT: coercion failed for column "f1" of type pg_lsn
INSERT INTO PG_LSN_TBL VALUES ('ABCD/');
ERROR: invalid input syntax for type pg_lsn: "ABCD/"
LINE 1: INSERT INTO PG_LSN_TBL VALUES ('ABCD/');
^
+CONTEXT: coercion failed for column "f1" of type pg_lsn
INSERT INTO PG_LSN_TBL VALUES ('/ABCD');
ERROR: invalid input syntax for type pg_lsn: "/ABCD"
LINE 1: INSERT INTO PG_LSN_TBL VALUES ('/ABCD');
^
+CONTEXT: coercion failed for column "f1" of type pg_lsn
DROP TABLE PG_LSN_TBL;
-- Operators
SELECT '0/16AE7F8' = '0/16AE7F8'::pg_lsn;
diff --git a/src/test/regress/expected/point.out b/src/test/regress/expected/point.out
index bfc0962..2733b4c 100644
--- a/src/test/regress/expected/point.out
+++ b/src/test/regress/expected/point.out
@@ -12,15 +12,18 @@ INSERT INTO POINT_TBL(f1) VALUES ('asdfasdf');
ERROR: invalid input syntax for type point: "asdfasdf"
LINE 1: INSERT INTO POINT_TBL(f1) VALUES ('asdfasdf');
^
+CONTEXT: coercion failed for column "f1" of type point
INSERT INTO POINT_TBL(f1) VALUES ('10.0,10.0');
INSERT INTO POINT_TBL(f1) VALUES ('(10.0 10.0)');
ERROR: invalid input syntax for type point: "(10.0 10.0)"
LINE 1: INSERT INTO POINT_TBL(f1) VALUES ('(10.0 10.0)');
^
+CONTEXT: coercion failed for column "f1" of type point
INSERT INTO POINT_TBL(f1) VALUES ('(10.0,10.0');
ERROR: invalid input syntax for type point: "(10.0,10.0"
LINE 1: INSERT INTO POINT_TBL(f1) VALUES ('(10.0,10.0');
^
+CONTEXT: coercion failed for column "f1" of type point
SELECT '' AS six, * FROM POINT_TBL;
six | f1
-----+------------
diff --git a/src/test/regress/expected/polygon.out b/src/test/regress/expected/polygon.out
index 2361274..882d342 100644
--- a/src/test/regress/expected/polygon.out
+++ b/src/test/regress/expected/polygon.out
@@ -14,22 +14,27 @@ INSERT INTO POLYGON_TBL(f1) VALUES ('0.0');
ERROR: invalid input syntax for type polygon: "0.0"
LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('0.0');
^
+CONTEXT: coercion failed for column "f1" of type polygon
INSERT INTO POLYGON_TBL(f1) VALUES ('(0.0 0.0');
ERROR: invalid input syntax for type polygon: "(0.0 0.0"
LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('(0.0 0.0');
^
+CONTEXT: coercion failed for column "f1" of type polygon
INSERT INTO POLYGON_TBL(f1) VALUES ('(0,1,2)');
ERROR: invalid input syntax for type polygon: "(0,1,2)"
LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('(0,1,2)');
^
+CONTEXT: coercion failed for column "f1" of type polygon
INSERT INTO POLYGON_TBL(f1) VALUES ('(0,1,2,3');
ERROR: invalid input syntax for type polygon: "(0,1,2,3"
LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('(0,1,2,3');
^
+CONTEXT: coercion failed for column "f1" of type polygon
INSERT INTO POLYGON_TBL(f1) VALUES ('asdf');
ERROR: invalid input syntax for type polygon: "asdf"
LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('asdf');
^
+CONTEXT: coercion failed for column "f1" of type polygon
SELECT '' AS four, * FROM POLYGON_TBL;
four | f1
------+---------------------
diff --git a/src/test/regress/expected/reltime.out b/src/test/regress/expected/reltime.out
index 14fdc6a..4a82bd4 100644
--- a/src/test/regress/expected/reltime.out
+++ b/src/test/regress/expected/reltime.out
@@ -13,10 +13,12 @@ INSERT INTO RELTIME_TBL (f1) VALUES ('badly formatted reltime');
ERROR: invalid input syntax for type reltime: "badly formatted reltime"
LINE 1: INSERT INTO RELTIME_TBL (f1) VALUES ('badly formatted reltim...
^
+CONTEXT: coercion failed for column "f1" of type reltime
INSERT INTO RELTIME_TBL (f1) VALUES ('@ 30 eons ago');
ERROR: invalid input syntax for type reltime: "@ 30 eons ago"
LINE 1: INSERT INTO RELTIME_TBL (f1) VALUES ('@ 30 eons ago');
^
+CONTEXT: coercion failed for column "f1" of type reltime
-- test reltime operators
SELECT '' AS six, * FROM RELTIME_TBL;
six | f1
diff --git a/src/test/regress/expected/rowtypes.out b/src/test/regress/expected/rowtypes.out
index 25b0828..227dde0 100644
--- a/src/test/regress/expected/rowtypes.out
+++ b/src/test/regress/expected/rowtypes.out
@@ -416,6 +416,7 @@ ERROR: column "f1" is of type integer but expression is of type compos
LINE 2: insert into compos values (v); -- fail
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: coercion failed for column "f1" of type integer
create function fcompos1(v compos) returns void as $$
insert into compos values (v.*);
$$ language sql;
diff --git a/src/test/regress/expected/time.out b/src/test/regress/expected/time.out
index 8e0afe6..aecb238 100644
--- a/src/test/regress/expected/time.out
+++ b/src/test/regress/expected/time.out
@@ -18,6 +18,7 @@ INSERT INTO TIME_TBL VALUES ('15:36:39 America/New_York');
ERROR: invalid input syntax for type time: "15:36:39 America/New_York"
LINE 1: INSERT INTO TIME_TBL VALUES ('15:36:39 America/New_York');
^
+CONTEXT: coercion failed for column "f1" of type time without time zone
SELECT f1 AS "Time" FROM TIME_TBL;
Time
-------------
diff --git a/src/test/regress/expected/timestamp.out b/src/test/regress/expected/timestamp.out
index 4a2fabd..1778274 100644
--- a/src/test/regress/expected/timestamp.out
+++ b/src/test/regress/expected/timestamp.out
@@ -84,14 +84,17 @@ INSERT INTO TIMESTAMP_TBL VALUES ('invalid');
ERROR: date/time value "invalid" is no longer supported
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('invalid');
^
+CONTEXT: coercion failed for column "d1" of type timestamp without time zone
INSERT INTO TIMESTAMP_TBL VALUES ('undefined');
ERROR: date/time value "undefined" is no longer supported
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('undefined');
^
+CONTEXT: coercion failed for column "d1" of type timestamp without time zone
INSERT INTO TIMESTAMP_TBL VALUES ('current');
ERROR: date/time value "current" is no longer supported
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('current');
^
+CONTEXT: coercion failed for column "d1" of type timestamp without time zone
-- Postgres v6.0 standard output format
INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
-- Variations on Postgres v6.1 standard output format
@@ -135,6 +138,7 @@ INSERT INTO TIMESTAMP_TBL VALUES ('19970710 173201 America/Does_not_exist');
ERROR: time zone "america/does_not_exist" not recognized
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('19970710 173201 America/D...
^
+CONTEXT: coercion failed for column "d1" of type timestamp without time zone
-- Check date conversion and date arithmetic
INSERT INTO TIMESTAMP_TBL VALUES ('1997-06-10 18:32:01 PDT');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 10 17:32:01 1997');
@@ -164,6 +168,7 @@ INSERT INTO TIMESTAMP_TBL VALUES ('Feb 29 17:32:01 1997');
ERROR: date/time field value out of range: "Feb 29 17:32:01 1997"
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('Feb 29 17:32:01 1997');
^
+CONTEXT: coercion failed for column "d1" of type timestamp without time zone
INSERT INTO TIMESTAMP_TBL VALUES ('Mar 01 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Dec 30 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Dec 31 17:32:01 1997');
@@ -176,10 +181,12 @@ INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 -0097');
ERROR: time zone displacement out of range: "Feb 16 17:32:01 -0097"
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 -0097');
^
+CONTEXT: coercion failed for column "d1" of type timestamp without time zone
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 5097 BC');
ERROR: timestamp out of range: "Feb 16 17:32:01 5097 BC"
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 5097 BC')...
^
+CONTEXT: coercion failed for column "d1" of type timestamp without time zone
SELECT '' AS "64", d1 FROM TIMESTAMP_TBL;
64 | d1
----+-----------------------------
diff --git a/src/test/regress/expected/timestamptz.out b/src/test/regress/expected/timestamptz.out
index 9fa93a4..9a7760f 100644
--- a/src/test/regress/expected/timestamptz.out
+++ b/src/test/regress/expected/timestamptz.out
@@ -83,14 +83,17 @@ INSERT INTO TIMESTAMPTZ_TBL VALUES ('invalid');
ERROR: date/time value "invalid" is no longer supported
LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('invalid');
^
+CONTEXT: coercion failed for column "d1" of type timestamp with time zone
INSERT INTO TIMESTAMPTZ_TBL VALUES ('undefined');
ERROR: date/time value "undefined" is no longer supported
LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('undefined');
^
+CONTEXT: coercion failed for column "d1" of type timestamp with time zone
INSERT INTO TIMESTAMPTZ_TBL VALUES ('current');
ERROR: date/time value "current" is no longer supported
LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('current');
^
+CONTEXT: coercion failed for column "d1" of type timestamp with time zone
-- Postgres v6.0 standard output format
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
-- Variations on Postgres v6.1 standard output format
@@ -147,6 +150,7 @@ INSERT INTO TIMESTAMPTZ_TBL VALUES ('19970710 173201 America/Does_not_exist');
ERROR: time zone "america/does_not_exist" not recognized
LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('19970710 173201 America...
^
+CONTEXT: coercion failed for column "d1" of type timestamp with time zone
SELECT '19970710 173201' AT TIME ZONE 'America/Does_not_exist';
ERROR: time zone "America/Does_not_exist" not recognized
-- Daylight saving time for timestamps beyond 32-bit time_t range.
@@ -203,6 +207,7 @@ INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 29 17:32:01 1997');
ERROR: date/time field value out of range: "Feb 29 17:32:01 1997"
LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 29 17:32:01 1997');
^
+CONTEXT: coercion failed for column "d1" of type timestamp with time zone
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mar 01 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Dec 30 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Dec 31 17:32:01 1997');
@@ -215,10 +220,12 @@ INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 -0097');
ERROR: time zone displacement out of range: "Feb 16 17:32:01 -0097"
LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 -0097')...
^
+CONTEXT: coercion failed for column "d1" of type timestamp with time zone
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 5097 BC');
ERROR: timestamp out of range: "Feb 16 17:32:01 5097 BC"
LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 5097 BC...
^
+CONTEXT: coercion failed for column "d1" of type timestamp with time zone
-- Alternative field order that we've historically supported (sort of)
-- with regular and POSIXy timezone specs
SELECT 'Wed Jul 11 10:51:14 America/New_York 2001'::timestamptz;
diff --git a/src/test/regress/expected/timetz.out b/src/test/regress/expected/timetz.out
index 4391131..9b6e72e 100644
--- a/src/test/regress/expected/timetz.out
+++ b/src/test/regress/expected/timetz.out
@@ -19,6 +19,7 @@ INSERT INTO TIMETZ_TBL VALUES ('15:36:39 America/New_York');
ERROR: invalid input syntax for type time with time zone: "15:36:39 America/New_York"
LINE 1: INSERT INTO TIMETZ_TBL VALUES ('15:36:39 America/New_York');
^
+CONTEXT: coercion failed for column "f1" of type time with time zone
SELECT f1 AS "Time TZ" FROM TIMETZ_TBL;
Time TZ
----------------
diff --git a/src/test/regress/expected/tinterval.out b/src/test/regress/expected/tinterval.out
index a018972..e910715 100644
--- a/src/test/regress/expected/tinterval.out
+++ b/src/test/regress/expected/tinterval.out
@@ -20,11 +20,13 @@ INSERT INTO TINTERVAL_TBL (f1)
ERROR: invalid input syntax for type abstime: "bad time specifications"
LINE 2: VALUES ('["bad time specifications" ""]');
^
+CONTEXT: coercion failed for column "f1" of type tinterval
INSERT INTO TINTERVAL_TBL (f1)
VALUES ('["" "infinity"]');
ERROR: invalid input syntax for type abstime: ""
LINE 2: VALUES ('["" "infinity"]');
^
+CONTEXT: coercion failed for column "f1" of type tinterval
-- test tinterval operators
SELECT '' AS five, * FROM TINTERVAL_TBL;
five | f1
diff --git a/src/test/regress/expected/uuid.out b/src/test/regress/expected/uuid.out
index 59cb1e0..300211c 100644
--- a/src/test/regress/expected/uuid.out
+++ b/src/test/regress/expected/uuid.out
@@ -16,29 +16,35 @@ INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111F');
ERROR: invalid input syntax for uuid: "11111111-1111-1111-1111-111111111111F"
LINE 1: INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-111...
^
+CONTEXT: coercion failed for column "guid_field" of type uuid
-- too short
INSERT INTO guid1(guid_field) VALUES('{11111111-1111-1111-1111-11111111111}');
ERROR: invalid input syntax for uuid: "{11111111-1111-1111-1111-11111111111}"
LINE 1: INSERT INTO guid1(guid_field) VALUES('{11111111-1111-1111-11...
^
+CONTEXT: coercion failed for column "guid_field" of type uuid
-- valid data but invalid format
INSERT INTO guid1(guid_field) VALUES('111-11111-1111-1111-1111-111111111111');
ERROR: invalid input syntax for uuid: "111-11111-1111-1111-1111-111111111111"
LINE 1: INSERT INTO guid1(guid_field) VALUES('111-11111-1111-1111-11...
^
+CONTEXT: coercion failed for column "guid_field" of type uuid
INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-2222-222222222222 ');
ERROR: invalid input syntax for uuid: "{22222222-2222-2222-2222-222222222222 "
LINE 1: INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-22...
^
+CONTEXT: coercion failed for column "guid_field" of type uuid
-- invalid data
INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-G111-111111111111');
ERROR: invalid input syntax for uuid: "11111111-1111-1111-G111-111111111111"
LINE 1: INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-G11...
^
+CONTEXT: coercion failed for column "guid_field" of type uuid
INSERT INTO guid1(guid_field) VALUES('11+11111-1111-1111-1111-111111111111');
ERROR: invalid input syntax for uuid: "11+11111-1111-1111-1111-111111111111"
LINE 1: INSERT INTO guid1(guid_field) VALUES('11+11111-1111-1111-111...
^
+CONTEXT: coercion failed for column "guid_field" of type uuid
--inserting three input formats
INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111');
INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-2222-222222222222}');
diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out
index d702703..e24f108 100644
--- a/src/test/regress/expected/xml_1.out
+++ b/src/test/regress/expected/xml_1.out
@@ -8,18 +8,21 @@ LINE 1: INSERT INTO xmltest VALUES (1, '<value>one</value>');
^
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
+CONTEXT: coercion failed for column "data" of type xml
INSERT INTO xmltest VALUES (2, '<value>two</value>');
ERROR: unsupported XML feature
LINE 1: INSERT INTO xmltest VALUES (2, '<value>two</value>');
^
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
+CONTEXT: coercion failed for column "data" of type xml
INSERT INTO xmltest VALUES (3, '<wrong');
ERROR: unsupported XML feature
LINE 1: INSERT INTO xmltest VALUES (3, '<wrong');
^
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
+CONTEXT: coercion failed for column "data" of type xml
SELECT * FROM xmltest;
id | data
----+------
--
2.7.3
On Thu, Oct 6, 2016 at 2:58 PM, Franck Verrot <franck@verrot.fr> wrote:
Michael, please find attached a revised patch addressing, amongst some other
changes, the testing issue (`make check` passes now) and the visibility of
the ` TransformExprState` struct.
+ /* Set up callback to identify error line number. */
+ errcallback.callback = TransformExprCallback;
Er, no. You want to know at least column name here, not a line number
*** /Users/mpaquier/git/postgres/src/test/regress/expected/xml_2.out
Mon Oct 17 11:32:26 2016
--- /Users/mpaquier/git/postgres/src/test/regress/results/xml.out
Mon Oct 17 15:58:42 2016
***************
*** 9,14 ****
--- 9,15 ----
LINE 1: INSERT INTO xmltest VALUES (3, '<wrong');
^
DETAIL: line 1: Couldn't find end of Start Tag wrong line 1
+ CONTEXT: coercion failed for column "data" of type xml
SELECT * FROM xmltest;
id | data
----+--------------------
make check is still broken here. You did not update the expected
output used when build is done with the --with-libxml switch. It would
be good to check other cases as well.
On top of that, I have found that a couple of other regression tests
are broken in contrib/, citext being one.
The context message is specifying only the column type and name. I
think that it would be useful to provide as well the relation name.
Imagine for example the case of a CTE using an INSERT query...
Providing the query type would be also useful I think. You can look at
state->p_is_insert for that. In short the context message could just
have this shape:
CONTEXT { INSERT | UPDATE } relname, column "col", type coltype.
Andres wrote:
+/* Support for TransformExprCallback */ +typedef struct TransformExprState +{ + const char *column_name; + Oid expected_type; +} TransformExprState; I see no need for this to be a struct defined in the header. Given that TransformExprCallback isn't public, and the whole thing is specific to TransformExprState...
That's a matter of taste, really. Personally I find cleaner to declare
that with the other static declarations at the top of the fil, and
keep the comments of transformAssignedExpr clean of everything.
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Mon, Oct 17, 2016 at 3:18 AM, Michael Paquier
<michael.paquier@gmail.com> wrote:
Andres wrote:
+/* Support for TransformExprCallback */ +typedef struct TransformExprState +{ + const char *column_name; + Oid expected_type; +} TransformExprState; I see no need for this to be a struct defined in the header. Given that TransformExprCallback isn't public, and the whole thing is specific to TransformExprState...That's a matter of taste, really. Personally I find cleaner to declare
that with the other static declarations at the top of the fil, and
keep the comments of transformAssignedExpr clean of everything.
It's pretty standard practice for PostgreSQL to keep declarations
private to particular files whenever they are used only in that file.
And I'd argue that it's good practice in general.
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Wed, Oct 19, 2016 at 3:14 AM, Robert Haas <robertmhaas@gmail.com> wrote:
On Mon, Oct 17, 2016 at 3:18 AM, Michael Paquier
<michael.paquier@gmail.com> wrote:Andres wrote:
+/* Support for TransformExprCallback */ +typedef struct TransformExprState +{ + const char *column_name; + Oid expected_type; +} TransformExprState; I see no need for this to be a struct defined in the header. Given that TransformExprCallback isn't public, and the whole thing is specific to TransformExprState...That's a matter of taste, really. Personally I find cleaner to declare
that with the other static declarations at the top of the fil, and
keep the comments of transformAssignedExpr clean of everything.It's pretty standard practice for PostgreSQL to keep declarations
private to particular files whenever they are used only in that file.
And I'd argue that it's good practice in general.
Yes, definitely. My comment was referring to the fact that the
declaration of this structure was not at the top of this .c file as
the last version of the patch is doing (would be better to declare
them at the beginning of this .c file for clarity actually). It seems
like I did not get Andres' review point, sorry for that.
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Mon, Oct 17, 2016 at 12:48 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:
*** /Users/mpaquier/git/postgres/src/test/regress/expected/xml_2.out Mon Oct 17 11:32:26 2016 --- /Users/mpaquier/git/postgres/src/test/regress/results/xml.out Mon Oct 17 15:58:42 2016 *************** *** 9,14 **** --- 9,15 ---- LINE 1: INSERT INTO xmltest VALUES (3, '<wrong'); ^ DETAIL: line 1: Couldn't find end of Start Tag wrong line 1 + CONTEXT: coercion failed for column "data" of type xml SELECT * FROM xmltest; id | data ----+-------------------- make check is still broken here. You did not update the expected output used when build is done with the --with-libxml switch. It would be good to check other cases as well.On top of that, I have found that a couple of other regression tests
are broken in contrib/, citext being one.
I've also tested with the patch. As Michael already pointed out, you
should update the expected output for citext and xml regression tests.
+ /* Set up callback to identify error line number. */ + errcallback.callback = TransformExprCallback; Er, no. You want to know at least column name here, not a line number
Please change the comment accordingly.
The context message is specifying only the column type and name. I
think that it would be useful to provide as well the relation name.
Imagine for example the case of a CTE using an INSERT query...
Providing the query type would be also useful I think. You can look at
state->p_is_insert for that. In short the context message could just
have this shape:
CONTEXT { INSERT | UPDATE } relname, column "col", type coltype.
+1 for providing relation name in the context message.
--
Thanks & Regards,
Kuntal Ghosh
EnterpriseDB: http://www.enterprisedb.com
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Wed, Oct 26, 2016 at 3:15 PM, Kuntal Ghosh
<kuntalghosh.2007@gmail.com> wrote:
On Mon, Oct 17, 2016 at 12:48 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:*** /Users/mpaquier/git/postgres/src/test/regress/expected/xml_2.out Mon Oct 17 11:32:26 2016 --- /Users/mpaquier/git/postgres/src/test/regress/results/xml.out Mon Oct 17 15:58:42 2016 *************** *** 9,14 **** --- 9,15 ---- LINE 1: INSERT INTO xmltest VALUES (3, '<wrong'); ^ DETAIL: line 1: Couldn't find end of Start Tag wrong line 1 + CONTEXT: coercion failed for column "data" of type xml SELECT * FROM xmltest; id | data ----+-------------------- make check is still broken here. You did not update the expected output used when build is done with the --with-libxml switch. It would be good to check other cases as well.On top of that, I have found that a couple of other regression tests
are broken in contrib/, citext being one.I've also tested with the patch. As Michael already pointed out, you
should update the expected output for citext and xml regression tests.+ /* Set up callback to identify error line number. */ + errcallback.callback = TransformExprCallback; Er, no. You want to know at least column name here, not a line numberPlease change the comment accordingly.
The context message is specifying only the column type and name. I
think that it would be useful to provide as well the relation name.
Imagine for example the case of a CTE using an INSERT query...
Providing the query type would be also useful I think. You can look at
state->p_is_insert for that. In short the context message could just
have this shape:
CONTEXT { INSERT | UPDATE } relname, column "col", type coltype.+1 for providing relation name in the context message.
Okay, so I have reworked the patch a bit and finished with the
attached, adapting the context message to give more information. I
have noticed as well a bug in the patch: the context callback was set
before checking if the column used for transformation is checked on
being a system column or not, the problem being that the callback
could be called without the fields set.
I have updated the regression tests that I found, the main portion of
the patch being dedicated to that and being sure that all the
alternate outputs are correctly refreshed. In this case int8, float4,
float8, xml and contrib/citext are the ones impacted by the change
with alternate outputs.
I am passing that down to a committer for review. The patch looks
large, but at 95% it involves diffs in the regression tests,
alternative outputs taking a large role in the bloat.
--
Michael
Attachments:
transform_errcontext.patchapplication/x-download; name=transform_errcontext.patchDownload
diff --git a/contrib/citext/expected/citext.out b/contrib/citext/expected/citext.out
index 1a1e6c8..4a5ced5 100644
--- a/contrib/citext/expected/citext.out
+++ b/contrib/citext/expected/citext.out
@@ -1081,12 +1081,14 @@ ERROR: column "bytea" is of type bytea but expression is of type text
LINE 1: INSERT INTO caster (bytea) VALUES ('foo'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "bytea", type bytea
INSERT INTO caster (text) VALUES ('foo'::bytea);
INSERT INTO caster (bytea) VALUES ('foo'::citext);
ERROR: column "bytea" is of type bytea but expression is of type citext
LINE 1: INSERT INTO caster (bytea) VALUES ('foo'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "bytea", type bytea
INSERT INTO caster (citext) VALUES ('foo'::bytea);
-- Cannot cast to boolean on assignment.
INSERT INTO caster (boolean) VALUES ('t'::text);
@@ -1094,12 +1096,14 @@ ERROR: column "boolean" is of type boolean but expression is of type text
LINE 1: INSERT INTO caster (boolean) VALUES ('t'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "boolean", type boolean
INSERT INTO caster (text) VALUES ('t'::boolean);
INSERT INTO caster (boolean) VALUES ('t'::citext);
ERROR: column "boolean" is of type boolean but expression is of type citext
LINE 1: INSERT INTO caster (boolean) VALUES ('t'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "boolean", type boolean
INSERT INTO caster (citext) VALUES ('t'::boolean);
-- Cannot cast to float8 on assignment.
INSERT INTO caster (float8) VALUES ('12.42'::text);
@@ -1107,12 +1111,14 @@ ERROR: column "float8" is of type double precision but expression is of type te
LINE 1: INSERT INTO caster (float8) VALUES ('12.42'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "float8", type double precision
INSERT INTO caster (text) VALUES ('12.42'::float8);
INSERT INTO caster (float8) VALUES ('12.42'::citext);
ERROR: column "float8" is of type double precision but expression is of type citext
LINE 1: INSERT INTO caster (float8) VALUES ('12.42'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "float8", type double precision
INSERT INTO caster (citext) VALUES ('12.42'::float8);
-- Cannot cast to float4 on assignment.
INSERT INTO caster (float4) VALUES ('12.42'::text);
@@ -1120,12 +1126,14 @@ ERROR: column "float4" is of type real but expression is of type text
LINE 1: INSERT INTO caster (float4) VALUES ('12.42'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "float4", type real
INSERT INTO caster (text) VALUES ('12.42'::float4);
INSERT INTO caster (float4) VALUES ('12.42'::citext);
ERROR: column "float4" is of type real but expression is of type citext
LINE 1: INSERT INTO caster (float4) VALUES ('12.42'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "float4", type real
INSERT INTO caster (citext) VALUES ('12.42'::float4);
-- Cannot cast to numeric on assignment.
INSERT INTO caster (numeric) VALUES ('12.42'::text);
@@ -1133,12 +1141,14 @@ ERROR: column "numeric" is of type numeric but expression is of type text
LINE 1: INSERT INTO caster (numeric) VALUES ('12.42'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "numeric", type numeric
INSERT INTO caster (text) VALUES ('12.42'::numeric);
INSERT INTO caster (numeric) VALUES ('12.42'::citext);
ERROR: column "numeric" is of type numeric but expression is of type citext
LINE 1: INSERT INTO caster (numeric) VALUES ('12.42'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "numeric", type numeric
INSERT INTO caster (citext) VALUES ('12.42'::numeric);
-- Cannot cast to int8 on assignment.
INSERT INTO caster (int8) VALUES ('12'::text);
@@ -1146,12 +1156,14 @@ ERROR: column "int8" is of type bigint but expression is of type text
LINE 1: INSERT INTO caster (int8) VALUES ('12'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "int8", type bigint
INSERT INTO caster (text) VALUES ('12'::int8);
INSERT INTO caster (int8) VALUES ('12'::citext);
ERROR: column "int8" is of type bigint but expression is of type citext
LINE 1: INSERT INTO caster (int8) VALUES ('12'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "int8", type bigint
INSERT INTO caster (citext) VALUES ('12'::int8);
-- Cannot cast to int4 on assignment.
INSERT INTO caster (int4) VALUES ('12'::text);
@@ -1159,12 +1171,14 @@ ERROR: column "int4" is of type integer but expression is of type text
LINE 1: INSERT INTO caster (int4) VALUES ('12'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "int4", type integer
INSERT INTO caster (text) VALUES ('12'::int4);
INSERT INTO caster (int4) VALUES ('12'::citext);
ERROR: column "int4" is of type integer but expression is of type citext
LINE 1: INSERT INTO caster (int4) VALUES ('12'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "int4", type integer
INSERT INTO caster (citext) VALUES ('12'::int4);
-- Cannot cast to int2 on assignment.
INSERT INTO caster (int2) VALUES ('12'::text);
@@ -1172,12 +1186,14 @@ ERROR: column "int2" is of type smallint but expression is of type text
LINE 1: INSERT INTO caster (int2) VALUES ('12'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "int2", type smallint
INSERT INTO caster (text) VALUES ('12'::int2);
INSERT INTO caster (int2) VALUES ('12'::citext);
ERROR: column "int2" is of type smallint but expression is of type citext
LINE 1: INSERT INTO caster (int2) VALUES ('12'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "int2", type smallint
INSERT INTO caster (citext) VALUES ('12'::int2);
-- Cannot cast to cidr on assignment.
INSERT INTO caster (cidr) VALUES ('192.168.100.128/25'::text);
@@ -1185,12 +1201,14 @@ ERROR: column "cidr" is of type cidr but expression is of type text
LINE 1: INSERT INTO caster (cidr) VALUES ('192.168.100.128/...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "cidr", type cidr
INSERT INTO caster (text) VALUES ('192.168.100.128/25'::cidr);
INSERT INTO caster (cidr) VALUES ('192.168.100.128/25'::citext);
ERROR: column "cidr" is of type cidr but expression is of type citext
LINE 1: INSERT INTO caster (cidr) VALUES ('192.168.100.128/...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "cidr", type cidr
INSERT INTO caster (citext) VALUES ('192.168.100.128/25'::cidr);
-- Cannot cast to inet on assignment.
INSERT INTO caster (inet) VALUES ('192.168.100.128'::text);
@@ -1198,12 +1216,14 @@ ERROR: column "inet" is of type inet but expression is of type text
LINE 1: INSERT INTO caster (inet) VALUES ('192.168.100.128'...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "inet", type inet
INSERT INTO caster (text) VALUES ('192.168.100.128'::inet);
INSERT INTO caster (inet) VALUES ('192.168.100.128'::citext);
ERROR: column "inet" is of type inet but expression is of type citext
LINE 1: INSERT INTO caster (inet) VALUES ('192.168.100.128'...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "inet", type inet
INSERT INTO caster (citext) VALUES ('192.168.100.128'::inet);
-- Cannot cast to macaddr on assignment.
INSERT INTO caster (macaddr) VALUES ('08:00:2b:01:02:03'::text);
@@ -1211,12 +1231,14 @@ ERROR: column "macaddr" is of type macaddr but expression is of type text
LINE 1: INSERT INTO caster (macaddr) VALUES ('08:00:2b:01:02:0...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "macaddr", type macaddr
INSERT INTO caster (text) VALUES ('08:00:2b:01:02:03'::macaddr);
INSERT INTO caster (macaddr) VALUES ('08:00:2b:01:02:03'::citext);
ERROR: column "macaddr" is of type macaddr but expression is of type citext
LINE 1: INSERT INTO caster (macaddr) VALUES ('08:00:2b:01:02:0...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "macaddr", type macaddr
INSERT INTO caster (citext) VALUES ('08:00:2b:01:02:03'::macaddr);
-- Cannot cast to money on assignment.
INSERT INTO caster (money) VALUES ('12'::text);
@@ -1224,12 +1246,14 @@ ERROR: column "money" is of type money but expression is of type text
LINE 1: INSERT INTO caster (money) VALUES ('12'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "money", type money
INSERT INTO caster (text) VALUES ('12'::money);
INSERT INTO caster (money) VALUES ('12'::citext);
ERROR: column "money" is of type money but expression is of type citext
LINE 1: INSERT INTO caster (money) VALUES ('12'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "money", type money
INSERT INTO caster (citext) VALUES ('12'::money);
-- Cannot cast to timestamp on assignment.
INSERT INTO caster (timestamp) VALUES ('1999-01-08 04:05:06'::text);
@@ -1237,12 +1261,14 @@ ERROR: column "timestamp" is of type timestamp without time zone but expression
LINE 1: INSERT INTO caster (timestamp) VALUES ('1999-01-08 04:05...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "timestamp", type timestamp without time zone
INSERT INTO caster (text) VALUES ('1999-01-08 04:05:06'::timestamp);
INSERT INTO caster (timestamp) VALUES ('1999-01-08 04:05:06'::citext);
ERROR: column "timestamp" is of type timestamp without time zone but expression is of type citext
LINE 1: INSERT INTO caster (timestamp) VALUES ('1999-01-08 04:05...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "timestamp", type timestamp without time zone
INSERT INTO caster (citext) VALUES ('1999-01-08 04:05:06'::timestamp);
-- Cannot cast to timestamptz on assignment.
INSERT INTO caster (timestamptz) VALUES ('1999-01-08 04:05:06'::text);
@@ -1250,12 +1276,14 @@ ERROR: column "timestamptz" is of type timestamp with time zone but expression
LINE 1: INSERT INTO caster (timestamptz) VALUES ('1999-01-08 04:05...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "timestamptz", type timestamp with time zone
INSERT INTO caster (text) VALUES ('1999-01-08 04:05:06'::timestamptz);
INSERT INTO caster (timestamptz) VALUES ('1999-01-08 04:05:06'::citext);
ERROR: column "timestamptz" is of type timestamp with time zone but expression is of type citext
LINE 1: INSERT INTO caster (timestamptz) VALUES ('1999-01-08 04:05...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "timestamptz", type timestamp with time zone
INSERT INTO caster (citext) VALUES ('1999-01-08 04:05:06'::timestamptz);
-- Cannot cast to interval on assignment.
INSERT INTO caster (interval) VALUES ('1 hour'::text);
@@ -1263,12 +1291,14 @@ ERROR: column "interval" is of type interval but expression is of type text
LINE 1: INSERT INTO caster (interval) VALUES ('1 hour'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "interval", type interval
INSERT INTO caster (text) VALUES ('1 hour'::interval);
INSERT INTO caster (interval) VALUES ('1 hour'::citext);
ERROR: column "interval" is of type interval but expression is of type citext
LINE 1: INSERT INTO caster (interval) VALUES ('1 hour'::citext)...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "interval", type interval
INSERT INTO caster (citext) VALUES ('1 hour'::interval);
-- Cannot cast to date on assignment.
INSERT INTO caster (date) VALUES ('1999-01-08'::text);
@@ -1276,12 +1306,14 @@ ERROR: column "date" is of type date but expression is of type text
LINE 1: INSERT INTO caster (date) VALUES ('1999-01-08'::tex...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "date", type date
INSERT INTO caster (text) VALUES ('1999-01-08'::date);
INSERT INTO caster (date) VALUES ('1999-01-08'::citext);
ERROR: column "date" is of type date but expression is of type citext
LINE 1: INSERT INTO caster (date) VALUES ('1999-01-08'::cit...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "date", type date
INSERT INTO caster (citext) VALUES ('1999-01-08'::date);
-- Cannot cast to time on assignment.
INSERT INTO caster (time) VALUES ('04:05:06'::text);
@@ -1289,12 +1321,14 @@ ERROR: column "time" is of type time without time zone but expression is of typ
LINE 1: INSERT INTO caster (time) VALUES ('04:05:06'::text)...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "time", type time without time zone
INSERT INTO caster (text) VALUES ('04:05:06'::time);
INSERT INTO caster (time) VALUES ('04:05:06'::citext);
ERROR: column "time" is of type time without time zone but expression is of type citext
LINE 1: INSERT INTO caster (time) VALUES ('04:05:06'::citex...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "time", type time without time zone
INSERT INTO caster (citext) VALUES ('04:05:06'::time);
-- Cannot cast to timetz on assignment.
INSERT INTO caster (timetz) VALUES ('04:05:06'::text);
@@ -1302,12 +1336,14 @@ ERROR: column "timetz" is of type time with time zone but expression is of type
LINE 1: INSERT INTO caster (timetz) VALUES ('04:05:06'::text)...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "timetz", type time with time zone
INSERT INTO caster (text) VALUES ('04:05:06'::timetz);
INSERT INTO caster (timetz) VALUES ('04:05:06'::citext);
ERROR: column "timetz" is of type time with time zone but expression is of type citext
LINE 1: INSERT INTO caster (timetz) VALUES ('04:05:06'::citex...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "timetz", type time with time zone
INSERT INTO caster (citext) VALUES ('04:05:06'::timetz);
-- Cannot cast to point on assignment.
INSERT INTO caster (point) VALUES ('( 1 , 1)'::text);
@@ -1315,12 +1351,14 @@ ERROR: column "point" is of type point but expression is of type text
LINE 1: INSERT INTO caster (point) VALUES ('( 1 , 1)'::text)...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "point", type point
INSERT INTO caster (text) VALUES ('( 1 , 1)'::point);
INSERT INTO caster (point) VALUES ('( 1 , 1)'::citext);
ERROR: column "point" is of type point but expression is of type citext
LINE 1: INSERT INTO caster (point) VALUES ('( 1 , 1)'::citex...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "point", type point
INSERT INTO caster (citext) VALUES ('( 1 , 1)'::point);
-- Cannot cast to lseg on assignment.
INSERT INTO caster (lseg) VALUES ('( 1 , 1 ) , ( 2 , 2 )'::text);
@@ -1328,12 +1366,14 @@ ERROR: column "lseg" is of type lseg but expression is of type text
LINE 1: INSERT INTO caster (lseg) VALUES ('( 1 , 1 ) , ( 2 ...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "lseg", type lseg
INSERT INTO caster (text) VALUES ('( 1 , 1 ) , ( 2 , 2 )'::lseg);
INSERT INTO caster (lseg) VALUES ('( 1 , 1 ) , ( 2 , 2 )'::citext);
ERROR: column "lseg" is of type lseg but expression is of type citext
LINE 1: INSERT INTO caster (lseg) VALUES ('( 1 , 1 ) , ( 2 ...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "lseg", type lseg
INSERT INTO caster (citext) VALUES ('( 1 , 1 ) , ( 2 , 2 )'::lseg);
-- Cannot cast to box on assignment.
INSERT INTO caster (box) VALUES ('(0,0),(1,1)'::text);
@@ -1341,12 +1381,14 @@ ERROR: column "box" is of type box but expression is of type text
LINE 1: INSERT INTO caster (box) VALUES ('(0,0),(1,1)'::te...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "box", type box
INSERT INTO caster (text) VALUES ('(0,0),(1,1)'::box);
INSERT INTO caster (box) VALUES ('(0,0),(1,1)'::citext);
ERROR: column "box" is of type box but expression is of type citext
LINE 1: INSERT INTO caster (box) VALUES ('(0,0),(1,1)'::ci...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "box", type box
INSERT INTO caster (citext) VALUES ('(0,0),(1,1)'::box);
-- Cannot cast to path on assignment.
INSERT INTO caster (path) VALUES ('((0,0),(1,1),(2,0))'::text);
@@ -1354,12 +1396,14 @@ ERROR: column "path" is of type path but expression is of type text
LINE 1: INSERT INTO caster (path) VALUES ('((0,0),(1,1),(2,...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "path", type path
INSERT INTO caster (text) VALUES ('((0,0),(1,1),(2,0))'::path);
INSERT INTO caster (path) VALUES ('((0,0),(1,1),(2,0))'::citext);
ERROR: column "path" is of type path but expression is of type citext
LINE 1: INSERT INTO caster (path) VALUES ('((0,0),(1,1),(2,...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "path", type path
INSERT INTO caster (citext) VALUES ('((0,0),(1,1),(2,0))'::path);
-- Cannot cast to polygon on assignment.
INSERT INTO caster (polygon) VALUES ('((0,0),(1,1))'::text);
@@ -1367,12 +1411,14 @@ ERROR: column "polygon" is of type polygon but expression is of type text
LINE 1: INSERT INTO caster (polygon) VALUES ('((0,0),(1,1))'::...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "polygon", type polygon
INSERT INTO caster (text) VALUES ('((0,0),(1,1))'::polygon);
INSERT INTO caster (polygon) VALUES ('((0,0),(1,1))'::citext);
ERROR: column "polygon" is of type polygon but expression is of type citext
LINE 1: INSERT INTO caster (polygon) VALUES ('((0,0),(1,1))'::...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "polygon", type polygon
INSERT INTO caster (citext) VALUES ('((0,0),(1,1))'::polygon);
-- Cannot cast to circle on assignment.
INSERT INTO caster (circle) VALUES ('((0,0),2)'::text);
@@ -1380,12 +1426,14 @@ ERROR: column "circle" is of type circle but expression is of type text
LINE 1: INSERT INTO caster (circle) VALUES ('((0,0),2)'::text...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "circle", type circle
INSERT INTO caster (text) VALUES ('((0,0),2)'::circle);
INSERT INTO caster (circle) VALUES ('((0,0),2)'::citext);
ERROR: column "circle" is of type circle but expression is of type citext
LINE 1: INSERT INTO caster (circle) VALUES ('((0,0),2)'::cite...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "circle", type circle
INSERT INTO caster (citext) VALUES ('((0,0),2)'::circle);
-- Cannot cast to bit on assignment.
INSERT INTO caster (bit) VALUES ('101'::text);
@@ -1393,12 +1441,14 @@ ERROR: column "bit" is of type bit but expression is of type text
LINE 1: INSERT INTO caster (bit) VALUES ('101'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "bit", type bit
INSERT INTO caster (text) VALUES ('101'::bit);
INSERT INTO caster (bit) VALUES ('101'::citext);
ERROR: column "bit" is of type bit but expression is of type citext
LINE 1: INSERT INTO caster (bit) VALUES ('101'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "bit", type bit
INSERT INTO caster (citext) VALUES ('101'::bit);
-- Cannot cast to bit varying on assignment.
INSERT INTO caster (bitv) VALUES ('101'::text);
@@ -1406,12 +1456,14 @@ ERROR: column "bitv" is of type bit varying but expression is of type text
LINE 1: INSERT INTO caster (bitv) VALUES ('101'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "bitv", type bit varying
INSERT INTO caster (text) VALUES ('101'::bit varying);
INSERT INTO caster (bitv) VALUES ('101'::citext);
ERROR: column "bitv" is of type bit varying but expression is of type citext
LINE 1: INSERT INTO caster (bitv) VALUES ('101'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "bitv", type bit varying
INSERT INTO caster (citext) VALUES ('101'::bit varying);
-- Cannot cast to tsvector on assignment.
INSERT INTO caster (tsvector) VALUES ('the fat cat'::text);
@@ -1419,12 +1471,14 @@ ERROR: column "tsvector" is of type tsvector but expression is of type text
LINE 1: INSERT INTO caster (tsvector) VALUES ('the fat cat'::te...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "tsvector", type tsvector
INSERT INTO caster (text) VALUES ('the fat cat'::tsvector);
INSERT INTO caster (tsvector) VALUES ('the fat cat'::citext);
ERROR: column "tsvector" is of type tsvector but expression is of type citext
LINE 1: INSERT INTO caster (tsvector) VALUES ('the fat cat'::ci...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "tsvector", type tsvector
INSERT INTO caster (citext) VALUES ('the fat cat'::tsvector);
-- Cannot cast to tsquery on assignment.
INSERT INTO caster (tsquery) VALUES ('fat & rat'::text);
@@ -1432,12 +1486,14 @@ ERROR: column "tsquery" is of type tsquery but expression is of type text
LINE 1: INSERT INTO caster (tsquery) VALUES ('fat & rat'::text...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "tsquery", type tsquery
INSERT INTO caster (text) VALUES ('fat & rat'::tsquery);
INSERT INTO caster (tsquery) VALUES ('fat & rat'::citext);
ERROR: column "tsquery" is of type tsquery but expression is of type citext
LINE 1: INSERT INTO caster (tsquery) VALUES ('fat & rat'::cite...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "tsquery", type tsquery
INSERT INTO caster (citext) VALUES ('fat & rat'::tsquery);
-- Cannot cast to uuid on assignment.
INSERT INTO caster (uuid) VALUES ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::text);
@@ -1445,12 +1501,14 @@ ERROR: column "uuid" is of type uuid but expression is of type text
LINE 1: INSERT INTO caster (uuid) VALUES ('a0eebc99-9c0b-4e...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "uuid", type uuid
INSERT INTO caster (text) VALUES ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid);
INSERT INTO caster (uuid) VALUES ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::citext);
ERROR: column "uuid" is of type uuid but expression is of type citext
LINE 1: INSERT INTO caster (uuid) VALUES ('a0eebc99-9c0b-4e...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "uuid", type uuid
INSERT INTO caster (citext) VALUES ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid);
-- Table 9-5. SQL String Functions and Operators
SELECT 'D'::citext || 'avid'::citext = 'David'::citext AS citext_concat;
diff --git a/contrib/citext/expected/citext_1.out b/contrib/citext/expected/citext_1.out
index 3331dbc..d8ecb06 100644
--- a/contrib/citext/expected/citext_1.out
+++ b/contrib/citext/expected/citext_1.out
@@ -1081,12 +1081,14 @@ ERROR: column "bytea" is of type bytea but expression is of type text
LINE 1: INSERT INTO caster (bytea) VALUES ('foo'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "bytea", type bytea
INSERT INTO caster (text) VALUES ('foo'::bytea);
INSERT INTO caster (bytea) VALUES ('foo'::citext);
ERROR: column "bytea" is of type bytea but expression is of type citext
LINE 1: INSERT INTO caster (bytea) VALUES ('foo'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "bytea", type bytea
INSERT INTO caster (citext) VALUES ('foo'::bytea);
-- Cannot cast to boolean on assignment.
INSERT INTO caster (boolean) VALUES ('t'::text);
@@ -1094,12 +1096,14 @@ ERROR: column "boolean" is of type boolean but expression is of type text
LINE 1: INSERT INTO caster (boolean) VALUES ('t'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "boolean", type boolean
INSERT INTO caster (text) VALUES ('t'::boolean);
INSERT INTO caster (boolean) VALUES ('t'::citext);
ERROR: column "boolean" is of type boolean but expression is of type citext
LINE 1: INSERT INTO caster (boolean) VALUES ('t'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "boolean", type boolean
INSERT INTO caster (citext) VALUES ('t'::boolean);
-- Cannot cast to float8 on assignment.
INSERT INTO caster (float8) VALUES ('12.42'::text);
@@ -1107,12 +1111,14 @@ ERROR: column "float8" is of type double precision but expression is of type te
LINE 1: INSERT INTO caster (float8) VALUES ('12.42'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "float8", type double precision
INSERT INTO caster (text) VALUES ('12.42'::float8);
INSERT INTO caster (float8) VALUES ('12.42'::citext);
ERROR: column "float8" is of type double precision but expression is of type citext
LINE 1: INSERT INTO caster (float8) VALUES ('12.42'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "float8", type double precision
INSERT INTO caster (citext) VALUES ('12.42'::float8);
-- Cannot cast to float4 on assignment.
INSERT INTO caster (float4) VALUES ('12.42'::text);
@@ -1120,12 +1126,14 @@ ERROR: column "float4" is of type real but expression is of type text
LINE 1: INSERT INTO caster (float4) VALUES ('12.42'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "float4", type real
INSERT INTO caster (text) VALUES ('12.42'::float4);
INSERT INTO caster (float4) VALUES ('12.42'::citext);
ERROR: column "float4" is of type real but expression is of type citext
LINE 1: INSERT INTO caster (float4) VALUES ('12.42'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "float4", type real
INSERT INTO caster (citext) VALUES ('12.42'::float4);
-- Cannot cast to numeric on assignment.
INSERT INTO caster (numeric) VALUES ('12.42'::text);
@@ -1133,12 +1141,14 @@ ERROR: column "numeric" is of type numeric but expression is of type text
LINE 1: INSERT INTO caster (numeric) VALUES ('12.42'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "numeric", type numeric
INSERT INTO caster (text) VALUES ('12.42'::numeric);
INSERT INTO caster (numeric) VALUES ('12.42'::citext);
ERROR: column "numeric" is of type numeric but expression is of type citext
LINE 1: INSERT INTO caster (numeric) VALUES ('12.42'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "numeric", type numeric
INSERT INTO caster (citext) VALUES ('12.42'::numeric);
-- Cannot cast to int8 on assignment.
INSERT INTO caster (int8) VALUES ('12'::text);
@@ -1146,12 +1156,14 @@ ERROR: column "int8" is of type bigint but expression is of type text
LINE 1: INSERT INTO caster (int8) VALUES ('12'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "int8", type bigint
INSERT INTO caster (text) VALUES ('12'::int8);
INSERT INTO caster (int8) VALUES ('12'::citext);
ERROR: column "int8" is of type bigint but expression is of type citext
LINE 1: INSERT INTO caster (int8) VALUES ('12'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "int8", type bigint
INSERT INTO caster (citext) VALUES ('12'::int8);
-- Cannot cast to int4 on assignment.
INSERT INTO caster (int4) VALUES ('12'::text);
@@ -1159,12 +1171,14 @@ ERROR: column "int4" is of type integer but expression is of type text
LINE 1: INSERT INTO caster (int4) VALUES ('12'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "int4", type integer
INSERT INTO caster (text) VALUES ('12'::int4);
INSERT INTO caster (int4) VALUES ('12'::citext);
ERROR: column "int4" is of type integer but expression is of type citext
LINE 1: INSERT INTO caster (int4) VALUES ('12'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "int4", type integer
INSERT INTO caster (citext) VALUES ('12'::int4);
-- Cannot cast to int2 on assignment.
INSERT INTO caster (int2) VALUES ('12'::text);
@@ -1172,12 +1186,14 @@ ERROR: column "int2" is of type smallint but expression is of type text
LINE 1: INSERT INTO caster (int2) VALUES ('12'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "int2", type smallint
INSERT INTO caster (text) VALUES ('12'::int2);
INSERT INTO caster (int2) VALUES ('12'::citext);
ERROR: column "int2" is of type smallint but expression is of type citext
LINE 1: INSERT INTO caster (int2) VALUES ('12'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "int2", type smallint
INSERT INTO caster (citext) VALUES ('12'::int2);
-- Cannot cast to cidr on assignment.
INSERT INTO caster (cidr) VALUES ('192.168.100.128/25'::text);
@@ -1185,12 +1201,14 @@ ERROR: column "cidr" is of type cidr but expression is of type text
LINE 1: INSERT INTO caster (cidr) VALUES ('192.168.100.128/...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "cidr", type cidr
INSERT INTO caster (text) VALUES ('192.168.100.128/25'::cidr);
INSERT INTO caster (cidr) VALUES ('192.168.100.128/25'::citext);
ERROR: column "cidr" is of type cidr but expression is of type citext
LINE 1: INSERT INTO caster (cidr) VALUES ('192.168.100.128/...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "cidr", type cidr
INSERT INTO caster (citext) VALUES ('192.168.100.128/25'::cidr);
-- Cannot cast to inet on assignment.
INSERT INTO caster (inet) VALUES ('192.168.100.128'::text);
@@ -1198,12 +1216,14 @@ ERROR: column "inet" is of type inet but expression is of type text
LINE 1: INSERT INTO caster (inet) VALUES ('192.168.100.128'...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "inet", type inet
INSERT INTO caster (text) VALUES ('192.168.100.128'::inet);
INSERT INTO caster (inet) VALUES ('192.168.100.128'::citext);
ERROR: column "inet" is of type inet but expression is of type citext
LINE 1: INSERT INTO caster (inet) VALUES ('192.168.100.128'...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "inet", type inet
INSERT INTO caster (citext) VALUES ('192.168.100.128'::inet);
-- Cannot cast to macaddr on assignment.
INSERT INTO caster (macaddr) VALUES ('08:00:2b:01:02:03'::text);
@@ -1211,12 +1231,14 @@ ERROR: column "macaddr" is of type macaddr but expression is of type text
LINE 1: INSERT INTO caster (macaddr) VALUES ('08:00:2b:01:02:0...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "macaddr", type macaddr
INSERT INTO caster (text) VALUES ('08:00:2b:01:02:03'::macaddr);
INSERT INTO caster (macaddr) VALUES ('08:00:2b:01:02:03'::citext);
ERROR: column "macaddr" is of type macaddr but expression is of type citext
LINE 1: INSERT INTO caster (macaddr) VALUES ('08:00:2b:01:02:0...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "macaddr", type macaddr
INSERT INTO caster (citext) VALUES ('08:00:2b:01:02:03'::macaddr);
-- Cannot cast to money on assignment.
INSERT INTO caster (money) VALUES ('12'::text);
@@ -1224,12 +1246,14 @@ ERROR: column "money" is of type money but expression is of type text
LINE 1: INSERT INTO caster (money) VALUES ('12'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "money", type money
INSERT INTO caster (text) VALUES ('12'::money);
INSERT INTO caster (money) VALUES ('12'::citext);
ERROR: column "money" is of type money but expression is of type citext
LINE 1: INSERT INTO caster (money) VALUES ('12'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "money", type money
INSERT INTO caster (citext) VALUES ('12'::money);
-- Cannot cast to timestamp on assignment.
INSERT INTO caster (timestamp) VALUES ('1999-01-08 04:05:06'::text);
@@ -1237,12 +1261,14 @@ ERROR: column "timestamp" is of type timestamp without time zone but expression
LINE 1: INSERT INTO caster (timestamp) VALUES ('1999-01-08 04:05...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "timestamp", type timestamp without time zone
INSERT INTO caster (text) VALUES ('1999-01-08 04:05:06'::timestamp);
INSERT INTO caster (timestamp) VALUES ('1999-01-08 04:05:06'::citext);
ERROR: column "timestamp" is of type timestamp without time zone but expression is of type citext
LINE 1: INSERT INTO caster (timestamp) VALUES ('1999-01-08 04:05...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "timestamp", type timestamp without time zone
INSERT INTO caster (citext) VALUES ('1999-01-08 04:05:06'::timestamp);
-- Cannot cast to timestamptz on assignment.
INSERT INTO caster (timestamptz) VALUES ('1999-01-08 04:05:06'::text);
@@ -1250,12 +1276,14 @@ ERROR: column "timestamptz" is of type timestamp with time zone but expression
LINE 1: INSERT INTO caster (timestamptz) VALUES ('1999-01-08 04:05...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "timestamptz", type timestamp with time zone
INSERT INTO caster (text) VALUES ('1999-01-08 04:05:06'::timestamptz);
INSERT INTO caster (timestamptz) VALUES ('1999-01-08 04:05:06'::citext);
ERROR: column "timestamptz" is of type timestamp with time zone but expression is of type citext
LINE 1: INSERT INTO caster (timestamptz) VALUES ('1999-01-08 04:05...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "timestamptz", type timestamp with time zone
INSERT INTO caster (citext) VALUES ('1999-01-08 04:05:06'::timestamptz);
-- Cannot cast to interval on assignment.
INSERT INTO caster (interval) VALUES ('1 hour'::text);
@@ -1263,12 +1291,14 @@ ERROR: column "interval" is of type interval but expression is of type text
LINE 1: INSERT INTO caster (interval) VALUES ('1 hour'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "interval", type interval
INSERT INTO caster (text) VALUES ('1 hour'::interval);
INSERT INTO caster (interval) VALUES ('1 hour'::citext);
ERROR: column "interval" is of type interval but expression is of type citext
LINE 1: INSERT INTO caster (interval) VALUES ('1 hour'::citext)...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "interval", type interval
INSERT INTO caster (citext) VALUES ('1 hour'::interval);
-- Cannot cast to date on assignment.
INSERT INTO caster (date) VALUES ('1999-01-08'::text);
@@ -1276,12 +1306,14 @@ ERROR: column "date" is of type date but expression is of type text
LINE 1: INSERT INTO caster (date) VALUES ('1999-01-08'::tex...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "date", type date
INSERT INTO caster (text) VALUES ('1999-01-08'::date);
INSERT INTO caster (date) VALUES ('1999-01-08'::citext);
ERROR: column "date" is of type date but expression is of type citext
LINE 1: INSERT INTO caster (date) VALUES ('1999-01-08'::cit...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "date", type date
INSERT INTO caster (citext) VALUES ('1999-01-08'::date);
-- Cannot cast to time on assignment.
INSERT INTO caster (time) VALUES ('04:05:06'::text);
@@ -1289,12 +1321,14 @@ ERROR: column "time" is of type time without time zone but expression is of typ
LINE 1: INSERT INTO caster (time) VALUES ('04:05:06'::text)...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "time", type time without time zone
INSERT INTO caster (text) VALUES ('04:05:06'::time);
INSERT INTO caster (time) VALUES ('04:05:06'::citext);
ERROR: column "time" is of type time without time zone but expression is of type citext
LINE 1: INSERT INTO caster (time) VALUES ('04:05:06'::citex...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "time", type time without time zone
INSERT INTO caster (citext) VALUES ('04:05:06'::time);
-- Cannot cast to timetz on assignment.
INSERT INTO caster (timetz) VALUES ('04:05:06'::text);
@@ -1302,12 +1336,14 @@ ERROR: column "timetz" is of type time with time zone but expression is of type
LINE 1: INSERT INTO caster (timetz) VALUES ('04:05:06'::text)...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "timetz", type time with time zone
INSERT INTO caster (text) VALUES ('04:05:06'::timetz);
INSERT INTO caster (timetz) VALUES ('04:05:06'::citext);
ERROR: column "timetz" is of type time with time zone but expression is of type citext
LINE 1: INSERT INTO caster (timetz) VALUES ('04:05:06'::citex...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "timetz", type time with time zone
INSERT INTO caster (citext) VALUES ('04:05:06'::timetz);
-- Cannot cast to point on assignment.
INSERT INTO caster (point) VALUES ('( 1 , 1)'::text);
@@ -1315,12 +1351,14 @@ ERROR: column "point" is of type point but expression is of type text
LINE 1: INSERT INTO caster (point) VALUES ('( 1 , 1)'::text)...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "point", type point
INSERT INTO caster (text) VALUES ('( 1 , 1)'::point);
INSERT INTO caster (point) VALUES ('( 1 , 1)'::citext);
ERROR: column "point" is of type point but expression is of type citext
LINE 1: INSERT INTO caster (point) VALUES ('( 1 , 1)'::citex...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "point", type point
INSERT INTO caster (citext) VALUES ('( 1 , 1)'::point);
-- Cannot cast to lseg on assignment.
INSERT INTO caster (lseg) VALUES ('( 1 , 1 ) , ( 2 , 2 )'::text);
@@ -1328,12 +1366,14 @@ ERROR: column "lseg" is of type lseg but expression is of type text
LINE 1: INSERT INTO caster (lseg) VALUES ('( 1 , 1 ) , ( 2 ...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "lseg", type lseg
INSERT INTO caster (text) VALUES ('( 1 , 1 ) , ( 2 , 2 )'::lseg);
INSERT INTO caster (lseg) VALUES ('( 1 , 1 ) , ( 2 , 2 )'::citext);
ERROR: column "lseg" is of type lseg but expression is of type citext
LINE 1: INSERT INTO caster (lseg) VALUES ('( 1 , 1 ) , ( 2 ...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "lseg", type lseg
INSERT INTO caster (citext) VALUES ('( 1 , 1 ) , ( 2 , 2 )'::lseg);
-- Cannot cast to box on assignment.
INSERT INTO caster (box) VALUES ('(0,0),(1,1)'::text);
@@ -1341,12 +1381,14 @@ ERROR: column "box" is of type box but expression is of type text
LINE 1: INSERT INTO caster (box) VALUES ('(0,0),(1,1)'::te...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "box", type box
INSERT INTO caster (text) VALUES ('(0,0),(1,1)'::box);
INSERT INTO caster (box) VALUES ('(0,0),(1,1)'::citext);
ERROR: column "box" is of type box but expression is of type citext
LINE 1: INSERT INTO caster (box) VALUES ('(0,0),(1,1)'::ci...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "box", type box
INSERT INTO caster (citext) VALUES ('(0,0),(1,1)'::box);
-- Cannot cast to path on assignment.
INSERT INTO caster (path) VALUES ('((0,0),(1,1),(2,0))'::text);
@@ -1354,12 +1396,14 @@ ERROR: column "path" is of type path but expression is of type text
LINE 1: INSERT INTO caster (path) VALUES ('((0,0),(1,1),(2,...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "path", type path
INSERT INTO caster (text) VALUES ('((0,0),(1,1),(2,0))'::path);
INSERT INTO caster (path) VALUES ('((0,0),(1,1),(2,0))'::citext);
ERROR: column "path" is of type path but expression is of type citext
LINE 1: INSERT INTO caster (path) VALUES ('((0,0),(1,1),(2,...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "path", type path
INSERT INTO caster (citext) VALUES ('((0,0),(1,1),(2,0))'::path);
-- Cannot cast to polygon on assignment.
INSERT INTO caster (polygon) VALUES ('((0,0),(1,1))'::text);
@@ -1367,12 +1411,14 @@ ERROR: column "polygon" is of type polygon but expression is of type text
LINE 1: INSERT INTO caster (polygon) VALUES ('((0,0),(1,1))'::...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "polygon", type polygon
INSERT INTO caster (text) VALUES ('((0,0),(1,1))'::polygon);
INSERT INTO caster (polygon) VALUES ('((0,0),(1,1))'::citext);
ERROR: column "polygon" is of type polygon but expression is of type citext
LINE 1: INSERT INTO caster (polygon) VALUES ('((0,0),(1,1))'::...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "polygon", type polygon
INSERT INTO caster (citext) VALUES ('((0,0),(1,1))'::polygon);
-- Cannot cast to circle on assignment.
INSERT INTO caster (circle) VALUES ('((0,0),2)'::text);
@@ -1380,12 +1426,14 @@ ERROR: column "circle" is of type circle but expression is of type text
LINE 1: INSERT INTO caster (circle) VALUES ('((0,0),2)'::text...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "circle", type circle
INSERT INTO caster (text) VALUES ('((0,0),2)'::circle);
INSERT INTO caster (circle) VALUES ('((0,0),2)'::citext);
ERROR: column "circle" is of type circle but expression is of type citext
LINE 1: INSERT INTO caster (circle) VALUES ('((0,0),2)'::cite...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "circle", type circle
INSERT INTO caster (citext) VALUES ('((0,0),2)'::circle);
-- Cannot cast to bit on assignment.
INSERT INTO caster (bit) VALUES ('101'::text);
@@ -1393,12 +1441,14 @@ ERROR: column "bit" is of type bit but expression is of type text
LINE 1: INSERT INTO caster (bit) VALUES ('101'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "bit", type bit
INSERT INTO caster (text) VALUES ('101'::bit);
INSERT INTO caster (bit) VALUES ('101'::citext);
ERROR: column "bit" is of type bit but expression is of type citext
LINE 1: INSERT INTO caster (bit) VALUES ('101'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "bit", type bit
INSERT INTO caster (citext) VALUES ('101'::bit);
-- Cannot cast to bit varying on assignment.
INSERT INTO caster (bitv) VALUES ('101'::text);
@@ -1406,12 +1456,14 @@ ERROR: column "bitv" is of type bit varying but expression is of type text
LINE 1: INSERT INTO caster (bitv) VALUES ('101'::text);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "bitv", type bit varying
INSERT INTO caster (text) VALUES ('101'::bit varying);
INSERT INTO caster (bitv) VALUES ('101'::citext);
ERROR: column "bitv" is of type bit varying but expression is of type citext
LINE 1: INSERT INTO caster (bitv) VALUES ('101'::citext);
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "bitv", type bit varying
INSERT INTO caster (citext) VALUES ('101'::bit varying);
-- Cannot cast to tsvector on assignment.
INSERT INTO caster (tsvector) VALUES ('the fat cat'::text);
@@ -1419,12 +1471,14 @@ ERROR: column "tsvector" is of type tsvector but expression is of type text
LINE 1: INSERT INTO caster (tsvector) VALUES ('the fat cat'::te...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "tsvector", type tsvector
INSERT INTO caster (text) VALUES ('the fat cat'::tsvector);
INSERT INTO caster (tsvector) VALUES ('the fat cat'::citext);
ERROR: column "tsvector" is of type tsvector but expression is of type citext
LINE 1: INSERT INTO caster (tsvector) VALUES ('the fat cat'::ci...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "tsvector", type tsvector
INSERT INTO caster (citext) VALUES ('the fat cat'::tsvector);
-- Cannot cast to tsquery on assignment.
INSERT INTO caster (tsquery) VALUES ('fat & rat'::text);
@@ -1432,12 +1486,14 @@ ERROR: column "tsquery" is of type tsquery but expression is of type text
LINE 1: INSERT INTO caster (tsquery) VALUES ('fat & rat'::text...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "tsquery", type tsquery
INSERT INTO caster (text) VALUES ('fat & rat'::tsquery);
INSERT INTO caster (tsquery) VALUES ('fat & rat'::citext);
ERROR: column "tsquery" is of type tsquery but expression is of type citext
LINE 1: INSERT INTO caster (tsquery) VALUES ('fat & rat'::cite...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "tsquery", type tsquery
INSERT INTO caster (citext) VALUES ('fat & rat'::tsquery);
-- Cannot cast to uuid on assignment.
INSERT INTO caster (uuid) VALUES ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::text);
@@ -1445,12 +1501,14 @@ ERROR: column "uuid" is of type uuid but expression is of type text
LINE 1: INSERT INTO caster (uuid) VALUES ('a0eebc99-9c0b-4e...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "uuid", type uuid
INSERT INTO caster (text) VALUES ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid);
INSERT INTO caster (uuid) VALUES ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::citext);
ERROR: column "uuid" is of type uuid but expression is of type citext
LINE 1: INSERT INTO caster (uuid) VALUES ('a0eebc99-9c0b-4e...
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "caster", column "uuid", type uuid
INSERT INTO caster (citext) VALUES ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid);
-- Table 9-5. SQL String Functions and Operators
SELECT 'D'::citext || 'avid'::citext = 'David'::citext AS citext_concat;
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index b7b82bf..39ed7e0 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -33,6 +33,16 @@
#include "utils/typcache.h"
+/* Error callback context for transformAssignedExpr */
+typedef struct TransformExprState
+{
+ const char *column_name;
+ const char *relation_name;
+ Oid expected_type;
+ bool is_insert;
+} TransformExprState;
+
+
static void markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
Var *var, int levelsup);
static Node *transformAssignmentIndirection(ParseState *pstate,
@@ -366,6 +376,34 @@ markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
/*
+ *
+ * Error context callback for transformAssignedExpr.
+ *
+ * The argument for the error context must be TransformExprState.
+ */
+static void
+TransformExprCallback(void *arg)
+{
+ TransformExprState *state = (TransformExprState *) arg;
+
+ if (state->is_insert)
+ {
+ errcontext("INSERT \"%s\", column \"%s\", type %s",
+ state->relation_name,
+ state->column_name,
+ format_type_be(state->expected_type));
+ }
+ else
+ {
+ errcontext("UPDATE \"%s\", column \"%s\", type %s",
+ state->relation_name,
+ state->column_name,
+ format_type_be(state->expected_type));
+ }
+}
+
+
+/*
* transformAssignedExpr()
* This is used in INSERT and UPDATE statements only. It prepares an
* expression for assignment to a column of the target table.
@@ -404,6 +442,8 @@ transformAssignedExpr(ParseState *pstate,
int32 attrtypmod;
Oid attrcollation; /* collation of target column */
ParseExprKind sv_expr_kind;
+ ErrorContextCallback errcallback;
+ TransformExprState te_state;
/*
* Save and restore identity of expression type we're parsing. We must
@@ -425,6 +465,16 @@ transformAssignedExpr(ParseState *pstate,
attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod;
attrcollation = rd->rd_att->attrs[attrno - 1]->attcollation;
+ /* Set up callback to fetch more details regarding the error */
+ errcallback.callback = TransformExprCallback;
+ errcallback.arg = (void *) &te_state;
+ errcallback.previous = error_context_stack;
+ error_context_stack = &errcallback;
+ te_state.relation_name = RelationGetRelationName(rd);
+ te_state.column_name = colname;
+ te_state.expected_type = attrtype;
+ te_state.is_insert = pstate->p_is_insert;
+
/*
* If the expression is a DEFAULT placeholder, insert the attribute's
* type/typmod/collation into it so that exprType etc will report the
@@ -531,6 +581,9 @@ transformAssignedExpr(ParseState *pstate,
pstate->p_expr_kind = sv_expr_kind;
+ /* Reset error callback */
+ error_context_stack = errcallback.previous;
+
return expr;
}
diff --git a/src/test/regress/expected/abstime.out b/src/test/regress/expected/abstime.out
index ed48f64..bde5f25 100644
--- a/src/test/regress/expected/abstime.out
+++ b/src/test/regress/expected/abstime.out
@@ -32,15 +32,18 @@ ERROR: date/time field value out of range: "Feb 35, 1946 10:00:00"
LINE 1: INSERT INTO ABSTIME_TBL (f1) VALUES ('Feb 35, 1946 10:00:00'...
^
HINT: Perhaps you need a different "datestyle" setting.
+CONTEXT: INSERT "abstime_tbl", column "f1", type abstime
INSERT INTO ABSTIME_TBL (f1) VALUES ('Feb 28, 1984 25:08:10');
ERROR: date/time field value out of range: "Feb 28, 1984 25:08:10"
LINE 1: INSERT INTO ABSTIME_TBL (f1) VALUES ('Feb 28, 1984 25:08:10'...
^
+CONTEXT: INSERT "abstime_tbl", column "f1", type abstime
-- badly formatted abstimes: these should result in invalid abstimes
INSERT INTO ABSTIME_TBL (f1) VALUES ('bad date format');
ERROR: invalid input syntax for type abstime: "bad date format"
LINE 1: INSERT INTO ABSTIME_TBL (f1) VALUES ('bad date format');
^
+CONTEXT: INSERT "abstime_tbl", column "f1", type abstime
INSERT INTO ABSTIME_TBL (f1) VALUES ('Jun 10, 1843');
-- test abstime operators
SELECT '' AS eight, * FROM ABSTIME_TBL;
diff --git a/src/test/regress/expected/box.out b/src/test/regress/expected/box.out
index 5f8b945..4a01df9 100644
--- a/src/test/regress/expected/box.out
+++ b/src/test/regress/expected/box.out
@@ -27,10 +27,12 @@ INSERT INTO BOX_TBL (f1) VALUES ('(2.3, 4.5)');
ERROR: invalid input syntax for type box: "(2.3, 4.5)"
LINE 1: INSERT INTO BOX_TBL (f1) VALUES ('(2.3, 4.5)');
^
+CONTEXT: INSERT "box_tbl", column "f1", type box
INSERT INTO BOX_TBL (f1) VALUES ('asdfasdf(ad');
ERROR: invalid input syntax for type box: "asdfasdf(ad"
LINE 1: INSERT INTO BOX_TBL (f1) VALUES ('asdfasdf(ad');
^
+CONTEXT: INSERT "box_tbl", column "f1", type box
SELECT '' AS four, * FROM BOX_TBL;
four | f1
------+---------------------
diff --git a/src/test/regress/expected/circle.out b/src/test/regress/expected/circle.out
index 9ba4a04..98576f0 100644
--- a/src/test/regress/expected/circle.out
+++ b/src/test/regress/expected/circle.out
@@ -13,14 +13,17 @@ INSERT INTO CIRCLE_TBL VALUES ('<(-100,0),-100>');
ERROR: invalid input syntax for type circle: "<(-100,0),-100>"
LINE 1: INSERT INTO CIRCLE_TBL VALUES ('<(-100,0),-100>');
^
+CONTEXT: INSERT "circle_tbl", column "f1", type circle
INSERT INTO CIRCLE_TBL VALUES ('1abc,3,5');
ERROR: invalid input syntax for type circle: "1abc,3,5"
LINE 1: INSERT INTO CIRCLE_TBL VALUES ('1abc,3,5');
^
+CONTEXT: INSERT "circle_tbl", column "f1", type circle
INSERT INTO CIRCLE_TBL VALUES ('(3,(1,2),3)');
ERROR: invalid input syntax for type circle: "(3,(1,2),3)"
LINE 1: INSERT INTO CIRCLE_TBL VALUES ('(3,(1,2),3)');
^
+CONTEXT: INSERT "circle_tbl", column "f1", type circle
SELECT * FROM CIRCLE_TBL;
f1
----------------
diff --git a/src/test/regress/expected/date.out b/src/test/regress/expected/date.out
index 418b146..03e13f9 100644
--- a/src/test/regress/expected/date.out
+++ b/src/test/regress/expected/date.out
@@ -13,6 +13,7 @@ INSERT INTO DATE_TBL VALUES ('1997-02-29');
ERROR: date/time field value out of range: "1997-02-29"
LINE 1: INSERT INTO DATE_TBL VALUES ('1997-02-29');
^
+CONTEXT: INSERT "date_tbl", column "f1", type date
INSERT INTO DATE_TBL VALUES ('1997-03-01');
INSERT INTO DATE_TBL VALUES ('1997-03-02');
INSERT INTO DATE_TBL VALUES ('2000-04-01');
diff --git a/src/test/regress/expected/float4-exp-three-digits.out b/src/test/regress/expected/float4-exp-three-digits.out
index f17f956..ebbbf08 100644
--- a/src/test/regress/expected/float4-exp-three-digits.out
+++ b/src/test/regress/expected/float4-exp-three-digits.out
@@ -12,51 +12,63 @@ INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
ERROR: value out of range: overflow
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
ERROR: value out of range: overflow
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
ERROR: value out of range: underflow
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
ERROR: value out of range: underflow
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
-- bad input
INSERT INTO FLOAT4_TBL(f1) VALUES ('');
ERROR: invalid input syntax for type real: ""
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES (' ');
ERROR: invalid input syntax for type real: " "
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES (' ');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('xyz');
ERROR: invalid input syntax for type real: "xyz"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('xyz');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('5.0.0');
ERROR: invalid input syntax for type real: "5.0.0"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5.0.0');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('5 . 0');
ERROR: invalid input syntax for type real: "5 . 0"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5 . 0');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('5. 0');
ERROR: invalid input syntax for type real: "5. 0"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5. 0');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES (' - 3.0');
ERROR: invalid input syntax for type real: " - 3.0"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES (' - 3.0');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5');
ERROR: invalid input syntax for type real: "123 5"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
-- special inputs
SELECT 'NaN'::float4;
float4
diff --git a/src/test/regress/expected/float4.out b/src/test/regress/expected/float4.out
index fd46a4a..d479762 100644
--- a/src/test/regress/expected/float4.out
+++ b/src/test/regress/expected/float4.out
@@ -12,51 +12,63 @@ INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
ERROR: value out of range: overflow
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
ERROR: value out of range: overflow
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
ERROR: value out of range: underflow
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
ERROR: value out of range: underflow
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
-- bad input
INSERT INTO FLOAT4_TBL(f1) VALUES ('');
ERROR: invalid input syntax for type real: ""
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES (' ');
ERROR: invalid input syntax for type real: " "
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES (' ');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('xyz');
ERROR: invalid input syntax for type real: "xyz"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('xyz');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('5.0.0');
ERROR: invalid input syntax for type real: "5.0.0"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5.0.0');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('5 . 0');
ERROR: invalid input syntax for type real: "5 . 0"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5 . 0');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('5. 0');
ERROR: invalid input syntax for type real: "5. 0"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5. 0');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES (' - 3.0');
ERROR: invalid input syntax for type real: " - 3.0"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES (' - 3.0');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5');
ERROR: invalid input syntax for type real: "123 5"
LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5');
^
+CONTEXT: INSERT "float4_tbl", column "f1", type real
-- special inputs
SELECT 'NaN'::float4;
float4
diff --git a/src/test/regress/expected/float8-exp-three-digits-win32.out b/src/test/regress/expected/float8-exp-three-digits-win32.out
index 7e11533..f02777a 100644
--- a/src/test/regress/expected/float8-exp-three-digits-win32.out
+++ b/src/test/regress/expected/float8-exp-three-digits-win32.out
@@ -29,34 +29,42 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('');
ERROR: invalid input syntax for type double precision: ""
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES (' ');
ERROR: invalid input syntax for type double precision: " "
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' ');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz');
ERROR: invalid input syntax for type double precision: "xyz"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0');
ERROR: invalid input syntax for type double precision: "5.0.0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0');
ERROR: invalid input syntax for type double precision: "5 . 0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0');
ERROR: invalid input syntax for type double precision: "5. 0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3');
ERROR: invalid input syntax for type double precision: " - 3"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5');
ERROR: invalid input syntax for type double precision: "123 5"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
-- special inputs
SELECT 'NaN'::float8;
float8
@@ -414,18 +422,22 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400');
ERROR: "10e400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400');
ERROR: "-10e400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400');
ERROR: "10e-400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400');
ERROR: "-10e-400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
-- maintain external table consistency across platforms
-- delete all values and reinsert well-behaved ones
DELETE FROM FLOAT8_TBL;
diff --git a/src/test/regress/expected/float8-small-is-zero.out b/src/test/regress/expected/float8-small-is-zero.out
index 26b8378..44dfd36 100644
--- a/src/test/regress/expected/float8-small-is-zero.out
+++ b/src/test/regress/expected/float8-small-is-zero.out
@@ -33,34 +33,42 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('');
ERROR: invalid input syntax for type double precision: ""
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES (' ');
ERROR: invalid input syntax for type double precision: " "
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' ');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz');
ERROR: invalid input syntax for type double precision: "xyz"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0');
ERROR: invalid input syntax for type double precision: "5.0.0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0');
ERROR: invalid input syntax for type double precision: "5 . 0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0');
ERROR: invalid input syntax for type double precision: "5. 0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3');
ERROR: invalid input syntax for type double precision: " - 3"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5');
ERROR: invalid input syntax for type double precision: "123 5"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
-- special inputs
SELECT 'NaN'::float8;
float8
@@ -418,10 +426,12 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400');
ERROR: "10e400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400');
ERROR: "-10e400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400');
INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400');
-- maintain external table consistency across platforms
diff --git a/src/test/regress/expected/float8-small-is-zero_1.out b/src/test/regress/expected/float8-small-is-zero_1.out
index cea2790..45bd9cb 100644
--- a/src/test/regress/expected/float8-small-is-zero_1.out
+++ b/src/test/regress/expected/float8-small-is-zero_1.out
@@ -33,34 +33,42 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('');
ERROR: invalid input syntax for type double precision: ""
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES (' ');
ERROR: invalid input syntax for type double precision: " "
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' ');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz');
ERROR: invalid input syntax for type double precision: "xyz"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0');
ERROR: invalid input syntax for type double precision: "5.0.0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0');
ERROR: invalid input syntax for type double precision: "5 . 0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0');
ERROR: invalid input syntax for type double precision: "5. 0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3');
ERROR: invalid input syntax for type double precision: " - 3"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5');
ERROR: invalid input syntax for type double precision: "123 5"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
-- special inputs
SELECT 'NaN'::float8;
float8
@@ -418,10 +426,12 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400');
ERROR: "10e400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400');
ERROR: "-10e400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400');
INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400');
-- maintain external table consistency across platforms
diff --git a/src/test/regress/expected/float8.out b/src/test/regress/expected/float8.out
index 20c985e..4a086be 100644
--- a/src/test/regress/expected/float8.out
+++ b/src/test/regress/expected/float8.out
@@ -29,34 +29,42 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('');
ERROR: invalid input syntax for type double precision: ""
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES (' ');
ERROR: invalid input syntax for type double precision: " "
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' ');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz');
ERROR: invalid input syntax for type double precision: "xyz"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0');
ERROR: invalid input syntax for type double precision: "5.0.0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0');
ERROR: invalid input syntax for type double precision: "5 . 0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0');
ERROR: invalid input syntax for type double precision: "5. 0"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3');
ERROR: invalid input syntax for type double precision: " - 3"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5');
ERROR: invalid input syntax for type double precision: "123 5"
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
-- special inputs
SELECT 'NaN'::float8;
float8
@@ -414,18 +422,22 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400');
ERROR: "10e400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400');
ERROR: "-10e400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400');
ERROR: "10e-400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400');
ERROR: "-10e-400" is out of range for type double precision
LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400');
^
+CONTEXT: INSERT "float8_tbl", column "f1", type double precision
-- maintain external table consistency across platforms
-- delete all values and reinsert well-behaved ones
DELETE FROM FLOAT8_TBL;
diff --git a/src/test/regress/expected/inet.out b/src/test/regress/expected/inet.out
index be9427e..15fd6bf 100644
--- a/src/test/regress/expected/inet.out
+++ b/src/test/regress/expected/inet.out
@@ -28,10 +28,12 @@ ERROR: invalid cidr value: "192.168.1.2/30"
LINE 1: INSERT INTO INET_TBL (c, i) VALUES ('192.168.1.2/30', '192.1...
^
DETAIL: Value has bits set to right of mask.
+CONTEXT: INSERT "inet_tbl", column "c", type cidr
INSERT INTO INET_TBL (c, i) VALUES ('1234::1234::1234', '::1.2.3.4');
ERROR: invalid input syntax for type cidr: "1234::1234::1234"
LINE 1: INSERT INTO INET_TBL (c, i) VALUES ('1234::1234::1234', '::1...
^
+CONTEXT: INSERT "inet_tbl", column "c", type cidr
-- check that CIDR rejects invalid input when converting from text:
INSERT INTO INET_TBL (c, i) VALUES (cidr('192.168.1.2/30'), '192.168.1.226');
ERROR: invalid cidr value: "192.168.1.2/30"
diff --git a/src/test/regress/expected/insert.out b/src/test/regress/expected/insert.out
index 70107b5..cd054dd 100644
--- a/src/test/regress/expected/insert.out
+++ b/src/test/regress/expected/insert.out
@@ -96,6 +96,7 @@ insert into inserttest (f2[1], f2[2]) values (1,default); -- not supported
ERROR: cannot set an array element to DEFAULT
LINE 1: insert into inserttest (f2[1], f2[2]) values (1,default);
^
+CONTEXT: INSERT "inserttest", column "f2", type integer[]
insert into inserttest (f3.if1, f3.if2) values (1,array['foo']);
insert into inserttest (f3.if1, f3.if2) values (1,'{foo}'), (2,'{bar}');
insert into inserttest (f3.if1, f3.if2) select 3, '{baz,quux}';
@@ -103,6 +104,7 @@ insert into inserttest (f3.if1, f3.if2) values (1,default); -- not supported
ERROR: cannot set a subfield to DEFAULT
LINE 1: insert into inserttest (f3.if1, f3.if2) values (1,default);
^
+CONTEXT: INSERT "inserttest", column "f3", type insert_test_type
insert into inserttest (f3.if2[1], f3.if2[2]) values ('foo', 'bar');
insert into inserttest (f3.if2[1], f3.if2[2]) values ('foo', 'bar'), ('baz', 'quux');
insert into inserttest (f3.if2[1], f3.if2[2]) select 'bear', 'beer';
diff --git a/src/test/regress/expected/int2.out b/src/test/regress/expected/int2.out
index 3ea4ed9..2ece418 100644
--- a/src/test/regress/expected/int2.out
+++ b/src/test/regress/expected/int2.out
@@ -9,6 +9,7 @@ INSERT INTO INT2_TBL(f1) VALUES ('34.5');
ERROR: invalid input syntax for integer: "34.5"
LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('34.5');
^
+CONTEXT: INSERT "int2_tbl", column "f1", type smallint
-- largest and smallest values
INSERT INTO INT2_TBL(f1) VALUES ('32767');
INSERT INTO INT2_TBL(f1) VALUES ('-32767');
@@ -17,30 +18,37 @@ INSERT INTO INT2_TBL(f1) VALUES ('100000');
ERROR: value "100000" is out of range for type smallint
LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('100000');
^
+CONTEXT: INSERT "int2_tbl", column "f1", type smallint
INSERT INTO INT2_TBL(f1) VALUES ('asdf');
ERROR: invalid input syntax for integer: "asdf"
LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('asdf');
^
+CONTEXT: INSERT "int2_tbl", column "f1", type smallint
INSERT INTO INT2_TBL(f1) VALUES (' ');
ERROR: invalid input syntax for integer: " "
LINE 1: INSERT INTO INT2_TBL(f1) VALUES (' ');
^
+CONTEXT: INSERT "int2_tbl", column "f1", type smallint
INSERT INTO INT2_TBL(f1) VALUES ('- 1234');
ERROR: invalid input syntax for integer: "- 1234"
LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('- 1234');
^
+CONTEXT: INSERT "int2_tbl", column "f1", type smallint
INSERT INTO INT2_TBL(f1) VALUES ('4 444');
ERROR: invalid input syntax for integer: "4 444"
LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('4 444');
^
+CONTEXT: INSERT "int2_tbl", column "f1", type smallint
INSERT INTO INT2_TBL(f1) VALUES ('123 dt');
ERROR: invalid input syntax for integer: "123 dt"
LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('123 dt');
^
+CONTEXT: INSERT "int2_tbl", column "f1", type smallint
INSERT INTO INT2_TBL(f1) VALUES ('');
ERROR: invalid input syntax for integer: ""
LINE 1: INSERT INTO INT2_TBL(f1) VALUES ('');
^
+CONTEXT: INSERT "int2_tbl", column "f1", type smallint
SELECT '' AS five, * FROM INT2_TBL;
five | f1
------+--------
diff --git a/src/test/regress/expected/int4.out b/src/test/regress/expected/int4.out
index 372fd4d..e0d0fc2 100644
--- a/src/test/regress/expected/int4.out
+++ b/src/test/regress/expected/int4.out
@@ -9,6 +9,7 @@ INSERT INTO INT4_TBL(f1) VALUES ('34.5');
ERROR: invalid input syntax for integer: "34.5"
LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('34.5');
^
+CONTEXT: INSERT "int4_tbl", column "f1", type integer
-- largest and smallest values
INSERT INTO INT4_TBL(f1) VALUES ('2147483647');
INSERT INTO INT4_TBL(f1) VALUES ('-2147483647');
@@ -17,30 +18,37 @@ INSERT INTO INT4_TBL(f1) VALUES ('1000000000000');
ERROR: value "1000000000000" is out of range for type integer
LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('1000000000000');
^
+CONTEXT: INSERT "int4_tbl", column "f1", type integer
INSERT INTO INT4_TBL(f1) VALUES ('asdf');
ERROR: invalid input syntax for integer: "asdf"
LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('asdf');
^
+CONTEXT: INSERT "int4_tbl", column "f1", type integer
INSERT INTO INT4_TBL(f1) VALUES (' ');
ERROR: invalid input syntax for integer: " "
LINE 1: INSERT INTO INT4_TBL(f1) VALUES (' ');
^
+CONTEXT: INSERT "int4_tbl", column "f1", type integer
INSERT INTO INT4_TBL(f1) VALUES (' asdf ');
ERROR: invalid input syntax for integer: " asdf "
LINE 1: INSERT INTO INT4_TBL(f1) VALUES (' asdf ');
^
+CONTEXT: INSERT "int4_tbl", column "f1", type integer
INSERT INTO INT4_TBL(f1) VALUES ('- 1234');
ERROR: invalid input syntax for integer: "- 1234"
LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('- 1234');
^
+CONTEXT: INSERT "int4_tbl", column "f1", type integer
INSERT INTO INT4_TBL(f1) VALUES ('123 5');
ERROR: invalid input syntax for integer: "123 5"
LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('123 5');
^
+CONTEXT: INSERT "int4_tbl", column "f1", type integer
INSERT INTO INT4_TBL(f1) VALUES ('');
ERROR: invalid input syntax for integer: ""
LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('');
^
+CONTEXT: INSERT "int4_tbl", column "f1", type integer
SELECT '' AS five, * FROM INT4_TBL;
five | f1
------+-------------
diff --git a/src/test/regress/expected/int8-exp-three-digits.out b/src/test/regress/expected/int8-exp-three-digits.out
index 7ad4dce..a17be9a 100644
--- a/src/test/regress/expected/int8-exp-three-digits.out
+++ b/src/test/regress/expected/int8-exp-three-digits.out
@@ -13,30 +13,37 @@ INSERT INTO INT8_TBL(q1) VALUES (' ');
ERROR: invalid input syntax for integer: " "
LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' ');
^
+CONTEXT: INSERT "int8_tbl", column "q1", type bigint
INSERT INTO INT8_TBL(q1) VALUES ('xxx');
ERROR: invalid input syntax for integer: "xxx"
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('xxx');
^
+CONTEXT: INSERT "int8_tbl", column "q1", type bigint
INSERT INTO INT8_TBL(q1) VALUES ('3908203590239580293850293850329485');
ERROR: value "3908203590239580293850293850329485" is out of range for type bigint
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('39082035902395802938502938...
^
+CONTEXT: INSERT "int8_tbl", column "q1", type bigint
INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340329840934');
ERROR: value "-1204982019841029840928340329840934" is out of range for type bigint
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340...
^
+CONTEXT: INSERT "int8_tbl", column "q1", type bigint
INSERT INTO INT8_TBL(q1) VALUES ('- 123');
ERROR: invalid input syntax for integer: "- 123"
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('- 123');
^
+CONTEXT: INSERT "int8_tbl", column "q1", type bigint
INSERT INTO INT8_TBL(q1) VALUES (' 345 5');
ERROR: invalid input syntax for integer: " 345 5"
LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' 345 5');
^
+CONTEXT: INSERT "int8_tbl", column "q1", type bigint
INSERT INTO INT8_TBL(q1) VALUES ('');
ERROR: invalid input syntax for integer: ""
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('');
^
+CONTEXT: INSERT "int8_tbl", column "q1", type bigint
SELECT * FROM INT8_TBL;
q1 | q2
------------------+-------------------
diff --git a/src/test/regress/expected/int8.out b/src/test/regress/expected/int8.out
index ed0bd34..a311675 100644
--- a/src/test/regress/expected/int8.out
+++ b/src/test/regress/expected/int8.out
@@ -13,30 +13,37 @@ INSERT INTO INT8_TBL(q1) VALUES (' ');
ERROR: invalid input syntax for integer: " "
LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' ');
^
+CONTEXT: INSERT "int8_tbl", column "q1", type bigint
INSERT INTO INT8_TBL(q1) VALUES ('xxx');
ERROR: invalid input syntax for integer: "xxx"
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('xxx');
^
+CONTEXT: INSERT "int8_tbl", column "q1", type bigint
INSERT INTO INT8_TBL(q1) VALUES ('3908203590239580293850293850329485');
ERROR: value "3908203590239580293850293850329485" is out of range for type bigint
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('39082035902395802938502938...
^
+CONTEXT: INSERT "int8_tbl", column "q1", type bigint
INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340329840934');
ERROR: value "-1204982019841029840928340329840934" is out of range for type bigint
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340...
^
+CONTEXT: INSERT "int8_tbl", column "q1", type bigint
INSERT INTO INT8_TBL(q1) VALUES ('- 123');
ERROR: invalid input syntax for integer: "- 123"
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('- 123');
^
+CONTEXT: INSERT "int8_tbl", column "q1", type bigint
INSERT INTO INT8_TBL(q1) VALUES (' 345 5');
ERROR: invalid input syntax for integer: " 345 5"
LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' 345 5');
^
+CONTEXT: INSERT "int8_tbl", column "q1", type bigint
INSERT INTO INT8_TBL(q1) VALUES ('');
ERROR: invalid input syntax for integer: ""
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('');
^
+CONTEXT: INSERT "int8_tbl", column "q1", type bigint
SELECT * FROM INT8_TBL;
q1 | q2
------------------+-------------------
diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out
index c873a99..66d7c18 100644
--- a/src/test/regress/expected/interval.out
+++ b/src/test/regress/expected/interval.out
@@ -68,10 +68,12 @@ INSERT INTO INTERVAL_TBL (f1) VALUES ('badly formatted interval');
ERROR: invalid input syntax for type interval: "badly formatted interval"
LINE 1: INSERT INTO INTERVAL_TBL (f1) VALUES ('badly formatted inter...
^
+CONTEXT: INSERT "interval_tbl", column "f1", type interval
INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 30 eons ago');
ERROR: invalid input syntax for type interval: "@ 30 eons ago"
LINE 1: INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 30 eons ago');
^
+CONTEXT: INSERT "interval_tbl", column "f1", type interval
-- test interval operators
SELECT '' AS ten, * FROM INTERVAL_TBL;
ten | f1
diff --git a/src/test/regress/expected/line.out b/src/test/regress/expected/line.out
index f20abdc..26020f2 100644
--- a/src/test/regress/expected/line.out
+++ b/src/test/regress/expected/line.out
@@ -13,6 +13,7 @@ INSERT INTO LINE_TBL VALUES ('[(1,0),(1,0)]');
ERROR: invalid line specification: must be two distinct points
LINE 1: INSERT INTO LINE_TBL VALUES ('[(1,0),(1,0)]');
^
+CONTEXT: INSERT "line_tbl", column "s", type line
-- horizontal
INSERT INTO LINE_TBL VALUES ('[(1,3),(2,3)]');
-- vertical
@@ -22,22 +23,27 @@ INSERT INTO LINE_TBL VALUES ('{0,0,1}');
ERROR: invalid line specification: A and B cannot both be zero
LINE 1: INSERT INTO LINE_TBL VALUES ('{0,0,1}');
^
+CONTEXT: INSERT "line_tbl", column "s", type line
INSERT INTO LINE_TBL VALUES ('(3asdf,2 ,3,4r2)');
ERROR: invalid input syntax for type line: "(3asdf,2 ,3,4r2)"
LINE 1: INSERT INTO LINE_TBL VALUES ('(3asdf,2 ,3,4r2)');
^
+CONTEXT: INSERT "line_tbl", column "s", type line
INSERT INTO LINE_TBL VALUES ('[1,2,3, 4');
ERROR: invalid input syntax for type line: "[1,2,3, 4"
LINE 1: INSERT INTO LINE_TBL VALUES ('[1,2,3, 4');
^
+CONTEXT: INSERT "line_tbl", column "s", type line
INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
ERROR: invalid input syntax for type line: "[(,2),(3,4)]"
LINE 1: INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
^
+CONTEXT: INSERT "line_tbl", column "s", type line
INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
ERROR: invalid input syntax for type line: "[(1,2),(3,4)"
LINE 1: INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
^
+CONTEXT: INSERT "line_tbl", column "s", type line
select * from LINE_TBL;
s
---------------------------------------------
diff --git a/src/test/regress/expected/lseg.out b/src/test/regress/expected/lseg.out
index bba1f3e..5b1602b 100644
--- a/src/test/regress/expected/lseg.out
+++ b/src/test/regress/expected/lseg.out
@@ -14,18 +14,22 @@ INSERT INTO LSEG_TBL VALUES ('(3asdf,2 ,3,4r2)');
ERROR: invalid input syntax for type lseg: "(3asdf,2 ,3,4r2)"
LINE 1: INSERT INTO LSEG_TBL VALUES ('(3asdf,2 ,3,4r2)');
^
+CONTEXT: INSERT "lseg_tbl", column "s", type lseg
INSERT INTO LSEG_TBL VALUES ('[1,2,3, 4');
ERROR: invalid input syntax for type lseg: "[1,2,3, 4"
LINE 1: INSERT INTO LSEG_TBL VALUES ('[1,2,3, 4');
^
+CONTEXT: INSERT "lseg_tbl", column "s", type lseg
INSERT INTO LSEG_TBL VALUES ('[(,2),(3,4)]');
ERROR: invalid input syntax for type lseg: "[(,2),(3,4)]"
LINE 1: INSERT INTO LSEG_TBL VALUES ('[(,2),(3,4)]');
^
+CONTEXT: INSERT "lseg_tbl", column "s", type lseg
INSERT INTO LSEG_TBL VALUES ('[(1,2),(3,4)');
ERROR: invalid input syntax for type lseg: "[(1,2),(3,4)"
LINE 1: INSERT INTO LSEG_TBL VALUES ('[(1,2),(3,4)');
^
+CONTEXT: INSERT "lseg_tbl", column "s", type lseg
select * from LSEG_TBL;
s
-------------------------------
diff --git a/src/test/regress/expected/macaddr.out b/src/test/regress/expected/macaddr.out
index e84ff5f..fc64f00 100644
--- a/src/test/regress/expected/macaddr.out
+++ b/src/test/regress/expected/macaddr.out
@@ -13,10 +13,12 @@ INSERT INTO macaddr_data VALUES (8, '0800:2b01:0203'); -- invalid
ERROR: invalid input syntax for type macaddr: "0800:2b01:0203"
LINE 1: INSERT INTO macaddr_data VALUES (8, '0800:2b01:0203');
^
+CONTEXT: INSERT "macaddr_data", column "b", type macaddr
INSERT INTO macaddr_data VALUES (9, 'not even close'); -- invalid
ERROR: invalid input syntax for type macaddr: "not even close"
LINE 1: INSERT INTO macaddr_data VALUES (9, 'not even close');
^
+CONTEXT: INSERT "macaddr_data", column "b", type macaddr
INSERT INTO macaddr_data VALUES (10, '08:00:2b:01:02:04');
INSERT INTO macaddr_data VALUES (11, '08:00:2b:01:02:02');
INSERT INTO macaddr_data VALUES (12, '08:00:2a:01:02:03');
diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expected/numeric.out
index ae0beb9..f7e0bee 100644
--- a/src/test/regress/expected/numeric.out
+++ b/src/test/regress/expected/numeric.out
@@ -1293,34 +1293,42 @@ INSERT INTO num_input_test(n1) VALUES (' ');
ERROR: invalid input syntax for type numeric: " "
LINE 1: INSERT INTO num_input_test(n1) VALUES (' ');
^
+CONTEXT: INSERT "num_input_test", column "n1", type numeric
INSERT INTO num_input_test(n1) VALUES (' 1234 %');
ERROR: invalid input syntax for type numeric: " 1234 %"
LINE 1: INSERT INTO num_input_test(n1) VALUES (' 1234 %');
^
+CONTEXT: INSERT "num_input_test", column "n1", type numeric
INSERT INTO num_input_test(n1) VALUES ('xyz');
ERROR: invalid input syntax for type numeric: "xyz"
LINE 1: INSERT INTO num_input_test(n1) VALUES ('xyz');
^
+CONTEXT: INSERT "num_input_test", column "n1", type numeric
INSERT INTO num_input_test(n1) VALUES ('- 1234');
ERROR: invalid input syntax for type numeric: "- 1234"
LINE 1: INSERT INTO num_input_test(n1) VALUES ('- 1234');
^
+CONTEXT: INSERT "num_input_test", column "n1", type numeric
INSERT INTO num_input_test(n1) VALUES ('5 . 0');
ERROR: invalid input syntax for type numeric: "5 . 0"
LINE 1: INSERT INTO num_input_test(n1) VALUES ('5 . 0');
^
+CONTEXT: INSERT "num_input_test", column "n1", type numeric
INSERT INTO num_input_test(n1) VALUES ('5. 0 ');
ERROR: invalid input syntax for type numeric: "5. 0 "
LINE 1: INSERT INTO num_input_test(n1) VALUES ('5. 0 ');
^
+CONTEXT: INSERT "num_input_test", column "n1", type numeric
INSERT INTO num_input_test(n1) VALUES ('');
ERROR: invalid input syntax for type numeric: ""
LINE 1: INSERT INTO num_input_test(n1) VALUES ('');
^
+CONTEXT: INSERT "num_input_test", column "n1", type numeric
INSERT INTO num_input_test(n1) VALUES (' N aN ');
ERROR: invalid input syntax for type numeric: " N aN "
LINE 1: INSERT INTO num_input_test(n1) VALUES (' N aN ');
^
+CONTEXT: INSERT "num_input_test", column "n1", type numeric
SELECT * FROM num_input_test;
n1
---------
diff --git a/src/test/regress/expected/oid.out b/src/test/regress/expected/oid.out
index 1eab9cc..0c7a984 100644
--- a/src/test/regress/expected/oid.out
+++ b/src/test/regress/expected/oid.out
@@ -16,42 +16,52 @@ INSERT INTO OID_TBL(f1) VALUES ('');
ERROR: invalid input syntax for type oid: ""
LINE 1: INSERT INTO OID_TBL(f1) VALUES ('');
^
+CONTEXT: INSERT "oid_tbl", column "f1", type oid
INSERT INTO OID_TBL(f1) VALUES (' ');
ERROR: invalid input syntax for type oid: " "
LINE 1: INSERT INTO OID_TBL(f1) VALUES (' ');
^
+CONTEXT: INSERT "oid_tbl", column "f1", type oid
INSERT INTO OID_TBL(f1) VALUES ('asdfasd');
ERROR: invalid input syntax for type oid: "asdfasd"
LINE 1: INSERT INTO OID_TBL(f1) VALUES ('asdfasd');
^
+CONTEXT: INSERT "oid_tbl", column "f1", type oid
INSERT INTO OID_TBL(f1) VALUES ('99asdfasd');
ERROR: invalid input syntax for type oid: "99asdfasd"
LINE 1: INSERT INTO OID_TBL(f1) VALUES ('99asdfasd');
^
+CONTEXT: INSERT "oid_tbl", column "f1", type oid
INSERT INTO OID_TBL(f1) VALUES ('5 d');
ERROR: invalid input syntax for type oid: "5 d"
LINE 1: INSERT INTO OID_TBL(f1) VALUES ('5 d');
^
+CONTEXT: INSERT "oid_tbl", column "f1", type oid
INSERT INTO OID_TBL(f1) VALUES (' 5d');
ERROR: invalid input syntax for type oid: " 5d"
LINE 1: INSERT INTO OID_TBL(f1) VALUES (' 5d');
^
+CONTEXT: INSERT "oid_tbl", column "f1", type oid
INSERT INTO OID_TBL(f1) VALUES ('5 5');
ERROR: invalid input syntax for type oid: "5 5"
LINE 1: INSERT INTO OID_TBL(f1) VALUES ('5 5');
^
+CONTEXT: INSERT "oid_tbl", column "f1", type oid
INSERT INTO OID_TBL(f1) VALUES (' - 500');
ERROR: invalid input syntax for type oid: " - 500"
LINE 1: INSERT INTO OID_TBL(f1) VALUES (' - 500');
^
+CONTEXT: INSERT "oid_tbl", column "f1", type oid
INSERT INTO OID_TBL(f1) VALUES ('32958209582039852935');
ERROR: value "32958209582039852935" is out of range for type oid
LINE 1: INSERT INTO OID_TBL(f1) VALUES ('32958209582039852935');
^
+CONTEXT: INSERT "oid_tbl", column "f1", type oid
INSERT INTO OID_TBL(f1) VALUES ('-23582358720398502385');
ERROR: value "-23582358720398502385" is out of range for type oid
LINE 1: INSERT INTO OID_TBL(f1) VALUES ('-23582358720398502385');
^
+CONTEXT: INSERT "oid_tbl", column "f1", type oid
SELECT '' AS six, * FROM OID_TBL;
six | f1
-----+------------
diff --git a/src/test/regress/expected/path.out b/src/test/regress/expected/path.out
index 08d6d61..7f017da 100644
--- a/src/test/regress/expected/path.out
+++ b/src/test/regress/expected/path.out
@@ -16,10 +16,12 @@ INSERT INTO PATH_TBL VALUES ('[(,2),(3,4)]');
ERROR: invalid input syntax for type path: "[(,2),(3,4)]"
LINE 1: INSERT INTO PATH_TBL VALUES ('[(,2),(3,4)]');
^
+CONTEXT: INSERT "path_tbl", column "f1", type path
INSERT INTO PATH_TBL VALUES ('[(1,2),(3,4)');
ERROR: invalid input syntax for type path: "[(1,2),(3,4)"
LINE 1: INSERT INTO PATH_TBL VALUES ('[(1,2),(3,4)');
^
+CONTEXT: INSERT "path_tbl", column "f1", type path
SELECT f1 FROM PATH_TBL;
f1
---------------------------
diff --git a/src/test/regress/expected/pg_lsn.out b/src/test/regress/expected/pg_lsn.out
index 2854cfd..6211af4 100644
--- a/src/test/regress/expected/pg_lsn.out
+++ b/src/test/regress/expected/pg_lsn.out
@@ -10,22 +10,27 @@ INSERT INTO PG_LSN_TBL VALUES ('G/0');
ERROR: invalid input syntax for type pg_lsn: "G/0"
LINE 1: INSERT INTO PG_LSN_TBL VALUES ('G/0');
^
+CONTEXT: INSERT "pg_lsn_tbl", column "f1", type pg_lsn
INSERT INTO PG_LSN_TBL VALUES ('-1/0');
ERROR: invalid input syntax for type pg_lsn: "-1/0"
LINE 1: INSERT INTO PG_LSN_TBL VALUES ('-1/0');
^
+CONTEXT: INSERT "pg_lsn_tbl", column "f1", type pg_lsn
INSERT INTO PG_LSN_TBL VALUES (' 0/12345678');
ERROR: invalid input syntax for type pg_lsn: " 0/12345678"
LINE 1: INSERT INTO PG_LSN_TBL VALUES (' 0/12345678');
^
+CONTEXT: INSERT "pg_lsn_tbl", column "f1", type pg_lsn
INSERT INTO PG_LSN_TBL VALUES ('ABCD/');
ERROR: invalid input syntax for type pg_lsn: "ABCD/"
LINE 1: INSERT INTO PG_LSN_TBL VALUES ('ABCD/');
^
+CONTEXT: INSERT "pg_lsn_tbl", column "f1", type pg_lsn
INSERT INTO PG_LSN_TBL VALUES ('/ABCD');
ERROR: invalid input syntax for type pg_lsn: "/ABCD"
LINE 1: INSERT INTO PG_LSN_TBL VALUES ('/ABCD');
^
+CONTEXT: INSERT "pg_lsn_tbl", column "f1", type pg_lsn
DROP TABLE PG_LSN_TBL;
-- Operators
SELECT '0/16AE7F8' = '0/16AE7F8'::pg_lsn;
diff --git a/src/test/regress/expected/point.out b/src/test/regress/expected/point.out
index bfc0962..f726f12 100644
--- a/src/test/regress/expected/point.out
+++ b/src/test/regress/expected/point.out
@@ -12,15 +12,18 @@ INSERT INTO POINT_TBL(f1) VALUES ('asdfasdf');
ERROR: invalid input syntax for type point: "asdfasdf"
LINE 1: INSERT INTO POINT_TBL(f1) VALUES ('asdfasdf');
^
+CONTEXT: INSERT "point_tbl", column "f1", type point
INSERT INTO POINT_TBL(f1) VALUES ('10.0,10.0');
INSERT INTO POINT_TBL(f1) VALUES ('(10.0 10.0)');
ERROR: invalid input syntax for type point: "(10.0 10.0)"
LINE 1: INSERT INTO POINT_TBL(f1) VALUES ('(10.0 10.0)');
^
+CONTEXT: INSERT "point_tbl", column "f1", type point
INSERT INTO POINT_TBL(f1) VALUES ('(10.0,10.0');
ERROR: invalid input syntax for type point: "(10.0,10.0"
LINE 1: INSERT INTO POINT_TBL(f1) VALUES ('(10.0,10.0');
^
+CONTEXT: INSERT "point_tbl", column "f1", type point
SELECT '' AS six, * FROM POINT_TBL;
six | f1
-----+------------
diff --git a/src/test/regress/expected/polygon.out b/src/test/regress/expected/polygon.out
index 2361274..ffc3bcd 100644
--- a/src/test/regress/expected/polygon.out
+++ b/src/test/regress/expected/polygon.out
@@ -14,22 +14,27 @@ INSERT INTO POLYGON_TBL(f1) VALUES ('0.0');
ERROR: invalid input syntax for type polygon: "0.0"
LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('0.0');
^
+CONTEXT: INSERT "polygon_tbl", column "f1", type polygon
INSERT INTO POLYGON_TBL(f1) VALUES ('(0.0 0.0');
ERROR: invalid input syntax for type polygon: "(0.0 0.0"
LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('(0.0 0.0');
^
+CONTEXT: INSERT "polygon_tbl", column "f1", type polygon
INSERT INTO POLYGON_TBL(f1) VALUES ('(0,1,2)');
ERROR: invalid input syntax for type polygon: "(0,1,2)"
LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('(0,1,2)');
^
+CONTEXT: INSERT "polygon_tbl", column "f1", type polygon
INSERT INTO POLYGON_TBL(f1) VALUES ('(0,1,2,3');
ERROR: invalid input syntax for type polygon: "(0,1,2,3"
LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('(0,1,2,3');
^
+CONTEXT: INSERT "polygon_tbl", column "f1", type polygon
INSERT INTO POLYGON_TBL(f1) VALUES ('asdf');
ERROR: invalid input syntax for type polygon: "asdf"
LINE 1: INSERT INTO POLYGON_TBL(f1) VALUES ('asdf');
^
+CONTEXT: INSERT "polygon_tbl", column "f1", type polygon
SELECT '' AS four, * FROM POLYGON_TBL;
four | f1
------+---------------------
diff --git a/src/test/regress/expected/reltime.out b/src/test/regress/expected/reltime.out
index 14fdc6a..4c53841 100644
--- a/src/test/regress/expected/reltime.out
+++ b/src/test/regress/expected/reltime.out
@@ -13,10 +13,12 @@ INSERT INTO RELTIME_TBL (f1) VALUES ('badly formatted reltime');
ERROR: invalid input syntax for type reltime: "badly formatted reltime"
LINE 1: INSERT INTO RELTIME_TBL (f1) VALUES ('badly formatted reltim...
^
+CONTEXT: INSERT "reltime_tbl", column "f1", type reltime
INSERT INTO RELTIME_TBL (f1) VALUES ('@ 30 eons ago');
ERROR: invalid input syntax for type reltime: "@ 30 eons ago"
LINE 1: INSERT INTO RELTIME_TBL (f1) VALUES ('@ 30 eons ago');
^
+CONTEXT: INSERT "reltime_tbl", column "f1", type reltime
-- test reltime operators
SELECT '' AS six, * FROM RELTIME_TBL;
six | f1
diff --git a/src/test/regress/expected/rowtypes.out b/src/test/regress/expected/rowtypes.out
index 25b0828..e74ff33 100644
--- a/src/test/regress/expected/rowtypes.out
+++ b/src/test/regress/expected/rowtypes.out
@@ -416,6 +416,7 @@ ERROR: column "f1" is of type integer but expression is of type compos
LINE 2: insert into compos values (v); -- fail
^
HINT: You will need to rewrite or cast the expression.
+CONTEXT: INSERT "compos", column "f1", type integer
create function fcompos1(v compos) returns void as $$
insert into compos values (v.*);
$$ language sql;
diff --git a/src/test/regress/expected/time.out b/src/test/regress/expected/time.out
index 8e0afe6..51c5c99 100644
--- a/src/test/regress/expected/time.out
+++ b/src/test/regress/expected/time.out
@@ -18,6 +18,7 @@ INSERT INTO TIME_TBL VALUES ('15:36:39 America/New_York');
ERROR: invalid input syntax for type time: "15:36:39 America/New_York"
LINE 1: INSERT INTO TIME_TBL VALUES ('15:36:39 America/New_York');
^
+CONTEXT: INSERT "time_tbl", column "f1", type time without time zone
SELECT f1 AS "Time" FROM TIME_TBL;
Time
-------------
diff --git a/src/test/regress/expected/timestamp.out b/src/test/regress/expected/timestamp.out
index 4a2fabd..fa3d8cf 100644
--- a/src/test/regress/expected/timestamp.out
+++ b/src/test/regress/expected/timestamp.out
@@ -84,14 +84,17 @@ INSERT INTO TIMESTAMP_TBL VALUES ('invalid');
ERROR: date/time value "invalid" is no longer supported
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('invalid');
^
+CONTEXT: INSERT "timestamp_tbl", column "d1", type timestamp without time zone
INSERT INTO TIMESTAMP_TBL VALUES ('undefined');
ERROR: date/time value "undefined" is no longer supported
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('undefined');
^
+CONTEXT: INSERT "timestamp_tbl", column "d1", type timestamp without time zone
INSERT INTO TIMESTAMP_TBL VALUES ('current');
ERROR: date/time value "current" is no longer supported
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('current');
^
+CONTEXT: INSERT "timestamp_tbl", column "d1", type timestamp without time zone
-- Postgres v6.0 standard output format
INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
-- Variations on Postgres v6.1 standard output format
@@ -135,6 +138,7 @@ INSERT INTO TIMESTAMP_TBL VALUES ('19970710 173201 America/Does_not_exist');
ERROR: time zone "america/does_not_exist" not recognized
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('19970710 173201 America/D...
^
+CONTEXT: INSERT "timestamp_tbl", column "d1", type timestamp without time zone
-- Check date conversion and date arithmetic
INSERT INTO TIMESTAMP_TBL VALUES ('1997-06-10 18:32:01 PDT');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 10 17:32:01 1997');
@@ -164,6 +168,7 @@ INSERT INTO TIMESTAMP_TBL VALUES ('Feb 29 17:32:01 1997');
ERROR: date/time field value out of range: "Feb 29 17:32:01 1997"
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('Feb 29 17:32:01 1997');
^
+CONTEXT: INSERT "timestamp_tbl", column "d1", type timestamp without time zone
INSERT INTO TIMESTAMP_TBL VALUES ('Mar 01 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Dec 30 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Dec 31 17:32:01 1997');
@@ -176,10 +181,12 @@ INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 -0097');
ERROR: time zone displacement out of range: "Feb 16 17:32:01 -0097"
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 -0097');
^
+CONTEXT: INSERT "timestamp_tbl", column "d1", type timestamp without time zone
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 5097 BC');
ERROR: timestamp out of range: "Feb 16 17:32:01 5097 BC"
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 5097 BC')...
^
+CONTEXT: INSERT "timestamp_tbl", column "d1", type timestamp without time zone
SELECT '' AS "64", d1 FROM TIMESTAMP_TBL;
64 | d1
----+-----------------------------
diff --git a/src/test/regress/expected/timestamptz.out b/src/test/regress/expected/timestamptz.out
index 9fa93a4..b51e614 100644
--- a/src/test/regress/expected/timestamptz.out
+++ b/src/test/regress/expected/timestamptz.out
@@ -83,14 +83,17 @@ INSERT INTO TIMESTAMPTZ_TBL VALUES ('invalid');
ERROR: date/time value "invalid" is no longer supported
LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('invalid');
^
+CONTEXT: INSERT "timestamptz_tbl", column "d1", type timestamp with time zone
INSERT INTO TIMESTAMPTZ_TBL VALUES ('undefined');
ERROR: date/time value "undefined" is no longer supported
LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('undefined');
^
+CONTEXT: INSERT "timestamptz_tbl", column "d1", type timestamp with time zone
INSERT INTO TIMESTAMPTZ_TBL VALUES ('current');
ERROR: date/time value "current" is no longer supported
LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('current');
^
+CONTEXT: INSERT "timestamptz_tbl", column "d1", type timestamp with time zone
-- Postgres v6.0 standard output format
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
-- Variations on Postgres v6.1 standard output format
@@ -147,6 +150,7 @@ INSERT INTO TIMESTAMPTZ_TBL VALUES ('19970710 173201 America/Does_not_exist');
ERROR: time zone "america/does_not_exist" not recognized
LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('19970710 173201 America...
^
+CONTEXT: INSERT "timestamptz_tbl", column "d1", type timestamp with time zone
SELECT '19970710 173201' AT TIME ZONE 'America/Does_not_exist';
ERROR: time zone "America/Does_not_exist" not recognized
-- Daylight saving time for timestamps beyond 32-bit time_t range.
@@ -203,6 +207,7 @@ INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 29 17:32:01 1997');
ERROR: date/time field value out of range: "Feb 29 17:32:01 1997"
LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 29 17:32:01 1997');
^
+CONTEXT: INSERT "timestamptz_tbl", column "d1", type timestamp with time zone
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mar 01 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Dec 30 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Dec 31 17:32:01 1997');
@@ -215,10 +220,12 @@ INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 -0097');
ERROR: time zone displacement out of range: "Feb 16 17:32:01 -0097"
LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 -0097')...
^
+CONTEXT: INSERT "timestamptz_tbl", column "d1", type timestamp with time zone
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 5097 BC');
ERROR: timestamp out of range: "Feb 16 17:32:01 5097 BC"
LINE 1: INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 5097 BC...
^
+CONTEXT: INSERT "timestamptz_tbl", column "d1", type timestamp with time zone
-- Alternative field order that we've historically supported (sort of)
-- with regular and POSIXy timezone specs
SELECT 'Wed Jul 11 10:51:14 America/New_York 2001'::timestamptz;
diff --git a/src/test/regress/expected/timetz.out b/src/test/regress/expected/timetz.out
index 4391131..645fc3c 100644
--- a/src/test/regress/expected/timetz.out
+++ b/src/test/regress/expected/timetz.out
@@ -19,6 +19,7 @@ INSERT INTO TIMETZ_TBL VALUES ('15:36:39 America/New_York');
ERROR: invalid input syntax for type time with time zone: "15:36:39 America/New_York"
LINE 1: INSERT INTO TIMETZ_TBL VALUES ('15:36:39 America/New_York');
^
+CONTEXT: INSERT "timetz_tbl", column "f1", type time with time zone
SELECT f1 AS "Time TZ" FROM TIMETZ_TBL;
Time TZ
----------------
diff --git a/src/test/regress/expected/tinterval.out b/src/test/regress/expected/tinterval.out
index a018972..dfd4903 100644
--- a/src/test/regress/expected/tinterval.out
+++ b/src/test/regress/expected/tinterval.out
@@ -20,11 +20,13 @@ INSERT INTO TINTERVAL_TBL (f1)
ERROR: invalid input syntax for type abstime: "bad time specifications"
LINE 2: VALUES ('["bad time specifications" ""]');
^
+CONTEXT: INSERT "tinterval_tbl", column "f1", type tinterval
INSERT INTO TINTERVAL_TBL (f1)
VALUES ('["" "infinity"]');
ERROR: invalid input syntax for type abstime: ""
LINE 2: VALUES ('["" "infinity"]');
^
+CONTEXT: INSERT "tinterval_tbl", column "f1", type tinterval
-- test tinterval operators
SELECT '' AS five, * FROM TINTERVAL_TBL;
five | f1
diff --git a/src/test/regress/expected/uuid.out b/src/test/regress/expected/uuid.out
index 59cb1e0..e2b4341 100644
--- a/src/test/regress/expected/uuid.out
+++ b/src/test/regress/expected/uuid.out
@@ -16,29 +16,35 @@ INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111F');
ERROR: invalid input syntax for uuid: "11111111-1111-1111-1111-111111111111F"
LINE 1: INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-111...
^
+CONTEXT: INSERT "guid1", column "guid_field", type uuid
-- too short
INSERT INTO guid1(guid_field) VALUES('{11111111-1111-1111-1111-11111111111}');
ERROR: invalid input syntax for uuid: "{11111111-1111-1111-1111-11111111111}"
LINE 1: INSERT INTO guid1(guid_field) VALUES('{11111111-1111-1111-11...
^
+CONTEXT: INSERT "guid1", column "guid_field", type uuid
-- valid data but invalid format
INSERT INTO guid1(guid_field) VALUES('111-11111-1111-1111-1111-111111111111');
ERROR: invalid input syntax for uuid: "111-11111-1111-1111-1111-111111111111"
LINE 1: INSERT INTO guid1(guid_field) VALUES('111-11111-1111-1111-11...
^
+CONTEXT: INSERT "guid1", column "guid_field", type uuid
INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-2222-222222222222 ');
ERROR: invalid input syntax for uuid: "{22222222-2222-2222-2222-222222222222 "
LINE 1: INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-22...
^
+CONTEXT: INSERT "guid1", column "guid_field", type uuid
-- invalid data
INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-G111-111111111111');
ERROR: invalid input syntax for uuid: "11111111-1111-1111-G111-111111111111"
LINE 1: INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-G11...
^
+CONTEXT: INSERT "guid1", column "guid_field", type uuid
INSERT INTO guid1(guid_field) VALUES('11+11111-1111-1111-1111-111111111111');
ERROR: invalid input syntax for uuid: "11+11111-1111-1111-1111-111111111111"
LINE 1: INSERT INTO guid1(guid_field) VALUES('11+11111-1111-1111-111...
^
+CONTEXT: INSERT "guid1", column "guid_field", type uuid
--inserting three input formats
INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111');
INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-2222-222222222222}');
diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out
index f21e119..7f89126 100644
--- a/src/test/regress/expected/xml.out
+++ b/src/test/regress/expected/xml.out
@@ -11,6 +11,7 @@ LINE 1: INSERT INTO xmltest VALUES (3, '<wrong');
DETAIL: line 1: Couldn't find end of Start Tag wrong line 1
<wrong
^
+CONTEXT: INSERT "xmltest", column "data", type xml
SELECT * FROM xmltest;
id | data
----+--------------------
diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out
index d702703..ccc9bf9 100644
--- a/src/test/regress/expected/xml_1.out
+++ b/src/test/regress/expected/xml_1.out
@@ -8,18 +8,21 @@ LINE 1: INSERT INTO xmltest VALUES (1, '<value>one</value>');
^
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
+CONTEXT: INSERT "xmltest", column "data", type xml
INSERT INTO xmltest VALUES (2, '<value>two</value>');
ERROR: unsupported XML feature
LINE 1: INSERT INTO xmltest VALUES (2, '<value>two</value>');
^
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
+CONTEXT: INSERT "xmltest", column "data", type xml
INSERT INTO xmltest VALUES (3, '<wrong');
ERROR: unsupported XML feature
LINE 1: INSERT INTO xmltest VALUES (3, '<wrong');
^
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
+CONTEXT: INSERT "xmltest", column "data", type xml
SELECT * FROM xmltest;
id | data
----+------
diff --git a/src/test/regress/expected/xml_2.out b/src/test/regress/expected/xml_2.out
index 530faf5..af587df 100644
--- a/src/test/regress/expected/xml_2.out
+++ b/src/test/regress/expected/xml_2.out
@@ -9,6 +9,7 @@ ERROR: invalid XML content
LINE 1: INSERT INTO xmltest VALUES (3, '<wrong');
^
DETAIL: line 1: Couldn't find end of Start Tag wrong line 1
+CONTEXT: INSERT "xmltest", column "data", type xml
SELECT * FROM xmltest;
id | data
----+--------------------
On Sun, Oct 30, 2016 at 12:04 AM, Michael Paquier <michael.paquier@gmail.com
wrote:
Okay, so I have reworked the patch a bit and finished with the
attached, adapting the context message to give more information. I
have noticed as well a bug in the patch: the context callback was set
before checking if the column used for transformation is checked on
being a system column or not, the problem being that the callback
could be called without the fields set.
Interesting. I wasn't sure it was set at the right time indeed.
I have updated the regression tests that I found, the main portion of
the patch being dedicated to that and being sure that all the
alternate outputs are correctly refreshed. In this case int8, float4,
float8, xml and contrib/citext are the ones impacted by the change
with alternate outputs.
Thanks! I couldn't find time to update it last week, so thanks for chiming
in.
I am passing that down to a committer for review. The patch looks
large, but at 95% it involves diffs in the regression tests,
alternative outputs taking a large role in the bloat.
Great, thanks Michael!
--
Franck
Michael Paquier <michael.paquier@gmail.com> writes:
I am passing that down to a committer for review. The patch looks
large, but at 95% it involves diffs in the regression tests,
alternative outputs taking a large role in the bloat.
This is kind of cute, but it doesn't seem to cover very much territory,
because it only catches errors that are found in the parse stage.
For instance, it fails to cover Franck's original example:
# create table foo(bar varchar(4), baz varchar(2));
CREATE TABLE
# insert into foo values ('foo2!', 'ok');
ERROR: value too long for type character varying(4)
That's still all you get, because the parser sets that up as a varchar
literal with a runtime length coercion, and the failure doesn't occur
till later. In this particular example it happens during the planner's
constant-folding stage, but with a non-constant expression it would
happen in the executor.
Maybe it'd be all right to commit this anyway, but I'm afraid the most
common reaction would be "why's it give me this info some of the time,
but not when I really need it?" I'm inclined to think that an acceptable
patch will need to provide context for the plan-time and run-time cases
too, and I'm not very sure where would be a sane place to plug in for
those cases.
Less important comments:
* I don't really see the point of including the column type name in the
error message. We don't do that in the COPY context message this is
based on. If we were going to print it, I should think we'd need the
typmod as well --- eg, the difference between varchar(4) and varchar(4000)
could be pretty relevant.
* The coding order here is subtly wrong:
+ /* Set up callback to fetch more details regarding the error */
+ errcallback.callback = TransformExprCallback;
+ errcallback.arg = (void *) &te_state;
+ errcallback.previous = error_context_stack;
+ error_context_stack = &errcallback;
+ te_state.relation_name = RelationGetRelationName(rd);
+ te_state.column_name = colname;
+ te_state.expected_type = attrtype;
+ te_state.is_insert = pstate->p_is_insert;
The callback is "live" the instant you assign to error_context_stack;
any data it depends on had better be valid before that. In this case
you're effectively depending on the assumption that
RelationGetRelationName can't throw an error. While it probably can't
today, better style would be to set up te_state first, eg
+ /* Set up callback to fetch more details regarding the error */
+ te_state.relation_name = RelationGetRelationName(rd);
+ te_state.column_name = colname;
+ te_state.expected_type = attrtype;
+ te_state.is_insert = pstate->p_is_insert;
+ errcallback.callback = TransformExprCallback;
+ errcallback.arg = (void *) &te_state;
+ errcallback.previous = error_context_stack;
+ error_context_stack = &errcallback;
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Fri, Nov 4, 2016 at 12:15 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Michael Paquier <michael.paquier@gmail.com> writes:
I am passing that down to a committer for review. The patch looks
large, but at 95% it involves diffs in the regression tests,
alternative outputs taking a large role in the bloat.This is kind of cute, but it doesn't seem to cover very much territory,
because it only catches errors that are found in the parse stage.
For instance, it fails to cover Franck's original example:
[...]Maybe it'd be all right to commit this anyway, but I'm afraid the most
common reaction would be "why's it give me this info some of the time,
but not when I really need it?" I'm inclined to think that an acceptable
patch will need to provide context for the plan-time and run-time cases
too, and I'm not very sure where would be a sane place to plug in for
those cases.
Agreed.
David J.
On Sat, Nov 5, 2016 at 4:15 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
The callback is "live" the instant you assign to error_context_stack;
any data it depends on had better be valid before that. In this case
you're effectively depending on the assumption that
RelationGetRelationName can't throw an error.
Argh, that's obvious. Thanks for the notice.
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
I wrote:
Maybe it'd be all right to commit this anyway, but I'm afraid the most
common reaction would be "why's it give me this info some of the time,
but not when I really need it?" I'm inclined to think that an acceptable
patch will need to provide context for the plan-time and run-time cases
too, and I'm not very sure where would be a sane place to plug in for
those cases.
I thought about that a little more. It would probably not be that hard to
fix the plan-time-error case, because that type of error would happen
while applying constant folding to the target list, ie basically here:
parse->targetList = (List *)
preprocess_expression(root, (Node *) parse->targetList,
EXPRKIND_TARGET);
Right now that processes the whole tlist indiscriminately, but it would
not be very much additional code to make it iterate over the individual
tlist elements and set a callback while processing one that corresponds
directly to an insert or update target column.
However, getting it to happen for run-time errors seems like a complete
mess. The evaluation of the expression doesn't even happen in the
ModifyTable node per se, but in some child plan node that has no idea that
it's supplying data that's destined to get stored into a table column.
I can think of ways around that --- the most obvious one is to invent some
kind of wrapper expression node that has no impact on semantics but sets
up an errcontext callback. But I'm sure Andres will object, because that
would break his idea of getting rid of recursive-descent expression
evaluation. And any way of doing this would probably create a measurable
performance impact, which nobody would be happy about.
So it seems to me that we have to decide whether supplying context only
for assignment of constant expressions is good enough. If it isn't,
we'd be best off to reject this patch rather than create an expectation
among users that such context should be there. And personally, I think
it probably isn't good enough --- non-constant expressions would be
precisely the case where you most need some localization.
The cases that are successfully annotated by the current patch seem to
mostly already have error cursor information, which really is good enough
IMO --- you can certainly figure out which column corresponds to the
textual spot that the cursor is pointing at. I wonder whether we should
not try to move in the direction of expanding the set of errors that we
can provide error cursor info for. One aspect of that would be making
sure that the text of the current statement is always available at
runtime. I believe we do always have it somewhere now, but I'm not sure
that it's passed through to the executor in any convenient way. The
other aspect would then be to provide errlocation information based on
the expression node that we're currently executing. That seems do-able
probably. The overhead would likely consist of storing a pointer to the
current node someplace where an error context callback could find it.
Which is not zero cost, but I think it wouldn't be awful.
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
I wrote:
... I wonder whether we should
not try to move in the direction of expanding the set of errors that we
can provide error cursor info for. One aspect of that would be making
sure that the text of the current statement is always available at
runtime. I believe we do always have it somewhere now, but I'm not sure
that it's passed through to the executor in any convenient way. The
other aspect would then be to provide errlocation information based on
the expression node that we're currently executing. That seems do-able
probably. The overhead would likely consist of storing a pointer to the
current node someplace where an error context callback could find it.
Which is not zero cost, but I think it wouldn't be awful.
Just to demonstrate what I'm talking about, I made a really dirty
proof-of-concept patch, attached. With this, you get results like
regression=# create table foo(bar varchar(4), baz varchar(2));
CREATE TABLE
regression=# insert into foo values ('foo2!', 'ok');
ERROR: value too long for type character varying(4)
LINE 1: insert into foo values ('foo2!', 'ok');
^
which was the original complaint, and it also works for run-time cases:
regression=# insert into foo values (random()::text, 'ok');
ERROR: value too long for type character varying(4)
LINE 1: insert into foo values (random()::text, 'ok');
^
If that seems like a satisfactory behavior, somebody could push forward
with turning this into a committable patch. There's a lot to do:
* I just used debug_query_string as the statement text source, which means
it only works correctly for errors in directly client-issued statements.
We'd need some work on appropriately passing the correct text down to
execution. (It would be a good idea to decouple elog.c from
debug_query_string while at it, I think.)
* I didn't do anything about nested execution contexts. You'd want only
the innermost one to set the cursor pointer, but as the code stands
I think the outermost one would win.
* Some attention needs to be paid to factorizing the support nicely
--- multiple copies of the callback isn't good, and we might end up
with many copies of the setup boilerplate. Maybe the parser's
pcb_error_callback infrastructure would be a useful prototype.
* I only bothered to hook in execution of function/operator nodes.
That's probably a 90% solution already, but it's not meant to be
the final version.
Likely, doing anything about the last point should wait on Andres' work
with linearizing expression execution. As this patch stands, you have to
think carefully about where within an ExecEvalFoo function is the right
place to set cur_expr, since it shouldn't get set till after control
returns from subsidiary nodes. But those recursive calls would go away.
regards, tom lane
Attachments:
cursor-positions-for-runtime-errors-crude-hack.patchtext/x-diff; charset=us-ascii; name=cursor-positions-for-runtime-errors-crude-hack.patchDownload
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 743e7d6..81aa0b8 100644
*** a/src/backend/executor/execQual.c
--- b/src/backend/executor/execQual.c
***************
*** 44,49 ****
--- 44,50 ----
#include "executor/execdebug.h"
#include "executor/nodeSubplan.h"
#include "funcapi.h"
+ #include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
***************
*** 51,56 ****
--- 52,58 ----
#include "parser/parse_coerce.h"
#include "parser/parsetree.h"
#include "pgstat.h"
+ #include "tcop/tcopprot.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/date.h"
*************** restart:
*** 1772,1777 ****
--- 1774,1782 ----
fcache->setArgsValid = false;
}
+ /* Treat function as active beginning here */
+ econtext->cur_expr = (ExprState *) fcache;
+
/*
* Now call the function, passing the evaluated parameter values.
*/
*************** restart:
*** 1969,1974 ****
--- 1974,1980 ----
if (fcinfo->argnull[i])
{
*isNull = true;
+ econtext->cur_expr = NULL;
return (Datum) 0;
}
}
*************** restart:
*** 1983,1988 ****
--- 1989,1996 ----
pgstat_end_function_usage(&fcusage, true);
}
+ econtext->cur_expr = NULL;
+
return result;
}
*************** ExecMakeFunctionResultNoSets(FuncExprSta
*** 2040,2045 ****
--- 2048,2056 ----
}
}
+ /* Treat function as active beginning here */
+ econtext->cur_expr = (ExprState *) fcache;
+
pgstat_init_function_usage(fcinfo, &fcusage);
fcinfo->isnull = false;
*************** ExecMakeFunctionResultNoSets(FuncExprSta
*** 2048,2053 ****
--- 2059,2066 ----
pgstat_end_function_usage(&fcusage, true);
+ econtext->cur_expr = NULL;
+
return result;
}
*************** ExecPrepareExpr(Expr *node, EState *esta
*** 5309,5314 ****
--- 5322,5350 ----
* ----------------------------------------------------------------
*/
+ static void
+ ExprErrorCallback(void *arg)
+ {
+ ExprContext *econtext = (ExprContext *) arg;
+
+ if (econtext->cur_expr)
+ {
+ int location = exprLocation((Node *) econtext->cur_expr->expr);
+ int pos;
+
+ /* No-op if location was not provided */
+ if (location < 0)
+ return;
+ /* Can't do anything if source text is not available */
+ if (debug_query_string == NULL)
+ return;
+ /* Convert offset to character number */
+ pos = pg_mbstrlen_with_len(debug_query_string, location) + 1;
+ /* And pass it to the ereport mechanism */
+ errposition(pos);
+ }
+ }
+
/* ----------------------------------------------------------------
* ExecQual
*
*************** bool
*** 5341,5346 ****
--- 5377,5383 ----
ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
{
bool result;
+ ErrorContextCallback errcallback;
MemoryContext oldContext;
ListCell *l;
*************** ExecQual(List *qual, ExprContext *econte
*** 5351,5356 ****
--- 5388,5400 ----
EV_nodeDisplay(qual);
EV_printf("\n");
+ /* Setup error traceback support for ereport() */
+ econtext->cur_expr = NULL;
+ errcallback.callback = ExprErrorCallback;
+ errcallback.arg = (void *) econtext;
+ errcallback.previous = error_context_stack;
+ error_context_stack = &errcallback;
+
/*
* Run in short-lived per-tuple context while computing expressions.
*/
*************** ExecQual(List *qual, ExprContext *econte
*** 5398,5403 ****
--- 5442,5449 ----
MemoryContextSwitchTo(oldContext);
+ error_context_stack = errcallback.previous;
+
return result;
}
*************** ExecTargetList(List *targetlist,
*** 5463,5472 ****
--- 5509,5526 ----
ExprDoneCond *isDone)
{
Form_pg_attribute *att = tupdesc->attrs;
+ ErrorContextCallback errcallback;
MemoryContext oldContext;
ListCell *tl;
bool haveDoneSets;
+ /* Setup error traceback support for ereport() */
+ econtext->cur_expr = NULL;
+ errcallback.callback = ExprErrorCallback;
+ errcallback.arg = (void *) econtext;
+ errcallback.previous = error_context_stack;
+ error_context_stack = &errcallback;
+
/*
* Run in short-lived per-tuple context while computing expressions.
*/
*************** ExecTargetList(List *targetlist,
*** 5524,5529 ****
--- 5578,5584 ----
*/
*isDone = ExprEndResult;
MemoryContextSwitchTo(oldContext);
+ error_context_stack = errcallback.previous;
return false;
}
else
*************** ExecTargetList(List *targetlist,
*** 5587,5592 ****
--- 5642,5648 ----
}
MemoryContextSwitchTo(oldContext);
+ error_context_stack = errcallback.previous;
return false;
}
}
*************** ExecTargetList(List *targetlist,
*** 5595,5600 ****
--- 5651,5658 ----
/* Report success */
MemoryContextSwitchTo(oldContext);
+ error_context_stack = errcallback.previous;
+
return true;
}
*************** ExecProject(ProjectionInfo *projInfo, Ex
*** 5616,5621 ****
--- 5674,5680 ----
{
TupleTableSlot *slot;
ExprContext *econtext;
+ ErrorContextCallback errcallback;
int numSimpleVars;
/*
*************** ExecProject(ProjectionInfo *projInfo, Ex
*** 5629,5634 ****
--- 5688,5700 ----
slot = projInfo->pi_slot;
econtext = projInfo->pi_exprContext;
+ /* Setup error traceback support for ereport() */
+ econtext->cur_expr = NULL;
+ errcallback.callback = ExprErrorCallback;
+ errcallback.arg = (void *) econtext;
+ errcallback.previous = error_context_stack;
+ error_context_stack = &errcallback;
+
/* Assume single result row until proven otherwise */
if (isDone)
*isDone = ExprSingleResult;
*************** ExecProject(ProjectionInfo *projInfo, Ex
*** 5714,5722 ****
--- 5780,5793 ----
slot->tts_isnull,
projInfo->pi_itemIsDone,
isDone))
+ {
+ error_context_stack = errcallback.previous;
return slot; /* no more result rows, return empty slot */
+ }
}
+ error_context_stack = errcallback.previous;
+
/*
* Successfully formed a result row. Mark the result slot as containing a
* valid virtual tuple.
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 1688310..583cf43 100644
*** a/src/backend/optimizer/util/clauses.c
--- b/src/backend/optimizer/util/clauses.c
***************
*** 29,34 ****
--- 29,35 ----
#include "executor/executor.h"
#include "executor/functions.h"
#include "funcapi.h"
+ #include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
*************** sql_inline_error_callback(void *arg)
*** 4698,4703 ****
--- 4699,4727 ----
errcontext("SQL function \"%s\" during inlining", callback_arg->proname);
}
+ static void
+ ExprErrorCallback(void *arg)
+ {
+ ExprContext *econtext = (ExprContext *) arg;
+
+ if (econtext->cur_expr)
+ {
+ int location = exprLocation((Node *) econtext->cur_expr->expr);
+ int pos;
+
+ /* No-op if location was not provided */
+ if (location < 0)
+ return;
+ /* Can't do anything if source text is not available */
+ if (debug_query_string == NULL)
+ return;
+ /* Convert offset to character number */
+ pos = pg_mbstrlen_with_len(debug_query_string, location) + 1;
+ /* And pass it to the ereport mechanism */
+ errposition(pos);
+ }
+ }
+
/*
* evaluate_expr: pre-evaluate a constant expression
*
*************** evaluate_expr(Expr *expr, Oid result_typ
*** 4710,4715 ****
--- 4734,4741 ----
{
EState *estate;
ExprState *exprstate;
+ ExprContext *econtext;
+ ErrorContextCallback errcallback;
MemoryContext oldcontext;
Datum const_val;
bool const_is_null;
*************** evaluate_expr(Expr *expr, Oid result_typ
*** 4733,4738 ****
--- 4759,4772 ----
*/
exprstate = ExecInitExpr(expr, NULL);
+ /* Setup error traceback support for ereport() */
+ econtext = GetPerTupleExprContext(estate);
+ econtext->cur_expr = NULL;
+ errcallback.callback = ExprErrorCallback;
+ errcallback.arg = (void *) econtext;
+ errcallback.previous = error_context_stack;
+ error_context_stack = &errcallback;
+
/*
* And evaluate it.
*
*************** evaluate_expr(Expr *expr, Oid result_typ
*** 4742,4750 ****
* not depend on context, by definition, n'est ce pas?
*/
const_val = ExecEvalExprSwitchContext(exprstate,
! GetPerTupleExprContext(estate),
&const_is_null, NULL);
/* Get info needed about result datatype */
get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
--- 4776,4786 ----
* not depend on context, by definition, n'est ce pas?
*/
const_val = ExecEvalExprSwitchContext(exprstate,
! econtext,
&const_is_null, NULL);
+ error_context_stack = errcallback.previous;
+
/* Get info needed about result datatype */
get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index f6f73f3..a390206 100644
*** a/src/include/nodes/execnodes.h
--- b/src/include/nodes/execnodes.h
*************** typedef struct ExprContext
*** 147,152 ****
--- 147,155 ----
Datum domainValue_datum;
bool domainValue_isNull;
+ /* Currently executing expression node state, or NULL if indeterminate */
+ struct ExprState *cur_expr;
+
/* Link to containing EState (NULL if a standalone ExprContext) */
struct EState *ecxt_estate;
On Sat, Nov 5, 2016 at 11:13 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
The cases that are successfully annotated by the current patch seem to
mostly already have error cursor information, which really is good enough
IMO --- you can certainly figure out which column corresponds to the
textual spot that the cursor is pointing at.
The original intent of that patch tried to cover the case where we insert
records
made of dozens columns sharing the same type definition, and trying to
understand
what is going on, at a glance, when we debugged something like this:
# create table probes (
id int,
pin_1 varchar(2),
pin_2 varchar(2),
...
pin_19 varchar(2),
pin_20 varchar(2));
CREATE TABLE
# insert into probes (
pin_1,
pin_2,
...
pin_19,
pin_20)
values ( <only valid values> );
INSERT 0 1
# insert into probes (
pin_1,
pin_2,
...
pin_19,
pin_20)
values ( <values, some subjects to type casting errors> );
ERROR: value too long for type character varying(2)
Relying on the cursor seems to be of little help I'm afraid.
Thanks for having looked into that, very useful to try understanding all
the mechanisms that are involved to make that happen.
Franck
--
Franck Verrot
Franck Verrot <franck@verrot.fr> writes:
On Sat, Nov 5, 2016 at 11:13 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
The cases that are successfully annotated by the current patch seem to
mostly already have error cursor information, which really is good enough
IMO --- you can certainly figure out which column corresponds to the
textual spot that the cursor is pointing at.
The original intent of that patch tried to cover the case where we insert
records
made of dozens columns sharing the same type definition, and trying to
understand
what is going on, at a glance, when we debugged something like this:
...
Relying on the cursor seems to be of little help I'm afraid.
Well, it would be an improvement over what we've got now. Also, a feature
similar to what I suggested would help in localizing many types of errors
that have nothing to do with coercion to a target column type.
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Sun, Nov 6, 2016 at 1:13 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
The original intent of that patch tried to cover the case where we insert
records
made of dozens columns sharing the same type definition, and trying to
understand
what is going on, at a glance, when we debugged something like this:
...
Relying on the cursor seems to be of little help I'm afraid.Well, it would be an improvement over what we've got now. Also, a feature
similar to what I suggested would help in localizing many types of errors
that have nothing to do with coercion to a target column type.
Yes, it's a neat improvement in any case.
--
Franck Verrot
On Mon, Nov 7, 2016 at 10:26 AM, Franck Verrot <franck@verrot.fr> wrote:
On Sun, Nov 6, 2016 at 1:13 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
The original intent of that patch tried to cover the case where we
insert
records
made of dozens columns sharing the same type definition, and trying to
understand
what is going on, at a glance, when we debugged something like this:
...
Relying on the cursor seems to be of little help I'm afraid.Well, it would be an improvement over what we've got now. Also, a feature
similar to what I suggested would help in localizing many types of errors
that have nothing to do with coercion to a target column type.Yes, it's a neat improvement in any case.
I have marked this patch as "Returned with Feedback" as it got its
share of reviews.
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers