@ -366,7 +366,9 @@ static void ATExecDropCluster(Relation rel, LOCKMODE lockmode);
static void ATPrepSetTableSpace ( AlteredTableInfo * tab , Relation rel ,
char * tablespacename , LOCKMODE lockmode ) ;
static void ATExecSetTableSpace ( Oid tableOid , Oid newTableSpace , LOCKMODE lockmode ) ;
static void ATExecSetRelOptions ( Relation rel , List * defList , bool isReset , LOCKMODE lockmode ) ;
static void ATExecSetRelOptions ( Relation rel , List * defList ,
AlterTableType operation ,
LOCKMODE lockmode ) ;
static void ATExecEnableDisableTrigger ( Relation rel , char * trigname ,
char fires_when , bool skip_system , LOCKMODE lockmode ) ;
static void ATExecEnableDisableRule ( Relation rel , char * rulename ,
@ -2866,6 +2868,7 @@ AlterTableGetLockLevel(List *cmds)
case AT_DropCluster :
case AT_SetRelOptions :
case AT_ResetRelOptions :
case AT_ReplaceRelOptions :
case AT_SetOptions :
case AT_ResetOptions :
case AT_SetStorage :
@ -3094,8 +3097,9 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
pass = AT_PASS_MISC ; /* doesn't actually matter */
break ;
case AT_SetRelOptions : /* SET (...) */
case AT_ResetRelOptions : /* RESET (...) */
ATSimplePermissions ( rel , ATT_TABLE | ATT_INDEX ) ;
case AT_ResetRelOptions : /* RESET (...) */
case AT_ReplaceRelOptions : /* reset them all, then set just these */
ATSimplePermissions ( rel , ATT_TABLE | ATT_INDEX | ATT_VIEW ) ;
/* This command never recurses */
/* No command-specific prep needed */
pass = AT_PASS_MISC ;
@ -3338,12 +3342,10 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
*/
break ;
case AT_SetRelOptions : /* SET (...) */
ATExecSetRelOptions ( rel , ( List * ) cmd - > def , false , lockmode ) ;
break ;
case AT_ResetRelOptions : /* RESET (...) */
ATExecSetRelOptions ( rel , ( List * ) cmd - > def , true , lockmode ) ;
case AT_ReplaceRelOptions : /* replace entire option list */
ATExecSetRelOptions ( rel , ( List * ) cmd - > def , cmd - > subtype , lockmode ) ;
break ;
case AT_EnableTrig : /* ENABLE TRIGGER name */
ATExecEnableDisableTrigger ( rel , cmd - > name ,
TRIGGER_FIRES_ON_ORIGIN , false , lockmode ) ;
@ -8271,10 +8273,11 @@ ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, char *tablespacename, L
}
/*
* ALTER TABLE / INDEX SET ( . . . ) or RESET ( . . . )
* Set , reset , or replace reloptions .
*/
static void
ATExecSetRelOptions ( Relation rel , List * defList , bool isReset , LOCKMODE lockmode )
ATExecSetRelOptions ( Relation rel , List * defList , AlterTableType operation ,
LOCKMODE lockmode )
{
Oid relid ;
Relation pgclass ;
@ -8288,28 +8291,44 @@ ATExecSetRelOptions(Relation rel, List *defList, bool isReset, LOCKMODE lockmode
bool repl_repl [ Natts_pg_class ] ;
static char * validnsps [ ] = HEAP_RELOPT_NAMESPACES ;
if ( defList = = NIL )
if ( defList = = NIL & & operation ! = AT_ReplaceRelOptions )
return ; /* nothing to do */
pgclass = heap_open ( RelationRelationId , RowExclusiveLock ) ;
/* Get the old reloptions */
/* Fetch heap tuple */
relid = RelationGetRelid ( rel ) ;
tuple = SearchSysCache1 ( RELOID , ObjectIdGetDatum ( relid ) ) ;
if ( ! HeapTupleIsValid ( tuple ) )
elog ( ERROR , " cache lookup failed for relation %u " , relid ) ;
datum = SysCacheGetAttr ( RELOID , tuple , Anum_pg_class_reloptions , & isnull ) ;
if ( operation = = AT_ReplaceRelOptions )
{
/*
* If we ' re supposed to replace the reloptions list , we just pretend
* there were none before .
*/
datum = ( Datum ) 0 ;
isnull = true ;
}
else
{
/* Get the old reloptions */
datum = SysCacheGetAttr ( RELOID , tuple , Anum_pg_class_reloptions ,
& isnull ) ;
}
/* Generate new proposed reloptions (text array) */
newOptions = transformRelOptions ( isnull ? ( Datum ) 0 : datum ,
defList , NULL , validnsps , false , isReset ) ;
defList , NULL , validnsps , false ,
operation = = AT_ResetRelOptions ) ;
/* Validate */
switch ( rel - > rd_rel - > relkind )
{
case RELKIND_RELATION :
case RELKIND_TOASTVALUE :
case RELKIND_VIEW :
( void ) heap_reloptions ( rel - > rd_rel - > relkind , newOptions , true ) ;
break ;
case RELKIND_INDEX :
@ -8357,15 +8376,30 @@ ATExecSetRelOptions(Relation rel, List *defList, bool isReset, LOCKMODE lockmode
toastrel = heap_open ( toastid , lockmode ) ;
/* Get the old reloptions */
/* Fetch heap tuple */
tuple = SearchSysCache1 ( RELOID , ObjectIdGetDatum ( toastid ) ) ;
if ( ! HeapTupleIsValid ( tuple ) )
elog ( ERROR , " cache lookup failed for relation %u " , toastid ) ;
datum = SysCacheGetAttr ( RELOID , tuple , Anum_pg_class_reloptions , & isnull ) ;
if ( operation = = AT_ReplaceRelOptions )
{
/*
* If we ' re supposed to replace the reloptions list , we just
* pretend there were none before .
*/
datum = ( Datum ) 0 ;
isnull = true ;
}
else
{
/* Get the old reloptions */
datum = SysCacheGetAttr ( RELOID , tuple , Anum_pg_class_reloptions ,
& isnull ) ;
}
newOptions = transformRelOptions ( isnull ? ( Datum ) 0 : datum ,
defList , " toast " , validnsps , false , isReset ) ;
defList , " toast " , validnsps , false ,
operation = = AT_ResetRelOptions ) ;
( void ) heap_reloptions ( RELKIND_TOASTVALUE , newOptions , true ) ;