]> granicus.if.org Git - postgresql/commitdiff
A couple further reloptions improvements, per KaiGai Kohei: add a validation
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Thu, 8 Jan 2009 19:34:41 +0000 (19:34 +0000)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Thu, 8 Jan 2009 19:34:41 +0000 (19:34 +0000)
function to the string type and add a couple of macros for string handling.

In passing, fix an off-by-one bug of mine.

src/backend/access/common/reloptions.c
src/include/access/reloptions.h

index 7690da0e671a3b98aeda539e36d2dfac1fe5a3f3..600e6c7243dec323d75f732a7d80ccbd923e748d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.16 2009/01/06 14:47:37 alvherre Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.17 2009/01/08 19:34:41 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -336,9 +336,15 @@ add_real_reloption(int kind, char *name, char *desc, double default_val,
 /*
  * 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)
+add_string_reloption(int kind, char *name, char *desc, char *default_val,
+                                        validate_string_relopt validator)
 {
        MemoryContext   oldcxt;
        relopt_string  *newoption;
@@ -359,6 +365,7 @@ add_string_reloption(int kind, char *name, char *desc, char *default_val)
        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,6 +379,10 @@ add_string_reloption(int kind, char *name, char *desc, char *default_val)
                newoption->default_isnull = true;
        }
 
+       /* make sure the validator/default combination is sane */
+       if (newoption->validate_cb)
+               (newoption->validate_cb) (newoption->default_val, true);
+
        MemoryContextSwitchTo(oldcxt);
 
        add_reloption((relopt_gen *) newoption);
@@ -729,10 +740,15 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
                        }
                        break;
                case RELOPT_TYPE_STRING:
-                       option->values.string_val = value;
-                       nofree = true;
-                       parsed = true;
-                       /* no validation possible */
+                       {
+                               relopt_string   *optstring = (relopt_string *) option->gen;
+
+                               option->values.string_val = value;
+                               nofree = true;
+                               if (optstring->validate_cb)
+                                       (optstring->validate_cb) (value, validate);
+                               parsed = true;
+                       }
                        break;
                default:
                        elog(ERROR, "unsupported reloption type %d", option->gen->type);
index 5238c70904ac0c21f312cbb60b62125f6ee8d8da..5672cb4dcbfd6299e52aa80b1056827734c68f2f 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/reloptions.h,v 1.8 2009/01/06 14:47:37 alvherre Exp $
+ * $PostgreSQL: pgsql/src/include/access/reloptions.h,v 1.9 2009/01/08 19:34:41 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -90,11 +90,14 @@ typedef struct relopt_real
        double          max;
 } relopt_real;
 
+typedef void (*validate_string_relopt) (char *value, bool validate);
+
 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,7 +116,7 @@ typedef struct relopt_string
  * need this information.
  */
 #define HAVE_RELOPTION(optname, option) \
-       (pg_strncasecmp(option.gen->name, optname, option.gen->namelen) == 0)
+       (pg_strncasecmp(option.gen->name, optname, option.gen->namelen + 1) == 0)
 
 #define HANDLE_INT_RELOPTION(optname, var, option, wasset)                     \
        do {                                                                                                                    \
@@ -141,7 +144,7 @@ typedef struct relopt_string
                }                                                                                                                       \
        } while (0)
 
-#define HANDLE_REAL_RELOPTION(optname, var, option, wasset)                    \
+#define HANDLE_REAL_RELOPTION(optname, var, option, wasset)            \
        do {                                                                                                                    \
                if (HAVE_RELOPTION(optname, option))                                            \
                {                                                                                                                       \
@@ -166,23 +169,23 @@ typedef struct relopt_string
  * string options have been processed.
  */
 #define HANDLE_STRING_RELOPTION(optname, var, option, base, offset, wasset)    \
-       do {                                                                                                                    \
+       do {                                                                                                            \
                if (HAVE_RELOPTION(optname, option))                                            \
                {                                                                                                                       \
                        relopt_string *optstring = (relopt_string *) option.gen;\
-                       char *string_val = NULL;                                                                \
-                                                                                                                                       \
+                       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)                                                                                \
+                       if (string_val == NULL)                                                                 \
                                var = 0;                                                                                        \
                        else                                                                                                    \
                        {                                                                                                               \
-                               strcpy((char *)(base) + (offset), string_val);          \
+                               strcpy(((char *)(base)) + (offset), string_val);        \
                                var = (offset);                                                                         \
                                (offset) += strlen(string_val) + 1;                                     \
                        }                                                                                                               \
@@ -190,6 +193,24 @@ typedef struct relopt_string
                }                                                                                                                       \
        } 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,7 +219,7 @@ extern void add_int_reloption(int kind, char *name, char *desc,
 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);
+                                        char *default_val, validate_string_relopt validator);
                        
 extern Datum transformRelOptions(Datum oldOptions, List *defList,
                                        bool ignoreOids, bool isReset);