@ -6579,14 +6579,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
rawEnt = ( RawColumnDefault * ) palloc ( sizeof ( RawColumnDefault ) ) ;
rawEnt = ( RawColumnDefault * ) palloc ( sizeof ( RawColumnDefault ) ) ;
rawEnt - > attnum = attribute . attnum ;
rawEnt - > attnum = attribute . attnum ;
rawEnt - > raw_default = copyObject ( colDef - > raw_default ) ;
rawEnt - > raw_default = copyObject ( colDef - > raw_default ) ;
rawEnt - > missingMode = false ; /* XXX vestigial */
/*
* Attempt to skip a complete table rewrite by storing the specified
* DEFAULT value outside of the heap . This may be disabled inside
* AddRelationNewConstraints if the optimization cannot be applied .
*/
rawEnt - > missingMode = ( ! colDef - > generated ) ;
rawEnt - > generated = colDef - > generated ;
rawEnt - > generated = colDef - > generated ;
/*
/*
@ -6598,13 +6591,6 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
/* Make the additional catalog changes visible */
/* Make the additional catalog changes visible */
CommandCounterIncrement ( ) ;
CommandCounterIncrement ( ) ;
/*
* Did the request for a missing value work ? If not we ' ll have to do a
* rewrite
*/
if ( ! rawEnt - > missingMode )
tab - > rewrite | = AT_REWRITE_DEFAULT_VAL ;
}
}
/*
/*
@ -6621,9 +6607,9 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
* rejects nulls . If there are any domain constraints then we construct
* rejects nulls . If there are any domain constraints then we construct
* an explicit NULL default value that will be passed through
* an explicit NULL default value that will be passed through
* CoerceToDomain processing . ( This is a tad inefficient , since it causes
* CoerceToDomain processing . ( This is a tad inefficient , since it causes
* rewriting the table which we really do n ' t have to do , but the presen t
* rewriting the table which we really woul dn' t have to do ; but we do i t
* design of domain processing doesn ' t offer any simple way of checking
* to preserve the historical behavior that such a failure will be raised
* the constraints more directly . )
* only if the table currently contains some rows . )
*
*
* Note : we use build_column_default , and not just the cooked default
* Note : we use build_column_default , and not just the cooked default
* returned by AddRelationNewConstraints , so that the right thing happens
* returned by AddRelationNewConstraints , so that the right thing happens
@ -6642,6 +6628,9 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
*/
*/
if ( RELKIND_HAS_STORAGE ( relkind ) & & attribute . attnum > 0 )
if ( RELKIND_HAS_STORAGE ( relkind ) & & attribute . attnum > 0 )
{
{
bool has_domain_constraints ;
bool has_missing = false ;
/*
/*
* For an identity column , we can ' t use build_column_default ( ) ,
* For an identity column , we can ' t use build_column_default ( ) ,
* because the sequence ownership isn ' t set yet . So do it manually .
* because the sequence ownership isn ' t set yet . So do it manually .
@ -6654,14 +6643,13 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
nve - > typeId = typeOid ;
nve - > typeId = typeOid ;
defval = ( Expr * ) nve ;
defval = ( Expr * ) nve ;
/* must do a rewrite for identity columns */
tab - > rewrite | = AT_REWRITE_DEFAULT_VAL ;
}
}
else
else
defval = ( Expr * ) build_column_default ( rel , attribute . attnum ) ;
defval = ( Expr * ) build_column_default ( rel , attribute . attnum ) ;
if ( ! defval & & DomainHasConstraints ( typeOid ) )
/* Build CoerceToDomain(NULL) expression if needed */
has_domain_constraints = DomainHasConstraints ( typeOid ) ;
if ( ! defval & & has_domain_constraints )
{
{
Oid baseTypeId ;
Oid baseTypeId ;
int32 baseTypeMod ;
int32 baseTypeMod ;
@ -6687,18 +6675,61 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
{
{
NewColumnValue * newval ;
NewColumnValue * newval ;
/* Prepare defval for execution, either here or in Phase 3 */
defval = expression_planner ( defval ) ;
/* Add the new default to the newvals list */
newval = ( NewColumnValue * ) palloc0 ( sizeof ( NewColumnValue ) ) ;
newval = ( NewColumnValue * ) palloc0 ( sizeof ( NewColumnValue ) ) ;
newval - > attnum = attribute . attnum ;
newval - > attnum = attribute . attnum ;
newval - > expr = expression_planner ( defval ) ;
newval - > expr = defval ;
newval - > is_generated = ( colDef - > generated ! = ' \0 ' ) ;
newval - > is_generated = ( colDef - > generated ! = ' \0 ' ) ;
tab - > newvals = lappend ( tab - > newvals , newval ) ;
tab - > newvals = lappend ( tab - > newvals , newval ) ;
}
if ( DomainHasConstraints ( typeOid ) )
/*
tab - > rewrite | = AT_REWRITE_DEFAULT_VAL ;
* Attempt to skip a complete table rewrite by storing the
* specified DEFAULT value outside of the heap . This is only
* allowed for plain relations and non - generated columns , and the
* default expression can ' t be volatile ( stable is OK ) . Note that
* contain_volatile_functions deems CoerceToDomain immutable , but
* here we consider that coercion to a domain with constraints is
* volatile ; else it might fail even when the table is empty .
*/
if ( rel - > rd_rel - > relkind = = RELKIND_RELATION & &
! colDef - > generated & &
! has_domain_constraints & &
! contain_volatile_functions ( ( Node * ) defval ) )
{
EState * estate ;
ExprState * exprState ;
Datum missingval ;
bool missingIsNull ;
/* Evaluate the default expression */
estate = CreateExecutorState ( ) ;
exprState = ExecPrepareExpr ( defval , estate ) ;
missingval = ExecEvalExpr ( exprState ,
GetPerTupleExprContext ( estate ) ,
& missingIsNull ) ;
/* If it turns out NULL, nothing to do; else store it */
if ( ! missingIsNull )
{
StoreAttrMissingVal ( rel , attribute . attnum , missingval ) ;
has_missing = true ;
}
FreeExecutorState ( estate ) ;
}
else
{
/*
* Failed to use missing mode . We have to do a table rewrite
* to install the value .
*/
tab - > rewrite | = AT_REWRITE_DEFAULT_VAL ;
}
}
if ( ! TupleDescAttr ( rel - > rd_att , attribute . attnum - 1 ) - > atthasmissing )
if ( ! has_ missing )
{
{
/*
/*
* If the new column is NOT NULL , and there is no missing value ,
* If the new column is NOT NULL , and there is no missing value ,