aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/variable.c
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>1998-01-05 18:43:18 +0000
committerBruce Momjian <bruce@momjian.us>1998-01-05 18:43:18 +0000
commit9db64857e0bd31eee463e90c21aba52be8174726 (patch)
tree3872821a2d3c96896bfccbd450ab29ab977a467d /src/backend/commands/variable.c
parentdeea69b90efa866544de6dd34b6e01c04f09806f (diff)
downloadpostgresql-9db64857e0bd31eee463e90c21aba52be8174726.tar.gz
postgresql-9db64857e0bd31eee463e90c21aba52be8174726.zip
Move variable.c to commands/ and aclchk.c to catalog/.
Diffstat (limited to 'src/backend/commands/variable.c')
-rw-r--r--src/backend/commands/variable.c612
1 files changed, 612 insertions, 0 deletions
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
new file mode 100644
index 00000000000..8ee7e777af8
--- /dev/null
+++ b/src/backend/commands/variable.c
@@ -0,0 +1,612 @@
+/*
+ * Routines for handling of 'SET var TO',
+ * 'SHOW var' and 'RESET var' statements.
+ *
+ * $Id: variable.c,v 1.1 1998/01/05 18:42:50 momjian Exp $
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include "postgres.h"
+#include "miscadmin.h"
+#include "commands/variable.h"
+#include "utils/builtins.h"
+#include "optimizer/internal.h"
+
+extern Cost _cpu_page_wight_;
+extern Cost _cpu_index_page_wight_;
+extern bool _use_geqo_;
+extern int32 _use_geqo_rels_;
+extern bool _use_right_sided_plans_;
+
+/*-----------------------------------------------------------------------*/
+#if USE_EURODATES
+#define DATE_EURO TRUE
+#else
+#define DATE_EURO FALSE
+#endif
+
+/*-----------------------------------------------------------------------*/
+struct PGVariables PGVariables =
+{
+ {DATE_EURO, Date_Postgres}
+};
+
+/*-----------------------------------------------------------------------*/
+static const char *
+get_token(char **tok, char **val, const char *str)
+{
+ const char *start;
+ int len = 0;
+
+ *tok = NULL;
+ if (val != NULL)
+ *val = NULL;
+
+ if (!(*str))
+ return NULL;
+
+ /* skip white spaces */
+ while (isspace(*str))
+ str++;
+ if (*str == ',' || *str == '=')
+ elog(ERROR, "Syntax error near (%s): empty setting", str);
+
+ /* end of string? then return NULL */
+ if (!(*str))
+ return NULL;
+
+ /* OK, at beginning of non-NULL string... */
+ start = str;
+
+ /*
+ * count chars in token until we hit white space or comma or '=' or
+ * end of string
+ */
+ while (*str && (!isspace(*str))
+ && *str != ',' && *str != '=')
+ {
+ str++;
+ len++;
+ }
+
+ *tok = (char *) PALLOC(len + 1);
+ StrNCpy(*tok, start, len+1);
+
+ /* skip white spaces */
+ while (isspace(*str))
+ str++;
+
+ /* end of string? */
+ if (!(*str))
+ {
+ return (str);
+
+ /* delimiter? */
+ }
+ else if (*str == ',')
+ {
+ return (++str);
+
+ }
+ else if ((val == NULL) || (*str != '='))
+ {
+ elog(ERROR, "Syntax error near (%s)", str);
+ };
+
+ str++; /* '=': get value */
+ len = 0;
+
+ /* skip white spaces */
+ while (isspace(*str))
+ str++;
+
+ if (*str == ',' || !(*str))
+ elog(ERROR, "Syntax error near (=%s)", str);
+
+ start = str;
+
+ /*
+ * count chars in token's value until we hit white space or comma or
+ * end of string
+ */
+ while (*str && (!isspace(*str)) && *str != ',')
+ {
+ str++;
+ len++;
+ }
+
+ *val = (char *) PALLOC(len + 1);
+ StrNCpy(*val, start, len+1);
+
+ /* skip white spaces */
+ while (isspace(*str))
+ str++;
+
+ if (!(*str))
+ return (NULL);
+ if (*str == ',')
+ return (++str);
+
+ elog(ERROR, "Syntax error near (%s)", str);
+
+ return str;
+}
+
+/*-----------------------------------------------------------------------*/
+#if FALSE
+static bool
+parse_null(const char *value)
+{
+ return TRUE;
+}
+
+static bool
+show_null(const char *value)
+{
+ return TRUE;
+}
+
+static bool
+reset_null(const char *value)
+{
+ return TRUE;
+}
+#endif
+
+bool
+parse_geqo(const char *value)
+{
+ const char *rest;
+ char *tok,
+ *val;
+
+ if (value == NULL)
+ {
+ reset_geqo();
+ return TRUE;
+ }
+
+ rest = get_token(&tok, &val, value);
+ if (tok == NULL)
+ elog(ERROR, "Value undefined");
+
+ if ((rest) && (*rest != '\0'))
+ elog(ERROR, "Unable to parse '%s'", value);
+
+ if (strcasecmp(tok, "on") == 0)
+ {
+ int32 geqo_rels = GEQO_RELS;
+
+ if (val != NULL)
+ {
+ geqo_rels = pg_atoi(val, sizeof(int32), '\0');
+ if (geqo_rels <= 1)
+ elog(ERROR, "Bad value for # of relations (%s)", val);
+ PFREE(val);
+ }
+ _use_geqo_ = true;
+ _use_geqo_rels_ = geqo_rels;
+ }
+ else if (strcasecmp(tok, "off") == 0)
+ {
+ if ((val != NULL) && (*val != '\0'))
+ elog(ERROR, "%s does not allow a parameter", tok);
+ _use_geqo_ = false;
+ }
+ else
+ elog(ERROR, "Bad value for GEQO (%s)", value);
+
+ PFREE(tok);
+ return TRUE;
+}
+
+bool
+show_geqo()
+{
+
+ if (_use_geqo_)
+ elog(NOTICE, "GEQO is ON beginning with %d relations", _use_geqo_rels_);
+ else
+ elog(NOTICE, "GEQO is OFF");
+ return TRUE;
+}
+
+bool
+reset_geqo(void)
+{
+
+#ifdef GEQO
+ _use_geqo_ = true;
+#else
+ _use_geqo_ = false;
+#endif
+ _use_geqo_rels_ = GEQO_RELS;
+ return TRUE;
+}
+
+bool
+parse_r_plans(const char *value)
+{
+ if (value == NULL)
+ {
+ reset_r_plans();
+ return TRUE;
+ }
+
+ if (strcasecmp(value, "on") == 0)
+ _use_right_sided_plans_ = true;
+ else if (strcasecmp(value, "off") == 0)
+ _use_right_sided_plans_ = false;
+ else
+ elog(ERROR, "Bad value for Right-sided Plans (%s)", value);
+
+ return TRUE;
+}
+
+bool
+show_r_plans()
+{
+
+ if (_use_right_sided_plans_)
+ elog(NOTICE, "Right-sided Plans are ON");
+ else
+ elog(NOTICE, "Right-sided Plans are OFF");
+ return TRUE;
+}
+
+bool
+reset_r_plans()
+{
+
+#ifdef USE_RIGHT_SIDED_PLANS
+ _use_right_sided_plans_ = true;
+#else
+ _use_right_sided_plans_ = false;
+#endif
+ return TRUE;
+}
+
+bool
+parse_cost_heap(const char *value)
+{
+ float32 res;
+
+ if (value == NULL)
+ {
+ reset_cost_heap();
+ return TRUE;
+ }
+
+ res = float4in((char *) value);
+ _cpu_page_wight_ = *res;
+
+ return TRUE;
+}
+
+bool
+show_cost_heap()
+{
+
+ elog(NOTICE, "COST_HEAP is %f", _cpu_page_wight_);
+ return TRUE;
+}
+
+bool
+reset_cost_heap()
+{
+ _cpu_page_wight_ = _CPU_PAGE_WEIGHT_;
+ return TRUE;
+}
+
+bool
+parse_cost_index(const char *value)
+{
+ float32 res;
+
+ if (value == NULL)
+ {
+ reset_cost_index();
+ return TRUE;
+ }
+
+ res = float4in((char *) value);
+ _cpu_index_page_wight_ = *res;
+
+ return TRUE;
+}
+
+bool
+show_cost_index()
+{
+
+ elog(NOTICE, "COST_INDEX is %f", _cpu_index_page_wight_);
+ return TRUE;
+}
+
+bool
+reset_cost_index()
+{
+ _cpu_index_page_wight_ = _CPU_INDEX_PAGE_WEIGHT_;
+ return TRUE;
+}
+
+bool
+parse_date(const char *value)
+{
+ char *tok;
+ int dcnt = 0,
+ ecnt = 0;
+
+ if (value == NULL)
+ {
+ reset_date();
+ return TRUE;
+ }
+
+ while ((value = get_token(&tok, NULL, value)) != 0)
+ {
+ /* Ugh. Somebody ought to write a table driven version -- mjl */
+
+ if (!strcasecmp(tok, "ISO"))
+ {
+ DateStyle = USE_ISO_DATES;
+ dcnt++;
+ }
+ else if (!strcasecmp(tok, "SQL"))
+ {
+ DateStyle = USE_SQL_DATES;
+ dcnt++;
+ }
+ else if (!strcasecmp(tok, "POSTGRES"))
+ {
+ DateStyle = USE_POSTGRES_DATES;
+ dcnt++;
+ }
+ else if (!strcasecmp(tok, "GERMAN"))
+ {
+ DateStyle = USE_GERMAN_DATES;
+ dcnt++;
+ EuroDates = TRUE;
+ if ((ecnt > 0) && (! EuroDates)) ecnt++;
+ }
+ else if (!strncasecmp(tok, "EURO", 4))
+ {
+ EuroDates = TRUE;
+ if ((dcnt <= 0) || (DateStyle != USE_GERMAN_DATES)) ecnt++;
+ }
+ else if ((!strcasecmp(tok, "US"))
+ || (!strncasecmp(tok, "NONEURO", 7)))
+ {
+ EuroDates = FALSE;
+ if ((dcnt <= 0) || (DateStyle == USE_GERMAN_DATES)) ecnt++;
+ }
+ else if (!strcasecmp(tok, "DEFAULT"))
+ {
+ DateStyle = USE_POSTGRES_DATES;
+ EuroDates = FALSE;
+ ecnt++;
+ }
+ else
+ {
+ elog(ERROR, "Bad value for date style (%s)", tok);
+ }
+ PFREE(tok);
+ }
+
+ if (dcnt > 1 || ecnt > 1)
+ elog(NOTICE, "Conflicting settings for date");
+
+ return TRUE;
+}
+
+bool
+show_date()
+{
+ char buf[64];
+
+ strcpy(buf, "DateStyle is ");
+ switch (DateStyle)
+ {
+ case USE_ISO_DATES:
+ strcat(buf, "ISO");
+ break;
+ case USE_SQL_DATES:
+ strcat(buf, "SQL");
+ break;
+ case USE_GERMAN_DATES:
+ strcat(buf, "German");
+ break;
+ default:
+ strcat(buf, "Postgres");
+ break;
+ };
+ strcat(buf, " with ");
+ strcat(buf, ((EuroDates) ? "European" : "US (NonEuropean)"));
+ strcat(buf, " conventions");
+
+ elog(NOTICE, buf, NULL);
+
+ return TRUE;
+}
+
+bool
+reset_date()
+{
+ DateStyle = USE_POSTGRES_DATES;
+ EuroDates = FALSE;
+
+ return TRUE;
+}
+
+/* Timezone support
+ * Working storage for strings is allocated with an arbitrary size of 64 bytes.
+ */
+
+static char *defaultTZ = NULL;
+static char TZvalue[64];
+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
+ */
+bool
+parse_timezone(const char *value)
+{
+ char *tok;
+
+ if (value == NULL)
+ {
+ reset_timezone();
+ return TRUE;
+ }
+
+ 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 (getenv("TZ") != NULL)
+ {
+ defaultTZ = getenv("TZ");
+ if (defaultTZ == NULL)
+ defaultTZ = (char *) -1;
+ else
+ 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();
+ PFREE(tok);
+ }
+
+ return TRUE;
+} /* parse_timezone() */
+
+bool
+show_timezone()
+{
+ char *tz;
+
+ tz = getenv("TZ");
+
+ elog(NOTICE, "Time zone is %s", ((tz != NULL)? tz: "unknown"));
+
+ return TRUE;
+} /* show_timezone() */
+
+/* reset_timezone()
+ * Set TZ environment variable to original value.
+ * Note that if TZ was originally not set, TZ should be cleared.
+ * 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).
+ */
+bool
+reset_timezone()
+{
+ if ((defaultTZ != NULL) && (defaultTZ != (char *) -1))
+ {
+ strcpy(tzbuf, "TZ=");
+ strcat(tzbuf, TZvalue);
+ if (putenv(tzbuf) != 0)
+ elog(ERROR, "Unable to set TZ environment variable to %s", TZvalue);
+ }
+ else
+ {
+ strcpy(tzbuf, "=");
+ if (putenv(tzbuf) != 0)
+ elog(ERROR, "Unable to clear TZ environment variable", NULL);
+ }
+ tzset();
+
+ return TRUE;
+} /* reset_timezone() */
+
+/*-----------------------------------------------------------------------*/
+struct VariableParsers
+{
+ const char *name;
+ bool (*parser) (const char *);
+ bool (*show) ();
+ bool (*reset) ();
+} VariableParsers[] =
+
+{
+ { "datestyle", parse_date, show_date, reset_date },
+ { "timezone", parse_timezone, show_timezone, reset_timezone },
+ { "cost_heap", parse_cost_heap, show_cost_heap, reset_cost_heap },
+ { "cost_index", parse_cost_index, show_cost_index, reset_cost_index },
+ { "geqo", parse_geqo, show_geqo, reset_geqo },
+ { "r_plans", parse_r_plans, show_r_plans, reset_r_plans },
+ { NULL, NULL, NULL, NULL }
+};
+
+/*-----------------------------------------------------------------------*/
+bool
+SetPGVariable(const char *name, const char *value)
+{
+ struct VariableParsers *vp;
+
+ for (vp = VariableParsers; vp->name; vp++)
+ {
+ if (!strcasecmp(vp->name, name))
+ return (vp->parser) (value);
+ }
+
+ elog(NOTICE, "Unrecognized variable %s", name);
+
+ return TRUE;
+}
+
+/*-----------------------------------------------------------------------*/
+bool
+GetPGVariable(const char *name)
+{
+ struct VariableParsers *vp;
+
+ for (vp = VariableParsers; vp->name; vp++)
+ {
+ if (!strcasecmp(vp->name, name))
+ return (vp->show) ();
+ }
+
+ elog(NOTICE, "Unrecognized variable %s", name);
+
+ return TRUE;
+}
+
+/*-----------------------------------------------------------------------*/
+bool
+ResetPGVariable(const char *name)
+{
+ struct VariableParsers *vp;
+
+ for (vp = VariableParsers; vp->name; vp++)
+ {
+ if (!strcasecmp(vp->name, name))
+ return (vp->reset) ();
+ }
+
+ elog(NOTICE, "Unrecognized variable %s", name);
+
+ return TRUE;
+}