@ -10,7 +10,7 @@
* Written by Peter Eisentraut < peter_e @ gmx . net > .
* Written by Peter Eisentraut < peter_e @ gmx . net > .
*
*
* IDENTIFICATION
* IDENTIFICATION
* $ PostgreSQL : pgsql / src / backend / utils / misc / guc . c , v 1.419 2007 / 09 / 10 02 : 01 : 19 tgl Exp $
* $ PostgreSQL : pgsql / src / backend / utils / misc / guc . c , v 1.420 2007 / 09 / 11 00 : 06 : 42 tgl Exp $
*
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
@ -422,9 +422,9 @@ const char *const config_type_names[] =
* 4. Add a record below .
* 4. Add a record below .
*
*
* 5. Add it to src / backend / utils / misc / postgresql . conf . sample , if
* 5. Add it to src / backend / utils / misc / postgresql . conf . sample , if
* appropriate
* appropriate .
*
*
* 6. Don ' t forget to document the option .
* 6. Don ' t forget to document the option ( at least in config . sgml ) .
*
*
* 7. If it ' s a new GUC_LIST option you must edit pg_dumpall . c to ensure
* 7. If it ' s a new GUC_LIST option you must edit pg_dumpall . c to ensure
* it is not single quoted at dump time .
* it is not single quoted at dump time .
@ -2499,7 +2499,7 @@ static int GUCNestLevel = 0; /* 1 when in main transaction */
static int guc_var_compare ( const void * a , const void * b ) ;
static int guc_var_compare ( const void * a , const void * b ) ;
static int guc_name_compare ( const char * namea , const char * nameb ) ;
static int guc_name_compare ( const char * namea , const char * nameb ) ;
static void push_old_value ( struct config_generic * gconf ) ;
static void push_old_value ( struct config_generic * gconf , GucAction action ) ;
static void ReportGUCOption ( struct config_generic * record ) ;
static void ReportGUCOption ( struct config_generic * record ) ;
static void ShowGUCConfigOption ( const char * name , DestReceiver * dest ) ;
static void ShowGUCConfigOption ( const char * name , DestReceiver * dest ) ;
static void ShowAllGUCConfig ( DestReceiver * dest ) ;
static void ShowAllGUCConfig ( DestReceiver * dest ) ;
@ -2568,13 +2568,12 @@ set_string_field(struct config_string * conf, char **field, char *newval)
if ( oldval = = NULL | |
if ( oldval = = NULL | |
oldval = = * ( conf - > variable ) | |
oldval = = * ( conf - > variable ) | |
oldval = = conf - > reset_val | |
oldval = = conf - > reset_val | |
oldval = = conf - > tentative_val | |
oldval = = conf - > boot_val )
oldval = = conf - > boot_val )
return ;
return ;
for ( stack = conf - > gen . stack ; stack ; stack = stack - > prev )
for ( stack = conf - > gen . stack ; stack ; stack = stack - > prev )
{
{
if ( oldval = = stack - > tentative_val . stringval | |
if ( oldval = = stack - > prior . stringval | |
oldval = = stack - > value . stringval )
oldval = = stack - > masked . stringval )
return ;
return ;
}
}
@ -2592,19 +2591,71 @@ string_field_used(struct config_string * conf, char *strval)
if ( strval = = * ( conf - > variable ) | |
if ( strval = = * ( conf - > variable ) | |
strval = = conf - > reset_val | |
strval = = conf - > reset_val | |
strval = = conf - > tentative_val | |
strval = = conf - > boot_val )
strval = = conf - > boot_val )
return true ;
return true ;
for ( stack = conf - > gen . stack ; stack ; stack = stack - > prev )
for ( stack = conf - > gen . stack ; stack ; stack = stack - > prev )
{
{
if ( strval = = stack - > tentative_val . stringval | |
if ( strval = = stack - > prior . stringval | |
strval = = stack - > value . stringval )
strval = = stack - > masked . stringval )
return true ;
return true ;
}
}
return false ;
return false ;
}
}
/*
* Support for copying a variable ' s active value into a stack entry
*/
static void
set_stack_value ( struct config_generic * gconf , union config_var_value * val )
{
switch ( gconf - > vartype )
{
case PGC_BOOL :
val - > boolval =
* ( ( struct config_bool * ) gconf ) - > variable ;
break ;
case PGC_INT :
val - > intval =
* ( ( struct config_int * ) gconf ) - > variable ;
break ;
case PGC_REAL :
val - > realval =
* ( ( struct config_real * ) gconf ) - > variable ;
break ;
case PGC_STRING :
/* we assume stringval is NULL if not valid */
set_string_field ( ( struct config_string * ) gconf ,
& ( val - > stringval ) ,
* ( ( struct config_string * ) gconf ) - > variable ) ;
break ;
}
}
/*
* Support for discarding a no - longer - needed value in a stack entry
*/
static void
discard_stack_value ( struct config_generic * gconf , union config_var_value * val )
{
switch ( gconf - > vartype )
{
case PGC_BOOL :
case PGC_INT :
case PGC_REAL :
/* no need to do anything */
break ;
case PGC_STRING :
set_string_field ( ( struct config_string * ) gconf ,
& ( val - > stringval ) ,
NULL ) ;
break ;
}
}
/*
* Fetch the sorted array pointer ( exported for help_config . c ' s use ONLY )
*/
struct config_generic * *
struct config_generic * *
get_guc_variables ( void )
get_guc_variables ( void )
{
{
@ -2878,7 +2929,9 @@ guc_var_compare(const void *a, const void *b)
return guc_name_compare ( confa - > name , confb - > name ) ;
return guc_name_compare ( confa - > name , confb - > name ) ;
}
}
/*
* the bare comparison function for GUC names
*/
static int
static int
guc_name_compare ( const char * namea , const char * nameb )
guc_name_compare ( const char * namea , const char * nameb )
{
{
@ -2941,7 +2994,6 @@ InitializeGUCOptions(void)
gconf - > status = 0 ;
gconf - > status = 0 ;
gconf - > reset_source = PGC_S_DEFAULT ;
gconf - > reset_source = PGC_S_DEFAULT ;
gconf - > tentative_source = PGC_S_DEFAULT ;
gconf - > source = PGC_S_DEFAULT ;
gconf - > source = PGC_S_DEFAULT ;
gconf - > stack = NULL ;
gconf - > stack = NULL ;
@ -2994,7 +3046,6 @@ InitializeGUCOptions(void)
* conf - > variable = NULL ;
* conf - > variable = NULL ;
conf - > reset_val = NULL ;
conf - > reset_val = NULL ;
conf - > tentative_val = NULL ;
if ( conf - > boot_val = = NULL )
if ( conf - > boot_val = = NULL )
{
{
@ -3260,7 +3311,7 @@ ResetAllOptions(void)
continue ;
continue ;
/* Save old value to support transaction abort */
/* Save old value to support transaction abort */
push_old_value ( gconf ) ;
push_old_value ( gconf , GUC_ACTION_SET ) ;
switch ( gconf - > vartype )
switch ( gconf - > vartype )
{
{
@ -3273,11 +3324,7 @@ ResetAllOptions(void)
PGC_S_SESSION ) )
PGC_S_SESSION ) )
elog ( ERROR , " failed to reset %s " , conf - > gen . name ) ;
elog ( ERROR , " failed to reset %s " , conf - > gen . name ) ;
* conf - > variable = conf - > reset_val ;
* conf - > variable = conf - > reset_val ;
conf - > tentative_val = conf - > reset_val ;
conf - > gen . source = conf - > gen . reset_source ;
conf - > gen . source = conf - > gen . reset_source ;
conf - > gen . tentative_source = conf - > gen . reset_source ;
conf - > gen . status | = GUC_HAVE_TENTATIVE ;
guc_dirty = true ;
break ;
break ;
}
}
case PGC_INT :
case PGC_INT :
@ -3289,11 +3336,7 @@ ResetAllOptions(void)
PGC_S_SESSION ) )
PGC_S_SESSION ) )
elog ( ERROR , " failed to reset %s " , conf - > gen . name ) ;
elog ( ERROR , " failed to reset %s " , conf - > gen . name ) ;
* conf - > variable = conf - > reset_val ;
* conf - > variable = conf - > reset_val ;
conf - > tentative_val = conf - > reset_val ;
conf - > gen . source = conf - > gen . reset_source ;
conf - > gen . source = conf - > gen . reset_source ;
conf - > gen . tentative_source = conf - > gen . reset_source ;
conf - > gen . status | = GUC_HAVE_TENTATIVE ;
guc_dirty = true ;
break ;
break ;
}
}
case PGC_REAL :
case PGC_REAL :
@ -3305,11 +3348,7 @@ ResetAllOptions(void)
PGC_S_SESSION ) )
PGC_S_SESSION ) )
elog ( ERROR , " failed to reset %s " , conf - > gen . name ) ;
elog ( ERROR , " failed to reset %s " , conf - > gen . name ) ;
* conf - > variable = conf - > reset_val ;
* conf - > variable = conf - > reset_val ;
conf - > tentative_val = conf - > reset_val ;
conf - > gen . source = conf - > gen . reset_source ;
conf - > gen . source = conf - > gen . reset_source ;
conf - > gen . tentative_source = conf - > gen . reset_source ;
conf - > gen . status | = GUC_HAVE_TENTATIVE ;
guc_dirty = true ;
break ;
break ;
}
}
case PGC_STRING :
case PGC_STRING :
@ -3338,11 +3377,7 @@ ResetAllOptions(void)
}
}
set_string_field ( conf , conf - > variable , str ) ;
set_string_field ( conf , conf - > variable , str ) ;
set_string_field ( conf , & conf - > tentative_val , str ) ;
conf - > gen . source = conf - > gen . reset_source ;
conf - > gen . source = conf - > gen . reset_source ;
conf - > gen . tentative_source = conf - > gen . reset_source ;
conf - > gen . status | = GUC_HAVE_TENTATIVE ;
guc_dirty = true ;
break ;
break ;
}
}
}
}
@ -3355,84 +3390,84 @@ ResetAllOptions(void)
/*
/*
* push_old_value
* push_old_value
* Push previous state during first assignment to a GUC variable
* Push previous state during transactional assignment to a GUC variable .
* within a particular transaction .
*
* We have to be willing to " back-fill " the state stack if the first
* assignment occurs within a subtransaction nested several levels deep .
* This ensures that if an intermediate transaction aborts , it will have
* the proper value available to restore the setting to .
*/
*/
static void
static void
push_old_value ( struct config_generic * gconf )
push_old_value ( struct config_generic * gconf , GucAction action )
{
{
GucStack * stack ;
GucStack * stack ;
/* If we're not inside a transaction , do nothing */
/* If we're not inside a nest level , do nothing */
if ( GUCNestLevel = = 0 )
if ( GUCNestLevel = = 0 )
return ;
return ;
for ( ; ; )
/* Do we already have a stack entry of the current nest level? */
stack = gconf - > stack ;
if ( stack & & stack - > nest_level > = GUCNestLevel )
{
/* Yes, so adjust its state if necessary */
Assert ( stack - > nest_level = = GUCNestLevel ) ;
switch ( action )
{
{
/* Done if we already pushed it at this nesting depth */
case GUC_ACTION_SET :
if ( gconf - > stack & & gconf - > stack - > nest_level > = GUCNestLevel )
/* SET overrides any prior action at same nest level */
if ( stack - > state = = GUC_SET_LOCAL )
{
/* must discard old masked value */
discard_stack_value ( gconf , & stack - > masked ) ;
}
stack - > state = GUC_SET ;
break ;
case GUC_ACTION_LOCAL :
if ( stack - > state = = GUC_SET )
{
/* SET followed by SET LOCAL, remember SET's value */
set_stack_value ( gconf , & stack - > masked ) ;
stack - > state = GUC_SET_LOCAL ;
}
/* in all other cases, no change to stack entry */
break ;
case GUC_ACTION_SAVE :
/* Could only have a prior SAVE of same variable */
Assert ( stack - > state = = GUC_SAVE ) ;
break ;
}
Assert ( guc_dirty ) ; /* must be set already */
return ;
return ;
}
/*
/*
* We keep all the stack entries in TopTransactionContext so as to
* Push a new stack entry
* avoid allocation problems when a subtransaction back - fills stack
*
* entries for upper transaction levels .
* We keep all the stack entries in TopTransactionContext for simplicity .
*/
*/
stack = ( GucStack * ) MemoryContextAlloc ( TopTransactionContext ,
stack = ( GucStack * ) MemoryContextAllocZero ( TopTransactionContext ,
sizeof ( GucStack ) ) ;
sizeof ( GucStack ) ) ;
stack - > prev = gconf - > stack ;
stack - > prev = gconf - > stack ;
stack - > nest_level = stack - > prev ? stack - > prev - > nest_level + 1 : 1 ;
stack - > nest_level = GUCNestLevel ;
stack - > status = gconf - > status ;
switch ( action )
stack - > tentative_source = gconf - > tentative_source ;
stack - > source = gconf - > source ;
switch ( gconf - > vartype )
{
{
case PGC_BOOL :
case GUC_ACTION_SET :
stack - > tentative_val . boolval =
stack - > state = GUC_SET ;
( ( struct config_bool * ) gconf ) - > tentative_val ;
stack - > value . boolval =
* ( ( struct config_bool * ) gconf ) - > variable ;
break ;
case PGC_INT :
stack - > tentative_val . intval =
( ( struct config_int * ) gconf ) - > tentative_val ;
stack - > value . intval =
* ( ( struct config_int * ) gconf ) - > variable ;
break ;
break ;
case GUC_ACTION_LOCAL :
case PGC_REAL :
stack - > state = GUC_LOCAL ;
stack - > tentative_val . realval =
( ( struct config_real * ) gconf ) - > tentative_val ;
stack - > value . realval =
* ( ( struct config_real * ) gconf ) - > variable ;
break ;
break ;
case GUC_ACTION_SAVE :
case PGC_STRING :
stack - > state = GUC_SAVE ;
stack - > tentative_val . stringval =
( ( struct config_string * ) gconf ) - > tentative_val ;
stack - > value . stringval =
* ( ( struct config_string * ) gconf ) - > variable ;
break ;
break ;
}
}
stack - > source = gconf - > source ;
set_stack_value ( gconf , & stack - > prior ) ;
gconf - > stack = stack ;
gconf - > stack = stack ;
/* Set state to indicate nothing happened yet within this level */
gconf - > status = GUC_HAVE_STACK ;
/* Ensure we remember to pop at end of xact */
/* Ensure we remember to pop at end of xact */
guc_dirty = true ;
guc_dirty = true ;
}
}
}
/*
/*
* Do GUC processing at main transaction start .
* Do GUC processing at main transaction start .
*/
*/
@ -3471,6 +3506,7 @@ NewGUCNestLevel(void)
void
void
AtEOXact_GUC ( bool isCommit , int nestLevel )
AtEOXact_GUC ( bool isCommit , int nestLevel )
{
{
bool still_dirty ;
int i ;
int i ;
Assert ( nestLevel > 0 & & nestLevel < = GUCNestLevel ) ;
Assert ( nestLevel > 0 & & nestLevel < = GUCNestLevel ) ;
@ -3482,79 +3518,128 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
return ;
return ;
}
}
still_dirty = false ;
for ( i = 0 ; i < num_guc_variables ; i + + )
for ( i = 0 ; i < num_guc_variables ; i + + )
{
{
struct config_generic * gconf = guc_variables [ i ] ;
struct config_generic * gconf = guc_variables [ i ] ;
int my_status = gconf - > status ;
GucStack * stack ;
GucStack * stack = gconf - > stack ;
bool useTentative ;
/*
* Process and pop each stack entry within the nest level . To
* simplify fmgr_security_definer ( ) , we allow failure exit from
* a function - with - SET - options to be recovered at the surrounding
* transaction or subtransaction abort ; so there could be more than
* one stack entry to pop .
*/
while ( ( stack = gconf - > stack ) ! = NULL & &
stack - > nest_level > = nestLevel )
{
GucStack * prev = stack - > prev ;
bool restorePrior = false ;
bool restoreMasked = false ;
bool changed ;
bool changed ;
/*
/*
* Skip if nothing ' s happened to this var in this transaction
* In this next bit , if we don ' t set either restorePrior or
* restoreMasked , we must " discard " any unwanted fields of the
* stack entries to avoid leaking memory . If we do set one of
* those flags , unused fields will be cleaned up after restoring .
*/
*/
if ( ( my_status & ( GUC_HAVE_TENTATIVE |
if ( ! isCommit ) /* if abort, always restore prior value */
GUC_HAVE_LOCAL |
restorePrior = true ;
GUC_HAVE_STACK ) ) = = 0 )
else if ( stack - > state = = GUC_SAVE )
restorePrior = true ;
else if ( stack - > nest_level = = 1 )
{
{
Assert ( stack = = NULL ) ;
/* transaction commit */
continue ;
if ( stack - > state = = GUC_SET_LOCAL )
restoreMasked = true ;
else if ( stack - > state = = GUC_SET )
{
/* we keep the current active value */
discard_stack_value ( gconf , & stack - > prior ) ;
}
}
/* Assert that we stacked old value before changing it */
else /* must be GUC_LOCAL */
Assert ( stack ! = NULL & & ( my_status & GUC_HAVE_STACK ) ) ;
restorePrior = true ;
/* However, the last change may have been at an outer xact level */
}
if ( stack - > nest_level < nestLevel )
else if ( prev = = NULL | |
prev - > nest_level < stack - > nest_level - 1 )
{
/* decrement entry's level and do not pop it */
stack - > nest_level - - ;
continue ;
continue ;
Assert ( stack - > nest_level = = nestLevel ) ;
}
else
{
/*
/*
* We will pop the stack entry . Start by restoring outer xact status
* We have to merge this stack entry into prev .
* ( since we may want to modify it below ) . Be careful to use
* See README for discussion of this bit .
* my_status to reference the inner xact status below this point . . .
*/
*/
gconf - > status = stack - > status ;
switch ( stack - > state )
{
case GUC_SAVE :
Assert ( false ) ; /* can't get here */
/*
case GUC_SET :
* We have two cases :
/* next level always becomes SET */
*
discard_stack_value ( gconf , & stack - > prior ) ;
* If commit and HAVE_TENTATIVE , set actual value to tentative ( this
if ( prev - > state = = GUC_SET_LOCAL )
* is to override a SET LOCAL if one occurred later than SET ) . We keep
discard_stack_value ( gconf , & prev - > masked ) ;
* the tentative value and propagate HAVE_TENTATIVE to the parent
prev - > state = GUC_SET ;
* status , allowing the SET ' s effect to percolate up . ( But if we ' re
break ;
* exiting the outermost transaction , we ' ll drop the HAVE_TENTATIVE
* bit below . )
case GUC_LOCAL :
*
if ( prev - > state = = GUC_SET )
* Otherwise , we have a transaction that aborted or executed only SET
{
* LOCAL ( or no SET at all ) . In either case it should have no further
/* LOCAL migrates down */
* effect , so restore both tentative and actual values from the stack
prev - > masked = stack - > prior ;
* entry .
prev - > state = GUC_SET_LOCAL ;
*/
}
else
{
/* else just forget this stack level */
discard_stack_value ( gconf , & stack - > prior ) ;
}
break ;
case GUC_SET_LOCAL :
/* prior state at this level no longer wanted */
discard_stack_value ( gconf , & stack - > prior ) ;
/* copy down the masked state */
if ( prev - > state = = GUC_SET_LOCAL )
discard_stack_value ( gconf , & prev - > masked ) ;
prev - > masked = stack - > masked ;
prev - > state = GUC_SET_LOCAL ;
break ;
}
}
useTentative = isCommit & & ( my_status & GUC_HAVE_TENTATIVE ) ! = 0 ;
changed = false ;
changed = false ;
switch ( gconf - > vartype )
if ( restorePrior | | restoreMasked )
{
case PGC_BOOL :
{
{
struct config_bool * conf = ( struct config_bool * ) gconf ;
/* Perform appropriate restoration of the stacked value */
bool newval ;
union config_var_value newvalue ;
GucSource newsource ;
GucSource newsource ;
if ( useTentative )
if ( restoreMasked )
{
{
newval = conf - > tentative_val ;
newvalue = stack - > masked ;
newsource = conf - > gen . tentative_source ;
newsource = PGC_S_SESSION ;
conf - > gen . status | = GUC_HAVE_TENTATIVE ;
}
}
else
else
{
{
newval = stack - > value . boolval ;
newvalue = stack - > prior ;
newsource = stack - > source ;
newsource = stack - > source ;
conf - > tentative_val = stack - > tentative_val . boolval ;
conf - > gen . tentative_source = stack - > tentative_source ;
}
}
switch ( gconf - > vartype )
{
case PGC_BOOL :
{
struct config_bool * conf = ( struct config_bool * ) gconf ;
bool newval = newvalue . boolval ;
if ( * conf - > variable ! = newval )
if ( * conf - > variable ! = newval )
{
{
if ( conf - > assign_hook )
if ( conf - > assign_hook )
@ -3565,28 +3650,12 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
* conf - > variable = newval ;
* conf - > variable = newval ;
changed = true ;
changed = true ;
}
}
conf - > gen . source = newsource ;
break ;
break ;
}
}
case PGC_INT :
case PGC_INT :
{
{
struct config_int * conf = ( struct config_int * ) gconf ;
struct config_int * conf = ( struct config_int * ) gconf ;
int newval ;
int newval = newvalue . intval ;
GucSource newsource ;
if ( useTentative )
{
newval = conf - > tentative_val ;
newsource = conf - > gen . tentative_source ;
conf - > gen . status | = GUC_HAVE_TENTATIVE ;
}
else
{
newval = stack - > value . intval ;
newsource = stack - > source ;
conf - > tentative_val = stack - > tentative_val . intval ;
conf - > gen . tentative_source = stack - > tentative_source ;
}
if ( * conf - > variable ! = newval )
if ( * conf - > variable ! = newval )
{
{
@ -3598,28 +3667,12 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
* conf - > variable = newval ;
* conf - > variable = newval ;
changed = true ;
changed = true ;
}
}
conf - > gen . source = newsource ;
break ;
break ;
}
}
case PGC_REAL :
case PGC_REAL :
{
{
struct config_real * conf = ( struct config_real * ) gconf ;
struct config_real * conf = ( struct config_real * ) gconf ;
double newval ;
double newval = newvalue . realval ;
GucSource newsource ;
if ( useTentative )
{
newval = conf - > tentative_val ;
newsource = conf - > gen . tentative_source ;
conf - > gen . status | = GUC_HAVE_TENTATIVE ;
}
else
{
newval = stack - > value . realval ;
newsource = stack - > source ;
conf - > tentative_val = stack - > tentative_val . realval ;
conf - > gen . tentative_source = stack - > tentative_source ;
}
if ( * conf - > variable ! = newval )
if ( * conf - > variable ! = newval )
{
{
@ -3631,29 +3684,12 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
* conf - > variable = newval ;
* conf - > variable = newval ;
changed = true ;
changed = true ;
}
}
conf - > gen . source = newsource ;
break ;
break ;
}
}
case PGC_STRING :
case PGC_STRING :
{
{
struct config_string * conf = ( struct config_string * ) gconf ;
struct config_string * conf = ( struct config_string * ) gconf ;
char * newval ;
char * newval = newvalue . stringval ;
GucSource newsource ;
if ( useTentative )
{
newval = conf - > tentative_val ;
newsource = conf - > gen . tentative_source ;
conf - > gen . status | = GUC_HAVE_TENTATIVE ;
}
else
{
newval = stack - > value . stringval ;
newsource = stack - > source ;
set_string_field ( conf , & conf - > tentative_val ,
stack - > tentative_val . stringval ) ;
conf - > gen . tentative_source = stack - > tentative_source ;
}
if ( * conf - > variable ! = newval )
if ( * conf - > variable ! = newval )
{
{
@ -3682,46 +3718,36 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
set_string_field ( conf , conf - > variable , newval ) ;
set_string_field ( conf , conf - > variable , newval ) ;
changed = true ;
changed = true ;
}
}
conf - > gen . source = newsource ;
/*
/* Release stacked values if not used anymore */
* Release stacked values if not used anymore .
set_string_field ( conf , & stack - > value . stringval ,
* We could use discard_stack_value ( ) here , but since
NULL ) ;
* we have type - specific code anyway , might as well
set_string_field ( conf , & stack - > tentative_val . stringval ,
* inline it .
NULL ) ;
*/
/* Don't store tentative value separately after commit */
set_string_field ( conf , & stack - > prior . stringval , NULL ) ;
if ( nestLevel = = 1 )
set_string_field ( conf , & stack - > masked . stringval , NULL ) ;
set_string_field ( conf , & conf - > tentative_val , NULL ) ;
break ;
break ;
}
}
}
}
gconf - > source = newsource ;
}
/* Finish popping the state stack */
/* Finish popping the state stack */
gconf - > stack = stack - > prev ;
gconf - > stack = prev ;
pfree ( stack ) ;
pfree ( stack ) ;
/*
* If we ' re now out of all xact levels , forget TENTATIVE status bit ;
* there ' s nothing tentative about the value anymore .
*/
if ( nestLevel = = 1 )
{
Assert ( gconf - > stack = = NULL ) ;
gconf - > status = 0 ;
}
/* Report new value if we changed it */
/* Report new value if we changed it */
if ( changed & & ( gconf - > flags & GUC_REPORT ) )
if ( changed & & ( gconf - > flags & GUC_REPORT ) )
ReportGUCOption ( gconf ) ;
ReportGUCOption ( gconf ) ;
} /* end of stack-popping loop */
if ( stack ! = NULL )
still_dirty = true ;
}
}
/*
/* If there are no remaining stack entries, we can reset guc_dirty */
* If we ' re now out of all xact levels , we can clear guc_dirty . ( Note : we
guc_dirty = still_dirty ;
* cannot reset guc_dirty when exiting a subtransaction , because we know
* that all outer transaction levels will have stacked values to deal
* with . )
*/
if ( nestLevel = = 1 )
guc_dirty = false ;
/* Update nesting level */
/* Update nesting level */
GUCNestLevel = nestLevel - 1 ;
GUCNestLevel = nestLevel - 1 ;
@ -4123,8 +4149,13 @@ call_string_assign_hook(GucStringAssignHook assign_hook,
* function is being called so it can apply the access restrictions
* function is being called so it can apply the access restrictions
* properly .
* properly .
*
*
* If value is NULL , set the option to its default value . If the
* If value is NULL , set the option to its default value ( normally the
* parameter changeVal is false then don ' t really set the option but do all
* reset_val , but if source = = PGC_S_DEFAULT we instead use the boot_val ) .
*
* action indicates whether to set the value globally in the session , locally
* to the current top transaction , or just for the duration of a function call .
*
* If changeVal is false then don ' t really set the option but do all
* the checks to see if it would work .
* the checks to see if it would work .
*
*
* If there is an error ( non - existing option , invalid value ) then an
* If there is an error ( non - existing option , invalid value ) then an
@ -4141,7 +4172,7 @@ call_string_assign_hook(GucStringAssignHook assign_hook,
bool
bool
set_config_option ( const char * name , const char * value ,
set_config_option ( const char * name , const char * value ,
GucContext context , GucSource source ,
GucContext context , GucSource source ,
bool isLocal , bool changeVal )
GucAction action , bool changeVal )
{
{
struct config_generic * record ;
struct config_generic * record ;
int elevel ;
int elevel ;
@ -4306,9 +4337,6 @@ set_config_option(const char *name, const char *value,
/*
/*
* Evaluate value and set variable .
* Evaluate value and set variable .
*
* Note : if value = = NULL then we are supposed to set to the reset_val ,
* except when source = = PGC_S_DEFAULT ; then we set to the boot_val .
*/
*/
switch ( record - > vartype )
switch ( record - > vartype )
{
{
@ -4350,7 +4378,7 @@ set_config_option(const char *name, const char *value,
{
{
/* Save old value to support transaction abort */
/* Save old value to support transaction abort */
if ( ! makeDefault )
if ( ! makeDefault )
push_old_value ( & conf - > gen ) ;
push_old_value ( & conf - > gen , action ) ;
if ( changeVal )
if ( changeVal )
{
{
* conf - > variable = newval ;
* conf - > variable = newval ;
@ -4369,23 +4397,11 @@ set_config_option(const char *name, const char *value,
{
{
if ( stack - > source < = source )
if ( stack - > source < = source )
{
{
stack - > value . boolval = newval ;
stack - > prior . boolval = newval ;
stack - > source = source ;
stack - > source = source ;
}
}
}
}
}
}
else if ( isLocal )
{
conf - > gen . status | = GUC_HAVE_LOCAL ;
guc_dirty = true ;
}
else
{
conf - > tentative_val = newval ;
conf - > gen . tentative_source = source ;
conf - > gen . status | = GUC_HAVE_TENTATIVE ;
guc_dirty = true ;
}
}
}
break ;
break ;
}
}
@ -4439,7 +4455,7 @@ set_config_option(const char *name, const char *value,
{
{
/* Save old value to support transaction abort */
/* Save old value to support transaction abort */
if ( ! makeDefault )
if ( ! makeDefault )
push_old_value ( & conf - > gen ) ;
push_old_value ( & conf - > gen , action ) ;
if ( changeVal )
if ( changeVal )
{
{
* conf - > variable = newval ;
* conf - > variable = newval ;
@ -4458,23 +4474,11 @@ set_config_option(const char *name, const char *value,
{
{
if ( stack - > source < = source )
if ( stack - > source < = source )
{
{
stack - > value . intval = newval ;
stack - > prior . intval = newval ;
stack - > source = source ;
stack - > source = source ;
}
}
}
}
}
}
else if ( isLocal )
{
conf - > gen . status | = GUC_HAVE_LOCAL ;
guc_dirty = true ;
}
else
{
conf - > tentative_val = newval ;
conf - > gen . tentative_source = source ;
conf - > gen . status | = GUC_HAVE_TENTATIVE ;
guc_dirty = true ;
}
}
}
break ;
break ;
}
}
@ -4525,7 +4529,7 @@ set_config_option(const char *name, const char *value,
{
{
/* Save old value to support transaction abort */
/* Save old value to support transaction abort */
if ( ! makeDefault )
if ( ! makeDefault )
push_old_value ( & conf - > gen ) ;
push_old_value ( & conf - > gen , action ) ;
if ( changeVal )
if ( changeVal )
{
{
* conf - > variable = newval ;
* conf - > variable = newval ;
@ -4544,23 +4548,11 @@ set_config_option(const char *name, const char *value,
{
{
if ( stack - > source < = source )
if ( stack - > source < = source )
{
{
stack - > value . realval = newval ;
stack - > prior . realval = newval ;
stack - > source = source ;
stack - > source = source ;
}
}
}
}
}
}
else if ( isLocal )
{
conf - > gen . status | = GUC_HAVE_LOCAL ;
guc_dirty = true ;
}
else
{
conf - > tentative_val = newval ;
conf - > gen . tentative_source = source ;
conf - > gen . status | = GUC_HAVE_TENTATIVE ;
guc_dirty = true ;
}
}
}
break ;
break ;
}
}
@ -4653,7 +4645,7 @@ set_config_option(const char *name, const char *value,
{
{
/* Save old value to support transaction abort */
/* Save old value to support transaction abort */
if ( ! makeDefault )
if ( ! makeDefault )
push_old_value ( & conf - > gen ) ;
push_old_value ( & conf - > gen , action ) ;
if ( changeVal )
if ( changeVal )
{
{
set_string_field ( conf , conf - > variable , newval ) ;
set_string_field ( conf , conf - > variable , newval ) ;
@ -4672,7 +4664,7 @@ set_config_option(const char *name, const char *value,
{
{
if ( stack - > source < = source )
if ( stack - > source < = source )
{
{
set_string_field ( conf , & stack - > value . stringval ,
set_string_field ( conf , & stack - > prior . stringval ,
newval ) ;
newval ) ;
stack - > source = source ;
stack - > source = source ;
}
}
@ -4681,18 +4673,6 @@ set_config_option(const char *name, const char *value,
if ( newval & & ! string_field_used ( conf , newval ) )
if ( newval & & ! string_field_used ( conf , newval ) )
free ( newval ) ;
free ( newval ) ;
}
}
else if ( isLocal )
{
conf - > gen . status | = GUC_HAVE_LOCAL ;
guc_dirty = true ;
}
else
{
set_string_field ( conf , & conf - > tentative_val , newval ) ;
conf - > gen . tentative_source = source ;
conf - > gen . status | = GUC_HAVE_TENTATIVE ;
guc_dirty = true ;
}
}
}
else if ( newval )
else if ( newval )
free ( newval ) ;
free ( newval ) ;
@ -4716,7 +4696,8 @@ void
SetConfigOption ( const char * name , const char * value ,
SetConfigOption ( const char * name , const char * value ,
GucContext context , GucSource source )
GucContext context , GucSource source )
{
{
( void ) set_config_option ( name , value , context , source , false , true ) ;
( void ) set_config_option ( name , value , context , source ,
GUC_ACTION_SET , true ) ;
}
}
@ -4942,6 +4923,8 @@ flatten_set_variable_args(const char *name, List *args)
void
void
ExecSetVariableStmt ( VariableSetStmt * stmt )
ExecSetVariableStmt ( VariableSetStmt * stmt )
{
{
GucAction action = stmt - > is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET ;
switch ( stmt - > kind )
switch ( stmt - > kind )
{
{
case VAR_SET_VALUE :
case VAR_SET_VALUE :
@ -4950,7 +4933,7 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
ExtractSetVariableArgs ( stmt ) ,
ExtractSetVariableArgs ( stmt ) ,
( superuser ( ) ? PGC_SUSET : PGC_USERSET ) ,
( superuser ( ) ? PGC_SUSET : PGC_USERSET ) ,
PGC_S_SESSION ,
PGC_S_SESSION ,
stmt - > is_local ,
action ,
true ) ;
true ) ;
break ;
break ;
case VAR_SET_MULTI :
case VAR_SET_MULTI :
@ -5006,7 +4989,7 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
NULL ,
NULL ,
( superuser ( ) ? PGC_SUSET : PGC_USERSET ) ,
( superuser ( ) ? PGC_SUSET : PGC_USERSET ) ,
PGC_S_SESSION ,
PGC_S_SESSION ,
stmt - > is_local ,
action ,
true ) ;
true ) ;
break ;
break ;
case VAR_RESET_ALL :
case VAR_RESET_ALL :
@ -5051,7 +5034,7 @@ SetPGVariable(const char *name, List *args, bool is_local)
argstring ,
argstring ,
( superuser ( ) ? PGC_SUSET : PGC_USERSET ) ,
( superuser ( ) ? PGC_SUSET : PGC_USERSET ) ,
PGC_S_SESSION ,
PGC_S_SESSION ,
is_local ,
is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET ,
true ) ;
true ) ;
}
}
@ -5095,7 +5078,7 @@ set_config_by_name(PG_FUNCTION_ARGS)
value ,
value ,
( superuser ( ) ? PGC_SUSET : PGC_USERSET ) ,
( superuser ( ) ? PGC_SUSET : PGC_USERSET ) ,
PGC_S_SESSION ,
PGC_S_SESSION ,
is_local ,
is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET ,
true ) ;
true ) ;
/* get the new current value */
/* get the new current value */
@ -5190,7 +5173,7 @@ define_custom_variable(struct config_generic *variable)
if ( value )
if ( value )
set_config_option ( name , value ,
set_config_option ( name , value ,
pHolder - > gen . context , pHolder - > gen . source ,
pHolder - > gen . context , pHolder - > gen . source ,
false , true ) ;
GUC_ACTION_SET , true ) ;
/*
/*
* Free up as much as we conveniently can of the placeholder structure
* Free up as much as we conveniently can of the placeholder structure
@ -5198,7 +5181,6 @@ define_custom_variable(struct config_generic *variable)
*/
*/
set_string_field ( pHolder , pHolder - > variable , NULL ) ;
set_string_field ( pHolder , pHolder - > variable , NULL ) ;
set_string_field ( pHolder , & pHolder - > reset_val , NULL ) ;
set_string_field ( pHolder , & pHolder - > reset_val , NULL ) ;
set_string_field ( pHolder , & pHolder - > tentative_val , NULL ) ;
free ( pHolder ) ;
free ( pHolder ) ;
}
}
@ -6145,7 +6127,7 @@ read_nondefault_variables(void)
elog ( FATAL , " invalid format of exec config params file " ) ;
elog ( FATAL , " invalid format of exec config params file " ) ;
( void ) set_config_option ( varname , varvalue , record - > context ,
( void ) set_config_option ( varname , varvalue , record - > context ,
varsource , false , true ) ;
varsource , GUC_ACTION_SET , true ) ;
free ( varname ) ;
free ( varname ) ;
free ( varvalue ) ;
free ( varvalue ) ;
}
}
@ -6196,13 +6178,13 @@ ParseLongOption(const char *string, char **name, char **value)
/*
/*
* Handle options fetched from pg_database . datconfig , pg_authid . rolconfig ,
* Handle options fetched from pg_database . datconfig , pg_authid . rolconfig ,
* pg_proc . proconfig , etc . Caller must specify proper context / source / local .
* pg_proc . proconfig , etc . Caller must specify proper context / source / action .
*
*
* The array parameter must be an array of TEXT ( it must not be NULL ) .
* The array parameter must be an array of TEXT ( it must not be NULL ) .
*/
*/
void
void
ProcessGUCArray ( ArrayType * array ,
ProcessGUCArray ( ArrayType * array ,
GucContext context , GucSource source , bool isLocal )
GucContext context , GucSource source , GucAction action )
{
{
int i ;
int i ;
@ -6242,7 +6224,7 @@ ProcessGUCArray(ArrayType *array,
continue ;
continue ;
}
}
( void ) set_config_option ( name , value , context , source , isLocal , true ) ;
( void ) set_config_option ( name , value , context , source , action , true ) ;
free ( name ) ;
free ( name ) ;
if ( value )
if ( value )
@ -6269,7 +6251,7 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value)
/* test if the option is valid */
/* test if the option is valid */
set_config_option ( name , value ,
set_config_option ( name , value ,
superuser ( ) ? PGC_SUSET : PGC_USERSET ,
superuser ( ) ? PGC_SUSET : PGC_USERSET ,
PGC_S_TEST , false , false ) ;
PGC_S_TEST , GUC_ACTION_SET , false ) ;
/* convert name to canonical spelling, so we can use plain strcmp */
/* convert name to canonical spelling, so we can use plain strcmp */
( void ) GetConfigOptionByName ( name , & varname ) ;
( void ) GetConfigOptionByName ( name , & varname ) ;
@ -6347,7 +6329,7 @@ GUCArrayDelete(ArrayType *array, const char *name)
/* test if the option is valid */
/* test if the option is valid */
set_config_option ( name , NULL ,
set_config_option ( name , NULL ,
superuser ( ) ? PGC_SUSET : PGC_USERSET ,
superuser ( ) ? PGC_SUSET : PGC_USERSET ,
PGC_S_TEST , false , false ) ;
PGC_S_TEST , GUC_ACTION_SET , false ) ;
/* convert name to canonical spelling, so we can use plain strcmp */
/* convert name to canonical spelling, so we can use plain strcmp */
( void ) GetConfigOptionByName ( name , & varname ) ;
( void ) GetConfigOptionByName ( name , & varname ) ;