#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"
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);
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
-- 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;
-- 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;
-- 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);
-- 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;
-- 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;
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
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
-- 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
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');
-- 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
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
---+------+---
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;
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;
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"
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
-------+---
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
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
------+---+---+---
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;
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;
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
-------+---------
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
---+--------+----+----+----
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
------+---+---------------+----
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
---+---------------+----
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