*** src/backend/access/common/reloptions.c	6 Jan 2009 14:47:37 -0000	1.16
--- src/backend/access/common/reloptions.c	7 Jan 2009 13:35:42 -0000
***************
*** 336,344 ****
  /*
   * add_string_reloption
   *		Add a new string reloption
   */
  void
! add_string_reloption(int kind, char *name, char *desc, char *default_val)
  {
  	MemoryContext	oldcxt;
  	relopt_string  *newoption;
--- 336,350 ----
  /*
   * add_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
! add_string_reloption(int kind, char *name, char *desc, char *default_val,
! 					 validate_string_relopt validator)
  {
  	MemoryContext	oldcxt;
  	relopt_string  *newoption;
***************
*** 359,364 ****
--- 365,371 ----
  	newoption->gen.kind = kind;
  	newoption->gen.namelen = strlen(name);
  	newoption->gen.type = RELOPT_TYPE_STRING;
+ 	newoption->validate_cb = validator;
  	if (default_val)
  	{
  		strcpy(newoption->default_val, default_val);
***************
*** 372,377 ****
--- 379,388 ----
  		newoption->default_isnull = true;
  	}
  
+ 	/* make sure the validator/default combination is sane */
+ 	if (newoption->validate_cb)
+ 		(newoption->validate_cb) (newoption->default_val);
+ 
  	MemoryContextSwitchTo(oldcxt);
  
  	add_reloption((relopt_gen *) newoption);
***************
*** 729,738 ****
  			}
  			break;
  		case RELOPT_TYPE_STRING:
! 			option->values.string_val = value;
! 			nofree = true;
! 			parsed = true;
! 			/* no validation possible */
  			break;
  		default:
  			elog(ERROR, "unsupported reloption type %d", option->gen->type);
--- 740,754 ----
  			}
  			break;
  		case RELOPT_TYPE_STRING:
! 			{
! 				relopt_string   *optstring = (relopt_string *) option->gen;
! 
! 				option->values.string_val = value;
! 				nofree = true;
! 				if (optstring->validate_cb)
! 					(optstring->validate_cb) (value);
! 				parsed = true;
! 			}
  			break;
  		default:
  			elog(ERROR, "unsupported reloption type %d", option->gen->type);
*** src/include/access/reloptions.h	6 Jan 2009 14:47:37 -0000	1.8
--- src/include/access/reloptions.h	7 Jan 2009 13:31:25 -0000
***************
*** 90,100 ****
--- 90,103 ----
  	double		max;
  } relopt_real;
  
+ typedef void (*validate_string_relopt) (char *);
+ 
  typedef struct relopt_string
  {
  	relopt_gen	gen;
  	int			default_len;
  	bool		default_isnull;
+ 	validate_string_relopt	validate_cb;
  	char		default_val[1];	/* variable length */
  } relopt_string;
  
***************
*** 113,119 ****
   * need this information.
   */
  #define HAVE_RELOPTION(optname, option) \
! 	(pg_strncasecmp(option.gen->name, optname, option.gen->namelen) == 0)
  
  #define HANDLE_INT_RELOPTION(optname, var, option, wasset)			\
  	do {															\
--- 116,122 ----
   * need this information.
   */
  #define HAVE_RELOPTION(optname, option) \
! 	(pg_strncasecmp(option.gen->name, optname, option.gen->namelen + 1) == 0)
  
  #define HANDLE_INT_RELOPTION(optname, var, option, wasset)			\
  	do {															\
***************
*** 124,130 ****
  			else													\
  				var = ((relopt_int *) option.gen)->default_val; 	\
  			(wasset) != NULL ? *(wasset) = option.isset : (dummyret)NULL; \
- 			continue;												\
  		}															\
  	} while (0)
  
--- 127,132 ----
***************
*** 137,143 ****
  			else													\
  				var = ((relopt_bool *) option.gen)->default_val;	\
  			(wasset) != NULL ? *(wasset) = option.isset : (dummyret) NULL; \
- 			continue;												\
  		}															\
  	} while (0)
  
--- 139,144 ----
***************
*** 150,156 ****
  			else													\
  				var = ((relopt_real *) option.gen)->default_val;	\
  			(wasset) != NULL ? *(wasset) = option.isset : (dummyret) NULL; \
- 			continue;												\
  		}															\
  	} while (0)
  
--- 151,156 ----
***************
*** 170,195 ****
  		if (HAVE_RELOPTION(optname, option))						\
  		{															\
  			relopt_string *optstring = (relopt_string *) option.gen;\
! 			char *string_val = NULL;								\
  																	\
  			if (option.isset)										\
  				string_val = option.values.string_val;				\
  			else if (!optstring->default_isnull)					\
  				string_val = optstring->default_val;				\
  			(wasset) != NULL ? *(wasset) = option.isset : (dummyret) NULL; \
  																	\
! 			if (!string_val)										\
  				var = 0;											\
  			else													\
  			{														\
! 				strcpy((char *)(base) + (offset), string_val);		\
  				var = (offset);										\
  				(offset) += strlen(string_val) + 1;					\
  			}														\
- 			continue;												\
  		}															\
  	} while (0)
  
  extern int add_reloption_kind(void);
  extern void add_bool_reloption(int kind, char *name, char *desc,
  				   bool default_val);
--- 170,214 ----
  		if (HAVE_RELOPTION(optname, option))						\
  		{															\
  			relopt_string *optstring = (relopt_string *) option.gen;\
! 			char *string_val;										\
  																	\
  			if (option.isset)										\
  				string_val = option.values.string_val;				\
  			else if (!optstring->default_isnull)					\
  				string_val = optstring->default_val;				\
+ 			else													\
+ 				string_val = NULL;									\
  			(wasset) != NULL ? *(wasset) = option.isset : (dummyret) NULL; \
  																	\
! 			if (string_val == NULL)									\
  				var = 0;											\
  			else													\
  			{														\
! 				strcpy(((char *)(base)) + (offset), string_val);	\
  				var = (offset);										\
  				(offset) += strlen(string_val) + 1;					\
  			}														\
  		}															\
  	} 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 void add_bool_reloption(int kind, char *name, char *desc,
  				   bool default_val);
***************
*** 198,204 ****
  extern void add_real_reloption(int kind, char *name, char *desc,
  				   double default_val, double min_val, double max_val);
  extern void add_string_reloption(int kind, char *name, char *desc,
! 					 char *default_val);
  			
  extern Datum transformRelOptions(Datum oldOptions, List *defList,
  					bool ignoreOids, bool isReset);
--- 217,223 ----
  extern void add_real_reloption(int kind, char *name, char *desc,
  				   double default_val, double min_val, double max_val);
  extern void add_string_reloption(int kind, char *name, char *desc,
! 					 char *default_val, validate_string_relopt validator);
  			
  extern Datum transformRelOptions(Datum oldOptions, List *defList,
  					bool ignoreOids, bool isReset);
