LCOV - code coverage report
Current view: top level - src/backend/commands - define.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 78 125 62.4 %
Date: 2020-06-01 09:07:10 Functions: 8 9 88.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * define.c
       4             :  *    Support routines for various kinds of object creation.
       5             :  *
       6             :  *
       7             :  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
       8             :  * Portions Copyright (c) 1994, Regents of the University of California
       9             :  *
      10             :  *
      11             :  * IDENTIFICATION
      12             :  *    src/backend/commands/define.c
      13             :  *
      14             :  * DESCRIPTION
      15             :  *    The "DefineFoo" routines take the parse tree and pick out the
      16             :  *    appropriate arguments/flags, passing the results to the
      17             :  *    corresponding "FooDefine" routines (in src/catalog) that do
      18             :  *    the actual catalog-munging.  These routines also verify permission
      19             :  *    of the user to execute the command.
      20             :  *
      21             :  * NOTES
      22             :  *    These things must be defined and committed in the following order:
      23             :  *      "create function":
      24             :  *              input/output, recv/send procedures
      25             :  *      "create type":
      26             :  *              type
      27             :  *      "create operator":
      28             :  *              operators
      29             :  *
      30             :  *
      31             :  *-------------------------------------------------------------------------
      32             :  */
      33             : #include "postgres.h"
      34             : 
      35             : #include <ctype.h>
      36             : #include <math.h>
      37             : 
      38             : #include "catalog/namespace.h"
      39             : #include "commands/defrem.h"
      40             : #include "nodes/makefuncs.h"
      41             : #include "parser/parse_type.h"
      42             : #include "parser/scansup.h"
      43             : #include "utils/builtins.h"
      44             : 
      45             : /*
      46             :  * Extract a string value (otherwise uninterpreted) from a DefElem.
      47             :  */
      48             : char *
      49       41318 : defGetString(DefElem *def)
      50             : {
      51       41318 :     if (def->arg == NULL)
      52           0 :         ereport(ERROR,
      53             :                 (errcode(ERRCODE_SYNTAX_ERROR),
      54             :                  errmsg("%s requires a parameter",
      55             :                         def->defname)));
      56       41318 :     switch (nodeTag(def->arg))
      57             :     {
      58         548 :         case T_Integer:
      59         548 :             return psprintf("%ld", (long) intVal(def->arg));
      60          80 :         case T_Float:
      61             : 
      62             :             /*
      63             :              * T_Float values are kept in string form, so this type cheat
      64             :              * works (and doesn't risk losing precision)
      65             :              */
      66          80 :             return strVal(def->arg);
      67       26928 :         case T_String:
      68       26928 :             return strVal(def->arg);
      69       13762 :         case T_TypeName:
      70       13762 :             return TypeNameToString((TypeName *) def->arg);
      71           0 :         case T_List:
      72           0 :             return NameListToString((List *) def->arg);
      73           0 :         case T_A_Star:
      74           0 :             return pstrdup("*");
      75           0 :         default:
      76           0 :             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
      77             :     }
      78             :     return NULL;                /* keep compiler quiet */
      79             : }
      80             : 
      81             : /*
      82             :  * Extract a numeric value (actually double) from a DefElem.
      83             :  */
      84             : double
      85        3254 : defGetNumeric(DefElem *def)
      86             : {
      87        3254 :     if (def->arg == NULL)
      88           0 :         ereport(ERROR,
      89             :                 (errcode(ERRCODE_SYNTAX_ERROR),
      90             :                  errmsg("%s requires a numeric value",
      91             :                         def->defname)));
      92        3254 :     switch (nodeTag(def->arg))
      93             :     {
      94        3240 :         case T_Integer:
      95        3240 :             return (double) intVal(def->arg);
      96          14 :         case T_Float:
      97          14 :             return floatVal(def->arg);
      98           0 :         default:
      99           0 :             ereport(ERROR,
     100             :                     (errcode(ERRCODE_SYNTAX_ERROR),
     101             :                      errmsg("%s requires a numeric value",
     102             :                             def->defname)));
     103             :     }
     104             :     return 0;                   /* keep compiler quiet */
     105             : }
     106             : 
     107             : /*
     108             :  * Extract a boolean value from a DefElem.
     109             :  */
     110             : bool
     111       12782 : defGetBoolean(DefElem *def)
     112             : {
     113             :     /*
     114             :      * If no parameter given, assume "true" is meant.
     115             :      */
     116       12782 :     if (def->arg == NULL)
     117        4564 :         return true;
     118             : 
     119             :     /*
     120             :      * Allow 0, 1, "true", "false", "on", "off"
     121             :      */
     122        8218 :     switch (nodeTag(def->arg))
     123             :     {
     124         136 :         case T_Integer:
     125         136 :             switch (intVal(def->arg))
     126             :             {
     127          48 :                 case 0:
     128          48 :                     return false;
     129          84 :                 case 1:
     130          84 :                     return true;
     131           4 :                 default:
     132             :                     /* otherwise, error out below */
     133           4 :                     break;
     134             :             }
     135           4 :             break;
     136        8082 :         default:
     137           0 :             {
     138        8082 :                 char       *sval = defGetString(def);
     139             : 
     140             :                 /*
     141             :                  * The set of strings accepted here should match up with the
     142             :                  * grammar's opt_boolean_or_string production.
     143             :                  */
     144        8082 :                 if (pg_strcasecmp(sval, "true") == 0)
     145        1110 :                     return true;
     146        6972 :                 if (pg_strcasecmp(sval, "false") == 0)
     147         548 :                     return false;
     148        6424 :                 if (pg_strcasecmp(sval, "on") == 0)
     149          24 :                     return true;
     150        6400 :                 if (pg_strcasecmp(sval, "off") == 0)
     151        6400 :                     return false;
     152             :             }
     153           0 :             break;
     154             :     }
     155           4 :     ereport(ERROR,
     156             :             (errcode(ERRCODE_SYNTAX_ERROR),
     157             :              errmsg("%s requires a Boolean value",
     158             :                     def->defname)));
     159             :     return false;               /* keep compiler quiet */
     160             : }
     161             : 
     162             : /*
     163             :  * Extract an int32 value from a DefElem.
     164             :  */
     165             : int32
     166         834 : defGetInt32(DefElem *def)
     167             : {
     168         834 :     if (def->arg == NULL)
     169           0 :         ereport(ERROR,
     170             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     171             :                  errmsg("%s requires an integer value",
     172             :                         def->defname)));
     173         834 :     switch (nodeTag(def->arg))
     174             :     {
     175         834 :         case T_Integer:
     176         834 :             return (int32) intVal(def->arg);
     177           0 :         default:
     178           0 :             ereport(ERROR,
     179             :                     (errcode(ERRCODE_SYNTAX_ERROR),
     180             :                      errmsg("%s requires an integer value",
     181             :                             def->defname)));
     182             :     }
     183             :     return 0;                   /* keep compiler quiet */
     184             : }
     185             : 
     186             : /*
     187             :  * Extract an int64 value from a DefElem.
     188             :  */
     189             : int64
     190         512 : defGetInt64(DefElem *def)
     191             : {
     192         512 :     if (def->arg == NULL)
     193           0 :         ereport(ERROR,
     194             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     195             :                  errmsg("%s requires a numeric value",
     196             :                         def->defname)));
     197         512 :     switch (nodeTag(def->arg))
     198             :     {
     199         490 :         case T_Integer:
     200         490 :             return (int64) intVal(def->arg);
     201          22 :         case T_Float:
     202             : 
     203             :             /*
     204             :              * Values too large for int4 will be represented as Float
     205             :              * constants by the lexer.  Accept these if they are valid int8
     206             :              * strings.
     207             :              */
     208          22 :             return DatumGetInt64(DirectFunctionCall1(int8in,
     209             :                                                      CStringGetDatum(strVal(def->arg))));
     210           0 :         default:
     211           0 :             ereport(ERROR,
     212             :                     (errcode(ERRCODE_SYNTAX_ERROR),
     213             :                      errmsg("%s requires a numeric value",
     214             :                             def->defname)));
     215             :     }
     216             :     return 0;                   /* keep compiler quiet */
     217             : }
     218             : 
     219             : /*
     220             :  * Extract a possibly-qualified name (as a List of Strings) from a DefElem.
     221             :  */
     222             : List *
     223       24418 : defGetQualifiedName(DefElem *def)
     224             : {
     225       24418 :     if (def->arg == NULL)
     226           0 :         ereport(ERROR,
     227             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     228             :                  errmsg("%s requires a parameter",
     229             :                         def->defname)));
     230       24418 :     switch (nodeTag(def->arg))
     231             :     {
     232       14358 :         case T_TypeName:
     233       14358 :             return ((TypeName *) def->arg)->names;
     234        1720 :         case T_List:
     235        1720 :             return (List *) def->arg;
     236        8340 :         case T_String:
     237             :             /* Allow quoted name for backwards compatibility */
     238        8340 :             return list_make1(def->arg);
     239           0 :         default:
     240           0 :             ereport(ERROR,
     241             :                     (errcode(ERRCODE_SYNTAX_ERROR),
     242             :                      errmsg("argument of %s must be a name",
     243             :                             def->defname)));
     244             :     }
     245             :     return NIL;                 /* keep compiler quiet */
     246             : }
     247             : 
     248             : /*
     249             :  * Extract a TypeName from a DefElem.
     250             :  *
     251             :  * Note: we do not accept a List arg here, because the parser will only
     252             :  * return a bare List when the name looks like an operator name.
     253             :  */
     254             : TypeName *
     255        4340 : defGetTypeName(DefElem *def)
     256             : {
     257        4340 :     if (def->arg == NULL)
     258           0 :         ereport(ERROR,
     259             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     260             :                  errmsg("%s requires a parameter",
     261             :                         def->defname)));
     262        4340 :     switch (nodeTag(def->arg))
     263             :     {
     264        4336 :         case T_TypeName:
     265        4336 :             return (TypeName *) def->arg;
     266           4 :         case T_String:
     267             :             /* Allow quoted typename for backwards compatibility */
     268           4 :             return makeTypeNameFromNameList(list_make1(def->arg));
     269           0 :         default:
     270           0 :             ereport(ERROR,
     271             :                     (errcode(ERRCODE_SYNTAX_ERROR),
     272             :                      errmsg("argument of %s must be a type name",
     273             :                             def->defname)));
     274             :     }
     275             :     return NULL;                /* keep compiler quiet */
     276             : }
     277             : 
     278             : /*
     279             :  * Extract a type length indicator (either absolute bytes, or
     280             :  * -1 for "variable") from a DefElem.
     281             :  */
     282             : int
     283         112 : defGetTypeLength(DefElem *def)
     284             : {
     285         112 :     if (def->arg == NULL)
     286           0 :         ereport(ERROR,
     287             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     288             :                  errmsg("%s requires a parameter",
     289             :                         def->defname)));
     290         112 :     switch (nodeTag(def->arg))
     291             :     {
     292          88 :         case T_Integer:
     293          88 :             return intVal(def->arg);
     294           0 :         case T_Float:
     295           0 :             ereport(ERROR,
     296             :                     (errcode(ERRCODE_SYNTAX_ERROR),
     297             :                      errmsg("%s requires an integer value",
     298             :                             def->defname)));
     299             :             break;
     300           0 :         case T_String:
     301           0 :             if (pg_strcasecmp(strVal(def->arg), "variable") == 0)
     302           0 :                 return -1;      /* variable length */
     303           0 :             break;
     304          24 :         case T_TypeName:
     305             :             /* cope if grammar chooses to believe "variable" is a typename */
     306          24 :             if (pg_strcasecmp(TypeNameToString((TypeName *) def->arg),
     307             :                               "variable") == 0)
     308          24 :                 return -1;      /* variable length */
     309           0 :             break;
     310           0 :         case T_List:
     311             :             /* must be an operator name */
     312           0 :             break;
     313           0 :         default:
     314           0 :             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
     315             :     }
     316           0 :     ereport(ERROR,
     317             :             (errcode(ERRCODE_SYNTAX_ERROR),
     318             :              errmsg("invalid argument for %s: \"%s\"",
     319             :                     def->defname, defGetString(def))));
     320             :     return 0;                   /* keep compiler quiet */
     321             : }
     322             : 
     323             : /*
     324             :  * Extract a list of string values (otherwise uninterpreted) from a DefElem.
     325             :  */
     326             : List *
     327           0 : defGetStringList(DefElem *def)
     328             : {
     329             :     ListCell   *cell;
     330             : 
     331           0 :     if (def->arg == NULL)
     332           0 :         ereport(ERROR,
     333             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     334             :                  errmsg("%s requires a parameter",
     335             :                         def->defname)));
     336           0 :     if (nodeTag(def->arg) != T_List)
     337           0 :         elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
     338             : 
     339           0 :     foreach(cell, (List *) def->arg)
     340             :     {
     341           0 :         Node       *str = (Node *) lfirst(cell);
     342             : 
     343           0 :         if (!IsA(str, String))
     344           0 :             elog(ERROR, "unexpected node type in name list: %d",
     345             :                  (int) nodeTag(str));
     346             :     }
     347             : 
     348           0 :     return (List *) def->arg;
     349             : }

Generated by: LCOV version 1.13