aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/variable.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/variable.c')
-rw-r--r--src/backend/commands/variable.c293
1 files changed, 208 insertions, 85 deletions
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 029ea86a2bd..9da67760745 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.53 2001/09/19 15:19:12 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.54 2001/10/18 17:30:14 thomas Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,6 +27,7 @@
#include "optimizer/paths.h"
#include "parser/parse_expr.h"
#include "utils/builtins.h"
+#include "utils/date.h"
#include "utils/guc.h"
#include "utils/tqual.h"
@@ -41,24 +42,24 @@
static bool show_datestyle(void);
static bool reset_datestyle(void);
-static bool parse_datestyle(char *);
+static bool parse_datestyle(List *);
static bool show_timezone(void);
static bool reset_timezone(void);
-static bool parse_timezone(char *);
+static bool parse_timezone(List *);
static bool show_XactIsoLevel(void);
static bool reset_XactIsoLevel(void);
-static bool parse_XactIsoLevel(char *);
-static bool parse_random_seed(char *);
+static bool parse_XactIsoLevel(List *);
static bool show_random_seed(void);
static bool reset_random_seed(void);
+static bool parse_random_seed(List *);
static bool show_client_encoding(void);
static bool reset_client_encoding(void);
-static bool parse_client_encoding(char *);
+static bool parse_client_encoding(List *);
static bool show_server_encoding(void);
static bool reset_server_encoding(void);
-static bool parse_server_encoding(char *);
+static bool parse_server_encoding(List *);
/*
@@ -177,7 +178,7 @@ get_token(char **tok, char **val, char *str)
/*
- * DATE_STYLE
+ * DATESTYLE
*
* NOTE: set_default_datestyle() is called during backend startup to check
* if the PGDATESTYLE environment variable is set. We want the env var
@@ -189,17 +190,14 @@ static int DefaultDateStyle;
static bool DefaultEuroDates;
static bool
-parse_datestyle(char *value)
+parse_datestyle_internal(char *value)
{
char *tok;
int dcnt = 0,
ecnt = 0;
if (value == NULL)
- {
- reset_datestyle();
- return TRUE;
- }
+ return reset_datestyle();
while ((value = get_token(&tok, NULL, value)) != 0)
{
@@ -258,6 +256,21 @@ parse_datestyle(char *value)
}
static bool
+parse_datestyle(List *args)
+{
+ char *value;
+
+ if (args == NULL)
+ return reset_datestyle();
+
+ Assert(IsA(lfirst(args), A_Const));
+
+ value = ((A_Const *) lfirst(args))->val.val.str;
+
+ return parse_datestyle_internal(value);
+}
+
+static bool
show_datestyle(void)
{
char buf[64];
@@ -321,8 +334,11 @@ set_default_datestyle(void)
*/
DBDate = strdup(DBDate);
- /* Parse desired setting into DateStyle/EuroDates */
- parse_datestyle(DBDate);
+ /* Parse desired setting into DateStyle/EuroDates
+ * Use parse_datestyle_internal() to avoid any palloc() issues per above
+ * - thomas 2001-10-15
+ */
+ parse_datestyle_internal(DBDate);
free(DBDate);
@@ -348,39 +364,96 @@ static char tzbuf[64];
/* parse_timezone()
* Handle SET TIME ZONE...
* Try to save existing TZ environment variable for later use in RESET TIME ZONE.
- * - thomas 1997-11-10
+ * Accept an explicit interval per SQL9x, though this is less useful than a full time zone.
+ * - thomas 2001-10-11
*/
static bool
-parse_timezone(char *value)
+parse_timezone(List *args)
{
- char *tok;
+ List *arg;
+ TypeName *type;
- if (value == NULL)
- {
- reset_timezone();
- return TRUE;
- }
+ if (args == NULL)
+ return reset_timezone();
- while ((value = get_token(&tok, NULL, value)) != 0)
+ Assert(IsA(args, List));
+
+ foreach(arg, args)
{
- /* Not yet tried to save original value from environment? */
- if (defaultTZ == NULL)
- {
- /* found something? then save it for later */
- if ((defaultTZ = getenv("TZ")) != NULL)
- strcpy(TZvalue, defaultTZ);
+ A_Const *p;
- /* found nothing so mark with an invalid pointer */
- else
- defaultTZ = (char *) -1;
- }
+ Assert(IsA(arg, List));
+ p = lfirst(arg);
+ Assert(IsA(p, A_Const));
- strcpy(tzbuf, "TZ=");
- strcat(tzbuf, tok);
- if (putenv(tzbuf) != 0)
- elog(ERROR, "Unable to set TZ environment variable to %s", tok);
+ type = p->typename;
+ if (type != NULL)
+ {
+ if (strcmp(type->name, "interval") == 0)
+ {
+ Interval *interval;
+
+ interval = DatumGetIntervalP(DirectFunctionCall3(interval_in,
+ CStringGetDatum(p->val.val.str),
+ ObjectIdGetDatum(InvalidOid),
+ Int32GetDatum(-1)));
+ if (interval->month != 0)
+ elog(ERROR, "SET TIME ZONE illegal INTERVAL; month not allowed");
+ CTimeZone = interval->time;
+ }
+ else if (strcmp(type->name, "float8") == 0)
+ {
+ float8 time;
+
+ time = DatumGetFloat8(DirectFunctionCall1(float8in, CStringGetDatum(p->val.val.str)));
+ CTimeZone = time * 3600;
+ }
+ /* We do not actually generate an integer constant in gram.y so this is not used... */
+ else if (strcmp(type->name, "int4") == 0)
+ {
+ int32 time;
+
+ time = p->val.val.ival;
+ CTimeZone = time * 3600;
+ }
+ else
+ {
+ elog(ERROR, "Unable to process SET TIME ZONE command; internal coding error");
+ }
- tzset();
+ HasCTZSet = true;
+ }
+ else
+ {
+ char *tok;
+ char *value;
+
+ value = p->val.val.str;
+
+ while ((value = get_token(&tok, NULL, value)) != 0)
+ {
+ /* Not yet tried to save original value from environment? */
+ if (defaultTZ == NULL)
+ {
+ /* found something? then save it for later */
+ if ((defaultTZ = getenv("TZ")) != NULL)
+ strcpy(TZvalue, defaultTZ);
+
+ /* found nothing so mark with an invalid pointer */
+ else
+ defaultTZ = (char *) -1;
+ }
+
+ strcpy(tzbuf, "TZ=");
+ strcat(tzbuf, tok);
+ if (putenv(tzbuf) != 0)
+ elog(ERROR, "Unable to set TZ environment variable to %s", tok);
+
+ tzset();
+ }
+
+ HasCTZSet = false;
+ }
}
return TRUE;
@@ -389,11 +462,26 @@ parse_timezone(char *value)
static bool
show_timezone(void)
{
- char *tz;
+ char *tzn;
+
+ if (HasCTZSet)
+ {
+ Interval interval;
- tz = getenv("TZ");
+ interval.month = 0;
+ interval.time = CTimeZone;
+
+ tzn = DatumGetCString(DirectFunctionCall1(interval_out, IntervalPGetDatum(&interval)));
+ }
+ else
+ {
+ tzn = getenv("TZ");
+ }
- elog(NOTICE, "Time zone is %s", ((tz != NULL) ? tz : "unset"));
+ if (tzn != NULL)
+ elog(NOTICE, "Time zone is '%s'", tzn);
+ else
+ elog(NOTICE, "Time zone is unset");
return TRUE;
} /* show_timezone() */
@@ -411,8 +499,13 @@ show_timezone(void)
static bool
reset_timezone(void)
{
+ if (HasCTZSet)
+ {
+ HasCTZSet = false;
+ }
+
/* no time zone has been set in this session? */
- if (defaultTZ == NULL)
+ else if (defaultTZ == NULL)
{
}
@@ -443,17 +536,23 @@ reset_timezone(void)
-/* SET TRANSACTION */
+/*
+ *
+ * SET TRANSACTION
+ *
+ */
static bool
-parse_XactIsoLevel(char *value)
+parse_XactIsoLevel(List *args)
{
+ char *value;
- if (value == NULL)
- {
- reset_XactIsoLevel();
- return TRUE;
- }
+ if (args == NULL)
+ return reset_XactIsoLevel();
+
+ Assert(IsA(lfirst(args), A_Const));
+
+ value = ((A_Const *) lfirst(args))->val.val.str;
if (SerializableSnapshot != NULL)
{
@@ -461,7 +560,6 @@ parse_XactIsoLevel(char *value)
return TRUE;
}
-
if (strcmp(value, "serializable") == 0)
XactIsoLevel = XACT_SERIALIZABLE;
else if (strcmp(value, "read committed") == 0)
@@ -503,17 +601,21 @@ reset_XactIsoLevel(void)
* Random number seed
*/
static bool
-parse_random_seed(char *value)
+parse_random_seed(List *args)
{
- double seed = 0;
+ char *value;
+ double seed = 0;
+
+ if (args == NULL)
+ return reset_random_seed();
+
+ Assert(IsA(lfirst(args), A_Const));
+
+ value = ((A_Const *) lfirst(args))->val.val.str;
+
+ sscanf(value, "%lf", &seed);
+ DirectFunctionCall1(setseed, Float8GetDatum(seed));
- if (value == NULL)
- reset_random_seed();
- else
- {
- sscanf(value, "%lf", &seed);
- DirectFunctionCall1(setseed, Float8GetDatum(seed));
- }
return (TRUE);
}
@@ -544,16 +646,26 @@ reset_random_seed(void)
*/
static bool
-parse_client_encoding(char *value)
+parse_client_encoding(List *args)
{
+ char *value;
#ifdef MULTIBYTE
- int encoding;
+ int encoding;
+#endif
+ if (args == NULL)
+ return reset_client_encoding();
+
+ Assert(IsA(lfirst(args), A_Const));
+
+ value = ((A_Const *) lfirst(args))->val.val.str;
+
+#ifdef MULTIBYTE
encoding = pg_valid_client_encoding(value);
if (encoding < 0)
{
if (value)
- elog(ERROR, "Client encoding %s is not supported", value);
+ elog(ERROR, "Client encoding '%s' is not supported", value);
else
elog(ERROR, "No client encoding is specified");
}
@@ -576,8 +688,8 @@ parse_client_encoding(char *value)
static bool
show_client_encoding(void)
{
- elog(NOTICE, "Current client encoding is %s",
- pg_get_client_encoding_name());
+ elog(NOTICE, "Current client encoding is '%s'",
+ pg_get_client_encoding_name());
return TRUE;
}
@@ -596,6 +708,7 @@ reset_client_encoding(void)
}
else
encoding = GetDatabaseEncoding();
+
pg_set_client_encoding(encoding);
#endif
return TRUE;
@@ -610,7 +723,7 @@ set_default_client_encoding(void)
static bool
-parse_server_encoding(char *value)
+parse_server_encoding(List *args)
{
elog(NOTICE, "SET SERVER_ENCODING is not supported");
return TRUE;
@@ -619,7 +732,7 @@ parse_server_encoding(char *value)
static bool
show_server_encoding(void)
{
- elog(NOTICE, "Current server encoding is %s", GetDatabaseEncodingName());
+ elog(NOTICE, "Current server encoding is '%s'", GetDatabaseEncodingName());
return TRUE;
}
@@ -632,33 +745,42 @@ reset_server_encoding(void)
+/* SetPGVariable()
+ * Dispatcher for handling SET commands.
+ * Special cases ought to be removed and handled separately by TCOP
+ */
void
-SetPGVariable(const char *name, const char *value)
+SetPGVariable(const char *name, List *args)
{
- char *mvalue = value ? pstrdup(value) : ((char *) NULL);
-
- /*
- * Special cases ought to be removed and handled separately by TCOP
- */
if (strcasecmp(name, "datestyle") == 0)
- parse_datestyle(mvalue);
+ parse_datestyle(args);
else if (strcasecmp(name, "timezone") == 0)
- parse_timezone(mvalue);
+ parse_timezone(args);
else if (strcasecmp(name, "XactIsoLevel") == 0)
- parse_XactIsoLevel(mvalue);
+ parse_XactIsoLevel(args);
else if (strcasecmp(name, "client_encoding") == 0)
- parse_client_encoding(mvalue);
+ parse_client_encoding(args);
else if (strcasecmp(name, "server_encoding") == 0)
- parse_server_encoding(mvalue);
+ parse_server_encoding(args);
else if (strcasecmp(name, "seed") == 0)
- parse_random_seed(mvalue);
- else if (strcasecmp(name, "session_authorization") == 0)
- SetSessionAuthorization(value);
+ parse_random_seed(args);
else
- SetConfigOption(name, value, superuser() ? PGC_SUSET : PGC_USERSET, false);
+ {
+ /* For routines defined somewhere else,
+ * go ahead and extract the string argument
+ * to match the original interface definition.
+ * Later, we can change this code too...
+ */
+ char *value;
- if (mvalue)
- pfree(mvalue);
+ value = ((args != NULL)? ((A_Const *) lfirst(args))->val.val.str: NULL);
+
+ if (strcasecmp(name, "session_authorization") == 0)
+ SetSessionAuthorization(value);
+ else
+ SetConfigOption(name, value, superuser() ? PGC_SUSET : PGC_USERSET, false);
+ }
+ return;
}
void
@@ -685,7 +807,8 @@ GetPGVariable(const char *name)
show_client_encoding();
show_server_encoding();
show_random_seed();
- } else
+ }
+ else
{
const char *val = GetConfigOption(name);