PostgreSQL Source Code  git master
appendinfo.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/appendinfo.h"
#include "parser/parsetree.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for appendinfo.c:

Go to the source code of this file.

Data Structures

struct  adjust_appendrel_attrs_context
 

Functions

static void make_inh_translation_list (Relation oldrelation, Relation newrelation, Index newvarno, AppendRelInfo *appinfo)
 
static Nodeadjust_appendrel_attrs_mutator (Node *node, adjust_appendrel_attrs_context *context)
 
static Listadjust_inherited_tlist (List *tlist, AppendRelInfo *context)
 
AppendRelInfomake_append_rel_info (Relation parentrel, Relation childrel, Index parentRTindex, Index childRTindex)
 
Nodeadjust_appendrel_attrs (PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
 
Nodeadjust_appendrel_attrs_multilevel (PlannerInfo *root, Node *node, Relids child_relids, Relids top_parent_relids)
 
Relids adjust_child_relids (Relids relids, int nappinfos, AppendRelInfo **appinfos)
 
Relids adjust_child_relids_multilevel (PlannerInfo *root, Relids relids, Relids child_relids, Relids top_parent_relids)
 
AppendRelInfo ** find_appinfos_by_relids (PlannerInfo *root, Relids relids, int *nappinfos)
 

Function Documentation

◆ adjust_appendrel_attrs()

Node* adjust_appendrel_attrs ( PlannerInfo root,
Node node,
int  nappinfos,
AppendRelInfo **  appinfos 
)

Definition at line 194 of file appendinfo.c.

References adjust_appendrel_attrs_mutator(), adjust_inherited_tlist(), adjust_appendrel_attrs_context::appinfos, Assert, AppendRelInfo::child_relid, CMD_UPDATE, Query::commandType, IsA, adjust_appendrel_attrs_context::nappinfos, AppendRelInfo::parent_relid, QTW_IGNORE_RC_SUBQUERIES, query_tree_mutator(), Query::resultRelation, adjust_appendrel_attrs_context::root, and Query::targetList.

Referenced by add_child_join_rel_equivalences(), add_child_rel_equivalences(), adjust_appendrel_attrs_multilevel(), apply_child_basequals(), apply_scanjoin_target_to_paths(), build_child_join_rel(), build_child_join_reltarget(), build_child_join_sjinfo(), create_partitionwise_grouping_paths(), inheritance_planner(), make_partitionedrel_pruneinfo(), set_append_rel_size(), and try_partitionwise_join().

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 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
static List * adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
Definition: appendinfo.c:640
int resultRelation
Definition: parsenodes.h:122
Definition: nodes.h:528
List * targetList
Definition: parsenodes.h:140
#define QTW_IGNORE_RC_SUBQUERIES
Definition: nodeFuncs.h:22
static Node * adjust_appendrel_attrs_mutator(Node *node, adjust_appendrel_attrs_context *context)
Definition: appendinfo.c:244
CmdType commandType
Definition: parsenodes.h:112
#define Assert(condition)
Definition: c.h:746
AppendRelInfo ** appinfos
Definition: appendinfo.c:31
Index child_relid
Definition: pathnodes.h:2229
Index parent_relid
Definition: pathnodes.h:2228
Query * query_tree_mutator(Query *query, Node *(*mutator)(), void *context, int flags)
Definition: nodeFuncs.c:3251

◆ adjust_appendrel_attrs_multilevel()

Node* adjust_appendrel_attrs_multilevel ( PlannerInfo root,
Node node,
Relids  child_relids,
Relids  top_parent_relids 
)

Definition at line 502 of file appendinfo.c.

References adjust_appendrel_attrs(), adjust_appendrel_attrs_multilevel(), Assert, bms_add_member(), bms_equal(), bms_num_members(), find_appinfos_by_relids(), AppendRelInfo::parent_relid, and pfree().

Referenced by add_child_join_rel_equivalences(), add_child_rel_equivalences(), adjust_appendrel_attrs_multilevel(), generate_join_implied_equalities_broken(), and make_partitionedrel_pruneinfo().

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 }
Node * adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node, Relids child_relids, Relids top_parent_relids)
Definition: appendinfo.c:502
void pfree(void *pointer)
Definition: mcxt.c:1057
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:646
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Definition: appendinfo.c:728
#define Assert(condition)
Definition: c.h:746
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
Index parent_relid
Definition: pathnodes.h:2228
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

◆ adjust_appendrel_attrs_mutator()

static Node * adjust_appendrel_attrs_mutator ( Node node,
adjust_appendrel_attrs_context context 
)
static

Definition at line 244 of file appendinfo.c.

References adjust_child_relids(), adjust_appendrel_attrs_context::appinfos, ConvertRowtypeExpr::arg, RowExpr::args, Assert, AppendRelInfo::child_relid, AppendRelInfo::child_reltype, RestrictInfo::clause, RestrictInfo::clause_relids, COERCE_IMPLICIT_CAST, Alias::colnames, RowExpr::colnames, ConvertRowtypeExpr::convertformat, copyObject, CurrentOfExpr::cvarno, elog, RangeTblEntry::eref, ERROR, RestrictInfo::eval_cost, expression_tree_mutator(), get_rel_name(), IsA, RestrictInfo::left_bucketsize, RestrictInfo::left_em, RestrictInfo::left_mcvfreq, RestrictInfo::left_relids, list_length(), list_nth(), ConvertRowtypeExpr::location, RowExpr::location, makeNode, adjust_appendrel_attrs_context::nappinfos, NIL, RestrictInfo::norm_selec, RestrictInfo::nullable_relids, OidIsValid, RestrictInfo::orclause, RestrictInfo::outer_relids, RestrictInfo::outer_selec, AppendRelInfo::parent_relid, AppendRelInfo::parent_reloid, AppendRelInfo::parent_reltype, PlannerInfo::parse, PlaceHolderVar::phlevelsup, PlaceHolderVar::phrels, RestrictInfo::required_relids, ConvertRowtypeExpr::resulttype, RestrictInfo::right_bucketsize, RestrictInfo::right_em, RestrictInfo::right_mcvfreq, RestrictInfo::right_relids, adjust_appendrel_attrs_context::root, RowExpr::row_format, RowExpr::row_typeid, rt_fetch, Query::rtable, RangeTblRef::rtindex, JoinExpr::rtindex, RestrictInfo::scansel_cache, QualCost::startup, AppendRelInfo::translated_vars, Var::varattno, Var::varattnosyn, Var::varlevelsup, Var::varno, Var::varnosyn, and Var::vartype.

Referenced by adjust_appendrel_attrs().

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 }
QualCost eval_cost
Definition: pathnodes.h:2021
#define NIL
Definition: pg_list.h:65
List * args
Definition: primnodes.h:1025
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
Query * parse
Definition: pathnodes.h:177
Index varlevelsup
Definition: primnodes.h:191
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2565
Relids required_relids
Definition: pathnodes.h:2002
List * colnames
Definition: primnodes.h:43
Selectivity right_mcvfreq
Definition: pathnodes.h:2048
Expr * orclause
Definition: pathnodes.h:2015
Relids clause_relids
Definition: pathnodes.h:1999
Definition: nodes.h:528
Relids left_relids
Definition: pathnodes.h:2011
AttrNumber varattno
Definition: primnodes.h:186
Definition: primnodes.h:181
#define OidIsValid(objectId)
Definition: c.h:652
List * translated_vars
Definition: pathnodes.h:2256
Oid parent_reltype
Definition: pathnodes.h:2237
Cost startup
Definition: pathnodes.h:45
Relids outer_relids
Definition: pathnodes.h:2005
Selectivity norm_selec
Definition: pathnodes.h:2022
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
List * colnames
Definition: primnodes.h:1041
static void * list_nth(const List *list, int n)
Definition: pg_list.h:266
Oid vartype
Definition: primnodes.h:188
EquivalenceMember * left_em
Definition: pathnodes.h:2034
int location
Definition: primnodes.h:1042
Selectivity outer_selec
Definition: pathnodes.h:2025
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
Index varnosyn
Definition: primnodes.h:194
EquivalenceMember * right_em
Definition: pathnodes.h:2035
Expr * clause
Definition: pathnodes.h:1984
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:2008
AttrNumber varattnosyn
Definition: primnodes.h:195
CoercionForm convertformat
Definition: primnodes.h:889
Selectivity left_bucketsize
Definition: pathnodes.h:2045
#define makeNode(_type_)
Definition: nodes.h:576
Relids right_relids
Definition: pathnodes.h:2012
#define Assert(condition)
Definition: c.h:746
Selectivity left_mcvfreq
Definition: pathnodes.h:2047
Oid row_typeid
Definition: primnodes.h:1026
static int list_length(const List *l)
Definition: pg_list.h:149
AppendRelInfo ** appinfos
Definition: appendinfo.c:31
Index phlevelsup
Definition: pathnodes.h:2106
Selectivity right_bucketsize
Definition: pathnodes.h:2046
Relids adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:541
#define elog(elevel,...)
Definition: elog.h:214
Index child_relid
Definition: pathnodes.h:2229
Alias * eref
Definition: parsenodes.h:1116
#define copyObject(obj)
Definition: nodes.h:644
Index parent_relid
Definition: pathnodes.h:2228
CoercionForm row_format
Definition: primnodes.h:1040
int rtindex
Definition: primnodes.h:1498
Definition: pg_list.h:50
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1840
List * scansel_cache
Definition: pathnodes.h:2036

◆ adjust_child_relids()

Relids adjust_child_relids ( Relids  relids,
int  nappinfos,
AppendRelInfo **  appinfos 
)

Definition at line 541 of file appendinfo.c.

References bms_add_member(), bms_copy(), bms_del_member(), bms_is_member(), AppendRelInfo::child_relid, and AppendRelInfo::parent_relid.

Referenced by adjust_appendrel_attrs_mutator(), adjust_child_relids_multilevel(), and build_child_join_sjinfo().

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 }
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:74
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
Index child_relid
Definition: pathnodes.h:2229
Index parent_relid
Definition: pathnodes.h:2228
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition: bitmapset.c:773
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427

◆ adjust_child_relids_multilevel()

Relids adjust_child_relids_multilevel ( PlannerInfo root,
Relids  relids,
Relids  child_relids,
Relids  top_parent_relids 
)

Definition at line 576 of file appendinfo.c.

References adjust_child_relids(), adjust_child_relids_multilevel(), bms_add_member(), bms_equal(), bms_free(), bms_overlap(), find_appinfos_by_relids(), AppendRelInfo::parent_relid, and pfree().

Referenced by add_child_join_rel_equivalences(), adjust_child_relids_multilevel(), and reparameterize_path_by_child().

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 }
Relids adjust_child_relids_multilevel(PlannerInfo *root, Relids relids, Relids child_relids, Relids top_parent_relids)
Definition: appendinfo.c:576
void pfree(void *pointer)
Definition: mcxt.c:1057
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Definition: appendinfo.c:728
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:494
Relids adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:541
Index parent_relid
Definition: pathnodes.h:2228
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:94

◆ adjust_inherited_tlist()

static List * adjust_inherited_tlist ( List tlist,
AppendRelInfo context 
)
static

Definition at line 640 of file appendinfo.c.

References Assert, elog, ERROR, get_rel_name(), IsA, lappend(), lfirst, list_length(), list_nth(), NIL, OidIsValid, AppendRelInfo::parent_reloid, TargetEntry::resjunk, TargetEntry::resno, AppendRelInfo::translated_vars, and Var::varattno.

Referenced by adjust_appendrel_attrs().

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 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
AttrNumber varattno
Definition: primnodes.h:186
Definition: primnodes.h:181
#define OidIsValid(objectId)
Definition: c.h:652
List * translated_vars
Definition: pathnodes.h:2256
bool resjunk
Definition: primnodes.h:1417
#define ERROR
Definition: elog.h:43
static void * list_nth(const List *list, int n)
Definition: pg_list.h:266
AttrNumber resno
Definition: primnodes.h:1411
List * lappend(List *list, void *datum)
Definition: list.c:321
#define Assert(condition)
Definition: c.h:746
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
#define elog(elevel,...)
Definition: elog.h:214
Definition: pg_list.h:50
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1840

◆ find_appinfos_by_relids()

AppendRelInfo** find_appinfos_by_relids ( PlannerInfo root,
Relids  relids,
int *  nappinfos 
)

Definition at line 728 of file appendinfo.c.

References PlannerInfo::append_rel_array, bms_next_member(), bms_num_members(), elog, ERROR, i, and palloc().

Referenced by adjust_appendrel_attrs_multilevel(), adjust_child_relids_multilevel(), apply_scanjoin_target_to_paths(), build_child_join_rel(), build_child_join_sjinfo(), create_partitionwise_grouping_paths(), make_partitionedrel_pruneinfo(), and try_partitionwise_join().

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 }
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1043
#define ERROR
Definition: elog.h:43
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:646
struct AppendRelInfo ** append_rel_array
Definition: pathnodes.h:217
void * palloc(Size size)
Definition: mcxt.c:950
#define elog(elevel,...)
Definition: elog.h:214
int i

◆ make_append_rel_info()

AppendRelInfo* make_append_rel_info ( Relation  parentrel,
Relation  childrel,
Index  parentRTindex,
Index  childRTindex 
)

Definition at line 49 of file appendinfo.c.

References AppendRelInfo::child_relid, AppendRelInfo::child_reltype, make_inh_translation_list(), makeNode, AppendRelInfo::parent_relid, AppendRelInfo::parent_reloid, AppendRelInfo::parent_reltype, RelationData::rd_rel, and RelationGetRelid.

Referenced by expand_single_inheritance_child().

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 }
static void make_inh_translation_list(Relation oldrelation, Relation newrelation, Index newvarno, AppendRelInfo *appinfo)
Definition: appendinfo.c:78
Form_pg_class rd_rel
Definition: rel.h:109
Oid parent_reltype
Definition: pathnodes.h:2237
#define makeNode(_type_)
Definition: nodes.h:576
Index child_relid
Definition: pathnodes.h:2229
Index parent_relid
Definition: pathnodes.h:2228
#define RelationGetRelid(relation)
Definition: rel.h:456

◆ make_inh_translation_list()

static void make_inh_translation_list ( Relation  oldrelation,
Relation  newrelation,
Index  newvarno,
AppendRelInfo appinfo 
)
static

Definition at line 78 of file appendinfo.c.

References Assert, attcollation, attname, attnum, atttypid, elog, ERROR, GETSTRUCT, HeapTupleIsValid, lappend(), makeVar(), NameStr, TupleDescData::natts, NIL, AppendRelInfo::num_child_cols, palloc0(), AppendRelInfo::parent_colnos, RelationGetDescr, RelationGetRelationName, RelationGetRelid, ReleaseSysCache(), SearchSysCacheAttName(), AppendRelInfo::translated_vars, and TupleDescAttr.

Referenced by make_append_rel_info().

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 }
#define NIL
Definition: pg_list.h:65
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
int num_child_cols
Definition: pathnodes.h:2264
#define RelationGetDescr(relation)
Definition: rel.h:482
AttrNumber * parent_colnos
Definition: pathnodes.h:2265
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
unsigned int Oid
Definition: postgres_ext.h:31
List * translated_vars
Definition: pathnodes.h:2256
signed int int32
Definition: c.h:363
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
Oid attcollation
Definition: pg_attribute.h:157
#define RelationGetRelationName(relation)
Definition: rel.h:490
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
Oid atttypid
Definition: pg_attribute.h:49
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
List * lappend(List *list, void *datum)
Definition: list.c:321
void * palloc0(Size size)
Definition: mcxt.c:981
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:746
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1257
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:623
Definition: regcomp.c:224
Definition: pg_list.h:50
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:456