88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.17 2009/01/08 19:34:41 alvherre Exp $
11+ * $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.18 2009/01/12 21:02:14 alvherre Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
3333 *
3434 * To add an option:
3535 *
36- * (i) decide on a class (integer, real, bool, string), name, default value,
37- * upper and lower bounds (if applicable).
38- * (ii) add a record below.
39- * (iii) add it to StdRdOptions if appropriate
40- * (iv) add a block to the appropriate handling routine (probably
36+ * (i) decide on a type (integer, real, bool, string), name, default value,
37+ * upper and lower bounds (if applicable); for strings, consider a validation
38+ * routine.
39+ * (ii) add a record below (or use add_<type>_reloption).
40+ * (iii) add it to the appropriate options struct (perhaps StdRdOptions)
41+ * (iv) add it to the appropriate handling routine (perhaps
4142 * default_reloptions)
4243 * (v) don't forget to document the option
4344 *
@@ -381,7 +382,7 @@ add_string_reloption(int kind, char *name, char *desc, char *default_val,
381382
382383/* make sure the validator/default combination is sane */
383384if (newoption -> validate_cb )
384- (newoption -> validate_cb ) (newoption -> default_val , true );
385+ (newoption -> validate_cb ) (newoption -> default_val );
385386
386387MemoryContextSwitchTo (oldcxt );
387388
@@ -745,8 +746,8 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
745746
746747option -> values .string_val = value ;
747748nofree = true;
748- if (optstring -> validate_cb )
749- (optstring -> validate_cb ) (value , validate );
749+ if (validate && optstring -> validate_cb )
750+ (optstring -> validate_cb ) (value );
750751parsed = true;
751752}
752753break ;
@@ -762,6 +763,110 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
762763pfree (value );
763764}
764765
766+ /*
767+ * Given the result from parseRelOptions, allocate a struct that's of the
768+ * specified base size plus any extra space that's needed for string variables.
769+ *
770+ * "base" should be sizeof(struct) of the reloptions struct (StdRdOptions or
771+ * equivalent).
772+ */
773+ void *
774+ allocateReloptStruct (Size base ,relopt_value * options ,int numoptions )
775+ {
776+ Size size = base ;
777+ int i ;
778+
779+ for (i = 0 ;i < numoptions ;i ++ )
780+ if (options [i ].gen -> type == RELOPT_TYPE_STRING )
781+ size += GET_STRING_RELOPTION_LEN (options [i ])+ 1 ;
782+
783+ return palloc0 (size );
784+ }
785+
786+ /*
787+ * Given the result of parseRelOptions and a parsing table, fill in the
788+ * struct (previously allocated with allocateReloptStruct) with the parsed
789+ * values.
790+ *
791+ * rdopts is the pointer to the allocated struct to be filled; basesize is
792+ * the sizeof(struct) that was passed to allocateReloptStruct. options and
793+ * numoptions are parseRelOptions' output. elems and numelems is the array
794+ * of elements to be parsed. Note that when validate is true, it is expected
795+ * that all options are also in elems.
796+ */
797+ void
798+ fillRelOptions (void * rdopts ,Size basesize ,relopt_value * options ,
799+ int numoptions ,bool validate ,relopt_parse_elt * elems ,
800+ int numelems )
801+ {
802+ int i ;
803+ int offset = basesize ;
804+
805+ for (i = 0 ;i < numoptions ;i ++ )
806+ {
807+ int j ;
808+ bool found = false;
809+
810+ for (j = 0 ;j < numelems ;j ++ )
811+ {
812+ if (pg_strcasecmp (options [i ].gen -> name ,elems [j ].optname )== 0 )
813+ {
814+ relopt_string * optstring ;
815+ char * itempos = ((char * )rdopts )+ elems [j ].offset ;
816+ char * string_val ;
817+
818+ switch (options [i ].gen -> type )
819+ {
820+ case RELOPT_TYPE_BOOL :
821+ * (bool * )itempos = options [i ].isset ?
822+ options [i ].values .bool_val :
823+ ((relopt_bool * )options [i ].gen )-> default_val ;
824+ break ;
825+ case RELOPT_TYPE_INT :
826+ * (int * )itempos = options [i ].isset ?
827+ options [i ].values .int_val :
828+ ((relopt_int * )options [i ].gen )-> default_val ;
829+ break ;
830+ case RELOPT_TYPE_REAL :
831+ * (double * )itempos = options [i ].isset ?
832+ options [i ].values .real_val :
833+ ((relopt_real * )options [i ].gen )-> default_val ;
834+ break ;
835+ case RELOPT_TYPE_STRING :
836+ optstring = (relopt_string * )options [i ].gen ;
837+ if (options [i ].isset )
838+ string_val = options [i ].values .string_val ;
839+ else if (!optstring -> default_isnull )
840+ string_val = optstring -> default_val ;
841+ else
842+ string_val = NULL ;
843+
844+ if (string_val == NULL )
845+ * (int * )itempos = 0 ;
846+ else
847+ {
848+ strcpy ((char * )rdopts + offset ,string_val );
849+ * (int * )itempos = offset ;
850+ offset += strlen (string_val )+ 1 ;
851+ }
852+ break ;
853+ default :
854+ elog (ERROR ,"unrecognized reloption type %c" ,
855+ options [i ].gen -> type );
856+ break ;
857+ }
858+ found = true;
859+ break ;
860+ }
861+ }
862+ if (validate && !found )
863+ elog (ERROR ,"storate parameter \"%s\" not found in parse table" ,
864+ options [i ].gen -> name );
865+ }
866+ SET_VARSIZE (rdopts ,offset );
867+ }
868+
869+
765870/*
766871 * Option parser for anything that uses StdRdOptions (i.e. fillfactor only)
767872 */
@@ -770,32 +875,24 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
770875{
771876relopt_value * options ;
772877StdRdOptions * rdopts ;
773- StdRdOptions lopts ;
774878int numoptions ;
775- int len ;
776- int i ;
879+ relopt_parse_elt tab []= {
880+ {"fillfactor" ,RELOPT_TYPE_INT , offsetof(StdRdOptions ,fillfactor )}
881+ };
777882
778883options = parseRelOptions (reloptions ,validate ,kind ,& numoptions );
779884
780885/* if none set, we're done */
781886if (numoptions == 0 )
782887return NULL ;
783888
784- MemSet ( & lopts , 0 , sizeof (StdRdOptions ));
889+ rdopts = allocateReloptStruct ( sizeof (StdRdOptions ), options , numoptions );
785890
786- for (i = 0 ;i < numoptions ;i ++ )
787- {
788- HANDLE_INT_RELOPTION ("fillfactor" ,lopts .fillfactor ,options [i ],
789- (char * )NULL );
790- }
891+ fillRelOptions ((void * )rdopts ,sizeof (StdRdOptions ),options ,numoptions ,
892+ validate ,tab ,lengthof (tab ));
791893
792894pfree (options );
793895
794- len = sizeof (StdRdOptions );
795- rdopts = palloc (len );
796- memcpy (rdopts ,& lopts ,len );
797- SET_VARSIZE (rdopts ,len );
798-
799896return (bytea * )rdopts ;
800897}
801898