variable.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 832 行 · 第 1/2 页

C
832
字号
		Interval   *interval;		valueptr += 8;		while (isspace((unsigned char) *valueptr))			valueptr++;		if (*valueptr++ != '\'')			return NULL;		val = pstrdup(valueptr);		/* Check and remove trailing quote */		endptr = strchr(val, '\'');		if (!endptr || endptr[1] != '\0')		{			pfree(val);			return NULL;		}		*endptr = '\0';		/*		 * Try to parse it.  XXX an invalid interval format will result in		 * ereport, which is not desirable for GUC.  We did what we could		 * to guard against this in flatten_set_variable_args, but a		 * string coming in from postgresql.conf might contain anything.		 */		interval = DatumGetIntervalP(DirectFunctionCall3(interval_in,													CStringGetDatum(val),											ObjectIdGetDatum(InvalidOid),													 Int32GetDatum(-1)));		pfree(val);		if (interval->month != 0)		{			if (interactive)				ereport(ERROR,						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),						 errmsg("invalid interval value for time zone: month not allowed")));			pfree(interval);			return NULL;		}		if (doit)		{			/* Here we change from SQL to Unix sign convention */			CTimeZone = -interval->time;			HasCTZSet = true;		}		pfree(interval);	}	else	{		/*		 * Try it as a numeric number of hours (possibly fractional).		 */		hours = strtod(value, &endptr);		if (endptr != value && *endptr == '\0')		{			if (doit)			{				/* Here we change from SQL to Unix sign convention */				CTimeZone = -hours * 3600;				HasCTZSet = true;			}		}		else if (strcasecmp(value, "UNKNOWN") == 0)		{			/*			 * UNKNOWN is the value shown as the "default" for TimeZone in			 * guc.c.  We interpret it as meaning the original TZ			 * inherited from the environment.	Note that if there is an			 * original TZ setting, we will return that rather than			 * UNKNOWN as the canonical spelling.			 */			if (doit)			{				bool		ok;				/* Revert to original setting of TZ, whatever it was */				if (orig_tzbuf[0])				{					set_tz(orig_tzbuf);					ok = tzset_succeeded(orig_tzbuf) && tz_acceptable();				}				else				{					clear_tz();					ok = tz_acceptable();				}				if (ok)					HasCTZSet = false;				else				{					/* Bogus, so force UTC (equivalent to INTERVAL 0) */					CTimeZone = 0;					HasCTZSet = true;				}			}		}		else		{			/*			 * Otherwise assume it is a timezone name.			 *			 * We have to actually apply the change before we can have any			 * hope of checking it.  So, save the old value in case we			 * have to back out.  Note that it's possible the old setting			 * is in tzbuf, so we'd better copy it.			 */			char		save_tzbuf[TZBUF_LEN];			char	   *save_tz;			bool		known,						acceptable;			save_tz = getenv("TZ");			if (save_tz)				StrNCpy(save_tzbuf, save_tz, sizeof(save_tzbuf));			set_tz(value);			known = tzset_succeeded(value);			acceptable = tz_acceptable();			if (doit && known && acceptable)			{				/* Keep the changed TZ */				HasCTZSet = false;			}			else			{				/*				 * Revert to prior TZ setting; note we haven't changed				 * HasCTZSet in this path, so if we were previously using				 * a fixed offset, we still are.				 */				if (save_tz)					set_tz(save_tzbuf);				else					clear_tz();				/* Complain if it was bad */				if (!known)				{					ereport(interactive ? ERROR : LOG,							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),							 errmsg("unrecognized time zone name: \"%s\"",									value)));					return NULL;				}				if (!acceptable)				{					ereport(interactive ? ERROR : LOG,							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),					errmsg("time zone \"%s\" appears to use leap seconds",						   value),							 errdetail("PostgreSQL does not support leap seconds.")));					return NULL;				}			}		}	}	/*	 * If we aren't going to do the assignment, just return OK indicator.	 */	if (!doit)		return value;	/*	 * Prepare the canonical string to return.	GUC wants it malloc'd.	 */	result = (char *) malloc(sizeof(tzbuf));	if (!result)		return NULL;	if (HasCTZSet)		snprintf(result, sizeof(tzbuf), "%.5f",				 (double) (-CTimeZone) / 3600.0);	else if (tzbuf[0] == 'T')		strcpy(result, tzbuf + 3);	else		strcpy(result, "UNKNOWN");	return result;}/* * show_timezone: GUC show_hook for timezone */const char *show_timezone(void){	char	   *tzn;	if (HasCTZSet)	{		Interval	interval;		interval.month = 0;		interval.time = -CTimeZone;		tzn = DatumGetCString(DirectFunctionCall1(interval_out,										  IntervalPGetDatum(&interval)));	}	else		tzn = getenv("TZ");	if (tzn != NULL)		return tzn;	return "unknown";}/* * SET TRANSACTION ISOLATION LEVEL */const char *assign_XactIsoLevel(const char *value, bool doit, bool interactive){	if (doit && interactive && SerializableSnapshot != NULL)		ereport(ERROR,				(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),				 errmsg("SET TRANSACTION ISOLATION LEVEL must be called before any query")));	if (strcmp(value, "serializable") == 0)	{		if (doit)			XactIsoLevel = XACT_SERIALIZABLE;	}	else if (strcmp(value, "read committed") == 0)	{		if (doit)			XactIsoLevel = XACT_READ_COMMITTED;	}	else if (strcmp(value, "default") == 0)	{		if (doit)			XactIsoLevel = DefaultXactIsoLevel;	}	else		return NULL;	return value;}const char *show_XactIsoLevel(void){	if (XactIsoLevel == XACT_SERIALIZABLE)		return "serializable";	else		return "read committed";}/* * Random number seed */boolassign_random_seed(double value, bool doit, bool interactive){	/* Can't really roll back on error, so ignore non-interactive setting */	if (doit && interactive)		DirectFunctionCall1(setseed, Float8GetDatum(value));	return true;}const char *show_random_seed(void){	return "unavailable";}/* * encoding handling functions */const char *assign_client_encoding(const char *value, bool doit, bool interactive){	int			encoding;	encoding = pg_valid_client_encoding(value);	if (encoding < 0)		return NULL;	/*	 * Note: if we are in startup phase then SetClientEncoding may not be	 * able to really set the encoding.  In this case we will assume that	 * the encoding is okay, and InitializeClientEncoding() will fix	 * things once initialization is complete.	 */	if (SetClientEncoding(encoding, doit) < 0)	{		if (interactive)			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				  errmsg("conversion between %s and %s is not supported",						 value, GetDatabaseEncodingName())));		return NULL;	}	return value;}/* * SET SESSION AUTHORIZATION * * When resetting session auth after an error, we can't expect to do catalog * lookups.  Hence, the stored form of the value must provide a numeric userid * that can be re-used directly.  We store the string in the form of * NAMEDATALEN 'x's, followed by T or F to indicate superuserness, followed * by the numeric userid, followed by a comma, followed by the user name. * This cannot be confused with a plain user name because of the NAMEDATALEN * limit on names, so we can tell whether we're being passed an initial * username or a saved/restored value. */extern char *session_authorization_string; /* in guc.c */const char *assign_session_authorization(const char *value, bool doit, bool interactive){	AclId		usesysid = 0;	bool		is_superuser = false;	const char *actual_username = NULL;	char	   *result;	if (strspn(value, "x") == NAMEDATALEN &&		(value[NAMEDATALEN] == 'T' || value[NAMEDATALEN] == 'F'))	{		/* might be a saved userid string */		AclId		savedsysid;		char	   *endptr;		savedsysid = (AclId) strtoul(value + NAMEDATALEN + 1, &endptr, 10);		if (endptr != value + NAMEDATALEN + 1 && *endptr == ',')		{			/* syntactically valid, so break out the data */			usesysid = savedsysid;			is_superuser = (value[NAMEDATALEN] == 'T');			actual_username = endptr + 1;		}	}	if (usesysid == 0)	{		/* not a saved ID, so look it up */		HeapTuple	userTup;		if (!IsTransactionState())		{			/*			 * Can't do catalog lookups, so fail.  The upshot of this is			 * that session_authorization cannot be set in			 * postgresql.conf, which seems like a good thing anyway.			 */			return NULL;		}		userTup = SearchSysCache(SHADOWNAME,								 PointerGetDatum(value),								 0, 0, 0);		if (!HeapTupleIsValid(userTup))		{			if (interactive)				ereport(ERROR,						(errcode(ERRCODE_UNDEFINED_OBJECT),						 errmsg("user \"%s\" does not exist", value)));			return NULL;		}		usesysid = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;		is_superuser = ((Form_pg_shadow) GETSTRUCT(userTup))->usesuper;		actual_username = value;		ReleaseSysCache(userTup);	}	if (doit)		SetSessionAuthorization(usesysid, is_superuser);	result = (char *) malloc(NAMEDATALEN + 32 + strlen(actual_username));	if (!result)		return NULL;	memset(result, 'x', NAMEDATALEN);	sprintf(result + NAMEDATALEN, "%c%lu,%s",			is_superuser ? 'T' : 'F',			(unsigned long) usesysid,			actual_username);	return result;}const char *show_session_authorization(void){	/*	 * Extract the user name from the stored string; see	 * assign_session_authorization	 */	const char *value = session_authorization_string;	AclId		savedsysid;	char	   *endptr;	Assert(strspn(value, "x") == NAMEDATALEN &&		   (value[NAMEDATALEN] == 'T' || value[NAMEDATALEN] == 'F'));	savedsysid = (AclId) strtoul(value + NAMEDATALEN + 1, &endptr, 10);	Assert(endptr != value + NAMEDATALEN + 1 && *endptr == ',');	return endptr + 1;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?