Skip to content

Commit b813c8d

Browse files
committed
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.
1 parent eb0d7e2 commit b813c8d

File tree

2 files changed

+53
-16
lines changed

2 files changed

+53
-16
lines changed

src/backend/access/common/reloptions.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.16 2009/01/06 14:47:37 alvherre Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.17 2009/01/08 19:34:41 alvherre Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -336,9 +336,15 @@ add_real_reloption(int kind, char *name, char *desc, double default_val,
336336
/*
337337
* add_string_reloption
338338
* Add a new string reloption
339+
*
340+
* "validator" is an optional function pointer that can be used to test the
341+
* validity of the values. It must elog(ERROR) when the argument string is
342+
* not acceptable for the variable. Note that the default value must pass
343+
* the validation.
339344
*/
340345
void
341-
add_string_reloption(int kind, char *name, char *desc, char *default_val)
346+
add_string_reloption(int kind, char *name, char *desc, char *default_val,
347+
validate_string_relopt validator)
342348
{
343349
MemoryContext oldcxt;
344350
relopt_string *newoption;
@@ -359,6 +365,7 @@ add_string_reloption(int kind, char *name, char *desc, char *default_val)
359365
newoption->gen.kind = kind;
360366
newoption->gen.namelen = strlen(name);
361367
newoption->gen.type = RELOPT_TYPE_STRING;
368+
newoption->validate_cb = validator;
362369
if (default_val)
363370
{
364371
strcpy(newoption->default_val, default_val);
@@ -372,6 +379,10 @@ add_string_reloption(int kind, char *name, char *desc, char *default_val)
372379
newoption->default_isnull = true;
373380
}
374381

382+
/* make sure the validator/default combination is sane */
383+
if (newoption->validate_cb)
384+
(newoption->validate_cb) (newoption->default_val, true);
385+
375386
MemoryContextSwitchTo(oldcxt);
376387

377388
add_reloption((relopt_gen *) newoption);
@@ -729,10 +740,15 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
729740
}
730741
break;
731742
case RELOPT_TYPE_STRING:
732-
option->values.string_val = value;
733-
nofree = true;
734-
parsed = true;
735-
/* no validation possible */
743+
{
744+
relopt_string *optstring = (relopt_string *) option->gen;
745+
746+
option->values.string_val = value;
747+
nofree = true;
748+
if (optstring->validate_cb)
749+
(optstring->validate_cb) (value, validate);
750+
parsed = true;
751+
}
736752
break;
737753
default:
738754
elog(ERROR, "unsupported reloption type %d", option->gen->type);

src/include/access/reloptions.h

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
1212
* Portions Copyright (c) 1994, Regents of the University of California
1313
*
14-
* $PostgreSQL: pgsql/src/include/access/reloptions.h,v 1.8 2009/01/06 14:47:37 alvherre Exp $
14+
* $PostgreSQL: pgsql/src/include/access/reloptions.h,v 1.9 2009/01/08 19:34:41 alvherre Exp $
1515
*
1616
*-------------------------------------------------------------------------
1717
*/
@@ -90,11 +90,14 @@ typedef struct relopt_real
9090
double max;
9191
} relopt_real;
9292

93+
typedef void (*validate_string_relopt) (char *value, bool validate);
94+
9395
typedef struct relopt_string
9496
{
9597
relopt_gen gen;
9698
int default_len;
9799
bool default_isnull;
100+
validate_string_relopt validate_cb;
98101
char default_val[1]; /* variable length */
99102
} relopt_string;
100103

@@ -113,7 +116,7 @@ typedef struct relopt_string
113116
* need this information.
114117
*/
115118
#define HAVE_RELOPTION(optname, option) \
116-
(pg_strncasecmp(option.gen->name, optname, option.gen->namelen) == 0)
119+
(pg_strncasecmp(option.gen->name, optname, option.gen->namelen + 1) == 0)
117120

118121
#define HANDLE_INT_RELOPTION(optname, var, option, wasset) \
119122
do { \
@@ -141,7 +144,7 @@ typedef struct relopt_string
141144
} \
142145
} while (0)
143146

144-
#define HANDLE_REAL_RELOPTION(optname, var, option, wasset) \
147+
#define HANDLE_REAL_RELOPTION(optname, var, option, wasset) \
145148
do { \
146149
if (HAVE_RELOPTION(optname, option)) \
147150
{ \
@@ -166,30 +169,48 @@ typedef struct relopt_string
166169
* string options have been processed.
167170
*/
168171
#define HANDLE_STRING_RELOPTION(optname, var, option, base, offset, wasset) \
169-
do { \
172+
do { \
170173
if (HAVE_RELOPTION(optname, option)) \
171174
{ \
172175
relopt_string *optstring = (relopt_string *) option.gen;\
173-
char *string_val = NULL; \
174-
\
176+
char *string_val; \
175177
if (option.isset) \
176178
string_val = option.values.string_val; \
177179
else if (!optstring->default_isnull) \
178180
string_val = optstring->default_val; \
181+
else \
182+
string_val = NULL; \
179183
(wasset) != NULL ? *(wasset) = option.isset : (dummyret) NULL; \
180-
\
181-
if (!string_val) \
184+
if (string_val == NULL) \
182185
var = 0; \
183186
else \
184187
{ \
185-
strcpy((char *)(base) + (offset), string_val); \
188+
strcpy(((char *)(base)) + (offset), string_val); \
186189
var = (offset); \
187190
(offset) += strlen(string_val) + 1; \
188191
} \
189192
continue; \
190193
} \
191194
} while (0)
192195

196+
/*
197+
* For use during amoptions: get the strlen of a string option
198+
* (either default or the user defined value)
199+
*/
200+
#define GET_STRING_RELOPTION_LEN(option) \
201+
((option).isset ? strlen((option).values.string_val) : \
202+
((relopt_string *) (option).gen)->default_len)
203+
204+
/*
205+
* For use by code reading options already parsed: get a pointer to the string
206+
* value itself. "optstruct" is the StdRdOption struct or equivalent, "member"
207+
* is the struct member corresponding to the string option
208+
*/
209+
#define GET_STRING_RELOPTION(optstruct, member) \
210+
((optstruct)->member == 0 ? NULL : \
211+
(char *)(optstruct) + (optstruct)->member)
212+
213+
193214
extern int add_reloption_kind(void);
194215
extern void add_bool_reloption(int kind, char *name, char *desc,
195216
bool default_val);
@@ -198,7 +219,7 @@ extern void add_int_reloption(int kind, char *name, char *desc,
198219
extern void add_real_reloption(int kind, char *name, char *desc,
199220
double default_val, double min_val, double max_val);
200221
extern void add_string_reloption(int kind, char *name, char *desc,
201-
char *default_val);
222+
char *default_val, validate_string_relopt validator);
202223

203224
extern Datum transformRelOptions(Datum oldOptions, List *defList,
204225
bool ignoreOids, bool isReset);

0 commit comments

Comments
 (0)