Skip to content
Snippets Groups Projects
Select Git revision
  • benchmark-tools
  • postgres-lambda
  • master default
  • REL9_4_25
  • REL9_5_20
  • REL9_6_16
  • REL_10_11
  • REL_11_6
  • REL_12_1
  • REL_12_0
  • REL_12_RC1
  • REL_12_BETA4
  • REL9_4_24
  • REL9_5_19
  • REL9_6_15
  • REL_10_10
  • REL_11_5
  • REL_12_BETA3
  • REL9_4_23
  • REL9_5_18
  • REL9_6_14
  • REL_10_9
  • REL_11_4
23 results

variable.c

Blame
    • Tom Lane's avatar
      2938eec7
      Extend GUC concepts of parse_hook and assign_hook to all four supported · 2938eec7
      Tom Lane authored
      datatypes, not only strings.  parse_hook is useless for bool, I suppose,
      but it seems possibly useful for int and double to apply variable-specific
      constraints that are more complex than simple range limits.  assign_hook
      is definitely useful for all datatypes --- we need it right now for bool
      to support date cache reset when changing Australian timezone rule setting.
      Also, clean up some residual problems with the reset all/show all patch,
      including memory leaks and mistaken reset of PostPortNumber.  It seems
      best that RESET ALL not touch variables that don't have SUSET or
      USERSET context.
      2938eec7
      History
      Extend GUC concepts of parse_hook and assign_hook to all four supported
      Tom Lane authored
      datatypes, not only strings.  parse_hook is useless for bool, I suppose,
      but it seems possibly useful for int and double to apply variable-specific
      constraints that are more complex than simple range limits.  assign_hook
      is definitely useful for all datatypes --- we need it right now for bool
      to support date cache reset when changing Australian timezone rule setting.
      Also, clean up some residual problems with the reset all/show all patch,
      including memory leaks and mistaken reset of PostPortNumber.  It seems
      best that RESET ALL not touch variables that don't have SUSET or
      USERSET context.
    variable.c 17.24 KiB
    /*-------------------------------------------------------------------------
     *
     * variable.c
     *		Routines for handling of 'SET var TO',
     *		'SHOW var' and 'RESET var' statements.
     *
     * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
     * Portions Copyright (c) 1994, Regents of the University of California
     *
     *
     * IDENTIFICATION
     *	  $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.50 2001/06/12 22:54:05 tgl Exp $
     *
     *-------------------------------------------------------------------------
     */
    
    #include "postgres.h"
    
    #include <ctype.h>
    #include <time.h>
    
    #include "access/xact.h"
    #include "catalog/pg_shadow.h"
    #include "commands/variable.h"
    #include "miscadmin.h"
    #include "optimizer/cost.h"
    #include "optimizer/paths.h"
    #include "parser/parse_expr.h"
    #include "utils/builtins.h"
    #include "utils/guc.h"
    #include "utils/tqual.h"
    
    #ifdef MULTIBYTE
    #include "mb/pg_wchar.h"
    #else
    /* Grand unified hard-coded badness */
    #define pg_encoding_to_char(x) "SQL_ASCII"
    #define pg_get_client_encoding()  0
    #endif
    
    
    static bool show_datestyle(void);
    static bool reset_datestyle(void);
    static bool parse_datestyle(char *);
    static bool show_timezone(void);
    static bool reset_timezone(void);
    static bool parse_timezone(char *);
    
    static bool show_DefaultXactIsoLevel(void);
    static bool reset_DefaultXactIsoLevel(void);
    static bool parse_DefaultXactIsoLevel(char *);
    static bool show_XactIsoLevel(void);
    static bool reset_XactIsoLevel(void);
    static bool parse_XactIsoLevel(char *);
    static bool parse_random_seed(char *);
    static bool show_random_seed(void);
    static bool reset_random_seed(void);
    
    static bool show_client_encoding(void);
    static bool reset_client_encoding(void);
    static bool parse_client_encoding(char *);
    static bool show_server_encoding(void);
    static bool reset_server_encoding(void);
    static bool parse_server_encoding(char *);
    
    
    /*
     * get_token
     *		Obtain the next item in a comma-separated list of items,
     *		where each item can be either "word" or "word=word".
     *		The "word=word" form is only accepted if 'val' is not NULL.
     *		Words are any sequences not containing whitespace, ',', or '='.
     *		Whitespace can appear between the words and punctuation.
     *
     * 'tok': receives a pointer to first word of item, or NULL if none.
     * 'val': if not NULL, receives a pointer to second word, or NULL if none.
     * 'str': start of input string.
     *
     * Returns NULL if input string contained no more words, else pointer
     * to just past this item, which can be used as 'str' for next call.
     * (If this is the last item, returned pointer will point at a null char,
     * so caller can alternatively check for that instead of calling again.)
     *
     * NB: input string is destructively modified by placing null characters
     * at ends of words!
     *
     * A former version of this code avoided modifying the input string by
     * returning palloc'd copies of the words.  However, we want to use this
     * code early in backend startup to parse the PGDATESTYLE environment var,
     * and palloc/pfree aren't initialized at that point.  Cleanest answer
     * seems to be to palloc in SetPGVariable() so that we can treat the string
     * as modifiable here.
     */
    static char *
    get_token(char **tok, char **val, char *str)
    {
    	char		ch;
    
    	*tok = NULL;
    	if (val != NULL)
    		*val = NULL;
    
    	if (!str || *str == '\0')
    		return NULL;
    
    	/* skip leading white space */
    	while (isspace((unsigned char) *str))
    		str++;
    
    	/* end of string? then return NULL */
    	if (*str == '\0')
    		return NULL;
    
    	if (*str == ',' || *str == '=')
    		elog(ERROR, "Syntax error near \"%s\": empty setting", str);
    
    	/* OK, at beginning of non-empty item */
    	*tok = str;
    
    	/* Advance to end of word */
    	while (*str && !isspace((unsigned char) *str) &&
    		   *str != ',' && *str != '=')
    		str++;
    
    	/* Terminate word string for caller */
    	ch = *str;
    	*str = '\0';
    
    	/* Skip any whitespace */
    	while (isspace((unsigned char) ch))
    		ch = *(++str);
    
    	/* end of string? */
    	if (ch == '\0')
    		return str;
    	/* delimiter? */
    	if (ch == ',')
    		return ++str;
    
    	/* Had better be '=', and caller must be expecting it */
    	if (val == NULL || ch != '=')
    		elog(ERROR, "Syntax error near \"%s\"", str);
    
    	/* '=': get the value */
    	str++;
    
    	/* skip whitespace after '=' */
    	while (isspace((unsigned char) *str))
    		str++;
    
    	if (*str == ',' || *str == '\0')
    		elog(ERROR, "Syntax error near \"=%s\"", str);
    
    	/* OK, at beginning of non-empty value */
    	*val = str;
    
    	/* Advance to end of word */
    	while (*str && !isspace((unsigned char) *str) && *str != ',')
    		str++;
    
    	/* Terminate word string for caller */
    	ch = *str;
    	*str = '\0';
    
    	/* Skip any whitespace */
    	while (isspace((unsigned char) ch))
    		ch = *(++str);
    
    	/* end of string? */
    	if (ch == '\0')
    		return str;
    	/* delimiter? */
    	if (ch == ',')
    		return ++str;
    
    	elog(ERROR, "Syntax error near \"%s\"", str);
    
    	return str;
    }
    
    
    /*
     * DATE_STYLE
     *
     * NOTE: set_default_datestyle() is called during backend startup to check
     * if the PGDATESTYLE environment variable is set.	We want the env var
     * to determine the value that "RESET DateStyle" will reset to!
     */
    
    /* These get initialized from the "master" values in init/globals.c */
    static int	DefaultDateStyle;
    static bool DefaultEuroDates;
    
    static bool
    parse_datestyle(char *value)
    {
    	char	   *tok;
    	int			dcnt = 0,
    				ecnt = 0;
    
    	if (value == NULL)
    	{
    		reset_datestyle();
    		return TRUE;
    	}
    
    	while ((value = get_token(&tok, NULL, value)) != 0)
    	{
    		/* Ugh. Somebody ought to write a table driven version -- mjl */
    
    		if (!strcasecmp(tok, "ISO"))
    		{
    			DateStyle = USE_ISO_DATES;
    			dcnt++;
    		}
    		else if (!strcasecmp(tok, "SQL"))
    		{
    			DateStyle = USE_SQL_DATES;
    			dcnt++;
    		}
    		else if (!strcasecmp(tok, "POSTGRES"))
    		{
    			DateStyle = USE_POSTGRES_DATES;
    			dcnt++;
    		}
    		else if (!strcasecmp(tok, "GERMAN"))
    		{
    			DateStyle = USE_GERMAN_DATES;
    			dcnt++;
    			EuroDates = TRUE;
    			if ((ecnt > 0) && (!EuroDates))
    				ecnt++;
    		}
    		else if (!strncasecmp(tok, "EURO", 4))
    		{
    			EuroDates = TRUE;
    			if ((dcnt <= 0) || (DateStyle != USE_GERMAN_DATES))
    				ecnt++;
    		}
    		else if ((!strcasecmp(tok, "US"))
    				 || (!strncasecmp(tok, "NONEURO", 7)))
    		{
    			EuroDates = FALSE;
    			if ((dcnt <= 0) || (DateStyle == USE_GERMAN_DATES))
    				ecnt++;
    		}
    		else if (!strcasecmp(tok, "DEFAULT"))
    		{
    			DateStyle = DefaultDateStyle;
    			EuroDates = DefaultEuroDates;
    			ecnt++;
    		}
    		else
    			elog(ERROR, "Bad value for date style (%s)", tok);
    	}
    
    	if (dcnt > 1 || ecnt > 1)
    		elog(NOTICE, "Conflicting settings for date");
    
    	return TRUE;
    }
    
    static bool
    show_datestyle(void)
    {
    	char		buf[64];
    
    	strcpy(buf, "DateStyle is ");
    	switch (DateStyle)
    	{
    		case USE_ISO_DATES:
    			strcat(buf, "ISO");
    			break;
    		case USE_SQL_DATES:
    			strcat(buf, "SQL");
    			break;
    		case USE_GERMAN_DATES:
    			strcat(buf, "German");
    			break;
    		default:
    			strcat(buf, "Postgres");
    			break;
    	};
    	strcat(buf, " with ");
    	strcat(buf, ((EuroDates) ? "European" : "US (NonEuropean)"));
    	strcat(buf, " conventions");
    
    	elog(NOTICE, buf, NULL);
    
    	return TRUE;
    }
    
    static bool
    reset_datestyle(void)
    {
    	DateStyle = DefaultDateStyle;
    	EuroDates = DefaultEuroDates;
    
    	return TRUE;
    }
    
    void
    set_default_datestyle(void)
    {
    	char	   *DBDate;
    
    	/*
    	 * Initialize from compile-time defaults in init/globals.c. NB: this
    	 * is a necessary step; consider PGDATESTYLE="DEFAULT".
    	 */
    	DefaultDateStyle = DateStyle;
    	DefaultEuroDates = EuroDates;
    
    	/* If the environment var is set, override compiled-in values */
    	DBDate = getenv("PGDATESTYLE");
    	if (DBDate == NULL)
    		return;
    
    	/*
    	 * Make a modifiable copy --- overwriting the env var doesn't seem
    	 * like a good idea, even though we currently won't look at it again.
    	 * Note that we cannot use palloc at this early stage of
    	 * initialization.
    	 */
    	DBDate = strdup(DBDate);
    
    	/* Parse desired setting into DateStyle/EuroDates */
    	parse_datestyle(DBDate);
    
    	free(DBDate);
    
    	/* And make it the default for future RESETs */
    	DefaultDateStyle = DateStyle;
    	DefaultEuroDates = EuroDates;
    }
    
    
    /* Timezone support
     * Working storage for strings is allocated with an arbitrary size of 64 bytes.
     */
    
    static char *defaultTZ = NULL;
    static char TZvalue[64];
    static char tzbuf[64];
    
    /*
     *
     * TIMEZONE
     *
     */
    /* parse_timezone()
     * Handle SET TIME ZONE...
     * Try to save existing TZ environment variable for later use in RESET TIME ZONE.
     * - thomas 1997-11-10
     */
    static bool
    parse_timezone(char *value)
    {
    	char	   *tok;
    
    	if (value == NULL)
    	{
    		reset_timezone();
    		return TRUE;
    	}
    
    	while ((value = get_token(&tok, NULL, value)) != 0)
    	{
    		/* Not yet tried to save original value from environment? */
    		if (defaultTZ == NULL)
    		{
    			/* found something? then save it for later */
    			if ((defaultTZ = getenv("TZ")) != NULL)
    				strcpy(TZvalue, defaultTZ);
    
    			/* found nothing so mark with an invalid pointer */
    			else
    				defaultTZ = (char *) -1;
    		}
    
    		strcpy(tzbuf, "TZ=");
    		strcat(tzbuf, tok);
    		if (putenv(tzbuf) != 0)
    			elog(ERROR, "Unable to set TZ environment variable to %s", tok);
    
    		tzset();
    	}
    
    	return TRUE;
    }	/* parse_timezone() */
    
    static bool
    show_timezone(void)
    {
    	char	   *tz;
    
    	tz = getenv("TZ");
    
    	elog(NOTICE, "Time zone is %s", ((tz != NULL) ? tz : "unset"));
    
    	return TRUE;
    }	/* show_timezone() */
    
    /* reset_timezone()
     * Set TZ environment variable to original value.
     * Note that if TZ was originally not set, TZ should be cleared.
     * unsetenv() works fine, but is BSD, not POSIX, and is not available
     * under Solaris, among others. Apparently putenv() called as below
     * clears the process-specific environment variables.
     * Other reasonable arguments to putenv() (e.g. "TZ=", "TZ", "") result
     * in a core dump (under Linux anyway).
     * - thomas 1998-01-26
     */
    static bool
    reset_timezone(void)
    {
    	/* no time zone has been set in this session? */
    	if (defaultTZ == NULL)
    	{
    	}
    
    	/* time zone was set and original explicit time zone available? */
    	else if (defaultTZ != (char *) -1)
    	{
    		strcpy(tzbuf, "TZ=");
    		strcat(tzbuf, TZvalue);
    		if (putenv(tzbuf) != 0)
    			elog(ERROR, "Unable to set TZ environment variable to %s", TZvalue);
    		tzset();
    	}
    
    	/*
    	 * otherwise, time zone was set but no original explicit time zone
    	 * available
    	 */
    	else
    	{
    		strcpy(tzbuf, "=");
    		if (putenv(tzbuf) != 0)
    			elog(ERROR, "Unable to clear TZ environment variable");
    		tzset();
    	}
    
    	return TRUE;
    }	/* reset_timezone() */
    
    
    
    /* SET TRANSACTION */
    
    static bool
    parse_DefaultXactIsoLevel(char *value)
    {
    #if 0
    	TransactionState s = CurrentTransactionState;
    
    #endif
    
    	if (value == NULL)
    	{
    		reset_DefaultXactIsoLevel();
    		return TRUE;
    	}
    
    #if 0
    	if (s->state != TRANS_DEFAULT)
    	{
    		elog(ERROR, "ALTER SESSION/SET TRANSACTION ISOLATION LEVEL"
    			 " can not be called within a transaction");
    		return TRUE;
    	}
    #endif
    
    	if (strcasecmp(value, "SERIALIZABLE") == 0)
    		DefaultXactIsoLevel = XACT_SERIALIZABLE;
    	else if (strcasecmp(value, "COMMITTED") == 0)
    		DefaultXactIsoLevel = XACT_READ_COMMITTED;
    	else
    		elog(ERROR, "Bad TRANSACTION ISOLATION LEVEL (%s)", value);
    
    	return TRUE;
    }
    
    static bool
    show_DefaultXactIsoLevel(void)
    {
    
    	if (DefaultXactIsoLevel == XACT_SERIALIZABLE)
    		elog(NOTICE, "Default TRANSACTION ISOLATION LEVEL is SERIALIZABLE");
    	else
    		elog(NOTICE, "Default TRANSACTION ISOLATION LEVEL is READ COMMITTED");
    	return TRUE;
    }
    
    static bool
    reset_DefaultXactIsoLevel(void)
    {
    #if 0
    	TransactionState s = CurrentTransactionState;
    
    	if (s->state != TRANS_DEFAULT)
    	{
    		elog(ERROR, "ALTER SESSION/SET TRANSACTION ISOLATION LEVEL"
    			 " can not be called within a transaction");
    		return TRUE;
    	}
    #endif
    
    	DefaultXactIsoLevel = XACT_READ_COMMITTED;
    
    	return TRUE;
    }
    
    static bool
    parse_XactIsoLevel(char *value)
    {
    
    	if (value == NULL)
    	{
    		reset_XactIsoLevel();
    		return TRUE;
    	}
    
    	if (SerializableSnapshot != NULL)
    	{
    		elog(ERROR, "SET TRANSACTION ISOLATION LEVEL must be called before any query");
    		return TRUE;
    	}
    
    
    	if (strcasecmp(value, "SERIALIZABLE") == 0)
    		XactIsoLevel = XACT_SERIALIZABLE;
    	else if (strcasecmp(value, "COMMITTED") == 0)
    		XactIsoLevel = XACT_READ_COMMITTED;
    	else
    		elog(ERROR, "Bad TRANSACTION ISOLATION LEVEL (%s)", value);
    
    	return TRUE;
    }
    
    static bool
    show_XactIsoLevel(void)
    {
    
    	if (XactIsoLevel == XACT_SERIALIZABLE)
    		elog(NOTICE, "TRANSACTION ISOLATION LEVEL is SERIALIZABLE");
    	else
    		elog(NOTICE, "TRANSACTION ISOLATION LEVEL is READ COMMITTED");
    	return TRUE;
    }
    
    static bool
    reset_XactIsoLevel(void)
    {
    
    	if (SerializableSnapshot != NULL)
    	{
    		elog(ERROR, "SET TRANSACTION ISOLATION LEVEL must be called before any query");
    		return TRUE;
    	}
    
    	XactIsoLevel = DefaultXactIsoLevel;
    
    	return TRUE;
    }
    
    
    /*
     * Random number seed
     */
    static bool
    parse_random_seed(char *value)
    {
    	double		seed = 0;
    
    	if (value == NULL)
    		reset_random_seed();
    	else
    	{
    		sscanf(value, "%lf", &seed);
    		DirectFunctionCall1(setseed, Float8GetDatum(seed));
    	}
    	return (TRUE);
    }
    
    static bool
    show_random_seed(void)
    {
    	elog(NOTICE, "Seed for random number generator is unavailable");
    	return (TRUE);
    }
    
    static bool
    reset_random_seed(void)
    {
    	double		seed = 0.5;
    
    	DirectFunctionCall1(setseed, Float8GetDatum(seed));
    	return (TRUE);
    }
    
    
    /*
     * MULTIBYTE-related functions
     *
     * If MULTIBYTE support was not compiled, we still allow these variables
     * to exist, but you can't set them to anything but "SQL_ASCII".  This
     * minimizes interoperability problems between non-MB servers and MB-enabled
     * clients.
     */
    
    static bool
    parse_client_encoding(char *value)
    {
    #ifdef MULTIBYTE
    	int			encoding;
    
    	encoding = pg_valid_client_encoding(value);
    	if (encoding < 0)
    	{
    		if (value)
    			elog(ERROR, "Client encoding %s is not supported", value);
    		else
    			elog(ERROR, "No client encoding is specified");
    	}
    	else
    	{
    		if (pg_set_client_encoding(encoding))
    		{
    			elog(ERROR, "Conversion between %s and %s is not supported",
    				 value, pg_encoding_to_char(GetDatabaseEncoding()));
    		}
    	}
    #else
    	if (value &&
    	strcasecmp(value, pg_encoding_to_char(pg_get_client_encoding())) != 0)
    		elog(ERROR, "Client encoding %s is not supported", value);
    #endif
    	return TRUE;
    }
    
    static bool
    show_client_encoding(void)
    {
    	elog(NOTICE, "Current client encoding is %s",
    		 pg_encoding_to_char(pg_get_client_encoding()));
    	return TRUE;
    }
    
    static bool
    reset_client_encoding(void)
    {
    #ifdef MULTIBYTE
    	int			encoding;
    	char	   *env = getenv("PGCLIENTENCODING");
    
    	if (env)
    	{
    		encoding = pg_char_to_encoding(env);
    		if (encoding < 0)
    			encoding = GetDatabaseEncoding();
    	}
    	else
    		encoding = GetDatabaseEncoding();
    	pg_set_client_encoding(encoding);
    #endif
    	return TRUE;
    }
    
    /* Called during MULTIBYTE backend startup ... */
    void
    set_default_client_encoding(void)
    {
    	reset_client_encoding();
    }
    
    
    static bool
    parse_server_encoding(char *value)
    {
    	elog(NOTICE, "SET SERVER_ENCODING is not supported");
    	return TRUE;
    }
    
    static bool
    show_server_encoding(void)
    {
    	elog(NOTICE, "Current server encoding is %s",
    		 pg_encoding_to_char(GetDatabaseEncoding()));
    	return TRUE;
    }
    
    static bool
    reset_server_encoding(void)
    {
    	elog(NOTICE, "RESET SERVER_ENCODING is not supported");
    	return TRUE;
    }
    
    
    
    void
    SetPGVariable(const char *name, const char *value)
    {
    	char	   *mvalue = value ? pstrdup(value) : ((char *) NULL);
    
    	/*
    	 * Special cases ought to be removed and handled separately by TCOP
    	 */
    	if (strcasecmp(name, "datestyle") == 0)
    		parse_datestyle(mvalue);
    	else if (strcasecmp(name, "timezone") == 0)
    		parse_timezone(mvalue);
    	else if (strcasecmp(name, "DefaultXactIsoLevel") == 0)
    		parse_DefaultXactIsoLevel(mvalue);
    	else if (strcasecmp(name, "XactIsoLevel") == 0)
    		parse_XactIsoLevel(mvalue);
    	else if (strcasecmp(name, "client_encoding") == 0)
    		parse_client_encoding(mvalue);
    	else if (strcasecmp(name, "server_encoding") == 0)
    		parse_server_encoding(mvalue);
    	else if (strcasecmp(name, "seed") == 0)
    		parse_random_seed(mvalue);
    	else if (strcasecmp(name, "session_authorization") == 0)
    		SetSessionAuthorization(value);
    	else
    		SetConfigOption(name, value, superuser() ? PGC_SUSET : PGC_USERSET, false);
    
    	if (mvalue)
    		pfree(mvalue);
    }
    
    void
    GetPGVariable(const char *name)
    {
    	if (strcasecmp(name, "datestyle") == 0)
    		show_datestyle();
    	else if (strcasecmp(name, "timezone") == 0)
    		show_timezone();
    	else if (strcasecmp(name, "DefaultXactIsoLevel") == 0)
    		show_DefaultXactIsoLevel();
    	else if (strcasecmp(name, "XactIsoLevel") == 0)
    		show_XactIsoLevel();
    	else if (strcasecmp(name, "client_encoding") == 0)
    		show_client_encoding();
    	else if (strcasecmp(name, "server_encoding") == 0)
    		show_server_encoding();
    	else if (strcasecmp(name, "seed") == 0)
    		show_random_seed();
    	else if (strcasecmp(name, "all") == 0)
    	{
    		ShowAllGUCConfig();
    		show_datestyle();
    		show_timezone();
    		show_DefaultXactIsoLevel();
    		show_XactIsoLevel();
    		show_client_encoding();
    		show_server_encoding();
    		show_random_seed();
    	} else
    	{
    		const char *val = GetConfigOption(name);
    
    		elog(NOTICE, "%s is %s", name, val);
    	}
    }
    
    void
    ResetPGVariable(const char *name)
    {
    	if (strcasecmp(name, "datestyle") == 0)
    		reset_datestyle();
    	else if (strcasecmp(name, "timezone") == 0)
    		reset_timezone();
    	else if (strcasecmp(name, "DefaultXactIsoLevel") == 0)
    		reset_DefaultXactIsoLevel();
    	else if (strcasecmp(name, "XactIsoLevel") == 0)
    		reset_XactIsoLevel();
    	else if (strcasecmp(name, "client_encoding") == 0)
    		reset_client_encoding();
    	else if (strcasecmp(name, "server_encoding") == 0)
    		reset_server_encoding();
    	else if (strcasecmp(name, "seed") == 0)
    		reset_random_seed();
    	else if (strcasecmp(name, "all") == 0)
    	{
    		reset_DefaultXactIsoLevel();
    		reset_XactIsoLevel();
    		reset_random_seed();
    		/* reset_server_encoding(); */
    		reset_client_encoding();
    		reset_datestyle();
    		reset_timezone();
    
    		ResetAllOptions(false);
    	} else
    		SetConfigOption(name, NULL,
    						superuser() ? PGC_SUSET : PGC_USERSET,
    						false);
    }