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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy