@ -192,13 +192,15 @@ typedef struct NewConstraint
* Phase 3 copy ( this could be either a new column with a non - null default , or
* Phase 3 copy ( this could be either a new column with a non - null default , or
* a column that we ' re changing the type of ) . Columns without such an entry
* a column that we ' re changing the type of ) . Columns without such an entry
* are just copied from the old table during ATRewriteTable . Note that the
* are just copied from the old table during ATRewriteTable . Note that the
* expr is an expression over * old * table values .
* expr is an expression over * old * table values , except when is_generated
* is true ; then it is an expression over columns of the * new * tuple .
*/
*/
typedef struct NewColumnValue
typedef struct NewColumnValue
{
{
AttrNumber attnum ; /* which column */
AttrNumber attnum ; /* which column */
Expr * expr ; /* expression to compute */
Expr * expr ; /* expression to compute */
ExprState * exprstate ; /* execution state */
ExprState * exprstate ; /* execution state */
bool is_generated ; /* is it a GENERATED expression? */
} NewColumnValue ;
} NewColumnValue ;
/*
/*
@ -4961,7 +4963,9 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
/*
/*
* Process supplied expressions to replace selected columns .
* Process supplied expressions to replace selected columns .
* Expression inputs come from the old tuple .
*
* First , evaluate expressions whose inputs come from the old
* tuple .
*/
*/
econtext - > ecxt_scantuple = oldslot ;
econtext - > ecxt_scantuple = oldslot ;
@ -4969,6 +4973,9 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
{
{
NewColumnValue * ex = lfirst ( l ) ;
NewColumnValue * ex = lfirst ( l ) ;
if ( ex - > is_generated )
continue ;
newslot - > tts_values [ ex - > attnum - 1 ]
newslot - > tts_values [ ex - > attnum - 1 ]
= ExecEvalExpr ( ex - > exprstate ,
= ExecEvalExpr ( ex - > exprstate ,
econtext ,
econtext ,
@ -4977,6 +4984,26 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
ExecStoreVirtualTuple ( newslot ) ;
ExecStoreVirtualTuple ( newslot ) ;
/*
* Now , evaluate any expressions whose inputs come from the
* new tuple . We assume these columns won ' t reference each
* other , so that there ' s no ordering dependency .
*/
econtext - > ecxt_scantuple = newslot ;
foreach ( l , tab - > newvals )
{
NewColumnValue * ex = lfirst ( l ) ;
if ( ! ex - > is_generated )
continue ;
newslot - > tts_values [ ex - > attnum - 1 ]
= ExecEvalExpr ( ex - > exprstate ,
econtext ,
& newslot - > tts_isnull [ ex - > attnum - 1 ] ) ;
}
/*
/*
* Constraints might reference the tableoid column , so
* Constraints might reference the tableoid column , so
* initialize t_tableOid before evaluating them .
* initialize t_tableOid before evaluating them .
@ -5892,6 +5919,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
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 = expression_planner ( defval ) ;
newval - > is_generated = ( colDef - > generated ! = ' \0 ' ) ;
tab - > newvals = lappend ( tab - > newvals , newval ) ;
tab - > newvals = lappend ( tab - > newvals , newval ) ;
}
}
@ -10379,6 +10407,7 @@ ATPrepAlterColumnType(List **wqueue,
newval = ( NewColumnValue * ) palloc0 ( sizeof ( NewColumnValue ) ) ;
newval = ( NewColumnValue * ) palloc0 ( sizeof ( NewColumnValue ) ) ;
newval - > attnum = attnum ;
newval - > attnum = attnum ;
newval - > expr = ( Expr * ) transform ;
newval - > expr = ( Expr * ) transform ;
newval - > is_generated = false ;
tab - > newvals = lappend ( tab - > newvals , newval ) ;
tab - > newvals = lappend ( tab - > newvals , newval ) ;
if ( ATColumnChangeRequiresRewrite ( transform , attnum ) )
if ( ATColumnChangeRequiresRewrite ( transform , attnum ) )