LCOV - differential code coverage report
Current view: top level - src/backend/parser - parse_node.c (source / functions) Coverage Total Hit LBC UBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 96.9 % 131 127 2 2 51 3 73 2 49 3
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 9 9 9 9
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * parse_node.c
       4                 :  *    various routines that make nodes for querytrees
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7                 :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :  *
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *    src/backend/parser/parse_node.c
      12                 :  *
      13                 :  *-------------------------------------------------------------------------
      14                 :  */
      15                 : #include "postgres.h"
      16                 : 
      17                 : #include "access/htup_details.h"
      18                 : #include "access/table.h"
      19                 : #include "catalog/pg_type.h"
      20                 : #include "mb/pg_wchar.h"
      21                 : #include "nodes/makefuncs.h"
      22                 : #include "nodes/miscnodes.h"
      23                 : #include "nodes/nodeFuncs.h"
      24                 : #include "nodes/subscripting.h"
      25                 : #include "parser/parse_coerce.h"
      26                 : #include "parser/parse_expr.h"
      27                 : #include "parser/parse_relation.h"
      28                 : #include "parser/parsetree.h"
      29                 : #include "utils/builtins.h"
      30                 : #include "utils/lsyscache.h"
      31                 : #include "utils/syscache.h"
      32                 : #include "utils/varbit.h"
      33                 : 
      34                 : static void pcb_error_callback(void *arg);
      35                 : 
      36                 : 
      37                 : /*
      38                 :  * make_parsestate
      39                 :  *      Allocate and initialize a new ParseState.
      40                 :  *
      41                 :  * Caller should eventually release the ParseState via free_parsestate().
      42                 :  */
      43                 : ParseState *
      44 GIC     1144016 : make_parsestate(ParseState *parentParseState)
      45 ECB             : {
      46                 :     ParseState *pstate;
      47                 : 
      48 GIC     1144016 :     pstate = palloc0(sizeof(ParseState));
      49 ECB             : 
      50 GIC     1144016 :     pstate->parentParseState = parentParseState;
      51 ECB             : 
      52                 :     /* Fill in fields that don't start at null/false/zero */
      53 GIC     1144016 :     pstate->p_next_resno = 1;
      54 CBC     1144016 :     pstate->p_resolve_unknowns = true;
      55 ECB             : 
      56 GIC     1144016 :     if (parentParseState)
      57 ECB             :     {
      58 GIC       77714 :         pstate->p_sourcetext = parentParseState->p_sourcetext;
      59 ECB             :         /* all hooks are copied from parent */
      60 GIC       77714 :         pstate->p_pre_columnref_hook = parentParseState->p_pre_columnref_hook;
      61 CBC       77714 :         pstate->p_post_columnref_hook = parentParseState->p_post_columnref_hook;
      62           77714 :         pstate->p_paramref_hook = parentParseState->p_paramref_hook;
      63           77714 :         pstate->p_coerce_param_hook = parentParseState->p_coerce_param_hook;
      64           77714 :         pstate->p_ref_hook_state = parentParseState->p_ref_hook_state;
      65 ECB             :         /* query environment stays in context for the whole parse analysis */
      66 GIC       77714 :         pstate->p_queryEnv = parentParseState->p_queryEnv;
      67 ECB             :     }
      68                 : 
      69 GIC     1144016 :     return pstate;
      70 ECB             : }
      71                 : 
      72                 : /*
      73                 :  * free_parsestate
      74                 :  *      Release a ParseState and any subsidiary resources.
      75                 :  */
      76                 : void
      77 GIC     1063519 : free_parsestate(ParseState *pstate)
      78 ECB             : {
      79                 :     /*
      80                 :      * Check that we did not produce too many resnos; at the very least we
      81                 :      * cannot allow more than 2^16, since that would exceed the range of a
      82                 :      * AttrNumber. It seems safest to use MaxTupleAttributeNumber.
      83                 :      */
      84 GIC     1063519 :     if (pstate->p_next_resno - 1 > MaxTupleAttributeNumber)
      85 LBC           0 :         ereport(ERROR,
      86 EUB             :                 (errcode(ERRCODE_TOO_MANY_COLUMNS),
      87                 :                  errmsg("target lists can have at most %d entries",
      88                 :                         MaxTupleAttributeNumber)));
      89                 : 
      90 GIC     1063519 :     if (pstate->p_target_relation != NULL)
      91 CBC       52204 :         table_close(pstate->p_target_relation, NoLock);
      92 ECB             : 
      93 GIC     1063519 :     pfree(pstate);
      94 CBC     1063519 : }
      95 ECB             : 
      96                 : 
      97                 : /*
      98                 :  * parser_errposition
      99                 :  *      Report a parse-analysis-time cursor position, if possible.
     100                 :  *
     101                 :  * This is expected to be used within an ereport() call.  The return value
     102                 :  * is a dummy (always 0, in fact).
     103                 :  *
     104                 :  * The locations stored in raw parsetrees are byte offsets into the source
     105                 :  * string.  We have to convert them to 1-based character indexes for reporting
     106                 :  * to clients.  (We do things this way to avoid unnecessary overhead in the
     107                 :  * normal non-error case: computing character indexes would be much more
     108                 :  * expensive than storing token offsets.)
     109                 :  */
     110                 : int
     111 GIC        4027 : parser_errposition(ParseState *pstate, int location)
     112 ECB             : {
     113                 :     int         pos;
     114                 : 
     115                 :     /* No-op if location was not provided */
     116 GIC        4027 :     if (location < 0)
     117 CBC          39 :         return 0;
     118 ECB             :     /* Can't do anything if source text is not available */
     119 GIC        3988 :     if (pstate == NULL || pstate->p_sourcetext == NULL)
     120 CBC          67 :         return 0;
     121 ECB             :     /* Convert offset to character number */
     122 GIC        3921 :     pos = pg_mbstrlen_with_len(pstate->p_sourcetext, location) + 1;
     123 ECB             :     /* And pass it to the ereport mechanism */
     124 GIC        3921 :     return errposition(pos);
     125 ECB             : }
     126                 : 
     127                 : 
     128                 : /*
     129                 :  * setup_parser_errposition_callback
     130                 :  *      Arrange for non-parser errors to report an error position
     131                 :  *
     132                 :  * Sometimes the parser calls functions that aren't part of the parser
     133                 :  * subsystem and can't reasonably be passed a ParseState; yet we would
     134                 :  * like any errors thrown in those functions to be tagged with a parse
     135                 :  * error location.  Use this function to set up an error context stack
     136                 :  * entry that will accomplish that.  Usage pattern:
     137                 :  *
     138                 :  *      declare a local variable "ParseCallbackState pcbstate"
     139                 :  *      ...
     140                 :  *      setup_parser_errposition_callback(&pcbstate, pstate, location);
     141                 :  *      call function that might throw error;
     142                 :  *      cancel_parser_errposition_callback(&pcbstate);
     143                 :  */
     144                 : void
     145 GIC     1504124 : setup_parser_errposition_callback(ParseCallbackState *pcbstate,
     146 ECB             :                                   ParseState *pstate, int location)
     147                 : {
     148                 :     /* Setup error traceback support for ereport() */
     149 GIC     1504124 :     pcbstate->pstate = pstate;
     150 CBC     1504124 :     pcbstate->location = location;
     151         1504124 :     pcbstate->errcallback.callback = pcb_error_callback;
     152         1504124 :     pcbstate->errcallback.arg = (void *) pcbstate;
     153         1504124 :     pcbstate->errcallback.previous = error_context_stack;
     154         1504124 :     error_context_stack = &pcbstate->errcallback;
     155         1504124 : }
     156 ECB             : 
     157                 : /*
     158                 :  * Cancel a previously-set-up errposition callback.
     159                 :  */
     160                 : void
     161 GIC     1501867 : cancel_parser_errposition_callback(ParseCallbackState *pcbstate)
     162 ECB             : {
     163                 :     /* Pop the error context stack */
     164 GIC     1501867 :     error_context_stack = pcbstate->errcallback.previous;
     165 CBC     1501867 : }
     166 ECB             : 
     167                 : /*
     168                 :  * Error context callback for inserting parser error location.
     169                 :  *
     170                 :  * Note that this will be called for *any* error occurring while the
     171                 :  * callback is installed.  We avoid inserting an irrelevant error location
     172                 :  * if the error is a query cancel --- are there any other important cases?
     173                 :  */
     174                 : static void
     175 GIC        2264 : pcb_error_callback(void *arg)
     176 ECB             : {
     177 GIC        2264 :     ParseCallbackState *pcbstate = (ParseCallbackState *) arg;
     178 ECB             : 
     179 GIC        2264 :     if (geterrcode() != ERRCODE_QUERY_CANCELED)
     180 CBC        2264 :         (void) parser_errposition(pcbstate->pstate, pcbstate->location);
     181            2264 : }
     182 ECB             : 
     183                 : 
     184                 : /*
     185                 :  * transformContainerType()
     186                 :  *      Identify the actual container type for a subscripting operation.
     187                 :  *
     188                 :  * containerType/containerTypmod are modified if necessary to identify
     189                 :  * the actual container type and typmod.  This mainly involves smashing
     190                 :  * any domain to its base type, but there are some special considerations.
     191                 :  * Note that caller still needs to check if the result type is a container.
     192                 :  */
     193                 : void
     194 GIC        9320 : transformContainerType(Oid *containerType, int32 *containerTypmod)
     195 ECB             : {
     196                 :     /*
     197                 :      * If the input is a domain, smash to base type, and extract the actual
     198                 :      * typmod to be applied to the base type. Subscripting a domain is an
     199                 :      * operation that necessarily works on the base container type, not the
     200                 :      * domain itself. (Note that we provide no method whereby the creator of a
     201                 :      * domain over a container type could hide its ability to be subscripted.)
     202                 :      */
     203 GIC        9320 :     *containerType = getBaseTypeAndTypmod(*containerType, containerTypmod);
     204 ECB             : 
     205                 :     /*
     206                 :      * We treat int2vector and oidvector as though they were domains over
     207                 :      * int2[] and oid[].  This is needed because array slicing could create an
     208                 :      * array that doesn't satisfy the dimensionality constraints of the
     209                 :      * xxxvector type; so we want the result of a slice operation to be
     210                 :      * considered to be of the more general type.
     211                 :      */
     212 GIC        9320 :     if (*containerType == INT2VECTOROID)
     213 CBC        1391 :         *containerType = INT2ARRAYOID;
     214            7929 :     else if (*containerType == OIDVECTOROID)
     215             411 :         *containerType = OIDARRAYOID;
     216            9320 : }
     217 ECB             : 
     218                 : /*
     219                 :  * transformContainerSubscripts()
     220                 :  *      Transform container (array, etc) subscripting.  This is used for both
     221                 :  *      container fetch and container assignment.
     222                 :  *
     223                 :  * In a container fetch, we are given a source container value and we produce
     224                 :  * an expression that represents the result of extracting a single container
     225                 :  * element or a container slice.
     226                 :  *
     227                 :  * Container assignments are treated basically the same as container fetches
     228                 :  * here.  The caller will modify the result node to insert the source value
     229                 :  * that is to be assigned to the element or slice that a fetch would have
     230                 :  * retrieved.  The execution result will be a new container value with
     231                 :  * the source value inserted into the right part of the container.
     232                 :  *
     233                 :  * For both cases, if the source is of a domain-over-container type, the
     234                 :  * result is the same as if it had been of the container type; essentially,
     235                 :  * we must fold a domain to its base type before applying subscripting.
     236                 :  * (Note that int2vector and oidvector are treated as domains here.)
     237                 :  *
     238                 :  * pstate           Parse state
     239                 :  * containerBase    Already-transformed expression for the container as a whole
     240                 :  * containerType    OID of container's datatype (should match type of
     241                 :  *                  containerBase, or be the base type of containerBase's
     242                 :  *                  domain type)
     243                 :  * containerTypMod  typmod for the container
     244                 :  * indirection      Untransformed list of subscripts (must not be NIL)
     245                 :  * isAssignment     True if this will become a container assignment.
     246                 :  */
     247                 : SubscriptingRef *
     248 GIC        9320 : transformContainerSubscripts(ParseState *pstate,
     249 ECB             :                              Node *containerBase,
     250                 :                              Oid containerType,
     251                 :                              int32 containerTypMod,
     252                 :                              List *indirection,
     253                 :                              bool isAssignment)
     254                 : {
     255                 :     SubscriptingRef *sbsref;
     256                 :     const SubscriptRoutines *sbsroutines;
     257                 :     Oid         elementType;
     258 GIC        9320 :     bool        isSlice = false;
     259 ECB             :     ListCell   *idx;
     260                 : 
     261                 :     /*
     262                 :      * Determine the actual container type, smashing any domain.  In the
     263                 :      * assignment case the caller already did this, since it also needs to
     264                 :      * know the actual container type.
     265                 :      */
     266 GIC        9320 :     if (!isAssignment)
     267 CBC        8661 :         transformContainerType(&containerType, &containerTypMod);
     268 ECB             : 
     269                 :     /*
     270                 :      * Verify that the container type is subscriptable, and get its support
     271                 :      * functions and typelem.
     272                 :      */
     273 GIC        9320 :     sbsroutines = getSubscriptingRoutines(containerType, &elementType);
     274 CBC        9320 :     if (!sbsroutines)
     275               5 :         ereport(ERROR,
     276 ECB             :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
     277                 :                  errmsg("cannot subscript type %s because it does not support subscripting",
     278                 :                         format_type_be(containerType)),
     279                 :                  parser_errposition(pstate, exprLocation(containerBase))));
     280                 : 
     281                 :     /*
     282                 :      * Detect whether any of the indirection items are slice specifiers.
     283                 :      *
     284                 :      * A list containing only simple subscripts refers to a single container
     285                 :      * element.  If any of the items are slice specifiers (lower:upper), then
     286                 :      * the subscript expression means a container slice operation.
     287                 :      */
     288 GIC       18648 :     foreach(idx, indirection)
     289 ECB             :     {
     290 GIC        9554 :         A_Indices  *ai = lfirst_node(A_Indices, idx);
     291 ECB             : 
     292 GIC        9554 :         if (ai->is_slice)
     293 ECB             :         {
     294 GIC         221 :             isSlice = true;
     295 CBC         221 :             break;
     296 ECB             :         }
     297                 :     }
     298                 : 
     299                 :     /*
     300                 :      * Ready to build the SubscriptingRef node.
     301                 :      */
     302 GIC        9315 :     sbsref = makeNode(SubscriptingRef);
     303 ECB             : 
     304 GIC        9315 :     sbsref->refcontainertype = containerType;
     305 CBC        9315 :     sbsref->refelemtype = elementType;
     306 ECB             :     /* refrestype is to be set by container-specific logic */
     307 GIC        9315 :     sbsref->reftypmod = containerTypMod;
     308 ECB             :     /* refcollid will be set by parse_collate.c */
     309                 :     /* refupperindexpr, reflowerindexpr are to be set by container logic */
     310 GIC        9315 :     sbsref->refexpr = (Expr *) containerBase;
     311 CBC        9315 :     sbsref->refassgnexpr = NULL; /* caller will fill if it's an assignment */
     312 ECB             : 
     313                 :     /*
     314                 :      * Call the container-type-specific logic to transform the subscripts and
     315                 :      * determine the subscripting result type.
     316                 :      */
     317 GIC        9315 :     sbsroutines->transform(sbsref, indirection, pstate,
     318 ECB             :                            isSlice, isAssignment);
     319                 : 
     320                 :     /*
     321                 :      * Verify we got a valid type (this defends, for example, against someone
     322                 :      * using array_subscript_handler as typsubscript without setting typelem).
     323                 :      */
     324 GIC        9292 :     if (!OidIsValid(sbsref->refrestype))
     325 LBC           0 :         ereport(ERROR,
     326 EUB             :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
     327                 :                  errmsg("cannot subscript type %s because it does not support subscripting",
     328                 :                         format_type_be(containerType))));
     329                 : 
     330 GIC        9292 :     return sbsref;
     331 ECB             : }
     332                 : 
     333                 : /*
     334                 :  * make_const
     335                 :  *
     336                 :  *  Convert an A_Const node (as returned by the grammar) to a Const node
     337                 :  *  of the "natural" type for the constant.  Note that this routine is
     338                 :  *  only used when there is no explicit cast for the constant, so we
     339                 :  *  have to guess what type is wanted.
     340                 :  *
     341                 :  *  For string literals we produce a constant of type UNKNOWN ---- whose
     342                 :  *  representation is the same as cstring, but it indicates to later type
     343                 :  *  resolution that we're not sure yet what type it should be considered.
     344                 :  *  Explicit "NULL" constants are also typed as UNKNOWN.
     345                 :  *
     346                 :  *  For integers and floats we produce int4, int8, or numeric depending
     347                 :  *  on the value of the number.  XXX We should produce int2 as well,
     348                 :  *  but additional cleanup is needed before we can do that; there are
     349                 :  *  too many examples that fail if we try.
     350                 :  */
     351                 : Const *
     352 GIC      878012 : make_const(ParseState *pstate, A_Const *aconst)
     353 ECB             : {
     354                 :     Const      *con;
     355                 :     Datum       val;
     356                 :     Oid         typeid;
     357                 :     int         typelen;
     358                 :     bool        typebyval;
     359                 :     ParseCallbackState pcbstate;
     360                 : 
     361 GIC      878012 :     if (aconst->isnull)
     362 ECB             :     {
     363                 :         /* return a null const */
     364 GIC      111148 :         con = makeConst(UNKNOWNOID,
     365 ECB             :                         -1,
     366                 :                         InvalidOid,
     367                 :                         -2,
     368                 :                         (Datum) 0,
     369                 :                         true,
     370                 :                         false);
     371 GIC      111148 :         con->location = aconst->location;
     372 CBC      111148 :         return con;
     373 ECB             :     }
     374                 : 
     375 GIC      766864 :     switch (nodeTag(&aconst->val))
     376 ECB             :     {
     377 GIC      243326 :         case T_Integer:
     378 CBC      243326 :             val = Int32GetDatum(intVal(&aconst->val));
     379 ECB             : 
     380 GIC      243326 :             typeid = INT4OID;
     381 CBC      243326 :             typelen = sizeof(int32);
     382          243326 :             typebyval = true;
     383          243326 :             break;
     384 ECB             : 
     385 GIC        5249 :         case T_Float:
     386 ECB             :             {
     387                 :                 /* could be an oversize integer as well as a float ... */
     388                 : 
     389 GNC        5249 :                 ErrorSaveContext escontext = {T_ErrorSaveContext};
     390                 :                 int64       val64;
     391                 : 
     392            5249 :                 val64 = pg_strtoint64_safe(aconst->val.fval.fval, (Node *) &escontext);
     393            5249 :                 if (!escontext.error_occurred)
     394                 :                 {
     395                 :                     /*
     396                 :                      * It might actually fit in int32. Probably only INT_MIN
     397                 :                      * can occur, but we'll code the test generally just to be
     398                 :                      * sure.
     399                 :                      */
     400 CBC         420 :                     int32       val32 = (int32) val64;
     401                 : 
     402             420 :                     if (val64 == (int64) val32)
     403                 :                     {
     404              60 :                         val = Int32GetDatum(val32);
     405                 : 
     406              60 :                         typeid = INT4OID;
     407              60 :                         typelen = sizeof(int32);
     408              60 :                         typebyval = true;
     409                 :                     }
     410                 :                     else
     411                 :                     {
     412             360 :                         val = Int64GetDatum(val64);
     413                 : 
     414             360 :                         typeid = INT8OID;
     415             360 :                         typelen = sizeof(int64);
     416             360 :                         typebyval = FLOAT8PASSBYVAL;    /* int8 and float8 alike */
     417                 :                     }
     418                 :                 }
     419                 :                 else
     420                 :                 {
     421                 :                     /* arrange to report location if numeric_in() fails */
     422            4829 :                     setup_parser_errposition_callback(&pcbstate, pstate, aconst->location);
     423            4829 :                     val = DirectFunctionCall3(numeric_in,
     424                 :                                               CStringGetDatum(aconst->val.fval.fval),
     425                 :                                               ObjectIdGetDatum(InvalidOid),
     426                 :                                               Int32GetDatum(-1));
     427            4829 :                     cancel_parser_errposition_callback(&pcbstate);
     428                 : 
     429            4829 :                     typeid = NUMERICOID;
     430            4829 :                     typelen = -1;   /* variable len */
     431            4829 :                     typebyval = false;
     432                 :                 }
     433            5249 :                 break;
     434                 :             }
     435                 : 
     436           29715 :         case T_Boolean:
     437           29715 :             val = BoolGetDatum(boolVal(&aconst->val));
     438                 : 
     439           29715 :             typeid = BOOLOID;
     440           29715 :             typelen = 1;
     441           29715 :             typebyval = true;
     442           29715 :             break;
     443                 : 
     444          486551 :         case T_String:
     445                 : 
     446                 :             /*
     447                 :              * We assume here that UNKNOWN's internal representation is the
     448                 :              * same as CSTRING
     449                 :              */
     450          486551 :             val = CStringGetDatum(strVal(&aconst->val));
     451                 : 
     452          486551 :             typeid = UNKNOWNOID;    /* will be coerced later */
     453          486551 :             typelen = -2;       /* cstring-style varwidth type */
     454          486551 :             typebyval = false;
     455          486551 :             break;
     456                 : 
     457            2023 :         case T_BitString:
     458                 :             /* arrange to report location if bit_in() fails */
     459            2023 :             setup_parser_errposition_callback(&pcbstate, pstate, aconst->location);
     460            2023 :             val = DirectFunctionCall3(bit_in,
     461                 :                                       CStringGetDatum(aconst->val.bsval.bsval),
     462                 :                                       ObjectIdGetDatum(InvalidOid),
     463                 :                                       Int32GetDatum(-1));
     464            2023 :             cancel_parser_errposition_callback(&pcbstate);
     465            2023 :             typeid = BITOID;
     466            2023 :             typelen = -1;
     467            2023 :             typebyval = false;
     468            2023 :             break;
     469                 : 
     470 UBC           0 :         default:
     471               0 :             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(&aconst->val));
     472                 :             return NULL;        /* keep compiler quiet */
     473                 :     }
     474                 : 
     475 CBC      766864 :     con = makeConst(typeid,
     476                 :                     -1,         /* typmod -1 is OK for all cases */
     477                 :                     InvalidOid, /* all cases are uncollatable types */
     478                 :                     typelen,
     479                 :                     val,
     480                 :                     false,
     481                 :                     typebyval);
     482          766864 :     con->location = aconst->location;
     483                 : 
     484          766864 :     return con;
     485                 : }
        

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