LCOV - differential code coverage report
Current view: top level - src/backend/optimizer/util - paramassign.c (source / functions) Coverage Total Hit UBC GIC GNC CBC ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 95.1 % 205 195 10 15 8 172 14 9
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 12 12 2 2 8 2
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * paramassign.c
       4                 :  *      Functions for assigning PARAM_EXEC slots during planning.
       5                 :  *
       6                 :  * This module is responsible for managing three planner data structures:
       7                 :  *
       8                 :  * root->glob->paramExecTypes: records actual assignments of PARAM_EXEC slots.
       9                 :  * The i'th list element holds the data type OID of the i'th parameter slot.
      10                 :  * (Elements can be InvalidOid if they represent slots that are needed for
      11                 :  * chgParam signaling, but will never hold a value at runtime.)  This list is
      12                 :  * global to the whole plan since the executor has only one PARAM_EXEC array.
      13                 :  * Assignments are permanent for the plan: we never remove entries once added.
      14                 :  *
      15                 :  * root->plan_params: a list of PlannerParamItem nodes, recording Vars and
      16                 :  * PlaceHolderVars that the root's query level needs to supply to lower-level
      17                 :  * subqueries, along with the PARAM_EXEC number to use for each such value.
      18                 :  * Elements are added to this list while planning a subquery, and the list
      19                 :  * is reset to empty after completion of each subquery.
      20                 :  *
      21                 :  * root->curOuterParams: a list of NestLoopParam nodes, recording Vars and
      22                 :  * PlaceHolderVars that some outer level of nestloop needs to pass down to
      23                 :  * a lower-level plan node in its righthand side.  Elements are added to this
      24                 :  * list as createplan.c creates lower Plan nodes that need such Params, and
      25                 :  * are removed when it creates a NestLoop Plan node that will supply those
      26                 :  * values.
      27                 :  *
      28                 :  * The latter two data structures are used to prevent creating multiple
      29                 :  * PARAM_EXEC slots (each requiring work to fill) when the same upper
      30                 :  * SubPlan or NestLoop supplies a value that is referenced in more than
      31                 :  * one place in its child plan nodes.  However, when the same Var has to
      32                 :  * be supplied to different subplan trees by different SubPlan or NestLoop
      33                 :  * parent nodes, we don't recognize any commonality; a fresh plan_params or
      34                 :  * curOuterParams entry will be made (since the old one has been removed
      35                 :  * when we finished processing the earlier SubPlan or NestLoop) and a fresh
      36                 :  * PARAM_EXEC number will be assigned.  At one time we tried to avoid
      37                 :  * allocating duplicate PARAM_EXEC numbers in such cases, but it's harder
      38                 :  * than it seems to avoid bugs due to overlapping Param lifetimes, so we
      39                 :  * don't risk that anymore.  Minimizing the number of PARAM_EXEC slots
      40                 :  * doesn't really save much executor work anyway.
      41                 :  *
      42                 :  *
      43                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
      44                 :  * Portions Copyright (c) 1994, Regents of the University of California
      45                 :  *
      46                 :  * IDENTIFICATION
      47                 :  *    src/backend/optimizer/util/paramassign.c
      48                 :  *
      49                 :  *-------------------------------------------------------------------------
      50                 :  */
      51                 : #include "postgres.h"
      52                 : 
      53                 : #include "nodes/nodeFuncs.h"
      54                 : #include "nodes/plannodes.h"
      55                 : #include "optimizer/paramassign.h"
      56                 : #include "optimizer/placeholder.h"
      57                 : #include "rewrite/rewriteManip.h"
      58                 : 
      59                 : 
      60                 : /*
      61                 :  * Select a PARAM_EXEC number to identify the given Var as a parameter for
      62                 :  * the current subquery.  (It might already have one.)
      63                 :  * Record the need for the Var in the proper upper-level root->plan_params.
      64                 :  */
      65                 : static int
      66 CBC       19428 : assign_param_for_var(PlannerInfo *root, Var *var)
      67                 : {
      68                 :     ListCell   *ppl;
      69                 :     PlannerParamItem *pitem;
      70                 :     Index       levelsup;
      71                 : 
      72                 :     /* Find the query level the Var belongs to */
      73           39573 :     for (levelsup = var->varlevelsup; levelsup > 0; levelsup--)
      74           20145 :         root = root->parent_root;
      75                 : 
      76                 :     /* If there's already a matching PlannerParamItem there, just use it */
      77           29060 :     foreach(ppl, root->plan_params)
      78                 :     {
      79           12683 :         pitem = (PlannerParamItem *) lfirst(ppl);
      80           12683 :         if (IsA(pitem->item, Var))
      81                 :         {
      82           12683 :             Var        *pvar = (Var *) pitem->item;
      83                 : 
      84                 :             /*
      85                 :              * This comparison must match _equalVar(), except for ignoring
      86                 :              * varlevelsup.  Note that _equalVar() ignores varnosyn,
      87                 :              * varattnosyn, and location, so this does too.
      88                 :              */
      89           12683 :             if (pvar->varno == var->varno &&
      90           11719 :                 pvar->varattno == var->varattno &&
      91            3051 :                 pvar->vartype == var->vartype &&
      92            3051 :                 pvar->vartypmod == var->vartypmod &&
      93            3051 :                 pvar->varcollid == var->varcollid)
      94            3051 :                 return pitem->paramId;
      95                 :         }
      96                 :     }
      97                 : 
      98                 :     /* Nope, so make a new one */
      99           16377 :     var = copyObject(var);
     100           16377 :     var->varlevelsup = 0;
     101                 : 
     102           16377 :     pitem = makeNode(PlannerParamItem);
     103           16377 :     pitem->item = (Node *) var;
     104           16377 :     pitem->paramId = list_length(root->glob->paramExecTypes);
     105           16377 :     root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes,
     106                 :                                              var->vartype);
     107                 : 
     108           16377 :     root->plan_params = lappend(root->plan_params, pitem);
     109                 : 
     110           16377 :     return pitem->paramId;
     111                 : }
     112                 : 
     113                 : /*
     114                 :  * Generate a Param node to replace the given Var,
     115                 :  * which is expected to have varlevelsup > 0 (ie, it is not local).
     116                 :  * Record the need for the Var in the proper upper-level root->plan_params.
     117                 :  */
     118                 : Param *
     119           19428 : replace_outer_var(PlannerInfo *root, Var *var)
     120                 : {
     121                 :     Param      *retval;
     122                 :     int         i;
     123                 : 
     124           19428 :     Assert(var->varlevelsup > 0 && var->varlevelsup < root->query_level);
     125                 : 
     126                 :     /* Find the Var in the appropriate plan_params, or add it if not present */
     127           19428 :     i = assign_param_for_var(root, var);
     128                 : 
     129           19428 :     retval = makeNode(Param);
     130           19428 :     retval->paramkind = PARAM_EXEC;
     131           19428 :     retval->paramid = i;
     132           19428 :     retval->paramtype = var->vartype;
     133           19428 :     retval->paramtypmod = var->vartypmod;
     134           19428 :     retval->paramcollid = var->varcollid;
     135           19428 :     retval->location = var->location;
     136                 : 
     137           19428 :     return retval;
     138                 : }
     139                 : 
     140                 : /*
     141                 :  * Select a PARAM_EXEC number to identify the given PlaceHolderVar as a
     142                 :  * parameter for the current subquery.  (It might already have one.)
     143                 :  * Record the need for the PHV in the proper upper-level root->plan_params.
     144                 :  *
     145                 :  * This is just like assign_param_for_var, except for PlaceHolderVars.
     146                 :  */
     147                 : static int
     148              21 : assign_param_for_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
     149                 : {
     150                 :     ListCell   *ppl;
     151                 :     PlannerParamItem *pitem;
     152                 :     Index       levelsup;
     153                 : 
     154                 :     /* Find the query level the PHV belongs to */
     155              42 :     for (levelsup = phv->phlevelsup; levelsup > 0; levelsup--)
     156              21 :         root = root->parent_root;
     157                 : 
     158                 :     /* If there's already a matching PlannerParamItem there, just use it */
     159              51 :     foreach(ppl, root->plan_params)
     160                 :     {
     161              30 :         pitem = (PlannerParamItem *) lfirst(ppl);
     162              30 :         if (IsA(pitem->item, PlaceHolderVar))
     163                 :         {
     164 UBC           0 :             PlaceHolderVar *pphv = (PlaceHolderVar *) pitem->item;
     165                 : 
     166                 :             /* We assume comparing the PHIDs is sufficient */
     167               0 :             if (pphv->phid == phv->phid)
     168               0 :                 return pitem->paramId;
     169                 :         }
     170                 :     }
     171                 : 
     172                 :     /* Nope, so make a new one */
     173 CBC          21 :     phv = copyObject(phv);
     174              21 :     IncrementVarSublevelsUp((Node *) phv, -((int) phv->phlevelsup), 0);
     175              21 :     Assert(phv->phlevelsup == 0);
     176                 : 
     177              21 :     pitem = makeNode(PlannerParamItem);
     178              21 :     pitem->item = (Node *) phv;
     179              21 :     pitem->paramId = list_length(root->glob->paramExecTypes);
     180              21 :     root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes,
     181              21 :                                              exprType((Node *) phv->phexpr));
     182                 : 
     183              21 :     root->plan_params = lappend(root->plan_params, pitem);
     184                 : 
     185              21 :     return pitem->paramId;
     186                 : }
     187                 : 
     188                 : /*
     189                 :  * Generate a Param node to replace the given PlaceHolderVar,
     190                 :  * which is expected to have phlevelsup > 0 (ie, it is not local).
     191                 :  * Record the need for the PHV in the proper upper-level root->plan_params.
     192                 :  *
     193                 :  * This is just like replace_outer_var, except for PlaceHolderVars.
     194                 :  */
     195                 : Param *
     196              21 : replace_outer_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
     197                 : {
     198                 :     Param      *retval;
     199                 :     int         i;
     200                 : 
     201              21 :     Assert(phv->phlevelsup > 0 && phv->phlevelsup < root->query_level);
     202                 : 
     203                 :     /* Find the PHV in the appropriate plan_params, or add it if not present */
     204              21 :     i = assign_param_for_placeholdervar(root, phv);
     205                 : 
     206              21 :     retval = makeNode(Param);
     207              21 :     retval->paramkind = PARAM_EXEC;
     208              21 :     retval->paramid = i;
     209              21 :     retval->paramtype = exprType((Node *) phv->phexpr);
     210              21 :     retval->paramtypmod = exprTypmod((Node *) phv->phexpr);
     211              21 :     retval->paramcollid = exprCollation((Node *) phv->phexpr);
     212              21 :     retval->location = -1;
     213                 : 
     214              21 :     return retval;
     215                 : }
     216                 : 
     217                 : /*
     218                 :  * Generate a Param node to replace the given Aggref
     219                 :  * which is expected to have agglevelsup > 0 (ie, it is not local).
     220                 :  * Record the need for the Aggref in the proper upper-level root->plan_params.
     221                 :  */
     222                 : Param *
     223              26 : replace_outer_agg(PlannerInfo *root, Aggref *agg)
     224                 : {
     225                 :     Param      *retval;
     226                 :     PlannerParamItem *pitem;
     227                 :     Index       levelsup;
     228                 : 
     229              26 :     Assert(agg->agglevelsup > 0 && agg->agglevelsup < root->query_level);
     230                 : 
     231                 :     /* Find the query level the Aggref belongs to */
     232              52 :     for (levelsup = agg->agglevelsup; levelsup > 0; levelsup--)
     233              26 :         root = root->parent_root;
     234                 : 
     235                 :     /*
     236                 :      * It does not seem worthwhile to try to de-duplicate references to outer
     237                 :      * aggs.  Just make a new slot every time.
     238                 :      */
     239              26 :     agg = copyObject(agg);
     240              26 :     IncrementVarSublevelsUp((Node *) agg, -((int) agg->agglevelsup), 0);
     241              26 :     Assert(agg->agglevelsup == 0);
     242                 : 
     243              26 :     pitem = makeNode(PlannerParamItem);
     244              26 :     pitem->item = (Node *) agg;
     245              26 :     pitem->paramId = list_length(root->glob->paramExecTypes);
     246              26 :     root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes,
     247                 :                                              agg->aggtype);
     248                 : 
     249              26 :     root->plan_params = lappend(root->plan_params, pitem);
     250                 : 
     251              26 :     retval = makeNode(Param);
     252              26 :     retval->paramkind = PARAM_EXEC;
     253              26 :     retval->paramid = pitem->paramId;
     254              26 :     retval->paramtype = agg->aggtype;
     255              26 :     retval->paramtypmod = -1;
     256              26 :     retval->paramcollid = agg->aggcollid;
     257              26 :     retval->location = agg->location;
     258                 : 
     259              26 :     return retval;
     260                 : }
     261                 : 
     262                 : /*
     263                 :  * Generate a Param node to replace the given GroupingFunc expression which is
     264                 :  * expected to have agglevelsup > 0 (ie, it is not local).
     265                 :  * Record the need for the GroupingFunc in the proper upper-level
     266                 :  * root->plan_params.
     267                 :  */
     268                 : Param *
     269              32 : replace_outer_grouping(PlannerInfo *root, GroupingFunc *grp)
     270                 : {
     271                 :     Param      *retval;
     272                 :     PlannerParamItem *pitem;
     273                 :     Index       levelsup;
     274              32 :     Oid         ptype = exprType((Node *) grp);
     275                 : 
     276              32 :     Assert(grp->agglevelsup > 0 && grp->agglevelsup < root->query_level);
     277                 : 
     278                 :     /* Find the query level the GroupingFunc belongs to */
     279              68 :     for (levelsup = grp->agglevelsup; levelsup > 0; levelsup--)
     280              36 :         root = root->parent_root;
     281                 : 
     282                 :     /*
     283                 :      * It does not seem worthwhile to try to de-duplicate references to outer
     284                 :      * aggs.  Just make a new slot every time.
     285                 :      */
     286              32 :     grp = copyObject(grp);
     287              32 :     IncrementVarSublevelsUp((Node *) grp, -((int) grp->agglevelsup), 0);
     288              32 :     Assert(grp->agglevelsup == 0);
     289                 : 
     290              32 :     pitem = makeNode(PlannerParamItem);
     291              32 :     pitem->item = (Node *) grp;
     292              32 :     pitem->paramId = list_length(root->glob->paramExecTypes);
     293              32 :     root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes,
     294                 :                                              ptype);
     295                 : 
     296              32 :     root->plan_params = lappend(root->plan_params, pitem);
     297                 : 
     298              32 :     retval = makeNode(Param);
     299              32 :     retval->paramkind = PARAM_EXEC;
     300              32 :     retval->paramid = pitem->paramId;
     301              32 :     retval->paramtype = ptype;
     302              32 :     retval->paramtypmod = -1;
     303              32 :     retval->paramcollid = InvalidOid;
     304              32 :     retval->location = grp->location;
     305                 : 
     306              32 :     return retval;
     307                 : }
     308                 : 
     309                 : /*
     310                 :  * Generate a Param node to replace the given Var,
     311                 :  * which is expected to come from some upper NestLoop plan node.
     312                 :  * Record the need for the Var in root->curOuterParams.
     313                 :  */
     314                 : Param *
     315           33369 : replace_nestloop_param_var(PlannerInfo *root, Var *var)
     316                 : {
     317                 :     Param      *param;
     318                 :     NestLoopParam *nlp;
     319                 :     ListCell   *lc;
     320                 : 
     321                 :     /* Is this Var already listed in root->curOuterParams? */
     322           35997 :     foreach(lc, root->curOuterParams)
     323                 :     {
     324           18081 :         nlp = (NestLoopParam *) lfirst(lc);
     325           18081 :         if (equal(var, nlp->paramval))
     326                 :         {
     327                 :             /* Yes, so just make a Param referencing this NLP's slot */
     328           15453 :             param = makeNode(Param);
     329           15453 :             param->paramkind = PARAM_EXEC;
     330           15453 :             param->paramid = nlp->paramno;
     331           15453 :             param->paramtype = var->vartype;
     332           15453 :             param->paramtypmod = var->vartypmod;
     333           15453 :             param->paramcollid = var->varcollid;
     334           15453 :             param->location = var->location;
     335           15453 :             return param;
     336                 :         }
     337                 :     }
     338                 : 
     339                 :     /* No, so assign a PARAM_EXEC slot for a new NLP */
     340           17916 :     param = generate_new_exec_param(root,
     341                 :                                     var->vartype,
     342                 :                                     var->vartypmod,
     343                 :                                     var->varcollid);
     344           17916 :     param->location = var->location;
     345                 : 
     346                 :     /* Add it to the list of required NLPs */
     347           17916 :     nlp = makeNode(NestLoopParam);
     348           17916 :     nlp->paramno = param->paramid;
     349           17916 :     nlp->paramval = copyObject(var);
     350           17916 :     root->curOuterParams = lappend(root->curOuterParams, nlp);
     351                 : 
     352                 :     /* And return the replacement Param */
     353           17916 :     return param;
     354                 : }
     355                 : 
     356                 : /*
     357                 :  * Generate a Param node to replace the given PlaceHolderVar,
     358                 :  * which is expected to come from some upper NestLoop plan node.
     359                 :  * Record the need for the PHV in root->curOuterParams.
     360                 :  *
     361                 :  * This is just like replace_nestloop_param_var, except for PlaceHolderVars.
     362                 :  */
     363                 : Param *
     364             117 : replace_nestloop_param_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
     365                 : {
     366                 :     Param      *param;
     367                 :     NestLoopParam *nlp;
     368                 :     ListCell   *lc;
     369                 : 
     370                 :     /* Is this PHV already listed in root->curOuterParams? */
     371             156 :     foreach(lc, root->curOuterParams)
     372                 :     {
     373              90 :         nlp = (NestLoopParam *) lfirst(lc);
     374              90 :         if (equal(phv, nlp->paramval))
     375                 :         {
     376                 :             /* Yes, so just make a Param referencing this NLP's slot */
     377              51 :             param = makeNode(Param);
     378              51 :             param->paramkind = PARAM_EXEC;
     379              51 :             param->paramid = nlp->paramno;
     380              51 :             param->paramtype = exprType((Node *) phv->phexpr);
     381              51 :             param->paramtypmod = exprTypmod((Node *) phv->phexpr);
     382              51 :             param->paramcollid = exprCollation((Node *) phv->phexpr);
     383              51 :             param->location = -1;
     384              51 :             return param;
     385                 :         }
     386                 :     }
     387                 : 
     388                 :     /* No, so assign a PARAM_EXEC slot for a new NLP */
     389              66 :     param = generate_new_exec_param(root,
     390              66 :                                     exprType((Node *) phv->phexpr),
     391              66 :                                     exprTypmod((Node *) phv->phexpr),
     392              66 :                                     exprCollation((Node *) phv->phexpr));
     393                 : 
     394                 :     /* Add it to the list of required NLPs */
     395              66 :     nlp = makeNode(NestLoopParam);
     396              66 :     nlp->paramno = param->paramid;
     397              66 :     nlp->paramval = (Var *) copyObject(phv);
     398              66 :     root->curOuterParams = lappend(root->curOuterParams, nlp);
     399                 : 
     400                 :     /* And return the replacement Param */
     401              66 :     return param;
     402                 : }
     403                 : 
     404                 : /*
     405                 :  * process_subquery_nestloop_params
     406                 :  *    Handle params of a parameterized subquery that need to be fed
     407                 :  *    from an outer nestloop.
     408                 :  *
     409                 :  * Currently, that would be *all* params that a subquery in FROM has demanded
     410                 :  * from the current query level, since they must be LATERAL references.
     411                 :  *
     412                 :  * subplan_params is a list of PlannerParamItems that we intend to pass to
     413                 :  * a subquery-in-FROM.  (This was constructed in root->plan_params while
     414                 :  * planning the subquery, but isn't there anymore when this is called.)
     415                 :  *
     416                 :  * The subplan's references to the outer variables are already represented
     417                 :  * as PARAM_EXEC Params, since that conversion was done by the routines above
     418                 :  * while planning the subquery.  So we need not modify the subplan or the
     419                 :  * PlannerParamItems here.  What we do need to do is add entries to
     420                 :  * root->curOuterParams to signal the parent nestloop plan node that it must
     421                 :  * provide these values.  This differs from replace_nestloop_param_var in
     422                 :  * that the PARAM_EXEC slots to use have already been determined.
     423                 :  *
     424                 :  * Note that we also use root->curOuterRels as an implicit parameter for
     425                 :  * sanity checks.
     426                 :  */
     427                 : void
     428             191 : process_subquery_nestloop_params(PlannerInfo *root, List *subplan_params)
     429                 : {
     430                 :     ListCell   *lc;
     431                 : 
     432             430 :     foreach(lc, subplan_params)
     433                 :     {
     434             239 :         PlannerParamItem *pitem = lfirst_node(PlannerParamItem, lc);
     435                 : 
     436             239 :         if (IsA(pitem->item, Var))
     437                 :         {
     438             224 :             Var        *var = (Var *) pitem->item;
     439                 :             NestLoopParam *nlp;
     440                 :             ListCell   *lc2;
     441                 : 
     442                 :             /* If not from a nestloop outer rel, complain */
     443             224 :             if (!bms_is_member(var->varno, root->curOuterRels))
     444 UBC           0 :                 elog(ERROR, "non-LATERAL parameter required by subquery");
     445                 : 
     446                 :             /* Is this param already listed in root->curOuterParams? */
     447 GNC         328 :             foreach(lc2, root->curOuterParams)
     448                 :             {
     449             104 :                 nlp = (NestLoopParam *) lfirst(lc2);
     450 CBC         104 :                 if (nlp->paramno == pitem->paramId)
     451                 :                 {
     452 UBC           0 :                     Assert(equal(var, nlp->paramval));
     453                 :                     /* Present, so nothing to do */
     454               0 :                     break;
     455                 :                 }
     456                 :             }
     457 GNC         224 :             if (lc2 == NULL)
     458                 :             {
     459                 :                 /* No, so add it */
     460 CBC         224 :                 nlp = makeNode(NestLoopParam);
     461             224 :                 nlp->paramno = pitem->paramId;
     462             224 :                 nlp->paramval = copyObject(var);
     463             224 :                 root->curOuterParams = lappend(root->curOuterParams, nlp);
     464                 :             }
     465                 :         }
     466              15 :         else if (IsA(pitem->item, PlaceHolderVar))
     467                 :         {
     468              15 :             PlaceHolderVar *phv = (PlaceHolderVar *) pitem->item;
     469                 :             NestLoopParam *nlp;
     470                 :             ListCell   *lc2;
     471                 : 
     472                 :             /* If not from a nestloop outer rel, complain */
     473 GNC          15 :             if (!bms_is_subset(find_placeholder_info(root, phv)->ph_eval_at,
     474 CBC          15 :                                root->curOuterRels))
     475 UBC           0 :                 elog(ERROR, "non-LATERAL parameter required by subquery");
     476                 : 
     477                 :             /* Is this param already listed in root->curOuterParams? */
     478 GNC          45 :             foreach(lc2, root->curOuterParams)
     479                 :             {
     480              30 :                 nlp = (NestLoopParam *) lfirst(lc2);
     481 CBC          30 :                 if (nlp->paramno == pitem->paramId)
     482                 :                 {
     483 UBC           0 :                     Assert(equal(phv, nlp->paramval));
     484                 :                     /* Present, so nothing to do */
     485               0 :                     break;
     486                 :                 }
     487                 :             }
     488 GNC          15 :             if (lc2 == NULL)
     489                 :             {
     490                 :                 /* No, so add it */
     491 CBC          15 :                 nlp = makeNode(NestLoopParam);
     492              15 :                 nlp->paramno = pitem->paramId;
     493              15 :                 nlp->paramval = (Var *) copyObject(phv);
     494              15 :                 root->curOuterParams = lappend(root->curOuterParams, nlp);
     495                 :             }
     496                 :         }
     497                 :         else
     498 UBC           0 :             elog(ERROR, "unexpected type of subquery parameter");
     499                 :     }
     500 CBC         191 : }
     501                 : 
     502                 : /*
     503                 :  * Identify any NestLoopParams that should be supplied by a NestLoop plan
     504                 :  * node with the specified lefthand rels.  Remove them from the active
     505                 :  * root->curOuterParams list and return them as the result list.
     506                 :  */
     507                 : List *
     508           32419 : identify_current_nestloop_params(PlannerInfo *root, Relids leftrelids)
     509                 : {
     510                 :     List       *result;
     511                 :     ListCell   *cell;
     512                 : 
     513           32419 :     result = NIL;
     514           51079 :     foreach(cell, root->curOuterParams)
     515                 :     {
     516           18660 :         NestLoopParam *nlp = (NestLoopParam *) lfirst(cell);
     517                 : 
     518                 :         /*
     519                 :          * We are looking for Vars and PHVs that can be supplied by the
     520                 :          * lefthand rels.
     521 ECB             :          */
     522 CBC       37239 :         if (IsA(nlp->paramval, Var) &&
     523 GIC       18579 :             bms_is_member(nlp->paramval->varno, leftrelids))
     524 ECB             :         {
     525 GIC       18140 :             root->curOuterParams = foreach_delete_current(root->curOuterParams,
     526 ECB             :                                                           cell);
     527 GIC       18140 :             result = lappend(result, nlp);
     528 ECB             :         }
     529 CBC         601 :         else if (IsA(nlp->paramval, PlaceHolderVar) &&
     530 GIC         162 :                  bms_is_subset(find_placeholder_info(root,
     531 GNC          81 :                                                      (PlaceHolderVar *) nlp->paramval)->ph_eval_at,
     532 ECB             :                                leftrelids))
     533                 :         {
     534 GIC          81 :             root->curOuterParams = foreach_delete_current(root->curOuterParams,
     535 ECB             :                                                           cell);
     536 GIC          81 :             result = lappend(result, nlp);
     537                 :         }
     538                 :     }
     539           32419 :     return result;
     540                 : }
     541                 : 
     542                 : /*
     543                 :  * Generate a new Param node that will not conflict with any other.
     544                 :  *
     545                 :  * This is used to create Params representing subplan outputs or
     546                 :  * NestLoop parameters.
     547                 :  *
     548                 :  * We don't need to build a PlannerParamItem for such a Param, but we do
     549 ECB             :  * need to make sure we record the type in paramExecTypes (otherwise,
     550                 :  * there won't be a slot allocated for it).
     551                 :  */
     552                 : Param *
     553 GIC       26823 : generate_new_exec_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod,
     554 ECB             :                         Oid paramcollation)
     555                 : {
     556                 :     Param      *retval;
     557                 : 
     558 GIC       26823 :     retval = makeNode(Param);
     559 CBC       26823 :     retval->paramkind = PARAM_EXEC;
     560           26823 :     retval->paramid = list_length(root->glob->paramExecTypes);
     561           26823 :     root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes,
     562 ECB             :                                              paramtype);
     563 GIC       26823 :     retval->paramtype = paramtype;
     564 CBC       26823 :     retval->paramtypmod = paramtypmod;
     565 GIC       26823 :     retval->paramcollid = paramcollation;
     566           26823 :     retval->location = -1;
     567                 : 
     568           26823 :     return retval;
     569                 : }
     570                 : 
     571                 : /*
     572                 :  * Assign a (nonnegative) PARAM_EXEC ID for a special parameter (one that
     573                 :  * is not actually used to carry a value at runtime).  Such parameters are
     574                 :  * used for special runtime signaling purposes, such as connecting a
     575                 :  * recursive union node to its worktable scan node or forcing plan
     576 ECB             :  * re-evaluation within the EvalPlanQual mechanism.  No actual Param node
     577                 :  * exists with this ID, however.
     578                 :  */
     579                 : int
     580 CBC       57657 : assign_special_exec_param(PlannerInfo *root)
     581                 : {
     582           57657 :     int         paramId = list_length(root->glob->paramExecTypes);
     583                 : 
     584 GIC       57657 :     root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes,
     585                 :                                              InvalidOid);
     586           57657 :     return paramId;
     587                 : }
        

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