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

Commitcb33de7

Browse files
committed
Fix ALTER TABLE to check pre-existing NOT NULL constraints when rewriting
a table. Otherwise a USING clause that yields NULL can leave the tableviolating its constraint (possibly there are other cases too). Per reportfrom Alexander Pravking.
1 parentc5133e5 commitcb33de7

File tree

1 file changed

+38
-31
lines changed

1 file changed

+38
-31
lines changed

‎src/backend/commands/tablecmds.c

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.192 2006/07/03 22:45:38 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.193 2006/07/10 22:10:39 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -123,6 +123,7 @@ typedef struct AlteredTableInfo
123123
/* Information saved by Phases 1/2 for Phase 3: */
124124
List*constraints;/* List of NewConstraint */
125125
List*newvals;/* List of NewColumnValue */
126+
boolnew_notnull;/* T if we added new NOT NULL constraints */
126127
OidnewTableSpace;/* new tablespace; 0 means no change */
127128
/* Objects to rebuild after completing ALTER TYPE operations */
128129
List*changedConstraintOids;/* OIDs of constraints to rebuild */
@@ -132,11 +133,11 @@ typedef struct AlteredTableInfo
132133
}AlteredTableInfo;
133134

134135
/* Struct describing one new constraint to check in Phase 3 scan */
136+
/* Note: new NOT NULL constraints are handled elsewhere */
135137
typedefstructNewConstraint
136138
{
137139
char*name;/* Constraint name, or NULL if none */
138-
ConstrTypecontype;/* CHECK, NOT_NULL, or FOREIGN */
139-
AttrNumberattnum;/* only relevant for NOT_NULL */
140+
ConstrTypecontype;/* CHECK or FOREIGN */
140141
Oidrefrelid;/* PK rel, if FOREIGN */
141142
Node*qual;/* Check expr or FkConstraint struct */
142143
List*qualstate;/* Execution state for CHECK */
@@ -2438,7 +2439,7 @@ ATRewriteTables(List **wqueue)
24382439
* Test the current data within the table against new constraints
24392440
* generated by ALTER TABLE commands, but don't rebuild data.
24402441
*/
2441-
if (tab->constraints!=NIL)
2442+
if (tab->constraints!=NIL||tab->new_notnull)
24422443
ATRewriteTable(tab,InvalidOid);
24432444

24442445
/*
@@ -2504,6 +2505,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
25042505
TupleDescoldTupDesc;
25052506
TupleDescnewTupDesc;
25062507
boolneedscan= false;
2508+
List*notnull_attrs;
25072509
inti;
25082510
ListCell*l;
25092511
EState*estate;
@@ -2554,9 +2556,6 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
25542556
caseCONSTR_FOREIGN:
25552557
/* Nothing to do here */
25562558
break;
2557-
caseCONSTR_NOTNULL:
2558-
needscan= true;
2559-
break;
25602559
default:
25612560
elog(ERROR,"unrecognized constraint type: %d",
25622561
(int)con->contype);
@@ -2572,6 +2571,25 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
25722571
ex->exprstate=ExecPrepareExpr((Expr*)ex->expr,estate);
25732572
}
25742573

2574+
notnull_attrs=NIL;
2575+
if (newrel||tab->new_notnull)
2576+
{
2577+
/*
2578+
* If we are rebuilding the tuples OR if we added any new NOT NULL
2579+
* constraints, check all not-null constraints. This is a bit of
2580+
* overkill but it minimizes risk of bugs, and heap_attisnull is
2581+
* a pretty cheap test anyway.
2582+
*/
2583+
for (i=0;i<newTupDesc->natts;i++)
2584+
{
2585+
if (newTupDesc->attrs[i]->attnotnull&&
2586+
!newTupDesc->attrs[i]->attisdropped)
2587+
notnull_attrs=lappend_int(notnull_attrs,i);
2588+
}
2589+
if (notnull_attrs)
2590+
needscan= true;
2591+
}
2592+
25752593
if (needscan)
25762594
{
25772595
ExprContext*econtext;
@@ -2672,6 +2690,17 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
26722690
ExecStoreTuple(tuple,newslot,InvalidBuffer, false);
26732691
econtext->ecxt_scantuple=newslot;
26742692

2693+
foreach(l,notnull_attrs)
2694+
{
2695+
intattn=lfirst_int(l);
2696+
2697+
if (heap_attisnull(tuple,attn+1))
2698+
ereport(ERROR,
2699+
(errcode(ERRCODE_NOT_NULL_VIOLATION),
2700+
errmsg("column \"%s\" contains null values",
2701+
NameStr(newTupDesc->attrs[attn]->attname))));
2702+
}
2703+
26752704
foreach(l,tab->constraints)
26762705
{
26772706
NewConstraint*con=lfirst(l);
@@ -2685,21 +2714,6 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
26852714
errmsg("check constraint \"%s\" is violated by some row",
26862715
con->name)));
26872716
break;
2688-
caseCONSTR_NOTNULL:
2689-
{
2690-
Datumd;
2691-
boolisnull;
2692-
2693-
d=heap_getattr(tuple,con->attnum,newTupDesc,
2694-
&isnull);
2695-
if (isnull)
2696-
ereport(ERROR,
2697-
(errcode(ERRCODE_NOT_NULL_VIOLATION),
2698-
errmsg("column \"%s\" contains null values",
2699-
get_attname(tab->relid,
2700-
con->attnum))));
2701-
}
2702-
break;
27032717
caseCONSTR_FOREIGN:
27042718
/* Nothing to do here */
27052719
break;
@@ -3398,7 +3412,6 @@ ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
33983412
HeapTupletuple;
33993413
AttrNumberattnum;
34003414
Relationattr_rel;
3401-
NewConstraint*newcon;
34023415

34033416
/*
34043417
* lookup the attribute
@@ -3434,13 +3447,8 @@ ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
34343447
/* keep the system catalog indexes current */
34353448
CatalogUpdateIndexes(attr_rel,tuple);
34363449

3437-
/* Tell Phase 3 to test the constraint */
3438-
newcon= (NewConstraint*)palloc0(sizeof(NewConstraint));
3439-
newcon->contype=CONSTR_NOTNULL;
3440-
newcon->attnum=attnum;
3441-
newcon->name="NOT NULL";
3442-
3443-
tab->constraints=lappend(tab->constraints,newcon);
3450+
/* Tell Phase 3 it needs to test the constraint */
3451+
tab->new_notnull= true;
34443452
}
34453453

34463454
heap_close(attr_rel,RowExclusiveLock);
@@ -3909,7 +3917,6 @@ ATExecAddConstraint(AlteredTableInfo *tab, Relation rel, Node *newConstraint)
39093917
newcon= (NewConstraint*)palloc0(sizeof(NewConstraint));
39103918
newcon->name=ccon->name;
39113919
newcon->contype=ccon->contype;
3912-
newcon->attnum=ccon->attnum;
39133920
/* ExecQual wants implicit-AND format */
39143921
newcon->qual= (Node*)
39153922
make_ands_implicit((Expr*)ccon->expr);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp