LCOV - code coverage report
Current view: top level - src/backend/commands - define.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 58.6 % 133 78
Test Date: 2026-01-26 10:56:24 Functions: 90.9 % 11 10
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 31.0 % 174 54

             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                 :        4217 : defGetString(DefElem *def)
      35                 :             : {
      36         [ +  - ]:        4217 :         if (def->arg == NULL)
      37   [ #  #  #  # ]:           0 :                 ereport(ERROR,
      38                 :             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
      39                 :             :                                  errmsg("%s requires a parameter",
      40                 :             :                                                 def->defname)));
      41   [ +  +  +  +  :        4217 :         switch (nodeTag(def->arg))
             +  -  -  - ]
      42                 :             :         {
      43                 :             :                 case T_Integer:
      44                 :         156 :                         return psprintf("%d", intVal(def->arg));
      45                 :             :                 case T_Float:
      46                 :          14 :                         return castNode(Float, def->arg)->fval;
      47                 :             :                 case T_Boolean:
      48                 :          73 :                         return boolVal(def->arg) ? "true" : "false";
      49                 :             :                 case T_String:
      50                 :        3744 :                         return strVal(def->arg);
      51                 :             :                 case T_TypeName:
      52                 :         230 :                         return TypeNameToString((TypeName *) def->arg);
      53                 :             :                 case T_List:
      54                 :           0 :                         return NameListToString((List *) def->arg);
      55                 :             :                 case T_A_Star:
      56                 :           0 :                         return pstrdup("*");
      57                 :             :                 default:
      58   [ #  #  #  # ]:           0 :                         elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
      59                 :           0 :         }
      60                 :           0 :         return NULL;                            /* keep compiler quiet */
      61                 :        4217 : }
      62                 :             : 
      63                 :             : /*
      64                 :             :  * Extract a numeric value (actually double) from a DefElem.
      65                 :             :  */
      66                 :             : double
      67                 :          56 : defGetNumeric(DefElem *def)
      68                 :             : {
      69         [ +  - ]:          56 :         if (def->arg == NULL)
      70   [ #  #  #  # ]:           0 :                 ereport(ERROR,
      71                 :             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
      72                 :             :                                  errmsg("%s requires a numeric value",
      73                 :             :                                                 def->defname)));
      74      [ +  +  - ]:          56 :         switch (nodeTag(def->arg))
      75                 :             :         {
      76                 :             :                 case T_Integer:
      77                 :          53 :                         return (double) intVal(def->arg);
      78                 :             :                 case T_Float:
      79                 :           3 :                         return floatVal(def->arg);
      80                 :             :                 default:
      81   [ #  #  #  # ]:           0 :                         ereport(ERROR,
      82                 :             :                                         (errcode(ERRCODE_SYNTAX_ERROR),
      83                 :             :                                          errmsg("%s requires a numeric value",
      84                 :             :                                                         def->defname)));
      85                 :           0 :         }
      86                 :           0 :         return 0;                                       /* keep compiler quiet */
      87                 :          56 : }
      88                 :             : 
      89                 :             : /*
      90                 :             :  * Extract a boolean value from a DefElem.
      91                 :             :  */
      92                 :             : bool
      93                 :        4173 : defGetBoolean(DefElem *def)
      94                 :             : {
      95                 :             :         /*
      96                 :             :          * If no parameter value given, assume "true" is meant.
      97                 :             :          */
      98         [ +  + ]:        4173 :         if (def->arg == NULL)
      99                 :        1258 :                 return true;
     100                 :             : 
     101                 :             :         /*
     102                 :             :          * Allow 0, 1, "true", "false", "on", "off"
     103                 :             :          */
     104         [ +  + ]:        2915 :         switch (nodeTag(def->arg))
     105                 :             :         {
     106                 :             :                 case T_Integer:
     107      [ +  +  + ]:          20 :                         switch (intVal(def->arg))
     108                 :             :                         {
     109                 :             :                                 case 0:
     110                 :          10 :                                         return false;
     111                 :             :                                 case 1:
     112                 :           9 :                                         return true;
     113                 :             :                                 default:
     114                 :             :                                         /* otherwise, error out below */
     115                 :           1 :                                         break;
     116                 :             :                         }
     117                 :           1 :                         break;
     118                 :             :                 default:
     119                 :             :                         {
     120                 :        2895 :                                 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         [ +  + ]:        2895 :                                 if (pg_strcasecmp(sval, "true") == 0)
     127                 :          46 :                                         return true;
     128         [ +  + ]:        2849 :                                 if (pg_strcasecmp(sval, "false") == 0)
     129                 :          80 :                                         return false;
     130         [ +  + ]:        2769 :                                 if (pg_strcasecmp(sval, "on") == 0)
     131                 :          32 :                                         return true;
     132         [ +  + ]:        2737 :                                 if (pg_strcasecmp(sval, "off") == 0)
     133                 :        2733 :                                         return false;
     134      [ -  +  + ]:        2895 :                         }
     135                 :           4 :                         break;
     136                 :             :         }
     137   [ -  +  +  - ]:           5 :         ereport(ERROR,
     138                 :             :                         (errcode(ERRCODE_SYNTAX_ERROR),
     139                 :             :                          errmsg("%s requires a Boolean value",
     140                 :             :                                         def->defname)));
     141                 :           0 :         return false;                           /* keep compiler quiet */
     142                 :        4168 : }
     143                 :             : 
     144                 :             : /*
     145                 :             :  * Extract an int32 value from a DefElem.
     146                 :             :  */
     147                 :             : int32
     148                 :         384 : defGetInt32(DefElem *def)
     149                 :             : {
     150         [ +  + ]:         384 :         if (def->arg == NULL)
     151   [ +  -  +  - ]:           1 :                 ereport(ERROR,
     152                 :             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
     153                 :             :                                  errmsg("%s requires an integer value",
     154                 :             :                                                 def->defname)));
     155         [ +  + ]:         383 :         switch (nodeTag(def->arg))
     156                 :             :         {
     157                 :             :                 case T_Integer:
     158                 :         382 :                         return (int32) intVal(def->arg);
     159                 :             :                 default:
     160   [ +  -  +  - ]:           1 :                         ereport(ERROR,
     161                 :             :                                         (errcode(ERRCODE_SYNTAX_ERROR),
     162                 :             :                                          errmsg("%s requires an integer value",
     163                 :             :                                                         def->defname)));
     164                 :           0 :         }
     165                 :           0 :         return 0;                                       /* keep compiler quiet */
     166                 :         382 : }
     167                 :             : 
     168                 :             : /*
     169                 :             :  * Extract an int64 value from a DefElem.
     170                 :             :  */
     171                 :             : int64
     172                 :          73 : defGetInt64(DefElem *def)
     173                 :             : {
     174         [ +  - ]:          73 :         if (def->arg == NULL)
     175   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     176                 :             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
     177                 :             :                                  errmsg("%s requires a numeric value",
     178                 :             :                                                 def->defname)));
     179      [ +  +  - ]:          73 :         switch (nodeTag(def->arg))
     180                 :             :         {
     181                 :             :                 case T_Integer:
     182                 :          63 :                         return (int64) intVal(def->arg);
     183                 :             :                 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                 :          10 :                         return DatumGetInt64(DirectFunctionCall1(int8in,
     191                 :             :                                                                                                          CStringGetDatum(castNode(Float, def->arg)->fval)));
     192                 :             :                 default:
     193   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     194                 :             :                                         (errcode(ERRCODE_SYNTAX_ERROR),
     195                 :             :                                          errmsg("%s requires a numeric value",
     196                 :             :                                                         def->defname)));
     197                 :           0 :         }
     198                 :           0 :         return 0;                                       /* keep compiler quiet */
     199                 :          73 : }
     200                 :             : 
     201                 :             : /*
     202                 :             :  * Extract an OID value from a DefElem.
     203                 :             :  */
     204                 :             : Oid
     205                 :           2 : defGetObjectId(DefElem *def)
     206                 :             : {
     207         [ +  - ]:           2 :         if (def->arg == NULL)
     208   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     209                 :             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
     210                 :             :                                  errmsg("%s requires a numeric value",
     211                 :             :                                                 def->defname)));
     212      [ +  -  - ]:           2 :         switch (nodeTag(def->arg))
     213                 :             :         {
     214                 :             :                 case T_Integer:
     215                 :           2 :                         return (Oid) intVal(def->arg);
     216                 :             :                 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                 :             :                 default:
     226   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     227                 :             :                                         (errcode(ERRCODE_SYNTAX_ERROR),
     228                 :             :                                          errmsg("%s requires a numeric value",
     229                 :             :                                                         def->defname)));
     230                 :           0 :         }
     231                 :           0 :         return 0;                                       /* keep compiler quiet */
     232                 :           2 : }
     233                 :             : 
     234                 :             : /*
     235                 :             :  * Extract a possibly-qualified name (as a List of Strings) from a DefElem.
     236                 :             :  */
     237                 :             : List *
     238                 :         695 : defGetQualifiedName(DefElem *def)
     239                 :             : {
     240         [ +  - ]:         695 :         if (def->arg == NULL)
     241   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     242                 :             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
     243                 :             :                                  errmsg("%s requires a parameter",
     244                 :             :                                                 def->defname)));
     245   [ +  +  +  - ]:         695 :         switch (nodeTag(def->arg))
     246                 :             :         {
     247                 :             :                 case T_TypeName:
     248                 :         438 :                         return ((TypeName *) def->arg)->names;
     249                 :             :                 case T_List:
     250                 :         222 :                         return (List *) def->arg;
     251                 :             :                 case T_String:
     252                 :             :                         /* Allow quoted name for backwards compatibility */
     253                 :          35 :                         return list_make1(def->arg);
     254                 :             :                 default:
     255   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     256                 :             :                                         (errcode(ERRCODE_SYNTAX_ERROR),
     257                 :             :                                          errmsg("argument of %s must be a name",
     258                 :             :                                                         def->defname)));
     259                 :           0 :         }
     260                 :           0 :         return NIL;                                     /* keep compiler quiet */
     261                 :         695 : }
     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                 :         525 : defGetTypeName(DefElem *def)
     271                 :             : {
     272         [ +  - ]:         525 :         if (def->arg == NULL)
     273   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     274                 :             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
     275                 :             :                                  errmsg("%s requires a parameter",
     276                 :             :                                                 def->defname)));
     277      [ +  +  - ]:         525 :         switch (nodeTag(def->arg))
     278                 :             :         {
     279                 :             :                 case T_TypeName:
     280                 :         524 :                         return (TypeName *) def->arg;
     281                 :             :                 case T_String:
     282                 :             :                         /* Allow quoted typename for backwards compatibility */
     283                 :           1 :                         return makeTypeNameFromNameList(list_make1(def->arg));
     284                 :             :                 default:
     285   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     286                 :             :                                         (errcode(ERRCODE_SYNTAX_ERROR),
     287                 :             :                                          errmsg("argument of %s must be a type name",
     288                 :             :                                                         def->defname)));
     289                 :           0 :         }
     290                 :           0 :         return NULL;                            /* keep compiler quiet */
     291                 :         525 : }
     292                 :             : 
     293                 :             : /*
     294                 :             :  * Extract a type length indicator (either absolute bytes, or
     295                 :             :  * -1 for "variable") from a DefElem.
     296                 :             :  */
     297                 :             : int
     298                 :           6 : defGetTypeLength(DefElem *def)
     299                 :             : {
     300         [ +  - ]:           6 :         if (def->arg == NULL)
     301   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     302                 :             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
     303                 :             :                                  errmsg("%s requires a parameter",
     304                 :             :                                                 def->defname)));
     305   [ +  -  +  -  :           6 :         switch (nodeTag(def->arg))
                   -  - ]
     306                 :             :         {
     307                 :             :                 case T_Integer:
     308                 :           4 :                         return intVal(def->arg);
     309                 :             :                 case T_Float:
     310   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     311                 :             :                                         (errcode(ERRCODE_SYNTAX_ERROR),
     312                 :             :                                          errmsg("%s requires an integer value",
     313                 :             :                                                         def->defname)));
     314                 :           0 :                         break;
     315                 :             :                 case T_String:
     316         [ #  # ]:           0 :                         if (pg_strcasecmp(strVal(def->arg), "variable") == 0)
     317                 :           0 :                                 return -1;              /* variable length */
     318                 :           0 :                         break;
     319                 :             :                 case T_TypeName:
     320                 :             :                         /* cope if grammar chooses to believe "variable" is a typename */
     321                 :           2 :                         if (pg_strcasecmp(TypeNameToString((TypeName *) def->arg),
     322         [ +  - ]:           2 :                                                           "variable") == 0)
     323                 :           2 :                                 return -1;              /* variable length */
     324                 :           0 :                         break;
     325                 :             :                 case T_List:
     326                 :             :                         /* must be an operator name */
     327                 :             :                         break;
     328                 :             :                 default:
     329   [ #  #  #  # ]:           0 :                         elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
     330                 :           0 :         }
     331   [ #  #  #  # ]:           0 :         ereport(ERROR,
     332                 :             :                         (errcode(ERRCODE_SYNTAX_ERROR),
     333                 :             :                          errmsg("invalid argument for %s: \"%s\"",
     334                 :             :                                         def->defname, defGetString(def))));
     335                 :           0 :         return 0;                                       /* keep compiler quiet */
     336                 :           6 : }
     337                 :             : 
     338                 :             : /*
     339                 :             :  * Extract a list of string values (otherwise uninterpreted) from a DefElem.
     340                 :             :  */
     341                 :             : List *
     342                 :           0 : defGetStringList(DefElem *def)
     343                 :             : {
     344                 :           0 :         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                 :           0 :         }
     362                 :             : 
     363                 :           0 :         return (List *) def->arg;
     364                 :           0 : }
     365                 :             : 
     366                 :             : /*
     367                 :             :  * Raise an error about a conflicting DefElem.
     368                 :             :  */
     369                 :             : void
     370                 :          26 : errorConflictingDefElem(DefElem *defel, ParseState *pstate)
     371                 :             : {
     372   [ +  -  +  - ]:          26 :         ereport(ERROR,
     373                 :             :                         errcode(ERRCODE_SYNTAX_ERROR),
     374                 :             :                         errmsg("conflicting or redundant options"),
     375                 :             :                         parser_errposition(pstate, defel->location));
     376                 :           0 : }
        

Generated by: LCOV version 2.3.2-1