LTP GCOV extension - code coverage report
Current view: directory - access/common - reloptions.c
Test: unnamed
Date: 2008-07-03 Instrumented lines: 107
Code covered: 24.3 % Executed lines: 26
Legend: not executed executed

       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * reloptions.c
       4                 :  *        Core support for relation options (pg_class.reloptions)
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
       7                 :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :  *
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *        $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.7 2007/12/01 23:44:44 tgl Exp $
      12                 :  *
      13                 :  *-------------------------------------------------------------------------
      14                 :  */
      15                 : 
      16                 : #include "postgres.h"
      17                 : 
      18                 : #include "access/reloptions.h"
      19                 : #include "catalog/pg_type.h"
      20                 : #include "commands/defrem.h"
      21                 : #include "nodes/makefuncs.h"
      22                 : #include "utils/array.h"
      23                 : #include "utils/builtins.h"
      24                 : #include "utils/rel.h"
      25                 : 
      26                 : 
      27                 : /*
      28                 :  * Transform a relation options list (list of DefElem) into the text array
      29                 :  * format that is kept in pg_class.reloptions.
      30                 :  *
      31                 :  * This is used for three cases: CREATE TABLE/INDEX, ALTER TABLE SET, and
      32                 :  * ALTER TABLE RESET.  In the ALTER cases, oldOptions is the existing
      33                 :  * reloptions value (possibly NULL), and we replace or remove entries
      34                 :  * as needed.
      35                 :  *
      36                 :  * If ignoreOids is true, then we should ignore any occurrence of "oids"
      37                 :  * in the list (it will be or has been handled by interpretOidsOption()).
      38                 :  *
      39                 :  * Note that this is not responsible for determining whether the options
      40                 :  * are valid.
      41                 :  *
      42                 :  * Both oldOptions and the result are text arrays (or NULL for "default"),
      43                 :  * but we declare them as Datums to avoid including array.h in reloptions.h.
      44                 :  */
      45                 : Datum
      46                 : transformRelOptions(Datum oldOptions, List *defList,
      47                 :                                         bool ignoreOids, bool isReset)
      48            1078 : {
      49                 :         Datum           result;
      50                 :         ArrayBuildState *astate;
      51                 :         ListCell   *cell;
      52                 : 
      53                 :         /* no change if empty list */
      54            1078 :         if (defList == NIL)
      55             843 :                 return oldOptions;
      56                 : 
      57                 :         /* We build new array using accumArrayResult */
      58             235 :         astate = NULL;
      59                 : 
      60                 :         /* Copy any oldOptions that aren't to be replaced */
      61             235 :         if (oldOptions != (Datum) 0)
      62                 :         {
      63               0 :                 ArrayType  *array = DatumGetArrayTypeP(oldOptions);
      64                 :                 Datum      *oldoptions;
      65                 :                 int                     noldoptions;
      66                 :                 int                     i;
      67                 : 
      68                 :                 Assert(ARR_ELEMTYPE(array) == TEXTOID);
      69                 : 
      70               0 :                 deconstruct_array(array, TEXTOID, -1, false, 'i',
      71                 :                                                   &oldoptions, NULL, &noldoptions);
      72                 : 
      73               0 :                 for (i = 0; i < noldoptions; i++)
      74                 :                 {
      75               0 :                         text       *oldoption = DatumGetTextP(oldoptions[i]);
      76               0 :                         char       *text_str = VARDATA(oldoption);
      77               0 :                         int                     text_len = VARSIZE(oldoption) - VARHDRSZ;
      78                 : 
      79                 :                         /* Search for a match in defList */
      80               0 :                         foreach(cell, defList)
      81                 :                         {
      82               0 :                                 DefElem    *def = lfirst(cell);
      83               0 :                                 int                     kw_len = strlen(def->defname);
      84                 : 
      85               0 :                                 if (text_len > kw_len && text_str[kw_len] == '=' &&
      86                 :                                         pg_strncasecmp(text_str, def->defname, kw_len) == 0)
      87               0 :                                         break;
      88                 :                         }
      89               0 :                         if (!cell)
      90                 :                         {
      91                 :                                 /* No match, so keep old option */
      92               0 :                                 astate = accumArrayResult(astate, oldoptions[i],
      93                 :                                                                                   false, TEXTOID,
      94                 :                                                                                   CurrentMemoryContext);
      95                 :                         }
      96                 :                 }
      97                 :         }
      98                 : 
      99                 :         /*
     100                 :          * If CREATE/SET, add new options to array; if RESET, just check that the
     101                 :          * user didn't say RESET (option=val).  (Must do this because the grammar
     102                 :          * doesn't enforce it.)
     103                 :          */
     104             470 :         foreach(cell, defList)
     105                 :         {
     106             235 :                 DefElem    *def = lfirst(cell);
     107                 : 
     108             235 :                 if (isReset)
     109                 :                 {
     110               0 :                         if (def->arg != NULL)
     111               0 :                                 ereport(ERROR,
     112                 :                                                 (errcode(ERRCODE_SYNTAX_ERROR),
     113                 :                                         errmsg("RESET must not include values for parameters")));
     114                 :                 }
     115                 :                 else
     116                 :                 {
     117                 :                         text       *t;
     118                 :                         const char *value;
     119                 :                         Size            len;
     120                 : 
     121             235 :                         if (ignoreOids && pg_strcasecmp(def->defname, "oids") == 0)
     122             235 :                                 continue;
     123                 : 
     124                 :                         /*
     125                 :                          * Flatten the DefElem into a text string like "name=arg". If we
     126                 :                          * have just "name", assume "name=true" is meant.
     127                 :                          */
     128               0 :                         if (def->arg != NULL)
     129               0 :                                 value = defGetString(def);
     130                 :                         else
     131               0 :                                 value = "true";
     132               0 :                         len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
     133                 :                         /* +1 leaves room for sprintf's trailing null */
     134               0 :                         t = (text *) palloc(len + 1);
     135               0 :                         SET_VARSIZE(t, len);
     136               0 :                         sprintf(VARDATA(t), "%s=%s", def->defname, value);
     137                 : 
     138               0 :                         astate = accumArrayResult(astate, PointerGetDatum(t),
     139                 :                                                                           false, TEXTOID,
     140                 :                                                                           CurrentMemoryContext);
     141                 :                 }
     142                 :         }
     143                 : 
     144             235 :         if (astate)
     145               0 :                 result = makeArrayResult(astate, CurrentMemoryContext);
     146                 :         else
     147             235 :                 result = (Datum) 0;
     148                 : 
     149             235 :         return result;
     150                 : }
     151                 : 
     152                 : 
     153                 : /*
     154                 :  * Convert the text-array format of reloptions into a List of DefElem.
     155                 :  * This is the inverse of transformRelOptions().
     156                 :  */
     157                 : List *
     158                 : untransformRelOptions(Datum options)
     159               0 : {
     160               0 :         List       *result = NIL;
     161                 :         ArrayType  *array;
     162                 :         Datum      *optiondatums;
     163                 :         int                     noptions;
     164                 :         int                     i;
     165                 : 
     166                 :         /* Nothing to do if no options */
     167               0 :         if (options == (Datum) 0)
     168               0 :                 return result;
     169                 : 
     170               0 :         array = DatumGetArrayTypeP(options);
     171                 : 
     172                 :         Assert(ARR_ELEMTYPE(array) == TEXTOID);
     173                 : 
     174               0 :         deconstruct_array(array, TEXTOID, -1, false, 'i',
     175                 :                                           &optiondatums, NULL, &noptions);
     176                 : 
     177               0 :         for (i = 0; i < noptions; i++)
     178                 :         {
     179                 :                 char       *s;
     180                 :                 char       *p;
     181               0 :                 Node       *val = NULL;
     182                 : 
     183               0 :                 s = DatumGetCString(DirectFunctionCall1(textout, optiondatums[i]));
     184               0 :                 p = strchr(s, '=');
     185               0 :                 if (p)
     186                 :                 {
     187               0 :                         *p++ = '\0';
     188               0 :                         val = (Node *) makeString(pstrdup(p));
     189                 :                 }
     190               0 :                 result = lappend(result, makeDefElem(pstrdup(s), val));
     191                 :         }
     192                 : 
     193               0 :         return result;
     194                 : }
     195                 : 
     196                 : 
     197                 : /*
     198                 :  * Interpret reloptions that are given in text-array format.
     199                 :  *
     200                 :  *      options: array of "keyword=value" strings, as built by transformRelOptions
     201                 :  *      numkeywords: number of legal keywords
     202                 :  *      keywords: the allowed keywords
     203                 :  *      values: output area
     204                 :  *      validate: if true, throw error for unrecognized keywords.
     205                 :  *
     206                 :  * The keywords and values arrays must both be of length numkeywords.
     207                 :  * The values entry corresponding to a keyword is set to a palloc'd string
     208                 :  * containing the corresponding value, or NULL if the keyword does not appear.
     209                 :  */
     210                 : void
     211                 : parseRelOptions(Datum options, int numkeywords, const char *const * keywords,
     212                 :                                 char **values, bool validate)
     213             792 : {
     214                 :         ArrayType  *array;
     215                 :         Datum      *optiondatums;
     216                 :         int                     noptions;
     217                 :         int                     i;
     218                 : 
     219                 :         /* Initialize to "all defaulted" */
     220             792 :         MemSet(values, 0, numkeywords * sizeof(char *));
     221                 : 
     222                 :         /* Done if no options */
     223             792 :         if (options == (Datum) 0)
     224             792 :                 return;
     225                 : 
     226               0 :         array = DatumGetArrayTypeP(options);
     227                 : 
     228                 :         Assert(ARR_ELEMTYPE(array) == TEXTOID);
     229                 : 
     230               0 :         deconstruct_array(array, TEXTOID, -1, false, 'i',
     231                 :                                           &optiondatums, NULL, &noptions);
     232                 : 
     233               0 :         for (i = 0; i < noptions; i++)
     234                 :         {
     235               0 :                 text       *optiontext = DatumGetTextP(optiondatums[i]);
     236               0 :                 char       *text_str = VARDATA(optiontext);
     237               0 :                 int                     text_len = VARSIZE(optiontext) - VARHDRSZ;
     238                 :                 int                     j;
     239                 : 
     240                 :                 /* Search for a match in keywords */
     241               0 :                 for (j = 0; j < numkeywords; j++)
     242                 :                 {
     243               0 :                         int                     kw_len = strlen(keywords[j]);
     244                 : 
     245               0 :                         if (text_len > kw_len && text_str[kw_len] == '=' &&
     246                 :                                 pg_strncasecmp(text_str, keywords[j], kw_len) == 0)
     247                 :                         {
     248                 :                                 char       *value;
     249                 :                                 int                     value_len;
     250                 : 
     251               0 :                                 if (values[j] && validate)
     252               0 :                                         ereport(ERROR,
     253                 :                                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     254                 :                                                   errmsg("parameter \"%s\" specified more than once",
     255                 :                                                                  keywords[j])));
     256               0 :                                 value_len = text_len - kw_len - 1;
     257               0 :                                 value = (char *) palloc(value_len + 1);
     258               0 :                                 memcpy(value, text_str + kw_len + 1, value_len);
     259               0 :                                 value[value_len] = '\0';
     260               0 :                                 values[j] = value;
     261               0 :                                 break;
     262                 :                         }
     263                 :                 }
     264               0 :                 if (j >= numkeywords && validate)
     265                 :                 {
     266                 :                         char       *s;
     267                 :                         char       *p;
     268                 : 
     269               0 :                         s = DatumGetCString(DirectFunctionCall1(textout, optiondatums[i]));
     270               0 :                         p = strchr(s, '=');
     271               0 :                         if (p)
     272               0 :                                 *p = '\0';
     273               0 :                         ereport(ERROR,
     274                 :                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     275                 :                                          errmsg("unrecognized parameter \"%s\"", s)));
     276                 :                 }
     277                 :         }
     278                 : }
     279                 : 
     280                 : 
     281                 : /*
     282                 :  * Parse reloptions for anything using StdRdOptions (ie, fillfactor only)
     283                 :  */
     284                 : bytea *
     285                 : default_reloptions(Datum reloptions, bool validate,
     286                 :                                    int minFillfactor, int defaultFillfactor)
     287             792 : {
     288                 :         static const char *const default_keywords[1] = {"fillfactor"};
     289                 :         char       *values[1];
     290                 :         int32           fillfactor;
     291                 :         StdRdOptions *result;
     292                 : 
     293             792 :         parseRelOptions(reloptions, 1, default_keywords, values, validate);
     294                 : 
     295                 :         /*
     296                 :          * If no options, we can just return NULL rather than doing anything.
     297                 :          * (defaultFillfactor is thus not used, but we require callers to pass it
     298                 :          * anyway since we would need it if more options were added.)
     299                 :          */
     300             792 :         if (values[0] == NULL)
     301             792 :                 return NULL;
     302                 : 
     303               0 :         fillfactor = pg_atoi(values[0], sizeof(int32), 0);
     304               0 :         if (fillfactor < minFillfactor || fillfactor > 100)
     305                 :         {
     306               0 :                 if (validate)
     307               0 :                         ereport(ERROR,
     308                 :                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     309                 :                                          errmsg("fillfactor=%d is out of range (should be between %d and 100)",
     310                 :                                                         fillfactor, minFillfactor)));
     311               0 :                 return NULL;
     312                 :         }
     313                 : 
     314               0 :         result = (StdRdOptions *) palloc(sizeof(StdRdOptions));
     315               0 :         SET_VARSIZE(result, sizeof(StdRdOptions));
     316                 : 
     317               0 :         result->fillfactor = fillfactor;
     318                 : 
     319               0 :         return (bytea *) result;
     320                 : }
     321                 : 
     322                 : 
     323                 : /*
     324                 :  * Parse options for heaps (and perhaps someday toast tables).
     325                 :  */
     326                 : bytea *
     327                 : heap_reloptions(char relkind, Datum reloptions, bool validate)
     328             792 : {
     329             792 :         return default_reloptions(reloptions, validate,
     330                 :                                                           HEAP_MIN_FILLFACTOR,
     331                 :                                                           HEAP_DEFAULT_FILLFACTOR);
     332                 : }
     333                 : 
     334                 : 
     335                 : /*
     336                 :  * Parse options for indexes.
     337                 :  *
     338                 :  *      amoptions       Oid of option parser
     339                 :  *      reloptions      options as text[] datum
     340                 :  *      validate        error flag
     341                 :  */
     342                 : bytea *
     343                 : index_reloptions(RegProcedure amoptions, Datum reloptions, bool validate)
     344             286 : {
     345                 :         FmgrInfo        flinfo;
     346                 :         FunctionCallInfoData fcinfo;
     347                 :         Datum           result;
     348                 : 
     349                 :         Assert(RegProcedureIsValid(amoptions));
     350                 : 
     351                 :         /* Assume function is strict */
     352             286 :         if (reloptions == (Datum) 0)
     353             286 :                 return NULL;
     354                 : 
     355                 :         /* Can't use OidFunctionCallN because we might get a NULL result */
     356               0 :         fmgr_info(amoptions, &flinfo);
     357                 : 
     358               0 :         InitFunctionCallInfoData(fcinfo, &flinfo, 2, NULL, NULL);
     359                 : 
     360               0 :         fcinfo.arg[0] = reloptions;
     361               0 :         fcinfo.arg[1] = BoolGetDatum(validate);
     362               0 :         fcinfo.argnull[0] = false;
     363               0 :         fcinfo.argnull[1] = false;
     364                 : 
     365               0 :         result = FunctionCallInvoke(&fcinfo);
     366                 : 
     367               0 :         if (fcinfo.isnull || DatumGetPointer(result) == NULL)
     368               0 :                 return NULL;
     369                 : 
     370               0 :         return DatumGetByteaP(result);
     371                 : }

Generated by: LTP GCOV extension version 1.5