variable.c

来自「PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统」· C语言 代码 · 共 830 行 · 第 1/2 页

C
830
字号
/*------------------------------------------------------------------------- * * variable.c *		Routines for handling specialized SET variables. * * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/commands/variable.c,v 1.114.2.2 2006/02/12 22:32:56 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <ctype.h>#include "access/xact.h"#include "catalog/pg_authid.h"#include "commands/variable.h"#include "miscadmin.h"#include "parser/scansup.h"#include "pgtime.h"#include "utils/acl.h"#include "utils/builtins.h"#include "utils/guc.h"#include "utils/syscache.h"#include "utils/tqual.h"#include "mb/pg_wchar.h"/* * DATESTYLE *//* * assign_datestyle: GUC assign_hook for datestyle */const char *assign_datestyle(const char *value, bool doit, GucSource source){	int			newDateStyle = DateStyle;	int			newDateOrder = DateOrder;	bool		have_style = false;	bool		have_order = false;	bool		ok = true;	char	   *rawstring;	char	   *result;	List	   *elemlist;	ListCell   *l;	/* Need a modifiable copy of string */	rawstring = pstrdup(value);	/* Parse string into list of identifiers */	if (!SplitIdentifierString(rawstring, ',', &elemlist))	{		/* syntax error in list */		pfree(rawstring);		list_free(elemlist);		if (source >= PGC_S_INTERACTIVE)			ereport(ERROR,					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("invalid list syntax for parameter \"datestyle\"")));		return NULL;	}	foreach(l, elemlist)	{		char	   *tok = (char *) lfirst(l);		/* Ugh. Somebody ought to write a table driven version -- mjl */		if (pg_strcasecmp(tok, "ISO") == 0)		{			if (have_style && newDateStyle != USE_ISO_DATES)				ok = false;		/* conflicting styles */			newDateStyle = USE_ISO_DATES;			have_style = true;		}		else if (pg_strcasecmp(tok, "SQL") == 0)		{			if (have_style && newDateStyle != USE_SQL_DATES)				ok = false;		/* conflicting styles */			newDateStyle = USE_SQL_DATES;			have_style = true;		}		else if (pg_strncasecmp(tok, "POSTGRES", 8) == 0)		{			if (have_style && newDateStyle != USE_POSTGRES_DATES)				ok = false;		/* conflicting styles */			newDateStyle = USE_POSTGRES_DATES;			have_style = true;		}		else if (pg_strcasecmp(tok, "GERMAN") == 0)		{			if (have_style && newDateStyle != USE_GERMAN_DATES)				ok = false;		/* conflicting styles */			newDateStyle = USE_GERMAN_DATES;			have_style = true;			/* GERMAN also sets DMY, unless explicitly overridden */			if (!have_order)				newDateOrder = DATEORDER_DMY;		}		else if (pg_strcasecmp(tok, "YMD") == 0)		{			if (have_order && newDateOrder != DATEORDER_YMD)				ok = false;		/* conflicting orders */			newDateOrder = DATEORDER_YMD;			have_order = true;		}		else if (pg_strcasecmp(tok, "DMY") == 0 ||				 pg_strncasecmp(tok, "EURO", 4) == 0)		{			if (have_order && newDateOrder != DATEORDER_DMY)				ok = false;		/* conflicting orders */			newDateOrder = DATEORDER_DMY;			have_order = true;		}		else if (pg_strcasecmp(tok, "MDY") == 0 ||				 pg_strcasecmp(tok, "US") == 0 ||				 pg_strncasecmp(tok, "NONEURO", 7) == 0)		{			if (have_order && newDateOrder != DATEORDER_MDY)				ok = false;		/* conflicting orders */			newDateOrder = DATEORDER_MDY;			have_order = true;		}		else if (pg_strcasecmp(tok, "DEFAULT") == 0)		{			/*			 * Easiest way to get the current DEFAULT state is to fetch the			 * DEFAULT string from guc.c and recursively parse it.			 *			 * We can't simply "return assign_datestyle(...)" because we need			 * to handle constructs like "DEFAULT, ISO".			 */			int			saveDateStyle = DateStyle;			int			saveDateOrder = DateOrder;			const char *subval;			subval = assign_datestyle(GetConfigOptionResetString("datestyle"),									  true, source);			if (!have_style)				newDateStyle = DateStyle;			if (!have_order)				newDateOrder = DateOrder;			DateStyle = saveDateStyle;			DateOrder = saveDateOrder;			if (!subval)			{				ok = false;				break;			}			/* Here we know that our own return value is always malloc'd */			/* when doit is true */			free((char *) subval);		}		else		{			if (source >= PGC_S_INTERACTIVE)				ereport(ERROR,						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),						 errmsg("unrecognized \"datestyle\" key word: \"%s\"",								tok)));			ok = false;			break;		}	}	pfree(rawstring);	list_free(elemlist);	if (!ok)	{		if (source >= PGC_S_INTERACTIVE)			ereport(ERROR,					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),					 errmsg("conflicting \"datestyle\" specifications")));		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(32);	if (!result)		return NULL;	switch (newDateStyle)	{		case USE_ISO_DATES:			strcpy(result, "ISO");			break;		case USE_SQL_DATES:			strcpy(result, "SQL");			break;		case USE_GERMAN_DATES:			strcpy(result, "German");			break;		default:			strcpy(result, "Postgres");			break;	}	switch (newDateOrder)	{		case DATEORDER_YMD:			strcat(result, ", YMD");			break;		case DATEORDER_DMY:			strcat(result, ", DMY");			break;		default:			strcat(result, ", MDY");			break;	}	/*	 * Finally, it's safe to assign to the global variables; the assignment	 * cannot fail now.	 */	DateStyle = newDateStyle;	DateOrder = newDateOrder;	return result;}/* * TIMEZONE *//* * assign_timezone: GUC assign_hook for timezone */const char *assign_timezone(const char *value, bool doit, GucSource source){	char	   *result;	char	   *endptr;	double		hours;	/*	 * Check for INTERVAL 'foo'	 */	if (pg_strncasecmp(value, "interval", 8) == 0)	{		const char *valueptr = value;		char	   *val;		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 (source >= PGC_S_INTERACTIVE)				ereport(ERROR,						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),						 errmsg("invalid interval value for time zone: month not allowed")));			pfree(interval);			return NULL;		}		if (interval->day != 0)		{			if (source >= PGC_S_INTERACTIVE)				ereport(ERROR,						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),						 errmsg("invalid interval value for time zone: day not allowed")));			pfree(interval);			return NULL;		}		if (doit)		{			/* Here we change from SQL to Unix sign convention */#ifdef HAVE_INT64_TIMESTAMP			CTimeZone = -(interval->time / USECS_PER_SEC);#else			CTimeZone = -interval->time;#endif			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 * SECS_PER_HOUR;				HasCTZSet = true;			}		}		else if (pg_strcasecmp(value, "UNKNOWN") == 0)		{			/*			 * UNKNOWN is the value shown as the "default" for TimeZone in			 * guc.c.  We interpret it as being a complete no-op; we don't			 * change the timezone setting.  Note that if there is a known			 * timezone setting, we will return that name rather than UNKNOWN			 * as the canonical spelling.			 *			 * During GUC initialization, since the timezone library isn't set			 * up yet, pg_get_timezone_name will return NULL and we will leave			 * the setting as UNKNOWN.	If this isn't overridden from the			 * config file then pg_timezone_initialize() will eventually			 * select a default value from the environment.			 */			if (doit)			{				const char *curzone = pg_get_timezone_name(global_timezone);				if (curzone)					value = curzone;			}		}		else		{			/*			 * Otherwise assume it is a timezone name, and try to load it.			 */			pg_tz	   *new_tz;			new_tz = pg_tzset(value);			if (!new_tz)			{				ereport((source >= PGC_S_INTERACTIVE) ? ERROR : LOG,						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),						 errmsg("unrecognized time zone name: \"%s\"",								value)));				return NULL;			}			if (!tz_acceptable(new_tz))			{				ereport((source >= PGC_S_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 (doit)			{				/* Save the changed TZ */				global_timezone = new_tz;				HasCTZSet = false;			}		}	}	/*	 * 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.	 */	if (HasCTZSet)	{		result = (char *) malloc(64);		if (!result)			return NULL;		snprintf(result, 64, "%.5f",				 (double) (-CTimeZone) / (double) SECS_PER_HOUR);	}	else		result = strdup(value);	return result;}

⌨️ 快捷键说明

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