LCOV - differential code coverage report
Current view: top level - src/backend/commands - define.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 63.8 % 138 88 50 88
Current Date: 2023-04-08 15:15:32 Functions: 90.9 % 11 10 1 10
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a