Alvaro Herrera escreveu:
> So I gave up waiting for someone else to do the reloptions patch for
> autovacuum and started work on it myself.  What I soon discovered is
> that on first blush it seems a lot easier than I had expected.
> 
Sorry about that. :( I was swamped with PGCon Brasil and then I took
some days to rest. I'm expecting to finish it before next CF.

What did I already do? I refactored reloptions.c to support multiple
options. I tried to follow up the same way GUC do (of course, it is much
 simpler). I'm thinking about removing (replacing?) StdRdOptions 'cause
we need a different struct to store reloptions. Suggestions?

I'm attaching the WIP patch so you can comment on it. I want to continue
working on it but I'm afraid you already did more than I do (in this
case, let me know for not duplicating efforts).


-- 
  Euler Taveira de Oliveira
  http://www.timbira.com/
Index: src/backend/access/common/reloptions.c
===================================================================
RCS file: /a/pgsql/dev/anoncvs/pgsql/src/backend/access/common/reloptions.c,v
retrieving revision 1.11
diff -c -r1.11 reloptions.c
*** src/backend/access/common/reloptions.c      23 Jul 2008 17:29:53 -0000      
1.11
--- src/backend/access/common/reloptions.c      10 Oct 2008 13:55:15 -0000
***************
*** 24,29 ****
--- 24,182 ----
  #include "utils/guc.h"
  #include "utils/rel.h"
  
+ /*
+  * Contents of pg_class.reloptions
+  *
+  * To add an option:
+  *
+  * (i) decide on a class (integer, double, bool), name, default value, upper
+  * and lower bounds (if applicable).
+  *
+  * (ii) add a record below.
+  *
+  * (iii) don't forget to document the option
+  */
+ 
+ static struct relopt_bool     relOptBools[] =
+ {
+       {
+               {
+                       "autovacuum_enabled",
+                       "Enables autovacuum in this relation",
+                       RO_BOOL
+               },
+               false
+       },
+       /* End-of-list marker */
+       {
+               {
+                       NULL,
+                       NULL,
+                       RO_BOOL
+               },
+               false
+       }
+ };
+ 
+ static struct relopt_int      relOptInts[] =
+ {
+       {
+               {
+                       "fillfactor",
+                       "Packs table pages only to this percentage",
+                       RO_INT
+               },
+               100,
+               10,
+               100
+       },
+       {
+               {
+                       "autovacuum_vac_base_thresh",
+                       "Minimum number of tuple updates or deletes prior to 
vacuum",
+                       RO_INT
+               },
+               50,
+               0,
+               INT_MAX
+       },
+       {
+               {
+                       "autovacuum_anl_base_thresh",
+                       "Minimum number of tuple inserts, updates or deletes 
prior to analyze",
+                       RO_INT
+               },
+               50,
+               0,
+               INT_MAX
+       },
+       {
+               {
+                       "autovacuum_vac_cost_delay",
+                       "Vacuum cost delay in milliseconds, for autovacuum",
+                       RO_INT
+               },
+               20,
+               -1,
+               1000
+       },
+       {
+               {
+                       "autovacuum_vac_cost_limit",
+                       "Vacuum cost ammount available before napping, for 
autovacuum",
+                       RO_INT
+               },
+               -1,
+               -1,
+               10000
+       },
+       {
+               {
+                       "autovacuum_freeze_min_age",
+                       "Minimum age at which VACUUM should freeze a table row, 
for autovacuum",
+                       RO_INT
+               },
+               100000000,
+               0,
+               1000000000
+       },
+       {
+               {
+                       "autovacuum_freeze_max_age",
+                       "Age at which to autovacuum a table to prevent 
transaction ID wraparound",
+                       RO_INT
+               },
+               200000000,
+               100000000,
+               2000000000
+       },
+       /* End-of-list marker */
+       {
+               {
+                       NULL,
+                       NULL,
+                       RO_INT
+               },
+               0,
+               0,
+               0
+       }
+ };
+ 
+ struct relopt_real    relOptReals[] =
+ {
+       {
+               {
+                       "autovacuum_vac_scale_factor",
+                       "Number of tuples inserts, updates or deletes prior to 
vacuum as a fraction of reltuples",
+                       RO_REAL
+               },
+               0.2,
+               0.0,
+               100.0
+       },
+       {
+               {
+                       "autovacuum_anl_scale_factor",
+                       "Number of tuples inserts, updates or deletes prior to 
analyze as a fraction of reltuples",
+                       RO_REAL
+               },
+               0.1,
+               0.0,
+               100.0
+       },
+       /* End-of-list marker */
+       {
+               {
+                       NULL,
+                       NULL,
+                       RO_REAL
+               },
+               0.0,
+               0.0,
+               0.0
+       }
+ };
  
  /*
   * Transform a relation options list (list of DefElem) into the text array
***************
*** 51,56 ****
--- 204,212 ----
        ArrayBuildState *astate;
        ListCell   *cell;
  
+       ereport(DEBUG2,
+                       (errmsg("starting transformRelOptions() ...")));
+ 
        /* no change if empty list */
        if (defList == NIL)
                return oldOptions;
***************
*** 77,82 ****
--- 233,243 ----
                        char       *text_str = VARDATA(oldoption);
                        int                     text_len = VARSIZE(oldoption) - 
VARHDRSZ;
  
+                       char *tmp = text_str;
+                       tmp[text_len] = '\0';
+                       ereport(DEBUG1,
+                                       (errmsg("old reloption: %s", 
text_str)));
+ 
                        /* Search for a match in defList */
                        foreach(cell, defList)
                        {
***************
*** 93,98 ****
--- 254,261 ----
                                astate = accumArrayResult(astate, oldoptions[i],
                                                                                
  false, TEXTOID,
                                                                                
  CurrentMemoryContext);
+                               ereport(DEBUG1,
+                                               (errmsg("added old reloption: 
%s", tmp)));
                        }
                }
        }
***************
*** 136,141 ****
--- 299,307 ----
                        SET_VARSIZE(t, len);
                        sprintf(VARDATA(t), "%s=%s", def->defname, value);
  
+                       ereport(DEBUG1,
+                                       (errmsg("added new reloption: %s=%s", 
def->defname, value)));
+ 
                        astate = accumArrayResult(astate, PointerGetDatum(t),
                                                                          
false, TEXTOID,
                                                                          
CurrentMemoryContext);
***************
*** 147,152 ****
--- 313,321 ----
        else
                result = (Datum) 0;
  
+       ereport(DEBUG2,
+                       (errmsg("ending transformRelOptions() ...")));
+ 
        return result;
  }
  
***************
*** 164,169 ****
--- 333,341 ----
        int                     noptions;
        int                     i;
  
+       ereport(DEBUG2,
+                       (errmsg("starting untransformRelOptions() ...")));
+ 
        /* Nothing to do if no options */
        if (!PointerIsValid(DatumGetPointer(options)))
                return result;
***************
*** 188,196 ****
--- 360,375 ----
                        *p++ = '\0';
                        val = (Node *) makeString(pstrdup(p));
                }
+ 
+               ereport(DEBUG1,
+                               (errmsg("added reloption: %s=%s", s, p)));
+ 
                result = lappend(result, makeDefElem(pstrdup(s), val));
        }
  
+       ereport(DEBUG2,
+                       (errmsg("ending untransformRelOptions() ...")));
+ 
        return result;
  }
  
***************
*** 199,206 ****
   * Interpret reloptions that are given in text-array format.
   *
   *    options: array of "keyword=value" strings, as built by 
transformRelOptions
-  *    numkeywords: number of legal keywords
-  *    keywords: the allowed keywords
   *    values: output area
   *    validate: if true, throw error for unrecognized keywords.
   *
--- 378,383 ----
***************
*** 209,221 ****
   * containing the corresponding value, or NULL if the keyword does not appear.
   */
  void
! parseRelOptions(Datum options, int numkeywords, const char *const * keywords,
!                               char **values, bool validate)
  {
        ArrayType  *array;
        Datum      *optiondatums;
        int                     noptions;
        int                     i;
  
        /* Initialize to "all defaulted" */
        MemSet(values, 0, numkeywords * sizeof(char *));
--- 386,410 ----
   * containing the corresponding value, or NULL if the keyword does not appear.
   */
  void
! parseRelOptions(Datum options, char **values, bool validate, int 
minFillfactor)
  {
        ArrayType  *array;
        Datum      *optiondatums;
        int                     noptions;
        int                     i;
+       int                     numkeywords = 0;
+ 
+       ereport(DEBUG2,
+                       (errmsg("starting parseRelOptions() ...")));
+ 
+       for (i = 0; relOptBools[i].gen.name; i++)
+               numkeywords++;
+       for (i = 0; relOptInts[i].gen.name; i++)
+               numkeywords++;
+       for (i = 0; relOptReals[i].gen.name; i++)
+               numkeywords++;
+       ereport(DEBUG1,
+                       (errmsg("number of keywords: %d", numkeywords)));
  
        /* Initialize to "all defaulted" */
        MemSet(values, 0, numkeywords * sizeof(char *));
***************
*** 236,267 ****
                text       *optiontext = DatumGetTextP(optiondatums[i]);
                char       *text_str = VARDATA(optiontext);
                int                     text_len = VARSIZE(optiontext) - 
VARHDRSZ;
!               int                     j;
  
                /* Search for a match in keywords */
!               for (j = 0; j < numkeywords; j++)
                {
!                       int                     kw_len = strlen(keywords[j]);
  
                        if (text_len > kw_len && text_str[kw_len] == '=' &&
!                               pg_strncasecmp(text_str, keywords[j], kw_len) 
== 0)
                        {
!                               char       *value;
!                               int                     value_len;
  
                                if (values[j] && validate)
                                        ereport(ERROR,
                                                        
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!                                                 errmsg("parameter \"%s\" 
specified more than once",
!                                                                keywords[j])));
                                value_len = text_len - kw_len - 1;
                                value = (char *) palloc(value_len + 1);
                                memcpy(value, text_str + kw_len + 1, value_len);
                                value[value_len] = '\0';
                                values[j] = value;
                                break;
                        }
                }
                if (j >= numkeywords && validate)
                {
                        char       *s;
--- 425,574 ----
                text       *optiontext = DatumGetTextP(optiondatums[i]);
                char       *text_str = VARDATA(optiontext);
                int                     text_len = VARSIZE(optiontext) - 
VARHDRSZ;
!               int                     j = 0;
!               bool            found = false;
! 
!               char *tmp = text_str;
!               tmp[text_len] = '\0';
!               ereport(DEBUG1,
!                               (errmsg("parsing reloption %s ...", tmp)));
  
                /* Search for a match in keywords */
!               while (relOptBools[j].gen.name)
                {
!                       int             kw_len = 
strlen(relOptBools[j].gen.name);
  
                        if (text_len > kw_len && text_str[kw_len] == '=' &&
!                               pg_strcasecmp(text_str, 
relOptBools[j].gen.name, kw_len) == 0)
                        {
!                               char    *value;
!                               int             value_len;
  
                                if (values[j] && validate)
                                        ereport(ERROR,
                                                        
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!                                               errmsg("parameter \"%s\" 
specified more than once",
!                                                               
relOptBools[j].gen.name)));
! 
                                value_len = text_len - kw_len - 1;
                                value = (char *) palloc(value_len + 1);
                                memcpy(value, text_str + kw_len + 1, value_len);
                                value[value_len] = '\0';
+ 
+                               if (parse_bool(value, NULL) == false && 
validate)
+                                       ereport(ERROR,
+                                                       
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                        errmsg("invalid input 
value for parameter %s: \"%s\"",
+                                                                       
relOptBools[j].gen.name, value),
+                                                        errhint("value must be 
a boolean")));
+ 
                                values[j] = value;
+ 
+                               found = true;
                                break;
                        }
+ 
+                       j++;
                }
+ 
+               while (relOptInts[j].gen.name || !found)
+               {
+                       int             kw_len = strlen(relOptInts[j].gen.name);
+ 
+                       if (text_len > kw_len && text_str[kw_len] == '=' &&
+                               pg_strcasecmp(text_str, relOptInts[j].gen.name, 
kw_len) == 0)
+                       {
+                               char    *value;
+                               int             value_len;
+ 
+                               if (values[j] && validate)
+                                       ereport(ERROR,
+                                                       
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                               errmsg("parameter \"%s\" 
specified more than once",
+                                                               
relOptInts[j].gen.name)));
+ 
+                               value_len = text_len - kw_len - 1;
+                               value = (char *) palloc(value_len + 1);
+                               memcpy(value, text_str + kw_len + 1, value_len);
+                               value[value_len] = '\0';
+ 
+                               if (parse_int(value, NULL, 0, NULL) == false && 
validate)
+                                       ereport(ERROR,
+                                                       
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                        errmsg("invalid input 
value for parameter %s: \"%s\"",
+                                                                       
relOptBools[j].gen.name, value),
+                                                        errhint("value must be 
an integer")));
+ 
+                               if ((value < relOptInts[j].min || value > 
relOptInts[j].max) && validate)
+                                       ereport(ERROR,
+                                                       
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                        errmsg("%s=%s is out 
of range (should be between %d and %d)",
+                                                                       
relOptInts[j].gen.name, value, relOptInts[j].min, relOptInts[j].max)));
+ 
+                               /* 
+                                * Especial check for fillfactor because 
minimum fillfactor values
+                                * are AMs and/or heap dependant. We don't need 
to check upper
+                                * limit because we already did it above.
+                                */
+                               if (pg_strcasecmp(relOptInts[j].gen.name, 
"fillfactor") == 0 &&
+                                               value < minFillfactor && 
validate)
+                                       ereport(ERROR,
+                                                       
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                        errmsg("fillfactor=%s 
is out of range (should be between %d and 100)",
+                                                                value, 
minFillfactor)));
+ 
+                               values[j] = value;
+ 
+                               found = true;
+                               break;
+                       }
+ 
+                       j++;
+               }
+ 
+               while (relOptReals[j].gen.name || !found)
+               {
+                       int             kw_len = 
strlen(relOptReals[j].gen.name);
+ 
+                       if (text_len > kw_len && text_str[kw_len] == '=' &&
+                               pg_strcasecmp(text_str, 
relOptReals[j].gen.name, kw_len) == 0)
+                       {
+                               char    *value;
+                               int             value_len;
+ 
+                               if (values[j] && validate)
+                                       ereport(ERROR,
+                                                       
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                               errmsg("parameter \"%s\" 
specified more than once",
+                                                               
relOptReals[j].gen.name)));
+ 
+                               value_len = text_len - kw_len - 1;
+                               value = (char *) palloc(value_len + 1);
+                               memcpy(value, text_str + kw_len + 1, value_len);
+                               value[value_len] = '\0';
+ 
+                               if (parse_real(value, NULL) == false && 
validate)
+                                       ereport(ERROR,
+                                                       
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                        errmsg("invalid input 
value for parameter %s: \"%s\"",
+                                                                       
relOptBools[j].gen.name, value),
+                                                        errhint("value must be 
a float")));
+ 
+                               if ((value < relOptReals[j].min || value > 
relOptReals[j].max) && validate)
+                                       ereport(ERROR,
+                                                       
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                        errmsg("%s=%s is out 
of range (should be between %d and %d)",
+                                                                       
relOptReals[j].gen.name, value, relOptReals[j].min, relOptReals[j].max)));
+ 
+                               values[j] = value;
+ 
+                               found = true;
+                               break;
+                       }
+ 
+                       j++;
+               }
+ 
                if (j >= numkeywords && validate)
                {
                        char       *s;
***************
*** 276,281 ****
--- 583,591 ----
                                         errmsg("unrecognized parameter 
\"%s\"", s)));
                }
        }
+ 
+       ereport(DEBUG2,
+                       (errmsg("ending parseRelOptions() ...")));
  }
  
  
***************
*** 286,297 ****
  default_reloptions(Datum reloptions, bool validate,
                                   int minFillfactor, int defaultFillfactor)
  {
-       static const char *const default_keywords[1] = {"fillfactor"};
        char       *values[1];
        int                     fillfactor;
        StdRdOptions *result;
  
!       parseRelOptions(reloptions, 1, default_keywords, values, validate);
  
        /*
         * If no options, we can just return NULL rather than doing anything.
--- 596,609 ----
  default_reloptions(Datum reloptions, bool validate,
                                   int minFillfactor, int defaultFillfactor)
  {
        char       *values[1];
        int                     fillfactor;
        StdRdOptions *result;
  
!       ereport(DEBUG2,
!                       (errmsg("starting default_options() ...")));
! 
!       parseRelOptions(reloptions, values, validate, minFillfactor);
  
        /*
         * If no options, we can just return NULL rather than doing anything.
***************
*** 301,331 ****
        if (values[0] == NULL)
                return NULL;
  
-       if (!parse_int(values[0], &fillfactor, 0, NULL))
-       {
-               if (validate)
-                       ereport(ERROR,
-                                       
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                        errmsg("fillfactor must be an integer: 
\"%s\"",
-                                                       values[0])));
-               return NULL;
-       }
- 
-       if (fillfactor < minFillfactor || fillfactor > 100)
-       {
-               if (validate)
-                       ereport(ERROR,
-                                       
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                        errmsg("fillfactor=%d is out of range 
(should be between %d and 100)",
-                                                       fillfactor, 
minFillfactor)));
-               return NULL;
-       }
- 
        result = (StdRdOptions *) palloc(sizeof(StdRdOptions));
        SET_VARSIZE(result, sizeof(StdRdOptions));
  
        result->fillfactor = fillfactor;
  
        return (bytea *) result;
  }
  
--- 613,626 ----
        if (values[0] == NULL)
                return NULL;
  
        result = (StdRdOptions *) palloc(sizeof(StdRdOptions));
        SET_VARSIZE(result, sizeof(StdRdOptions));
  
        result->fillfactor = fillfactor;
  
+       ereport(DEBUG2,
+                       (errmsg("ending default_reloptions() ...")));
+ 
        return (bytea *) result;
  }
  
***************
*** 336,344 ****
  bytea *
  heap_reloptions(char relkind, Datum reloptions, bool validate)
  {
!       return default_reloptions(reloptions, validate,
!                                                         HEAP_MIN_FILLFACTOR,
!                                                         
HEAP_DEFAULT_FILLFACTOR);
  }
  
  
--- 631,642 ----
  bytea *
  heap_reloptions(char relkind, Datum reloptions, bool validate)
  {
!       ereport(DEBUG2,
!                       (errmsg("starting heap_reloptions() ...")));
! 
!       return default_reloptions(reloptions, validate, 
!                                                               
HEAP_MIN_FILLFACTOR, 
!                                                               
HEAP_DEFAULT_FILLFACTOR);
  }
  
  
***************
*** 356,361 ****
--- 654,662 ----
        FunctionCallInfoData fcinfo;
        Datum           result;
  
+       ereport(DEBUG2,
+                       (errmsg("starting index_reloptions() ...")));
+ 
        Assert(RegProcedureIsValid(amoptions));
  
        /* Assume function is strict */
***************
*** 377,381 ****
--- 678,685 ----
        if (fcinfo.isnull || DatumGetPointer(result) == NULL)
                return NULL;
  
+       ereport(DEBUG2,
+                       (errmsg("ending index_reloptions() ...")));
+ 
        return DatumGetByteaP(result);
  }
Index: src/backend/access/gin/ginutil.c
===================================================================
RCS file: /a/pgsql/dev/anoncvs/pgsql/src/backend/access/gin/ginutil.c,v
retrieving revision 1.17
diff -c -r1.17 ginutil.c
*** src/backend/access/gin/ginutil.c    30 Sep 2008 10:52:10 -0000      1.17
--- src/backend/access/gin/ginutil.c    2 Oct 2008 20:33:13 -0000
***************
*** 339,347 ****
  #define GIN_MIN_FILLFACTOR                    10
  #define GIN_DEFAULT_FILLFACTOR                100
  
!       result = default_reloptions(reloptions, validate,
!                                                               
GIN_MIN_FILLFACTOR,
                                                                
GIN_DEFAULT_FILLFACTOR);
        if (result)
                PG_RETURN_BYTEA_P(result);
        PG_RETURN_NULL();
--- 339,350 ----
  #define GIN_MIN_FILLFACTOR                    10
  #define GIN_DEFAULT_FILLFACTOR                100
  
!       /* TODO how can we pass the min|default fillfactor to reloptions? */
!       /* XXX different AM has different values! */
!       result = default_reloptions(reloptions, validate, 
!                                                               
GIN_MIN_FILLFACTOR, 
                                                                
GIN_DEFAULT_FILLFACTOR);
+ 
        if (result)
                PG_RETURN_BYTEA_P(result);
        PG_RETURN_NULL();
Index: src/backend/access/gist/gistutil.c
===================================================================
RCS file: /a/pgsql/dev/anoncvs/pgsql/src/backend/access/gist/gistutil.c,v
retrieving revision 1.31
diff -c -r1.31 gistutil.c
*** src/backend/access/gist/gistutil.c  30 Sep 2008 10:52:10 -0000      1.31
--- src/backend/access/gist/gistutil.c  2 Oct 2008 20:33:28 -0000
***************
*** 670,678 ****
        bool            validate = PG_GETARG_BOOL(1);
        bytea      *result;
  
!       result = default_reloptions(reloptions, validate,
!                                                               
GIST_MIN_FILLFACTOR,
                                                                
GIST_DEFAULT_FILLFACTOR);
        if (result)
                PG_RETURN_BYTEA_P(result);
        PG_RETURN_NULL();
--- 670,681 ----
        bool            validate = PG_GETARG_BOOL(1);
        bytea      *result;
  
!       /* TODO how can we pass the min|default fillfactor to reloptions? */
!       /* XXX different AM has different values! */
!       result = default_reloptions(reloptions, validate, 
!                                                               
GIST_MIN_FILLFACTOR, 
                                                                
GIST_DEFAULT_FILLFACTOR);
+ 
        if (result)
                PG_RETURN_BYTEA_P(result);
        PG_RETURN_NULL();
Index: src/backend/access/hash/hashutil.c
===================================================================
RCS file: /a/pgsql/dev/anoncvs/pgsql/src/backend/access/hash/hashutil.c,v
retrieving revision 1.57
diff -c -r1.57 hashutil.c
*** src/backend/access/hash/hashutil.c  15 Sep 2008 18:43:41 -0000      1.57
--- src/backend/access/hash/hashutil.c  2 Oct 2008 20:32:48 -0000
***************
*** 224,232 ****
        bool            validate = PG_GETARG_BOOL(1);
        bytea      *result;
  
!       result = default_reloptions(reloptions, validate,
!                                                               
HASH_MIN_FILLFACTOR,
                                                                
HASH_DEFAULT_FILLFACTOR);
        if (result)
                PG_RETURN_BYTEA_P(result);
        PG_RETURN_NULL();
--- 224,235 ----
        bool            validate = PG_GETARG_BOOL(1);
        bytea      *result;
  
!       /* TODO how can we pass the min|default fillfactor to reloptions? */
!       /* XXX different AM has different values! */
!       result = default_reloptions(reloptions, validate, 
!                                                               
HASH_MIN_FILLFACTOR, 
                                                                
HASH_DEFAULT_FILLFACTOR);
+ 
        if (result)
                PG_RETURN_BYTEA_P(result);
        PG_RETURN_NULL();
Index: src/backend/access/nbtree/nbtutils.c
===================================================================
RCS file: /a/pgsql/dev/anoncvs/pgsql/src/backend/access/nbtree/nbtutils.c,v
retrieving revision 1.91
diff -c -r1.91 nbtutils.c
*** src/backend/access/nbtree/nbtutils.c        19 Jun 2008 00:46:03 -0000      
1.91
--- src/backend/access/nbtree/nbtutils.c        2 Oct 2008 20:32:35 -0000
***************
*** 1402,1410 ****
        bool            validate = PG_GETARG_BOOL(1);
        bytea      *result;
  
!       result = default_reloptions(reloptions, validate,
!                                                               
BTREE_MIN_FILLFACTOR,
                                                                
BTREE_DEFAULT_FILLFACTOR);
        if (result)
                PG_RETURN_BYTEA_P(result);
        PG_RETURN_NULL();
--- 1402,1413 ----
        bool            validate = PG_GETARG_BOOL(1);
        bytea      *result;
  
!       /* TODO how can we pass the min|default fillfactor to reloptions? */
!       /* XXX different AM has different values! */
!       result = default_reloptions(reloptions, validate, 
!                                                               
BTREE_MIN_FILLFACTOR, 
                                                                
BTREE_DEFAULT_FILLFACTOR);
+ 
        if (result)
                PG_RETURN_BYTEA_P(result);
        PG_RETURN_NULL();
Index: src/include/access/reloptions.h
===================================================================
RCS file: /a/pgsql/dev/anoncvs/pgsql/src/include/access/reloptions.h,v
retrieving revision 1.5
diff -c -r1.5 reloptions.h
*** src/include/access/reloptions.h     1 Jan 2008 19:45:56 -0000       1.5
--- src/include/access/reloptions.h     7 Oct 2008 04:57:59 -0000
***************
*** 20,36 ****
  
  #include "nodes/pg_list.h"
  
  extern Datum transformRelOptions(Datum oldOptions, List *defList,
                                        bool ignoreOids, bool isReset);
  
  extern List *untransformRelOptions(Datum options);
  
! extern void parseRelOptions(Datum options, int numkeywords,
!                               const char *const * keywords,
!                               char **values, bool validate);
  
! extern bytea *default_reloptions(Datum reloptions, bool validate,
!                                  int minFillfactor, int defaultFillfactor);
  
  extern bytea *heap_reloptions(char relkind, Datum reloptions, bool validate);
  
--- 20,85 ----
  
  #include "nodes/pg_list.h"
  
+ /* types supported by reloptions */
+ enum ro_type
+ {
+       RO_BOOL,
+       RO_INT,
+       RO_REAL
+ };
+ 
+ /* kind supported by reloptions */
+ enum ro_kind
+ {
+       RO_INDEX,
+       RO_HEAP
+ };
+ 
+ /* generic struct to hold shared data */
+ struct relopt_gen
+ {
+       const char              *name;
+       const char              *desc;
+       enum ro_type    type;   /* type of variable */
+       enum ro_kind    kind;   /* index or heap? */
+ };
+ 
+ /* reloptions records for specific variable types */
+ struct relopt_bool
+ {
+       struct relopt_gen       gen;
+       bool                            value;
+       bool                            reset_value;    /* XXX useful? */
+ };
+       
+ struct relopt_int
+ {
+       struct relopt_gen       gen;
+       int                                     value;
+       int                                     min;
+       int                                     max;
+       int                                     reset_value;    /* XXX useful? 
*/
+ };
+       
+ struct relopt_real
+ {
+       struct relopt_gen       gen;
+       double                          value;
+       double                          min;
+       double                          max;
+       double                          reset_value;    /* XXX useful? */
+ };
+ 
  extern Datum transformRelOptions(Datum oldOptions, List *defList,
                                        bool ignoreOids, bool isReset);
  
  extern List *untransformRelOptions(Datum options);
  
! extern void parseRelOptions(Datum options, char **values, bool validate,
!                               int minFillfactor);
  
! extern bytea *default_reloptions(Datum reloptions, bool validate, 
!                               int minFillfactor, int defaultFillfactor);
  
  extern bytea *heap_reloptions(char relkind, Datum reloptions, bool validate);
  
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to