Header And Logo

PostgreSQL
| The world's most advanced open source database.

reloptions.h

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * reloptions.h
00004  *    Core support for relation and tablespace options (pg_class.reloptions
00005  *    and pg_tablespace.spcoptions)
00006  *
00007  * Note: the functions dealing with text-array reloptions values declare
00008  * them as Datum, not ArrayType *, to avoid needing to include array.h
00009  * into a lot of low-level code.
00010  *
00011  *
00012  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00013  * Portions Copyright (c) 1994, Regents of the University of California
00014  *
00015  * src/include/access/reloptions.h
00016  *
00017  *-------------------------------------------------------------------------
00018  */
00019 #ifndef RELOPTIONS_H
00020 #define RELOPTIONS_H
00021 
00022 #include "access/htup.h"
00023 #include "access/tupdesc.h"
00024 #include "nodes/pg_list.h"
00025 
00026 /* types supported by reloptions */
00027 typedef enum relopt_type
00028 {
00029     RELOPT_TYPE_BOOL,
00030     RELOPT_TYPE_INT,
00031     RELOPT_TYPE_REAL,
00032     RELOPT_TYPE_STRING
00033 } relopt_type;
00034 
00035 /* kinds supported by reloptions */
00036 typedef enum relopt_kind
00037 {
00038     RELOPT_KIND_HEAP = (1 << 0),
00039     RELOPT_KIND_TOAST = (1 << 1),
00040     RELOPT_KIND_BTREE = (1 << 2),
00041     RELOPT_KIND_HASH = (1 << 3),
00042     RELOPT_KIND_GIN = (1 << 4),
00043     RELOPT_KIND_GIST = (1 << 5),
00044     RELOPT_KIND_ATTRIBUTE = (1 << 6),
00045     RELOPT_KIND_TABLESPACE = (1 << 7),
00046     RELOPT_KIND_SPGIST = (1 << 8),
00047     RELOPT_KIND_VIEW = (1 << 9),
00048     /* if you add a new kind, make sure you update "last_default" too */
00049     RELOPT_KIND_LAST_DEFAULT = RELOPT_KIND_VIEW,
00050     /* some compilers treat enums as signed ints, so we can't use 1 << 31 */
00051     RELOPT_KIND_MAX = (1 << 30)
00052 } relopt_kind;
00053 
00054 /* reloption namespaces allowed for heaps -- currently only TOAST */
00055 #define HEAP_RELOPT_NAMESPACES { "toast", NULL }
00056 
00057 /* generic struct to hold shared data */
00058 typedef struct relopt_gen
00059 {
00060     const char *name;           /* must be first (used as list termination
00061                                  * marker) */
00062     const char *desc;
00063     bits32      kinds;
00064     int         namelen;
00065     relopt_type type;
00066 } relopt_gen;
00067 
00068 /* holds a parsed value */
00069 typedef struct relopt_value
00070 {
00071     relopt_gen *gen;
00072     bool        isset;
00073     union
00074     {
00075         bool        bool_val;
00076         int         int_val;
00077         double      real_val;
00078         char       *string_val; /* allocated separately */
00079     }           values;
00080 } relopt_value;
00081 
00082 /* reloptions records for specific variable types */
00083 typedef struct relopt_bool
00084 {
00085     relopt_gen  gen;
00086     bool        default_val;
00087 } relopt_bool;
00088 
00089 typedef struct relopt_int
00090 {
00091     relopt_gen  gen;
00092     int         default_val;
00093     int         min;
00094     int         max;
00095 } relopt_int;
00096 
00097 typedef struct relopt_real
00098 {
00099     relopt_gen  gen;
00100     double      default_val;
00101     double      min;
00102     double      max;
00103 } relopt_real;
00104 
00105 /* validation routines for strings */
00106 typedef void (*validate_string_relopt) (char *value);
00107 
00108 typedef struct relopt_string
00109 {
00110     relopt_gen  gen;
00111     int         default_len;
00112     bool        default_isnull;
00113     validate_string_relopt validate_cb;
00114     char       *default_val;
00115 } relopt_string;
00116 
00117 /* This is the table datatype for fillRelOptions */
00118 typedef struct
00119 {
00120     const char *optname;        /* option's name */
00121     relopt_type opttype;        /* option's datatype */
00122     int         offset;         /* offset of field in result struct */
00123 } relopt_parse_elt;
00124 
00125 
00126 /*
00127  * These macros exist for the convenience of amoptions writers (but consider
00128  * using fillRelOptions, which is a lot simpler).  Beware of multiple
00129  * evaluation of arguments!
00130  *
00131  * The last argument in the HANDLE_*_RELOPTION macros allows the caller to
00132  * determine whether the option was set (true), or its value acquired from
00133  * defaults (false); it can be passed as (char *) NULL if the caller does not
00134  * need this information.
00135  *
00136  * optname is the option name (a string), var is the variable
00137  * on which the value should be stored (e.g. StdRdOptions->fillfactor), and
00138  * option is a relopt_value pointer.
00139  *
00140  * The normal way to use this is to loop on the relopt_value array returned by
00141  * parseRelOptions:
00142  * for (i = 0; options[i].gen->name; i++)
00143  * {
00144  *      if (HAVE_RELOPTION("fillfactor", options[i])
00145  *      {
00146  *          HANDLE_INT_RELOPTION("fillfactor", rdopts->fillfactor, options[i], &isset);
00147  *          continue;
00148  *      }
00149  *      if (HAVE_RELOPTION("default_row_acl", options[i])
00150  *      {
00151  *          ...
00152  *      }
00153  *      ...
00154  *      if (validate)
00155  *          ereport(ERROR,
00156  *                  (errmsg("unknown option")));
00157  *  }
00158  *
00159  *  Note that this is more or less the same that fillRelOptions does, so only
00160  *  use this if you need to do something non-standard within some option's
00161  *  code block.
00162  */
00163 #define HAVE_RELOPTION(optname, option) \
00164     (pg_strncasecmp(option.gen->name, optname, option.gen->namelen + 1) == 0)
00165 
00166 #define HANDLE_INT_RELOPTION(optname, var, option, wasset)      \
00167     do {                                                        \
00168         if (option.isset)                                       \
00169             var = option.values.int_val;                        \
00170         else                                                    \
00171             var = ((relopt_int *) option.gen)->default_val;     \
00172         (wasset) != NULL ? *(wasset) = option.isset : (dummyret)NULL; \
00173     } while (0)
00174 
00175 #define HANDLE_BOOL_RELOPTION(optname, var, option, wasset)         \
00176     do {                                                            \
00177         if (option.isset)                                       \
00178             var = option.values.bool_val;                       \
00179         else                                                    \
00180             var = ((relopt_bool *) option.gen)->default_val;    \
00181         (wasset) != NULL ? *(wasset) = option.isset : (dummyret) NULL; \
00182     } while (0)
00183 
00184 #define HANDLE_REAL_RELOPTION(optname, var, option, wasset)     \
00185     do {                                                        \
00186         if (option.isset)                                       \
00187             var = option.values.real_val;                       \
00188         else                                                    \
00189             var = ((relopt_real *) option.gen)->default_val;    \
00190         (wasset) != NULL ? *(wasset) = option.isset : (dummyret) NULL; \
00191     } while (0)
00192 
00193 /*
00194  * Note that this assumes that the variable is already allocated at the tail of
00195  * reloptions structure (StdRdOptions or equivalent).
00196  *
00197  * "base" is a pointer to the reloptions structure, and "offset" is an integer
00198  * variable that must be initialized to sizeof(reloptions structure).  This
00199  * struct must have been allocated with enough space to hold any string option
00200  * present, including terminating \0 for every option.  SET_VARSIZE() must be
00201  * called on the struct with this offset as the second argument, after all the
00202  * string options have been processed.
00203  */
00204 #define HANDLE_STRING_RELOPTION(optname, var, option, base, offset, wasset) \
00205     do {                                                        \
00206         relopt_string *optstring = (relopt_string *) option.gen;\
00207         char *string_val;                                       \
00208         if (option.isset)                                       \
00209             string_val = option.values.string_val;              \
00210         else if (!optstring->default_isnull)                    \
00211             string_val = optstring->default_val;                \
00212         else                                                    \
00213             string_val = NULL;                                  \
00214         (wasset) != NULL ? *(wasset) = option.isset : (dummyret) NULL; \
00215         if (string_val == NULL)                                 \
00216             var = 0;                                            \
00217         else                                                    \
00218         {                                                       \
00219             strcpy(((char *)(base)) + (offset), string_val);    \
00220             var = (offset);                                     \
00221             (offset) += strlen(string_val) + 1;                 \
00222         }                                                       \
00223     } while (0)
00224 
00225 /*
00226  * For use during amoptions: get the strlen of a string option
00227  * (either default or the user defined value)
00228  */
00229 #define GET_STRING_RELOPTION_LEN(option) \
00230     ((option).isset ? strlen((option).values.string_val) : \
00231      ((relopt_string *) (option).gen)->default_len)
00232 
00233 /*
00234  * For use by code reading options already parsed: get a pointer to the string
00235  * value itself.  "optstruct" is the StdRdOption struct or equivalent, "member"
00236  * is the struct member corresponding to the string option
00237  */
00238 #define GET_STRING_RELOPTION(optstruct, member) \
00239     ((optstruct)->member == 0 ? NULL : \
00240      (char *)(optstruct) + (optstruct)->member)
00241 
00242 
00243 extern relopt_kind add_reloption_kind(void);
00244 extern void add_bool_reloption(bits32 kinds, char *name, char *desc,
00245                    bool default_val);
00246 extern void add_int_reloption(bits32 kinds, char *name, char *desc,
00247                   int default_val, int min_val, int max_val);
00248 extern void add_real_reloption(bits32 kinds, char *name, char *desc,
00249                    double default_val, double min_val, double max_val);
00250 extern void add_string_reloption(bits32 kinds, char *name, char *desc,
00251                      char *default_val, validate_string_relopt validator);
00252 
00253 extern Datum transformRelOptions(Datum oldOptions, List *defList,
00254                     char *namspace, char *validnsps[],
00255                     bool ignoreOids, bool isReset);
00256 extern List *untransformRelOptions(Datum options);
00257 extern bytea *extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
00258                   Oid amoptions);
00259 extern relopt_value *parseRelOptions(Datum options, bool validate,
00260                 relopt_kind kind, int *numrelopts);
00261 extern void *allocateReloptStruct(Size base, relopt_value *options,
00262                      int numoptions);
00263 extern void fillRelOptions(void *rdopts, Size basesize,
00264                relopt_value *options, int numoptions,
00265                bool validate,
00266                const relopt_parse_elt *elems, int nelems);
00267 
00268 extern bytea *default_reloptions(Datum reloptions, bool validate,
00269                    relopt_kind kind);
00270 extern bytea *heap_reloptions(char relkind, Datum reloptions, bool validate);
00271 extern bytea *index_reloptions(RegProcedure amoptions, Datum reloptions,
00272                  bool validate);
00273 extern bytea *attribute_reloptions(Datum reloptions, bool validate);
00274 extern bytea *tablespace_reloptions(Datum reloptions, bool validate);
00275 
00276 #endif   /* RELOPTIONS_H */