LCOV - differential code coverage report
Current view: top level - src/backend/optimizer/util - appendinfo.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 95.2 % 335 319 4 2 7 3 3 142 25 149 10 145 23
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 14 14 10 1 3 9 1
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 100.0 % 1 1 1 1
Legend: Lines: hit not hit (60,120] days: 84.6 % 13 11 2 11
(180,240] days: 87.5 % 16 14 2 14
(240..) days: 96.1 % 305 293 2 7 3 3 141 149 10 135
Function coverage date bins:
(240..) days: 60.9 % 23 14 10 1 3 9

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * appendinfo.c
                                  4                 :  *    Routines for mapping between append parent(s) and children
                                  5                 :  *
                                  6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  7                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :  *
                                  9                 :  *
                                 10                 :  * IDENTIFICATION
                                 11                 :  *    src/backend/optimizer/util/appendinfo.c
                                 12                 :  *
                                 13                 :  *-------------------------------------------------------------------------
                                 14                 :  */
                                 15                 : #include "postgres.h"
                                 16                 : 
                                 17                 : #include "access/htup_details.h"
                                 18                 : #include "access/table.h"
                                 19                 : #include "foreign/fdwapi.h"
                                 20                 : #include "nodes/makefuncs.h"
                                 21                 : #include "nodes/nodeFuncs.h"
                                 22                 : #include "optimizer/appendinfo.h"
                                 23                 : #include "optimizer/pathnode.h"
                                 24                 : #include "optimizer/planmain.h"
                                 25                 : #include "parser/parsetree.h"
                                 26                 : #include "utils/lsyscache.h"
                                 27                 : #include "utils/rel.h"
                                 28                 : #include "utils/syscache.h"
                                 29                 : 
                                 30                 : 
                                 31                 : typedef struct
                                 32                 : {
                                 33                 :     PlannerInfo *root;
                                 34                 :     int         nappinfos;
                                 35                 :     AppendRelInfo **appinfos;
                                 36                 : } adjust_appendrel_attrs_context;
                                 37                 : 
                                 38                 : static void make_inh_translation_list(Relation oldrelation,
                                 39                 :                                       Relation newrelation,
                                 40                 :                                       Index newvarno,
                                 41                 :                                       AppendRelInfo *appinfo);
                                 42                 : static Node *adjust_appendrel_attrs_mutator(Node *node,
                                 43                 :                                             adjust_appendrel_attrs_context *context);
                                 44                 : 
                                 45                 : 
                                 46                 : /*
                                 47                 :  * make_append_rel_info
                                 48                 :  *    Build an AppendRelInfo for the parent-child pair
                                 49                 :  */
                                 50                 : AppendRelInfo *
 1550 alvherre                   51 CBC       17823 : make_append_rel_info(Relation parentrel, Relation childrel,
                                 52                 :                      Index parentRTindex, Index childRTindex)
                                 53                 : {
                                 54           17823 :     AppendRelInfo *appinfo = makeNode(AppendRelInfo);
                                 55                 : 
                                 56           17823 :     appinfo->parent_relid = parentRTindex;
                                 57           17823 :     appinfo->child_relid = childRTindex;
                                 58           17823 :     appinfo->parent_reltype = parentrel->rd_rel->reltype;
                                 59           17823 :     appinfo->child_reltype = childrel->rd_rel->reltype;
 1224 tgl                        60           17823 :     make_inh_translation_list(parentrel, childrel, childRTindex, appinfo);
 1550 alvherre                   61           17822 :     appinfo->parent_reloid = RelationGetRelid(parentrel);
                                 62                 : 
                                 63           17822 :     return appinfo;
                                 64                 : }
                                 65                 : 
                                 66                 : /*
                                 67                 :  * make_inh_translation_list
                                 68                 :  *    Build the list of translations from parent Vars to child Vars for
                                 69                 :  *    an inheritance child, as well as a reverse-translation array.
                                 70                 :  *
                                 71                 :  * The reverse-translation array has an entry for each child relation
                                 72                 :  * column, which is either the 1-based index of the corresponding parent
                                 73                 :  * column, or 0 if there's no match (that happens for dropped child columns,
                                 74                 :  * as well as child columns beyond those of the parent, which are allowed in
                                 75                 :  * traditional inheritance though not partitioning).
                                 76                 :  *
                                 77                 :  * For paranoia's sake, we match type/collation as well as attribute name.
                                 78                 :  */
                                 79                 : static void
                                 80           17823 : make_inh_translation_list(Relation oldrelation, Relation newrelation,
                                 81                 :                           Index newvarno,
                                 82                 :                           AppendRelInfo *appinfo)
                                 83                 : {
                                 84           17823 :     List       *vars = NIL;
                                 85                 :     AttrNumber *pcolnos;
                                 86           17823 :     TupleDesc   old_tupdesc = RelationGetDescr(oldrelation);
                                 87           17823 :     TupleDesc   new_tupdesc = RelationGetDescr(newrelation);
                                 88           17823 :     Oid         new_relid = RelationGetRelid(newrelation);
                                 89           17823 :     int         oldnatts = old_tupdesc->natts;
                                 90           17823 :     int         newnatts = new_tupdesc->natts;
                                 91                 :     int         old_attno;
                                 92           17823 :     int         new_attno = 0;
                                 93                 : 
                                 94                 :     /* Initialize reverse-translation array with all entries zero */
 1224 tgl                        95           17823 :     appinfo->num_child_cols = newnatts;
                                 96           17823 :     appinfo->parent_colnos = pcolnos =
                                 97           17823 :         (AttrNumber *) palloc0(newnatts * sizeof(AttrNumber));
                                 98                 : 
 1550 alvherre                   99           66781 :     for (old_attno = 0; old_attno < oldnatts; old_attno++)
                                100                 :     {
                                101                 :         Form_pg_attribute att;
                                102                 :         char       *attname;
                                103                 :         Oid         atttypid;
                                104                 :         int32       atttypmod;
                                105                 :         Oid         attcollation;
                                106                 : 
                                107           48959 :         att = TupleDescAttr(old_tupdesc, old_attno);
                                108           48959 :         if (att->attisdropped)
                                109                 :         {
                                110                 :             /* Just put NULL into this list entry */
                                111            1550 :             vars = lappend(vars, NULL);
                                112            1550 :             continue;
                                113                 :         }
                                114           47409 :         attname = NameStr(att->attname);
                                115           47409 :         atttypid = att->atttypid;
                                116           47409 :         atttypmod = att->atttypmod;
                                117           47409 :         attcollation = att->attcollation;
                                118                 : 
                                119                 :         /*
                                120                 :          * When we are generating the "translation list" for the parent table
                                121                 :          * of an inheritance set, no need to search for matches.
                                122                 :          */
                                123           47409 :         if (oldrelation == newrelation)
                                124                 :         {
                                125            2831 :             vars = lappend(vars, makeVar(newvarno,
                                126            2831 :                                          (AttrNumber) (old_attno + 1),
                                127                 :                                          atttypid,
                                128                 :                                          atttypmod,
                                129                 :                                          attcollation,
                                130                 :                                          0));
 1224 tgl                       131            2831 :             pcolnos[old_attno] = old_attno + 1;
 1550 alvherre                  132            2831 :             continue;
                                133                 :         }
                                134                 : 
                                135                 :         /*
                                136                 :          * Otherwise we have to search for the matching column by name.
                                137                 :          * There's no guarantee it'll have the same column position, because
                                138                 :          * of cases like ALTER TABLE ADD COLUMN and multiple inheritance.
                                139                 :          * However, in simple cases, the relative order of columns is mostly
                                140                 :          * the same in both relations, so try the column of newrelation that
                                141                 :          * follows immediately after the one that we just found, and if that
                                142                 :          * fails, let syscache handle it.
                                143                 :          */
                                144           44578 :         if (new_attno >= newnatts ||
                                145           43544 :             (att = TupleDescAttr(new_tupdesc, new_attno))->attisdropped ||
                                146           43138 :             strcmp(attname, NameStr(att->attname)) != 0)
                                147                 :         {
                                148                 :             HeapTuple   newtup;
                                149                 : 
                                150            3705 :             newtup = SearchSysCacheAttName(new_relid, attname);
 1435 tgl                       151            3705 :             if (!HeapTupleIsValid(newtup))
 1550 alvherre                  152 UBC           0 :                 elog(ERROR, "could not find inherited attribute \"%s\" of relation \"%s\"",
                                153                 :                      attname, RelationGetRelationName(newrelation));
 1550 alvherre                  154 CBC        3705 :             new_attno = ((Form_pg_attribute) GETSTRUCT(newtup))->attnum - 1;
 1224 tgl                       155            3705 :             Assert(new_attno >= 0 && new_attno < newnatts);
 1550 alvherre                  156            3705 :             ReleaseSysCache(newtup);
                                157                 : 
                                158            3705 :             att = TupleDescAttr(new_tupdesc, new_attno);
                                159                 :         }
                                160                 : 
                                161                 :         /* Found it, check type and collation match */
                                162           44578 :         if (atttypid != att->atttypid || atttypmod != att->atttypmod)
                                163               1 :             elog(ERROR, "attribute \"%s\" of relation \"%s\" does not match parent's type",
                                164                 :                  attname, RelationGetRelationName(newrelation));
                                165           44577 :         if (attcollation != att->attcollation)
 1550 alvherre                  166 UBC           0 :             elog(ERROR, "attribute \"%s\" of relation \"%s\" does not match parent's collation",
                                167                 :                  attname, RelationGetRelationName(newrelation));
                                168                 : 
 1550 alvherre                  169 CBC       44577 :         vars = lappend(vars, makeVar(newvarno,
                                170           44577 :                                      (AttrNumber) (new_attno + 1),
                                171                 :                                      atttypid,
                                172                 :                                      atttypmod,
                                173                 :                                      attcollation,
                                174                 :                                      0));
 1224 tgl                       175           44577 :         pcolnos[new_attno] = old_attno + 1;
 1550 alvherre                  176           44577 :         new_attno++;
                                177                 :     }
                                178                 : 
 1224 tgl                       179           17822 :     appinfo->translated_vars = vars;
 1550 alvherre                  180           17822 : }
                                181                 : 
                                182                 : /*
                                183                 :  * adjust_appendrel_attrs
                                184                 :  *    Copy the specified query or expression and translate Vars referring to a
                                185                 :  *    parent rel to refer to the corresponding child rel instead.  We also
                                186                 :  *    update rtindexes appearing outside Vars, such as resultRelation and
                                187                 :  *    jointree relids.
                                188                 :  *
                                189                 :  * Note: this is only applied after conversion of sublinks to subplans,
                                190                 :  * so we don't need to cope with recursion into sub-queries.
                                191                 :  *
                                192                 :  * Note: this is not hugely different from what pullup_replace_vars() does;
                                193                 :  * maybe we should try to fold the two routines together.
                                194                 :  */
                                195                 : Node *
                                196           89853 : adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos,
                                197                 :                        AppendRelInfo **appinfos)
                                198                 : {
                                199                 :     adjust_appendrel_attrs_context context;
                                200                 : 
                                201           89853 :     context.root = root;
                                202           89853 :     context.nappinfos = nappinfos;
                                203           89853 :     context.appinfos = appinfos;
                                204                 : 
                                205                 :     /* If there's nothing to adjust, don't call this function. */
                                206           89853 :     Assert(nappinfos >= 1 && appinfos != NULL);
                                207                 : 
                                208                 :     /* Should never be translating a Query tree. */
  739 tgl                       209           89853 :     Assert(node == NULL || !IsA(node, Query));
                                210                 : 
                                211           89853 :     return adjust_appendrel_attrs_mutator(node, &context);
                                212                 : }
                                213                 : 
                                214                 : static Node *
 1550 alvherre                  215          413977 : adjust_appendrel_attrs_mutator(Node *node,
                                216                 :                                adjust_appendrel_attrs_context *context)
                                217                 : {
                                218          413977 :     AppendRelInfo **appinfos = context->appinfos;
                                219          413977 :     int         nappinfos = context->nappinfos;
                                220                 :     int         cnt;
                                221                 : 
                                222          413977 :     if (node == NULL)
                                223           42104 :         return NULL;
                                224          371873 :     if (IsA(node, Var))
                                225                 :     {
                                226          163250 :         Var        *var = (Var *) copyObject(node);
                                227          163250 :         AppendRelInfo *appinfo = NULL;
                                228                 : 
 1186 tgl                       229          163250 :         if (var->varlevelsup != 0)
 1186 tgl                       230 UBC           0 :             return (Node *) var;    /* no changes needed */
                                231                 : 
                                232                 :         /*
                                233                 :          * You might think we need to adjust var->varnullingrels, but that
                                234                 :          * shouldn't need any changes.  It will contain outer-join relids,
                                235                 :          * while the transformation we are making affects only baserels.
                                236                 :          * Below, we just propagate var->varnullingrels into the translated
                                237                 :          * Var.
                                238                 :          *
                                239                 :          * If var->varnullingrels isn't empty, and the translation wouldn't be
                                240                 :          * a Var, we have to fail.  One could imagine wrapping the translated
                                241                 :          * expression in a PlaceHolderVar, but that won't work because this is
                                242                 :          * typically used after freezing placeholders.  Fortunately, the case
                                243                 :          * appears unreachable at the moment.  We can see nonempty
                                244                 :          * var->varnullingrels here, but only in cases involving partitionwise
                                245                 :          * joining, and in such cases the translations will always be Vars.
                                246                 :          * (Non-Var translations occur only for appendrels made by flattening
                                247                 :          * UNION ALL subqueries.)  Should we need to make this work in future,
                                248                 :          * a possible fix is to mandate that prepjointree.c create PHVs for
                                249                 :          * all non-Var outputs of such subqueries, and then we could look up
                                250                 :          * the pre-existing PHV here.  Or perhaps just wrap the translations
                                251                 :          * that way to begin with?
                                252                 :          */
                                253                 : 
 1550 alvherre                  254 GIC      207917 :         for (cnt = 0; cnt < nappinfos; cnt++)
                                255                 :         {
                                256          182140 :             if (var->varno == appinfos[cnt]->parent_relid)
                                257                 :             {
                                258          137473 :                 appinfo = appinfos[cnt];
                                259          137473 :                 break;
                                260                 :             }
                                261                 :         }
                                262                 : 
 1186 tgl                       263          163250 :         if (appinfo)
                                264                 :         {
 1550 alvherre                  265          137473 :             var->varno = appinfo->child_relid;
                                266                 :             /* it's now a generated Var, so drop any syntactic labeling */
 1186 tgl                       267          137473 :             var->varnosyn = 0;
                                268          137473 :             var->varattnosyn = 0;
 1550 alvherre                  269          137473 :             if (var->varattno > 0)
                                270                 :             {
                                271                 :                 Node       *newnode;
                                272                 : 
                                273          130174 :                 if (var->varattno > list_length(appinfo->translated_vars))
 1550 alvherre                  274 UIC           0 :                     elog(ERROR, "attribute %d of relation \"%s\" does not exist",
                                275                 :                          var->varattno, get_rel_name(appinfo->parent_reloid));
 1550 alvherre                  276 CBC      130174 :                 newnode = copyObject(list_nth(appinfo->translated_vars,
                                277                 :                                               var->varattno - 1));
                                278          130174 :                 if (newnode == NULL)
 1550 alvherre                  279 UIC           0 :                     elog(ERROR, "attribute %d of relation \"%s\" does not exist",
 1550 alvherre                  280 ECB             :                          var->varattno, get_rel_name(appinfo->parent_reloid));
   69 tgl                       281 GNC      130174 :                 if (IsA(newnode, Var))
                                282          128492 :                     ((Var *) newnode)->varnullingrels = var->varnullingrels;
                                283            1682 :                 else if (var->varnullingrels != NULL)
   69 tgl                       284 UNC           0 :                     elog(ERROR, "failed to apply nullingrels to a non-Var");
 1550 alvherre                  285 CBC      130174 :                 return newnode;
                                286                 :             }
 1550 alvherre                  287 GIC        7299 :             else if (var->varattno == 0)
                                288                 :             {
 1550 alvherre                  289 ECB             :                 /*
                                290                 :                  * Whole-row Var: if we are dealing with named rowtypes, we
                                291                 :                  * can use a whole-row Var for the child table plus a coercion
                                292                 :                  * step to convert the tuple layout to the parent's rowtype.
                                293                 :                  * Otherwise we have to generate a RowExpr.
                                294                 :                  */
 1550 alvherre                  295 CBC         443 :                 if (OidIsValid(appinfo->child_reltype))
                                296                 :                 {
 1550 alvherre                  297 GIC         415 :                     Assert(var->vartype == appinfo->parent_reltype);
                                298             415 :                     if (appinfo->parent_reltype != appinfo->child_reltype)
 1550 alvherre                  299 ECB             :                     {
 1550 alvherre                  300 GBC         343 :                         ConvertRowtypeExpr *r = makeNode(ConvertRowtypeExpr);
                                301                 : 
 1550 alvherre                  302 CBC         343 :                         r->arg = (Expr *) var;
 1550 alvherre                  303 GIC         343 :                         r->resulttype = appinfo->parent_reltype;
 1550 alvherre                  304 CBC         343 :                         r->convertformat = COERCE_IMPLICIT_CAST;
 1550 alvherre                  305 GBC         343 :                         r->location = -1;
                                306                 :                         /* Make sure the Var node has the right type ID, too */
 1550 alvherre                  307 CBC         343 :                         var->vartype = appinfo->child_reltype;
                                308             343 :                         return (Node *) r;
 1550 alvherre                  309 ECB             :                     }
 1550 alvherre                  310 EUB             :                 }
 1550 alvherre                  311 ECB             :                 else
                                312                 :                 {
                                313                 :                     /*
                                314                 :                      * Build a RowExpr containing the translated variables.
                                315                 :                      *
                                316                 :                      * In practice var->vartype will always be RECORDOID here,
                                317                 :                      * so we need to come up with some suitable column names.
                                318                 :                      * We use the parent RTE's column names.
                                319                 :                      *
                                320                 :                      * Note: we can't get here for inheritance cases, so there
                                321                 :                      * is no need to worry that translated_vars might contain
                                322                 :                      * some dummy NULLs.
                                323                 :                      */
                                324                 :                     RowExpr    *rowexpr;
                                325                 :                     List       *fields;
                                326                 :                     RangeTblEntry *rte;
                                327                 : 
 1550 alvherre                  328 CBC          28 :                     rte = rt_fetch(appinfo->parent_relid,
 1550 alvherre                  329 ECB             :                                    context->root->parse->rtable);
 1550 alvherre                  330 CBC          28 :                     fields = copyObject(appinfo->translated_vars);
                                331              28 :                     rowexpr = makeNode(RowExpr);
 1550 alvherre                  332 GIC          28 :                     rowexpr->args = fields;
 1550 alvherre                  333 CBC          28 :                     rowexpr->row_typeid = var->vartype;
                                334              28 :                     rowexpr->row_format = COERCE_IMPLICIT_CAST;
 1550 alvherre                  335 GIC          28 :                     rowexpr->colnames = copyObject(rte->eref->colnames);
                                336              28 :                     rowexpr->location = -1;
                                337                 : 
   69 tgl                       338 GNC          28 :                     if (var->varnullingrels != NULL)
   69 tgl                       339 UNC           0 :                         elog(ERROR, "failed to apply nullingrels to a non-Var");
                                340                 : 
 1550 alvherre                  341 GIC          28 :                     return (Node *) rowexpr;
                                342                 :                 }
                                343                 :             }
                                344                 :             /* system attributes don't need any other translation */
                                345                 :         }
  739 tgl                       346           25777 :         else if (var->varno == ROWID_VAR)
                                347                 :         {
                                348                 :             /*
                                349                 :              * If it's a ROWID_VAR placeholder, see if we've reached a leaf
                                350                 :              * target rel, for which we can translate the Var to a specific
                                351                 :              * instantiation.  We should never be asked to translate to a set
                                352                 :              * of relids containing more than one leaf target rel, so the
                                353                 :              * answer will be unique.  If we're still considering non-leaf
                                354                 :              * inheritance levels, return the ROWID_VAR Var as-is.
                                355                 :              */
                                356            8291 :             Relids      leaf_result_relids = context->root->leaf_result_relids;
  739 tgl                       357 CBC        8291 :             Index       leaf_relid = 0;
                                358                 : 
                                359           16582 :             for (cnt = 0; cnt < nappinfos; cnt++)
  739 tgl                       360 ECB             :             {
  739 tgl                       361 CBC        8291 :                 if (bms_is_member(appinfos[cnt]->child_relid,
  739 tgl                       362 ECB             :                                   leaf_result_relids))
                                363                 :                 {
  739 tgl                       364 CBC        7267 :                     if (leaf_relid)
  739 tgl                       365 LBC           0 :                         elog(ERROR, "cannot translate to multiple leaf relids");
  739 tgl                       366 GIC        7267 :                     leaf_relid = appinfos[cnt]->child_relid;
  739 tgl                       367 ECB             :                 }
  739 tgl                       368 EUB             :             }
                                369                 : 
  739 tgl                       370 CBC        8291 :             if (leaf_relid)
                                371                 :             {
                                372                 :                 RowIdentityVarInfo *ridinfo = (RowIdentityVarInfo *)
  739 tgl                       373 GIC        7267 :                 list_nth(context->root->row_identity_vars, var->varattno - 1);
                                374                 : 
  739 tgl                       375 CBC        7267 :                 if (bms_is_member(leaf_relid, ridinfo->rowidrels))
                                376                 :                 {
                                377                 :                     /* Substitute the Var given in the RowIdentityVarInfo */
  739 tgl                       378 GIC        7223 :                     var = copyObject(ridinfo->rowidvar);
                                379                 :                     /* ... but use the correct relid */
                                380            7223 :                     var->varno = leaf_relid;
                                381                 :                     /* identity vars shouldn't have nulling rels */
   69 tgl                       382 GNC        7223 :                     Assert(var->varnullingrels == NULL);
                                383                 :                     /* varnosyn in the RowIdentityVarInfo is probably wrong */
  739 tgl                       384 GIC        7223 :                     var->varnosyn = 0;
                                385            7223 :                     var->varattnosyn = 0;
                                386                 :                 }
  739 tgl                       387 ECB             :                 else
                                388                 :                 {
                                389                 :                     /*
                                390                 :                      * This leaf rel can't return the desired value, so
                                391                 :                      * substitute a NULL of the correct type.
                                392                 :                      */
  739 tgl                       393 GIC          44 :                     return (Node *) makeNullConst(var->vartype,
                                394                 :                                                   var->vartypmod,
  739 tgl                       395 ECB             :                                                   var->varcollid);
  739 tgl                       396 EUB             :                 }
  739 tgl                       397 ECB             :             }
                                398                 :         }
 1550 alvherre                  399 GIC       32661 :         return (Node *) var;
                                400                 :     }
 1550 alvherre                  401 CBC      208623 :     if (IsA(node, CurrentOfExpr))
                                402                 :     {
 1550 alvherre                  403 GIC          92 :         CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
 1550 alvherre                  404 ECB             : 
 1550 alvherre                  405 GIC          92 :         for (cnt = 0; cnt < nappinfos; cnt++)
 1550 alvherre                  406 ECB             :         {
 1550 alvherre                  407 GIC          92 :             AppendRelInfo *appinfo = appinfos[cnt];
                                408                 : 
 1550 alvherre                  409 CBC          92 :             if (cexpr->cvarno == appinfo->parent_relid)
                                410                 :             {
                                411              92 :                 cexpr->cvarno = appinfo->child_relid;
 1550 alvherre                  412 GIC          92 :                 break;
 1550 alvherre                  413 ECB             :             }
                                414                 :         }
 1550 alvherre                  415 CBC          92 :         return (Node *) cexpr;
 1550 alvherre                  416 ECB             :     }
 1550 alvherre                  417 GIC      208531 :     if (IsA(node, PlaceHolderVar))
                                418                 :     {
                                419                 :         /* Copy the PlaceHolderVar node with correct mutation of subnodes */
                                420                 :         PlaceHolderVar *phv;
                                421                 : 
                                422            1086 :         phv = (PlaceHolderVar *) expression_tree_mutator(node,
                                423                 :                                                          adjust_appendrel_attrs_mutator,
 1550 alvherre                  424 ECB             :                                                          (void *) context);
                                425                 :         /* now fix PlaceHolderVar's relid sets */
 1550 alvherre                  426 GIC        1086 :         if (phv->phlevelsup == 0)
                                427                 :         {
   69 tgl                       428 GNC        1086 :             phv->phrels = adjust_child_relids(phv->phrels,
                                429                 :                                               nappinfos, appinfos);
                                430                 :             /* as above, we needn't touch phnullingrels */
                                431                 :         }
 1550 alvherre                  432 GIC        1086 :         return (Node *) phv;
 1550 alvherre                  433 ECB             :     }
                                434                 :     /* Shouldn't need to handle planner auxiliary nodes here */
 1550 alvherre                  435 CBC      207445 :     Assert(!IsA(node, SpecialJoinInfo));
 1550 alvherre                  436 GIC      207445 :     Assert(!IsA(node, AppendRelInfo));
 1550 alvherre                  437 CBC      207445 :     Assert(!IsA(node, PlaceHolderInfo));
 1550 alvherre                  438 GIC      207445 :     Assert(!IsA(node, MinMaxAggInfo));
 1550 alvherre                  439 ECB             : 
                                440                 :     /*
                                441                 :      * We have to process RestrictInfo nodes specially.  (Note: although
                                442                 :      * set_append_rel_pathlist will hide RestrictInfos in the parent's
                                443                 :      * baserestrictinfo list from us, it doesn't hide those in joininfo.)
                                444                 :      */
 1550 alvherre                  445 CBC      207445 :     if (IsA(node, RestrictInfo))
 1550 alvherre                  446 ECB             :     {
 1550 alvherre                  447 GIC       16784 :         RestrictInfo *oldinfo = (RestrictInfo *) node;
                                448           16784 :         RestrictInfo *newinfo = makeNode(RestrictInfo);
 1550 alvherre                  449 ECB             : 
                                450                 :         /* Copy all flat-copiable fields, notably including rinfo_serial */
 1550 alvherre                  451 CBC       16784 :         memcpy(newinfo, oldinfo, sizeof(RestrictInfo));
                                452                 : 
                                453                 :         /* Recursively fix the clause itself */
 1550 alvherre                  454 GIC       16784 :         newinfo->clause = (Expr *)
                                455           16784 :             adjust_appendrel_attrs_mutator((Node *) oldinfo->clause, context);
 1550 alvherre                  456 ECB             : 
                                457                 :         /* and the modified version, if an OR clause */
 1550 alvherre                  458 GIC       16784 :         newinfo->orclause = (Expr *)
                                459           16784 :             adjust_appendrel_attrs_mutator((Node *) oldinfo->orclause, context);
 1550 alvherre                  460 ECB             : 
                                461                 :         /* adjust relid sets too */
 1550 alvherre                  462 CBC       16784 :         newinfo->clause_relids = adjust_child_relids(oldinfo->clause_relids,
                                463                 :                                                      context->nappinfos,
                                464                 :                                                      context->appinfos);
 1550 alvherre                  465 GIC       16784 :         newinfo->required_relids = adjust_child_relids(oldinfo->required_relids,
 1550 alvherre                  466 ECB             :                                                        context->nappinfos,
                                467                 :                                                        context->appinfos);
 1550 alvherre                  468 GIC       16784 :         newinfo->outer_relids = adjust_child_relids(oldinfo->outer_relids,
 1550 alvherre                  469 ECB             :                                                     context->nappinfos,
                                470                 :                                                     context->appinfos);
 1550 alvherre                  471 GIC       16784 :         newinfo->left_relids = adjust_child_relids(oldinfo->left_relids,
                                472                 :                                                    context->nappinfos,
                                473                 :                                                    context->appinfos);
                                474           16784 :         newinfo->right_relids = adjust_child_relids(oldinfo->right_relids,
                                475                 :                                                     context->nappinfos,
 1550 alvherre                  476 ECB             :                                                     context->appinfos);
                                477                 : 
                                478                 :         /*
                                479                 :          * Reset cached derivative fields, since these might need to have
                                480                 :          * different values when considering the child relation.  Note we
                                481                 :          * don't reset left_ec/right_ec: each child variable is implicitly
                                482                 :          * equivalent to its parent, so still a member of the same EC if any.
                                483                 :          */
 1550 alvherre                  484 GIC       16784 :         newinfo->eval_cost.startup = -1;
 1550 alvherre                  485 CBC       16784 :         newinfo->norm_selec = -1;
                                486           16784 :         newinfo->outer_selec = -1;
 1550 alvherre                  487 GIC       16784 :         newinfo->left_em = NULL;
                                488           16784 :         newinfo->right_em = NULL;
 1550 alvherre                  489 CBC       16784 :         newinfo->scansel_cache = NIL;
                                490           16784 :         newinfo->left_bucketsize = -1;
 1550 alvherre                  491 GIC       16784 :         newinfo->right_bucketsize = -1;
                                492           16784 :         newinfo->left_mcvfreq = -1;
 1550 alvherre                  493 CBC       16784 :         newinfo->right_mcvfreq = -1;
                                494                 : 
 1550 alvherre                  495 GIC       16784 :         return (Node *) newinfo;
 1550 alvherre                  496 ECB             :     }
                                497                 : 
                                498                 :     /*
                                499                 :      * NOTE: we do not need to recurse into sublinks, because they should
                                500                 :      * already have been converted to subplans before we see them.
                                501                 :      */
 1550 alvherre                  502 CBC      190661 :     Assert(!IsA(node, SubLink));
 1550 alvherre                  503 GIC      190661 :     Assert(!IsA(node, Query));
                                504                 :     /* We should never see these Query substructures, either. */
  739 tgl                       505 CBC      190661 :     Assert(!IsA(node, RangeTblRef));
  739 tgl                       506 GIC      190661 :     Assert(!IsA(node, JoinExpr));
                                507                 : 
 1550 alvherre                  508          190661 :     return expression_tree_mutator(node, adjust_appendrel_attrs_mutator,
                                509                 :                                    (void *) context);
                                510                 : }
                                511                 : 
                                512                 : /*
                                513                 :  * adjust_appendrel_attrs_multilevel
                                514                 :  *    Apply Var translations from an appendrel parent down to a child.
 1544 alvherre                  515 ECB             :  *
                                516                 :  * Replace Vars in the "node" expression that reference "parentrel" with
                                517                 :  * the appropriate Vars for "childrel".  childrel can be more than one
                                518                 :  * inheritance level removed from parentrel.
                                519                 :  */
                                520                 : Node *
 1544 alvherre                  521 CBC       15268 : adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node,
                                522                 :                                   RelOptInfo *childrel,
                                523                 :                                   RelOptInfo *parentrel)
 1544 alvherre                  524 ECB             : {
                                525                 :     AppendRelInfo **appinfos;
                                526                 :     int         nappinfos;
                                527                 : 
                                528                 :     /* Recurse if immediate parent is not the top parent. */
  234 tgl                       529 GNC       15268 :     if (childrel->parent != parentrel)
                                530                 :     {
                                531            4544 :         if (childrel->parent)
                                532            4544 :             node = adjust_appendrel_attrs_multilevel(root, node,
                                533            4544 :                                                      childrel->parent,
                                534                 :                                                      parentrel);
                                535                 :         else
  234 tgl                       536 UNC           0 :             elog(ERROR, "childrel is not a child of parentrel");
                                537                 :     }
                                538                 : 
                                539                 :     /* Now translate for this child. */
  234 tgl                       540 GNC       15268 :     appinfos = find_appinfos_by_relids(root, childrel->relids, &nappinfos);
                                541                 : 
 1544 alvherre                  542 GIC       15268 :     node = adjust_appendrel_attrs(root, node, nappinfos, appinfos);
                                543                 : 
                                544           15268 :     pfree(appinfos);
                                545                 : 
                                546           15268 :     return node;
 1544 alvherre                  547 ECB             : }
                                548                 : 
                                549                 : /*
                                550                 :  * Substitute child relids for parent relids in a Relid set.  The array of
                                551                 :  * appinfos specifies the substitutions to be performed.
                                552                 :  */
                                553                 : Relids
 1550 alvherre                  554 GIC       98632 : adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
 1550 alvherre                  555 ECB             : {
 1550 alvherre                  556 GIC       98632 :     Bitmapset  *result = NULL;
 1550 alvherre                  557 ECB             :     int         cnt;
                                558                 : 
 1550 alvherre                  559 CBC      237290 :     for (cnt = 0; cnt < nappinfos; cnt++)
                                560                 :     {
 1550 alvherre                  561 GIC      138658 :         AppendRelInfo *appinfo = appinfos[cnt];
 1550 alvherre                  562 EUB             : 
                                563                 :         /* Remove parent, add child */
 1550 alvherre                  564 GIC      138658 :         if (bms_is_member(appinfo->parent_relid, relids))
                                565                 :         {
 1550 alvherre                  566 ECB             :             /* Make a copy if we are changing the set. */
 1550 alvherre                  567 GIC       85689 :             if (!result)
 1550 alvherre                  568 CBC       73686 :                 result = bms_copy(relids);
                                569                 : 
                                570           85689 :             result = bms_del_member(result, appinfo->parent_relid);
 1550 alvherre                  571 GIC       85689 :             result = bms_add_member(result, appinfo->child_relid);
 1550 alvherre                  572 ECB             :         }
                                573                 :     }
                                574                 : 
                                575                 :     /* If we made any changes, return the modified copy. */
 1550 alvherre                  576 GIC       98632 :     if (result)
                                577           73686 :         return result;
                                578                 : 
                                579                 :     /* Otherwise, return the original set without modification. */
 1550 alvherre                  580 CBC       24946 :     return relids;
                                581                 : }
 1550 alvherre                  582 ECB             : 
                                583                 : /*
                                584                 :  * Substitute child's relids for parent's relids in a Relid set.
                                585                 :  * The childrel can be multiple inheritance levels below the parent.
                                586                 :  */
                                587                 : Relids
 1550 alvherre                  588 GIC        4154 : adjust_child_relids_multilevel(PlannerInfo *root, Relids relids,
                                589                 :                                RelOptInfo *childrel,
                                590                 :                                RelOptInfo *parentrel)
                                591                 : {
                                592                 :     AppendRelInfo **appinfos;
 1550 alvherre                  593 ECB             :     int         nappinfos;
                                594                 : 
                                595                 :     /*
                                596                 :      * If the given relids set doesn't contain any of the parent relids, it
                                597                 :      * will remain unchanged.
                                598                 :      */
  234 tgl                       599 GNC        4154 :     if (!bms_overlap(relids, parentrel->relids))
 1550 alvherre                  600 UIC           0 :         return relids;
                                601                 : 
                                602                 :     /* Recurse if immediate parent is not the top parent. */
  234 tgl                       603 GNC        4154 :     if (childrel->parent != parentrel)
                                604                 :     {
                                605              72 :         if (childrel->parent)
                                606              72 :             relids = adjust_child_relids_multilevel(root, relids,
                                607              72 :                                                     childrel->parent,
                                608                 :                                                     parentrel);
                                609                 :         else
  234 tgl                       610 UNC           0 :             elog(ERROR, "childrel is not a child of parentrel");
                                611                 :     }
                                612                 : 
                                613                 :     /* Now translate for this child. */
  234 tgl                       614 GNC        4154 :     appinfos = find_appinfos_by_relids(root, childrel->relids, &nappinfos);
                                615                 : 
                                616            4154 :     relids = adjust_child_relids(relids, nappinfos, appinfos);
 1550 alvherre                  617 EUB             : 
 1550 alvherre                  618 CBC        4154 :     pfree(appinfos);
 1550 alvherre                  619 ECB             : 
  234 tgl                       620 GNC        4154 :     return relids;
                                621                 : }
                                622                 : 
 1550 alvherre                  623 EUB             : /*
                                624                 :  * adjust_inherited_attnums
                                625                 :  *    Translate an integer list of attribute numbers from parent to child.
                                626                 :  */
  739 tgl                       627 ECB             : List *
  739 tgl                       628 GIC        2173 : adjust_inherited_attnums(List *attnums, AppendRelInfo *context)
 1550 alvherre                  629 ECB             : {
  739 tgl                       630 GIC        2173 :     List       *result = NIL;
  739 tgl                       631 ECB             :     ListCell   *lc;
                                632                 : 
 1550 alvherre                  633                 :     /* This should only happen for an inheritance case, not UNION ALL */
 1550 alvherre                  634 GIC        2173 :     Assert(OidIsValid(context->parent_reloid));
                                635                 : 
                                636                 :     /* Look up each attribute in the AppendRelInfo's translated_vars list */
  739 tgl                       637            4754 :     foreach(lc, attnums)
                                638                 :     {
                                639            2581 :         AttrNumber  parentattno = lfirst_int(lc);
                                640                 :         Var        *childvar;
 1550 alvherre                  641 ECB             : 
                                642                 :         /* Look up the translation of this column: it must be a Var */
  739 tgl                       643 CBC        5162 :         if (parentattno <= 0 ||
  739 tgl                       644 GIC        2581 :             parentattno > list_length(context->translated_vars))
 1550 alvherre                  645 UIC           0 :             elog(ERROR, "attribute %d of relation \"%s\" does not exist",
                                646                 :                  parentattno, get_rel_name(context->parent_reloid));
  739 tgl                       647 CBC        2581 :         childvar = (Var *) list_nth(context->translated_vars, parentattno - 1);
 1550 alvherre                  648 GIC        2581 :         if (childvar == NULL || !IsA(childvar, Var))
 1550 alvherre                  649 UIC           0 :             elog(ERROR, "attribute %d of relation \"%s\" does not exist",
  739 tgl                       650 ECB             :                  parentattno, get_rel_name(context->parent_reloid));
                                651                 : 
  739 tgl                       652 CBC        2581 :         result = lappend_int(result, childvar->varattno);
                                653                 :     }
  739 tgl                       654 GIC        2173 :     return result;
                                655                 : }
 1550 alvherre                  656 ECB             : 
  739 tgl                       657                 : /*
  739 tgl                       658 EUB             :  * adjust_inherited_attnums_multilevel
                                659                 :  *    As above, but traverse multiple inheritance levels as needed.
  739 tgl                       660 ECB             :  */
                                661                 : List *
  739 tgl                       662 GBC        2173 : adjust_inherited_attnums_multilevel(PlannerInfo *root, List *attnums,
                                663                 :                                     Index child_relid, Index top_parent_relid)
                                664                 : {
  739 tgl                       665 CBC        2173 :     AppendRelInfo *appinfo = root->append_rel_array[child_relid];
                                666                 : 
                                667            2173 :     if (!appinfo)
  739 tgl                       668 UIC           0 :         elog(ERROR, "child rel %d not found in append_rel_array", child_relid);
                                669                 : 
                                670                 :     /* Recurse if immediate parent is not the top parent. */
  739 tgl                       671 GIC        2173 :     if (appinfo->parent_relid != top_parent_relid)
                                672             395 :         attnums = adjust_inherited_attnums_multilevel(root, attnums,
                                673                 :                                                       appinfo->parent_relid,
                                674                 :                                                       top_parent_relid);
 1550 alvherre                  675 ECB             : 
                                676                 :     /* Now translate for this child */
  739 tgl                       677 GIC        2173 :     return adjust_inherited_attnums(attnums, appinfo);
  739 tgl                       678 ECB             : }
                                679                 : 
                                680                 : /*
  739 tgl                       681 EUB             :  * get_translated_update_targetlist
                                682                 :  *    Get the processed_tlist of an UPDATE query, translated as needed to
                                683                 :  *    match a child target relation.
  739 tgl                       684 ECB             :  *
                                685                 :  * Optionally also return the list of target column numbers translated
                                686                 :  * to this target relation.  (The resnos in processed_tlist MUST NOT be
                                687                 :  * relied on for this purpose.)
                                688                 :  */
                                689                 : void
  739 tgl                       690 CBC          50 : get_translated_update_targetlist(PlannerInfo *root, Index relid,
                                691                 :                                  List **processed_tlist, List **update_colnos)
                                692                 : {
                                693                 :     /* This is pretty meaningless for commands other than UPDATE. */
  739 tgl                       694 GIC          50 :     Assert(root->parse->commandType == CMD_UPDATE);
                                695              50 :     if (relid == root->parse->resultRelation)
                                696                 :     {
                                697                 :         /*
                                698                 :          * Non-inheritance case, so it's easy.  The caller might be expecting
                                699                 :          * a tree it can scribble on, though, so copy.
                                700                 :          */
                                701              33 :         *processed_tlist = copyObject(root->processed_tlist);
                                702              33 :         if (update_colnos)
  739 tgl                       703 CBC          33 :             *update_colnos = copyObject(root->update_colnos);
                                704                 :     }
                                705                 :     else
                                706                 :     {
                                707              17 :         Assert(bms_is_member(relid, root->all_result_relids));
                                708              17 :         *processed_tlist = (List *)
  739 tgl                       709 GIC          17 :             adjust_appendrel_attrs_multilevel(root,
                                710              17 :                                               (Node *) root->processed_tlist,
                                711                 :                                               find_base_rel(root, relid),
  234 tgl                       712 GNC          17 :                                               find_base_rel(root, root->parse->resultRelation));
  739 tgl                       713 GIC          17 :         if (update_colnos)
  739 tgl                       714 CBC          17 :             *update_colnos =
                                715              17 :                 adjust_inherited_attnums_multilevel(root, root->update_colnos,
  739 tgl                       716 ECB             :                                                     relid,
  739 tgl                       717 GIC          17 :                                                     root->parse->resultRelation);
                                718                 :     }
 1550 alvherre                  719              50 : }
 1550 alvherre                  720 ECB             : 
                                721                 : /*
                                722                 :  * find_appinfos_by_relids
                                723                 :  *      Find AppendRelInfo structures for base relations listed in relids.
                                724                 :  *
                                725                 :  * The relids argument is typically a join relation's relids, which can
                                726                 :  * include outer-join RT indexes in addition to baserels.  We silently
                                727                 :  * ignore the outer joins.
                                728                 :  *
                                729                 :  * The AppendRelInfos are returned in an array, which can be pfree'd by the
                                730                 :  * caller. *nappinfos is set to the number of entries in the array.
                                731                 :  */
                                732                 : AppendRelInfo **
 1550 alvherre                  733 GIC       39498 : find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
 1550 alvherre                  734 ECB             : {
                                735                 :     AppendRelInfo **appinfos;
 1550 alvherre                  736 CBC       39498 :     int         cnt = 0;
                                737                 :     int         i;
                                738                 : 
                                739                 :     /* Allocate an array that's certainly big enough */
                                740                 :     appinfos = (AppendRelInfo **)
   69 tgl                       741 GNC       39498 :         palloc(sizeof(AppendRelInfo *) * bms_num_members(relids));
                                742                 : 
 1550 alvherre                  743 GIC       39498 :     i = -1;
                                744           94070 :     while ((i = bms_next_member(relids, i)) >= 0)
                                745                 :     {
                                746           54572 :         AppendRelInfo *appinfo = root->append_rel_array[i];
                                747                 : 
                                748           54572 :         if (!appinfo)
                                749                 :         {
                                750                 :             /* Probably i is an OJ index, but let's check */
   69 tgl                       751 GNC        4908 :             if (find_base_rel_ignore_join(root, i) == NULL)
                                752            4908 :                 continue;
                                753                 :             /* It's a base rel, but we lack an append_rel_array entry */
 1550 alvherre                  754 UIC           0 :             elog(ERROR, "child rel %d not found in append_rel_array", i);
                                755                 :         }
                                756                 : 
 1550 alvherre                  757 CBC       49664 :         appinfos[cnt++] = appinfo;
                                758                 :     }
   69 tgl                       759 GNC       39498 :     *nappinfos = cnt;
 1550 alvherre                  760 GIC       39498 :     return appinfos;
 1550 alvherre                  761 ECB             : }
                                762                 : 
                                763                 : 
                                764                 : /*****************************************************************************
                                765                 :  *
  739 tgl                       766                 :  *      ROW-IDENTITY VARIABLE MANAGEMENT
                                767                 :  *
                                768                 :  * This code lacks a good home, perhaps.  We choose to keep it here because
                                769                 :  * adjust_appendrel_attrs_mutator() is its principal co-conspirator.  That
                                770                 :  * function does most of what is needed to expand ROWID_VAR Vars into the
                                771                 :  * right things.
                                772                 :  *
                                773                 :  *****************************************************************************/
                                774                 : 
                                775                 : /*
                                776                 :  * add_row_identity_var
  167 alvherre                  777                 :  *    Register a row-identity column to be used in UPDATE/DELETE/MERGE.
                                778                 :  *
  739 tgl                       779 EUB             :  * The Var must be equal(), aside from varno, to any other row-identity
                                780                 :  * column with the same rowid_name.  Thus, for example, "wholerow"
                                781                 :  * row identities had better use vartype == RECORDOID.
  739 tgl                       782 ECB             :  *
                                783                 :  * rtindex is currently redundant with rowid_var->varno, but we specify
                                784                 :  * it as a separate parameter in case this is ever generalized to support
                                785                 :  * non-Var expressions.  (We could reasonably handle expressions over
                                786                 :  * Vars of the specified rtindex, but for now that seems unnecessary.)
                                787                 :  */
                                788                 : void
  739 tgl                       789 GIC       13375 : add_row_identity_var(PlannerInfo *root, Var *orig_var,
                                790                 :                      Index rtindex, const char *rowid_name)
                                791                 : {
                                792                 :     TargetEntry *tle;
                                793                 :     Var        *rowid_var;
                                794                 :     RowIdentityVarInfo *ridinfo;
                                795                 :     ListCell   *lc;
                                796                 : 
                                797                 :     /* For now, the argument must be just a Var of the given rtindex */
                                798           13375 :     Assert(IsA(orig_var, Var));
                                799           13375 :     Assert(orig_var->varno == rtindex);
                                800           13375 :     Assert(orig_var->varlevelsup == 0);
   69 tgl                       801 GNC       13375 :     Assert(orig_var->varnullingrels == NULL);
                                802                 : 
                                803                 :     /*
                                804                 :      * If we're doing non-inherited UPDATE/DELETE/MERGE, there's little need
                                805                 :      * for ROWID_VAR shenanigans.  Just shove the presented Var into the
                                806                 :      * processed_tlist, and we're done.
                                807                 :      */
  739 tgl                       808 GIC       13375 :     if (rtindex == root->parse->resultRelation)
                                809                 :     {
                                810            8828 :         tle = makeTargetEntry((Expr *) orig_var,
                                811            8828 :                               list_length(root->processed_tlist) + 1,
                                812                 :                               pstrdup(rowid_name),
                                813                 :                               true);
                                814            8828 :         root->processed_tlist = lappend(root->processed_tlist, tle);
  739 tgl                       815 CBC        8828 :         return;
                                816                 :     }
                                817                 : 
                                818                 :     /*
                                819                 :      * Otherwise, rtindex should reference a leaf target relation that's being
                                820                 :      * added to the query during expand_inherited_rtentry().
                                821                 :      */
  739 tgl                       822 GIC        4547 :     Assert(bms_is_member(rtindex, root->leaf_result_relids));
                                823            4547 :     Assert(root->append_rel_array[rtindex] != NULL);
  739 tgl                       824 ECB             : 
                                825                 :     /*
                                826                 :      * We have to find a matching RowIdentityVarInfo, or make one if there is
                                827                 :      * none.  To allow using equal() to match the vars, change the varno to
                                828                 :      * ROWID_VAR, leaving all else alone.
                                829                 :      */
  739 tgl                       830 GIC        4547 :     rowid_var = copyObject(orig_var);
                                831                 :     /* This could eventually become ChangeVarNodes() */
                                832            4547 :     rowid_var->varno = ROWID_VAR;
                                833                 : 
  739 tgl                       834 ECB             :     /* Look for an existing row-id column of the same name */
  739 tgl                       835 GIC        6878 :     foreach(lc, root->row_identity_vars)
  739 tgl                       836 ECB             :     {
  739 tgl                       837 CBC        4539 :         ridinfo = (RowIdentityVarInfo *) lfirst(lc);
  739 tgl                       838 GIC        4539 :         if (strcmp(rowid_name, ridinfo->rowidname) != 0)
                                839            2331 :             continue;
  739 tgl                       840 CBC        2208 :         if (equal(rowid_var, ridinfo->rowidvar))
  739 tgl                       841 ECB             :         {
                                842                 :             /* Found a match; we need only record that rtindex needs it too */
  739 tgl                       843 GIC        2208 :             ridinfo->rowidrels = bms_add_member(ridinfo->rowidrels, rtindex);
                                844            2208 :             return;
                                845                 :         }
                                846                 :         else
                                847                 :         {
  739 tgl                       848 ECB             :             /* Ooops, can't handle this */
  739 tgl                       849 LBC           0 :             elog(ERROR, "conflicting uses of row-identity name \"%s\"",
                                850                 :                  rowid_name);
                                851                 :         }
                                852                 :     }
                                853                 : 
                                854                 :     /* No request yet, so add a new RowIdentityVarInfo */
  739 tgl                       855 GIC        2339 :     ridinfo = makeNode(RowIdentityVarInfo);
  739 tgl                       856 CBC        2339 :     ridinfo->rowidvar = copyObject(rowid_var);
                                857                 :     /* for the moment, estimate width using just the datatype info */
                                858            2339 :     ridinfo->rowidwidth = get_typavgwidth(exprType((Node *) rowid_var),
                                859                 :                                           exprTypmod((Node *) rowid_var));
  739 tgl                       860 GIC        2339 :     ridinfo->rowidname = pstrdup(rowid_name);
  739 tgl                       861 CBC        2339 :     ridinfo->rowidrels = bms_make_singleton(rtindex);
                                862                 : 
                                863            2339 :     root->row_identity_vars = lappend(root->row_identity_vars, ridinfo);
  739 tgl                       864 ECB             : 
                                865                 :     /* Change rowid_var into a reference to this row_identity_vars entry */
  739 tgl                       866 CBC        2339 :     rowid_var->varattno = list_length(root->row_identity_vars);
                                867                 : 
                                868                 :     /* Push the ROWID_VAR reference variable into processed_tlist */
                                869            2339 :     tle = makeTargetEntry((Expr *) rowid_var,
                                870            2339 :                           list_length(root->processed_tlist) + 1,
                                871                 :                           pstrdup(rowid_name),
                                872                 :                           true);
  739 tgl                       873 GIC        2339 :     root->processed_tlist = lappend(root->processed_tlist, tle);
                                874                 : }
  739 tgl                       875 EUB             : 
                                876                 : /*
                                877                 :  * add_row_identity_columns
                                878                 :  *
                                879                 :  * This function adds the row identity columns needed by the core code.
                                880                 :  * FDWs might call add_row_identity_var() for themselves to add nonstandard
  739 tgl                       881 ECB             :  * columns.  (Duplicate requests are fine.)
                                882                 :  */
                                883                 : void
  739 tgl                       884 CBC       11118 : add_row_identity_columns(PlannerInfo *root, Index rtindex,
                                885                 :                          RangeTblEntry *target_rte,
  739 tgl                       886 ECB             :                          Relation target_relation)
                                887                 : {
  739 tgl                       888 GIC       11118 :     CmdType     commandType = root->parse->commandType;
  739 tgl                       889 CBC       11118 :     char        relkind = target_relation->rd_rel->relkind;
                                890                 :     Var        *var;
                                891                 : 
  377 alvherre                  892           11118 :     Assert(commandType == CMD_UPDATE || commandType == CMD_DELETE || commandType == CMD_MERGE);
                                893                 : 
  377 alvherre                  894 GIC       11118 :     if (commandType == CMD_MERGE ||
  377 alvherre                  895 CBC         315 :         relkind == RELKIND_RELATION ||
  739 tgl                       896             285 :         relkind == RELKIND_MATVIEW ||
                                897                 :         relkind == RELKIND_PARTITIONED_TABLE)
                                898                 :     {
  739 tgl                       899 ECB             :         /*
                                900                 :          * Emit CTID so that executor can find the row to merge, update or
                                901                 :          * delete.
                                902                 :          */
  739 tgl                       903 GIC       10845 :         var = makeVar(rtindex,
                                904                 :                       SelfItemPointerAttributeNumber,
                                905                 :                       TIDOID,
                                906                 :                       -1,
                                907                 :                       InvalidOid,
                                908                 :                       0);
                                909           10845 :         add_row_identity_var(root, var, rtindex, "ctid");
  739 tgl                       910 ECB             :     }
  739 tgl                       911 GIC         273 :     else if (relkind == RELKIND_FOREIGN_TABLE)
                                912                 :     {
                                913                 :         /*
  739 tgl                       914 ECB             :          * Let the foreign table's FDW add whatever junk TLEs it wants.
                                915                 :          */
                                916                 :         FdwRoutine *fdwroutine;
                                917                 : 
  739 tgl                       918 CBC         174 :         fdwroutine = GetFdwRoutineForRelation(target_relation, false);
                                919                 : 
                                920             174 :         if (fdwroutine->AddForeignUpdateTargets != NULL)
                                921             170 :             fdwroutine->AddForeignUpdateTargets(root, rtindex,
  739 tgl                       922 ECB             :                                                 target_rte, target_relation);
                                923                 : 
                                924                 :         /*
                                925                 :          * For UPDATE, we need to make the FDW fetch unchanged columns by
                                926                 :          * asking it to fetch a whole-row Var.  That's because the top-level
                                927                 :          * targetlist only contains entries for changed columns, but
                                928                 :          * ExecUpdate will need to build the complete new tuple.  (Actually,
                                929                 :          * we only really need this in UPDATEs that are not pushed to the
                                930                 :          * remote side, but it's hard to tell if that will be the case at the
                                931                 :          * point when this function is called.)
                                932                 :          *
                                933                 :          * We will also need the whole row if there are any row triggers, so
                                934                 :          * that the executor will have the "old" row to pass to the trigger.
                                935                 :          * Alas, this misses system columns.
                                936                 :          */
  739 tgl                       937 CBC         174 :         if (commandType == CMD_UPDATE ||
  739 tgl                       938 GIC          77 :             (target_relation->trigdesc &&
                                939              15 :              (target_relation->trigdesc->trig_delete_after_row ||
                                940               9 :               target_relation->trigdesc->trig_delete_before_row)))
                                941                 :         {
                                942             105 :             var = makeVar(rtindex,
                                943                 :                           InvalidAttrNumber,
  739 tgl                       944 ECB             :                           RECORDOID,
                                945                 :                           -1,
                                946                 :                           InvalidOid,
                                947                 :                           0);
  739 tgl                       948 GIC         105 :             add_row_identity_var(root, var, rtindex, "wholerow");
                                949                 :         }
                                950                 :     }
                                951           11118 : }
                                952                 : 
                                953                 : /*
                                954                 :  * distribute_row_identity_vars
                                955                 :  *
                                956                 :  * After we have finished identifying all the row identity columns
                                957                 :  * needed by an inherited UPDATE/DELETE/MERGE query, make sure that
                                958                 :  * these columns will be generated by all the target relations.
                                959                 :  *
                                960                 :  * This is more or less like what build_base_rel_tlists() does,
                                961                 :  * except that it would not understand what to do with ROWID_VAR Vars.
                                962                 :  * Since that function runs before inheritance relations are expanded,
  739 tgl                       963 ECB             :  * it will never see any such Vars anyway.
                                964                 :  */
                                965                 : void
  739 tgl                       966 CBC      128144 : distribute_row_identity_vars(PlannerInfo *root)
                                967                 : {
                                968          128144 :     Query      *parse = root->parse;
  739 tgl                       969 GIC      128144 :     int         result_relation = parse->resultRelation;
                                970                 :     RangeTblEntry *target_rte;
                                971                 :     RelOptInfo *target_rel;
                                972                 :     ListCell   *lc;
                                973                 : 
  377 alvherre                  974 ECB             :     /*
                                975                 :      * There's nothing to do if this isn't an inherited UPDATE/DELETE/MERGE.
                                976                 :      */
  377 alvherre                  977 CBC      128144 :     if (parse->commandType != CMD_UPDATE && parse->commandType != CMD_DELETE &&
  377 alvherre                  978 GIC      118595 :         parse->commandType != CMD_MERGE)
                                979                 :     {
  739 tgl                       980          118130 :         Assert(root->row_identity_vars == NIL);
                                981          118130 :         return;
                                982                 :     }
                                983           10014 :     target_rte = rt_fetch(result_relation, parse->rtable);
                                984           10014 :     if (!target_rte->inh)
                                985                 :     {
                                986            8848 :         Assert(root->row_identity_vars == NIL);
                                987            8848 :         return;
                                988                 :     }
                                989                 : 
                                990                 :     /*
                                991                 :      * Ordinarily, we expect that leaf result relation(s) will have added some
  739 tgl                       992 ECB             :      * ROWID_VAR Vars to the query.  However, it's possible that constraint
                                993                 :      * exclusion suppressed every leaf relation.  The executor will get upset
                                994                 :      * if the plan has no row identity columns at all, even though it will
                                995                 :      * certainly process no rows.  Handle this edge case by re-opening the top
                                996                 :      * result relation and adding the row identity columns it would have used,
                                997                 :      * as preprocess_targetlist() would have done if it weren't marked "inh".
                                998                 :      * Then re-run build_base_rel_tlists() to ensure that the added columns
                                999                 :      * get propagated to the relation's reltarget.  (This is a bit ugly, but
                               1000                 :      * it seems better to confine the ugliness and extra cycles to this
                               1001                 :      * unusual corner case.)
                               1002                 :      */
  739 tgl                      1003 CBC        1166 :     if (root->row_identity_vars == NIL)
  739 tgl                      1004 ECB             :     {
                               1005                 :         Relation    target_relation;
                               1006                 : 
  739 tgl                      1007 CBC          15 :         target_relation = table_open(target_rte->relid, NoLock);
  739 tgl                      1008 GIC          15 :         add_row_identity_columns(root, result_relation,
  739 tgl                      1009 ECB             :                                  target_rte, target_relation);
  739 tgl                      1010 CBC          15 :         table_close(target_relation, NoLock);
   12 tgl                      1011 GIC          15 :         build_base_rel_tlists(root, root->processed_tlist);
   12 tgl                      1012 ECB             :         /* There are no ROWID_VAR Vars in this case, so we're done. */
  739 tgl                      1013 CBC          15 :         return;
                               1014                 :     }
                               1015                 : 
                               1016                 :     /*
                               1017                 :      * Dig through the processed_tlist to find the ROWID_VAR reference Vars,
                               1018                 :      * and forcibly copy them into the reltarget list of the topmost target
                               1019                 :      * relation.  That's sufficient because they'll be copied to the
                               1020                 :      * individual leaf target rels (with appropriate translation) later,
                               1021                 :      * during appendrel expansion --- see set_append_rel_size().
                               1022                 :      */
  739 tgl                      1023 GIC        1151 :     target_rel = find_base_rel(root, result_relation);
                               1024                 : 
                               1025            4763 :     foreach(lc, root->processed_tlist)
                               1026                 :     {
                               1027            3612 :         TargetEntry *tle = lfirst(lc);
                               1028            3612 :         Var        *var = (Var *) tle->expr;
  739 tgl                      1029 ECB             : 
  739 tgl                      1030 GIC        3612 :         if (var && IsA(var, Var) && var->varno == ROWID_VAR)
                               1031                 :         {
                               1032            2339 :             target_rel->reltarget->exprs =
  739 tgl                      1033 CBC        2339 :                 lappend(target_rel->reltarget->exprs, copyObject(var));
  739 tgl                      1034 ECB             :             /* reltarget cost and width will be computed later */
                               1035                 :         }
                               1036                 :     }
                               1037                 : }
        

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