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 17:13:01 Functions: 100.0 % 12 12 2 2 8 2
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (180,240] days: 100.0 % 8 8 8
Legend: Lines: hit not hit (240..) days: 94.9 % 197 187 10 15 172 14
Function coverage date bins:
(240..) days: 85.7 % 14 12 2 2 8 2

 Age         Owner                  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
 1549 tgl                        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 &&
 1186                            93            3051 :                 pvar->varcollid == var->varcollid)
 1549                            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                 :         {
 1549 tgl                       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 */
 1549 tgl                       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                 :     {
  629 peter                     434             239 :         PlannerParamItem *pitem = lfirst_node(PlannerParamItem, lc);
                                435                 : 
 1549 tgl                       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))
 1549 tgl                       444 UBC           0 :                 elog(ERROR, "non-LATERAL parameter required by subquery");
                                445                 : 
                                446                 :             /* Is this param already listed in root->curOuterParams? */
  186 drowley                   447 GNC         328 :             foreach(lc2, root->curOuterParams)
                                448                 :             {
                                449             104 :                 nlp = (NestLoopParam *) lfirst(lc2);
 1549 tgl                       450 CBC         104 :                 if (nlp->paramno == pitem->paramId)
                                451                 :                 {
 1549 tgl                       452 UBC           0 :                     Assert(equal(var, nlp->paramval));
                                453                 :                     /* Present, so nothing to do */
                                454               0 :                     break;
                                455                 :                 }
                                456                 :             }
  186 drowley                   457 GNC         224 :             if (lc2 == NULL)
                                458                 :             {
                                459                 :                 /* No, so add it */
 1549 tgl                       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 */
  235 tgl                       473 GNC          15 :             if (!bms_is_subset(find_placeholder_info(root, phv)->ph_eval_at,
 1549 tgl                       474 CBC          15 :                                root->curOuterRels))
 1549 tgl                       475 UBC           0 :                 elog(ERROR, "non-LATERAL parameter required by subquery");
                                476                 : 
                                477                 :             /* Is this param already listed in root->curOuterParams? */
  186 drowley                   478 GNC          45 :             foreach(lc2, root->curOuterParams)
                                479                 :             {
                                480              30 :                 nlp = (NestLoopParam *) lfirst(lc2);
 1549 tgl                       481 CBC          30 :                 if (nlp->paramno == pitem->paramId)
                                482                 :                 {
 1549 tgl                       483 UBC           0 :                     Assert(equal(phv, nlp->paramval));
                                484                 :                     /* Present, so nothing to do */
                                485               0 :                     break;
                                486                 :                 }
                                487                 :             }
  186 drowley                   488 GNC          15 :             if (lc2 == NULL)
                                489                 :             {
                                490                 :                 /* No, so add it */
 1549 tgl                       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
 1549 tgl                       498 UBC           0 :             elog(ERROR, "unexpected type of subquery parameter");
                                499                 :     }
 1549 tgl                       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;
 1364                           514           51079 :     foreach(cell, root->curOuterParams)
                                515                 :     {
 1549                           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.
 1549 tgl                       521 ECB             :          */
 1549 tgl                       522 CBC       37239 :         if (IsA(nlp->paramval, Var) &&
 1549 tgl                       523 GIC       18579 :             bms_is_member(nlp->paramval->varno, leftrelids))
 1549 tgl                       524 ECB             :         {
 1364 tgl                       525 GIC       18140 :             root->curOuterParams = foreach_delete_current(root->curOuterParams,
 1364 tgl                       526 ECB             :                                                           cell);
 1549 tgl                       527 GIC       18140 :             result = lappend(result, nlp);
 1549 tgl                       528 ECB             :         }
 1549 tgl                       529 CBC         601 :         else if (IsA(nlp->paramval, PlaceHolderVar) &&
 1549 tgl                       530 GIC         162 :                  bms_is_subset(find_placeholder_info(root,
  235 tgl                       531 GNC          81 :                                                      (PlaceHolderVar *) nlp->paramval)->ph_eval_at,
 1549 tgl                       532 ECB             :                                leftrelids))
                                533                 :         {
 1364 tgl                       534 GIC          81 :             root->curOuterParams = foreach_delete_current(root->curOuterParams,
 1364 tgl                       535 ECB             :                                                           cell);
 1549 tgl                       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
 1549 tgl                       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 *
 1549 tgl                       553 GIC       26823 : generate_new_exec_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod,
 1549 tgl                       554 ECB             :                         Oid paramcollation)
                                555                 : {
                                556                 :     Param      *retval;
                                557                 : 
 1549 tgl                       558 GIC       26823 :     retval = makeNode(Param);
 1549 tgl                       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,
 1549 tgl                       562 ECB             :                                              paramtype);
 1549 tgl                       563 GIC       26823 :     retval->paramtype = paramtype;
 1549 tgl                       564 CBC       26823 :     retval->paramtypmod = paramtypmod;
 1549 tgl                       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
 1549 tgl                       576 ECB             :  * re-evaluation within the EvalPlanQual mechanism.  No actual Param node
                                577                 :  * exists with this ID, however.
                                578                 :  */
                                579                 : int
 1549 tgl                       580 CBC       57657 : assign_special_exec_param(PlannerInfo *root)
                                581                 : {
                                582           57657 :     int         paramId = list_length(root->glob->paramExecTypes);
                                583                 : 
 1549 tgl                       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