aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/execMain.c66
-rw-r--r--src/test/regress/expected/alter_table.out9
-rw-r--r--src/test/regress/expected/domain.out2
-rw-r--r--src/test/regress/expected/inherit.out6
-rw-r--r--src/test/regress/output/constraints.source20
5 files changed, 102 insertions, 1 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index d19e0978e4e..a6b26f6668a 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -47,6 +47,7 @@
#include "commands/tablespace.h"
#include "commands/trigger.h"
#include "executor/execdebug.h"
+#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "optimizer/clauses.h"
#include "parser/parse_clause.h"
@@ -85,6 +86,8 @@ static void ExecutePlan(EState *estate, PlanState *planstate,
DestReceiver *dest);
static bool ExecCheckRTEPerms(RangeTblEntry *rte);
static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt);
+static char *ExecBuildSlotValueDescription(TupleTableSlot *slot,
+ int maxfieldlen);
static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate,
Plan *planTree);
static void OpenIntoRel(QueryDesc *queryDesc);
@@ -1585,10 +1588,71 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
- RelationGetRelationName(rel), failed)));
+ RelationGetRelationName(rel), failed),
+ errdetail("Failing row contains %s.",
+ ExecBuildSlotValueDescription(slot, 64))));
}
}
+/*
+ * ExecBuildSlotValueDescription -- construct a string representing a tuple
+ *
+ * This is intentionally very similar to BuildIndexValueDescription, but
+ * unlike that function, we truncate long field values. That seems necessary
+ * here since heap field values could be very long, whereas index entries
+ * typically aren't so wide.
+ */
+static char *
+ExecBuildSlotValueDescription(TupleTableSlot *slot, int maxfieldlen)
+{
+ StringInfoData buf;
+ TupleDesc tupdesc = slot->tts_tupleDescriptor;
+ int i;
+
+ /* Make sure the tuple is fully deconstructed */
+ slot_getallattrs(slot);
+
+ initStringInfo(&buf);
+
+ appendStringInfoChar(&buf, '(');
+
+ for (i = 0; i < tupdesc->natts; i++)
+ {
+ char *val;
+ int vallen;
+
+ if (slot->tts_isnull[i])
+ val = "null";
+ else
+ {
+ Oid foutoid;
+ bool typisvarlena;
+
+ getTypeOutputInfo(tupdesc->attrs[i]->atttypid,
+ &foutoid, &typisvarlena);
+ val = OidOutputFunctionCall(foutoid, slot->tts_values[i]);
+ }
+
+ if (i > 0)
+ appendStringInfoString(&buf, ", ");
+
+ /* truncate if needed */
+ vallen = strlen(val);
+ if (vallen <= maxfieldlen)
+ appendStringInfoString(&buf, val);
+ else
+ {
+ vallen = pg_mbcliplen(val, vallen, maxfieldlen);
+ appendBinaryStringInfo(&buf, val, vallen);
+ appendStringInfoString(&buf, "...");
+ }
+ }
+
+ appendStringInfoChar(&buf, ')');
+
+ return buf.data;
+}
+
/*
* ExecFindRowMark -- find the ExecRowMark struct for given rangetable index
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 1aa4f09ed28..065d8fdcb27 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -390,6 +390,7 @@ alter table atacc1 add constraint atacc_test1 check (test>3);
-- should fail
insert into atacc1 (test) values (2);
ERROR: new row for relation "atacc1" violates check constraint "atacc_test1"
+DETAIL: Failing row contains (2).
-- should succeed
insert into atacc1 (test) values (4);
drop table atacc1;
@@ -415,6 +416,7 @@ alter table atacc1 add constraint atacc_test1 check (test+test2<test3*4);
-- should fail
insert into atacc1 (test,test2,test3) values (4,4,2);
ERROR: new row for relation "atacc1" violates check constraint "atacc_test1"
+DETAIL: Failing row contains (4, 4, 2).
-- should succeed
insert into atacc1 (test,test2,test3) values (4,4,5);
drop table atacc1;
@@ -424,6 +426,7 @@ alter table atacc1 add check (test2>test);
-- should fail for $2
insert into atacc1 (test2, test) values (3, 4);
ERROR: new row for relation "atacc1" violates check constraint "atacc1_check"
+DETAIL: Failing row contains (4, 3).
drop table atacc1;
-- inheritance related tests
create table atacc1 (test int);
@@ -433,10 +436,12 @@ alter table atacc2 add constraint foo check (test2>0);
-- fail and then succeed on atacc2
insert into atacc2 (test2) values (-3);
ERROR: new row for relation "atacc2" violates check constraint "foo"
+DETAIL: Failing row contains (-3).
insert into atacc2 (test2) values (3);
-- fail and then succeed on atacc3
insert into atacc3 (test2) values (-3);
ERROR: new row for relation "atacc3" violates check constraint "foo"
+DETAIL: Failing row contains (null, -3, null).
insert into atacc3 (test2) values (3);
drop table atacc3;
drop table atacc2;
@@ -507,6 +512,7 @@ insert into atacc1 (test) values (3);
-- check constraint is there on child
insert into atacc2 (test) values (-3);
ERROR: new row for relation "atacc2" violates check constraint "foo"
+DETAIL: Failing row contains (-3, null).
insert into atacc2 (test) values (3);
drop table atacc2;
drop table atacc1;
@@ -1450,6 +1456,7 @@ NOTICE: merging definition of column "f2" for child "c1"
insert into p1 values (1,2,'abc');
insert into c1 values(11,'xyz',33,0); -- should fail
ERROR: new row for relation "c1" violates check constraint "p1_a1_check"
+DETAIL: Failing row contains (11, xyz, 33, 0).
insert into c1 values(11,'xyz',33,22);
select * from p1;
f1 | a1 | f2
@@ -1537,6 +1544,7 @@ select * from anothertab;
insert into anothertab (atcol1, atcol2) values (45, null); -- fails
ERROR: new row for relation "anothertab" violates check constraint "anothertab_chk"
+DETAIL: Failing row contains (45, null).
insert into anothertab (atcol1, atcol2) values (default, null);
select * from anothertab;
atcol1 | atcol2
@@ -2110,5 +2118,6 @@ ALTER TABLE ONLY test_drop_constr_parent DROP CONSTRAINT "test_drop_constr_paren
-- should fail
INSERT INTO test_drop_constr_child (c) VALUES (NULL);
ERROR: new row for relation "test_drop_constr_child" violates check constraint "test_drop_constr_parent_c_check"
+DETAIL: Failing row contains (null).
DROP TABLE test_drop_constr_parent CASCADE;
NOTICE: drop cascades to table test_drop_constr_child
diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out
index 521fe01fa17..0e09f898a90 100644
--- a/src/test/regress/expected/domain.out
+++ b/src/test/regress/expected/domain.out
@@ -199,6 +199,7 @@ insert into nulltest values ('a', 'b', 'c', 'd', NULL);
ERROR: domain dcheck does not allow null values
insert into nulltest values ('a', 'b', 'c', 'd', 'a');
ERROR: new row for relation "nulltest" violates check constraint "nulltest_col5_check"
+DETAIL: Failing row contains (a, b, c, d, a).
INSERT INTO nulltest values (NULL, 'b', 'c', 'd', 'd');
ERROR: domain dnotnull does not allow null values
INSERT INTO nulltest values ('a', NULL, 'c', 'd', 'c');
@@ -216,6 +217,7 @@ CONTEXT: COPY nulltest, line 1, column col5: null input
-- Last row is bad
COPY nulltest FROM stdin;
ERROR: new row for relation "nulltest" violates check constraint "nulltest_col5_check"
+DETAIL: Failing row contains (a, b, c, null, a).
CONTEXT: COPY nulltest, line 3: "a b c \N a"
select * from nulltest;
col1 | col2 | col3 | col4 | col5
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index 72986c78a23..e6365752050 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -640,6 +640,7 @@ INSERT INTO inhg VALUES ('x', 'text', 'y'); /* Succeeds */
INSERT INTO inhg VALUES ('x', 'text', 'y'); /* Succeeds -- Unique constraints not copied */
INSERT INTO inhg VALUES ('x', 'foo', 'y'); /* fails due to constraint */
ERROR: new row for relation "inhg" violates check constraint "foo"
+DETAIL: Failing row contains (x, foo, y).
SELECT * FROM inhg; /* Two records with three columns in order x=x, xx=text, y=y */
x | xx | y
---+------+---
@@ -721,8 +722,10 @@ select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pg
insert into ac (aa) values (NULL);
ERROR: new row for relation "ac" violates check constraint "ac_check"
+DETAIL: Failing row contains (null).
insert into bc (aa) values (NULL);
ERROR: new row for relation "bc" violates check constraint "ac_check"
+DETAIL: Failing row contains (null, null).
alter table bc drop constraint ac_check; -- fail, disallowed
ERROR: cannot drop inherited constraint "ac_check" of relation "bc"
alter table ac drop constraint ac_check;
@@ -742,8 +745,10 @@ select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pg
insert into ac (aa) values (NULL);
ERROR: new row for relation "ac" violates check constraint "ac_aa_check"
+DETAIL: Failing row contains (null).
insert into bc (aa) values (NULL);
ERROR: new row for relation "bc" violates check constraint "ac_aa_check"
+DETAIL: Failing row contains (null, null).
alter table bc drop constraint ac_aa_check; -- fail, disallowed
ERROR: cannot drop inherited constraint "ac_aa_check" of relation "bc"
alter table ac drop constraint ac_aa_check;
@@ -830,6 +835,7 @@ insert into c1 values(1,1,2);
alter table p2 add check (f2>0);
insert into c1 values(1,-1,2); -- fail
ERROR: new row for relation "c1" violates check constraint "p2_f2_check"
+DETAIL: Failing row contains (1, -1, 2).
create table c2(f3 int) inherits(p1,p2);
\d c2
Table "public.c2"
diff --git a/src/test/regress/output/constraints.source b/src/test/regress/output/constraints.source
index e2f29399315..9a813535f7a 100644
--- a/src/test/regress/output/constraints.source
+++ b/src/test/regress/output/constraints.source
@@ -68,11 +68,14 @@ INSERT INTO CHECK_TBL VALUES (5);
INSERT INTO CHECK_TBL VALUES (4);
INSERT INTO CHECK_TBL VALUES (3);
ERROR: new row for relation "check_tbl" violates check constraint "check_con"
+DETAIL: Failing row contains (3).
INSERT INTO CHECK_TBL VALUES (2);
ERROR: new row for relation "check_tbl" violates check constraint "check_con"
+DETAIL: Failing row contains (2).
INSERT INTO CHECK_TBL VALUES (6);
INSERT INTO CHECK_TBL VALUES (1);
ERROR: new row for relation "check_tbl" violates check constraint "check_con"
+DETAIL: Failing row contains (1).
SELECT '' AS three, * FROM CHECK_TBL;
three | x
-------+---
@@ -88,12 +91,16 @@ CREATE TABLE CHECK2_TBL (x int, y text, z int,
INSERT INTO CHECK2_TBL VALUES (4, 'check ok', -2);
INSERT INTO CHECK2_TBL VALUES (1, 'x check failed', -2);
ERROR: new row for relation "check2_tbl" violates check constraint "sequence_con"
+DETAIL: Failing row contains (1, x check failed, -2).
INSERT INTO CHECK2_TBL VALUES (5, 'z check failed', 10);
ERROR: new row for relation "check2_tbl" violates check constraint "sequence_con"
+DETAIL: Failing row contains (5, z check failed, 10).
INSERT INTO CHECK2_TBL VALUES (0, 'check failed', -2);
ERROR: new row for relation "check2_tbl" violates check constraint "sequence_con"
+DETAIL: Failing row contains (0, check failed, -2).
INSERT INTO CHECK2_TBL VALUES (6, 'check failed', 11);
ERROR: new row for relation "check2_tbl" violates check constraint "sequence_con"
+DETAIL: Failing row contains (6, check failed, 11).
INSERT INTO CHECK2_TBL VALUES (7, 'check ok', 7);
SELECT '' AS two, * from CHECK2_TBL;
two | x | y | z
@@ -113,6 +120,7 @@ CREATE TABLE INSERT_TBL (x INT DEFAULT nextval('insert_seq'),
CHECK (x + z = 0));
INSERT INTO INSERT_TBL(x,z) VALUES (2, -2);
ERROR: new row for relation "insert_tbl" violates check constraint "insert_con"
+DETAIL: Failing row contains (2, -NULL-, -2).
SELECT '' AS zero, * FROM INSERT_TBL;
zero | x | y | z
------+---+---+---
@@ -126,12 +134,15 @@ SELECT 'one' AS one, nextval('insert_seq');
INSERT INTO INSERT_TBL(y) VALUES ('Y');
ERROR: new row for relation "insert_tbl" violates check constraint "insert_con"
+DETAIL: Failing row contains (2, Y, -2).
INSERT INTO INSERT_TBL(y) VALUES ('Y');
INSERT INTO INSERT_TBL(x,z) VALUES (1, -2);
ERROR: new row for relation "insert_tbl" violates check constraint "insert_tbl_check"
+DETAIL: Failing row contains (1, -NULL-, -2).
INSERT INTO INSERT_TBL(z,x) VALUES (-7, 7);
INSERT INTO INSERT_TBL VALUES (5, 'check failed', -5);
ERROR: new row for relation "insert_tbl" violates check constraint "insert_con"
+DETAIL: Failing row contains (5, check failed, -5).
INSERT INTO INSERT_TBL VALUES (7, '!check failed', -7);
INSERT INTO INSERT_TBL(y) VALUES ('-!NULL-');
SELECT '' AS four, * FROM INSERT_TBL;
@@ -145,8 +156,10 @@ SELECT '' AS four, * FROM INSERT_TBL;
INSERT INTO INSERT_TBL(y,z) VALUES ('check failed', 4);
ERROR: new row for relation "insert_tbl" violates check constraint "insert_tbl_check"
+DETAIL: Failing row contains (5, check failed, 4).
INSERT INTO INSERT_TBL(x,y) VALUES (5, 'check failed');
ERROR: new row for relation "insert_tbl" violates check constraint "insert_con"
+DETAIL: Failing row contains (5, check failed, -5).
INSERT INTO INSERT_TBL(x,y) VALUES (5, '!check failed');
INSERT INTO INSERT_TBL(y) VALUES ('-!NULL-');
SELECT '' AS six, * FROM INSERT_TBL;
@@ -168,6 +181,7 @@ SELECT 'seven' AS one, nextval('insert_seq');
INSERT INTO INSERT_TBL(y) VALUES ('Y');
ERROR: new row for relation "insert_tbl" violates check constraint "insert_con"
+DETAIL: Failing row contains (8, Y, -8).
SELECT 'eight' AS one, currval('insert_seq');
one | currval
-------+---------
@@ -199,10 +213,13 @@ CREATE TABLE INSERT_CHILD (cx INT default 42,
INSERT INTO INSERT_CHILD(x,z,cy) VALUES (7,-7,11);
INSERT INTO INSERT_CHILD(x,z,cy) VALUES (7,-7,6);
ERROR: new row for relation "insert_child" violates check constraint "insert_child_check"
+DETAIL: Failing row contains (7, -NULL-, -7, 42, 6).
INSERT INTO INSERT_CHILD(x,z,cy) VALUES (6,-7,7);
ERROR: new row for relation "insert_child" violates check constraint "insert_tbl_check"
+DETAIL: Failing row contains (6, -NULL-, -7, 42, 7).
INSERT INTO INSERT_CHILD(x,y,z,cy) VALUES (6,'check failed',-6,7);
ERROR: new row for relation "insert_child" violates check constraint "insert_con"
+DETAIL: Failing row contains (6, check failed, -6, 42, 7).
SELECT * FROM INSERT_CHILD;
x | y | z | cx | cy
---+--------+----+----+----
@@ -232,6 +249,7 @@ INSERT INTO INSERT_TBL SELECT * FROM tmp WHERE yd = 'try again';
INSERT INTO INSERT_TBL(y,z) SELECT yd, -7 FROM tmp WHERE yd = 'try again';
INSERT INTO INSERT_TBL(y,z) SELECT yd, -8 FROM tmp WHERE yd = 'try again';
ERROR: new row for relation "insert_tbl" violates check constraint "insert_con"
+DETAIL: Failing row contains (8, try again, -8).
SELECT '' AS four, * FROM INSERT_TBL;
four | x | y | z
------+---+---------------+----
@@ -251,6 +269,7 @@ UPDATE INSERT_TBL SET x = 6 WHERE x = 6;
UPDATE INSERT_TBL SET x = -z, z = -x;
UPDATE INSERT_TBL SET x = z, z = x;
ERROR: new row for relation "insert_tbl" violates check constraint "insert_con"
+DETAIL: Failing row contains (-4, Y, 4).
SELECT * FROM INSERT_TBL;
x | y | z
---+---------------+----
@@ -278,6 +297,7 @@ SELECT '' AS two, * FROM COPY_TBL;
COPY COPY_TBL FROM '@abs_srcdir@/data/constrf.data';
ERROR: new row for relation "copy_tbl" violates check constraint "copy_con"
+DETAIL: Failing row contains (7, check failed, 6).
CONTEXT: COPY copy_tbl, line 2: "7 check failed 6"
SELECT * FROM COPY_TBL;
x | y | z