48 bool *istrivial_tlist);
54 bool trivial_tlist,
List *child_tlist,
55 List *interesting_pathkeys,
67 List **istrivial_tlist);
77 List *refnames_tlist);
80 List *child_pathlist);
103 Query *leftmostQuery;
124 root->ec_merging_done =
true;
142 leftmostQuery = leftmostRTE->
subquery;
143 Assert(leftmostQuery != NULL);
148 if (
root->hasRecursion)
165 topop->colTypes, topop->colCollations,
172 root->processed_tlist = top_tlist;
215 List *colTypes,
List *colCollations,
216 List *refnames_tlist,
218 bool *istrivial_tlist)
222 *istrivial_tlist =
true;
253 false,
root->tuple_fraction,
260 if (
root->plan_params)
261 elog(
ERROR,
"unexpected outer reference in set operation subquery");
273 *pTargetList = tlist;
274 *istrivial_tlist = trivial_tlist;
316 *istrivial_tlist = trivial_tlist;
351 elog(
ERROR,
"unrecognized node type: %d",
365 List *refnames_tlist,
375 bool lpath_trivial_tlist;
377 bool rpath_trivial_tlist;
384 elog(
ERROR,
"only UNION queries can be recursive");
394 setOp->colTypes, setOp->colCollations,
397 &lpath_trivial_tlist);
403 root->non_recursive_path = lpath;
406 setOp->colTypes, setOp->colCollations,
409 &rpath_trivial_tlist);
414 root->non_recursive_path = NULL;
423 *pTargetList = tlist;
446 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
447 errmsg(
"could not implement recursive UNION"),
448 errdetail(
"All column datatypes must be hashable.")));
454 dNumGroups = lpath->
rows + rpath->
rows * 10;
489 bool trivial_tlist,
List *child_tlist,
490 List *interesting_pathkeys,
double *pNumGroups)
500 if (interesting_pathkeys !=
NIL)
504 interesting_pathkeys);
541 if (
subpath == cheapest_input_path)
557 if (interesting_pathkeys ==
NIL)
580 if (
subpath != cheapest_input_path &&
609 if (
subpath != cheapest_input_path)
637 Path *partial_subpath;
641 partial_path = (
Path *)
691 List *refnames_tlist,
702 bool partial_paths_valid =
true;
703 bool consider_parallel =
true;
706 List *trivial_tlist_list;
711 bool try_sorted =
false;
724 &trivial_tlist_list);
734 tlist_list, refnames_tlist);
735 *pTargetList = tlist;
750 root->query_pathkeys = union_pathkeys;
758 forthree(lc, rellist, lc2, trivial_tlist_list, lc3, tlist_list)
767 union_pathkeys, NULL);
786 cheapest_pathlist =
lappend(cheapest_pathlist,
797 if (ordered_path != NULL)
798 ordered_pathlist =
lappend(ordered_pathlist, ordered_path);
811 if (consider_parallel)
815 consider_parallel =
false;
816 partial_paths_valid =
false;
819 partial_paths_valid =
false;
821 partial_pathlist =
lappend(partial_pathlist,
834 if (cheapest_pathlist ==
NIL)
846 NIL,
NIL, NULL, 0,
false, -1);
859 if (partial_paths_valid)
862 int parallel_workers = 0;
865 foreach(lc, partial_pathlist)
869 parallel_workers =
Max(parallel_workers,
872 Assert(parallel_workers > 0);
883 parallel_workers =
Max(parallel_workers,
885 parallel_workers =
Min(parallel_workers,
888 Assert(parallel_workers > 0);
892 NIL, NULL, parallel_workers,
918 first_path->pathtarget->exprs,
933 dNumGroups = apath->
rows;
979 if (groupList !=
NIL)
1014 if (try_sorted && groupList !=
NIL)
1051 List *refnames_tlist,
1057 double save_fraction =
root->tuple_fraction;
1065 bool lpath_trivial_tlist,
1066 rpath_trivial_tlist,
1067 result_trivial_tlist;
1068 List *nonunion_pathkeys =
NIL;
1080 root->tuple_fraction = 0.0;
1085 op->colTypes, op->colCollations,
1088 &lpath_trivial_tlist);
1092 op->colTypes, op->colCollations,
1095 &rpath_trivial_tlist);
1105 0,
false, lpath_tlist, refnames_tlist,
1106 &result_trivial_tlist);
1109 Assert(result_trivial_tlist);
1111 *pTargetList = tlist;
1119 if (!can_sort && !can_hash)
1121 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1123 errmsg(
"could not implement %s",
1125 errdetail(
"Some of the datatypes only support hashing, while others only support sorting.")));
1133 root->query_pathkeys = nonunion_pathkeys;
1141 nonunion_pathkeys, &dLeftGroups);
1143 dLeftGroups = lrel->
rows;
1146 nonunion_pathkeys, &dRightGroups);
1148 dRightGroups = rrel->
rows;
1151 root->tuple_fraction = save_fraction;
1171 tmplist = lpath_tlist;
1172 lpath_tlist = rpath_tlist;
1173 rpath_tlist = tmplist;
1175 dLeftGroups = dRightGroups;
1176 dRightGroups = tmpd;
1228 NIL,
NIL, NULL, 0,
false, -1);
1271 dNumGroups = dLeftGroups;
1272 dNumOutputRows = op->
all ? lpath->
rows : dNumGroups;
1276 dNumGroups = dLeftGroups;
1277 dNumOutputRows = op->
all ?
Min(lpath->
rows, rpath->
rows) : dNumGroups;
1279 result_rel->
rows = dNumOutputRows;
1291 elog(
ERROR,
"unrecognized set op: %d", (
int) op->
op);
1397 List *refnames_tlist,
1399 List **istrivial_tlist)
1407 *istrivial_tlist =
NIL;
1409 while (pending_rels !=
NIL)
1419 if (op->
op == top_union->
op &&
1420 (op->
all == top_union->
all || op->
all) &&
1421 equal(op->colTypes, top_union->colTypes) &&
1422 equal(op->colCollations, top_union->colCollations))
1425 pending_rels =
lcons(op->
rarg, pending_rels);
1426 pending_rels =
lcons(op->
larg, pending_rels);
1440 top_union->
all ? NULL : top_union,
1441 top_union->colTypes,
1442 top_union->colCollations,
1446 *tlist_list =
lappend(*tlist_list, child_tlist);
1447 *istrivial_tlist =
lappend_int(*istrivial_tlist, trivial_tlist);
1485 bool hack_constants,
1487 List *refnames_tlist,
1488 bool *trivial_tlist)
1499 *trivial_tlist =
true;
1501 forfour(ctlc, colTypes, cclc, colCollations,
1502 itlc, input_tlist, rtlc, refnames_tlist)
1511 Assert(!inputtle->resjunk);
1512 Assert(!reftle->resjunk);
1553 "UNION/INTERSECT/EXCEPT");
1554 *trivial_tlist =
false;
1573 *trivial_tlist =
false;
1613 List *refnames_tlist)
1634 foreach(tlistl, input_tlists)
1641 foreach(subtlistl, subtlist)
1645 Assert(!subtle->resjunk);
1646 Assert(curColType != NULL);
1653 colTypmods[colindex] = subtypmod;
1654 else if (subtypmod != colTypmods[colindex])
1655 colTypmods[colindex] = -1;
1660 colTypmods[colindex] = -1;
1662 curColType =
lnext(colTypes, curColType);
1665 Assert(curColType == NULL);
1672 forthree(curColType, colTypes, curColCollation, colCollations,
1673 ref_tl_item, refnames_tlist)
1676 int32 colTypmod = colTypmods[colindex++];
1681 Assert(!reftle->resjunk);
1727 foreach(lt, targetlist)
1740 lg =
lnext(grouplist, lg);
1764 double parent_rows = 0;
1765 double parent_size = 0;
1770 foreach(lc, child_pathlist)
1774 parent_rows += path->
rows;
1775 parent_size += path->parent->reltarget->width * path->
rows;
1778 if (parent_rows > 0)
1779 reltarget->
width = rint(parent_size / parent_rows);
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
int max_parallel_workers_per_gather
void set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel)
bool enable_parallel_append
bool enable_incremental_sort
int errdetail(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
bool equal(const void *a, const void *b)
void add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel, List *child_tlist, List *setop_pathkeys)
Assert(PointerIsAligned(start, uint64))
bool is_dummy_rel(RelOptInfo *rel)
void mark_dummy_rel(RelOptInfo *rel)
List * lappend(List *list, void *datum)
List * list_delete_first(List *list)
List * lappend_int(List *list, int datum)
List * lcons(void *datum, List *list)
Datum subpath(PG_FUNCTION_ARGS)
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
char * pstrdup(const char *in)
void pfree(void *pointer)
Oid exprType(const Node *expr)
int32 exprTypmod(const Node *expr)
Oid exprCollation(const Node *expr)
Node * applyRelabelType(Node *arg, Oid rtype, int32 rtypmod, Oid rcollid, CoercionForm rformat, int rlocation, bool overwrite_ok)
#define IsA(nodeptr, _type_)
#define castNode(_type_, nodeptr)
Node * coerce_to_common_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *context)
Path * get_cheapest_path_for_pathkeys(List *paths, List *pathkeys, Relids required_outer, CostSelector cost_criterion, bool require_parallel_safe)
bool pathkeys_count_contained_in(List *keys1, List *keys2, int *n_common)
List * make_pathkeys_for_sortclauses(PlannerInfo *root, List *sortclauses, List *tlist)
List * convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel, List *subquery_pathkeys, List *subquery_tlist)
bool pathkeys_contained_in(List *keys1, List *keys2)
SetOpPath * create_setop_path(PlannerInfo *root, RelOptInfo *rel, Path *leftpath, Path *rightpath, SetOpCmd cmd, SetOpStrategy strategy, List *groupList, double numGroups, double outputRows)
ProjectionPath * create_projection_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target)
Path * apply_projection_to_path(PlannerInfo *root, RelOptInfo *rel, Path *path, PathTarget *target)
void set_cheapest(RelOptInfo *parent_rel)
void add_partial_path(RelOptInfo *parent_rel, Path *new_path)
AppendPath * create_append_path(PlannerInfo *root, RelOptInfo *rel, List *subpaths, List *partial_subpaths, List *pathkeys, Relids required_outer, int parallel_workers, bool parallel_aware, double rows)
SubqueryScanPath * create_subqueryscan_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, bool trivial_pathtarget, List *pathkeys, Relids required_outer)
IncrementalSortPath * create_incremental_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, int presorted_keys, double limit_tuples)
SortPath * create_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, double limit_tuples)
GatherPath * create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, Relids required_outer, double *rows)
void add_path(RelOptInfo *parent_rel, Path *new_path)
UniquePath * create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, int numCols, double numGroups)
AggPath * create_agg_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, AggStrategy aggstrategy, AggSplit aggsplit, List *groupClause, List *qual, const AggClauseCosts *aggcosts, double numGroups)
RecursiveUnionPath * create_recursiveunion_path(PlannerInfo *root, RelOptInfo *rel, Path *leftpath, Path *rightpath, PathTarget *target, List *distinctList, int wtParam, double numGroups)
MergeAppendPath * create_merge_append_path(PlannerInfo *root, RelOptInfo *rel, List *subpaths, List *pathkeys, Relids required_outer)
static int pg_leftmost_one_pos32(uint32 word)
#define lfirst_node(type, lc)
static int list_length(const List *l)
#define forthree(cell1, list1, cell2, list2, cell3, list3)
#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4)
static ListCell * list_head(const List *l)
static ListCell * lnext(const List *l, const ListCell *c)
#define list_make2(x1, x2)
char * choose_plan_name(PlannerGlobal *glob, const char *name, bool always_number)
PlannerInfo * subquery_planner(PlannerGlobal *glob, Query *parse, char *plan_name, PlannerInfo *parent_root, bool hasRecursion, double tuple_fraction, SetOperationStmt *setops)
create_upper_paths_hook_type create_upper_paths_hook
RelOptInfo * plan_set_operations(PlannerInfo *root)
static List * generate_setop_grouplist(SetOperationStmt *op, List *targetlist)
static RelOptInfo * generate_union_paths(SetOperationStmt *op, PlannerInfo *root, List *refnames_tlist, List **pTargetList)
static RelOptInfo * generate_nonunion_paths(SetOperationStmt *op, PlannerInfo *root, List *refnames_tlist, List **pTargetList)
static PathTarget * create_setop_pathtarget(PlannerInfo *root, List *tlist, List *child_pathlist)
static void postprocess_setop_rel(PlannerInfo *root, RelOptInfo *rel)
static List * generate_setop_tlist(List *colTypes, List *colCollations, Index varno, bool hack_constants, List *input_tlist, List *refnames_tlist, bool *trivial_tlist)
static RelOptInfo * recurse_set_operations(Node *setOp, PlannerInfo *root, SetOperationStmt *parentOp, List *colTypes, List *colCollations, List *refnames_tlist, List **pTargetList, bool *istrivial_tlist)
static RelOptInfo * generate_recursion_path(SetOperationStmt *setOp, PlannerInfo *root, List *refnames_tlist, List **pTargetList)
static List * generate_append_tlist(List *colTypes, List *colCollations, List *input_tlists, List *refnames_tlist)
static List * plan_union_children(PlannerInfo *root, SetOperationStmt *top_union, List *refnames_tlist, List **tlist_list, List **istrivial_tlist)
static void build_setop_child_paths(PlannerInfo *root, RelOptInfo *rel, bool trivial_tlist, List *child_tlist, List *interesting_pathkeys, double *pNumGroups)
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
void setup_simple_rel_arrays(PlannerInfo *root)
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, List **pgset, EstimationInfo *estinfo)
void check_stack_depth(void)
struct PathTarget * reltarget
struct Path * cheapest_total_path
bool tlist_same_collations(List *tlist, List *colCollations, bool junkOK)
bool grouping_is_sortable(List *groupClause)
List * make_tlist_from_pathtarget(PathTarget *target)
List * get_tlist_exprs(List *tlist, bool includeJunk)
bool grouping_is_hashable(List *groupClause)
bool tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK)
#define create_pathtarget(root, tlist)