PostgreSQL Source Code  git master
appendinfo.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * appendinfo.c
4  * Routines for mapping between append parent(s) and children
5  *
6  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/optimizer/path/appendinfo.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "access/htup_details.h"
18 #include "nodes/makefuncs.h"
19 #include "nodes/nodeFuncs.h"
20 #include "optimizer/appendinfo.h"
21 #include "parser/parsetree.h"
22 #include "utils/lsyscache.h"
23 #include "utils/rel.h"
24 #include "utils/syscache.h"
25 
26 
27 typedef struct
28 {
30  int nappinfos;
33 
34 static void make_inh_translation_list(Relation oldrelation,
35  Relation newrelation,
36  Index newvarno,
37  AppendRelInfo *appinfo);
40 static List *adjust_inherited_tlist(List *tlist,
41  AppendRelInfo *context);
42 
43 
44 /*
45  * make_append_rel_info
46  * Build an AppendRelInfo for the parent-child pair
47  */
50  Index parentRTindex, Index childRTindex)
51 {
53 
54  appinfo->parent_relid = parentRTindex;
55  appinfo->child_relid = childRTindex;
56  appinfo->parent_reltype = parentrel->rd_rel->reltype;
57  appinfo->child_reltype = childrel->rd_rel->reltype;
58  make_inh_translation_list(parentrel, childrel, childRTindex, appinfo);
59  appinfo->parent_reloid = RelationGetRelid(parentrel);
60 
61  return appinfo;
62 }
63 
64 /*
65  * make_inh_translation_list
66  * Build the list of translations from parent Vars to child Vars for
67  * an inheritance child, as well as a reverse-translation array.
68  *
69  * The reverse-translation array has an entry for each child relation
70  * column, which is either the 1-based index of the corresponding parent
71  * column, or 0 if there's no match (that happens for dropped child columns,
72  * as well as child columns beyond those of the parent, which are allowed in
73  * traditional inheritance though not partitioning).
74  *
75  * For paranoia's sake, we match type/collation as well as attribute name.
76  */
77 static void
78 make_inh_translation_list(Relation oldrelation, Relation newrelation,
79  Index newvarno,
80  AppendRelInfo *appinfo)
81 {
82  List *vars = NIL;
83  AttrNumber *pcolnos;
84  TupleDesc old_tupdesc = RelationGetDescr(oldrelation);
85  TupleDesc new_tupdesc = RelationGetDescr(newrelation);
86  Oid new_relid = RelationGetRelid(newrelation);
87  int oldnatts = old_tupdesc->natts;
88  int newnatts = new_tupdesc->natts;
89  int old_attno;
90  int new_attno = 0;
91 
92  /* Initialize reverse-translation array with all entries zero */
93  appinfo->num_child_cols = newnatts;
94  appinfo->parent_colnos = pcolnos =
95  (AttrNumber *) palloc0(newnatts * sizeof(AttrNumber));
96 
97  for (old_attno = 0; old_attno < oldnatts; old_attno++)
98  {
100  char *attname;
101  Oid atttypid;
102  int32 atttypmod;
104 
105  att = TupleDescAttr(old_tupdesc, old_attno);
106  if (att->attisdropped)
107  {
108  /* Just put NULL into this list entry */
109  vars = lappend(vars, NULL);
110  continue;
111  }
112  attname = NameStr(att->attname);
113  atttypid = att->atttypid;
114  atttypmod = att->atttypmod;
115  attcollation = att->attcollation;
116 
117  /*
118  * When we are generating the "translation list" for the parent table
119  * of an inheritance set, no need to search for matches.
120  */
121  if (oldrelation == newrelation)
122  {
123  vars = lappend(vars, makeVar(newvarno,
124  (AttrNumber) (old_attno + 1),
125  atttypid,
126  atttypmod,
127  attcollation,
128  0));
129  pcolnos[old_attno] = old_attno + 1;
130  continue;
131  }
132 
133  /*
134  * Otherwise we have to search for the matching column by name.
135  * There's no guarantee it'll have the same column position, because
136  * of cases like ALTER TABLE ADD COLUMN and multiple inheritance.
137  * However, in simple cases, the relative order of columns is mostly
138  * the same in both relations, so try the column of newrelation that
139  * follows immediately after the one that we just found, and if that
140  * fails, let syscache handle it.
141  */
142  if (new_attno >= newnatts ||
143  (att = TupleDescAttr(new_tupdesc, new_attno))->attisdropped ||
144  strcmp(attname, NameStr(att->attname)) != 0)
145  {
146  HeapTuple newtup;
147 
148  newtup = SearchSysCacheAttName(new_relid, attname);
149  if (!HeapTupleIsValid(newtup))
150  elog(ERROR, "could not find inherited attribute \"%s\" of relation \"%s\"",
151  attname, RelationGetRelationName(newrelation));
152  new_attno = ((Form_pg_attribute) GETSTRUCT(newtup))->attnum - 1;
153  Assert(new_attno >= 0 && new_attno < newnatts);
154  ReleaseSysCache(newtup);
155 
156  att = TupleDescAttr(new_tupdesc, new_attno);
157  }
158 
159  /* Found it, check type and collation match */
160  if (atttypid != att->atttypid || atttypmod != att->atttypmod)
161  elog(ERROR, "attribute \"%s\" of relation \"%s\" does not match parent's type",
162  attname, RelationGetRelationName(newrelation));
163  if (attcollation != att->attcollation)
164  elog(ERROR, "attribute \"%s\" of relation \"%s\" does not match parent's collation",
165  attname, RelationGetRelationName(newrelation));
166 
167  vars = lappend(vars, makeVar(newvarno,
168  (AttrNumber) (new_attno + 1),
169  atttypid,
170  atttypmod,
171  attcollation,
172  0));
173  pcolnos[new_attno] = old_attno + 1;
174  new_attno++;
175  }
176 
177  appinfo->translated_vars = vars;
178 }
179 
180 /*
181  * adjust_appendrel_attrs
182  * Copy the specified query or expression and translate Vars referring to a
183  * parent rel to refer to the corresponding child rel instead. We also
184  * update rtindexes appearing outside Vars, such as resultRelation and
185  * jointree relids.
186  *
187  * Note: this is only applied after conversion of sublinks to subplans,
188  * so we don't need to cope with recursion into sub-queries.
189  *
190  * Note: this is not hugely different from what pullup_replace_vars() does;
191  * maybe we should try to fold the two routines together.
192  */
193 Node *
194 adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos,
195  AppendRelInfo **appinfos)
196 {
197  Node *result;
199 
200  context.root = root;
201  context.nappinfos = nappinfos;
202  context.appinfos = appinfos;
203 
204  /* If there's nothing to adjust, don't call this function. */
205  Assert(nappinfos >= 1 && appinfos != NULL);
206 
207  /*
208  * Must be prepared to start with a Query or a bare expression tree.
209  */
210  if (node && IsA(node, Query))
211  {
212  Query *newnode;
213  int cnt;
214 
215  newnode = query_tree_mutator((Query *) node,
217  (void *) &context,
219  for (cnt = 0; cnt < nappinfos; cnt++)
220  {
221  AppendRelInfo *appinfo = appinfos[cnt];
222 
223  if (newnode->resultRelation == appinfo->parent_relid)
224  {
225  newnode->resultRelation = appinfo->child_relid;
226  /* Fix tlist resnos too, if it's inherited UPDATE */
227  if (newnode->commandType == CMD_UPDATE)
228  newnode->targetList =
230  appinfo);
231  break;
232  }
233  }
234 
235  result = (Node *) newnode;
236  }
237  else
238  result = adjust_appendrel_attrs_mutator(node, &context);
239 
240  return result;
241 }
242 
243 static Node *
246 {
247  AppendRelInfo **appinfos = context->appinfos;
248  int nappinfos = context->nappinfos;
249  int cnt;
250 
251  if (node == NULL)
252  return NULL;
253  if (IsA(node, Var))
254  {
255  Var *var = (Var *) copyObject(node);
256  AppendRelInfo *appinfo = NULL;
257 
258  if (var->varlevelsup != 0)
259  return (Node *) var; /* no changes needed */
260 
261  for (cnt = 0; cnt < nappinfos; cnt++)
262  {
263  if (var->varno == appinfos[cnt]->parent_relid)
264  {
265  appinfo = appinfos[cnt];
266  break;
267  }
268  }
269 
270  if (appinfo)
271  {
272  var->varno = appinfo->child_relid;
273  /* it's now a generated Var, so drop any syntactic labeling */
274  var->varnosyn = 0;
275  var->varattnosyn = 0;
276  if (var->varattno > 0)
277  {
278  Node *newnode;
279 
280  if (var->varattno > list_length(appinfo->translated_vars))
281  elog(ERROR, "attribute %d of relation \"%s\" does not exist",
282  var->varattno, get_rel_name(appinfo->parent_reloid));
283  newnode = copyObject(list_nth(appinfo->translated_vars,
284  var->varattno - 1));
285  if (newnode == NULL)
286  elog(ERROR, "attribute %d of relation \"%s\" does not exist",
287  var->varattno, get_rel_name(appinfo->parent_reloid));
288  return newnode;
289  }
290  else if (var->varattno == 0)
291  {
292  /*
293  * Whole-row Var: if we are dealing with named rowtypes, we
294  * can use a whole-row Var for the child table plus a coercion
295  * step to convert the tuple layout to the parent's rowtype.
296  * Otherwise we have to generate a RowExpr.
297  */
298  if (OidIsValid(appinfo->child_reltype))
299  {
300  Assert(var->vartype == appinfo->parent_reltype);
301  if (appinfo->parent_reltype != appinfo->child_reltype)
302  {
304 
305  r->arg = (Expr *) var;
306  r->resulttype = appinfo->parent_reltype;
308  r->location = -1;
309  /* Make sure the Var node has the right type ID, too */
310  var->vartype = appinfo->child_reltype;
311  return (Node *) r;
312  }
313  }
314  else
315  {
316  /*
317  * Build a RowExpr containing the translated variables.
318  *
319  * In practice var->vartype will always be RECORDOID here,
320  * so we need to come up with some suitable column names.
321  * We use the parent RTE's column names.
322  *
323  * Note: we can't get here for inheritance cases, so there
324  * is no need to worry that translated_vars might contain
325  * some dummy NULLs.
326  */
327  RowExpr *rowexpr;
328  List *fields;
329  RangeTblEntry *rte;
330 
331  rte = rt_fetch(appinfo->parent_relid,
332  context->root->parse->rtable);
333  fields = copyObject(appinfo->translated_vars);
334  rowexpr = makeNode(RowExpr);
335  rowexpr->args = fields;
336  rowexpr->row_typeid = var->vartype;
337  rowexpr->row_format = COERCE_IMPLICIT_CAST;
338  rowexpr->colnames = copyObject(rte->eref->colnames);
339  rowexpr->location = -1;
340 
341  return (Node *) rowexpr;
342  }
343  }
344  /* system attributes don't need any other translation */
345  }
346  return (Node *) var;
347  }
348  if (IsA(node, CurrentOfExpr))
349  {
350  CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
351 
352  for (cnt = 0; cnt < nappinfos; cnt++)
353  {
354  AppendRelInfo *appinfo = appinfos[cnt];
355 
356  if (cexpr->cvarno == appinfo->parent_relid)
357  {
358  cexpr->cvarno = appinfo->child_relid;
359  break;
360  }
361  }
362  return (Node *) cexpr;
363  }
364  if (IsA(node, RangeTblRef))
365  {
366  RangeTblRef *rtr = (RangeTblRef *) copyObject(node);
367 
368  for (cnt = 0; cnt < nappinfos; cnt++)
369  {
370  AppendRelInfo *appinfo = appinfos[cnt];
371 
372  if (rtr->rtindex == appinfo->parent_relid)
373  {
374  rtr->rtindex = appinfo->child_relid;
375  break;
376  }
377  }
378  return (Node *) rtr;
379  }
380  if (IsA(node, JoinExpr))
381  {
382  /* Copy the JoinExpr node with correct mutation of subnodes */
383  JoinExpr *j;
384  AppendRelInfo *appinfo;
385 
386  j = (JoinExpr *) expression_tree_mutator(node,
388  (void *) context);
389  /* now fix JoinExpr's rtindex (probably never happens) */
390  for (cnt = 0; cnt < nappinfos; cnt++)
391  {
392  appinfo = appinfos[cnt];
393 
394  if (j->rtindex == appinfo->parent_relid)
395  {
396  j->rtindex = appinfo->child_relid;
397  break;
398  }
399  }
400  return (Node *) j;
401  }
402  if (IsA(node, PlaceHolderVar))
403  {
404  /* Copy the PlaceHolderVar node with correct mutation of subnodes */
405  PlaceHolderVar *phv;
406 
409  (void *) context);
410  /* now fix PlaceHolderVar's relid sets */
411  if (phv->phlevelsup == 0)
412  phv->phrels = adjust_child_relids(phv->phrels, context->nappinfos,
413  context->appinfos);
414  return (Node *) phv;
415  }
416  /* Shouldn't need to handle planner auxiliary nodes here */
417  Assert(!IsA(node, SpecialJoinInfo));
418  Assert(!IsA(node, AppendRelInfo));
419  Assert(!IsA(node, PlaceHolderInfo));
420  Assert(!IsA(node, MinMaxAggInfo));
421 
422  /*
423  * We have to process RestrictInfo nodes specially. (Note: although
424  * set_append_rel_pathlist will hide RestrictInfos in the parent's
425  * baserestrictinfo list from us, it doesn't hide those in joininfo.)
426  */
427  if (IsA(node, RestrictInfo))
428  {
429  RestrictInfo *oldinfo = (RestrictInfo *) node;
430  RestrictInfo *newinfo = makeNode(RestrictInfo);
431 
432  /* Copy all flat-copiable fields */
433  memcpy(newinfo, oldinfo, sizeof(RestrictInfo));
434 
435  /* Recursively fix the clause itself */
436  newinfo->clause = (Expr *)
437  adjust_appendrel_attrs_mutator((Node *) oldinfo->clause, context);
438 
439  /* and the modified version, if an OR clause */
440  newinfo->orclause = (Expr *)
441  adjust_appendrel_attrs_mutator((Node *) oldinfo->orclause, context);
442 
443  /* adjust relid sets too */
444  newinfo->clause_relids = adjust_child_relids(oldinfo->clause_relids,
445  context->nappinfos,
446  context->appinfos);
448  context->nappinfos,
449  context->appinfos);
450  newinfo->outer_relids = adjust_child_relids(oldinfo->outer_relids,
451  context->nappinfos,
452  context->appinfos);
454  context->nappinfos,
455  context->appinfos);
456  newinfo->left_relids = adjust_child_relids(oldinfo->left_relids,
457  context->nappinfos,
458  context->appinfos);
459  newinfo->right_relids = adjust_child_relids(oldinfo->right_relids,
460  context->nappinfos,
461  context->appinfos);
462 
463  /*
464  * Reset cached derivative fields, since these might need to have
465  * different values when considering the child relation. Note we
466  * don't reset left_ec/right_ec: each child variable is implicitly
467  * equivalent to its parent, so still a member of the same EC if any.
468  */
469  newinfo->eval_cost.startup = -1;
470  newinfo->norm_selec = -1;
471  newinfo->outer_selec = -1;
472  newinfo->left_em = NULL;
473  newinfo->right_em = NULL;
474  newinfo->scansel_cache = NIL;
475  newinfo->left_bucketsize = -1;
476  newinfo->right_bucketsize = -1;
477  newinfo->left_mcvfreq = -1;
478  newinfo->right_mcvfreq = -1;
479 
480  return (Node *) newinfo;
481  }
482 
483  /*
484  * NOTE: we do not need to recurse into sublinks, because they should
485  * already have been converted to subplans before we see them.
486  */
487  Assert(!IsA(node, SubLink));
488  Assert(!IsA(node, Query));
489 
491  (void *) context);
492 }
493 
494 /*
495  * adjust_appendrel_attrs_multilevel
496  * Apply Var translations from a toplevel appendrel parent down to a child.
497  *
498  * In some cases we need to translate expressions referencing a parent relation
499  * to reference an appendrel child that's multiple levels removed from it.
500  */
501 Node *
503  Relids child_relids,
504  Relids top_parent_relids)
505 {
506  AppendRelInfo **appinfos;
507  Bitmapset *parent_relids = NULL;
508  int nappinfos;
509  int cnt;
510 
511  Assert(bms_num_members(child_relids) == bms_num_members(top_parent_relids));
512 
513  appinfos = find_appinfos_by_relids(root, child_relids, &nappinfos);
514 
515  /* Construct relids set for the immediate parent of given child. */
516  for (cnt = 0; cnt < nappinfos; cnt++)
517  {
518  AppendRelInfo *appinfo = appinfos[cnt];
519 
520  parent_relids = bms_add_member(parent_relids, appinfo->parent_relid);
521  }
522 
523  /* Recurse if immediate parent is not the top parent. */
524  if (!bms_equal(parent_relids, top_parent_relids))
525  node = adjust_appendrel_attrs_multilevel(root, node, parent_relids,
526  top_parent_relids);
527 
528  /* Now translate for this child */
529  node = adjust_appendrel_attrs(root, node, nappinfos, appinfos);
530 
531  pfree(appinfos);
532 
533  return node;
534 }
535 
536 /*
537  * Substitute child relids for parent relids in a Relid set. The array of
538  * appinfos specifies the substitutions to be performed.
539  */
540 Relids
541 adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
542 {
543  Bitmapset *result = NULL;
544  int cnt;
545 
546  for (cnt = 0; cnt < nappinfos; cnt++)
547  {
548  AppendRelInfo *appinfo = appinfos[cnt];
549 
550  /* Remove parent, add child */
551  if (bms_is_member(appinfo->parent_relid, relids))
552  {
553  /* Make a copy if we are changing the set. */
554  if (!result)
555  result = bms_copy(relids);
556 
557  result = bms_del_member(result, appinfo->parent_relid);
558  result = bms_add_member(result, appinfo->child_relid);
559  }
560  }
561 
562  /* If we made any changes, return the modified copy. */
563  if (result)
564  return result;
565 
566  /* Otherwise, return the original set without modification. */
567  return relids;
568 }
569 
570 /*
571  * Replace any relid present in top_parent_relids with its child in
572  * child_relids. Members of child_relids can be multiple levels below top
573  * parent in the partition hierarchy.
574  */
575 Relids
577  Relids child_relids, Relids top_parent_relids)
578 {
579  AppendRelInfo **appinfos;
580  int nappinfos;
581  Relids parent_relids = NULL;
582  Relids result;
583  Relids tmp_result = NULL;
584  int cnt;
585 
586  /*
587  * If the given relids set doesn't contain any of the top parent relids,
588  * it will remain unchanged.
589  */
590  if (!bms_overlap(relids, top_parent_relids))
591  return relids;
592 
593  appinfos = find_appinfos_by_relids(root, child_relids, &nappinfos);
594 
595  /* Construct relids set for the immediate parent of the given child. */
596  for (cnt = 0; cnt < nappinfos; cnt++)
597  {
598  AppendRelInfo *appinfo = appinfos[cnt];
599 
600  parent_relids = bms_add_member(parent_relids, appinfo->parent_relid);
601  }
602 
603  /* Recurse if immediate parent is not the top parent. */
604  if (!bms_equal(parent_relids, top_parent_relids))
605  {
606  tmp_result = adjust_child_relids_multilevel(root, relids,
607  parent_relids,
608  top_parent_relids);
609  relids = tmp_result;
610  }
611 
612  result = adjust_child_relids(relids, nappinfos, appinfos);
613 
614  /* Free memory consumed by any intermediate result. */
615  if (tmp_result)
616  bms_free(tmp_result);
617  bms_free(parent_relids);
618  pfree(appinfos);
619 
620  return result;
621 }
622 
623 /*
624  * Adjust the targetlist entries of an inherited UPDATE operation
625  *
626  * The expressions have already been fixed, but we have to make sure that
627  * the target resnos match the child table (they may not, in the case of
628  * a column that was added after-the-fact by ALTER TABLE). In some cases
629  * this can force us to re-order the tlist to preserve resno ordering.
630  * (We do all this work in special cases so that preptlist.c is fast for
631  * the typical case.)
632  *
633  * The given tlist has already been through expression_tree_mutator;
634  * therefore the TargetEntry nodes are fresh copies that it's okay to
635  * scribble on.
636  *
637  * Note that this is not needed for INSERT because INSERT isn't inheritable.
638  */
639 static List *
641 {
642  bool changed_it = false;
643  ListCell *tl;
644  List *new_tlist;
645  bool more;
646  int attrno;
647 
648  /* This should only happen for an inheritance case, not UNION ALL */
649  Assert(OidIsValid(context->parent_reloid));
650 
651  /* Scan tlist and update resnos to match attnums of child rel */
652  foreach(tl, tlist)
653  {
654  TargetEntry *tle = (TargetEntry *) lfirst(tl);
655  Var *childvar;
656 
657  if (tle->resjunk)
658  continue; /* ignore junk items */
659 
660  /* Look up the translation of this column: it must be a Var */
661  if (tle->resno <= 0 ||
662  tle->resno > list_length(context->translated_vars))
663  elog(ERROR, "attribute %d of relation \"%s\" does not exist",
664  tle->resno, get_rel_name(context->parent_reloid));
665  childvar = (Var *) list_nth(context->translated_vars, tle->resno - 1);
666  if (childvar == NULL || !IsA(childvar, Var))
667  elog(ERROR, "attribute %d of relation \"%s\" does not exist",
668  tle->resno, get_rel_name(context->parent_reloid));
669 
670  if (tle->resno != childvar->varattno)
671  {
672  tle->resno = childvar->varattno;
673  changed_it = true;
674  }
675  }
676 
677  /*
678  * If we changed anything, re-sort the tlist by resno, and make sure
679  * resjunk entries have resnos above the last real resno. The sort
680  * algorithm is a bit stupid, but for such a seldom-taken path, small is
681  * probably better than fast.
682  */
683  if (!changed_it)
684  return tlist;
685 
686  new_tlist = NIL;
687  more = true;
688  for (attrno = 1; more; attrno++)
689  {
690  more = false;
691  foreach(tl, tlist)
692  {
693  TargetEntry *tle = (TargetEntry *) lfirst(tl);
694 
695  if (tle->resjunk)
696  continue; /* ignore junk items */
697 
698  if (tle->resno == attrno)
699  new_tlist = lappend(new_tlist, tle);
700  else if (tle->resno > attrno)
701  more = true;
702  }
703  }
704 
705  foreach(tl, tlist)
706  {
707  TargetEntry *tle = (TargetEntry *) lfirst(tl);
708 
709  if (!tle->resjunk)
710  continue; /* here, ignore non-junk items */
711 
712  tle->resno = attrno;
713  new_tlist = lappend(new_tlist, tle);
714  attrno++;
715  }
716 
717  return new_tlist;
718 }
719 
720 /*
721  * find_appinfos_by_relids
722  * Find AppendRelInfo structures for all relations specified by relids.
723  *
724  * The AppendRelInfos are returned in an array, which can be pfree'd by the
725  * caller. *nappinfos is set to the number of entries in the array.
726  */
727 AppendRelInfo **
728 find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
729 {
730  AppendRelInfo **appinfos;
731  int cnt = 0;
732  int i;
733 
734  *nappinfos = bms_num_members(relids);
735  appinfos = (AppendRelInfo **) palloc(sizeof(AppendRelInfo *) * *nappinfos);
736 
737  i = -1;
738  while ((i = bms_next_member(relids, i)) >= 0)
739  {
740  AppendRelInfo *appinfo = root->append_rel_array[i];
741 
742  if (!appinfo)
743  elog(ERROR, "child rel %d not found in append_rel_array", i);
744 
745  appinfos[cnt++] = appinfo;
746  }
747  return appinfos;
748 }
QualCost eval_cost
Definition: pathnodes.h:1982
#define NIL
Definition: pg_list.h:65
List * args
Definition: primnodes.h:1022
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Query * parse
Definition: pathnodes.h:179
Index varlevelsup
Definition: primnodes.h:191
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2516
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:74
static List * adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
Definition: appendinfo.c:640
Relids required_relids
Definition: pathnodes.h:1963
List * colnames
Definition: primnodes.h:43
int num_child_cols
Definition: pathnodes.h:2225
Selectivity right_mcvfreq
Definition: pathnodes.h:2009
#define RelationGetDescr(relation)
Definition: rel.h:454
Expr * orclause
Definition: pathnodes.h:1976
static void make_inh_translation_list(Relation oldrelation, Relation newrelation, Index newvarno, AppendRelInfo *appinfo)
Definition: appendinfo.c:78
AttrNumber * parent_colnos
Definition: pathnodes.h:2226
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Relids clause_relids
Definition: pathnodes.h:1960
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1043
int resultRelation
Definition: parsenodes.h:122
Definition: nodes.h:525
Relids left_relids
Definition: pathnodes.h:1972
AttrNumber varattno
Definition: primnodes.h:186
Relids adjust_child_relids_multilevel(PlannerInfo *root, Relids relids, Relids child_relids, Relids top_parent_relids)
Definition: appendinfo.c:576
Form_pg_class rd_rel
Definition: rel.h:84
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:181
#define OidIsValid(objectId)
Definition: c.h:644
List * translated_vars
Definition: pathnodes.h:2217
Oid parent_reltype
Definition: pathnodes.h:2198
Cost startup
Definition: pathnodes.h:45
Relids outer_relids
Definition: pathnodes.h:1966
signed int int32
Definition: c.h:355
Selectivity norm_selec
Definition: pathnodes.h:1983
List * targetList
Definition: parsenodes.h:140
Node * adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node, Relids child_relids, Relids top_parent_relids)
Definition: appendinfo.c:502
#define QTW_IGNORE_RC_SUBQUERIES
Definition: nodeFuncs.h:22
void pfree(void *pointer)
Definition: mcxt.c:1056
bool resjunk
Definition: primnodes.h:1414
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
List * colnames
Definition: primnodes.h:1038
static void * list_nth(const List *list, int n)
Definition: pg_list.h:277
Oid vartype
Definition: primnodes.h:188
EquivalenceMember * left_em
Definition: pathnodes.h:1995
Oid attcollation
Definition: pg_attribute.h:164
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:646
int location
Definition: primnodes.h:1039
AttrNumber resno
Definition: primnodes.h:1408
#define RelationGetRelationName(relation)
Definition: rel.h:462
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
Selectivity outer_selec
Definition: pathnodes.h:1986
Oid atttypid
Definition: pg_attribute.h:49
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
Index varnosyn
Definition: primnodes.h:194
List * lappend(List *list, void *datum)
Definition: list.c:322
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Definition: appendinfo.c:728
EquivalenceMember * right_em
Definition: pathnodes.h:1996
Expr * clause
Definition: pathnodes.h:1945
static Node * adjust_appendrel_attrs_mutator(Node *node, adjust_appendrel_attrs_context *context)
Definition: appendinfo.c:244
Index varno
Definition: primnodes.h:184
Relids nullable_relids
Definition: pathnodes.h:1969
void * palloc0(Size size)
Definition: mcxt.c:980
AttrNumber varattnosyn
Definition: primnodes.h:195
CoercionForm convertformat
Definition: primnodes.h:886
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
struct AppendRelInfo ** append_rel_array
Definition: pathnodes.h:219
unsigned int Index
Definition: c.h:475
int16 attnum
Definition: pg_attribute.h:79
CmdType commandType
Definition: parsenodes.h:112
Selectivity left_bucketsize
Definition: pathnodes.h:2006
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208
#define makeNode(_type_)
Definition: nodes.h:573
Relids right_relids
Definition: pathnodes.h:1973
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:738
#define lfirst(lc)
Definition: pg_list.h:190
Selectivity left_mcvfreq
Definition: pathnodes.h:2008
Oid row_typeid
Definition: primnodes.h:1023
static int list_length(const List *l)
Definition: pg_list.h:169
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1257
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
AppendRelInfo ** appinfos
Definition: appendinfo.c:31
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:494
Index phlevelsup
Definition: pathnodes.h:2067
Selectivity right_bucketsize
Definition: pathnodes.h:2007
void * palloc(Size size)
Definition: mcxt.c:949
Relids adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:541
#define elog(elevel,...)
Definition: elog.h:228
int i
#define NameStr(name)
Definition: c.h:615
Index child_relid
Definition: pathnodes.h:2190
Alias * eref
Definition: parsenodes.h:1113
#define copyObject(obj)
Definition: nodes.h:641
Index parent_relid
Definition: pathnodes.h:2189
CoercionForm row_format
Definition: primnodes.h:1037
Definition: regcomp.c:224
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition: bitmapset.c:773
int rtindex
Definition: primnodes.h:1495
Definition: pg_list.h:50
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1730
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:428
AppendRelInfo * make_append_rel_info(Relation parentrel, Relation childrel, Index parentRTindex, Index childRTindex)
Definition: appendinfo.c:49
Query * query_tree_mutator(Query *query, Node *(*mutator)(), void *context, int flags)
Definition: nodeFuncs.c:3202
List * scansel_cache
Definition: pathnodes.h:1997
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:94
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:194