LCOV - code coverage report
Current view: top level - src/backend/commands - define.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 65.9 % 138 91
Test Date: 2026-07-03 19:57:34 Functions: 90.9 % 11 10
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 39.4 % 127 50

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

Generated by: LCOV version 2.0-1