diff options
Diffstat (limited to 'src/backend/commands/variable.c')
-rw-r--r-- | src/backend/commands/variable.c | 587 |
1 files changed, 0 insertions, 587 deletions
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c deleted file mode 100644 index 70e7e88d60c..00000000000 --- a/src/backend/commands/variable.c +++ /dev/null @@ -1,587 +0,0 @@ -/*------------------------------------------------------------------------- - * - * variable.c - * Routines for handling specialized SET variables. - * - * - * Portions Copyright (c) 1996-2002, 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.69 2002/06/20 20:29:27 momjian 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 "utils/builtins.h" -#include "utils/guc.h" -#include "utils/syscache.h" -#include "utils/tqual.h" - -#ifdef MULTIBYTE -#include "mb/pg_wchar.h" -#else -/* Grand unified hard-coded badness */ -#define pg_get_client_encoding_name() "SQL_ASCII" -#define GetDatabaseEncodingName() "SQL_ASCII" -#endif - - -/* - * DATESTYLE - */ - -/* - * assign_datestyle: GUC assign_hook for datestyle - */ -const char * -assign_datestyle(const char *value, bool doit, bool interactive) -{ - int newDateStyle = DateStyle; - bool newEuroDates = EuroDates; - bool ok = true; - int dcnt = 0, - ecnt = 0; - char *rawstring; - char *result; - List *elemlist; - List *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); - freeList(elemlist); - if (interactive) - elog(ERROR, "SET DATESTYLE: invalid list syntax"); - return NULL; - } - - foreach(l, elemlist) - { - char *tok = (char *) lfirst(l); - - /* Ugh. Somebody ought to write a table driven version -- mjl */ - - if (strcasecmp(tok, "ISO") == 0) - { - newDateStyle = USE_ISO_DATES; - dcnt++; - } - else if (strcasecmp(tok, "SQL") == 0) - { - newDateStyle = USE_SQL_DATES; - dcnt++; - } - else if (strncasecmp(tok, "POSTGRESQL", 8) == 0) - { - newDateStyle = USE_POSTGRES_DATES; - dcnt++; - } - else if (strcasecmp(tok, "GERMAN") == 0) - { - newDateStyle = USE_GERMAN_DATES; - dcnt++; - if ((ecnt > 0) && (!newEuroDates)) - ok = false; - newEuroDates = TRUE; - } - else if (strncasecmp(tok, "EURO", 4) == 0) - { - newEuroDates = TRUE; - ecnt++; - } - else if (strcasecmp(tok, "US") == 0 - || strncasecmp(tok, "NONEURO", 7) == 0) - { - newEuroDates = FALSE; - ecnt++; - if ((dcnt > 0) && (newDateStyle == USE_GERMAN_DATES)) - ok = false; - } - else if (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; - bool saveEuroDates = EuroDates; - const char *subval; - - subval = assign_datestyle(GetConfigOptionResetString("datestyle"), - true, interactive); - newDateStyle = DateStyle; - newEuroDates = EuroDates; - DateStyle = saveDateStyle; - EuroDates = saveEuroDates; - if (!subval) - { - ok = false; - break; - } - /* Here we know that our own return value is always malloc'd */ - /* when doit is true */ - free((char *) subval); - dcnt++; - ecnt++; - } - else - { - if (interactive) - elog(ERROR, "SET DATESTYLE: unrecognized keyword %s", tok); - ok = false; - break; - } - } - - if (dcnt > 1 || ecnt > 1) - ok = false; - - pfree(rawstring); - freeList(elemlist); - - if (!ok) - { - if (interactive) - elog(ERROR, "SET DATESTYLE: conflicting 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, "POSTGRESQL"); - break; - } - strcat(result, newEuroDates ? ", EURO" : ", US"); - - /* - * Finally, it's safe to assign to the global variables; - * the assignment cannot fail now. - */ - DateStyle = newDateStyle; - EuroDates = newEuroDates; - - return result; -} - -/* - * show_datestyle: GUC show_hook for datestyle - */ -const char * -show_datestyle(void) -{ - static char buf[64]; - - switch (DateStyle) - { - case USE_ISO_DATES: - strcpy(buf, "ISO"); - break; - case USE_SQL_DATES: - strcpy(buf, "SQL"); - break; - case USE_GERMAN_DATES: - strcpy(buf, "German"); - break; - default: - strcpy(buf, "Postgres"); - break; - }; - strcat(buf, " with "); - strcat(buf, ((EuroDates) ? "European" : "US (NonEuropean)")); - strcat(buf, " conventions"); - - return buf; -} - - -/* - * TIMEZONE - */ - -/* - * Storage for TZ env var is allocated with an arbitrary size of 64 bytes. - */ -static char tzbuf[64]; - -/* - * assign_timezone: GUC assign_hook for timezone - */ -const char * -assign_timezone(const char *value, bool doit, bool interactive) -{ - char *result; - char *endptr; - double hours; - - /* - * Check for INTERVAL 'foo' - */ - if (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 - * elog, 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) - elog(ERROR, "SET TIME ZONE: illegal INTERVAL; month not allowed"); - pfree(interval); - return NULL; - } - if (doit) - { - 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) - { - CTimeZone = hours * 3600; - HasCTZSet = true; - } - } - else if (strcasecmp(value, "UNKNOWN") == 0) - { - /* - * Clear any TZ value we may have established. - * - * 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 - */ - if (doit) - { - if (tzbuf[0] == 'T') - { - strcpy(tzbuf, "="); - if (putenv(tzbuf) != 0) - elog(ERROR, "Unable to clear TZ environment variable"); - tzset(); - } - HasCTZSet = false; - } - } - else - { - /* - * Otherwise assume it is a timezone name. - * - * XXX unfortunately we have no reasonable way to check whether a - * timezone name is good, so we have to just assume that it is. - */ - if (doit) - { - strcpy(tzbuf, "TZ="); - strncat(tzbuf, value, sizeof(tzbuf)-4); - if (putenv(tzbuf) != 0) /* shouldn't happen? */ - elog(LOG, "assign_timezone: putenv failed"); - tzset(); - 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. - */ - 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) - elog(ERROR, "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 - */ - -bool -assign_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"; -} - - -/* - * 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. - */ - -const char * -assign_client_encoding(const char *value, bool doit, bool interactive) -{ -#ifdef MULTIBYTE - int encoding; - int old_encoding = 0; - - encoding = pg_valid_client_encoding(value); - if (encoding < 0) - return NULL; - /* - * Ugly API here ... can't test validity without setting new encoding... - */ - if (!doit) - old_encoding = pg_get_client_encoding(); - if (pg_set_client_encoding(encoding) < 0) - { - if (interactive) - elog(ERROR, "Conversion between %s and %s is not supported", - value, GetDatabaseEncodingName()); - return NULL; - } - if (!doit) - pg_set_client_encoding(old_encoding); -#else - if (strcasecmp(value, pg_get_client_encoding_name()) != 0) - return NULL; -#endif - - return value; -} - - -const char * -assign_server_encoding(const char *value, bool doit, bool interactive) -{ - if (interactive) - elog(ERROR, "SET SERVER_ENCODING is not supported"); - /* Pretend never to fail in noninteractive case */ - return value; -} - -const char * -show_server_encoding(void) -{ - return GetDatabaseEncodingName(); -} - - -/* - * SET SESSION AUTHORIZATION - * - * Note: when resetting session auth after an error, we can't expect to do - * catalog lookups. Hence, the stored form of the value is always a numeric - * userid that can be re-used directly. - */ -const char * -assign_session_authorization(const char *value, bool doit, bool interactive) -{ - Oid usesysid; - char *endptr; - char *result; - - usesysid = (Oid) strtoul(value, &endptr, 10); - - if (endptr != value && *endptr == '\0' && OidIsValid(usesysid)) - { - /* use the numeric user ID */ - } - else - { - HeapTuple userTup; - - userTup = SearchSysCache(SHADOWNAME, - PointerGetDatum(value), - 0, 0, 0); - if (!HeapTupleIsValid(userTup)) - { - if (interactive) - elog(ERROR, "user \"%s\" does not exist", value); - return NULL; - } - - usesysid = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid; - - ReleaseSysCache(userTup); - } - - if (doit) - SetSessionAuthorization(usesysid); - - result = (char *) malloc(32); - if (!result) - return NULL; - - snprintf(result, 32, "%lu", (unsigned long) usesysid); - - return result; -} - -const char * -show_session_authorization(void) -{ - return GetUserNameFromId(GetSessionUserId()); -} |