LCOV - code coverage report
Current view: top level - src/backend/commands - define.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 65.9 % 138 91
Test Date: 2026-03-12 19:14:48 Functions: 90.9 % 11 10
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-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        32945 : defGetString(DefElem *def)
      35              : {
      36        32945 :     if (def->arg == NULL)
      37            0 :         ereport(ERROR,
      38              :                 (errcode(ERRCODE_SYNTAX_ERROR),
      39              :                  errmsg("%s requires a parameter",
      40              :                         def->defname)));
      41        32945 :     switch (nodeTag(def->arg))
      42              :     {
      43          556 :         case T_Integer:
      44          556 :             return psprintf("%d", intVal(def->arg));
      45           58 :         case T_Float:
      46           58 :             return castNode(Float, def->arg)->fval;
      47          293 :         case T_Boolean:
      48          293 :             return boolVal(def->arg) ? "true" : "false";
      49        29071 :         case T_String:
      50        29071 :             return strVal(def->arg);
      51         2967 :         case T_TypeName:
      52         2967 :             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         2041 : defGetNumeric(DefElem *def)
      68              : {
      69         2041 :     if (def->arg == NULL)
      70            0 :         ereport(ERROR,
      71              :                 (errcode(ERRCODE_SYNTAX_ERROR),
      72              :                  errmsg("%s requires a numeric value",
      73              :                         def->defname)));
      74         2041 :     switch (nodeTag(def->arg))
      75              :     {
      76         2031 :         case T_Integer:
      77         2031 :             return (double) intVal(def->arg);
      78           10 :         case T_Float:
      79           10 :             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        22773 : defGetBoolean(DefElem *def)
      94              : {
      95              :     /*
      96              :      * If no parameter value given, assume "true" is meant.
      97              :      */
      98        22773 :     if (def->arg == NULL)
      99        11867 :         return true;
     100              : 
     101              :     /*
     102              :      * Allow 0, 1, "true", "false", "on", "off"
     103              :      */
     104        10906 :     switch (nodeTag(def->arg))
     105              :     {
     106          241 :         case T_Integer:
     107          241 :             switch (intVal(def->arg))
     108              :             {
     109          209 :                 case 0:
     110          209 :                     return false;
     111           29 :                 case 1:
     112           29 :                     return true;
     113            3 :                 default:
     114              :                     /* otherwise, error out below */
     115            3 :                     break;
     116              :             }
     117            3 :             break;
     118        10665 :         default:
     119              :             {
     120        10665 :                 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        10665 :                 if (pg_strcasecmp(sval, "true") == 0)
     127          857 :                     return true;
     128         9808 :                 if (pg_strcasecmp(sval, "false") == 0)
     129          749 :                     return false;
     130         9059 :                 if (pg_strcasecmp(sval, "on") == 0)
     131          150 :                     return true;
     132         8909 :                 if (pg_strcasecmp(sval, "off") == 0)
     133         8897 :                     return false;
     134              :             }
     135           12 :             break;
     136              :     }
     137           15 :     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         1124 : defGetInt32(DefElem *def)
     149              : {
     150         1124 :     if (def->arg == NULL)
     151            3 :         ereport(ERROR,
     152              :                 (errcode(ERRCODE_SYNTAX_ERROR),
     153              :                  errmsg("%s requires an integer value",
     154              :                         def->defname)));
     155         1121 :     switch (nodeTag(def->arg))
     156              :     {
     157         1118 :         case T_Integer:
     158         1118 :             return (int32) intVal(def->arg);
     159            3 :         default:
     160            3 :             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          441 : defGetInt64(DefElem *def)
     173              : {
     174          441 :     if (def->arg == NULL)
     175            0 :         ereport(ERROR,
     176              :                 (errcode(ERRCODE_SYNTAX_ERROR),
     177              :                  errmsg("%s requires a numeric value",
     178              :                         def->defname)));
     179          441 :     switch (nodeTag(def->arg))
     180              :     {
     181          409 :         case T_Integer:
     182          409 :             return (int64) intVal(def->arg);
     183           32 :         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           32 :             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          133 : defGetObjectId(DefElem *def)
     206              : {
     207          133 :     if (def->arg == NULL)
     208            0 :         ereport(ERROR,
     209              :                 (errcode(ERRCODE_SYNTAX_ERROR),
     210              :                  errmsg("%s requires a numeric value",
     211              :                         def->defname)));
     212          133 :     switch (nodeTag(def->arg))
     213              :     {
     214          133 :         case T_Integer:
     215          133 :             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         8442 : defGetQualifiedName(DefElem *def)
     239              : {
     240         8442 :     if (def->arg == NULL)
     241            0 :         ereport(ERROR,
     242              :                 (errcode(ERRCODE_SYNTAX_ERROR),
     243              :                  errmsg("%s requires a parameter",
     244              :                         def->defname)));
     245         8442 :     switch (nodeTag(def->arg))
     246              :     {
     247         5236 :         case T_TypeName:
     248         8442 :             return ((TypeName *) def->arg)->names;
     249         1400 :         case T_List:
     250         1400 :             return (List *) def->arg;
     251         1806 :         case T_String:
     252              :             /* Allow quoted name for backwards compatibility */
     253         1806 :             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         3130 : defGetTypeName(DefElem *def)
     271              : {
     272         3130 :     if (def->arg == NULL)
     273            0 :         ereport(ERROR,
     274              :                 (errcode(ERRCODE_SYNTAX_ERROR),
     275              :                  errmsg("%s requires a parameter",
     276              :                         def->defname)));
     277         3130 :     switch (nodeTag(def->arg))
     278              :     {
     279         3127 :         case T_TypeName:
     280         3130 :             return (TypeName *) def->arg;
     281            3 :         case T_String:
     282              :             /* Allow quoted typename for backwards compatibility */
     283            3 :             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           78 : defGetTypeLength(DefElem *def)
     299              : {
     300           78 :     if (def->arg == NULL)
     301            0 :         ereport(ERROR,
     302              :                 (errcode(ERRCODE_SYNTAX_ERROR),
     303              :                  errmsg("%s requires a parameter",
     304              :                         def->defname)));
     305           78 :     switch (nodeTag(def->arg))
     306              :     {
     307           60 :         case T_Integer:
     308           60 :             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           18 :         case T_TypeName:
     320              :             /* cope if grammar chooses to believe "variable" is a typename */
     321           18 :             if (pg_strcasecmp(TypeNameToString((TypeName *) def->arg),
     322              :                               "variable") == 0)
     323           18 :                 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           84 : errorConflictingDefElem(DefElem *defel, ParseState *pstate)
     371              : {
     372           84 :     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