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

Commitc28b289

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 parent5e900bc commitc28b289

File tree

3 files changed

+57
-13
lines changed

3 files changed

+57
-13
lines changed

‎src/backend/executor/execMain.c

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ static void ExecutePlan(EState *estate, PlanState *planstate,
8383
staticboolExecCheckRTEPerms(RangeTblEntry*rte);
8484
staticvoidExecCheckXactReadOnly(PlannedStmt*plannedstmt);
8585
staticchar*ExecBuildSlotValueDescription(TupleTableSlot*slot,
86+
TupleDesctupdesc,
8687
intmaxfieldlen);
8788
staticvoidEvalPlanQualStart(EPQState*epqstate,EState*parentestate,
8889
Plan*planTree);
@@ -1586,25 +1587,28 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
15861587
TupleTableSlot*slot,EState*estate)
15871588
{
15881589
Relationrel=resultRelInfo->ri_RelationDesc;
1589-
TupleConstr*constr=rel->rd_att->constr;
1590+
TupleDesctupdesc=RelationGetDescr(rel);
1591+
TupleConstr*constr=tupdesc->constr;
15901592

15911593
Assert(constr);
15921594

15931595
if (constr->has_not_null)
15941596
{
1595-
intnatts=rel->rd_att->natts;
1597+
intnatts=tupdesc->natts;
15961598
intattrChk;
15971599

15981600
for (attrChk=1;attrChk <=natts;attrChk++)
15991601
{
1600-
if (rel->rd_att->attrs[attrChk-1]->attnotnull&&
1602+
if (tupdesc->attrs[attrChk-1]->attnotnull&&
16011603
slot_attisnull(slot,attrChk))
16021604
ereport(ERROR,
16031605
(errcode(ERRCODE_NOT_NULL_VIOLATION),
16041606
errmsg("null value in column \"%s\" violates not-null constraint",
1605-
NameStr(rel->rd_att->attrs[attrChk-1]->attname)),
1607+
NameStr(tupdesc->attrs[attrChk-1]->attname)),
16061608
errdetail("Failing row contains %s.",
1607-
ExecBuildSlotValueDescription(slot,64)),
1609+
ExecBuildSlotValueDescription(slot,
1610+
tupdesc,
1611+
64)),
16081612
errtablecol(rel,attrChk)));
16091613
}
16101614
}
@@ -1619,7 +1623,9 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
16191623
errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
16201624
RelationGetRelationName(rel),failed),
16211625
errdetail("Failing row contains %s.",
1622-
ExecBuildSlotValueDescription(slot,64)),
1626+
ExecBuildSlotValueDescription(slot,
1627+
tupdesc,
1628+
64)),
16231629
errtableconstraint(rel,failed)));
16241630
}
16251631
}
@@ -1663,23 +1669,32 @@ ExecWithCheckOptions(ResultRelInfo *resultRelInfo,
16631669
errmsg("new row violates WITH CHECK OPTION for view \"%s\"",
16641670
wco->viewname),
16651671
errdetail("Failing row contains %s.",
1666-
ExecBuildSlotValueDescription(slot,64))));
1672+
ExecBuildSlotValueDescription(slot,
1673+
RelationGetDescr(resultRelInfo->ri_RelationDesc),
1674+
64))));
16671675
}
16681676
}
16691677

16701678
/*
16711679
* ExecBuildSlotValueDescription -- construct a string representing a tuple
16721680
*
16731681
* This is intentionally very similar to BuildIndexValueDescription, but
1674-
* unlike that function, we truncate long field values. That seems necessary
1675-
* here since heap field values could be very long, whereas index entries
1676-
* typically aren't so wide.
1682+
* unlike that function, we truncate long field values (to at most maxfieldlen
1683+
* bytes).That seems necessary here since heap field values could be very
1684+
* long, whereas index entries typically aren't so wide.
1685+
*
1686+
* Also, unlike the case with index entries, we need to be prepared to ignore
1687+
* dropped columns. We used to use the slot's tuple descriptor to decode the
1688+
* data, but the slot's descriptor doesn't identify dropped columns, so we
1689+
* now need to be passed the relation's descriptor.
16771690
*/
16781691
staticchar*
1679-
ExecBuildSlotValueDescription(TupleTableSlot*slot,intmaxfieldlen)
1692+
ExecBuildSlotValueDescription(TupleTableSlot*slot,
1693+
TupleDesctupdesc,
1694+
intmaxfieldlen)
16801695
{
16811696
StringInfoDatabuf;
1682-
TupleDesctupdesc=slot->tts_tupleDescriptor;
1697+
boolwrite_comma=false;
16831698
inti;
16841699

16851700
/* Make sure the tuple is fully deconstructed */
@@ -1694,6 +1709,10 @@ ExecBuildSlotValueDescription(TupleTableSlot *slot, int maxfieldlen)
16941709
char*val;
16951710
intvallen;
16961711

1712+
/* ignore dropped columns */
1713+
if (tupdesc->attrs[i]->attisdropped)
1714+
continue;
1715+
16971716
if (slot->tts_isnull[i])
16981717
val="null";
16991718
else
@@ -1706,8 +1725,10 @@ ExecBuildSlotValueDescription(TupleTableSlot *slot, int maxfieldlen)
17061725
val=OidOutputFunctionCall(foutoid,slot->tts_values[i]);
17071726
}
17081727

1709-
if (i>0)
1728+
if (write_comma)
17101729
appendStringInfoString(&buf,", ");
1730+
else
1731+
write_comma= true;
17111732

17121733
/* truncate if needed */
17131734
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