LCOV - code coverage report
Current view: top level - src/backend/commands - define.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 88 138 63.8 %
Date: 2024-04-22 22:11:44 Functions: 10 11 90.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-2024, 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 "utils/fmgrprotos.h"
      43             : 
      44             : /*
      45             :  * Extract a string value (otherwise uninterpreted) from a DefElem.
      46             :  */
      47             : char *
      48       54816 : defGetString(DefElem *def)
      49             : {
      50       54816 :     if (def->arg == NULL)
      51           0 :         ereport(ERROR,
      52             :                 (errcode(ERRCODE_SYNTAX_ERROR),
      53             :                  errmsg("%s requires a parameter",
      54             :                         def->defname)));
      55       54816 :     switch (nodeTag(def->arg))
      56             :     {
      57        1048 :         case T_Integer:
      58        1048 :             return psprintf("%ld", (long) intVal(def->arg));
      59         106 :         case T_Float:
      60         106 :             return castNode(Float, def->arg)->fval;
      61         550 :         case T_Boolean:
      62         550 :             return boolVal(def->arg) ? "true" : "false";
      63       48556 :         case T_String:
      64       48556 :             return strVal(def->arg);
      65        4556 :         case T_TypeName:
      66        4556 :             return TypeNameToString((TypeName *) def->arg);
      67           0 :         case T_List:
      68           0 :             return NameListToString((List *) def->arg);
      69           0 :         case T_A_Star:
      70           0 :             return pstrdup("*");
      71           0 :         default:
      72           0 :             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
      73             :     }
      74             :     return NULL;                /* keep compiler quiet */
      75             : }
      76             : 
      77             : /*
      78             :  * Extract a numeric value (actually double) from a DefElem.
      79             :  */
      80             : double
      81        3922 : defGetNumeric(DefElem *def)
      82             : {
      83        3922 :     if (def->arg == NULL)
      84           0 :         ereport(ERROR,
      85             :                 (errcode(ERRCODE_SYNTAX_ERROR),
      86             :                  errmsg("%s requires a numeric value",
      87             :                         def->defname)));
      88        3922 :     switch (nodeTag(def->arg))
      89             :     {
      90        3902 :         case T_Integer:
      91        3902 :             return (double) intVal(def->arg);
      92          20 :         case T_Float:
      93          20 :             return floatVal(def->arg);
      94           0 :         default:
      95           0 :             ereport(ERROR,
      96             :                     (errcode(ERRCODE_SYNTAX_ERROR),
      97             :                      errmsg("%s requires a numeric value",
      98             :                             def->defname)));
      99             :     }
     100             :     return 0;                   /* keep compiler quiet */
     101             : }
     102             : 
     103             : /*
     104             :  * Extract a boolean value from a DefElem.
     105             :  */
     106             : bool
     107       32102 : defGetBoolean(DefElem *def)
     108             : {
     109             :     /*
     110             :      * If no parameter value given, assume "true" is meant.
     111             :      */
     112       32102 :     if (def->arg == NULL)
     113       15076 :         return true;
     114             : 
     115             :     /*
     116             :      * Allow 0, 1, "true", "false", "on", "off"
     117             :      */
     118       17026 :     switch (nodeTag(def->arg))
     119             :     {
     120         422 :         case T_Integer:
     121         422 :             switch (intVal(def->arg))
     122             :             {
     123         358 :                 case 0:
     124         358 :                     return false;
     125          58 :                 case 1:
     126          58 :                     return true;
     127           6 :                 default:
     128             :                     /* otherwise, error out below */
     129           6 :                     break;
     130             :             }
     131           6 :             break;
     132       16604 :         default:
     133             :             {
     134       16604 :                 char       *sval = defGetString(def);
     135             : 
     136             :                 /*
     137             :                  * The set of strings accepted here should match up with the
     138             :                  * grammar's opt_boolean_or_string production.
     139             :                  */
     140       16604 :                 if (pg_strcasecmp(sval, "true") == 0)
     141        1538 :                     return true;
     142       15066 :                 if (pg_strcasecmp(sval, "false") == 0)
     143        1354 :                     return false;
     144       13712 :                 if (pg_strcasecmp(sval, "on") == 0)
     145         132 :                     return true;
     146       13580 :                 if (pg_strcasecmp(sval, "off") == 0)
     147       13562 :                     return false;
     148             :             }
     149          18 :             break;
     150             :     }
     151          24 :     ereport(ERROR,
     152             :             (errcode(ERRCODE_SYNTAX_ERROR),
     153             :              errmsg("%s requires a Boolean value",
     154             :                     def->defname)));
     155             :     return false;               /* keep compiler quiet */
     156             : }
     157             : 
     158             : /*
     159             :  * Extract an int32 value from a DefElem.
     160             :  */
     161             : int32
     162        1782 : defGetInt32(DefElem *def)
     163             : {
     164        1782 :     if (def->arg == NULL)
     165           0 :         ereport(ERROR,
     166             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     167             :                  errmsg("%s requires an integer value",
     168             :                         def->defname)));
     169        1782 :     switch (nodeTag(def->arg))
     170             :     {
     171        1782 :         case T_Integer:
     172        1782 :             return (int32) intVal(def->arg);
     173           0 :         default:
     174           0 :             ereport(ERROR,
     175             :                     (errcode(ERRCODE_SYNTAX_ERROR),
     176             :                      errmsg("%s requires an integer value",
     177             :                             def->defname)));
     178             :     }
     179             :     return 0;                   /* keep compiler quiet */
     180             : }
     181             : 
     182             : /*
     183             :  * Extract an int64 value from a DefElem.
     184             :  */
     185             : int64
     186         756 : defGetInt64(DefElem *def)
     187             : {
     188         756 :     if (def->arg == NULL)
     189           0 :         ereport(ERROR,
     190             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     191             :                  errmsg("%s requires a numeric value",
     192             :                         def->defname)));
     193         756 :     switch (nodeTag(def->arg))
     194             :     {
     195         724 :         case T_Integer:
     196         724 :             return (int64) intVal(def->arg);
     197          32 :         case T_Float:
     198             : 
     199             :             /*
     200             :              * Values too large for int4 will be represented as Float
     201             :              * constants by the lexer.  Accept these if they are valid int8
     202             :              * strings.
     203             :              */
     204          32 :             return DatumGetInt64(DirectFunctionCall1(int8in,
     205             :                                                      CStringGetDatum(castNode(Float, def->arg)->fval)));
     206           0 :         default:
     207           0 :             ereport(ERROR,
     208             :                     (errcode(ERRCODE_SYNTAX_ERROR),
     209             :                      errmsg("%s requires a numeric value",
     210             :                             def->defname)));
     211             :     }
     212             :     return 0;                   /* keep compiler quiet */
     213             : }
     214             : 
     215             : /*
     216             :  * Extract an OID value from a DefElem.
     217             :  */
     218             : Oid
     219         182 : defGetObjectId(DefElem *def)
     220             : {
     221         182 :     if (def->arg == NULL)
     222           0 :         ereport(ERROR,
     223             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     224             :                  errmsg("%s requires a numeric value",
     225             :                         def->defname)));
     226         182 :     switch (nodeTag(def->arg))
     227             :     {
     228         182 :         case T_Integer:
     229         182 :             return (Oid) intVal(def->arg);
     230           0 :         case T_Float:
     231             : 
     232             :             /*
     233             :              * Values too large for int4 will be represented as Float
     234             :              * constants by the lexer.  Accept these if they are valid OID
     235             :              * strings.
     236             :              */
     237           0 :             return DatumGetObjectId(DirectFunctionCall1(oidin,
     238             :                                                         CStringGetDatum(castNode(Float, def->arg)->fval)));
     239           0 :         default:
     240           0 :             ereport(ERROR,
     241             :                     (errcode(ERRCODE_SYNTAX_ERROR),
     242             :                      errmsg("%s requires a numeric value",
     243             :                             def->defname)));
     244             :     }
     245             :     return 0;                   /* keep compiler quiet */
     246             : }
     247             : 
     248             : /*
     249             :  * Extract a possibly-qualified name (as a List of Strings) from a DefElem.
     250             :  */
     251             : List *
     252       14614 : defGetQualifiedName(DefElem *def)
     253             : {
     254       14614 :     if (def->arg == NULL)
     255           0 :         ereport(ERROR,
     256             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     257             :                  errmsg("%s requires a parameter",
     258             :                         def->defname)));
     259       14614 :     switch (nodeTag(def->arg))
     260             :     {
     261        9346 :         case T_TypeName:
     262       14614 :             return ((TypeName *) def->arg)->names;
     263        2614 :         case T_List:
     264        2614 :             return (List *) def->arg;
     265        2654 :         case T_String:
     266             :             /* Allow quoted name for backwards compatibility */
     267        2654 :             return list_make1(def->arg);
     268           0 :         default:
     269           0 :             ereport(ERROR,
     270             :                     (errcode(ERRCODE_SYNTAX_ERROR),
     271             :                      errmsg("argument of %s must be a name",
     272             :                             def->defname)));
     273             :     }
     274             :     return NIL;                 /* keep compiler quiet */
     275             : }
     276             : 
     277             : /*
     278             :  * Extract a TypeName from a DefElem.
     279             :  *
     280             :  * Note: we do not accept a List arg here, because the parser will only
     281             :  * return a bare List when the name looks like an operator name.
     282             :  */
     283             : TypeName *
     284        5924 : defGetTypeName(DefElem *def)
     285             : {
     286        5924 :     if (def->arg == NULL)
     287           0 :         ereport(ERROR,
     288             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     289             :                  errmsg("%s requires a parameter",
     290             :                         def->defname)));
     291        5924 :     switch (nodeTag(def->arg))
     292             :     {
     293        5918 :         case T_TypeName:
     294        5924 :             return (TypeName *) def->arg;
     295           6 :         case T_String:
     296             :             /* Allow quoted typename for backwards compatibility */
     297           6 :             return makeTypeNameFromNameList(list_make1(def->arg));
     298           0 :         default:
     299           0 :             ereport(ERROR,
     300             :                     (errcode(ERRCODE_SYNTAX_ERROR),
     301             :                      errmsg("argument of %s must be a type name",
     302             :                             def->defname)));
     303             :     }
     304             :     return NULL;                /* keep compiler quiet */
     305             : }
     306             : 
     307             : /*
     308             :  * Extract a type length indicator (either absolute bytes, or
     309             :  * -1 for "variable") from a DefElem.
     310             :  */
     311             : int
     312         130 : defGetTypeLength(DefElem *def)
     313             : {
     314         130 :     if (def->arg == NULL)
     315           0 :         ereport(ERROR,
     316             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     317             :                  errmsg("%s requires a parameter",
     318             :                         def->defname)));
     319         130 :     switch (nodeTag(def->arg))
     320             :     {
     321         100 :         case T_Integer:
     322         100 :             return intVal(def->arg);
     323           0 :         case T_Float:
     324           0 :             ereport(ERROR,
     325             :                     (errcode(ERRCODE_SYNTAX_ERROR),
     326             :                      errmsg("%s requires an integer value",
     327             :                             def->defname)));
     328             :             break;
     329           0 :         case T_String:
     330           0 :             if (pg_strcasecmp(strVal(def->arg), "variable") == 0)
     331           0 :                 return -1;      /* variable length */
     332           0 :             break;
     333          30 :         case T_TypeName:
     334             :             /* cope if grammar chooses to believe "variable" is a typename */
     335          30 :             if (pg_strcasecmp(TypeNameToString((TypeName *) def->arg),
     336             :                               "variable") == 0)
     337          30 :                 return -1;      /* variable length */
     338           0 :             break;
     339           0 :         case T_List:
     340             :             /* must be an operator name */
     341           0 :             break;
     342           0 :         default:
     343           0 :             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
     344             :     }
     345           0 :     ereport(ERROR,
     346             :             (errcode(ERRCODE_SYNTAX_ERROR),
     347             :              errmsg("invalid argument for %s: \"%s\"",
     348             :                     def->defname, defGetString(def))));
     349             :     return 0;                   /* keep compiler quiet */
     350             : }
     351             : 
     352             : /*
     353             :  * Extract a list of string values (otherwise uninterpreted) from a DefElem.
     354             :  */
     355             : List *
     356           0 : defGetStringList(DefElem *def)
     357             : {
     358             :     ListCell   *cell;
     359             : 
     360           0 :     if (def->arg == NULL)
     361           0 :         ereport(ERROR,
     362             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     363             :                  errmsg("%s requires a parameter",
     364             :                         def->defname)));
     365           0 :     if (nodeTag(def->arg) != T_List)
     366           0 :         elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
     367             : 
     368           0 :     foreach(cell, (List *) def->arg)
     369             :     {
     370           0 :         Node       *str = (Node *) lfirst(cell);
     371             : 
     372           0 :         if (!IsA(str, String))
     373           0 :             elog(ERROR, "unexpected node type in name list: %d",
     374             :                  (int) nodeTag(str));
     375             :     }
     376             : 
     377           0 :     return (List *) def->arg;
     378             : }
     379             : 
     380             : /*
     381             :  * Raise an error about a conflicting DefElem.
     382             :  */
     383             : void
     384         150 : errorConflictingDefElem(DefElem *defel, ParseState *pstate)
     385             : {
     386         150 :     ereport(ERROR,
     387             :             errcode(ERRCODE_SYNTAX_ERROR),
     388             :             errmsg("conflicting or redundant options"),
     389             :             parser_errposition(pstate, defel->location));
     390             : }

Generated by: LCOV version 1.14