LCOV - code coverage report
Current view: top level - src/backend/commands - define.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 91 138 65.9 %
Date: 2026-02-07 12:18:09 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-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       64700 : defGetString(DefElem *def)
      35             : {
      36       64700 :     if (def->arg == NULL)
      37           0 :         ereport(ERROR,
      38             :                 (errcode(ERRCODE_SYNTAX_ERROR),
      39             :                  errmsg("%s requires a parameter",
      40             :                         def->defname)));
      41       64700 :     switch (nodeTag(def->arg))
      42             :     {
      43        1110 :         case T_Integer:
      44        1110 :             return psprintf("%d", intVal(def->arg));
      45         114 :         case T_Float:
      46         114 :             return castNode(Float, def->arg)->fval;
      47         586 :         case T_Boolean:
      48         586 :             return boolVal(def->arg) ? "true" : "false";
      49       56956 :         case T_String:
      50       56956 :             return strVal(def->arg);
      51        5934 :         case T_TypeName:
      52        5934 :             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        5062 : defGetNumeric(DefElem *def)
      68             : {
      69        5062 :     if (def->arg == NULL)
      70           0 :         ereport(ERROR,
      71             :                 (errcode(ERRCODE_SYNTAX_ERROR),
      72             :                  errmsg("%s requires a numeric value",
      73             :                         def->defname)));
      74        5062 :     switch (nodeTag(def->arg))
      75             :     {
      76        5042 :         case T_Integer:
      77        5042 :             return (double) intVal(def->arg);
      78          20 :         case T_Float:
      79          20 :             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       44462 : defGetBoolean(DefElem *def)
      94             : {
      95             :     /*
      96             :      * If no parameter value given, assume "true" is meant.
      97             :      */
      98       44462 :     if (def->arg == NULL)
      99       23280 :         return true;
     100             : 
     101             :     /*
     102             :      * Allow 0, 1, "true", "false", "on", "off"
     103             :      */
     104       21182 :     switch (nodeTag(def->arg))
     105             :     {
     106         478 :         case T_Integer:
     107         478 :             switch (intVal(def->arg))
     108             :             {
     109         414 :                 case 0:
     110         414 :                     return false;
     111          58 :                 case 1:
     112          58 :                     return true;
     113           6 :                 default:
     114             :                     /* otherwise, error out below */
     115           6 :                     break;
     116             :             }
     117           6 :             break;
     118       20704 :         default:
     119             :             {
     120       20704 :                 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       20704 :                 if (pg_strcasecmp(sval, "true") == 0)
     127        1712 :                     return true;
     128       18992 :                 if (pg_strcasecmp(sval, "false") == 0)
     129        1468 :                     return false;
     130       17524 :                 if (pg_strcasecmp(sval, "on") == 0)
     131         298 :                     return true;
     132       17226 :                 if (pg_strcasecmp(sval, "off") == 0)
     133       17202 :                     return false;
     134             :             }
     135          24 :             break;
     136             :     }
     137          30 :     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        1982 : defGetInt32(DefElem *def)
     149             : {
     150        1982 :     if (def->arg == NULL)
     151           6 :         ereport(ERROR,
     152             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     153             :                  errmsg("%s requires an integer value",
     154             :                         def->defname)));
     155        1976 :     switch (nodeTag(def->arg))
     156             :     {
     157        1970 :         case T_Integer:
     158        1970 :             return (int32) intVal(def->arg);
     159           6 :         default:
     160           6 :             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         874 : defGetInt64(DefElem *def)
     173             : {
     174         874 :     if (def->arg == NULL)
     175           0 :         ereport(ERROR,
     176             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     177             :                  errmsg("%s requires a numeric value",
     178             :                         def->defname)));
     179         874 :     switch (nodeTag(def->arg))
     180             :     {
     181         810 :         case T_Integer:
     182         810 :             return (int64) intVal(def->arg);
     183          64 :         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          64 :             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         266 : defGetObjectId(DefElem *def)
     206             : {
     207         266 :     if (def->arg == NULL)
     208           0 :         ereport(ERROR,
     209             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     210             :                  errmsg("%s requires a numeric value",
     211             :                         def->defname)));
     212         266 :     switch (nodeTag(def->arg))
     213             :     {
     214         266 :         case T_Integer:
     215         266 :             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       16802 : defGetQualifiedName(DefElem *def)
     239             : {
     240       16802 :     if (def->arg == NULL)
     241           0 :         ereport(ERROR,
     242             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     243             :                  errmsg("%s requires a parameter",
     244             :                         def->defname)));
     245       16802 :     switch (nodeTag(def->arg))
     246             :     {
     247       10420 :         case T_TypeName:
     248       16802 :             return ((TypeName *) def->arg)->names;
     249        2770 :         case T_List:
     250        2770 :             return (List *) def->arg;
     251        3612 :         case T_String:
     252             :             /* Allow quoted name for backwards compatibility */
     253        3612 :             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        6216 : defGetTypeName(DefElem *def)
     271             : {
     272        6216 :     if (def->arg == NULL)
     273           0 :         ereport(ERROR,
     274             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     275             :                  errmsg("%s requires a parameter",
     276             :                         def->defname)));
     277        6216 :     switch (nodeTag(def->arg))
     278             :     {
     279        6210 :         case T_TypeName:
     280        6216 :             return (TypeName *) def->arg;
     281           6 :         case T_String:
     282             :             /* Allow quoted typename for backwards compatibility */
     283           6 :             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         156 : defGetTypeLength(DefElem *def)
     299             : {
     300         156 :     if (def->arg == NULL)
     301           0 :         ereport(ERROR,
     302             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     303             :                  errmsg("%s requires a parameter",
     304             :                         def->defname)));
     305         156 :     switch (nodeTag(def->arg))
     306             :     {
     307         120 :         case T_Integer:
     308         120 :             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          36 :         case T_TypeName:
     320             :             /* cope if grammar chooses to believe "variable" is a typename */
     321          36 :             if (pg_strcasecmp(TypeNameToString((TypeName *) def->arg),
     322             :                               "variable") == 0)
     323          36 :                 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         162 : errorConflictingDefElem(DefElem *defel, ParseState *pstate)
     371             : {
     372         162 :     ereport(ERROR,
     373             :             errcode(ERRCODE_SYNTAX_ERROR),
     374             :             errmsg("conflicting or redundant options"),
     375             :             parser_errposition(pstate, defel->location));
     376             : }

Generated by: LCOV version 1.16