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