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 + -
显示快捷键?