2 * Routines for handling of 'SET var TO',
3 * 'SHOW var' and 'RESET var' statements.
5 * $Id: variable.c,v 1.2 1998/01/07 18:46:26 momjian Exp $
14 #include "miscadmin.h"
15 #include "commands/variable.h"
16 #include "utils/builtins.h"
17 #include "optimizer/internal.h"
19 extern Cost _cpu_page_wight_;
20 extern Cost _cpu_index_page_wight_;
21 extern bool _use_geqo_;
22 extern int32 _use_geqo_rels_;
23 extern bool _use_right_sided_plans_;
25 /*-----------------------------------------------------------------------*/
27 #define DATE_EURO TRUE
29 #define DATE_EURO FALSE
32 /*-----------------------------------------------------------------------*/
33 struct PGVariables PGVariables =
35 {DATE_EURO, Date_Postgres}
38 /*-----------------------------------------------------------------------*/
40 get_token(char **tok, char **val, const char *str)
52 /* skip white spaces */
55 if (*str == ',' || *str == '=')
56 elog(ERROR, "Syntax error near (%s): empty setting", str);
58 /* end of string? then return NULL */
62 /* OK, at beginning of non-NULL string... */
66 * count chars in token until we hit white space or comma or '=' or
69 while (*str && (!isspace(*str))
70 && *str != ',' && *str != '=')
76 *tok = (char *) palloc(len + 1);
77 StrNCpy(*tok, start, len+1);
79 /* skip white spaces */
95 else if ((val == NULL) || (*str != '='))
97 elog(ERROR, "Syntax error near (%s)", str);
100 str++; /* '=': get value */
103 /* skip white spaces */
104 while (isspace(*str))
107 if (*str == ',' || !(*str))
108 elog(ERROR, "Syntax error near (=%s)", str);
113 * count chars in token's value until we hit white space or comma or
116 while (*str && (!isspace(*str)) && *str != ',')
122 *val = (char *) palloc(len + 1);
123 StrNCpy(*val, start, len+1);
125 /* skip white spaces */
126 while (isspace(*str))
134 elog(ERROR, "Syntax error near (%s)", str);
139 /*-----------------------------------------------------------------------*/
142 parse_null(const char *value)
148 show_null(const char *value)
154 reset_null(const char *value)
161 parse_geqo(const char *value)
173 rest = get_token(&tok, &val, value);
175 elog(ERROR, "Value undefined");
177 if ((rest) && (*rest != '\0'))
178 elog(ERROR, "Unable to parse '%s'", value);
180 if (strcasecmp(tok, "on") == 0)
182 int32 geqo_rels = GEQO_RELS;
186 geqo_rels = pg_atoi(val, sizeof(int32), '\0');
188 elog(ERROR, "Bad value for # of relations (%s)", val);
192 _use_geqo_rels_ = geqo_rels;
194 else if (strcasecmp(tok, "off") == 0)
196 if ((val != NULL) && (*val != '\0'))
197 elog(ERROR, "%s does not allow a parameter", tok);
201 elog(ERROR, "Bad value for GEQO (%s)", value);
212 elog(NOTICE, "GEQO is ON beginning with %d relations", _use_geqo_rels_);
214 elog(NOTICE, "GEQO is OFF");
227 _use_geqo_rels_ = GEQO_RELS;
232 parse_r_plans(const char *value)
240 if (strcasecmp(value, "on") == 0)
241 _use_right_sided_plans_ = true;
242 else if (strcasecmp(value, "off") == 0)
243 _use_right_sided_plans_ = false;
245 elog(ERROR, "Bad value for Right-sided Plans (%s)", value);
254 if (_use_right_sided_plans_)
255 elog(NOTICE, "Right-sided Plans are ON");
257 elog(NOTICE, "Right-sided Plans are OFF");
265 #ifdef USE_RIGHT_SIDED_PLANS
266 _use_right_sided_plans_ = true;
268 _use_right_sided_plans_ = false;
274 parse_cost_heap(const char *value)
284 res = float4in((char *) value);
285 _cpu_page_wight_ = *res;
294 elog(NOTICE, "COST_HEAP is %f", _cpu_page_wight_);
301 _cpu_page_wight_ = _CPU_PAGE_WEIGHT_;
306 parse_cost_index(const char *value)
316 res = float4in((char *) value);
317 _cpu_index_page_wight_ = *res;
326 elog(NOTICE, "COST_INDEX is %f", _cpu_index_page_wight_);
333 _cpu_index_page_wight_ = _CPU_INDEX_PAGE_WEIGHT_;
338 parse_date(const char *value)
350 while ((value = get_token(&tok, NULL, value)) != 0)
352 /* Ugh. Somebody ought to write a table driven version -- mjl */
354 if (!strcasecmp(tok, "ISO"))
356 DateStyle = USE_ISO_DATES;
359 else if (!strcasecmp(tok, "SQL"))
361 DateStyle = USE_SQL_DATES;
364 else if (!strcasecmp(tok, "POSTGRES"))
366 DateStyle = USE_POSTGRES_DATES;
369 else if (!strcasecmp(tok, "GERMAN"))
371 DateStyle = USE_GERMAN_DATES;
374 if ((ecnt > 0) && (! EuroDates)) ecnt++;
376 else if (!strncasecmp(tok, "EURO", 4))
379 if ((dcnt <= 0) || (DateStyle != USE_GERMAN_DATES)) ecnt++;
381 else if ((!strcasecmp(tok, "US"))
382 || (!strncasecmp(tok, "NONEURO", 7)))
385 if ((dcnt <= 0) || (DateStyle == USE_GERMAN_DATES)) ecnt++;
387 else if (!strcasecmp(tok, "DEFAULT"))
389 DateStyle = USE_POSTGRES_DATES;
395 elog(ERROR, "Bad value for date style (%s)", tok);
400 if (dcnt > 1 || ecnt > 1)
401 elog(NOTICE, "Conflicting settings for date");
411 strcpy(buf, "DateStyle is ");
420 case USE_GERMAN_DATES:
421 strcat(buf, "German");
424 strcat(buf, "Postgres");
427 strcat(buf, " with ");
428 strcat(buf, ((EuroDates) ? "European" : "US (NonEuropean)"));
429 strcat(buf, " conventions");
431 elog(NOTICE, buf, NULL);
439 DateStyle = USE_POSTGRES_DATES;
446 * Working storage for strings is allocated with an arbitrary size of 64 bytes.
449 static char *defaultTZ = NULL;
450 static char TZvalue[64];
451 static char tzbuf[64];
454 * Handle SET TIME ZONE...
455 * Try to save existing TZ environment variable for later use in RESET TIME ZONE.
456 * - thomas 1997-11-10
459 parse_timezone(const char *value)
469 while ((value = get_token(&tok, NULL, value)) != 0)
471 /* Not yet tried to save original value from environment? */
472 if (defaultTZ == NULL)
474 /* found something? then save it for later */
475 if (getenv("TZ") != NULL)
477 defaultTZ = getenv("TZ");
478 if (defaultTZ == NULL)
479 defaultTZ = (char *) -1;
481 strcpy(TZvalue, defaultTZ);
483 /* found nothing so mark with an invalid pointer */
486 defaultTZ = (char *) -1;
490 strcpy(tzbuf, "TZ=");
492 if (putenv(tzbuf) != 0)
493 elog(ERROR, "Unable to set TZ environment variable to %s", tok);
500 } /* parse_timezone() */
509 elog(NOTICE, "Time zone is %s", ((tz != NULL)? tz: "unknown"));
512 } /* show_timezone() */
515 * Set TZ environment variable to original value.
516 * Note that if TZ was originally not set, TZ should be cleared.
517 * unsetenv() works fine, but is BSD, not POSIX, and is not available
518 * under Solaris, among others. Apparently putenv() called as below
519 * clears the process-specific environment variables.
520 * Other reasonable arguments to putenv() (e.g. "TZ=", "TZ", "") result
521 * in a core dump (under Linux anyway).
526 if ((defaultTZ != NULL) && (defaultTZ != (char *) -1))
528 strcpy(tzbuf, "TZ=");
529 strcat(tzbuf, TZvalue);
530 if (putenv(tzbuf) != 0)
531 elog(ERROR, "Unable to set TZ environment variable to %s", TZvalue);
536 if (putenv(tzbuf) != 0)
537 elog(ERROR, "Unable to clear TZ environment variable", NULL);
542 } /* reset_timezone() */
544 /*-----------------------------------------------------------------------*/
545 struct VariableParsers
548 bool (*parser) (const char *);
551 } VariableParsers[] =
554 { "datestyle", parse_date, show_date, reset_date },
555 { "timezone", parse_timezone, show_timezone, reset_timezone },
556 { "cost_heap", parse_cost_heap, show_cost_heap, reset_cost_heap },
557 { "cost_index", parse_cost_index, show_cost_index, reset_cost_index },
558 { "geqo", parse_geqo, show_geqo, reset_geqo },
559 { "r_plans", parse_r_plans, show_r_plans, reset_r_plans },
560 { NULL, NULL, NULL, NULL }
563 /*-----------------------------------------------------------------------*/
565 SetPGVariable(const char *name, const char *value)
567 struct VariableParsers *vp;
569 for (vp = VariableParsers; vp->name; vp++)
571 if (!strcasecmp(vp->name, name))
572 return (vp->parser) (value);
575 elog(NOTICE, "Unrecognized variable %s", name);
580 /*-----------------------------------------------------------------------*/
582 GetPGVariable(const char *name)
584 struct VariableParsers *vp;
586 for (vp = VariableParsers; vp->name; vp++)
588 if (!strcasecmp(vp->name, name))
589 return (vp->show) ();
592 elog(NOTICE, "Unrecognized variable %s", name);
597 /*-----------------------------------------------------------------------*/
599 ResetPGVariable(const char *name)
601 struct VariableParsers *vp;
603 for (vp = VariableParsers; vp->name; vp++)
605 if (!strcasecmp(vp->name, name))
606 return (vp->reset) ();
609 elog(NOTICE, "Unrecognized variable %s", name);