LCOV - differential code coverage report
Current view: top level - src/backend/optimizer/util - paramassign.c (source / functions) Coverage Total Hit UNC UBC GNC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 95.3 % 232 221 1 10 20 201
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 13 13 1 12
Baseline: 16@8cea358b128 Branches: 70.4 % 142 100 5 37 3 97
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 95.2 % 21 20 1 20
(60,120] days: 100.0 % 2 2 2
(240..) days: 95.2 % 209 199 10 199
Function coverage date bins:
[..60] days: 100.0 % 1 1 1
(240..) days: 100.0 % 12 12 12
Branch coverage date bins:
[..60] days: 37.5 % 8 3 5 3
(60,120] days: 50.0 % 4 2 2 2
(240..) days: 73.1 % 130 95 35 95

 Age         Owner                    Branch data    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-2024, 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
 1920 tgl@sss.pgh.pa.us          66                 :CBC       22230 : 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         [ +  + ]:          44666 :     for (levelsup = var->varlevelsup; levelsup > 0; levelsup--)
                                 74                 :          22436 :         root = root->parent_root;
                                 75                 :                : 
                                 76                 :                :     /* If there's already a matching PlannerParamItem there, just use it */
                                 77   [ +  +  +  +  :          33145 :     foreach(ppl, root->plan_params)
                                              +  + ]
                                 78                 :                :     {
                                 79                 :          14413 :         pitem = (PlannerParamItem *) lfirst(ppl);
                                 80         [ +  - ]:          14413 :         if (IsA(pitem->item, Var))
                                 81                 :                :         {
                                 82                 :          14413 :             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         [ +  + ]:          14413 :             if (pvar->varno == var->varno &&
                                 90         [ +  + ]:          13366 :                 pvar->varattno == var->varattno &&
                                 91         [ +  - ]:           3498 :                 pvar->vartype == var->vartype &&
                                 92         [ +  - ]:           3498 :                 pvar->vartypmod == var->vartypmod &&
   79                            93   [ +  -  +  - ]:           6996 :                 pvar->varcollid == var->varcollid &&
                                 94                 :           3498 :                 bms_equal(pvar->varnullingrels, var->varnullingrels))
 1920                            95                 :           3498 :                 return pitem->paramId;
                                 96                 :                :         }
                                 97                 :                :     }
                                 98                 :                : 
                                 99                 :                :     /* Nope, so make a new one */
                                100                 :          18732 :     var = copyObject(var);
                                101                 :          18732 :     var->varlevelsup = 0;
                                102                 :                : 
                                103                 :          18732 :     pitem = makeNode(PlannerParamItem);
                                104                 :          18732 :     pitem->item = (Node *) var;
                                105                 :          18732 :     pitem->paramId = list_length(root->glob->paramExecTypes);
                                106                 :          18732 :     root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes,
                                107                 :                :                                              var->vartype);
                                108                 :                : 
                                109                 :          18732 :     root->plan_params = lappend(root->plan_params, pitem);
                                110                 :                : 
                                111                 :          18732 :     return pitem->paramId;
                                112                 :                : }
                                113                 :                : 
                                114                 :                : /*
                                115                 :                :  * Generate a Param node to replace the given Var,
                                116                 :                :  * which is expected to have varlevelsup > 0 (ie, it is not local).
                                117                 :                :  * Record the need for the Var in the proper upper-level root->plan_params.
                                118                 :                :  */
                                119                 :                : Param *
                                120                 :          22230 : replace_outer_var(PlannerInfo *root, Var *var)
                                121                 :                : {
                                122                 :                :     Param      *retval;
                                123                 :                :     int         i;
                                124                 :                : 
                                125   [ +  -  -  + ]:          22230 :     Assert(var->varlevelsup > 0 && var->varlevelsup < root->query_level);
                                126                 :                : 
                                127                 :                :     /* Find the Var in the appropriate plan_params, or add it if not present */
                                128                 :          22230 :     i = assign_param_for_var(root, var);
                                129                 :                : 
                                130                 :          22230 :     retval = makeNode(Param);
                                131                 :          22230 :     retval->paramkind = PARAM_EXEC;
                                132                 :          22230 :     retval->paramid = i;
                                133                 :          22230 :     retval->paramtype = var->vartype;
                                134                 :          22230 :     retval->paramtypmod = var->vartypmod;
                                135                 :          22230 :     retval->paramcollid = var->varcollid;
                                136                 :          22230 :     retval->location = var->location;
                                137                 :                : 
                                138                 :          22230 :     return retval;
                                139                 :                : }
                                140                 :                : 
                                141                 :                : /*
                                142                 :                :  * Select a PARAM_EXEC number to identify the given PlaceHolderVar as a
                                143                 :                :  * parameter for the current subquery.  (It might already have one.)
                                144                 :                :  * Record the need for the PHV in the proper upper-level root->plan_params.
                                145                 :                :  *
                                146                 :                :  * This is just like assign_param_for_var, except for PlaceHolderVars.
                                147                 :                :  */
                                148                 :                : static int
                                149                 :             21 : assign_param_for_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
                                150                 :                : {
                                151                 :                :     ListCell   *ppl;
                                152                 :                :     PlannerParamItem *pitem;
                                153                 :                :     Index       levelsup;
                                154                 :                : 
                                155                 :                :     /* Find the query level the PHV belongs to */
                                156         [ +  + ]:             42 :     for (levelsup = phv->phlevelsup; levelsup > 0; levelsup--)
                                157                 :             21 :         root = root->parent_root;
                                158                 :                : 
                                159                 :                :     /* If there's already a matching PlannerParamItem there, just use it */
                                160   [ +  +  +  +  :             51 :     foreach(ppl, root->plan_params)
                                              +  + ]
                                161                 :                :     {
                                162                 :             30 :         pitem = (PlannerParamItem *) lfirst(ppl);
                                163         [ -  + ]:             30 :         if (IsA(pitem->item, PlaceHolderVar))
                                164                 :                :         {
 1920 tgl@sss.pgh.pa.us         165                 :UBC           0 :             PlaceHolderVar *pphv = (PlaceHolderVar *) pitem->item;
                                166                 :                : 
                                167                 :                :             /* We assume comparing the PHIDs is sufficient */
                                168         [ #  # ]:              0 :             if (pphv->phid == phv->phid)
                                169                 :              0 :                 return pitem->paramId;
                                170                 :                :         }
                                171                 :                :     }
                                172                 :                : 
                                173                 :                :     /* Nope, so make a new one */
 1920 tgl@sss.pgh.pa.us         174                 :CBC          21 :     phv = copyObject(phv);
                                175                 :             21 :     IncrementVarSublevelsUp((Node *) phv, -((int) phv->phlevelsup), 0);
                                176         [ -  + ]:             21 :     Assert(phv->phlevelsup == 0);
                                177                 :                : 
                                178                 :             21 :     pitem = makeNode(PlannerParamItem);
                                179                 :             21 :     pitem->item = (Node *) phv;
                                180                 :             21 :     pitem->paramId = list_length(root->glob->paramExecTypes);
                                181                 :             21 :     root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes,
                                182                 :             21 :                                              exprType((Node *) phv->phexpr));
                                183                 :                : 
                                184                 :             21 :     root->plan_params = lappend(root->plan_params, pitem);
                                185                 :                : 
                                186                 :             21 :     return pitem->paramId;
                                187                 :                : }
                                188                 :                : 
                                189                 :                : /*
                                190                 :                :  * Generate a Param node to replace the given PlaceHolderVar,
                                191                 :                :  * which is expected to have phlevelsup > 0 (ie, it is not local).
                                192                 :                :  * Record the need for the PHV in the proper upper-level root->plan_params.
                                193                 :                :  *
                                194                 :                :  * This is just like replace_outer_var, except for PlaceHolderVars.
                                195                 :                :  */
                                196                 :                : Param *
                                197                 :             21 : replace_outer_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
                                198                 :                : {
                                199                 :                :     Param      *retval;
                                200                 :                :     int         i;
                                201                 :                : 
                                202   [ +  -  -  + ]:             21 :     Assert(phv->phlevelsup > 0 && phv->phlevelsup < root->query_level);
                                203                 :                : 
                                204                 :                :     /* Find the PHV in the appropriate plan_params, or add it if not present */
                                205                 :             21 :     i = assign_param_for_placeholdervar(root, phv);
                                206                 :                : 
                                207                 :             21 :     retval = makeNode(Param);
                                208                 :             21 :     retval->paramkind = PARAM_EXEC;
                                209                 :             21 :     retval->paramid = i;
                                210                 :             21 :     retval->paramtype = exprType((Node *) phv->phexpr);
                                211                 :             21 :     retval->paramtypmod = exprTypmod((Node *) phv->phexpr);
                                212                 :             21 :     retval->paramcollid = exprCollation((Node *) phv->phexpr);
                                213                 :             21 :     retval->location = -1;
                                214                 :                : 
                                215                 :             21 :     return retval;
                                216                 :                : }
                                217                 :                : 
                                218                 :                : /*
                                219                 :                :  * Generate a Param node to replace the given Aggref
                                220                 :                :  * which is expected to have agglevelsup > 0 (ie, it is not local).
                                221                 :                :  * Record the need for the Aggref in the proper upper-level root->plan_params.
                                222                 :                :  */
                                223                 :                : Param *
                                224                 :             26 : replace_outer_agg(PlannerInfo *root, Aggref *agg)
                                225                 :                : {
                                226                 :                :     Param      *retval;
                                227                 :                :     PlannerParamItem *pitem;
                                228                 :                :     Index       levelsup;
                                229                 :                : 
                                230   [ +  -  -  + ]:             26 :     Assert(agg->agglevelsup > 0 && agg->agglevelsup < root->query_level);
                                231                 :                : 
                                232                 :                :     /* Find the query level the Aggref belongs to */
                                233         [ +  + ]:             52 :     for (levelsup = agg->agglevelsup; levelsup > 0; levelsup--)
                                234                 :             26 :         root = root->parent_root;
                                235                 :                : 
                                236                 :                :     /*
                                237                 :                :      * It does not seem worthwhile to try to de-duplicate references to outer
                                238                 :                :      * aggs.  Just make a new slot every time.
                                239                 :                :      */
                                240                 :             26 :     agg = copyObject(agg);
                                241                 :             26 :     IncrementVarSublevelsUp((Node *) agg, -((int) agg->agglevelsup), 0);
                                242         [ -  + ]:             26 :     Assert(agg->agglevelsup == 0);
                                243                 :                : 
                                244                 :             26 :     pitem = makeNode(PlannerParamItem);
                                245                 :             26 :     pitem->item = (Node *) agg;
                                246                 :             26 :     pitem->paramId = list_length(root->glob->paramExecTypes);
                                247                 :             26 :     root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes,
                                248                 :                :                                              agg->aggtype);
                                249                 :                : 
                                250                 :             26 :     root->plan_params = lappend(root->plan_params, pitem);
                                251                 :                : 
                                252                 :             26 :     retval = makeNode(Param);
                                253                 :             26 :     retval->paramkind = PARAM_EXEC;
                                254                 :             26 :     retval->paramid = pitem->paramId;
                                255                 :             26 :     retval->paramtype = agg->aggtype;
                                256                 :             26 :     retval->paramtypmod = -1;
                                257                 :             26 :     retval->paramcollid = agg->aggcollid;
                                258                 :             26 :     retval->location = agg->location;
                                259                 :                : 
                                260                 :             26 :     return retval;
                                261                 :                : }
                                262                 :                : 
                                263                 :                : /*
                                264                 :                :  * Generate a Param node to replace the given GroupingFunc expression which is
                                265                 :                :  * expected to have agglevelsup > 0 (ie, it is not local).
                                266                 :                :  * Record the need for the GroupingFunc in the proper upper-level
                                267                 :                :  * root->plan_params.
                                268                 :                :  */
                                269                 :                : Param *
                                270                 :             32 : replace_outer_grouping(PlannerInfo *root, GroupingFunc *grp)
                                271                 :                : {
                                272                 :                :     Param      *retval;
                                273                 :                :     PlannerParamItem *pitem;
                                274                 :                :     Index       levelsup;
                                275                 :             32 :     Oid         ptype = exprType((Node *) grp);
                                276                 :                : 
                                277   [ +  -  -  + ]:             32 :     Assert(grp->agglevelsup > 0 && grp->agglevelsup < root->query_level);
                                278                 :                : 
                                279                 :                :     /* Find the query level the GroupingFunc belongs to */
                                280         [ +  + ]:             68 :     for (levelsup = grp->agglevelsup; levelsup > 0; levelsup--)
                                281                 :             36 :         root = root->parent_root;
                                282                 :                : 
                                283                 :                :     /*
                                284                 :                :      * It does not seem worthwhile to try to de-duplicate references to outer
                                285                 :                :      * aggs.  Just make a new slot every time.
                                286                 :                :      */
                                287                 :             32 :     grp = copyObject(grp);
                                288                 :             32 :     IncrementVarSublevelsUp((Node *) grp, -((int) grp->agglevelsup), 0);
                                289         [ -  + ]:             32 :     Assert(grp->agglevelsup == 0);
                                290                 :                : 
                                291                 :             32 :     pitem = makeNode(PlannerParamItem);
                                292                 :             32 :     pitem->item = (Node *) grp;
                                293                 :             32 :     pitem->paramId = list_length(root->glob->paramExecTypes);
                                294                 :             32 :     root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes,
                                295                 :                :                                              ptype);
                                296                 :                : 
                                297                 :             32 :     root->plan_params = lappend(root->plan_params, pitem);
                                298                 :                : 
                                299                 :             32 :     retval = makeNode(Param);
                                300                 :             32 :     retval->paramkind = PARAM_EXEC;
                                301                 :             32 :     retval->paramid = pitem->paramId;
                                302                 :             32 :     retval->paramtype = ptype;
                                303                 :             32 :     retval->paramtypmod = -1;
                                304                 :             32 :     retval->paramcollid = InvalidOid;
                                305                 :             32 :     retval->location = grp->location;
                                306                 :                : 
                                307                 :             32 :     return retval;
                                308                 :                : }
                                309                 :                : 
                                310                 :                : /*
                                311                 :                :  * Generate a Param node to replace the given MergeSupportFunc expression
                                312                 :                :  * which is expected to be in the RETURNING list of an upper-level MERGE
                                313                 :                :  * query.  Record the need for the MergeSupportFunc in the proper upper-level
                                314                 :                :  * root->plan_params.
                                315                 :                :  */
                                316                 :                : Param *
   28 dean.a.rasheed@gmail      317                 :GNC           3 : replace_outer_merge_support(PlannerInfo *root, MergeSupportFunc *msf)
                                318                 :                : {
                                319                 :                :     Param      *retval;
                                320                 :                :     PlannerParamItem *pitem;
                                321                 :              3 :     Oid         ptype = exprType((Node *) msf);
                                322                 :                : 
                                323         [ -  + ]:              3 :     Assert(root->parse->commandType != CMD_MERGE);
                                324                 :                : 
                                325                 :                :     /*
                                326                 :                :      * The parser should have ensured that the MergeSupportFunc is in the
                                327                 :                :      * RETURNING list of an upper-level MERGE query, so find that query.
                                328                 :                :      */
                                329                 :                :     do
                                330                 :                :     {
                                331                 :              3 :         root = root->parent_root;
                                332         [ -  + ]:              3 :         if (root == NULL)
   28 dean.a.rasheed@gmail      333         [ #  # ]:UNC           0 :             elog(ERROR, "MergeSupportFunc found outside MERGE");
   28 dean.a.rasheed@gmail      334         [ -  + ]:GNC           3 :     } while (root->parse->commandType != CMD_MERGE);
                                335                 :                : 
                                336                 :                :     /*
                                337                 :                :      * It does not seem worthwhile to try to de-duplicate references to outer
                                338                 :                :      * MergeSupportFunc expressions.  Just make a new slot every time.
                                339                 :                :      */
                                340                 :              3 :     msf = copyObject(msf);
                                341                 :                : 
                                342                 :              3 :     pitem = makeNode(PlannerParamItem);
                                343                 :              3 :     pitem->item = (Node *) msf;
                                344                 :              3 :     pitem->paramId = list_length(root->glob->paramExecTypes);
                                345                 :              3 :     root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes,
                                346                 :                :                                              ptype);
                                347                 :                : 
                                348                 :              3 :     root->plan_params = lappend(root->plan_params, pitem);
                                349                 :                : 
                                350                 :              3 :     retval = makeNode(Param);
                                351                 :              3 :     retval->paramkind = PARAM_EXEC;
                                352                 :              3 :     retval->paramid = pitem->paramId;
                                353                 :              3 :     retval->paramtype = ptype;
                                354                 :              3 :     retval->paramtypmod = -1;
                                355                 :              3 :     retval->paramcollid = InvalidOid;
                                356                 :              3 :     retval->location = msf->location;
                                357                 :                : 
                                358                 :              3 :     return retval;
                                359                 :                : }
                                360                 :                : 
                                361                 :                : /*
                                362                 :                :  * Generate a Param node to replace the given Var,
                                363                 :                :  * which is expected to come from some upper NestLoop plan node.
                                364                 :                :  * Record the need for the Var in root->curOuterParams.
                                365                 :                :  */
                                366                 :                : Param *
 1920 tgl@sss.pgh.pa.us         367                 :CBC       41306 : replace_nestloop_param_var(PlannerInfo *root, Var *var)
                                368                 :                : {
                                369                 :                :     Param      *param;
                                370                 :                :     NestLoopParam *nlp;
                                371                 :                :     ListCell   *lc;
                                372                 :                : 
                                373                 :                :     /* Is this Var already listed in root->curOuterParams? */
                                374   [ +  +  +  +  :          44716 :     foreach(lc, root->curOuterParams)
                                              +  + ]
                                375                 :                :     {
                                376                 :          22379 :         nlp = (NestLoopParam *) lfirst(lc);
                                377         [ +  + ]:          22379 :         if (equal(var, nlp->paramval))
                                378                 :                :         {
                                379                 :                :             /* Yes, so just make a Param referencing this NLP's slot */
                                380                 :          18969 :             param = makeNode(Param);
                                381                 :          18969 :             param->paramkind = PARAM_EXEC;
                                382                 :          18969 :             param->paramid = nlp->paramno;
                                383                 :          18969 :             param->paramtype = var->vartype;
                                384                 :          18969 :             param->paramtypmod = var->vartypmod;
                                385                 :          18969 :             param->paramcollid = var->varcollid;
                                386                 :          18969 :             param->location = var->location;
                                387                 :          18969 :             return param;
                                388                 :                :         }
                                389                 :                :     }
                                390                 :                : 
                                391                 :                :     /* No, so assign a PARAM_EXEC slot for a new NLP */
                                392                 :          22337 :     param = generate_new_exec_param(root,
                                393                 :                :                                     var->vartype,
                                394                 :                :                                     var->vartypmod,
                                395                 :                :                                     var->varcollid);
                                396                 :          22337 :     param->location = var->location;
                                397                 :                : 
                                398                 :                :     /* Add it to the list of required NLPs */
                                399                 :          22337 :     nlp = makeNode(NestLoopParam);
                                400                 :          22337 :     nlp->paramno = param->paramid;
                                401                 :          22337 :     nlp->paramval = copyObject(var);
                                402                 :          22337 :     root->curOuterParams = lappend(root->curOuterParams, nlp);
                                403                 :                : 
                                404                 :                :     /* And return the replacement Param */
                                405                 :          22337 :     return param;
                                406                 :                : }
                                407                 :                : 
                                408                 :                : /*
                                409                 :                :  * Generate a Param node to replace the given PlaceHolderVar,
                                410                 :                :  * which is expected to come from some upper NestLoop plan node.
                                411                 :                :  * Record the need for the PHV in root->curOuterParams.
                                412                 :                :  *
                                413                 :                :  * This is just like replace_nestloop_param_var, except for PlaceHolderVars.
                                414                 :                :  */
                                415                 :                : Param *
                                416                 :            123 : replace_nestloop_param_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
                                417                 :                : {
                                418                 :                :     Param      *param;
                                419                 :                :     NestLoopParam *nlp;
                                420                 :                :     ListCell   *lc;
                                421                 :                : 
                                422                 :                :     /* Is this PHV already listed in root->curOuterParams? */
                                423   [ +  +  +  +  :            162 :     foreach(lc, root->curOuterParams)
                                              +  + ]
                                424                 :                :     {
                                425                 :             90 :         nlp = (NestLoopParam *) lfirst(lc);
                                426         [ +  + ]:             90 :         if (equal(phv, nlp->paramval))
                                427                 :                :         {
                                428                 :                :             /* Yes, so just make a Param referencing this NLP's slot */
                                429                 :             51 :             param = makeNode(Param);
                                430                 :             51 :             param->paramkind = PARAM_EXEC;
                                431                 :             51 :             param->paramid = nlp->paramno;
                                432                 :             51 :             param->paramtype = exprType((Node *) phv->phexpr);
                                433                 :             51 :             param->paramtypmod = exprTypmod((Node *) phv->phexpr);
                                434                 :             51 :             param->paramcollid = exprCollation((Node *) phv->phexpr);
                                435                 :             51 :             param->location = -1;
                                436                 :             51 :             return param;
                                437                 :                :         }
                                438                 :                :     }
                                439                 :                : 
                                440                 :                :     /* No, so assign a PARAM_EXEC slot for a new NLP */
                                441                 :             72 :     param = generate_new_exec_param(root,
                                442                 :             72 :                                     exprType((Node *) phv->phexpr),
                                443                 :             72 :                                     exprTypmod((Node *) phv->phexpr),
                                444                 :             72 :                                     exprCollation((Node *) phv->phexpr));
                                445                 :                : 
                                446                 :                :     /* Add it to the list of required NLPs */
                                447                 :             72 :     nlp = makeNode(NestLoopParam);
                                448                 :             72 :     nlp->paramno = param->paramid;
                                449                 :             72 :     nlp->paramval = (Var *) copyObject(phv);
                                450                 :             72 :     root->curOuterParams = lappend(root->curOuterParams, nlp);
                                451                 :                : 
                                452                 :                :     /* And return the replacement Param */
                                453                 :             72 :     return param;
                                454                 :                : }
                                455                 :                : 
                                456                 :                : /*
                                457                 :                :  * process_subquery_nestloop_params
                                458                 :                :  *    Handle params of a parameterized subquery that need to be fed
                                459                 :                :  *    from an outer nestloop.
                                460                 :                :  *
                                461                 :                :  * Currently, that would be *all* params that a subquery in FROM has demanded
                                462                 :                :  * from the current query level, since they must be LATERAL references.
                                463                 :                :  *
                                464                 :                :  * subplan_params is a list of PlannerParamItems that we intend to pass to
                                465                 :                :  * a subquery-in-FROM.  (This was constructed in root->plan_params while
                                466                 :                :  * planning the subquery, but isn't there anymore when this is called.)
                                467                 :                :  *
                                468                 :                :  * The subplan's references to the outer variables are already represented
                                469                 :                :  * as PARAM_EXEC Params, since that conversion was done by the routines above
                                470                 :                :  * while planning the subquery.  So we need not modify the subplan or the
                                471                 :                :  * PlannerParamItems here.  What we do need to do is add entries to
                                472                 :                :  * root->curOuterParams to signal the parent nestloop plan node that it must
                                473                 :                :  * provide these values.  This differs from replace_nestloop_param_var in
                                474                 :                :  * that the PARAM_EXEC slots to use have already been determined.
                                475                 :                :  *
                                476                 :                :  * Note that we also use root->curOuterRels as an implicit parameter for
                                477                 :                :  * sanity checks.
                                478                 :                :  */
                                479                 :                : void
                                480                 :            221 : process_subquery_nestloop_params(PlannerInfo *root, List *subplan_params)
                                481                 :                : {
                                482                 :                :     ListCell   *lc;
                                483                 :                : 
                                484   [ +  +  +  +  :            487 :     foreach(lc, subplan_params)
                                              +  + ]
                                485                 :                :     {
 1000 peter@eisentraut.org      486                 :            266 :         PlannerParamItem *pitem = lfirst_node(PlannerParamItem, lc);
                                487                 :                : 
 1920 tgl@sss.pgh.pa.us         488         [ +  + ]:            266 :         if (IsA(pitem->item, Var))
                                489                 :                :         {
                                490                 :            251 :             Var        *var = (Var *) pitem->item;
                                491                 :                :             NestLoopParam *nlp;
                                492                 :                :             ListCell   *lc2;
                                493                 :                : 
                                494                 :                :             /* If not from a nestloop outer rel, complain */
                                495         [ -  + ]:            251 :             if (!bms_is_member(var->varno, root->curOuterRels))
 1920 tgl@sss.pgh.pa.us         496         [ #  # ]:UBC           0 :                 elog(ERROR, "non-LATERAL parameter required by subquery");
                                497                 :                : 
                                498                 :                :             /* Is this param already listed in root->curOuterParams? */
  557 drowley@postgresql.o      499   [ +  +  +  +  :CBC         341 :             foreach(lc2, root->curOuterParams)
                                              +  + ]
                                500                 :                :             {
                                501                 :             90 :                 nlp = (NestLoopParam *) lfirst(lc2);
 1920 tgl@sss.pgh.pa.us         502         [ -  + ]:             90 :                 if (nlp->paramno == pitem->paramId)
                                503                 :                :                 {
  299 tgl@sss.pgh.pa.us         504         [ #  # ]:UBC           0 :                     Assert(equal(var, nlp->paramval));
                                505                 :                :                     /* Present, so nothing to do */
 1920                           506                 :              0 :                     break;
                                507                 :                :                 }
                                508                 :                :             }
  557 drowley@postgresql.o      509         [ +  - ]:CBC         251 :             if (lc2 == NULL)
                                510                 :                :             {
                                511                 :                :                 /* No, so add it */
 1920 tgl@sss.pgh.pa.us         512                 :            251 :                 nlp = makeNode(NestLoopParam);
                                513                 :            251 :                 nlp->paramno = pitem->paramId;
  299                           514                 :            251 :                 nlp->paramval = copyObject(var);
 1920                           515                 :            251 :                 root->curOuterParams = lappend(root->curOuterParams, nlp);
                                516                 :                :             }
                                517                 :                :         }
                                518         [ +  - ]:             15 :         else if (IsA(pitem->item, PlaceHolderVar))
                                519                 :                :         {
                                520                 :             15 :             PlaceHolderVar *phv = (PlaceHolderVar *) pitem->item;
                                521                 :                :             NestLoopParam *nlp;
                                522                 :                :             ListCell   *lc2;
                                523                 :                : 
                                524                 :                :             /* If not from a nestloop outer rel, complain */
  606                           525         [ -  + ]:             15 :             if (!bms_is_subset(find_placeholder_info(root, phv)->ph_eval_at,
 1920                           526                 :             15 :                                root->curOuterRels))
 1920 tgl@sss.pgh.pa.us         527         [ #  # ]:UBC           0 :                 elog(ERROR, "non-LATERAL parameter required by subquery");
                                528                 :                : 
                                529                 :                :             /* Is this param already listed in root->curOuterParams? */
  557 drowley@postgresql.o      530   [ +  +  +  +  :CBC          45 :             foreach(lc2, root->curOuterParams)
                                              +  + ]
                                531                 :                :             {
                                532                 :             30 :                 nlp = (NestLoopParam *) lfirst(lc2);
 1920 tgl@sss.pgh.pa.us         533         [ -  + ]:             30 :                 if (nlp->paramno == pitem->paramId)
                                534                 :                :                 {
  299 tgl@sss.pgh.pa.us         535         [ #  # ]:UBC           0 :                     Assert(equal(phv, nlp->paramval));
                                536                 :                :                     /* Present, so nothing to do */
 1920                           537                 :              0 :                     break;
                                538                 :                :                 }
                                539                 :                :             }
  557 drowley@postgresql.o      540         [ +  - ]:CBC          15 :             if (lc2 == NULL)
                                541                 :                :             {
                                542                 :                :                 /* No, so add it */
 1920 tgl@sss.pgh.pa.us         543                 :             15 :                 nlp = makeNode(NestLoopParam);
                                544                 :             15 :                 nlp->paramno = pitem->paramId;
  299                           545                 :             15 :                 nlp->paramval = (Var *) copyObject(phv);
 1920                           546                 :             15 :                 root->curOuterParams = lappend(root->curOuterParams, nlp);
                                547                 :                :             }
                                548                 :                :         }
                                549                 :                :         else
 1920 tgl@sss.pgh.pa.us         550         [ #  # ]:UBC           0 :             elog(ERROR, "unexpected type of subquery parameter");
                                551                 :                :     }
 1920 tgl@sss.pgh.pa.us         552                 :CBC         221 : }
                                553                 :                : 
                                554                 :                : /*
                                555                 :                :  * Identify any NestLoopParams that should be supplied by a NestLoop plan
                                556                 :                :  * node with the specified lefthand rels.  Remove them from the active
                                557                 :                :  * root->curOuterParams list and return them as the result list.
                                558                 :                :  *
                                559                 :                :  * XXX Here we also hack up the returned Vars and PHVs so that they do not
                                560                 :                :  * contain nullingrel sets exceeding what is available from the outer side.
                                561                 :                :  * This is needed if we have applied outer join identity 3,
                                562                 :                :  *      (A leftjoin B on (Pab)) leftjoin C on (Pb*c)
                                563                 :                :  *      = A leftjoin (B leftjoin C on (Pbc)) on (Pab)
                                564                 :                :  * and C contains lateral references to B.  It's still safe to apply the
                                565                 :                :  * identity, but the parser will have created those references in the form
                                566                 :                :  * "b*" (i.e., with varnullingrels listing the A/B join), while what we will
                                567                 :                :  * have available from the nestloop's outer side is just "b".  We deal with
                                568                 :                :  * that here by stripping the nullingrels down to what is available from the
                                569                 :                :  * outer side according to leftrelids.
                                570                 :                :  *
                                571                 :                :  * That fixes matters for the case of forward application of identity 3.
                                572                 :                :  * If the identity was applied in the reverse direction, we will have
                                573                 :                :  * parameter Vars containing too few nullingrel bits rather than too many.
                                574                 :                :  * Currently, that causes no problems because setrefs.c applies only a
                                575                 :                :  * subset check to nullingrels in NestLoopParams, but we'd have to work
                                576                 :                :  * harder if we ever want to tighten that check.  This is all pretty annoying
                                577                 :                :  * because it greatly weakens setrefs.c's cross-check, but the alternative
                                578                 :                :  * seems to be to generate multiple versions of each laterally-parameterized
                                579                 :                :  * subquery, which'd be unduly expensive.
                                580                 :                :  */
                                581                 :                : List *
                                582                 :          39871 : identify_current_nestloop_params(PlannerInfo *root, Relids leftrelids)
                                583                 :                : {
                                584                 :                :     List       *result;
                                585                 :                :     ListCell   *cell;
                                586                 :                : 
                                587                 :          39871 :     result = NIL;
 1735                           588   [ +  +  +  +  :          63032 :     foreach(cell, root->curOuterParams)
                                              +  + ]
                                589                 :                :     {
 1920                           590                 :          23161 :         NestLoopParam *nlp = (NestLoopParam *) lfirst(cell);
                                591                 :                : 
                                592                 :                :         /*
                                593                 :                :          * We are looking for Vars and PHVs that can be supplied by the
                                594                 :                :          * lefthand rels.  When we find one, it's okay to modify it in-place
                                595                 :                :          * because all the routines above make a fresh copy to put into
                                596                 :                :          * curOuterParams.
                                597                 :                :          */
                                598   [ +  +  +  + ]:          46235 :         if (IsA(nlp->paramval, Var) &&
                                599                 :          23074 :             bms_is_member(nlp->paramval->varno, leftrelids))
                                600                 :          22588 :         {
  299                           601                 :          22588 :             Var        *var = (Var *) nlp->paramval;
                                602                 :                : 
 1735                           603                 :          22588 :             root->curOuterParams = foreach_delete_current(root->curOuterParams,
                                604                 :                :                                                           cell);
  299                           605                 :          22588 :             var->varnullingrels = bms_intersect(var->varnullingrels,
                                606                 :                :                                                 leftrelids);
 1920                           607                 :          22588 :             result = lappend(result, nlp);
                                608                 :                :         }
                                609   [ +  +  +  - ]:            660 :         else if (IsA(nlp->paramval, PlaceHolderVar) &&
                                610                 :            174 :                  bms_is_subset(find_placeholder_info(root,
  606                           611                 :             87 :                                                      (PlaceHolderVar *) nlp->paramval)->ph_eval_at,
                                612                 :                :                                leftrelids))
                                613                 :                :         {
  299                           614                 :             87 :             PlaceHolderVar *phv = (PlaceHolderVar *) nlp->paramval;
                                615                 :                : 
 1735                           616                 :             87 :             root->curOuterParams = foreach_delete_current(root->curOuterParams,
                                617                 :                :                                                           cell);
  299                           618                 :             87 :             phv->phnullingrels = bms_intersect(phv->phnullingrels,
                                619                 :                :                                                leftrelids);
 1920                           620                 :             87 :             result = lappend(result, nlp);
                                621                 :                :         }
                                622                 :                :     }
                                623                 :          39871 :     return result;
                                624                 :                : }
                                625                 :                : 
                                626                 :                : /*
                                627                 :                :  * Generate a new Param node that will not conflict with any other.
                                628                 :                :  *
                                629                 :                :  * This is used to create Params representing subplan outputs or
                                630                 :                :  * NestLoop parameters.
                                631                 :                :  *
                                632                 :                :  * We don't need to build a PlannerParamItem for such a Param, but we do
                                633                 :                :  * need to make sure we record the type in paramExecTypes (otherwise,
                                634                 :                :  * there won't be a slot allocated for it).
                                635                 :                :  */
                                636                 :                : Param *
                                637                 :          29052 : generate_new_exec_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod,
                                638                 :                :                         Oid paramcollation)
                                639                 :                : {
                                640                 :                :     Param      *retval;
                                641                 :                : 
                                642                 :          29052 :     retval = makeNode(Param);
                                643                 :          29052 :     retval->paramkind = PARAM_EXEC;
                                644                 :          29052 :     retval->paramid = list_length(root->glob->paramExecTypes);
                                645                 :          29052 :     root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes,
                                646                 :                :                                              paramtype);
                                647                 :          29052 :     retval->paramtype = paramtype;
                                648                 :          29052 :     retval->paramtypmod = paramtypmod;
                                649                 :          29052 :     retval->paramcollid = paramcollation;
                                650                 :          29052 :     retval->location = -1;
                                651                 :                : 
                                652                 :          29052 :     return retval;
                                653                 :                : }
                                654                 :                : 
                                655                 :                : /*
                                656                 :                :  * Assign a (nonnegative) PARAM_EXEC ID for a special parameter (one that
                                657                 :                :  * is not actually used to carry a value at runtime).  Such parameters are
                                658                 :                :  * used for special runtime signaling purposes, such as connecting a
                                659                 :                :  * recursive union node to its worktable scan node or forcing plan
                                660                 :                :  * re-evaluation within the EvalPlanQual mechanism.  No actual Param node
                                661                 :                :  * exists with this ID, however.
                                662                 :                :  */
                                663                 :                : int
                                664                 :          49829 : assign_special_exec_param(PlannerInfo *root)
                                665                 :                : {
                                666                 :          49829 :     int         paramId = list_length(root->glob->paramExecTypes);
                                667                 :                : 
                                668                 :          49829 :     root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes,
                                669                 :                :                                              InvalidOid);
                                670                 :          49829 :     return paramId;
                                671                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622