Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdf5d5f1

Browse files
committed
Prevent display of dropped columns in row constraint violation messages.
ExecBuildSlotValueDescription() printed "null" for each dropped column ina row being complained of by ExecConstraints(). This has some sanity interms of the underlying implementation, but is of course pretty surprisingto users. To fix, we must pass the target relation's descriptor toExecBuildSlotValueDescription(), because the slot descriptor it had beenusing doesn't get labeled with attisdropped markers.Per bug #8408 from Maxim Boguk. Back-patch to 9.2 where the feature ofprinting row values in NOT NULL and CHECK constraint violation messageswas introduced.Michael Paquier and Tom Lane
1 parent5d0731d commitdf5d5f1

File tree

3 files changed

+54
-12
lines changed

3 files changed

+54
-12
lines changed

‎src/backend/executor/execMain.c

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ static void ExecutePlan(EState *estate, PlanState *planstate,
8282
staticboolExecCheckRTEPerms(RangeTblEntry*rte);
8383
staticvoidExecCheckXactReadOnly(PlannedStmt*plannedstmt);
8484
staticchar*ExecBuildSlotValueDescription(TupleTableSlot*slot,
85+
TupleDesctupdesc,
8586
intmaxfieldlen);
8687
staticvoidEvalPlanQualStart(EPQState*epqstate,EState*parentestate,
8788
Plan*planTree);
@@ -1584,25 +1585,28 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
15841585
TupleTableSlot*slot,EState*estate)
15851586
{
15861587
Relationrel=resultRelInfo->ri_RelationDesc;
1587-
TupleConstr*constr=rel->rd_att->constr;
1588+
TupleDesctupdesc=RelationGetDescr(rel);
1589+
TupleConstr*constr=tupdesc->constr;
15881590

15891591
Assert(constr);
15901592

15911593
if (constr->has_not_null)
15921594
{
1593-
intnatts=rel->rd_att->natts;
1595+
intnatts=tupdesc->natts;
15941596
intattrChk;
15951597

15961598
for (attrChk=1;attrChk <=natts;attrChk++)
15971599
{
1598-
if (rel->rd_att->attrs[attrChk-1]->attnotnull&&
1600+
if (tupdesc->attrs[attrChk-1]->attnotnull&&
15991601
slot_attisnull(slot,attrChk))
16001602
ereport(ERROR,
16011603
(errcode(ERRCODE_NOT_NULL_VIOLATION),
16021604
errmsg("null value in column \"%s\" violates not-null constraint",
1603-
NameStr(rel->rd_att->attrs[attrChk-1]->attname)),
1605+
NameStr(tupdesc->attrs[attrChk-1]->attname)),
16041606
errdetail("Failing row contains %s.",
1605-
ExecBuildSlotValueDescription(slot,64)),
1607+
ExecBuildSlotValueDescription(slot,
1608+
tupdesc,
1609+
64)),
16061610
errtablecol(rel,attrChk)));
16071611
}
16081612
}
@@ -1617,7 +1621,9 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
16171621
errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
16181622
RelationGetRelationName(rel),failed),
16191623
errdetail("Failing row contains %s.",
1620-
ExecBuildSlotValueDescription(slot,64)),
1624+
ExecBuildSlotValueDescription(slot,
1625+
tupdesc,
1626+
64)),
16211627
errtableconstraint(rel,failed)));
16221628
}
16231629
}
@@ -1626,15 +1632,22 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
16261632
* ExecBuildSlotValueDescription -- construct a string representing a tuple
16271633
*
16281634
* This is intentionally very similar to BuildIndexValueDescription, but
1629-
* unlike that function, we truncate long field values. That seems necessary
1630-
* here since heap field values could be very long, whereas index entries
1631-
* typically aren't so wide.
1635+
* unlike that function, we truncate long field values (to at most maxfieldlen
1636+
* bytes).That seems necessary here since heap field values could be very
1637+
* long, whereas index entries typically aren't so wide.
1638+
*
1639+
* Also, unlike the case with index entries, we need to be prepared to ignore
1640+
* dropped columns. We used to use the slot's tuple descriptor to decode the
1641+
* data, but the slot's descriptor doesn't identify dropped columns, so we
1642+
* now need to be passed the relation's descriptor.
16321643
*/
16331644
staticchar*
1634-
ExecBuildSlotValueDescription(TupleTableSlot*slot,intmaxfieldlen)
1645+
ExecBuildSlotValueDescription(TupleTableSlot*slot,
1646+
TupleDesctupdesc,
1647+
intmaxfieldlen)
16351648
{
16361649
StringInfoDatabuf;
1637-
TupleDesctupdesc=slot->tts_tupleDescriptor;
1650+
boolwrite_comma=false;
16381651
inti;
16391652

16401653
/* Make sure the tuple is fully deconstructed */
@@ -1649,6 +1662,10 @@ ExecBuildSlotValueDescription(TupleTableSlot *slot, int maxfieldlen)
16491662
char*val;
16501663
intvallen;
16511664

1665+
/* ignore dropped columns */
1666+
if (tupdesc->attrs[i]->attisdropped)
1667+
continue;
1668+
16521669
if (slot->tts_isnull[i])
16531670
val="null";
16541671
else
@@ -1661,8 +1678,10 @@ ExecBuildSlotValueDescription(TupleTableSlot *slot, int maxfieldlen)
16611678
val=OidOutputFunctionCall(foutoid,slot->tts_values[i]);
16621679
}
16631680

1664-
if (i>0)
1681+
if (write_comma)
16651682
appendStringInfoString(&buf,", ");
1683+
else
1684+
write_comma= true;
16661685

16671686
/* truncate if needed */
16681687
vallen=strlen(val);

‎src/test/regress/expected/alter_table.out

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,20 @@ select * from atacc1;
11961196
--
11971197
(1 row)
11981198

1199+
drop table atacc1;
1200+
-- test constraint error reporting in presence of dropped columns
1201+
create table atacc1 (id serial primary key, value int check (value < 10));
1202+
insert into atacc1(value) values (100);
1203+
ERROR: new row for relation "atacc1" violates check constraint "atacc1_value_check"
1204+
DETAIL: Failing row contains (1, 100).
1205+
alter table atacc1 drop column value;
1206+
alter table atacc1 add column value int check (value < 10);
1207+
insert into atacc1(value) values (100);
1208+
ERROR: new row for relation "atacc1" violates check constraint "atacc1_value_check"
1209+
DETAIL: Failing row contains (2, 100).
1210+
insert into atacc1(id, value) values (null, 0);
1211+
ERROR: null value in column "id" violates not-null constraint
1212+
DETAIL: Failing row contains (null, 0).
11991213
drop table atacc1;
12001214
-- test inheritance
12011215
create table parent (a int, b int, c int);

‎src/test/regress/sql/alter_table.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,15 @@ select * from atacc1;
874874

875875
droptable atacc1;
876876

877+
-- test constraint error reporting in presence of dropped columns
878+
createtableatacc1 (idserialprimary key, valueintcheck (value<10));
879+
insert into atacc1(value)values (100);
880+
altertable atacc1 drop column value;
881+
altertable atacc1 add column valueintcheck (value<10);
882+
insert into atacc1(value)values (100);
883+
insert into atacc1(id, value)values (null,0);
884+
droptable atacc1;
885+
877886
-- test inheritance
878887
createtableparent (aint, bint, cint);
879888
insert into parentvalues (1,2,3);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp