LCOV - code coverage report
Current view: top level - src/backend/commands - define.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 53 91 58.2 %
Date: 2017-09-29 15:12:54 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-2017, 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        1239 : defGetString(DefElem *def)
      50             : {
      51        1239 :     if (def->arg == NULL)
      52           0 :         ereport(ERROR,
      53             :                 (errcode(ERRCODE_SYNTAX_ERROR),
      54             :                  errmsg("%s requires a parameter",
      55             :                         def->defname)));
      56        1239 :     switch (nodeTag(def->arg))
      57             :     {
      58             :         case T_Integer:
      59          59 :             return psprintf("%ld", (long) intVal(def->arg));
      60             :         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           9 :             return strVal(def->arg);
      67             :         case T_String:
      68        1091 :             return strVal(def->arg);
      69             :         case T_TypeName:
      70          80 :             return TypeNameToString((TypeName *) def->arg);
      71             :         case T_List:
      72           0 :             return NameListToString((List *) def->arg);
      73             :         case T_A_Star:
      74           0 :             return pstrdup("*");
      75             :         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          14 : defGetNumeric(DefElem *def)
      86             : {
      87          14 :     if (def->arg == NULL)
      88           0 :         ereport(ERROR,
      89             :                 (errcode(ERRCODE_SYNTAX_ERROR),
      90             :                  errmsg("%s requires a numeric value",
      91             :                         def->defname)));
      92          14 :     switch (nodeTag(def->arg))
      93             :     {
      94             :         case T_Integer:
      95          11 :             return (double) intVal(def->arg);
      96             :         case T_Float:
      97           3 :             return floatVal(def->arg);
      98             :         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         892 : defGetBoolean(DefElem *def)
     112             : {
     113             :     /*
     114             :      * If no parameter given, assume "true" is meant.
     115             :      */
     116         892 :     if (def->arg == NULL)
     117         105 :         return true;
     118             : 
     119             :     /*
     120             :      * Allow 0, 1, "true", "false", "on", "off"
     121             :      */
     122         787 :     switch (nodeTag(def->arg))
     123             :     {
     124             :         case T_Integer:
     125         121 :             switch (intVal(def->arg))
     126             :             {
     127             :                 case 0:
     128          45 :                     return false;
     129             :                 case 1:
     130          76 :                     return true;
     131             :                 default:
     132             :                     /* otherwise, error out below */
     133           0 :                     break;
     134             :             }
     135           0 :             break;
     136             :         default:
     137             :             {
     138         666 :                 char       *sval = defGetString(def);
     139             : 
     140             :                 /*
     141             :                  * The set of strings accepted here should match up with the
     142             :                  * grammar's opt_boolean production.
     143             :                  */
     144         666 :                 if (pg_strcasecmp(sval, "true") == 0)
     145          11 :                     return true;
     146         655 :                 if (pg_strcasecmp(sval, "false") == 0)
     147          13 :                     return false;
     148         642 :                 if (pg_strcasecmp(sval, "on") == 0)
     149           4 :                     return true;
     150         638 :                 if (pg_strcasecmp(sval, "off") == 0)
     151         638 :                     return false;
     152             :             }
     153           0 :             break;
     154             :     }
     155           0 :     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           3 : defGetInt32(DefElem *def)
     167             : {
     168           3 :     if (def->arg == NULL)
     169           0 :         ereport(ERROR,
     170             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     171             :                  errmsg("%s requires an integer value",
     172             :                         def->defname)));
     173           3 :     switch (nodeTag(def->arg))
     174             :     {
     175             :         case T_Integer:
     176           3 :             return (int32) intVal(def->arg);
     177             :         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          58 : defGetInt64(DefElem *def)
     191             : {
     192          58 :     if (def->arg == NULL)
     193           0 :         ereport(ERROR,
     194             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     195             :                  errmsg("%s requires a numeric value",
     196             :                         def->defname)));
     197          58 :     switch (nodeTag(def->arg))
     198             :     {
     199             :         case T_Integer:
     200          58 :             return (int64) intVal(def->arg);
     201             :         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           0 :             return DatumGetInt64(DirectFunctionCall1(int8in,
     209             :                                                      CStringGetDatum(strVal(def->arg))));
     210             :         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         462 : defGetQualifiedName(DefElem *def)
     224             : {
     225         462 :     if (def->arg == NULL)
     226           0 :         ereport(ERROR,
     227             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     228             :                  errmsg("%s requires a parameter",
     229             :                         def->defname)));
     230         462 :     switch (nodeTag(def->arg))
     231             :     {
     232             :         case T_TypeName:
     233         345 :             return ((TypeName *) def->arg)->names;
     234             :         case T_List:
     235         102 :             return (List *) def->arg;
     236             :         case T_String:
     237             :             /* Allow quoted name for backwards compatibility */
     238          15 :             return list_make1(def->arg);
     239             :         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         368 : defGetTypeName(DefElem *def)
     256             : {
     257         368 :     if (def->arg == NULL)
     258           0 :         ereport(ERROR,
     259             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     260             :                  errmsg("%s requires a parameter",
     261             :                         def->defname)));
     262         368 :     switch (nodeTag(def->arg))
     263             :     {
     264             :         case T_TypeName:
     265         367 :             return (TypeName *) def->arg;
     266             :         case T_String:
     267             :             /* Allow quoted typename for backwards compatibility */
     268           1 :             return makeTypeNameFromNameList(list_make1(def->arg));
     269             :         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           6 : defGetTypeLength(DefElem *def)
     284             : {
     285           6 :     if (def->arg == NULL)
     286           0 :         ereport(ERROR,
     287             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     288             :                  errmsg("%s requires a parameter",
     289             :                         def->defname)));
     290           6 :     switch (nodeTag(def->arg))
     291             :     {
     292             :         case T_Integer:
     293           4 :             return intVal(def->arg);
     294             :         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             :         case T_String:
     301           0 :             if (pg_strcasecmp(strVal(def->arg), "variable") == 0)
     302           0 :                 return -1;      /* variable length */
     303           0 :             break;
     304             :         case T_TypeName:
     305             :             /* cope if grammar chooses to believe "variable" is a typename */
     306           2 :             if (pg_strcasecmp(TypeNameToString((TypeName *) def->arg),
     307             :                               "variable") == 0)
     308           2 :                 return -1;      /* variable length */
     309           0 :             break;
     310             :         case T_List:
     311             :             /* must be an operator name */
     312           0 :             break;
     313             :         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.11