LCOV - differential code coverage report
Current view: top level - src/backend/optimizer/prep - preptlist.c (source / functions) Coverage Total Hit UNC UBC GNC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 89.0 % 145 129 16 10 119
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 4 4 1 3
Baseline: 16@8cea358b128 Branches: 86.3 % 124 107 1 16 11 96
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: 100.0 % 10 10 10
(240..) days: 88.1 % 135 119 16 119
Function coverage date bins:
(240..) days: 100.0 % 4 4 1 3
Branch coverage date bins:
[..60] days: 91.7 % 12 11 1 11
(240..) days: 85.7 % 112 96 16 96

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * preptlist.c
                                  4                 :                :  *    Routines to preprocess the parse tree target list
                                  5                 :                :  *
                                  6                 :                :  * For an INSERT, the targetlist must contain an entry for each attribute of
                                  7                 :                :  * the target relation in the correct order.
                                  8                 :                :  *
                                  9                 :                :  * For an UPDATE, the targetlist just contains the expressions for the new
                                 10                 :                :  * column values.
                                 11                 :                :  *
                                 12                 :                :  * For UPDATE and DELETE queries, the targetlist must also contain "junk"
                                 13                 :                :  * tlist entries needed to allow the executor to identify the rows to be
                                 14                 :                :  * updated or deleted; for example, the ctid of a heap row.  (The planner
                                 15                 :                :  * adds these; they're not in what we receive from the parser/rewriter.)
                                 16                 :                :  *
                                 17                 :                :  * For all query types, there can be additional junk tlist entries, such as
                                 18                 :                :  * sort keys, Vars needed for a RETURNING list, and row ID information needed
                                 19                 :                :  * for SELECT FOR UPDATE locking and/or EvalPlanQual checking.
                                 20                 :                :  *
                                 21                 :                :  * The query rewrite phase also does preprocessing of the targetlist (see
                                 22                 :                :  * rewriteTargetListIU).  The division of labor between here and there is
                                 23                 :                :  * partially historical, but it's not entirely arbitrary.  The stuff done
                                 24                 :                :  * here is closely connected to physical access to tables, whereas the
                                 25                 :                :  * rewriter's work is more concerned with SQL semantics.
                                 26                 :                :  *
                                 27                 :                :  *
                                 28                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                 29                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                 30                 :                :  *
                                 31                 :                :  * IDENTIFICATION
                                 32                 :                :  *    src/backend/optimizer/prep/preptlist.c
                                 33                 :                :  *
                                 34                 :                :  *-------------------------------------------------------------------------
                                 35                 :                :  */
                                 36                 :                : 
                                 37                 :                : #include "postgres.h"
                                 38                 :                : 
                                 39                 :                : #include "access/table.h"
                                 40                 :                : #include "nodes/makefuncs.h"
                                 41                 :                : #include "optimizer/appendinfo.h"
                                 42                 :                : #include "optimizer/optimizer.h"
                                 43                 :                : #include "optimizer/prep.h"
                                 44                 :                : #include "optimizer/tlist.h"
                                 45                 :                : #include "parser/parse_coerce.h"
                                 46                 :                : #include "parser/parsetree.h"
                                 47                 :                : #include "utils/rel.h"
                                 48                 :                : 
                                 49                 :                : static List *expand_insert_targetlist(List *tlist, Relation rel);
                                 50                 :                : 
                                 51                 :                : 
                                 52                 :                : /*
                                 53                 :                :  * preprocess_targetlist
                                 54                 :                :  *    Driver for preprocessing the parse tree targetlist.
                                 55                 :                :  *
                                 56                 :                :  * The preprocessed targetlist is returned in root->processed_tlist.
                                 57                 :                :  * Also, if this is an UPDATE, we return a list of target column numbers
                                 58                 :                :  * in root->update_colnos.  (Resnos in processed_tlist will be consecutive,
                                 59                 :                :  * so do not look at that to find out which columns are targets!)
                                 60                 :                :  */
                                 61                 :                : void
 2330 tgl@sss.pgh.pa.us          62                 :CBC      243260 : preprocess_targetlist(PlannerInfo *root)
                                 63                 :                : {
 6756 bruce@momjian.us           64                 :         243260 :     Query      *parse = root->parse;
                                 65                 :         243260 :     int         result_relation = parse->resultRelation;
                                 66                 :         243260 :     List       *range_table = parse->rtable;
                                 67                 :         243260 :     CmdType     command_type = parse->commandType;
 2330 tgl@sss.pgh.pa.us          68                 :         243260 :     RangeTblEntry *target_rte = NULL;
                                 69                 :         243260 :     Relation    target_relation = NULL;
                                 70                 :                :     List       *tlist;
                                 71                 :                :     ListCell   *lc;
                                 72                 :                : 
                                 73                 :                :     /*
                                 74                 :                :      * If there is a result relation, open it so we can look for missing
                                 75                 :                :      * columns and so on.  We assume that previous code already acquired at
                                 76                 :                :      * least AccessShareLock on the relation, so we need no lock here.
                                 77                 :                :      */
 8592                            78         [ +  + ]:         243260 :     if (result_relation)
                                 79                 :                :     {
 2330                            80                 :          43743 :         target_rte = rt_fetch(result_relation, range_table);
                                 81                 :                : 
                                 82                 :                :         /*
                                 83                 :                :          * Sanity check: it'd better be a real relation not, say, a subquery.
                                 84                 :                :          * Else parser or rewriter messed up.
                                 85                 :                :          */
                                 86         [ -  + ]:          43743 :         if (target_rte->rtekind != RTE_RELATION)
 2330 tgl@sss.pgh.pa.us          87         [ #  # ]:UBC           0 :             elog(ERROR, "result relation must be a regular relation");
                                 88                 :                : 
 1910 andres@anarazel.de         89                 :CBC       43743 :         target_relation = table_open(target_rte->relid, NoLock);
                                 90                 :                :     }
                                 91                 :                :     else
 2330 tgl@sss.pgh.pa.us          92         [ -  + ]:         199517 :         Assert(command_type == CMD_SELECT);
                                 93                 :                : 
                                 94                 :                :     /*
                                 95                 :                :      * In an INSERT, the executor expects the targetlist to match the exact
                                 96                 :                :      * order of the target table's attributes, including entries for
                                 97                 :                :      * attributes not mentioned in the source query.
                                 98                 :                :      *
                                 99                 :                :      * In an UPDATE, we don't rearrange the tlist order, but we need to make a
                                100                 :                :      * separate list of the target attribute numbers, in tlist order, and then
                                101                 :                :      * renumber the processed_tlist entries to be consecutive.
                                102                 :                :      */
                                103                 :         243260 :     tlist = parse->targetList;
 1110                           104         [ +  + ]:         243260 :     if (command_type == CMD_INSERT)
 1070                           105                 :          34097 :         tlist = expand_insert_targetlist(tlist, target_relation);
 1110                           106         [ +  + ]:         209163 :     else if (command_type == CMD_UPDATE)
 1070                           107                 :           6677 :         root->update_colnos = extract_update_targetlist_colnos(tlist);
                                108                 :                : 
                                109                 :                :     /*
                                110                 :                :      * For non-inherited UPDATE/DELETE/MERGE, register any junk column(s)
                                111                 :                :      * needed to allow the executor to identify the rows to be updated or
                                112                 :                :      * deleted.  In the inheritance case, we do nothing now, leaving this to
                                113                 :                :      * be dealt with when expand_inherited_rtentry() makes the leaf target
                                114                 :                :      * relations.  (But there might not be any leaf target relations, in which
                                115                 :                :      * case we must do this in distribute_row_identity_vars().)
                                116                 :                :      */
  733 alvherre@alvh.no-ip.      117   [ +  +  +  +  :         243260 :     if ((command_type == CMD_UPDATE || command_type == CMD_DELETE ||
                                              +  + ]
                                118                 :           9646 :          command_type == CMD_MERGE) &&
 1110 tgl@sss.pgh.pa.us         119         [ +  + ]:           9646 :         !target_rte->inh)
                                120                 :                :     {
                                121                 :                :         /* row-identity logic expects to add stuff to processed_tlist */
                                122                 :           8374 :         root->processed_tlist = tlist;
                                123                 :           8374 :         add_row_identity_columns(root, result_relation,
                                124                 :                :                                  target_rte, target_relation);
                                125                 :           8374 :         tlist = root->processed_tlist;
                                126                 :                :     }
                                127                 :                : 
                                128                 :                :     /*
                                129                 :                :      * For MERGE we also need to handle the target list for each INSERT and
                                130                 :                :      * UPDATE action separately.  In addition, we examine the qual of each
                                131                 :                :      * action and add any Vars there (other than those of the target rel) to
                                132                 :                :      * the subplan targetlist.
                                133                 :                :      */
  748 alvherre@alvh.no-ip.      134         [ +  + ]:         243260 :     if (command_type == CMD_MERGE)
                                135                 :                :     {
                                136                 :                :         ListCell   *l;
                                137                 :                :         List       *vars;
                                138                 :                : 
                                139                 :                :         /*
                                140                 :                :          * For MERGE, handle targetlist of each MergeAction separately. Give
                                141                 :                :          * the same treatment to MergeAction->targetList as we would have
                                142                 :                :          * given to a regular INSERT.  For UPDATE, collect the column numbers
                                143                 :                :          * being modified.
                                144                 :                :          */
                                145   [ +  -  +  +  :           2155 :         foreach(l, parse->mergeActionList)
                                              +  + ]
                                146                 :                :         {
                                147                 :           1303 :             MergeAction *action = (MergeAction *) lfirst(l);
                                148                 :                :             ListCell   *l2;
                                149                 :                : 
                                150         [ +  + ]:           1303 :             if (action->commandType == CMD_INSERT)
                                151                 :            413 :                 action->targetList = expand_insert_targetlist(action->targetList,
                                152                 :                :                                                               target_relation);
                                153         [ +  + ]:            890 :             else if (action->commandType == CMD_UPDATE)
                                154                 :            667 :                 action->updateColnos =
                                155                 :            667 :                     extract_update_targetlist_colnos(action->targetList);
                                156                 :                : 
                                157                 :                :             /*
                                158                 :                :              * Add resjunk entries for any Vars and PlaceHolderVars used in
                                159                 :                :              * each action's targetlist and WHEN condition that belong to
                                160                 :                :              * relations other than the target.  We don't expect to see any
                                161                 :                :              * aggregates or window functions here.
                                162                 :                :              */
  733                           163                 :           1303 :             vars = pull_var_clause((Node *)
                                164                 :           1303 :                                    list_concat_copy((List *) action->qual,
                                165                 :           1303 :                                                     action->targetList),
                                166                 :                :                                    PVC_INCLUDE_PLACEHOLDERS);
                                167   [ +  +  +  +  :           2976 :             foreach(l2, vars)
                                              +  + ]
                                168                 :                :             {
                                169                 :           1673 :                 Var        *var = (Var *) lfirst(l2);
                                170                 :                :                 TargetEntry *tle;
                                171                 :                : 
                                172   [ +  +  +  + ]:           1673 :                 if (IsA(var, Var) && var->varno == result_relation)
                                173                 :            831 :                     continue;   /* don't need it */
                                174                 :                : 
                                175         [ +  + ]:            842 :                 if (tlist_member((Expr *) var, tlist))
                                176                 :            226 :                     continue;   /* already got it */
                                177                 :                : 
                                178                 :            616 :                 tle = makeTargetEntry((Expr *) var,
                                179                 :            616 :                                       list_length(tlist) + 1,
                                180                 :                :                                       NULL, true);
                                181                 :            616 :                 tlist = lappend(tlist, tle);
                                182                 :                :             }
                                183                 :           1303 :             list_free(vars);
                                184                 :                :         }
                                185                 :                : 
                                186                 :                :         /*
                                187                 :                :          * Add resjunk entries for any Vars and PlaceHolderVars used in the
                                188                 :                :          * join condition that belong to relations other than the target.  We
                                189                 :                :          * don't expect to see any aggregates or window functions here.
                                190                 :                :          */
   15 dean.a.rasheed@gmail      191                 :GNC         852 :         vars = pull_var_clause(parse->mergeJoinCondition,
                                192                 :                :                                PVC_INCLUDE_PLACEHOLDERS);
                                193   [ +  +  +  +  :            966 :         foreach(l, vars)
                                              +  + ]
                                194                 :                :         {
                                195                 :            114 :             Var        *var = (Var *) lfirst(l);
                                196                 :                :             TargetEntry *tle;
                                197                 :                : 
                                198   [ +  -  +  + ]:            114 :             if (IsA(var, Var) && var->varno == result_relation)
                                199                 :             60 :                 continue;       /* don't need it */
                                200                 :                : 
                                201         [ +  + ]:             54 :             if (tlist_member((Expr *) var, tlist))
                                202                 :             42 :                 continue;       /* already got it */
                                203                 :                : 
                                204                 :             12 :             tle = makeTargetEntry((Expr *) var,
                                205                 :             12 :                                   list_length(tlist) + 1,
                                206                 :                :                                   NULL, true);
                                207                 :             12 :             tlist = lappend(tlist, tle);
                                208                 :                :         }
                                209                 :                :     }
                                210                 :                : 
                                211                 :                :     /*
                                212                 :                :      * Add necessary junk columns for rowmarked rels.  These values are needed
                                213                 :                :      * for locking of rels selected FOR UPDATE/SHARE, and to do EvalPlanQual
                                214                 :                :      * rechecking.  See comments for PlanRowMark in plannodes.h.  If you
                                215                 :                :      * change this stanza, see also expand_inherited_rtentry(), which has to
                                216                 :                :      * be able to add on junk columns equivalent to these.
                                217                 :                :      *
                                218                 :                :      * (Someday it might be useful to fold these resjunk columns into the
                                219                 :                :      * row-identity-column management used for UPDATE/DELETE.  Today is not
                                220                 :                :      * that day, however.  One notable issue is that it seems important that
                                221                 :                :      * the whole-row Vars made here use the real table rowtype, not RECORD, so
                                222                 :                :      * that conversion to/from child relations' rowtypes will happen.  Also,
                                223                 :                :      * since these entries don't potentially bloat with more and more child
                                224                 :                :      * relations, there's not really much need for column sharing.)
                                225                 :                :      */
 5284 tgl@sss.pgh.pa.us         226   [ +  +  +  +  :CBC      248419 :     foreach(lc, root->rowMarks)
                                              +  + ]
                                227                 :                :     {
                                228                 :           5159 :         PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
                                229                 :                :         Var        *var;
                                230                 :                :         char        resname[32];
                                231                 :                :         TargetEntry *tle;
                                232                 :                : 
                                233                 :                :         /* child rels use the same junk attrs as their parents */
                                234         [ -  + ]:           5159 :         if (rc->rti != rc->prti)
 5284 tgl@sss.pgh.pa.us         235                 :UBC           0 :             continue;
                                236                 :                : 
 3318 tgl@sss.pgh.pa.us         237         [ +  + ]:CBC        5159 :         if (rc->allMarkTypes & ~(1 << ROW_MARK_COPY))
                                238                 :                :         {
                                239                 :                :             /* Need to fetch TID */
 6559                           240                 :           4840 :             var = makeVar(rc->rti,
                                241                 :                :                           SelfItemPointerAttributeNumber,
                                242                 :                :                           TIDOID,
                                243                 :                :                           -1,
                                244                 :                :                           InvalidOid,
                                245                 :                :                           0);
 4813                           246                 :           4840 :             snprintf(resname, sizeof(resname), "ctid%u", rc->rowmarkId);
 6948                           247                 :           4840 :             tle = makeTargetEntry((Expr *) var,
                                248                 :           4840 :                                   list_length(tlist) + 1,
                                249                 :                :                                   pstrdup(resname),
                                250                 :                :                                   true);
                                251                 :           4840 :             tlist = lappend(tlist, tle);
                                252                 :                :         }
 3318                           253         [ +  + ]:           5159 :         if (rc->allMarkTypes & (1 << ROW_MARK_COPY))
                                254                 :                :         {
                                255                 :                :             /* Need the whole row as a junk var */
 4926                           256                 :            319 :             var = makeWholeRowVar(rt_fetch(rc->rti, range_table),
                                257                 :            319 :                                   rc->rti,
                                258                 :                :                                   0,
                                259                 :                :                                   false);
 4813                           260                 :            319 :             snprintf(resname, sizeof(resname), "wholerow%u", rc->rowmarkId);
 5284                           261                 :            319 :             tle = makeTargetEntry((Expr *) var,
                                262                 :            319 :                                   list_length(tlist) + 1,
                                263                 :                :                                   pstrdup(resname),
                                264                 :                :                                   true);
                                265                 :            319 :             tlist = lappend(tlist, tle);
                                266                 :                :         }
                                267                 :                : 
                                268                 :                :         /* If parent of inheritance tree, always fetch the tableoid too. */
 3280 sfrost@snowman.net        269         [ -  + ]:           5159 :         if (rc->isParent)
                                270                 :                :         {
 3280 sfrost@snowman.net        271                 :UBC           0 :             var = makeVar(rc->rti,
                                272                 :                :                           TableOidAttributeNumber,
                                273                 :                :                           OIDOID,
                                274                 :                :                           -1,
                                275                 :                :                           InvalidOid,
                                276                 :                :                           0);
                                277                 :              0 :             snprintf(resname, sizeof(resname), "tableoid%u", rc->rowmarkId);
                                278                 :              0 :             tle = makeTargetEntry((Expr *) var,
                                279                 :              0 :                                   list_length(tlist) + 1,
                                280                 :                :                                   pstrdup(resname),
                                281                 :                :                                   true);
                                282                 :              0 :             tlist = lappend(tlist, tle);
                                283                 :                :         }
                                284                 :                :     }
                                285                 :                : 
                                286                 :                :     /*
                                287                 :                :      * If the query has a RETURNING list, add resjunk entries for any Vars
                                288                 :                :      * used in RETURNING that belong to other relations.  We need to do this
                                289                 :                :      * to make these Vars available for the RETURNING calculation.  Vars that
                                290                 :                :      * belong to the result rel don't need to be added, because they will be
                                291                 :                :      * made to refer to the actual heap tuple.
                                292                 :                :      */
 6455 tgl@sss.pgh.pa.us         293   [ +  +  +  + ]:CBC      243260 :     if (parse->returningList && list_length(parse->rtable) > 1)
                                294                 :                :     {
                                295                 :                :         List       *vars;
                                296                 :                :         ListCell   *l;
                                297                 :                : 
 5474                           298                 :            751 :         vars = pull_var_clause((Node *) parse->returningList,
                                299                 :                :                                PVC_RECURSE_AGGREGATES |
                                300                 :                :                                PVC_RECURSE_WINDOWFUNCS |
                                301                 :                :                                PVC_INCLUDE_PLACEHOLDERS);
 6455                           302   [ +  +  +  +  :           2783 :         foreach(l, vars)
                                              +  + ]
                                303                 :                :         {
                                304                 :           2032 :             Var        *var = (Var *) lfirst(l);
                                305                 :                :             TargetEntry *tle;
                                306                 :                : 
 5654                           307         [ +  - ]:           2032 :             if (IsA(var, Var) &&
                                308         [ +  + ]:           2032 :                 var->varno == result_relation)
 6455                           309                 :           1800 :                 continue;       /* don't need it */
                                310                 :                : 
 2593 peter_e@gmx.net           311         [ +  + ]:            232 :             if (tlist_member((Expr *) var, tlist))
 6455 tgl@sss.pgh.pa.us         312                 :             71 :                 continue;       /* already got it */
                                313                 :                : 
                                314                 :            161 :             tle = makeTargetEntry((Expr *) var,
                                315                 :            161 :                                   list_length(tlist) + 1,
                                316                 :                :                                   NULL,
                                317                 :                :                                   true);
                                318                 :                : 
                                319                 :            161 :             tlist = lappend(tlist, tle);
                                320                 :                :         }
                                321                 :            751 :         list_free(vars);
                                322                 :                :     }
                                323                 :                : 
 1110                           324                 :         243260 :     root->processed_tlist = tlist;
                                325                 :                : 
 2330                           326         [ +  + ]:         243260 :     if (target_relation)
 1910 andres@anarazel.de        327                 :          43743 :         table_close(target_relation, NoLock);
 1110 tgl@sss.pgh.pa.us         328                 :         243260 : }
                                329                 :                : 
                                330                 :                : /*
                                331                 :                :  * extract_update_targetlist_colnos
                                332                 :                :  *      Extract a list of the target-table column numbers that
                                333                 :                :  *      an UPDATE's targetlist wants to assign to, then renumber.
                                334                 :                :  *
                                335                 :                :  * The convention in the parser and rewriter is that the resnos in an
                                336                 :                :  * UPDATE's non-resjunk TLE entries are the target column numbers
                                337                 :                :  * to assign to.  Here, we extract that info into a separate list, and
                                338                 :                :  * then convert the tlist to the sequential-numbering convention that's
                                339                 :                :  * used by all other query types.
                                340                 :                :  *
                                341                 :                :  * This is also applied to the tlist associated with INSERT ... ON CONFLICT
                                342                 :                :  * ... UPDATE, although not till much later in planning.
                                343                 :                :  */
                                344                 :                : List *
 1070                           345                 :           8059 : extract_update_targetlist_colnos(List *tlist)
                                346                 :                : {
 1110                           347                 :           8059 :     List       *update_colnos = NIL;
                                348                 :           8059 :     AttrNumber  nextresno = 1;
                                349                 :                :     ListCell   *lc;
                                350                 :                : 
                                351   [ +  +  +  +  :          18086 :     foreach(lc, tlist)
                                              +  + ]
                                352                 :                :     {
                                353                 :          10027 :         TargetEntry *tle = (TargetEntry *) lfirst(lc);
                                354                 :                : 
                                355         [ +  + ]:          10027 :         if (!tle->resjunk)
                                356                 :           9892 :             update_colnos = lappend_int(update_colnos, tle->resno);
                                357                 :          10027 :         tle->resno = nextresno++;
                                358                 :                :     }
                                359                 :           8059 :     return update_colnos;
                                360                 :                : }
                                361                 :                : 
                                362                 :                : 
                                363                 :                : /*****************************************************************************
                                364                 :                :  *
                                365                 :                :  *      TARGETLIST EXPANSION
                                366                 :                :  *
                                367                 :                :  *****************************************************************************/
                                368                 :                : 
                                369                 :                : /*
                                370                 :                :  * expand_insert_targetlist
                                371                 :                :  *    Given a target list as generated by the parser and a result relation,
                                372                 :                :  *    add targetlist entries for any missing attributes, and ensure the
                                373                 :                :  *    non-junk attributes appear in proper field order.
                                374                 :                :  *
                                375                 :                :  * Once upon a time we also did more or less this with UPDATE targetlists,
                                376                 :                :  * but now this code is only applied to INSERT targetlists.
                                377                 :                :  */
                                378                 :                : static List *
 1070                           379                 :          34510 : expand_insert_targetlist(List *tlist, Relation rel)
                                380                 :                : {
 8933                           381                 :          34510 :     List       *new_tlist = NIL;
                                382                 :                :     ListCell   *tlist_item;
                                383                 :                :     int         attrno,
                                384                 :                :                 numattrs;
                                385                 :                : 
 7263 neilc@samurai.com         386                 :          34510 :     tlist_item = list_head(tlist);
                                387                 :                : 
                                388                 :                :     /*
                                389                 :                :      * The rewriter should have already ensured that the TLEs are in correct
                                390                 :                :      * order; but we have to insert TLEs for any missing attributes.
                                391                 :                :      *
                                392                 :                :      * Scan the tuple description in the relation's relcache entry to make
                                393                 :                :      * sure we have all the user attributes in the right order.
                                394                 :                :      */
 8933 tgl@sss.pgh.pa.us         395                 :          34510 :     numattrs = RelationGetNumberOfAttributes(rel);
                                396                 :                : 
                                397         [ +  + ]:         112010 :     for (attrno = 1; attrno <= numattrs; attrno++)
                                398                 :                :     {
 2429 andres@anarazel.de        399                 :          77500 :         Form_pg_attribute att_tup = TupleDescAttr(rel->rd_att, attrno - 1);
 8768 bruce@momjian.us          400                 :          77500 :         TargetEntry *new_tle = NULL;
                                401                 :                : 
 7263 neilc@samurai.com         402         [ +  + ]:          77500 :         if (tlist_item != NULL)
                                403                 :                :         {
                                404                 :          72633 :             TargetEntry *old_tle = (TargetEntry *) lfirst(tlist_item);
                                405                 :                : 
 6948 tgl@sss.pgh.pa.us         406   [ +  -  +  + ]:          72633 :             if (!old_tle->resjunk && old_tle->resno == attrno)
                                407                 :                :             {
 8045                           408                 :          68105 :                 new_tle = old_tle;
 1735                           409                 :          68105 :                 tlist_item = lnext(tlist, tlist_item);
                                410                 :                :             }
                                411                 :                :         }
                                412                 :                : 
 8933                           413         [ +  + ]:          77500 :         if (new_tle == NULL)
                                414                 :                :         {
                                415                 :                :             /*
                                416                 :                :              * Didn't find a matching tlist entry, so make one.
                                417                 :                :              *
                                418                 :                :              * INSERTs should insert NULL in this case.  (We assume the
                                419                 :                :              * rewriter would have inserted any available non-NULL default
                                420                 :                :              * value.)  Also, if the column isn't dropped, apply any domain
                                421                 :                :              * constraints that might exist --- this is to catch domain NOT
                                422                 :                :              * NULL.
                                423                 :                :              *
                                424                 :                :              * When generating a NULL constant for a dropped column, we label
                                425                 :                :              * it INT4 (any other guaranteed-to-exist datatype would do as
                                426                 :                :              * well). We can't label it with the dropped column's datatype
                                427                 :                :              * since that might not exist anymore.  It does not really matter
                                428                 :                :              * what we claim the type is, since NULL is NULL --- its
                                429                 :                :              * representation is datatype-independent.  This could perhaps
                                430                 :                :              * confuse code comparing the finished plan to the target
                                431                 :                :              * relation, however.
                                432                 :                :              */
                                433                 :           9395 :             Oid         atttype = att_tup->atttypid;
 4814 peter_e@gmx.net           434                 :           9395 :             Oid         attcollation = att_tup->attcollation;
                                435                 :                :             Node       *new_expr;
                                436                 :                : 
 1068 tgl@sss.pgh.pa.us         437         [ +  + ]:           9395 :             if (!att_tup->attisdropped)
                                438                 :                :             {
                                439                 :           9088 :                 new_expr = (Node *) makeConst(atttype,
                                440                 :                :                                               -1,
                                441                 :                :                                               attcollation,
                                442                 :           9088 :                                               att_tup->attlen,
                                443                 :                :                                               (Datum) 0,
                                444                 :                :                                               true, /* isnull */
                                445                 :           9088 :                                               att_tup->attbyval);
                                446                 :           9088 :                 new_expr = coerce_to_domain(new_expr,
                                447                 :                :                                             InvalidOid, -1,
                                448                 :                :                                             atttype,
                                449                 :                :                                             COERCION_IMPLICIT,
                                450                 :                :                                             COERCE_IMPLICIT_CAST,
                                451                 :                :                                             -1,
                                452                 :                :                                             false);
                                453                 :                :             }
                                454                 :                :             else
                                455                 :                :             {
                                456                 :                :                 /* Insert NULL for dropped column */
                                457                 :            307 :                 new_expr = (Node *) makeConst(INT4OID,
                                458                 :                :                                               -1,
                                459                 :                :                                               InvalidOid,
                                460                 :                :                                               sizeof(int32),
                                461                 :                :                                               (Datum) 0,
                                462                 :                :                                               true, /* isnull */
                                463                 :                :                                               true /* byval */ );
                                464                 :                :             }
                                465                 :                : 
 6948                           466                 :           9395 :             new_tle = makeTargetEntry((Expr *) new_expr,
                                467                 :                :                                       attrno,
 7893 bruce@momjian.us          468                 :           9395 :                                       pstrdup(NameStr(att_tup->attname)),
                                469                 :                :                                       false);
                                470                 :                :         }
                                471                 :                : 
 8933 tgl@sss.pgh.pa.us         472                 :          77500 :         new_tlist = lappend(new_tlist, new_tle);
                                473                 :                :     }
                                474                 :                : 
                                475                 :                :     /*
                                476                 :                :      * The remaining tlist entries should be resjunk; append them all to the
                                477                 :                :      * end of the new tlist, making sure they have resnos higher than the last
                                478                 :                :      * real attribute.  (Note: although the rewriter already did such
                                479                 :                :      * renumbering, we have to do it again here in case we added NULL entries
                                480                 :                :      * above.)
                                481                 :                :      */
 7263 neilc@samurai.com         482         [ -  + ]:          34510 :     while (tlist_item)
                                483                 :                :     {
 7263 neilc@samurai.com         484                 :UBC           0 :         TargetEntry *old_tle = (TargetEntry *) lfirst(tlist_item);
                                485                 :                : 
 6948 tgl@sss.pgh.pa.us         486         [ #  # ]:              0 :         if (!old_tle->resjunk)
 7569                           487         [ #  # ]:              0 :             elog(ERROR, "targetlist is not sorted correctly");
                                488                 :                :         /* Get the resno right, but don't copy unnecessarily */
 6948                           489         [ #  # ]:              0 :         if (old_tle->resno != attrno)
                                490                 :                :         {
                                491                 :              0 :             old_tle = flatCopyTargetEntry(old_tle);
                                492                 :              0 :             old_tle->resno = attrno;
                                493                 :                :         }
 8045                           494                 :              0 :         new_tlist = lappend(new_tlist, old_tle);
                                495                 :              0 :         attrno++;
 1735                           496                 :              0 :         tlist_item = lnext(tlist, tlist_item);
                                497                 :                :     }
                                498                 :                : 
 8933 tgl@sss.pgh.pa.us         499                 :CBC       34510 :     return new_tlist;
                                500                 :                : }
                                501                 :                : 
                                502                 :                : 
                                503                 :                : /*
                                504                 :                :  * Locate PlanRowMark for given RT index, or return NULL if none
                                505                 :                :  *
                                506                 :                :  * This probably ought to be elsewhere, but there's no very good place
                                507                 :                :  */
                                508                 :                : PlanRowMark *
 5284                           509                 :          11040 : get_plan_rowmark(List *rowmarks, Index rtindex)
                                510                 :                : {
                                511                 :                :     ListCell   *l;
                                512                 :                : 
                                513   [ +  +  +  +  :          11704 :     foreach(l, rowmarks)
                                              +  + ]
                                514                 :                :     {
                                515                 :           1755 :         PlanRowMark *rc = (PlanRowMark *) lfirst(l);
                                516                 :                : 
                                517         [ +  + ]:           1755 :         if (rc->rti == rtindex)
                                518                 :           1091 :             return rc;
                                519                 :                :     }
                                520                 :           9949 :     return NULL;
                                521                 :                : }
        

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