PostgreSQL Source Code  git master
subselect.h File Reference
#include "nodes/plannodes.h"
#include "nodes/relation.h"
Include dependency graph for subselect.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void SS_process_ctes (PlannerInfo *root)
 
JoinExprconvert_ANY_sublink_to_join (PlannerInfo *root, SubLink *sublink, Relids available_rels)
 
JoinExprconvert_EXISTS_sublink_to_join (PlannerInfo *root, SubLink *sublink, bool under_not, Relids available_rels)
 
NodeSS_replace_correlation_vars (PlannerInfo *root, Node *expr)
 
NodeSS_process_sublinks (PlannerInfo *root, Node *expr, bool isQual)
 
void SS_identify_outer_params (PlannerInfo *root)
 
void SS_charge_for_initplans (PlannerInfo *root, RelOptInfo *final_rel)
 
void SS_attach_initplans (PlannerInfo *root, Plan *plan)
 
void SS_finalize_plan (PlannerInfo *root, Plan *plan)
 
ParamSS_make_initplan_output_param (PlannerInfo *root, Oid resulttype, int32 resulttypmod, Oid resultcollation)
 
void SS_make_initplan_from_plan (PlannerInfo *root, PlannerInfo *subroot, Plan *plan, Param *prm)
 
Paramassign_nestloop_param_var (PlannerInfo *root, Var *var)
 
Paramassign_nestloop_param_placeholdervar (PlannerInfo *root, PlaceHolderVar *phv)
 
int SS_assign_special_param (PlannerInfo *root)
 

Function Documentation

◆ assign_nestloop_param_placeholdervar()

Param* assign_nestloop_param_placeholdervar ( PlannerInfo root,
PlaceHolderVar phv 
)

Definition at line 283 of file subselect.c.

References Assert, assign_param_for_placeholdervar(), exprCollation(), exprType(), exprTypmod(), i, Param::location, makeNode, PARAM_EXEC, Param::paramcollid, Param::paramid, Param::paramkind, Param::paramtype, Param::paramtypmod, PlaceHolderVar::phexpr, and PlaceHolderVar::phlevelsup.

Referenced by replace_nestloop_params_mutator().

284 {
285  Param *retval;
286  int i;
287 
288  Assert(phv->phlevelsup == 0);
289 
290  i = assign_param_for_placeholdervar(root, phv);
291 
292  retval = makeNode(Param);
293  retval->paramkind = PARAM_EXEC;
294  retval->paramid = i;
295  retval->paramtype = exprType((Node *) phv->phexpr);
296  retval->paramtypmod = exprTypmod((Node *) phv->phexpr);
297  retval->paramcollid = exprCollation((Node *) phv->phexpr);
298  retval->location = -1;
299 
300  return retval;
301 }
static int assign_param_for_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
Definition: subselect.c:205
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:276
ParamKind paramkind
Definition: primnodes.h:244
Definition: nodes.h:511
Expr * phexpr
Definition: relation.h:1940
Oid paramcollid
Definition: primnodes.h:248
int location
Definition: primnodes.h:249
int32 paramtypmod
Definition: primnodes.h:247
#define makeNode(_type_)
Definition: nodes.h:559
#define Assert(condition)
Definition: c.h:670
int paramid
Definition: primnodes.h:245
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:720
Index phlevelsup
Definition: relation.h:1943
int i
Oid paramtype
Definition: primnodes.h:246

◆ assign_nestloop_param_var()

Param* assign_nestloop_param_var ( PlannerInfo root,
Var var 
)

Definition at line 177 of file subselect.c.

References Assert, assign_param_for_var(), i, Var::location, Param::location, makeNode, PARAM_EXEC, Param::paramcollid, Param::paramid, Param::paramkind, Param::paramtype, Param::paramtypmod, Var::varcollid, Var::varlevelsup, Var::vartype, and Var::vartypmod.

Referenced by replace_nestloop_params_mutator().

178 {
179  Param *retval;
180  int i;
181 
182  Assert(var->varlevelsup == 0);
183 
184  i = assign_param_for_var(root, var);
185 
186  retval = makeNode(Param);
187  retval->paramkind = PARAM_EXEC;
188  retval->paramid = i;
189  retval->paramtype = var->vartype;
190  retval->paramtypmod = var->vartypmod;
191  retval->paramcollid = var->varcollid;
192  retval->location = var->location;
193 
194  return retval;
195 }
Index varlevelsup
Definition: primnodes.h:173
static int assign_param_for_var(PlannerInfo *root, Var *var)
Definition: subselect.c:95
ParamKind paramkind
Definition: primnodes.h:244
Oid paramcollid
Definition: primnodes.h:248
int location
Definition: primnodes.h:249
Oid vartype
Definition: primnodes.h:170
int location
Definition: primnodes.h:178
int32 paramtypmod
Definition: primnodes.h:247
#define makeNode(_type_)
Definition: nodes.h:559
#define Assert(condition)
Definition: c.h:670
int paramid
Definition: primnodes.h:245
int i
Oid varcollid
Definition: primnodes.h:172
Oid paramtype
Definition: primnodes.h:246
int32 vartypmod
Definition: primnodes.h:171

◆ convert_ANY_sublink_to_join()

JoinExpr* convert_ANY_sublink_to_join ( PlannerInfo root,
SubLink sublink,
Relids  available_rels 
)

Definition at line 1317 of file subselect.c.

References addRangeTableEntryForSubquery(), JoinExpr::alias, ANY_SUBLINK, Assert, bms_is_empty(), bms_is_subset(), contain_vars_of_level(), contain_volatile_functions(), convert_testexpr(), generate_subquery_vars(), JoinExpr::isNatural, JOIN_SEMI, JoinExpr::jointype, lappend(), JoinExpr::larg, list_length(), make_parsestate(), makeAlias(), makeNode, NIL, parse(), PlannerInfo::parse, pull_varnos(), JoinExpr::quals, JoinExpr::rarg, Query::rtable, JoinExpr::rtindex, SubLink::subLinkType, SubLink::subselect, SubLink::testexpr, and JoinExpr::usingClause.

Referenced by pull_up_sublinks_qual_recurse().

1319 {
1320  JoinExpr *result;
1321  Query *parse = root->parse;
1322  Query *subselect = (Query *) sublink->subselect;
1323  Relids upper_varnos;
1324  int rtindex;
1325  RangeTblEntry *rte;
1326  RangeTblRef *rtr;
1327  List *subquery_vars;
1328  Node *quals;
1329  ParseState *pstate;
1330 
1331  Assert(sublink->subLinkType == ANY_SUBLINK);
1332 
1333  /*
1334  * The sub-select must not refer to any Vars of the parent query. (Vars of
1335  * higher levels should be okay, though.)
1336  */
1337  if (contain_vars_of_level((Node *) subselect, 1))
1338  return NULL;
1339 
1340  /*
1341  * The test expression must contain some Vars of the parent query, else
1342  * it's not gonna be a join. (Note that it won't have Vars referring to
1343  * the subquery, rather Params.)
1344  */
1345  upper_varnos = pull_varnos(sublink->testexpr);
1346  if (bms_is_empty(upper_varnos))
1347  return NULL;
1348 
1349  /*
1350  * However, it can't refer to anything outside available_rels.
1351  */
1352  if (!bms_is_subset(upper_varnos, available_rels))
1353  return NULL;
1354 
1355  /*
1356  * The combining operators and left-hand expressions mustn't be volatile.
1357  */
1358  if (contain_volatile_functions(sublink->testexpr))
1359  return NULL;
1360 
1361  /* Create a dummy ParseState for addRangeTableEntryForSubquery */
1362  pstate = make_parsestate(NULL);
1363 
1364  /*
1365  * Okay, pull up the sub-select into upper range table.
1366  *
1367  * We rely here on the assumption that the outer query has no references
1368  * to the inner (necessarily true, other than the Vars that we build
1369  * below). Therefore this is a lot easier than what pull_up_subqueries has
1370  * to go through.
1371  */
1372  rte = addRangeTableEntryForSubquery(pstate,
1373  subselect,
1374  makeAlias("ANY_subquery", NIL),
1375  false,
1376  false);
1377  parse->rtable = lappend(parse->rtable, rte);
1378  rtindex = list_length(parse->rtable);
1379 
1380  /*
1381  * Form a RangeTblRef for the pulled-up sub-select.
1382  */
1383  rtr = makeNode(RangeTblRef);
1384  rtr->rtindex = rtindex;
1385 
1386  /*
1387  * Build a list of Vars representing the subselect outputs.
1388  */
1389  subquery_vars = generate_subquery_vars(root,
1390  subselect->targetList,
1391  rtindex);
1392 
1393  /*
1394  * Build the new join's qual expression, replacing Params with these Vars.
1395  */
1396  quals = convert_testexpr(root, sublink->testexpr, subquery_vars);
1397 
1398  /*
1399  * And finally, build the JoinExpr node.
1400  */
1401  result = makeNode(JoinExpr);
1402  result->jointype = JOIN_SEMI;
1403  result->isNatural = false;
1404  result->larg = NULL; /* caller must fill this in */
1405  result->rarg = (Node *) rtr;
1406  result->usingClause = NIL;
1407  result->quals = quals;
1408  result->alias = NULL;
1409  result->rtindex = 0; /* we don't need an RTE for it */
1410 
1411  return result;
1412 }
static Node * convert_testexpr(PlannerInfo *root, Node *testexpr, List *subst_nodes)
Definition: subselect.c:980
#define NIL
Definition: pg_list.h:69
Query * parse
Definition: relation.h:155
Definition: nodes.h:511
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:957
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
Node * larg
Definition: primnodes.h:1458
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:386
List * rtable
Definition: parsenodes.h:135
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:308
static List * generate_subquery_vars(PlannerInfo *root, List *tlist, Index varno)
Definition: subselect.c:951
Relids pull_varnos(Node *node)
Definition: var.c:95
List * lappend(List *list, void *datum)
Definition: list.c:128
RangeTblEntry * addRangeTableEntryForSubquery(ParseState *pstate, Query *subquery, Alias *alias, bool lateral, bool inFromCl)
bool isNatural
Definition: primnodes.h:1457
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:663
List * usingClause
Definition: primnodes.h:1460
Node * quals
Definition: primnodes.h:1461
#define makeNode(_type_)
Definition: nodes.h:559
Node * rarg
Definition: primnodes.h:1459
Alias * alias
Definition: primnodes.h:1462
JoinType jointype
Definition: primnodes.h:1456
#define Assert(condition)
Definition: c.h:670
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:369
static int list_length(const List *l)
Definition: pg_list.h:89
int rtindex
Definition: primnodes.h:1463
Definition: pg_list.h:45
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:649

◆ convert_EXISTS_sublink_to_join()

JoinExpr* convert_EXISTS_sublink_to_join ( PlannerInfo root,
SubLink sublink,
bool  under_not,
Relids  available_rels 
)

Definition at line 1422 of file subselect.c.

References JoinExpr::alias, Assert, bms_add_member(), bms_first_member(), bms_free(), bms_is_empty(), bms_is_subset(), contain_vars_of_level(), contain_volatile_functions(), copyObject, Query::cteList, EXISTS_SUBLINK, FromExpr::fromlist, IncrementVarSublevelsUp(), JoinExpr::isNatural, JOIN_ANTI, JOIN_SEMI, Query::jointree, JoinExpr::jointype, JoinExpr::larg, linitial, list_concat(), list_length(), makeNode, NIL, OffsetVarNodes(), parse(), PlannerInfo::parse, pull_varnos(), JoinExpr::quals, FromExpr::quals, JoinExpr::rarg, Query::rtable, JoinExpr::rtindex, simplify_EXISTS_query(), SubLink::subLinkType, SubLink::subselect, and JoinExpr::usingClause.

Referenced by pull_up_sublinks_qual_recurse().

1424 {
1425  JoinExpr *result;
1426  Query *parse = root->parse;
1427  Query *subselect = (Query *) sublink->subselect;
1428  Node *whereClause;
1429  int rtoffset;
1430  int varno;
1431  Relids clause_varnos;
1432  Relids upper_varnos;
1433 
1434  Assert(sublink->subLinkType == EXISTS_SUBLINK);
1435 
1436  /*
1437  * Can't flatten if it contains WITH. (We could arrange to pull up the
1438  * WITH into the parent query's cteList, but that risks changing the
1439  * semantics, since a WITH ought to be executed once per associated query
1440  * call.) Note that convert_ANY_sublink_to_join doesn't have to reject
1441  * this case, since it just produces a subquery RTE that doesn't have to
1442  * get flattened into the parent query.
1443  */
1444  if (subselect->cteList)
1445  return NULL;
1446 
1447  /*
1448  * Copy the subquery so we can modify it safely (see comments in
1449  * make_subplan).
1450  */
1451  subselect = copyObject(subselect);
1452 
1453  /*
1454  * See if the subquery can be simplified based on the knowledge that it's
1455  * being used in EXISTS(). If we aren't able to get rid of its
1456  * targetlist, we have to fail, because the pullup operation leaves us
1457  * with noplace to evaluate the targetlist.
1458  */
1459  if (!simplify_EXISTS_query(root, subselect))
1460  return NULL;
1461 
1462  /*
1463  * The subquery must have a nonempty jointree, else we won't have a join.
1464  */
1465  if (subselect->jointree->fromlist == NIL)
1466  return NULL;
1467 
1468  /*
1469  * Separate out the WHERE clause. (We could theoretically also remove
1470  * top-level plain JOIN/ON clauses, but it's probably not worth the
1471  * trouble.)
1472  */
1473  whereClause = subselect->jointree->quals;
1474  subselect->jointree->quals = NULL;
1475 
1476  /*
1477  * The rest of the sub-select must not refer to any Vars of the parent
1478  * query. (Vars of higher levels should be okay, though.)
1479  */
1480  if (contain_vars_of_level((Node *) subselect, 1))
1481  return NULL;
1482 
1483  /*
1484  * On the other hand, the WHERE clause must contain some Vars of the
1485  * parent query, else it's not gonna be a join.
1486  */
1487  if (!contain_vars_of_level(whereClause, 1))
1488  return NULL;
1489 
1490  /*
1491  * We don't risk optimizing if the WHERE clause is volatile, either.
1492  */
1493  if (contain_volatile_functions(whereClause))
1494  return NULL;
1495 
1496  /*
1497  * Prepare to pull up the sub-select into top range table.
1498  *
1499  * We rely here on the assumption that the outer query has no references
1500  * to the inner (necessarily true). Therefore this is a lot easier than
1501  * what pull_up_subqueries has to go through.
1502  *
1503  * In fact, it's even easier than what convert_ANY_sublink_to_join has to
1504  * do. The machinations of simplify_EXISTS_query ensured that there is
1505  * nothing interesting in the subquery except an rtable and jointree, and
1506  * even the jointree FromExpr no longer has quals. So we can just append
1507  * the rtable to our own and use the FromExpr in our jointree. But first,
1508  * adjust all level-zero varnos in the subquery to account for the rtable
1509  * merger.
1510  */
1511  rtoffset = list_length(parse->rtable);
1512  OffsetVarNodes((Node *) subselect, rtoffset, 0);
1513  OffsetVarNodes(whereClause, rtoffset, 0);
1514 
1515  /*
1516  * Upper-level vars in subquery will now be one level closer to their
1517  * parent than before; in particular, anything that had been level 1
1518  * becomes level zero.
1519  */
1520  IncrementVarSublevelsUp((Node *) subselect, -1, 1);
1521  IncrementVarSublevelsUp(whereClause, -1, 1);
1522 
1523  /*
1524  * Now that the WHERE clause is adjusted to match the parent query
1525  * environment, we can easily identify all the level-zero rels it uses.
1526  * The ones <= rtoffset belong to the upper query; the ones > rtoffset do
1527  * not.
1528  */
1529  clause_varnos = pull_varnos(whereClause);
1530  upper_varnos = NULL;
1531  while ((varno = bms_first_member(clause_varnos)) >= 0)
1532  {
1533  if (varno <= rtoffset)
1534  upper_varnos = bms_add_member(upper_varnos, varno);
1535  }
1536  bms_free(clause_varnos);
1537  Assert(!bms_is_empty(upper_varnos));
1538 
1539  /*
1540  * Now that we've got the set of upper-level varnos, we can make the last
1541  * check: only available_rels can be referenced.
1542  */
1543  if (!bms_is_subset(upper_varnos, available_rels))
1544  return NULL;
1545 
1546  /* Now we can attach the modified subquery rtable to the parent */
1547  parse->rtable = list_concat(parse->rtable, subselect->rtable);
1548 
1549  /*
1550  * And finally, build the JoinExpr node.
1551  */
1552  result = makeNode(JoinExpr);
1553  result->jointype = under_not ? JOIN_ANTI : JOIN_SEMI;
1554  result->isNatural = false;
1555  result->larg = NULL; /* caller must fill this in */
1556  /* flatten out the FromExpr node if it's useless */
1557  if (list_length(subselect->jointree->fromlist) == 1)
1558  result->rarg = (Node *) linitial(subselect->jointree->fromlist);
1559  else
1560  result->rarg = (Node *) subselect->jointree;
1561  result->usingClause = NIL;
1562  result->quals = whereClause;
1563  result->alias = NULL;
1564  result->rtindex = 0; /* we don't need an RTE for it */
1565 
1566  return result;
1567 }
#define NIL
Definition: pg_list.h:69
int bms_first_member(Bitmapset *a)
Definition: bitmapset.c:885
Query * parse
Definition: relation.h:155
void OffsetVarNodes(Node *node, int offset, int sublevels_up)
Definition: rewriteManip.c:424
void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, int min_sublevels_up)
Definition: rewriteManip.c:773
FromExpr * jointree
Definition: parsenodes.h:136
Definition: nodes.h:511
List * list_concat(List *list1, List *list2)
Definition: list.c:321
List * fromlist
Definition: primnodes.h:1478
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:957
static bool simplify_EXISTS_query(PlannerInfo *root, Query *query)
Definition: subselect.c:1586
Node * quals
Definition: primnodes.h:1479
Node * larg
Definition: primnodes.h:1458
#define linitial(l)
Definition: pg_list.h:111
List * rtable
Definition: parsenodes.h:135
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:308
Relids pull_varnos(Node *node)
Definition: var.c:95
bool isNatural
Definition: primnodes.h:1457
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:663
List * usingClause
Definition: primnodes.h:1460
Node * quals
Definition: primnodes.h:1461
void bms_free(Bitmapset *a)
Definition: bitmapset.c:201
#define makeNode(_type_)
Definition: nodes.h:559
Node * rarg
Definition: primnodes.h:1459
Alias * alias
Definition: primnodes.h:1462
JoinType jointype
Definition: primnodes.h:1456
#define Assert(condition)
Definition: c.h:670
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:369
static int list_length(const List *l)
Definition: pg_list.h:89
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
List * cteList
Definition: parsenodes.h:133
#define copyObject(obj)
Definition: nodes.h:624
int rtindex
Definition: primnodes.h:1463
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:649

◆ SS_assign_special_param()

int SS_assign_special_param ( PlannerInfo root)

Definition at line 429 of file subselect.c.

References PlannerInfo::glob, InvalidOid, lappend_oid(), list_length(), and PlannerGlobal::paramExecTypes.

Referenced by create_gather_merge_plan(), create_gather_plan(), grouping_planner(), inheritance_planner(), SS_process_ctes(), and subquery_planner().

430 {
431  int paramId = list_length(root->glob->paramExecTypes);
432 
434  InvalidOid);
435  return paramId;
436 }
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
List * paramExecTypes
Definition: relation.h:117
PlannerGlobal * glob
Definition: relation.h:157
#define InvalidOid
Definition: postgres_ext.h:36
static int list_length(const List *l)
Definition: pg_list.h:89

◆ SS_attach_initplans()

void SS_attach_initplans ( PlannerInfo root,
Plan plan 
)

Definition at line 2220 of file subselect.c.

References PlannerInfo::init_plans, and Plan::initPlan.

Referenced by create_plan().

2221 {
2222  plan->initPlan = root->init_plans;
2223 }
List * init_plans
Definition: relation.h:228
List * initPlan
Definition: plannodes.h:148

◆ SS_charge_for_initplans()

void SS_charge_for_initplans ( PlannerInfo root,
RelOptInfo final_rel 
)

Definition at line 2170 of file subselect.c.

References PlannerInfo::init_plans, lfirst, NIL, Path::parallel_safe, RelOptInfo::pathlist, SubPlan::per_call_cost, SubPlan::startup_cost, Path::startup_cost, and Path::total_cost.

Referenced by build_minmax_path(), and subquery_planner().

2171 {
2172  Cost initplan_cost;
2173  ListCell *lc;
2174 
2175  /* Nothing to do if no initPlans */
2176  if (root->init_plans == NIL)
2177  return;
2178 
2179  /*
2180  * Compute the cost increment just once, since it will be the same for all
2181  * Paths. We assume each initPlan gets run once during top plan startup.
2182  * This is a conservative overestimate, since in fact an initPlan might be
2183  * executed later than plan startup, or even not at all.
2184  */
2185  initplan_cost = 0;
2186  foreach(lc, root->init_plans)
2187  {
2188  SubPlan *initsubplan = (SubPlan *) lfirst(lc);
2189 
2190  initplan_cost += initsubplan->startup_cost + initsubplan->per_call_cost;
2191  }
2192 
2193  /*
2194  * Now adjust the costs and parallel_safe flags.
2195  */
2196  foreach(lc, final_rel->pathlist)
2197  {
2198  Path *path = (Path *) lfirst(lc);
2199 
2200  path->startup_cost += initplan_cost;
2201  path->total_cost += initplan_cost;
2202  path->parallel_safe = false;
2203  }
2204 
2205  /* We needn't do set_cheapest() here, caller will do it */
2206 }
#define NIL
Definition: pg_list.h:69
Cost startup_cost
Definition: relation.h:1053
List * init_plans
Definition: relation.h:228
Cost per_call_cost
Definition: primnodes.h:713
Cost total_cost
Definition: relation.h:1054
#define lfirst(lc)
Definition: pg_list.h:106
bool parallel_safe
Definition: relation.h:1048
Cost startup_cost
Definition: primnodes.h:712
List * pathlist
Definition: relation.h:599
double Cost
Definition: nodes.h:642

◆ SS_finalize_plan()

void SS_finalize_plan ( PlannerInfo root,
Plan plan 
)

Definition at line 2235 of file subselect.c.

References finalize_plan(), and PlannerInfo::outer_params.

Referenced by finalize_plan(), and standard_planner().

2236 {
2237  /* No setup needed, just recurse through plan tree. */
2238  (void) finalize_plan(root, plan, -1, root->outer_params, NULL);
2239 }
static Bitmapset * finalize_plan(PlannerInfo *root, Plan *plan, int gather_param, Bitmapset *valid_params, Bitmapset *scan_params)
Definition: subselect.c:2273
Bitmapset * outer_params
Definition: relation.h:170

◆ SS_identify_outer_params()

void SS_identify_outer_params ( PlannerInfo root)

Definition at line 2108 of file subselect.c.

References bms_add_member(), PlannerInfo::glob, PlannerInfo::init_plans, lfirst, lfirst_int, NIL, PlannerInfo::outer_params, PlannerGlobal::paramExecTypes, PlannerParamItem::paramId, PlannerInfo::parent_root, PlannerInfo::plan_params, SubPlan::setParam, and PlannerInfo::wt_param_id.

Referenced by build_minmax_path(), and subquery_planner().

2109 {
2110  Bitmapset *outer_params;
2111  PlannerInfo *proot;
2112  ListCell *l;
2113 
2114  /*
2115  * If no parameters have been assigned anywhere in the tree, we certainly
2116  * don't need to do anything here.
2117  */
2118  if (root->glob->paramExecTypes == NIL)
2119  return;
2120 
2121  /*
2122  * Scan all query levels above this one to see which parameters are due to
2123  * be available from them, either because lower query levels have
2124  * requested them (via plan_params) or because they will be available from
2125  * initPlans of those levels.
2126  */
2127  outer_params = NULL;
2128  for (proot = root->parent_root; proot != NULL; proot = proot->parent_root)
2129  {
2130  /* Include ordinary Var/PHV/Aggref params */
2131  foreach(l, proot->plan_params)
2132  {
2133  PlannerParamItem *pitem = (PlannerParamItem *) lfirst(l);
2134 
2135  outer_params = bms_add_member(outer_params, pitem->paramId);
2136  }
2137  /* Include any outputs of outer-level initPlans */
2138  foreach(l, proot->init_plans)
2139  {
2140  SubPlan *initsubplan = (SubPlan *) lfirst(l);
2141  ListCell *l2;
2142 
2143  foreach(l2, initsubplan->setParam)
2144  {
2145  outer_params = bms_add_member(outer_params, lfirst_int(l2));
2146  }
2147  }
2148  /* Include worktable ID, if a recursive query is being planned */
2149  if (proot->wt_param_id >= 0)
2150  outer_params = bms_add_member(outer_params, proot->wt_param_id);
2151  }
2152  root->outer_params = outer_params;
2153 }
#define NIL
Definition: pg_list.h:69
List * plan_params
Definition: relation.h:169
int wt_param_id
Definition: relation.h:311
List * paramExecTypes
Definition: relation.h:117
#define lfirst_int(lc)
Definition: pg_list.h:107
PlannerGlobal * glob
Definition: relation.h:157
struct PlannerInfo * parent_root
Definition: relation.h:161
List * init_plans
Definition: relation.h:228
#define lfirst(lc)
Definition: pg_list.h:106
List * setParam
Definition: primnodes.h:707
Bitmapset * outer_params
Definition: relation.h:170
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698

◆ SS_make_initplan_from_plan()

void SS_make_initplan_from_plan ( PlannerInfo root,
PlannerInfo subroot,
Plan plan,
Param prm 
)

Definition at line 2984 of file subselect.c.

References cost_subplan(), EXPR_SUBLINK, SubPlan::firstColCollation, SubPlan::firstColType, SubPlan::firstColTypmod, get_first_col_type(), PlannerInfo::glob, PlannerInfo::init_plans, lappend(), list_length(), list_make1_int, makeNode, Param::paramid, SubPlan::plan_id, SubPlan::plan_name, psprintf(), SubPlan::setParam, SubPlan::subLinkType, PlannerGlobal::subplans, and PlannerGlobal::subroots.

Referenced by create_minmaxagg_plan().

2987 {
2988  SubPlan *node;
2989 
2990  /*
2991  * Add the subplan and its PlannerInfo to the global lists.
2992  */
2993  root->glob->subplans = lappend(root->glob->subplans, plan);
2994  root->glob->subroots = lappend(root->glob->subroots, subroot);
2995 
2996  /*
2997  * Create a SubPlan node and add it to the outer list of InitPlans. Note
2998  * it has to appear after any other InitPlans it might depend on (see
2999  * comments in ExecReScan).
3000  */
3001  node = makeNode(SubPlan);
3002  node->subLinkType = EXPR_SUBLINK;
3003  node->plan_id = list_length(root->glob->subplans);
3004  node->plan_name = psprintf("InitPlan %d (returns $%d)",
3005  node->plan_id, prm->paramid);
3006  get_first_col_type(plan, &node->firstColType, &node->firstColTypmod,
3007  &node->firstColCollation);
3008  node->setParam = list_make1_int(prm->paramid);
3009 
3010  root->init_plans = lappend(root->init_plans, node);
3011 
3012  /*
3013  * The node can't have any inputs (since it's an initplan), so the
3014  * parParam and args lists remain empty.
3015  */
3016 
3017  /* Set costs of SubPlan using info from the plan tree */
3018  cost_subplan(subroot, node, plan);
3019 }
Oid firstColType
Definition: primnodes.h:693
int plan_id
Definition: primnodes.h:689
static void get_first_col_type(Plan *plan, Oid *coltype, int32 *coltypmod, Oid *colcollation)
Definition: subselect.c:448
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
SubLinkType subLinkType
Definition: primnodes.h:684
List * subplans
Definition: relation.h:98
PlannerGlobal * glob
Definition: relation.h:157
#define list_make1_int(x1)
Definition: pg_list.h:145
List * lappend(List *list, void *datum)
Definition: list.c:128
List * init_plans
Definition: relation.h:228
int32 firstColTypmod
Definition: primnodes.h:694
#define makeNode(_type_)
Definition: nodes.h:559
char * plan_name
Definition: primnodes.h:691
List * setParam
Definition: primnodes.h:707
int paramid
Definition: primnodes.h:245
void cost_subplan(PlannerInfo *root, SubPlan *subplan, Plan *plan)
Definition: costsize.c:3308
static int list_length(const List *l)
Definition: pg_list.h:89
List * subroots
Definition: relation.h:100
Oid firstColCollation
Definition: primnodes.h:695

◆ SS_make_initplan_output_param()

Param* SS_make_initplan_output_param ( PlannerInfo root,
Oid  resulttype,
int32  resulttypmod,
Oid  resultcollation 
)

Definition at line 2969 of file subselect.c.

References generate_new_param().

Referenced by preprocess_minmax_aggregates().

2972 {
2973  return generate_new_param(root, resulttype, resulttypmod, resultcollation);
2974 }
static Param * generate_new_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod, Oid paramcollation)
Definition: subselect.c:402

◆ SS_process_ctes()

void SS_process_ctes ( PlannerInfo root)

Definition at line 1158 of file subselect.c.

References SubPlan::args, Assert, RelOptInfo::cheapest_total_path, CMD_SELECT, copyObject, cost_subplan(), create_plan(), PlannerInfo::cte_plan_ids, CTE_SUBLINK, Query::cteList, CommonTableExpr::ctename, CommonTableExpr::ctequery, CommonTableExpr::cterecursive, CommonTableExpr::cterefcount, elog, ERROR, fetch_upper_rel(), SubPlan::firstColCollation, SubPlan::firstColType, SubPlan::firstColTypmod, get_first_col_type(), PlannerInfo::glob, PlannerInfo::init_plans, lappend(), lappend_int(), lfirst, list_length(), list_make1_int, makeNode, NIL, SubPlan::parallel_safe, SubPlan::paramIds, SubPlan::parParam, PlannerInfo::parse, SubPlan::plan_id, SubPlan::plan_name, PlannerInfo::plan_params, psprintf(), SubPlan::setParam, splan, SS_assign_special_param(), SubPlan::subLinkType, PlannerGlobal::subplans, subquery_planner(), PlannerGlobal::subroots, SubPlan::testexpr, SubPlan::unknownEqFalse, UPPERREL_FINAL, and SubPlan::useHashTable.

Referenced by subquery_planner().

1159 {
1160  ListCell *lc;
1161 
1162  Assert(root->cte_plan_ids == NIL);
1163 
1164  foreach(lc, root->parse->cteList)
1165  {
1166  CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
1167  CmdType cmdType = ((Query *) cte->ctequery)->commandType;
1168  Query *subquery;
1169  PlannerInfo *subroot;
1170  RelOptInfo *final_rel;
1171  Path *best_path;
1172  Plan *plan;
1173  SubPlan *splan;
1174  int paramid;
1175 
1176  /*
1177  * Ignore SELECT CTEs that are not actually referenced anywhere.
1178  */
1179  if (cte->cterefcount == 0 && cmdType == CMD_SELECT)
1180  {
1181  /* Make a dummy entry in cte_plan_ids */
1182  root->cte_plan_ids = lappend_int(root->cte_plan_ids, -1);
1183  continue;
1184  }
1185 
1186  /*
1187  * Copy the source Query node. Probably not necessary, but let's keep
1188  * this similar to make_subplan.
1189  */
1190  subquery = (Query *) copyObject(cte->ctequery);
1191 
1192  /* plan_params should not be in use in current query level */
1193  Assert(root->plan_params == NIL);
1194 
1195  /*
1196  * Generate Paths for the CTE query. Always plan for full retrieval
1197  * --- we don't have enough info to predict otherwise.
1198  */
1199  subroot = subquery_planner(root->glob, subquery,
1200  root,
1201  cte->cterecursive, 0.0);
1202 
1203  /*
1204  * Since the current query level doesn't yet contain any RTEs, it
1205  * should not be possible for the CTE to have requested parameters of
1206  * this level.
1207  */
1208  if (root->plan_params)
1209  elog(ERROR, "unexpected outer reference in CTE query");
1210 
1211  /*
1212  * Select best Path and turn it into a Plan. At least for now, there
1213  * seems no reason to postpone doing that.
1214  */
1215  final_rel = fetch_upper_rel(subroot, UPPERREL_FINAL, NULL);
1216  best_path = final_rel->cheapest_total_path;
1217 
1218  plan = create_plan(subroot, best_path);
1219 
1220  /*
1221  * Make a SubPlan node for it. This is just enough unlike
1222  * build_subplan that we can't share code.
1223  *
1224  * Note plan_id, plan_name, and cost fields are set further down.
1225  */
1226  splan = makeNode(SubPlan);
1227  splan->subLinkType = CTE_SUBLINK;
1228  splan->testexpr = NULL;
1229  splan->paramIds = NIL;
1230  get_first_col_type(plan, &splan->firstColType, &splan->firstColTypmod,
1231  &splan->firstColCollation);
1232  splan->useHashTable = false;
1233  splan->unknownEqFalse = false;
1234 
1235  /*
1236  * CTE scans are not considered for parallelism (cf
1237  * set_rel_consider_parallel), and even if they were, initPlans aren't
1238  * parallel-safe.
1239  */
1240  splan->parallel_safe = false;
1241  splan->setParam = NIL;
1242  splan->parParam = NIL;
1243  splan->args = NIL;
1244 
1245  /*
1246  * The node can't have any inputs (since it's an initplan), so the
1247  * parParam and args lists remain empty. (It could contain references
1248  * to earlier CTEs' output param IDs, but CTE outputs are not
1249  * propagated via the args list.)
1250  */
1251 
1252  /*
1253  * Assign a param ID to represent the CTE's output. No ordinary
1254  * "evaluation" of this param slot ever happens, but we use the param
1255  * ID for setParam/chgParam signaling just as if the CTE plan were
1256  * returning a simple scalar output. (Also, the executor abuses the
1257  * ParamExecData slot for this param ID for communication among
1258  * multiple CteScan nodes that might be scanning this CTE.)
1259  */
1260  paramid = SS_assign_special_param(root);
1261  splan->setParam = list_make1_int(paramid);
1262 
1263  /*
1264  * Add the subplan and its PlannerInfo to the global lists.
1265  */
1266  root->glob->subplans = lappend(root->glob->subplans, plan);
1267  root->glob->subroots = lappend(root->glob->subroots, subroot);
1268  splan->plan_id = list_length(root->glob->subplans);
1269 
1270  root->init_plans = lappend(root->init_plans, splan);
1271 
1272  root->cte_plan_ids = lappend_int(root->cte_plan_ids, splan->plan_id);
1273 
1274  /* Label the subplan for EXPLAIN purposes */
1275  splan->plan_name = psprintf("CTE %s", cte->ctename);
1276 
1277  /* Lastly, fill in the cost estimates for use later */
1278  cost_subplan(root, splan, plan);
1279  }
1280 }
#define NIL
Definition: pg_list.h:69
Oid firstColType
Definition: primnodes.h:693
Query * parse
Definition: relation.h:155
int plan_id
Definition: primnodes.h:689
List * plan_params
Definition: relation.h:169
int SS_assign_special_param(PlannerInfo *root)
Definition: subselect.c:429
static void get_first_col_type(Plan *plan, Oid *coltype, int32 *coltypmod, Oid *colcollation)
Definition: subselect.c:448
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
SubLinkType subLinkType
Definition: primnodes.h:684
List * paramIds
Definition: primnodes.h:687
Plan * create_plan(PlannerInfo *root, Path *best_path)
Definition: createplan.c:304
#define ERROR
Definition: elog.h:43
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1137
struct Path * cheapest_total_path
Definition: relation.h:603
List * subplans
Definition: relation.h:98
PlannerGlobal * glob
Definition: relation.h:157
static SPIPlanPtr splan
Definition: regress.c:449
#define list_make1_int(x1)
Definition: pg_list.h:145
List * lappend_int(List *list, int datum)
Definition: list.c:146
List * lappend(List *list, void *datum)
Definition: list.c:128
List * cte_plan_ids
Definition: relation.h:230
Node * testexpr
Definition: primnodes.h:686
List * init_plans
Definition: relation.h:228
int32 firstColTypmod
Definition: primnodes.h:694
#define makeNode(_type_)
Definition: nodes.h:559
char * plan_name
Definition: primnodes.h:691
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
List * setParam
Definition: primnodes.h:707
void cost_subplan(PlannerInfo *root, SubPlan *subplan, Plan *plan)
Definition: costsize.c:3308
bool unknownEqFalse
Definition: primnodes.h:700
static int list_length(const List *l)
Definition: pg_list.h:89
List * subroots
Definition: relation.h:100
List * parParam
Definition: primnodes.h:709
bool parallel_safe
Definition: primnodes.h:703
List * cteList
Definition: parsenodes.h:133
bool useHashTable
Definition: primnodes.h:698
Oid firstColCollation
Definition: primnodes.h:695
#define elog
Definition: elog.h:219
#define copyObject(obj)
Definition: nodes.h:624
PlannerInfo * subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, bool hasRecursion, double tuple_fraction)
Definition: planner.c:517
CmdType
Definition: nodes.h:651
List * args
Definition: primnodes.h:710

◆ SS_process_sublinks()

Node* SS_process_sublinks ( PlannerInfo root,
Node expr,
bool  isQual 
)

Definition at line 1961 of file subselect.c.

References process_sublinks_context::isTopQual, process_sublinks_mutator(), convert_testexpr_context::root, and process_sublinks_context::root.

Referenced by build_subplan(), and preprocess_expression().

1962 {
1963  process_sublinks_context context;
1964 
1965  context.root = root;
1966  context.isTopQual = isQual;
1967  return process_sublinks_mutator(expr, &context);
1968 }
static Node * process_sublinks_mutator(Node *node, process_sublinks_context *context)
Definition: subselect.c:1971

◆ SS_replace_correlation_vars()

Node* SS_replace_correlation_vars ( PlannerInfo root,
Node expr 
)

Definition at line 1916 of file subselect.c.

References replace_correlation_vars_mutator().

Referenced by preprocess_expression().

1917 {
1918  /* No setup needed for tree walk, so away we go */
1919  return replace_correlation_vars_mutator(expr, root);
1920 }
static Node * replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
Definition: subselect.c:1923