PostgreSQL Source Code  git master
subselect.h File Reference
#include "nodes/pathnodes.h"
#include "nodes/plannodes.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)
 

Function Documentation

◆ convert_ANY_sublink_to_join()

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

Definition at line 1212 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().

1214 {
1215  JoinExpr *result;
1216  Query *parse = root->parse;
1217  Query *subselect = (Query *) sublink->subselect;
1218  Relids upper_varnos;
1219  int rtindex;
1220  ParseNamespaceItem *nsitem;
1221  RangeTblEntry *rte;
1222  RangeTblRef *rtr;
1223  List *subquery_vars;
1224  Node *quals;
1225  ParseState *pstate;
1226 
1227  Assert(sublink->subLinkType == ANY_SUBLINK);
1228 
1229  /*
1230  * The sub-select must not refer to any Vars of the parent query. (Vars of
1231  * higher levels should be okay, though.)
1232  */
1233  if (contain_vars_of_level((Node *) subselect, 1))
1234  return NULL;
1235 
1236  /*
1237  * The test expression must contain some Vars of the parent query, else
1238  * it's not gonna be a join. (Note that it won't have Vars referring to
1239  * the subquery, rather Params.)
1240  */
1241  upper_varnos = pull_varnos(sublink->testexpr);
1242  if (bms_is_empty(upper_varnos))
1243  return NULL;
1244 
1245  /*
1246  * However, it can't refer to anything outside available_rels.
1247  */
1248  if (!bms_is_subset(upper_varnos, available_rels))
1249  return NULL;
1250 
1251  /*
1252  * The combining operators and left-hand expressions mustn't be volatile.
1253  */
1254  if (contain_volatile_functions(sublink->testexpr))
1255  return NULL;
1256 
1257  /* Create a dummy ParseState for addRangeTableEntryForSubquery */
1258  pstate = make_parsestate(NULL);
1259 
1260  /*
1261  * Okay, pull up the sub-select into upper range table.
1262  *
1263  * We rely here on the assumption that the outer query has no references
1264  * to the inner (necessarily true, other than the Vars that we build
1265  * below). Therefore this is a lot easier than what pull_up_subqueries has
1266  * to go through.
1267  */
1268  nsitem = addRangeTableEntryForSubquery(pstate,
1269  subselect,
1270  makeAlias("ANY_subquery", NIL),
1271  false,
1272  false);
1273  rte = nsitem->p_rte;
1274  parse->rtable = lappend(parse->rtable, rte);
1275  rtindex = list_length(parse->rtable);
1276 
1277  /*
1278  * Form a RangeTblRef for the pulled-up sub-select.
1279  */
1280  rtr = makeNode(RangeTblRef);
1281  rtr->rtindex = rtindex;
1282 
1283  /*
1284  * Build a list of Vars representing the subselect outputs.
1285  */
1286  subquery_vars = generate_subquery_vars(root,
1287  subselect->targetList,
1288  rtindex);
1289 
1290  /*
1291  * Build the new join's qual expression, replacing Params with these Vars.
1292  */
1293  quals = convert_testexpr(root, sublink->testexpr, subquery_vars);
1294 
1295  /*
1296  * And finally, build the JoinExpr node.
1297  */
1298  result = makeNode(JoinExpr);
1299  result->jointype = JOIN_SEMI;
1300  result->isNatural = false;
1301  result->larg = NULL; /* caller must fill this in */
1302  result->rarg = (Node *) rtr;
1303  result->usingClause = NIL;
1304  result->quals = quals;
1305  result->alias = NULL;
1306  result->rtindex = 0; /* we don't need an RTE for it */
1307 
1308  return result;
1309 }
static Node * convert_testexpr(PlannerInfo *root, Node *testexpr, List *subst_nodes)
Definition: subselect.c:649
#define NIL
Definition: pg_list.h:65
Query * parse
Definition: pathnodes.h:179
Definition: nodes.h:526
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:726
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:43
Node * larg
Definition: primnodes.h:1490
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:385
List * rtable
Definition: parsenodes.h:137
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:315
static List * generate_subquery_vars(PlannerInfo *root, List *tlist, Index varno)
Definition: subselect.c:620
Relids pull_varnos(Node *node)
Definition: var.c:95
List * lappend(List *list, void *datum)
Definition: list.c:322
bool isNatural
Definition: primnodes.h:1489
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:701
List * usingClause
Definition: primnodes.h:1492
Node * quals
Definition: primnodes.h:1493
#define makeNode(_type_)
Definition: nodes.h:574
Node * rarg
Definition: primnodes.h:1491
Alias * alias
Definition: primnodes.h:1494
JoinType jointype
Definition: primnodes.h:1488
#define Assert(condition)
Definition: c.h:738
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:369
static int list_length(const List *l)
Definition: pg_list.h:169
ParseNamespaceItem * addRangeTableEntryForSubquery(ParseState *pstate, Query *subquery, Alias *alias, bool lateral, bool inFromCl)
int rtindex
Definition: primnodes.h:1495
Definition: pg_list.h:50
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:648

◆ convert_EXISTS_sublink_to_join()

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

Definition at line 1319 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, 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, replace_empty_jointree(), Query::rtable, JoinExpr::rtindex, simplify_EXISTS_query(), SubLink::subLinkType, SubLink::subselect, and JoinExpr::usingClause.

Referenced by pull_up_sublinks_qual_recurse().

1321 {
1322  JoinExpr *result;
1323  Query *parse = root->parse;
1324  Query *subselect = (Query *) sublink->subselect;
1325  Node *whereClause;
1326  int rtoffset;
1327  int varno;
1328  Relids clause_varnos;
1329  Relids upper_varnos;
1330 
1331  Assert(sublink->subLinkType == EXISTS_SUBLINK);
1332 
1333  /*
1334  * Can't flatten if it contains WITH. (We could arrange to pull up the
1335  * WITH into the parent query's cteList, but that risks changing the
1336  * semantics, since a WITH ought to be executed once per associated query
1337  * call.) Note that convert_ANY_sublink_to_join doesn't have to reject
1338  * this case, since it just produces a subquery RTE that doesn't have to
1339  * get flattened into the parent query.
1340  */
1341  if (subselect->cteList)
1342  return NULL;
1343 
1344  /*
1345  * Copy the subquery so we can modify it safely (see comments in
1346  * make_subplan).
1347  */
1348  subselect = copyObject(subselect);
1349 
1350  /*
1351  * See if the subquery can be simplified based on the knowledge that it's
1352  * being used in EXISTS(). If we aren't able to get rid of its
1353  * targetlist, we have to fail, because the pullup operation leaves us
1354  * with noplace to evaluate the targetlist.
1355  */
1356  if (!simplify_EXISTS_query(root, subselect))
1357  return NULL;
1358 
1359  /*
1360  * Separate out the WHERE clause. (We could theoretically also remove
1361  * top-level plain JOIN/ON clauses, but it's probably not worth the
1362  * trouble.)
1363  */
1364  whereClause = subselect->jointree->quals;
1365  subselect->jointree->quals = NULL;
1366 
1367  /*
1368  * The rest of the sub-select must not refer to any Vars of the parent
1369  * query. (Vars of higher levels should be okay, though.)
1370  */
1371  if (contain_vars_of_level((Node *) subselect, 1))
1372  return NULL;
1373 
1374  /*
1375  * On the other hand, the WHERE clause must contain some Vars of the
1376  * parent query, else it's not gonna be a join.
1377  */
1378  if (!contain_vars_of_level(whereClause, 1))
1379  return NULL;
1380 
1381  /*
1382  * We don't risk optimizing if the WHERE clause is volatile, either.
1383  */
1384  if (contain_volatile_functions(whereClause))
1385  return NULL;
1386 
1387  /*
1388  * The subquery must have a nonempty jointree, but we can make it so.
1389  */
1390  replace_empty_jointree(subselect);
1391 
1392  /*
1393  * Prepare to pull up the sub-select into top range table.
1394  *
1395  * We rely here on the assumption that the outer query has no references
1396  * to the inner (necessarily true). Therefore this is a lot easier than
1397  * what pull_up_subqueries has to go through.
1398  *
1399  * In fact, it's even easier than what convert_ANY_sublink_to_join has to
1400  * do. The machinations of simplify_EXISTS_query ensured that there is
1401  * nothing interesting in the subquery except an rtable and jointree, and
1402  * even the jointree FromExpr no longer has quals. So we can just append
1403  * the rtable to our own and use the FromExpr in our jointree. But first,
1404  * adjust all level-zero varnos in the subquery to account for the rtable
1405  * merger.
1406  */
1407  rtoffset = list_length(parse->rtable);
1408  OffsetVarNodes((Node *) subselect, rtoffset, 0);
1409  OffsetVarNodes(whereClause, rtoffset, 0);
1410 
1411  /*
1412  * Upper-level vars in subquery will now be one level closer to their
1413  * parent than before; in particular, anything that had been level 1
1414  * becomes level zero.
1415  */
1416  IncrementVarSublevelsUp((Node *) subselect, -1, 1);
1417  IncrementVarSublevelsUp(whereClause, -1, 1);
1418 
1419  /*
1420  * Now that the WHERE clause is adjusted to match the parent query
1421  * environment, we can easily identify all the level-zero rels it uses.
1422  * The ones <= rtoffset belong to the upper query; the ones > rtoffset do
1423  * not.
1424  */
1425  clause_varnos = pull_varnos(whereClause);
1426  upper_varnos = NULL;
1427  while ((varno = bms_first_member(clause_varnos)) >= 0)
1428  {
1429  if (varno <= rtoffset)
1430  upper_varnos = bms_add_member(upper_varnos, varno);
1431  }
1432  bms_free(clause_varnos);
1433  Assert(!bms_is_empty(upper_varnos));
1434 
1435  /*
1436  * Now that we've got the set of upper-level varnos, we can make the last
1437  * check: only available_rels can be referenced.
1438  */
1439  if (!bms_is_subset(upper_varnos, available_rels))
1440  return NULL;
1441 
1442  /* Now we can attach the modified subquery rtable to the parent */
1443  parse->rtable = list_concat(parse->rtable, subselect->rtable);
1444 
1445  /*
1446  * And finally, build the JoinExpr node.
1447  */
1448  result = makeNode(JoinExpr);
1449  result->jointype = under_not ? JOIN_ANTI : JOIN_SEMI;
1450  result->isNatural = false;
1451  result->larg = NULL; /* caller must fill this in */
1452  /* flatten out the FromExpr node if it's useless */
1453  if (list_length(subselect->jointree->fromlist) == 1)
1454  result->rarg = (Node *) linitial(subselect->jointree->fromlist);
1455  else
1456  result->rarg = (Node *) subselect->jointree;
1457  result->usingClause = NIL;
1458  result->quals = whereClause;
1459  result->alias = NULL;
1460  result->rtindex = 0; /* we don't need an RTE for it */
1461 
1462  return result;
1463 }
#define NIL
Definition: pg_list.h:65
int bms_first_member(Bitmapset *a)
Definition: bitmapset.c:996
Query * parse
Definition: pathnodes.h:179
void OffsetVarNodes(Node *node, int offset, int sublevels_up)
Definition: rewriteManip.c:425
void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, int min_sublevels_up)
Definition: rewriteManip.c:776
FromExpr * jointree
Definition: parsenodes.h:138
Definition: nodes.h:526
List * list_concat(List *list1, const List *list2)
Definition: list.c:516
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:726
static bool simplify_EXISTS_query(PlannerInfo *root, Query *query)
Definition: subselect.c:1482
void replace_empty_jointree(Query *parse)
Definition: prepjointree.c:148
Node * quals
Definition: primnodes.h:1511
Node * larg
Definition: primnodes.h:1490
#define linitial(l)
Definition: pg_list.h:195
List * rtable
Definition: parsenodes.h:137
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:315
Relids pull_varnos(Node *node)
Definition: var.c:95
bool isNatural
Definition: primnodes.h:1489
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:701
List * usingClause
Definition: primnodes.h:1492
Node * quals
Definition: primnodes.h:1493
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208
#define makeNode(_type_)
Definition: nodes.h:574
Node * rarg
Definition: primnodes.h:1491
Alias * alias
Definition: primnodes.h:1494
JoinType jointype
Definition: primnodes.h:1488
#define Assert(condition)
Definition: c.h:738
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:369
static int list_length(const List *l)
Definition: pg_list.h:169
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
List * cteList
Definition: parsenodes.h:135
#define copyObject(obj)
Definition: nodes.h:642
int rtindex
Definition: primnodes.h:1495
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:648

◆ SS_attach_initplans()

void SS_attach_initplans ( PlannerInfo root,
Plan plan 
)

Definition at line 2120 of file subselect.c.

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

Referenced by create_plan().

2121 {
2122  plan->initPlan = root->init_plans;
2123 }
List * init_plans
Definition: pathnodes.h:259
List * initPlan
Definition: plannodes.h:146

◆ SS_charge_for_initplans()

void SS_charge_for_initplans ( PlannerInfo root,
RelOptInfo final_rel 
)

Definition at line 2063 of file subselect.c.

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

Referenced by build_minmax_path(), and subquery_planner().

2064 {
2065  Cost initplan_cost;
2066  ListCell *lc;
2067 
2068  /* Nothing to do if no initPlans */
2069  if (root->init_plans == NIL)
2070  return;
2071 
2072  /*
2073  * Compute the cost increment just once, since it will be the same for all
2074  * Paths. We assume each initPlan gets run once during top plan startup.
2075  * This is a conservative overestimate, since in fact an initPlan might be
2076  * executed later than plan startup, or even not at all.
2077  */
2078  initplan_cost = 0;
2079  foreach(lc, root->init_plans)
2080  {
2081  SubPlan *initsubplan = (SubPlan *) lfirst(lc);
2082 
2083  initplan_cost += initsubplan->startup_cost + initsubplan->per_call_cost;
2084  }
2085 
2086  /*
2087  * Now adjust the costs and parallel_safe flags.
2088  */
2089  foreach(lc, final_rel->pathlist)
2090  {
2091  Path *path = (Path *) lfirst(lc);
2092 
2093  path->startup_cost += initplan_cost;
2094  path->total_cost += initplan_cost;
2095  path->parallel_safe = false;
2096  }
2097 
2098  /*
2099  * Forget about any partial paths and clear consider_parallel, too;
2100  * they're not usable if we attached an initPlan.
2101  */
2102  final_rel->partial_pathlist = NIL;
2103  final_rel->consider_parallel = false;
2104 
2105  /* We needn't do set_cheapest() here, caller will do it */
2106 }
#define NIL
Definition: pg_list.h:65
List * partial_pathlist
Definition: pathnodes.h:659
Cost startup_cost
Definition: pathnodes.h:1128
List * init_plans
Definition: pathnodes.h:259
Cost per_call_cost
Definition: primnodes.h:733
Cost total_cost
Definition: pathnodes.h:1129
#define lfirst(lc)
Definition: pg_list.h:190
bool parallel_safe
Definition: pathnodes.h:1123
bool consider_parallel
Definition: pathnodes.h:651
Cost startup_cost
Definition: primnodes.h:732
List * pathlist
Definition: pathnodes.h:657
double Cost
Definition: nodes.h:660

◆ SS_finalize_plan()

void SS_finalize_plan ( PlannerInfo root,
Plan plan 
)

Definition at line 2135 of file subselect.c.

References finalize_plan(), and PlannerInfo::outer_params.

Referenced by standard_planner().

2136 {
2137  /* No setup needed, just recurse through plan tree. */
2138  (void) finalize_plan(root, plan, -1, root->outer_params, NULL);
2139 }
static Bitmapset * finalize_plan(PlannerInfo *root, Plan *plan, int gather_param, Bitmapset *valid_params, Bitmapset *scan_params)
Definition: subselect.c:2173
Bitmapset * outer_params
Definition: pathnodes.h:194

◆ SS_identify_outer_params()

void SS_identify_outer_params ( PlannerInfo root)

Definition at line 2001 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().

2002 {
2003  Bitmapset *outer_params;
2004  PlannerInfo *proot;
2005  ListCell *l;
2006 
2007  /*
2008  * If no parameters have been assigned anywhere in the tree, we certainly
2009  * don't need to do anything here.
2010  */
2011  if (root->glob->paramExecTypes == NIL)
2012  return;
2013 
2014  /*
2015  * Scan all query levels above this one to see which parameters are due to
2016  * be available from them, either because lower query levels have
2017  * requested them (via plan_params) or because they will be available from
2018  * initPlans of those levels.
2019  */
2020  outer_params = NULL;
2021  for (proot = root->parent_root; proot != NULL; proot = proot->parent_root)
2022  {
2023  /* Include ordinary Var/PHV/Aggref params */
2024  foreach(l, proot->plan_params)
2025  {
2026  PlannerParamItem *pitem = (PlannerParamItem *) lfirst(l);
2027 
2028  outer_params = bms_add_member(outer_params, pitem->paramId);
2029  }
2030  /* Include any outputs of outer-level initPlans */
2031  foreach(l, proot->init_plans)
2032  {
2033  SubPlan *initsubplan = (SubPlan *) lfirst(l);
2034  ListCell *l2;
2035 
2036  foreach(l2, initsubplan->setParam)
2037  {
2038  outer_params = bms_add_member(outer_params, lfirst_int(l2));
2039  }
2040  }
2041  /* Include worktable ID, if a recursive query is being planned */
2042  if (proot->wt_param_id >= 0)
2043  outer_params = bms_add_member(outer_params, proot->wt_param_id);
2044  }
2045  root->outer_params = outer_params;
2046 }
#define NIL
Definition: pg_list.h:65
List * plan_params
Definition: pathnodes.h:193
PlannerInfo * parent_root
Definition: pathnodes.h:185
int wt_param_id
Definition: pathnodes.h:353
List * paramExecTypes
Definition: pathnodes.h:131
#define lfirst_int(lc)
Definition: pg_list.h:191
PlannerGlobal * glob
Definition: pathnodes.h:181
List * init_plans
Definition: pathnodes.h:259
#define lfirst(lc)
Definition: pg_list.h:190
List * setParam
Definition: primnodes.h:727
Bitmapset * outer_params
Definition: pathnodes.h:194
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736

◆ SS_make_initplan_from_plan()

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

Definition at line 2891 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().

2894 {
2895  SubPlan *node;
2896 
2897  /*
2898  * Add the subplan and its PlannerInfo to the global lists.
2899  */
2900  root->glob->subplans = lappend(root->glob->subplans, plan);
2901  root->glob->subroots = lappend(root->glob->subroots, subroot);
2902 
2903  /*
2904  * Create a SubPlan node and add it to the outer list of InitPlans. Note
2905  * it has to appear after any other InitPlans it might depend on (see
2906  * comments in ExecReScan).
2907  */
2908  node = makeNode(SubPlan);
2909  node->subLinkType = EXPR_SUBLINK;
2910  node->plan_id = list_length(root->glob->subplans);
2911  node->plan_name = psprintf("InitPlan %d (returns $%d)",
2912  node->plan_id, prm->paramid);
2913  get_first_col_type(plan, &node->firstColType, &node->firstColTypmod,
2914  &node->firstColCollation);
2915  node->setParam = list_make1_int(prm->paramid);
2916 
2917  root->init_plans = lappend(root->init_plans, node);
2918 
2919  /*
2920  * The node can't have any inputs (since it's an initplan), so the
2921  * parParam and args lists remain empty.
2922  */
2923 
2924  /* Set costs of SubPlan using info from the plan tree */
2925  cost_subplan(subroot, node, plan);
2926 }
Oid firstColType
Definition: primnodes.h:713
int plan_id
Definition: primnodes.h:709
static void get_first_col_type(Plan *plan, Oid *coltype, int32 *coltypmod, Oid *colcollation)
Definition: subselect.c:117
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
SubLinkType subLinkType
Definition: primnodes.h:704
List * subplans
Definition: pathnodes.h:111
PlannerGlobal * glob
Definition: pathnodes.h:181
#define list_make1_int(x1)
Definition: pg_list.h:238
List * lappend(List *list, void *datum)
Definition: list.c:322
List * init_plans
Definition: pathnodes.h:259
int32 firstColTypmod
Definition: primnodes.h:714
#define makeNode(_type_)
Definition: nodes.h:574
char * plan_name
Definition: primnodes.h:711
List * setParam
Definition: primnodes.h:727
int paramid
Definition: primnodes.h:263
void cost_subplan(PlannerInfo *root, SubPlan *subplan, Plan *plan)
Definition: costsize.c:3685
static int list_length(const List *l)
Definition: pg_list.h:169
List * subroots
Definition: pathnodes.h:113
Oid firstColCollation
Definition: primnodes.h:715

◆ SS_make_initplan_output_param()

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

Definition at line 2875 of file subselect.c.

References generate_new_exec_param().

Referenced by preprocess_minmax_aggregates().

2878 {
2879  return generate_new_exec_param(root, resulttype,
2880  resulttypmod, resultcollation);
2881 }
Param * generate_new_exec_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod, Oid paramcollation)
Definition: paramassign.c:557

◆ SS_process_ctes()

void SS_process_ctes ( PlannerInfo root)

Definition at line 830 of file subselect.c.

References SubPlan::args, Assert, assign_special_exec_param(), RelOptInfo::cheapest_total_path, CMD_SELECT, contain_dml(), contain_outer_selfref(), contain_volatile_functions(), copyObject, cost_subplan(), create_plan(), PlannerInfo::cte_plan_ids, CTE_SUBLINK, Query::cteList, CommonTableExpr::ctematerialized, CTEMaterializeDefault, CTEMaterializeNever, 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, inline_cte(), 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, SubPlan::subLinkType, PlannerGlobal::subplans, subquery_planner(), PlannerGlobal::subroots, SubPlan::testexpr, SubPlan::unknownEqFalse, UPPERREL_FINAL, and SubPlan::useHashTable.

Referenced by subquery_planner().

831 {
832  ListCell *lc;
833 
834  Assert(root->cte_plan_ids == NIL);
835 
836  foreach(lc, root->parse->cteList)
837  {
838  CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
839  CmdType cmdType = ((Query *) cte->ctequery)->commandType;
840  Query *subquery;
841  PlannerInfo *subroot;
842  RelOptInfo *final_rel;
843  Path *best_path;
844  Plan *plan;
845  SubPlan *splan;
846  int paramid;
847 
848  /*
849  * Ignore SELECT CTEs that are not actually referenced anywhere.
850  */
851  if (cte->cterefcount == 0 && cmdType == CMD_SELECT)
852  {
853  /* Make a dummy entry in cte_plan_ids */
854  root->cte_plan_ids = lappend_int(root->cte_plan_ids, -1);
855  continue;
856  }
857 
858  /*
859  * Consider inlining the CTE (creating RTE_SUBQUERY RTE(s)) instead of
860  * implementing it as a separately-planned CTE.
861  *
862  * We cannot inline if any of these conditions hold:
863  *
864  * 1. The user said not to (the CTEMaterializeAlways option).
865  *
866  * 2. The CTE is recursive.
867  *
868  * 3. The CTE has side-effects; this includes either not being a plain
869  * SELECT, or containing volatile functions. Inlining might change
870  * the side-effects, which would be bad.
871  *
872  * 4. The CTE is multiply-referenced and contains a self-reference to
873  * a recursive CTE outside itself. Inlining would result in multiple
874  * recursive self-references, which we don't support.
875  *
876  * Otherwise, we have an option whether to inline or not. That should
877  * always be a win if there's just a single reference, but if the CTE
878  * is multiply-referenced then it's unclear: inlining adds duplicate
879  * computations, but the ability to absorb restrictions from the outer
880  * query level could outweigh that. We do not have nearly enough
881  * information at this point to tell whether that's true, so we let
882  * the user express a preference. Our default behavior is to inline
883  * only singly-referenced CTEs, but a CTE marked CTEMaterializeNever
884  * will be inlined even if multiply referenced.
885  *
886  * Note: we check for volatile functions last, because that's more
887  * expensive than the other tests needed.
888  */
889  if ((cte->ctematerialized == CTEMaterializeNever ||
891  cte->cterefcount == 1)) &&
892  !cte->cterecursive &&
893  cmdType == CMD_SELECT &&
894  !contain_dml(cte->ctequery) &&
895  (cte->cterefcount <= 1 ||
898  {
899  inline_cte(root, cte);
900  /* Make a dummy entry in cte_plan_ids */
901  root->cte_plan_ids = lappend_int(root->cte_plan_ids, -1);
902  continue;
903  }
904 
905  /*
906  * Copy the source Query node. Probably not necessary, but let's keep
907  * this similar to make_subplan.
908  */
909  subquery = (Query *) copyObject(cte->ctequery);
910 
911  /* plan_params should not be in use in current query level */
912  Assert(root->plan_params == NIL);
913 
914  /*
915  * Generate Paths for the CTE query. Always plan for full retrieval
916  * --- we don't have enough info to predict otherwise.
917  */
918  subroot = subquery_planner(root->glob, subquery,
919  root,
920  cte->cterecursive, 0.0);
921 
922  /*
923  * Since the current query level doesn't yet contain any RTEs, it
924  * should not be possible for the CTE to have requested parameters of
925  * this level.
926  */
927  if (root->plan_params)
928  elog(ERROR, "unexpected outer reference in CTE query");
929 
930  /*
931  * Select best Path and turn it into a Plan. At least for now, there
932  * seems no reason to postpone doing that.
933  */
934  final_rel = fetch_upper_rel(subroot, UPPERREL_FINAL, NULL);
935  best_path = final_rel->cheapest_total_path;
936 
937  plan = create_plan(subroot, best_path);
938 
939  /*
940  * Make a SubPlan node for it. This is just enough unlike
941  * build_subplan that we can't share code.
942  *
943  * Note plan_id, plan_name, and cost fields are set further down.
944  */
945  splan = makeNode(SubPlan);
946  splan->subLinkType = CTE_SUBLINK;
947  splan->testexpr = NULL;
948  splan->paramIds = NIL;
949  get_first_col_type(plan, &splan->firstColType, &splan->firstColTypmod,
950  &splan->firstColCollation);
951  splan->useHashTable = false;
952  splan->unknownEqFalse = false;
953 
954  /*
955  * CTE scans are not considered for parallelism (cf
956  * set_rel_consider_parallel), and even if they were, initPlans aren't
957  * parallel-safe.
958  */
959  splan->parallel_safe = false;
960  splan->setParam = NIL;
961  splan->parParam = NIL;
962  splan->args = NIL;
963 
964  /*
965  * The node can't have any inputs (since it's an initplan), so the
966  * parParam and args lists remain empty. (It could contain references
967  * to earlier CTEs' output param IDs, but CTE outputs are not
968  * propagated via the args list.)
969  */
970 
971  /*
972  * Assign a param ID to represent the CTE's output. No ordinary
973  * "evaluation" of this param slot ever happens, but we use the param
974  * ID for setParam/chgParam signaling just as if the CTE plan were
975  * returning a simple scalar output. (Also, the executor abuses the
976  * ParamExecData slot for this param ID for communication among
977  * multiple CteScan nodes that might be scanning this CTE.)
978  */
979  paramid = assign_special_exec_param(root);
980  splan->setParam = list_make1_int(paramid);
981 
982  /*
983  * Add the subplan and its PlannerInfo to the global lists.
984  */
985  root->glob->subplans = lappend(root->glob->subplans, plan);
986  root->glob->subroots = lappend(root->glob->subroots, subroot);
987  splan->plan_id = list_length(root->glob->subplans);
988 
989  root->init_plans = lappend(root->init_plans, splan);
990 
991  root->cte_plan_ids = lappend_int(root->cte_plan_ids, splan->plan_id);
992 
993  /* Label the subplan for EXPLAIN purposes */
994  splan->plan_name = psprintf("CTE %s", cte->ctename);
995 
996  /* Lastly, fill in the cost estimates for use later */
997  cost_subplan(root, splan, plan);
998  }
999 }
#define NIL
Definition: pg_list.h:65
Oid firstColType
Definition: primnodes.h:713
Query * parse
Definition: pathnodes.h:179
int plan_id
Definition: primnodes.h:709
List * plan_params
Definition: pathnodes.h:193
static void get_first_col_type(Plan *plan, Oid *coltype, int32 *coltypmod, Oid *colcollation)
Definition: subselect.c:117
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
SubLinkType subLinkType
Definition: primnodes.h:704
List * paramIds
Definition: primnodes.h:707
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:726
int assign_special_exec_param(PlannerInfo *root)
Definition: paramassign.c:584
Plan * create_plan(PlannerInfo *root, Path *best_path)
Definition: createplan.c:313
#define ERROR
Definition: elog.h:43
static void inline_cte(PlannerInfo *root, CommonTableExpr *cte)
Definition: subselect.c:1089
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1177
struct Path * cheapest_total_path
Definition: pathnodes.h:661
List * subplans
Definition: pathnodes.h:111
PlannerGlobal * glob
Definition: pathnodes.h:181
static SPIPlanPtr splan
Definition: regress.c:258
#define list_make1_int(x1)
Definition: pg_list.h:238
List * lappend_int(List *list, int datum)
Definition: list.c:340
List * lappend(List *list, void *datum)
Definition: list.c:322
List * cte_plan_ids
Definition: pathnodes.h:261
Node * testexpr
Definition: primnodes.h:706
List * init_plans
Definition: pathnodes.h:259
static bool contain_dml(Node *node)
Definition: subselect.c:1007
static bool contain_outer_selfref(Node *node)
Definition: subselect.c:1034
int32 firstColTypmod
Definition: primnodes.h:714
#define makeNode(_type_)
Definition: nodes.h:574
char * plan_name
Definition: primnodes.h:711
#define Assert(condition)
Definition: c.h:738
#define lfirst(lc)
Definition: pg_list.h:190
CTEMaterialize ctematerialized
Definition: parsenodes.h:1451
List * setParam
Definition: primnodes.h:727
void cost_subplan(PlannerInfo *root, SubPlan *subplan, Plan *plan)
Definition: costsize.c:3685
bool unknownEqFalse
Definition: primnodes.h:720
static int list_length(const List *l)
Definition: pg_list.h:169
List * subroots
Definition: pathnodes.h:113
List * parParam
Definition: primnodes.h:729
bool parallel_safe
Definition: primnodes.h:723
List * cteList
Definition: parsenodes.h:135
#define elog(elevel,...)
Definition: elog.h:214
bool useHashTable
Definition: primnodes.h:718
Oid firstColCollation
Definition: primnodes.h:715
#define copyObject(obj)
Definition: nodes.h:642
PlannerInfo * subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, bool hasRecursion, double tuple_fraction)
Definition: planner.c:597
CmdType
Definition: nodes.h:669
List * args
Definition: primnodes.h:730

◆ SS_process_sublinks()

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

Definition at line 1854 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().

1855 {
1856  process_sublinks_context context;
1857 
1858  context.root = root;
1859  context.isTopQual = isQual;
1860  return process_sublinks_mutator(expr, &context);
1861 }
static Node * process_sublinks_mutator(Node *node, process_sublinks_context *context)
Definition: subselect.c:1864

◆ SS_replace_correlation_vars()

Node* SS_replace_correlation_vars ( PlannerInfo root,
Node expr 
)

Definition at line 1809 of file subselect.c.

References replace_correlation_vars_mutator().

Referenced by preprocess_expression().

1810 {
1811  /* No setup needed for tree walk, so away we go */
1812  return replace_correlation_vars_mutator(expr, root);
1813 }
static Node * replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
Definition: subselect.c:1816