Fix broken parsing for lists of options. Apparently broken when support was

added for keyword=value options.
This commit is contained in:
Thomas G. Lockhart 1997-06-20 17:17:03 +00:00
parent 9af564ada6
commit 2f09dd9958
1 changed files with 59 additions and 57 deletions

View File

@ -2,12 +2,13 @@
* Routines for handling of 'SET var TO', 'SHOW var' and 'RESET var' * Routines for handling of 'SET var TO', 'SHOW var' and 'RESET var'
* statements. * statements.
* *
* $Id: variable.c,v 1.11 1997/06/03 06:29:31 vadim Exp $ * $Id: variable.c,v 1.12 1997/06/20 17:17:03 thomas Exp $
* *
*/ */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h>
#include "postgres.h" #include "postgres.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "tcop/variable.h" #include "tcop/variable.h"
@ -38,55 +39,60 @@ static const char *get_token(char **tok, char **val, const char *str)
{ {
const char *start; const char *start;
int len = 0; int len = 0;
*tok = *val = NULL; *tok = NULL;
if (val != NULL) *val = NULL;
if ( !(*str) ) if ( !(*str) )
return NULL; return NULL;
/* skip white spaces */ /* skip white spaces */
while ( *str == ' ' || *str == '\t' ) while (isspace(*str)) str++;
str++;
if ( *str == ',' || *str == '=' ) if ( *str == ',' || *str == '=' )
elog(WARN, "Syntax error near (%s): empty setting", str); elog(WARN, "Syntax error near (%s): empty setting", str);
/* end of string? then return NULL */
if ( !(*str) ) if ( !(*str) )
return NULL; return NULL;
/* OK, at beginning of non-NULL string... */
start = str; start = str;
/* /*
* count chars in token until we hit white space or comma * count chars in token until we hit white space or comma
* or '=' or end of string * or '=' or end of string
*/ */
while ( *str && *str != ' ' && *str != '\t' while ( *str && (! isspace(*str))
&& *str != ',' && *str != '=' ) && *str != ',' && *str != '=' )
{ {
str++; str++;
len++; len++;
} }
*tok = (char*) palloc (len + 1); *tok = (char*) PALLOC(len + 1);
strncpy (*tok, start, len); strncpy (*tok, start, len);
(*tok)[len] = '\0'; (*tok)[len] = '\0';
/* skip white spaces */ /* skip white spaces */
while ( *str == ' ' || *str == '\t' ) while ( isspace(*str)) str++;
str++;
/* end of string? */
if ( !(*str) ) if ( !(*str) ) {
return (NULL); return(str);
if ( *str == ',' )
/* delimiter? */
} else if ( *str == ',' ) {
return (++str); return (++str);
if ( *str != '=' ) } else if ((val == NULL) || ( *str != '=' )) {
elog(WARN, "Syntax error near (%s)", str); elog(WARN, "Syntax error near (%s)", str);
};
str++; /* '=': get value */ str++; /* '=': get value */
len = 0; len = 0;
/* skip white spaces */ /* skip white spaces */
while ( *str == ' ' || *str == '\t' ) while ( isspace(*str)) str++;
str++;
if ( *str == ',' || !(*str) ) if ( *str == ',' || !(*str) )
elog(WARN, "Syntax error near (=%s)", str); elog(WARN, "Syntax error near (=%s)", str);
@ -94,22 +100,21 @@ static const char *get_token(char **tok, char **val, const char *str)
start = str; start = str;
/* /*
* count chars in token' value until we hit white space or comma * count chars in token's value until we hit white space or comma
* or end of string * or end of string
*/ */
while ( *str && *str != ' ' && *str != '\t' && *str != ',' ) while ( *str && (! isspace(*str)) && *str != ',' )
{ {
str++; str++;
len++; len++;
} }
*val = (char*) palloc (len + 1); *val = (char*) PALLOC(len + 1);
strncpy (*val, start, len); strncpy (*val, start, len);
(*val)[len] = '\0'; (*val)[len] = '\0';
/* skip white spaces */ /* skip white spaces */
while ( *str == ' ' || *str == '\t' ) while ( isspace(*str)) str++;
str++;
if ( !(*str) ) if ( !(*str) )
return (NULL); return (NULL);
@ -120,23 +125,23 @@ static const char *get_token(char **tok, char **val, const char *str)
return str; return str;
} }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
static bool parse_null(const char *value) static bool parse_null(const char *value)
{ {
return TRUE; return TRUE;
} }
static bool show_null(const char *value) static bool show_null(const char *value)
{ {
return TRUE; return TRUE;
} }
static bool reset_null(const char *value) static bool reset_null(const char *value)
{ {
return TRUE; return TRUE;
} }
static bool parse_geqo (const char *value) static bool parse_geqo (const char *value)
{ {
const char *rest; const char *rest;
@ -146,8 +151,8 @@ static bool parse_geqo (const char *value)
if ( tok == NULL ) if ( tok == NULL )
elog(WARN, "Value undefined"); elog(WARN, "Value undefined");
if ( rest ) if (( rest ) && ( *rest != '\0' ))
elog(WARN, "Unacceptable data (%s)", rest); elog(WARN, "Unable to parse '%s'", value);
if ( strcasecmp (tok, "on") == 0 ) if ( strcasecmp (tok, "on") == 0 )
{ {
@ -158,21 +163,21 @@ static bool parse_geqo (const char *value)
geqo_rels = pg_atoi (val, sizeof(int32), '\0'); geqo_rels = pg_atoi (val, sizeof(int32), '\0');
if ( geqo_rels <= 1 ) if ( geqo_rels <= 1 )
elog(WARN, "Bad value for # of relations (%s)", val); elog(WARN, "Bad value for # of relations (%s)", val);
pfree (val); PFREE(val);
} }
_use_geqo_ = true; _use_geqo_ = true;
_use_geqo_rels_ = geqo_rels; _use_geqo_rels_ = geqo_rels;
} }
else if ( strcasecmp (tok, "off") == 0 ) else if ( strcasecmp (tok, "off") == 0 )
{ {
if ( val != NULL ) if (( val != NULL ) && ( *val != '\0' ))
elog(WARN, "Unacceptable data (%s)", val); elog(WARN, "%s does not allow a parameter",tok);
_use_geqo_ = false; _use_geqo_ = false;
} }
else else
elog(WARN, "Bad value for GEQO (%s)", value); elog(WARN, "Bad value for GEQO (%s)", value);
pfree (tok); PFREE(tok);
return TRUE; return TRUE;
} }
@ -180,7 +185,7 @@ static bool show_geqo ()
{ {
if ( _use_geqo_ ) if ( _use_geqo_ )
elog (NOTICE, "GEQO is ON begining with %d relations", _use_geqo_rels_); elog (NOTICE, "GEQO is ON beginning with %d relations", _use_geqo_rels_);
else else
elog (NOTICE, "GEQO is OFF"); elog (NOTICE, "GEQO is OFF");
return TRUE; return TRUE;
@ -197,7 +202,7 @@ static bool reset_geqo ()
_use_geqo_rels_ = GEQO_RELS; _use_geqo_rels_ = GEQO_RELS;
return TRUE; return TRUE;
} }
static bool parse_r_plans (const char *value) static bool parse_r_plans (const char *value)
{ {
@ -231,7 +236,7 @@ static bool reset_r_plans ()
#endif #endif
return TRUE; return TRUE;
} }
static bool parse_cost_heap (const char *value) static bool parse_cost_heap (const char *value)
{ {
float32 res = float4in ((char*)value); float32 res = float4in ((char*)value);
@ -278,16 +283,13 @@ static bool reset_cost_index ()
static bool parse_date(const char *value) static bool parse_date(const char *value)
{ {
char *tok, *val; char *tok;
int dcnt = 0, ecnt = 0; int dcnt = 0, ecnt = 0;
while((value = get_token(&tok, &val, value)) != 0) while((value = get_token(&tok, NULL, value)) != 0)
{ {
if ( val != NULL )
elog(WARN, "Syntax error near (%s)", val);
/* Ugh. Somebody ought to write a table driven version -- mjl */ /* Ugh. Somebody ought to write a table driven version -- mjl */
if(!strcasecmp(tok, "iso")) if(!strcasecmp(tok, "iso"))
{ {
DateStyle = USE_ISO_DATES; DateStyle = USE_ISO_DATES;
@ -324,15 +326,15 @@ static bool parse_date(const char *value)
{ {
elog(WARN, "Bad value for date style (%s)", tok); elog(WARN, "Bad value for date style (%s)", tok);
} }
pfree (tok); PFREE(tok);
} }
if(dcnt > 1 || ecnt > 1) if(dcnt > 1 || ecnt > 1)
elog(NOTICE, "Conflicting settings for date"); elog(NOTICE, "Conflicting settings for date");
return TRUE; return TRUE;
} }
static bool show_date() static bool show_date()
{ {
char buf[64]; char buf[64];
@ -357,7 +359,7 @@ static bool show_date()
return TRUE; return TRUE;
} }
static bool reset_date() static bool reset_date()
{ {
DateStyle = USE_POSTGRES_DATES; DateStyle = USE_POSTGRES_DATES;
@ -365,7 +367,7 @@ static bool reset_date()
return TRUE; return TRUE;
} }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
struct VariableParsers struct VariableParsers
{ {
@ -390,13 +392,13 @@ struct VariableParsers
bool SetPGVariable(const char *name, const char *value) bool SetPGVariable(const char *name, const char *value)
{ {
struct VariableParsers *vp; struct VariableParsers *vp;
for(vp = VariableParsers; vp->name; vp++) for(vp = VariableParsers; vp->name; vp++)
{ {
if(!strcasecmp(vp->name, name)) if(!strcasecmp(vp->name, name))
return (vp->parser)(value); return (vp->parser)(value);
} }
elog(NOTICE, "Unrecognized variable %s", name); elog(NOTICE, "Unrecognized variable %s", name);
return TRUE; return TRUE;
@ -406,13 +408,13 @@ bool SetPGVariable(const char *name, const char *value)
bool GetPGVariable(const char *name) bool GetPGVariable(const char *name)
{ {
struct VariableParsers *vp; struct VariableParsers *vp;
for(vp = VariableParsers; vp->name; vp++) for(vp = VariableParsers; vp->name; vp++)
{ {
if(!strcasecmp(vp->name, name)) if(!strcasecmp(vp->name, name))
return (vp->show)(); return (vp->show)();
} }
elog(NOTICE, "Unrecognized variable %s", name); elog(NOTICE, "Unrecognized variable %s", name);
return TRUE; return TRUE;
@ -422,13 +424,13 @@ bool GetPGVariable(const char *name)
bool ResetPGVariable(const char *name) bool ResetPGVariable(const char *name)
{ {
struct VariableParsers *vp; struct VariableParsers *vp;
for(vp = VariableParsers; vp->name; vp++) for(vp = VariableParsers; vp->name; vp++)
{ {
if(!strcasecmp(vp->name, name)) if(!strcasecmp(vp->name, name))
return (vp->reset)(); return (vp->reset)();
} }
elog(NOTICE, "Unrecognized variable %s", name); elog(NOTICE, "Unrecognized variable %s", name);
return TRUE; return TRUE;