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

Generated by: LCOV version 1.14