Commit b813c8da authored by Alvaro Herrera's avatar Alvaro Herrera

A couple further reloptions improvements, per KaiGai Kohei: add a validation

function to the string type and add a couple of macros for string handling.

In passing, fix an off-by-one bug of mine.
parent eb0d7e24
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.16 2009/01/06 14:47:37 alvherre Exp $ * $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.17 2009/01/08 19:34:41 alvherre Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -336,9 +336,15 @@ add_real_reloption(int kind, char *name, char *desc, double default_val, ...@@ -336,9 +336,15 @@ add_real_reloption(int kind, char *name, char *desc, double default_val,
/* /*
* add_string_reloption * add_string_reloption
* Add a new string reloption * Add a new string reloption
*
* "validator" is an optional function pointer that can be used to test the
* validity of the values. It must elog(ERROR) when the argument string is
* not acceptable for the variable. Note that the default value must pass
* the validation.
*/ */
void void
add_string_reloption(int kind, char *name, char *desc, char *default_val) add_string_reloption(int kind, char *name, char *desc, char *default_val,
validate_string_relopt validator)
{ {
MemoryContext oldcxt; MemoryContext oldcxt;
relopt_string *newoption; relopt_string *newoption;
...@@ -359,6 +365,7 @@ add_string_reloption(int kind, char *name, char *desc, char *default_val) ...@@ -359,6 +365,7 @@ add_string_reloption(int kind, char *name, char *desc, char *default_val)
newoption->gen.kind = kind; newoption->gen.kind = kind;
newoption->gen.namelen = strlen(name); newoption->gen.namelen = strlen(name);
newoption->gen.type = RELOPT_TYPE_STRING; newoption->gen.type = RELOPT_TYPE_STRING;
newoption->validate_cb = validator;
if (default_val) if (default_val)
{ {
strcpy(newoption->default_val, default_val); strcpy(newoption->default_val, default_val);
...@@ -372,6 +379,10 @@ add_string_reloption(int kind, char *name, char *desc, char *default_val) ...@@ -372,6 +379,10 @@ add_string_reloption(int kind, char *name, char *desc, char *default_val)
newoption->default_isnull = true; newoption->default_isnull = true;
} }
/* make sure the validator/default combination is sane */
if (newoption->validate_cb)
(newoption->validate_cb) (newoption->default_val, true);
MemoryContextSwitchTo(oldcxt); MemoryContextSwitchTo(oldcxt);
add_reloption((relopt_gen *) newoption); add_reloption((relopt_gen *) newoption);
...@@ -729,10 +740,15 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len, ...@@ -729,10 +740,15 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
} }
break; break;
case RELOPT_TYPE_STRING: case RELOPT_TYPE_STRING:
option->values.string_val = value; {
nofree = true; relopt_string *optstring = (relopt_string *) option->gen;
parsed = true;
/* no validation possible */ option->values.string_val = value;
nofree = true;
if (optstring->validate_cb)
(optstring->validate_cb) (value, validate);
parsed = true;
}
break; break;
default: default:
elog(ERROR, "unsupported reloption type %d", option->gen->type); elog(ERROR, "unsupported reloption type %d", option->gen->type);
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/reloptions.h,v 1.8 2009/01/06 14:47:37 alvherre Exp $ * $PostgreSQL: pgsql/src/include/access/reloptions.h,v 1.9 2009/01/08 19:34:41 alvherre Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -90,11 +90,14 @@ typedef struct relopt_real ...@@ -90,11 +90,14 @@ typedef struct relopt_real
double max; double max;
} relopt_real; } relopt_real;
typedef void (*validate_string_relopt) (char *value, bool validate);
typedef struct relopt_string typedef struct relopt_string
{ {
relopt_gen gen; relopt_gen gen;
int default_len; int default_len;
bool default_isnull; bool default_isnull;
validate_string_relopt validate_cb;
char default_val[1]; /* variable length */ char default_val[1]; /* variable length */
} relopt_string; } relopt_string;
...@@ -113,7 +116,7 @@ typedef struct relopt_string ...@@ -113,7 +116,7 @@ typedef struct relopt_string
* need this information. * need this information.
*/ */
#define HAVE_RELOPTION(optname, option) \ #define HAVE_RELOPTION(optname, option) \
(pg_strncasecmp(option.gen->name, optname, option.gen->namelen) == 0) (pg_strncasecmp(option.gen->name, optname, option.gen->namelen + 1) == 0)
#define HANDLE_INT_RELOPTION(optname, var, option, wasset) \ #define HANDLE_INT_RELOPTION(optname, var, option, wasset) \
do { \ do { \
...@@ -141,7 +144,7 @@ typedef struct relopt_string ...@@ -141,7 +144,7 @@ typedef struct relopt_string
} \ } \
} while (0) } while (0)
#define HANDLE_REAL_RELOPTION(optname, var, option, wasset) \ #define HANDLE_REAL_RELOPTION(optname, var, option, wasset) \
do { \ do { \
if (HAVE_RELOPTION(optname, option)) \ if (HAVE_RELOPTION(optname, option)) \
{ \ { \
...@@ -166,23 +169,23 @@ typedef struct relopt_string ...@@ -166,23 +169,23 @@ typedef struct relopt_string
* string options have been processed. * string options have been processed.
*/ */
#define HANDLE_STRING_RELOPTION(optname, var, option, base, offset, wasset) \ #define HANDLE_STRING_RELOPTION(optname, var, option, base, offset, wasset) \
do { \ do { \
if (HAVE_RELOPTION(optname, option)) \ if (HAVE_RELOPTION(optname, option)) \
{ \ { \
relopt_string *optstring = (relopt_string *) option.gen;\ relopt_string *optstring = (relopt_string *) option.gen;\
char *string_val = NULL; \ char *string_val; \
\
if (option.isset) \ if (option.isset) \
string_val = option.values.string_val; \ string_val = option.values.string_val; \
else if (!optstring->default_isnull) \ else if (!optstring->default_isnull) \
string_val = optstring->default_val; \ string_val = optstring->default_val; \
else \
string_val = NULL; \
(wasset) != NULL ? *(wasset) = option.isset : (dummyret) NULL; \ (wasset) != NULL ? *(wasset) = option.isset : (dummyret) NULL; \
\ if (string_val == NULL) \
if (!string_val) \
var = 0; \ var = 0; \
else \ else \
{ \ { \
strcpy((char *)(base) + (offset), string_val); \ strcpy(((char *)(base)) + (offset), string_val); \
var = (offset); \ var = (offset); \
(offset) += strlen(string_val) + 1; \ (offset) += strlen(string_val) + 1; \
} \ } \
...@@ -190,6 +193,24 @@ typedef struct relopt_string ...@@ -190,6 +193,24 @@ typedef struct relopt_string
} \ } \
} while (0) } while (0)
/*
* For use during amoptions: get the strlen of a string option
* (either default or the user defined value)
*/
#define GET_STRING_RELOPTION_LEN(option) \
((option).isset ? strlen((option).values.string_val) : \
((relopt_string *) (option).gen)->default_len)
/*
* For use by code reading options already parsed: get a pointer to the string
* value itself. "optstruct" is the StdRdOption struct or equivalent, "member"
* is the struct member corresponding to the string option
*/
#define GET_STRING_RELOPTION(optstruct, member) \
((optstruct)->member == 0 ? NULL : \
(char *)(optstruct) + (optstruct)->member)
extern int add_reloption_kind(void); extern int add_reloption_kind(void);
extern void add_bool_reloption(int kind, char *name, char *desc, extern void add_bool_reloption(int kind, char *name, char *desc,
bool default_val); bool default_val);
...@@ -198,7 +219,7 @@ extern void add_int_reloption(int kind, char *name, char *desc, ...@@ -198,7 +219,7 @@ extern void add_int_reloption(int kind, char *name, char *desc,
extern void add_real_reloption(int kind, char *name, char *desc, extern void add_real_reloption(int kind, char *name, char *desc,
double default_val, double min_val, double max_val); double default_val, double min_val, double max_val);
extern void add_string_reloption(int kind, char *name, char *desc, extern void add_string_reloption(int kind, char *name, char *desc,
char *default_val); char *default_val, validate_string_relopt validator);
extern Datum transformRelOptions(Datum oldOptions, List *defList, extern Datum transformRelOptions(Datum oldOptions, List *defList,
bool ignoreOids, bool isReset); bool ignoreOids, bool isReset);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment