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

Commit8bd5a6a

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 parentaa8a2c3 commit8bd5a6a

File tree

3 files changed

+56
-12
lines changed

3 files changed

+56
-12
lines changed

‎src/backend/executor/execMain.c

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ static void ExecutePlan(EState *estate, PlanState *planstate,
8080
staticboolExecCheckRTEPerms(RangeTblEntry*rte);
8181
staticvoidExecCheckXactReadOnly(PlannedStmt*plannedstmt);
8282
staticchar*ExecBuildSlotValueDescription(TupleTableSlot*slot,
83+
TupleDesctupdesc,
8384
intmaxfieldlen);
8485
staticvoidEvalPlanQualStart(EPQState*epqstate,EState*parentestate,
8586
Plan*planTree);
@@ -1506,25 +1507,28 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
15061507
TupleTableSlot*slot,EState*estate)
15071508
{
15081509
Relationrel=resultRelInfo->ri_RelationDesc;
1509-
TupleConstr*constr=rel->rd_att->constr;
1510+
TupleDesctupdesc=RelationGetDescr(rel);
1511+
TupleConstr*constr=tupdesc->constr;
15101512

15111513
Assert(constr);
15121514

15131515
if (constr->has_not_null)
15141516
{
1515-
intnatts=rel->rd_att->natts;
1517+
intnatts=tupdesc->natts;
15161518
intattrChk;
15171519

15181520
for (attrChk=1;attrChk <=natts;attrChk++)
15191521
{
1520-
if (rel->rd_att->attrs[attrChk-1]->attnotnull&&
1522+
if (tupdesc->attrs[attrChk-1]->attnotnull&&
15211523
slot_attisnull(slot,attrChk))
15221524
ereport(ERROR,
15231525
(errcode(ERRCODE_NOT_NULL_VIOLATION),
15241526
errmsg("null value in column \"%s\" violates not-null constraint",
1525-
NameStr(rel->rd_att->attrs[attrChk-1]->attname)),
1527+
NameStr(tupdesc->attrs[attrChk-1]->attname)),
15261528
errdetail("Failing row contains %s.",
1527-
ExecBuildSlotValueDescription(slot,64))));
1529+
ExecBuildSlotValueDescription(slot,
1530+
tupdesc,
1531+
64))));
15281532
}
15291533
}
15301534

@@ -1538,23 +1542,32 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
15381542
errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
15391543
RelationGetRelationName(rel),failed),
15401544
errdetail("Failing row contains %s.",
1541-
ExecBuildSlotValueDescription(slot,64))));
1545+
ExecBuildSlotValueDescription(slot,
1546+
tupdesc,
1547+
64))));
15421548
}
15431549
}
15441550

15451551
/*
15461552
* ExecBuildSlotValueDescription -- construct a string representing a tuple
15471553
*
15481554
* This is intentionally very similar to BuildIndexValueDescription, but
1549-
* unlike that function, we truncate long field values. That seems necessary
1550-
* here since heap field values could be very long, whereas index entries
1551-
* typically aren't so wide.
1555+
* unlike that function, we truncate long field values (to at most maxfieldlen
1556+
* bytes).That seems necessary here since heap field values could be very
1557+
* long, whereas index entries typically aren't so wide.
1558+
*
1559+
* Also, unlike the case with index entries, we need to be prepared to ignore
1560+
* dropped columns. We used to use the slot's tuple descriptor to decode the
1561+
* data, but the slot's descriptor doesn't identify dropped columns, so we
1562+
* now need to be passed the relation's descriptor.
15521563
*/
15531564
staticchar*
1554-
ExecBuildSlotValueDescription(TupleTableSlot*slot,intmaxfieldlen)
1565+
ExecBuildSlotValueDescription(TupleTableSlot*slot,
1566+
TupleDesctupdesc,
1567+
intmaxfieldlen)
15551568
{
15561569
StringInfoDatabuf;
1557-
TupleDesctupdesc=slot->tts_tupleDescriptor;
1570+
boolwrite_comma=false;
15581571
inti;
15591572

15601573
/* Make sure the tuple is fully deconstructed */
@@ -1569,6 +1582,10 @@ ExecBuildSlotValueDescription(TupleTableSlot *slot, int maxfieldlen)
15691582
char*val;
15701583
intvallen;
15711584

1585+
/* ignore dropped columns */
1586+
if (tupdesc->attrs[i]->attisdropped)
1587+
continue;
1588+
15721589
if (slot->tts_isnull[i])
15731590
val="null";
15741591
else
@@ -1581,8 +1598,10 @@ ExecBuildSlotValueDescription(TupleTableSlot *slot, int maxfieldlen)
15811598
val=OidOutputFunctionCall(foutoid,slot->tts_values[i]);
15821599
}
15831600

1584-
if (i>0)
1601+
if (write_comma)
15851602
appendStringInfoString(&buf,", ");
1603+
else
1604+
write_comma= true;
15861605

15871606
/* truncate if needed */
15881607
vallen=strlen(val);

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,22 @@ select * from atacc1;
12231223
--
12241224
(1 row)
12251225

1226+
drop table atacc1;
1227+
-- test constraint error reporting in presence of dropped columns
1228+
create table atacc1 (id serial primary key, value int check (value < 10));
1229+
NOTICE: CREATE TABLE will create implicit sequence "atacc1_id_seq" for serial column "atacc1.id"
1230+
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "atacc1_pkey" for table "atacc1"
1231+
insert into atacc1(value) values (100);
1232+
ERROR: new row for relation "atacc1" violates check constraint "atacc1_value_check"
1233+
DETAIL: Failing row contains (1, 100).
1234+
alter table atacc1 drop column value;
1235+
alter table atacc1 add column value int check (value < 10);
1236+
insert into atacc1(value) values (100);
1237+
ERROR: new row for relation "atacc1" violates check constraint "atacc1_value_check"
1238+
DETAIL: Failing row contains (2, 100).
1239+
insert into atacc1(id, value) values (null, 0);
1240+
ERROR: null value in column "id" violates not-null constraint
1241+
DETAIL: Failing row contains (null, 0).
12261242
drop table atacc1;
12271243
-- test inheritance
12281244
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