Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * pathnode.c
4 : * Routines to manipulate pathlists and create path nodes
5 : *
6 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/optimizer/util/pathnode.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include <math.h>
18 :
19 : #include "miscadmin.h"
20 : #include "nodes/nodeFuncs.h"
21 : #include "optimizer/clauses.h"
22 : #include "optimizer/cost.h"
23 : #include "optimizer/pathnode.h"
24 : #include "optimizer/paths.h"
25 : #include "optimizer/planmain.h"
26 : #include "optimizer/restrictinfo.h"
27 : #include "optimizer/var.h"
28 : #include "parser/parsetree.h"
29 : #include "utils/lsyscache.h"
30 : #include "utils/selfuncs.h"
31 :
32 :
33 : typedef enum
34 : {
35 : COSTS_EQUAL, /* path costs are fuzzily equal */
36 : COSTS_BETTER1, /* first path is cheaper than second */
37 : COSTS_BETTER2, /* second path is cheaper than first */
38 : COSTS_DIFFERENT /* neither path dominates the other on cost */
39 : } PathCostComparison;
40 :
41 : /*
42 : * STD_FUZZ_FACTOR is the normal fuzz factor for compare_path_costs_fuzzily.
43 : * XXX is it worth making this user-controllable? It provides a tradeoff
44 : * between planner runtime and the accuracy of path cost comparisons.
45 : */
46 : #define STD_FUZZ_FACTOR 1.01
47 :
48 : static List *translate_sub_tlist(List *tlist, int relid);
49 :
50 :
51 : /*****************************************************************************
52 : * MISC. PATH UTILITIES
53 : *****************************************************************************/
54 :
55 : /*
56 : * compare_path_costs
57 : * Return -1, 0, or +1 according as path1 is cheaper, the same cost,
58 : * or more expensive than path2 for the specified criterion.
59 : */
60 : int
61 14079 : compare_path_costs(Path *path1, Path *path2, CostSelector criterion)
62 : {
63 14079 : if (criterion == STARTUP_COST)
64 : {
65 6866 : if (path1->startup_cost < path2->startup_cost)
66 4791 : return -1;
67 2075 : if (path1->startup_cost > path2->startup_cost)
68 1403 : return +1;
69 :
70 : /*
71 : * If paths have the same startup cost (not at all unlikely), order
72 : * them by total cost.
73 : */
74 672 : if (path1->total_cost < path2->total_cost)
75 487 : return -1;
76 185 : if (path1->total_cost > path2->total_cost)
77 0 : return +1;
78 : }
79 : else
80 : {
81 7213 : if (path1->total_cost < path2->total_cost)
82 7021 : return -1;
83 192 : if (path1->total_cost > path2->total_cost)
84 22 : return +1;
85 :
86 : /*
87 : * If paths have the same total cost, order them by startup cost.
88 : */
89 170 : if (path1->startup_cost < path2->startup_cost)
90 0 : return -1;
91 170 : if (path1->startup_cost > path2->startup_cost)
92 0 : return +1;
93 : }
94 355 : return 0;
95 : }
96 :
97 : /*
98 : * compare_path_fractional_costs
99 : * Return -1, 0, or +1 according as path1 is cheaper, the same cost,
100 : * or more expensive than path2 for fetching the specified fraction
101 : * of the total tuples.
102 : *
103 : * If fraction is <= 0 or > 1, we interpret it as 1, ie, we select the
104 : * path with the cheaper total_cost.
105 : */
106 : int
107 195 : compare_fractional_path_costs(Path *path1, Path *path2,
108 : double fraction)
109 : {
110 : Cost cost1,
111 : cost2;
112 :
113 195 : if (fraction <= 0.0 || fraction >= 1.0)
114 131 : return compare_path_costs(path1, path2, TOTAL_COST);
115 192 : cost1 = path1->startup_cost +
116 128 : fraction * (path1->total_cost - path1->startup_cost);
117 192 : cost2 = path2->startup_cost +
118 128 : fraction * (path2->total_cost - path2->startup_cost);
119 64 : if (cost1 < cost2)
120 28 : return -1;
121 36 : if (cost1 > cost2)
122 36 : return +1;
123 0 : return 0;
124 : }
125 :
126 : /*
127 : * compare_path_costs_fuzzily
128 : * Compare the costs of two paths to see if either can be said to
129 : * dominate the other.
130 : *
131 : * We use fuzzy comparisons so that add_path() can avoid keeping both of
132 : * a pair of paths that really have insignificantly different cost.
133 : *
134 : * The fuzz_factor argument must be 1.0 plus delta, where delta is the
135 : * fraction of the smaller cost that is considered to be a significant
136 : * difference. For example, fuzz_factor = 1.01 makes the fuzziness limit
137 : * be 1% of the smaller cost.
138 : *
139 : * The two paths are said to have "equal" costs if both startup and total
140 : * costs are fuzzily the same. Path1 is said to be better than path2 if
141 : * it has fuzzily better startup cost and fuzzily no worse total cost,
142 : * or if it has fuzzily better total cost and fuzzily no worse startup cost.
143 : * Path2 is better than path1 if the reverse holds. Finally, if one path
144 : * is fuzzily better than the other on startup cost and fuzzily worse on
145 : * total cost, we just say that their costs are "different", since neither
146 : * dominates the other across the whole performance spectrum.
147 : *
148 : * This function also enforces a policy rule that paths for which the relevant
149 : * one of parent->consider_startup and parent->consider_param_startup is false
150 : * cannot survive comparisons solely on the grounds of good startup cost, so
151 : * we never return COSTS_DIFFERENT when that is true for the total-cost loser.
152 : * (But if total costs are fuzzily equal, we compare startup costs anyway,
153 : * in hopes of eliminating one path or the other.)
154 : */
155 : static PathCostComparison
156 83331 : compare_path_costs_fuzzily(Path *path1, Path *path2, double fuzz_factor)
157 : {
158 : #define CONSIDER_PATH_STARTUP_COST(p) \
159 : ((p)->param_info == NULL ? (p)->parent->consider_startup : (p)->parent->consider_param_startup)
160 :
161 : /*
162 : * Check total cost first since it's more likely to be different; many
163 : * paths have zero startup cost.
164 : */
165 83331 : if (path1->total_cost > path2->total_cost * fuzz_factor)
166 : {
167 : /* path1 fuzzily worse on total cost */
168 40533 : if (CONSIDER_PATH_STARTUP_COST(path1) &&
169 1013 : path2->startup_cost > path1->startup_cost * fuzz_factor)
170 : {
171 : /* ... but path2 fuzzily worse on startup, so DIFFERENT */
172 210 : return COSTS_DIFFERENT;
173 : }
174 : /* else path2 dominates */
175 39310 : return COSTS_BETTER2;
176 : }
177 43811 : if (path2->total_cost > path1->total_cost * fuzz_factor)
178 : {
179 : /* path2 fuzzily worse on total cost */
180 24259 : if (CONSIDER_PATH_STARTUP_COST(path2) &&
181 295 : path1->startup_cost > path2->startup_cost * fuzz_factor)
182 : {
183 : /* ... but path1 fuzzily worse on startup, so DIFFERENT */
184 188 : return COSTS_DIFFERENT;
185 : }
186 : /* else path1 dominates */
187 23776 : return COSTS_BETTER1;
188 : }
189 : /* fuzzily the same on total cost ... */
190 19847 : if (path1->startup_cost > path2->startup_cost * fuzz_factor)
191 : {
192 : /* ... but path1 fuzzily worse on startup, so path2 wins */
193 8123 : return COSTS_BETTER2;
194 : }
195 11724 : if (path2->startup_cost > path1->startup_cost * fuzz_factor)
196 : {
197 : /* ... but path2 fuzzily worse on startup, so path1 wins */
198 1367 : return COSTS_BETTER1;
199 : }
200 : /* fuzzily the same on both costs */
201 10357 : return COSTS_EQUAL;
202 :
203 : #undef CONSIDER_PATH_STARTUP_COST
204 : }
205 :
206 : /*
207 : * set_cheapest
208 : * Find the minimum-cost paths from among a relation's paths,
209 : * and save them in the rel's cheapest-path fields.
210 : *
211 : * cheapest_total_path is normally the cheapest-total-cost unparameterized
212 : * path; but if there are no unparameterized paths, we assign it to be the
213 : * best (cheapest least-parameterized) parameterized path. However, only
214 : * unparameterized paths are considered candidates for cheapest_startup_path,
215 : * so that will be NULL if there are no unparameterized paths.
216 : *
217 : * The cheapest_parameterized_paths list collects all parameterized paths
218 : * that have survived the add_path() tournament for this relation. (Since
219 : * add_path ignores pathkeys for a parameterized path, these will be paths
220 : * that have best cost or best row count for their parameterization. We
221 : * may also have both a parallel-safe and a non-parallel-safe path in some
222 : * cases for the same parameterization in some cases, but this should be
223 : * relatively rare since, most typically, all paths for the same relation
224 : * will be parallel-safe or none of them will.)
225 : *
226 : * cheapest_parameterized_paths always includes the cheapest-total
227 : * unparameterized path, too, if there is one; the users of that list find
228 : * it more convenient if that's included.
229 : *
230 : * This is normally called only after we've finished constructing the path
231 : * list for the rel node.
232 : */
233 : void
234 64213 : set_cheapest(RelOptInfo *parent_rel)
235 : {
236 : Path *cheapest_startup_path;
237 : Path *cheapest_total_path;
238 : Path *best_param_path;
239 : List *parameterized_paths;
240 : ListCell *p;
241 :
242 64213 : Assert(IsA(parent_rel, RelOptInfo));
243 :
244 64213 : if (parent_rel->pathlist == NIL)
245 0 : elog(ERROR, "could not devise a query plan for the given query");
246 :
247 64213 : cheapest_startup_path = cheapest_total_path = best_param_path = NULL;
248 64213 : parameterized_paths = NIL;
249 :
250 138493 : foreach(p, parent_rel->pathlist)
251 : {
252 74280 : Path *path = (Path *) lfirst(p);
253 : int cmp;
254 :
255 74280 : if (path->param_info)
256 : {
257 : /* Parameterized path, so add it to parameterized_paths */
258 3699 : parameterized_paths = lappend(parameterized_paths, path);
259 :
260 : /*
261 : * If we have an unparameterized cheapest-total, we no longer care
262 : * about finding the best parameterized path, so move on.
263 : */
264 3699 : if (cheapest_total_path)
265 489 : continue;
266 :
267 : /*
268 : * Otherwise, track the best parameterized path, which is the one
269 : * with least total cost among those of the minimum
270 : * parameterization.
271 : */
272 3210 : if (best_param_path == NULL)
273 2980 : best_param_path = path;
274 : else
275 : {
276 460 : switch (bms_subset_compare(PATH_REQ_OUTER(path),
277 460 : PATH_REQ_OUTER(best_param_path)))
278 : {
279 : case BMS_EQUAL:
280 : /* keep the cheaper one */
281 0 : if (compare_path_costs(path, best_param_path,
282 : TOTAL_COST) < 0)
283 0 : best_param_path = path;
284 0 : break;
285 : case BMS_SUBSET1:
286 : /* new path is less-parameterized */
287 13 : best_param_path = path;
288 13 : break;
289 : case BMS_SUBSET2:
290 : /* old path is less-parameterized, keep it */
291 0 : break;
292 : case BMS_DIFFERENT:
293 :
294 : /*
295 : * This means that neither path has the least possible
296 : * parameterization for the rel. We'll sit on the old
297 : * path until something better comes along.
298 : */
299 217 : break;
300 : }
301 : }
302 : }
303 : else
304 : {
305 : /* Unparameterized path, so consider it for cheapest slots */
306 70581 : if (cheapest_total_path == NULL)
307 : {
308 64031 : cheapest_startup_path = cheapest_total_path = path;
309 64031 : continue;
310 : }
311 :
312 : /*
313 : * If we find two paths of identical costs, try to keep the
314 : * better-sorted one. The paths might have unrelated sort
315 : * orderings, in which case we can only guess which might be
316 : * better to keep, but if one is superior then we definitely
317 : * should keep that one.
318 : */
319 6550 : cmp = compare_path_costs(cheapest_startup_path, path, STARTUP_COST);
320 6550 : if (cmp > 0 ||
321 8 : (cmp == 0 &&
322 8 : compare_pathkeys(cheapest_startup_path->pathkeys,
323 : path->pathkeys) == PATHKEYS_BETTER2))
324 1381 : cheapest_startup_path = path;
325 :
326 6550 : cmp = compare_path_costs(cheapest_total_path, path, TOTAL_COST);
327 6550 : if (cmp > 0 ||
328 0 : (cmp == 0 &&
329 0 : compare_pathkeys(cheapest_total_path->pathkeys,
330 : path->pathkeys) == PATHKEYS_BETTER2))
331 0 : cheapest_total_path = path;
332 : }
333 : }
334 :
335 : /* Add cheapest unparameterized path, if any, to parameterized_paths */
336 64213 : if (cheapest_total_path)
337 64031 : parameterized_paths = lcons(cheapest_total_path, parameterized_paths);
338 :
339 : /*
340 : * If there is no unparameterized path, use the best parameterized path as
341 : * cheapest_total_path (but not as cheapest_startup_path).
342 : */
343 64213 : if (cheapest_total_path == NULL)
344 182 : cheapest_total_path = best_param_path;
345 64213 : Assert(cheapest_total_path != NULL);
346 :
347 64213 : parent_rel->cheapest_startup_path = cheapest_startup_path;
348 64213 : parent_rel->cheapest_total_path = cheapest_total_path;
349 64213 : parent_rel->cheapest_unique_path = NULL; /* computed only if needed */
350 64213 : parent_rel->cheapest_parameterized_paths = parameterized_paths;
351 64213 : }
352 :
353 : /*
354 : * add_path
355 : * Consider a potential implementation path for the specified parent rel,
356 : * and add it to the rel's pathlist if it is worthy of consideration.
357 : * A path is worthy if it has a better sort order (better pathkeys) or
358 : * cheaper cost (on either dimension), or generates fewer rows, than any
359 : * existing path that has the same or superset parameterization rels.
360 : * We also consider parallel-safe paths more worthy than others.
361 : *
362 : * We also remove from the rel's pathlist any old paths that are dominated
363 : * by new_path --- that is, new_path is cheaper, at least as well ordered,
364 : * generates no more rows, requires no outer rels not required by the old
365 : * path, and is no less parallel-safe.
366 : *
367 : * In most cases, a path with a superset parameterization will generate
368 : * fewer rows (since it has more join clauses to apply), so that those two
369 : * figures of merit move in opposite directions; this means that a path of
370 : * one parameterization can seldom dominate a path of another. But such
371 : * cases do arise, so we make the full set of checks anyway.
372 : *
373 : * There are two policy decisions embedded in this function, along with
374 : * its sibling add_path_precheck. First, we treat all parameterized paths
375 : * as having NIL pathkeys, so that they cannot win comparisons on the
376 : * basis of sort order. This is to reduce the number of parameterized
377 : * paths that are kept; see discussion in src/backend/optimizer/README.
378 : *
379 : * Second, we only consider cheap startup cost to be interesting if
380 : * parent_rel->consider_startup is true for an unparameterized path, or
381 : * parent_rel->consider_param_startup is true for a parameterized one.
382 : * Again, this allows discarding useless paths sooner.
383 : *
384 : * The pathlist is kept sorted by total_cost, with cheaper paths
385 : * at the front. Within this routine, that's simply a speed hack:
386 : * doing it that way makes it more likely that we will reject an inferior
387 : * path after a few comparisons, rather than many comparisons.
388 : * However, add_path_precheck relies on this ordering to exit early
389 : * when possible.
390 : *
391 : * NOTE: discarded Path objects are immediately pfree'd to reduce planner
392 : * memory consumption. We dare not try to free the substructure of a Path,
393 : * since much of it may be shared with other Paths or the query tree itself;
394 : * but just recycling discarded Path nodes is a very useful savings in
395 : * a large join tree. We can recycle the List nodes of pathlist, too.
396 : *
397 : * As noted in optimizer/README, deleting a previously-accepted Path is
398 : * safe because we know that Paths of this rel cannot yet be referenced
399 : * from any other rel, such as a higher-level join. However, in some cases
400 : * it is possible that a Path is referenced by another Path for its own
401 : * rel; we must not delete such a Path, even if it is dominated by the new
402 : * Path. Currently this occurs only for IndexPath objects, which may be
403 : * referenced as children of BitmapHeapPaths as well as being paths in
404 : * their own right. Hence, we don't pfree IndexPaths when rejecting them.
405 : *
406 : * 'parent_rel' is the relation entry to which the path corresponds.
407 : * 'new_path' is a potential path for parent_rel.
408 : *
409 : * Returns nothing, but modifies parent_rel->pathlist.
410 : */
411 : void
412 128029 : add_path(RelOptInfo *parent_rel, Path *new_path)
413 : {
414 128029 : bool accept_new = true; /* unless we find a superior old path */
415 128029 : ListCell *insert_after = NULL; /* where to insert new item */
416 : List *new_path_pathkeys;
417 : ListCell *p1;
418 : ListCell *p1_prev;
419 : ListCell *p1_next;
420 :
421 : /*
422 : * This is a convenient place to check for query cancel --- no part of the
423 : * planner goes very long without calling add_path().
424 : */
425 128029 : CHECK_FOR_INTERRUPTS();
426 :
427 : /* Pretend parameterized paths have no pathkeys, per comment above */
428 128029 : new_path_pathkeys = new_path->param_info ? NIL : new_path->pathkeys;
429 :
430 : /*
431 : * Loop to check proposed new path against old paths. Note it is possible
432 : * for more than one old path to be tossed out because new_path dominates
433 : * it.
434 : *
435 : * We can't use foreach here because the loop body may delete the current
436 : * list cell.
437 : */
438 128029 : p1_prev = NULL;
439 168516 : for (p1 = list_head(parent_rel->pathlist); p1 != NULL; p1 = p1_next)
440 : {
441 76128 : Path *old_path = (Path *) lfirst(p1);
442 76128 : bool remove_old = false; /* unless new proves superior */
443 : PathCostComparison costcmp;
444 : PathKeysComparison keyscmp;
445 : BMS_Comparison outercmp;
446 :
447 76128 : p1_next = lnext(p1);
448 :
449 : /*
450 : * Do a fuzzy cost comparison with standard fuzziness limit.
451 : */
452 76128 : costcmp = compare_path_costs_fuzzily(new_path, old_path,
453 : STD_FUZZ_FACTOR);
454 :
455 : /*
456 : * If the two paths compare differently for startup and total cost,
457 : * then we want to keep both, and we can skip comparing pathkeys and
458 : * required_outer rels. If they compare the same, proceed with the
459 : * other comparisons. Row count is checked last. (We make the tests
460 : * in this order because the cost comparison is most likely to turn
461 : * out "different", and the pathkeys comparison next most likely. As
462 : * explained above, row count very seldom makes a difference, so even
463 : * though it's cheap to compare there's not much point in checking it
464 : * earlier.)
465 : */
466 76128 : if (costcmp != COSTS_DIFFERENT)
467 : {
468 : /* Similarly check to see if either dominates on pathkeys */
469 : List *old_path_pathkeys;
470 :
471 75730 : old_path_pathkeys = old_path->param_info ? NIL : old_path->pathkeys;
472 75730 : keyscmp = compare_pathkeys(new_path_pathkeys,
473 : old_path_pathkeys);
474 75730 : if (keyscmp != PATHKEYS_DIFFERENT)
475 : {
476 74887 : switch (costcmp)
477 : {
478 : case COSTS_EQUAL:
479 7721 : outercmp = bms_subset_compare(PATH_REQ_OUTER(new_path),
480 7721 : PATH_REQ_OUTER(old_path));
481 7636 : if (keyscmp == PATHKEYS_BETTER1)
482 : {
483 33 : if ((outercmp == BMS_EQUAL ||
484 33 : outercmp == BMS_SUBSET1) &&
485 66 : new_path->rows <= old_path->rows &&
486 33 : new_path->parallel_safe >= old_path->parallel_safe)
487 33 : remove_old = true; /* new dominates old */
488 : }
489 7603 : else if (keyscmp == PATHKEYS_BETTER2)
490 : {
491 324 : if ((outercmp == BMS_EQUAL ||
492 324 : outercmp == BMS_SUBSET2) &&
493 648 : new_path->rows >= old_path->rows &&
494 324 : new_path->parallel_safe <= old_path->parallel_safe)
495 324 : accept_new = false; /* old dominates new */
496 : }
497 : else /* keyscmp == PATHKEYS_EQUAL */
498 : {
499 7279 : if (outercmp == BMS_EQUAL)
500 : {
501 : /*
502 : * Same pathkeys and outer rels, and fuzzily
503 : * the same cost, so keep just one; to decide
504 : * which, first check parallel-safety, then
505 : * rows, then do a fuzzy cost comparison with
506 : * very small fuzz limit. (We used to do an
507 : * exact cost comparison, but that results in
508 : * annoying platform-specific plan variations
509 : * due to roundoff in the cost estimates.) If
510 : * things are still tied, arbitrarily keep
511 : * only the old path. Notice that we will
512 : * keep only the old path even if the
513 : * less-fuzzy comparison decides the startup
514 : * and total costs compare differently.
515 : */
516 14426 : if (new_path->parallel_safe >
517 7213 : old_path->parallel_safe)
518 2 : remove_old = true; /* new dominates old */
519 14422 : else if (new_path->parallel_safe <
520 7211 : old_path->parallel_safe)
521 8 : accept_new = false; /* old dominates new */
522 7203 : else if (new_path->rows < old_path->rows)
523 0 : remove_old = true; /* new dominates old */
524 7203 : else if (new_path->rows > old_path->rows)
525 0 : accept_new = false; /* old dominates new */
526 7203 : else if (compare_path_costs_fuzzily(new_path,
527 : old_path,
528 : 1.0000000001) == COSTS_BETTER1)
529 558 : remove_old = true; /* new dominates old */
530 : else
531 6645 : accept_new = false; /* old equals or
532 : * dominates new */
533 : }
534 66 : else if (outercmp == BMS_SUBSET1 &&
535 0 : new_path->rows <= old_path->rows &&
536 0 : new_path->parallel_safe >= old_path->parallel_safe)
537 0 : remove_old = true; /* new dominates old */
538 121 : else if (outercmp == BMS_SUBSET2 &&
539 110 : new_path->rows >= old_path->rows &&
540 55 : new_path->parallel_safe <= old_path->parallel_safe)
541 55 : accept_new = false; /* old dominates new */
542 : /* else different parameterizations, keep both */
543 : }
544 7636 : break;
545 : case COSTS_BETTER1:
546 24469 : if (keyscmp != PATHKEYS_BETTER2)
547 : {
548 18301 : outercmp = bms_subset_compare(PATH_REQ_OUTER(new_path),
549 18301 : PATH_REQ_OUTER(old_path));
550 17801 : if ((outercmp == BMS_EQUAL ||
551 14883 : outercmp == BMS_SUBSET1) &&
552 29742 : new_path->rows <= old_path->rows &&
553 14859 : new_path->parallel_safe >= old_path->parallel_safe)
554 14810 : remove_old = true; /* new dominates old */
555 : }
556 24469 : break;
557 : case COSTS_BETTER2:
558 42782 : if (keyscmp != PATHKEYS_BETTER1)
559 : {
560 37813 : outercmp = bms_subset_compare(PATH_REQ_OUTER(new_path),
561 37813 : PATH_REQ_OUTER(old_path));
562 32082 : if ((outercmp == BMS_EQUAL ||
563 29800 : outercmp == BMS_SUBSET2) &&
564 58572 : new_path->rows >= old_path->rows &&
565 28772 : new_path->parallel_safe <= old_path->parallel_safe)
566 28609 : accept_new = false; /* old dominates new */
567 : }
568 42782 : break;
569 : case COSTS_DIFFERENT:
570 :
571 : /*
572 : * can't get here, but keep this case to keep compiler
573 : * quiet
574 : */
575 0 : break;
576 : }
577 : }
578 : }
579 :
580 : /*
581 : * Remove current element from pathlist if dominated by new.
582 : */
583 76128 : if (remove_old)
584 : {
585 15403 : parent_rel->pathlist = list_delete_cell(parent_rel->pathlist,
586 : p1, p1_prev);
587 :
588 : /*
589 : * Delete the data pointed-to by the deleted cell, if possible
590 : */
591 15403 : if (!IsA(old_path, IndexPath))
592 14642 : pfree(old_path);
593 : /* p1_prev does not advance */
594 : }
595 : else
596 : {
597 : /* new belongs after this old path if it has cost >= old's */
598 60725 : if (new_path->total_cost >= old_path->total_cost)
599 49463 : insert_after = p1;
600 : /* p1_prev advances */
601 60725 : p1_prev = p1;
602 : }
603 :
604 : /*
605 : * If we found an old path that dominates new_path, we can quit
606 : * scanning the pathlist; we will not add new_path, and we assume
607 : * new_path cannot dominate any other elements of the pathlist.
608 : */
609 76128 : if (!accept_new)
610 35641 : break;
611 : }
612 :
613 128029 : if (accept_new)
614 : {
615 : /* Accept the new path: insert it at proper place in pathlist */
616 92388 : if (insert_after)
617 9014 : lappend_cell(parent_rel->pathlist, insert_after, new_path);
618 : else
619 83374 : parent_rel->pathlist = lcons(new_path, parent_rel->pathlist);
620 : }
621 : else
622 : {
623 : /* Reject and recycle the new path */
624 35641 : if (!IsA(new_path, IndexPath))
625 32667 : pfree(new_path);
626 : }
627 128029 : }
628 :
629 : /*
630 : * add_path_precheck
631 : * Check whether a proposed new path could possibly get accepted.
632 : * We assume we know the path's pathkeys and parameterization accurately,
633 : * and have lower bounds for its costs.
634 : *
635 : * Note that we do not know the path's rowcount, since getting an estimate for
636 : * that is too expensive to do before prechecking. We assume here that paths
637 : * of a superset parameterization will generate fewer rows; if that holds,
638 : * then paths with different parameterizations cannot dominate each other
639 : * and so we can simply ignore existing paths of another parameterization.
640 : * (In the infrequent cases where that rule of thumb fails, add_path will
641 : * get rid of the inferior path.)
642 : *
643 : * At the time this is called, we haven't actually built a Path structure,
644 : * so the required information has to be passed piecemeal.
645 : */
646 : bool
647 82379 : add_path_precheck(RelOptInfo *parent_rel,
648 : Cost startup_cost, Cost total_cost,
649 : List *pathkeys, Relids required_outer)
650 : {
651 : List *new_path_pathkeys;
652 : bool consider_startup;
653 : ListCell *p1;
654 :
655 : /* Pretend parameterized paths have no pathkeys, per add_path policy */
656 82379 : new_path_pathkeys = required_outer ? NIL : pathkeys;
657 :
658 : /* Decide whether new path's startup cost is interesting */
659 82379 : consider_startup = required_outer ? parent_rel->consider_param_startup : parent_rel->consider_startup;
660 :
661 95062 : foreach(p1, parent_rel->pathlist)
662 : {
663 88674 : Path *old_path = (Path *) lfirst(p1);
664 : PathKeysComparison keyscmp;
665 :
666 : /*
667 : * We are looking for an old_path with the same parameterization (and
668 : * by assumption the same rowcount) that dominates the new path on
669 : * pathkeys as well as both cost metrics. If we find one, we can
670 : * reject the new path.
671 : *
672 : * Cost comparisons here should match compare_path_costs_fuzzily.
673 : */
674 88674 : if (total_cost > old_path->total_cost * STD_FUZZ_FACTOR)
675 : {
676 : /* new path can win on startup cost only if consider_startup */
677 55680 : if (startup_cost > old_path->startup_cost * STD_FUZZ_FACTOR ||
678 : !consider_startup)
679 : {
680 : /* new path loses on cost, so check pathkeys... */
681 : List *old_path_pathkeys;
682 :
683 55578 : old_path_pathkeys = old_path->param_info ? NIL : old_path->pathkeys;
684 55578 : keyscmp = compare_pathkeys(new_path_pathkeys,
685 : old_path_pathkeys);
686 55578 : if (keyscmp == PATHKEYS_EQUAL ||
687 : keyscmp == PATHKEYS_BETTER2)
688 : {
689 : /* new path does not win on pathkeys... */
690 44668 : if (bms_equal(required_outer, PATH_REQ_OUTER(old_path)))
691 : {
692 : /* Found an old path that dominates the new one */
693 42997 : return false;
694 : }
695 : }
696 : }
697 : }
698 : else
699 : {
700 : /*
701 : * Since the pathlist is sorted by total_cost, we can stop looking
702 : * once we reach a path with a total_cost larger than the new
703 : * path's.
704 : */
705 32994 : break;
706 : }
707 : }
708 :
709 39382 : return true;
710 : }
711 :
712 : /*
713 : * add_partial_path
714 : * Like add_path, our goal here is to consider whether a path is worthy
715 : * of being kept around, but the considerations here are a bit different.
716 : * A partial path is one which can be executed in any number of workers in
717 : * parallel such that each worker will generate a subset of the path's
718 : * overall result.
719 : *
720 : * As in add_path, the partial_pathlist is kept sorted with the cheapest
721 : * total path in front. This is depended on by multiple places, which
722 : * just take the front entry as the cheapest path without searching.
723 : *
724 : * We don't generate parameterized partial paths for several reasons. Most
725 : * importantly, they're not safe to execute, because there's nothing to
726 : * make sure that a parallel scan within the parameterized portion of the
727 : * plan is running with the same value in every worker at the same time.
728 : * Fortunately, it seems unlikely to be worthwhile anyway, because having
729 : * each worker scan the entire outer relation and a subset of the inner
730 : * relation will generally be a terrible plan. The inner (parameterized)
731 : * side of the plan will be small anyway. There could be rare cases where
732 : * this wins big - e.g. if join order constraints put a 1-row relation on
733 : * the outer side of the topmost join with a parameterized plan on the inner
734 : * side - but we'll have to be content not to handle such cases until
735 : * somebody builds an executor infrastructure that can cope with them.
736 : *
737 : * Because we don't consider parameterized paths here, we also don't
738 : * need to consider the row counts as a measure of quality: every path will
739 : * produce the same number of rows. Neither do we need to consider startup
740 : * costs: parallelism is only used for plans that will be run to completion.
741 : * Therefore, this routine is much simpler than add_path: it needs to
742 : * consider only pathkeys and total cost.
743 : *
744 : * As with add_path, we pfree paths that are found to be dominated by
745 : * another partial path; this requires that there be no other references to
746 : * such paths yet. Hence, GatherPaths must not be created for a rel until
747 : * we're done creating all partial paths for it. Unlike add_path, we don't
748 : * take an exception for IndexPaths as partial index paths won't be
749 : * referenced by partial BitmapHeapPaths.
750 : */
751 : void
752 1344 : add_partial_path(RelOptInfo *parent_rel, Path *new_path)
753 : {
754 1344 : bool accept_new = true; /* unless we find a superior old path */
755 1344 : ListCell *insert_after = NULL; /* where to insert new item */
756 : ListCell *p1;
757 : ListCell *p1_prev;
758 : ListCell *p1_next;
759 :
760 : /* Check for query cancel. */
761 1344 : CHECK_FOR_INTERRUPTS();
762 :
763 : /*
764 : * As in add_path, throw out any paths which are dominated by the new
765 : * path, but throw out the new path if some existing path dominates it.
766 : */
767 1344 : p1_prev = NULL;
768 2875 : for (p1 = list_head(parent_rel->partial_pathlist); p1 != NULL;
769 187 : p1 = p1_next)
770 : {
771 429 : Path *old_path = (Path *) lfirst(p1);
772 429 : bool remove_old = false; /* unless new proves superior */
773 : PathKeysComparison keyscmp;
774 :
775 429 : p1_next = lnext(p1);
776 :
777 : /* Compare pathkeys. */
778 429 : keyscmp = compare_pathkeys(new_path->pathkeys, old_path->pathkeys);
779 :
780 : /* Unless pathkeys are incompable, keep just one of the two paths. */
781 429 : if (keyscmp != PATHKEYS_DIFFERENT)
782 : {
783 429 : if (new_path->total_cost > old_path->total_cost * STD_FUZZ_FACTOR)
784 : {
785 : /* New path costs more; keep it only if pathkeys are better. */
786 318 : if (keyscmp != PATHKEYS_BETTER1)
787 229 : accept_new = false;
788 : }
789 111 : else if (old_path->total_cost > new_path->total_cost
790 : * STD_FUZZ_FACTOR)
791 : {
792 : /* Old path costs more; keep it only if pathkeys are better. */
793 96 : if (keyscmp != PATHKEYS_BETTER2)
794 81 : remove_old = true;
795 : }
796 15 : else if (keyscmp == PATHKEYS_BETTER1)
797 : {
798 : /* Costs are about the same, new path has better pathkeys. */
799 0 : remove_old = true;
800 : }
801 15 : else if (keyscmp == PATHKEYS_BETTER2)
802 : {
803 : /* Costs are about the same, old path has better pathkeys. */
804 4 : accept_new = false;
805 : }
806 11 : else if (old_path->total_cost > new_path->total_cost * 1.0000000001)
807 : {
808 : /* Pathkeys are the same, and the old path costs more. */
809 2 : remove_old = true;
810 : }
811 : else
812 : {
813 : /*
814 : * Pathkeys are the same, and new path isn't materially
815 : * cheaper.
816 : */
817 9 : accept_new = false;
818 : }
819 : }
820 :
821 : /*
822 : * Remove current element from partial_pathlist if dominated by new.
823 : */
824 429 : if (remove_old)
825 : {
826 83 : parent_rel->partial_pathlist =
827 83 : list_delete_cell(parent_rel->partial_pathlist, p1, p1_prev);
828 83 : pfree(old_path);
829 : /* p1_prev does not advance */
830 : }
831 : else
832 : {
833 : /* new belongs after this old path if it has cost >= old's */
834 346 : if (new_path->total_cost >= old_path->total_cost)
835 327 : insert_after = p1;
836 : /* p1_prev advances */
837 346 : p1_prev = p1;
838 : }
839 :
840 : /*
841 : * If we found an old path that dominates new_path, we can quit
842 : * scanning the partial_pathlist; we will not add new_path, and we
843 : * assume new_path cannot dominate any later path.
844 : */
845 429 : if (!accept_new)
846 242 : break;
847 : }
848 :
849 1344 : if (accept_new)
850 : {
851 : /* Accept the new path: insert it at proper place */
852 1102 : if (insert_after)
853 87 : lappend_cell(parent_rel->partial_pathlist, insert_after, new_path);
854 : else
855 1015 : parent_rel->partial_pathlist =
856 1015 : lcons(new_path, parent_rel->partial_pathlist);
857 : }
858 : else
859 : {
860 : /* Reject and recycle the new path */
861 242 : pfree(new_path);
862 : }
863 1344 : }
864 :
865 : /*
866 : * add_partial_path_precheck
867 : * Check whether a proposed new partial path could possibly get accepted.
868 : *
869 : * Unlike add_path_precheck, we can ignore startup cost and parameterization,
870 : * since they don't matter for partial paths (see add_partial_path). But
871 : * we do want to make sure we don't add a partial path if there's already
872 : * a complete path that dominates it, since in that case the proposed path
873 : * is surely a loser.
874 : */
875 : bool
876 95 : add_partial_path_precheck(RelOptInfo *parent_rel, Cost total_cost,
877 : List *pathkeys)
878 : {
879 : ListCell *p1;
880 :
881 : /*
882 : * Our goal here is twofold. First, we want to find out whether this path
883 : * is clearly inferior to some existing partial path. If so, we want to
884 : * reject it immediately. Second, we want to find out whether this path
885 : * is clearly superior to some existing partial path -- at least, modulo
886 : * final cost computations. If so, we definitely want to consider it.
887 : *
888 : * Unlike add_path(), we always compare pathkeys here. This is because we
889 : * expect partial_pathlist to be very short, and getting a definitive
890 : * answer at this stage avoids the need to call add_path_precheck.
891 : */
892 99 : foreach(p1, parent_rel->partial_pathlist)
893 : {
894 73 : Path *old_path = (Path *) lfirst(p1);
895 : PathKeysComparison keyscmp;
896 :
897 73 : keyscmp = compare_pathkeys(pathkeys, old_path->pathkeys);
898 73 : if (keyscmp != PATHKEYS_DIFFERENT)
899 : {
900 73 : if (total_cost > old_path->total_cost * STD_FUZZ_FACTOR &&
901 : keyscmp != PATHKEYS_BETTER1)
902 33 : return false;
903 40 : if (old_path->total_cost > total_cost * STD_FUZZ_FACTOR &&
904 : keyscmp != PATHKEYS_BETTER2)
905 36 : return true;
906 : }
907 : }
908 :
909 : /*
910 : * This path is neither clearly inferior to an existing partial path nor
911 : * clearly good enough that it might replace one. Compare it to
912 : * non-parallel plans. If it loses even before accounting for the cost of
913 : * the Gather node, we should definitely reject it.
914 : *
915 : * Note that we pass the total_cost to add_path_precheck twice. This is
916 : * because it's never advantageous to consider the startup cost of a
917 : * partial path; the resulting plans, if run in parallel, will be run to
918 : * completion.
919 : */
920 26 : if (!add_path_precheck(parent_rel, total_cost, total_cost, pathkeys,
921 : NULL))
922 2 : return false;
923 :
924 24 : return true;
925 : }
926 :
927 :
928 : /*****************************************************************************
929 : * PATH NODE CREATION ROUTINES
930 : *****************************************************************************/
931 :
932 : /*
933 : * create_seqscan_path
934 : * Creates a path corresponding to a sequential scan, returning the
935 : * pathnode.
936 : */
937 : Path *
938 16197 : create_seqscan_path(PlannerInfo *root, RelOptInfo *rel,
939 : Relids required_outer, int parallel_workers)
940 : {
941 16197 : Path *pathnode = makeNode(Path);
942 :
943 16197 : pathnode->pathtype = T_SeqScan;
944 16197 : pathnode->parent = rel;
945 16197 : pathnode->pathtarget = rel->reltarget;
946 16197 : pathnode->param_info = get_baserel_parampathinfo(root, rel,
947 : required_outer);
948 16197 : pathnode->parallel_aware = parallel_workers > 0 ? true : false;
949 16197 : pathnode->parallel_safe = rel->consider_parallel;
950 16197 : pathnode->parallel_workers = parallel_workers;
951 16197 : pathnode->pathkeys = NIL; /* seqscan has unordered result */
952 :
953 16197 : cost_seqscan(pathnode, root, rel, pathnode->param_info);
954 :
955 16197 : return pathnode;
956 : }
957 :
958 : /*
959 : * create_samplescan_path
960 : * Creates a path node for a sampled table scan.
961 : */
962 : Path *
963 36 : create_samplescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
964 : {
965 36 : Path *pathnode = makeNode(Path);
966 :
967 36 : pathnode->pathtype = T_SampleScan;
968 36 : pathnode->parent = rel;
969 36 : pathnode->pathtarget = rel->reltarget;
970 36 : pathnode->param_info = get_baserel_parampathinfo(root, rel,
971 : required_outer);
972 36 : pathnode->parallel_aware = false;
973 36 : pathnode->parallel_safe = rel->consider_parallel;
974 36 : pathnode->parallel_workers = 0;
975 36 : pathnode->pathkeys = NIL; /* samplescan has unordered result */
976 :
977 36 : cost_samplescan(pathnode, root, rel, pathnode->param_info);
978 :
979 36 : return pathnode;
980 : }
981 :
982 : /*
983 : * create_index_path
984 : * Creates a path node for an index scan.
985 : *
986 : * 'index' is a usable index.
987 : * 'indexclauses' is a list of RestrictInfo nodes representing clauses
988 : * to be used as index qual conditions in the scan.
989 : * 'indexclausecols' is an integer list of index column numbers (zero based)
990 : * the indexclauses can be used with.
991 : * 'indexorderbys' is a list of bare expressions (no RestrictInfos)
992 : * to be used as index ordering operators in the scan.
993 : * 'indexorderbycols' is an integer list of index column numbers (zero based)
994 : * the ordering operators can be used with.
995 : * 'pathkeys' describes the ordering of the path.
996 : * 'indexscandir' is ForwardScanDirection or BackwardScanDirection
997 : * for an ordered index, or NoMovementScanDirection for
998 : * an unordered index.
999 : * 'indexonly' is true if an index-only scan is wanted.
1000 : * 'required_outer' is the set of outer relids for a parameterized path.
1001 : * 'loop_count' is the number of repetitions of the indexscan to factor into
1002 : * estimates of caching behavior.
1003 : * 'partial_path' is true if constructing a parallel index scan path.
1004 : *
1005 : * Returns the new path node.
1006 : */
1007 : IndexPath *
1008 22002 : create_index_path(PlannerInfo *root,
1009 : IndexOptInfo *index,
1010 : List *indexclauses,
1011 : List *indexclausecols,
1012 : List *indexorderbys,
1013 : List *indexorderbycols,
1014 : List *pathkeys,
1015 : ScanDirection indexscandir,
1016 : bool indexonly,
1017 : Relids required_outer,
1018 : double loop_count,
1019 : bool partial_path)
1020 : {
1021 22002 : IndexPath *pathnode = makeNode(IndexPath);
1022 22002 : RelOptInfo *rel = index->rel;
1023 : List *indexquals,
1024 : *indexqualcols;
1025 :
1026 22002 : pathnode->path.pathtype = indexonly ? T_IndexOnlyScan : T_IndexScan;
1027 22002 : pathnode->path.parent = rel;
1028 22002 : pathnode->path.pathtarget = rel->reltarget;
1029 22002 : pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1030 : required_outer);
1031 22002 : pathnode->path.parallel_aware = false;
1032 22002 : pathnode->path.parallel_safe = rel->consider_parallel;
1033 22002 : pathnode->path.parallel_workers = 0;
1034 22002 : pathnode->path.pathkeys = pathkeys;
1035 :
1036 : /* Convert clauses to indexquals the executor can handle */
1037 22002 : expand_indexqual_conditions(index, indexclauses, indexclausecols,
1038 : &indexquals, &indexqualcols);
1039 :
1040 : /* Fill in the pathnode */
1041 22002 : pathnode->indexinfo = index;
1042 22002 : pathnode->indexclauses = indexclauses;
1043 22002 : pathnode->indexquals = indexquals;
1044 22002 : pathnode->indexqualcols = indexqualcols;
1045 22002 : pathnode->indexorderbys = indexorderbys;
1046 22002 : pathnode->indexorderbycols = indexorderbycols;
1047 22002 : pathnode->indexscandir = indexscandir;
1048 :
1049 22002 : cost_index(pathnode, root, loop_count, partial_path);
1050 :
1051 22002 : return pathnode;
1052 : }
1053 :
1054 : /*
1055 : * create_bitmap_heap_path
1056 : * Creates a path node for a bitmap scan.
1057 : *
1058 : * 'bitmapqual' is a tree of IndexPath, BitmapAndPath, and BitmapOrPath nodes.
1059 : * 'required_outer' is the set of outer relids for a parameterized path.
1060 : * 'loop_count' is the number of repetitions of the indexscan to factor into
1061 : * estimates of caching behavior.
1062 : *
1063 : * loop_count should match the value used when creating the component
1064 : * IndexPaths.
1065 : */
1066 : BitmapHeapPath *
1067 10944 : create_bitmap_heap_path(PlannerInfo *root,
1068 : RelOptInfo *rel,
1069 : Path *bitmapqual,
1070 : Relids required_outer,
1071 : double loop_count,
1072 : int parallel_degree)
1073 : {
1074 10944 : BitmapHeapPath *pathnode = makeNode(BitmapHeapPath);
1075 :
1076 10944 : pathnode->path.pathtype = T_BitmapHeapScan;
1077 10944 : pathnode->path.parent = rel;
1078 10944 : pathnode->path.pathtarget = rel->reltarget;
1079 10944 : pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1080 : required_outer);
1081 10944 : pathnode->path.parallel_aware = parallel_degree > 0 ? true : false;
1082 10944 : pathnode->path.parallel_safe = rel->consider_parallel;
1083 10944 : pathnode->path.parallel_workers = parallel_degree;
1084 10944 : pathnode->path.pathkeys = NIL; /* always unordered */
1085 :
1086 10944 : pathnode->bitmapqual = bitmapqual;
1087 :
1088 10944 : cost_bitmap_heap_scan(&pathnode->path, root, rel,
1089 : pathnode->path.param_info,
1090 : bitmapqual, loop_count);
1091 :
1092 10944 : return pathnode;
1093 : }
1094 :
1095 : /*
1096 : * create_bitmap_and_path
1097 : * Creates a path node representing a BitmapAnd.
1098 : */
1099 : BitmapAndPath *
1100 3 : create_bitmap_and_path(PlannerInfo *root,
1101 : RelOptInfo *rel,
1102 : List *bitmapquals)
1103 : {
1104 3 : BitmapAndPath *pathnode = makeNode(BitmapAndPath);
1105 :
1106 3 : pathnode->path.pathtype = T_BitmapAnd;
1107 3 : pathnode->path.parent = rel;
1108 3 : pathnode->path.pathtarget = rel->reltarget;
1109 3 : pathnode->path.param_info = NULL; /* not used in bitmap trees */
1110 :
1111 : /*
1112 : * Currently, a BitmapHeapPath, BitmapAndPath, or BitmapOrPath will be
1113 : * parallel-safe if and only if rel->consider_parallel is set. So, we can
1114 : * set the flag for this path based only on the relation-level flag,
1115 : * without actually iterating over the list of children.
1116 : */
1117 3 : pathnode->path.parallel_aware = false;
1118 3 : pathnode->path.parallel_safe = rel->consider_parallel;
1119 3 : pathnode->path.parallel_workers = 0;
1120 :
1121 3 : pathnode->path.pathkeys = NIL; /* always unordered */
1122 :
1123 3 : pathnode->bitmapquals = bitmapquals;
1124 :
1125 : /* this sets bitmapselectivity as well as the regular cost fields: */
1126 3 : cost_bitmap_and_node(pathnode, root);
1127 :
1128 3 : return pathnode;
1129 : }
1130 :
1131 : /*
1132 : * create_bitmap_or_path
1133 : * Creates a path node representing a BitmapOr.
1134 : */
1135 : BitmapOrPath *
1136 45 : create_bitmap_or_path(PlannerInfo *root,
1137 : RelOptInfo *rel,
1138 : List *bitmapquals)
1139 : {
1140 45 : BitmapOrPath *pathnode = makeNode(BitmapOrPath);
1141 :
1142 45 : pathnode->path.pathtype = T_BitmapOr;
1143 45 : pathnode->path.parent = rel;
1144 45 : pathnode->path.pathtarget = rel->reltarget;
1145 45 : pathnode->path.param_info = NULL; /* not used in bitmap trees */
1146 :
1147 : /*
1148 : * Currently, a BitmapHeapPath, BitmapAndPath, or BitmapOrPath will be
1149 : * parallel-safe if and only if rel->consider_parallel is set. So, we can
1150 : * set the flag for this path based only on the relation-level flag,
1151 : * without actually iterating over the list of children.
1152 : */
1153 45 : pathnode->path.parallel_aware = false;
1154 45 : pathnode->path.parallel_safe = rel->consider_parallel;
1155 45 : pathnode->path.parallel_workers = 0;
1156 :
1157 45 : pathnode->path.pathkeys = NIL; /* always unordered */
1158 :
1159 45 : pathnode->bitmapquals = bitmapquals;
1160 :
1161 : /* this sets bitmapselectivity as well as the regular cost fields: */
1162 45 : cost_bitmap_or_node(pathnode, root);
1163 :
1164 45 : return pathnode;
1165 : }
1166 :
1167 : /*
1168 : * create_tidscan_path
1169 : * Creates a path corresponding to a scan by TID, returning the pathnode.
1170 : */
1171 : TidPath *
1172 66 : create_tidscan_path(PlannerInfo *root, RelOptInfo *rel, List *tidquals,
1173 : Relids required_outer)
1174 : {
1175 66 : TidPath *pathnode = makeNode(TidPath);
1176 :
1177 66 : pathnode->path.pathtype = T_TidScan;
1178 66 : pathnode->path.parent = rel;
1179 66 : pathnode->path.pathtarget = rel->reltarget;
1180 66 : pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1181 : required_outer);
1182 66 : pathnode->path.parallel_aware = false;
1183 66 : pathnode->path.parallel_safe = rel->consider_parallel;
1184 66 : pathnode->path.parallel_workers = 0;
1185 66 : pathnode->path.pathkeys = NIL; /* always unordered */
1186 :
1187 66 : pathnode->tidquals = tidquals;
1188 :
1189 66 : cost_tidscan(&pathnode->path, root, rel, tidquals,
1190 : pathnode->path.param_info);
1191 :
1192 66 : return pathnode;
1193 : }
1194 :
1195 : /*
1196 : * create_append_path
1197 : * Creates a path corresponding to an Append plan, returning the
1198 : * pathnode.
1199 : *
1200 : * Note that we must handle subpaths = NIL, representing a dummy access path.
1201 : */
1202 : AppendPath *
1203 1069 : create_append_path(RelOptInfo *rel, List *subpaths, Relids required_outer,
1204 : int parallel_workers, List *partitioned_rels)
1205 : {
1206 1069 : AppendPath *pathnode = makeNode(AppendPath);
1207 : ListCell *l;
1208 :
1209 1069 : pathnode->path.pathtype = T_Append;
1210 1069 : pathnode->path.parent = rel;
1211 1069 : pathnode->path.pathtarget = rel->reltarget;
1212 1069 : pathnode->path.param_info = get_appendrel_parampathinfo(rel,
1213 : required_outer);
1214 1069 : pathnode->path.parallel_aware = false;
1215 1069 : pathnode->path.parallel_safe = rel->consider_parallel;
1216 1069 : pathnode->path.parallel_workers = parallel_workers;
1217 1069 : pathnode->path.pathkeys = NIL; /* result is always considered unsorted */
1218 1069 : pathnode->partitioned_rels = list_copy(partitioned_rels);
1219 1069 : pathnode->subpaths = subpaths;
1220 :
1221 : /*
1222 : * We don't bother with inventing a cost_append(), but just do it here.
1223 : *
1224 : * Compute rows and costs as sums of subplan rows and costs. We charge
1225 : * nothing extra for the Append itself, which perhaps is too optimistic,
1226 : * but since it doesn't do any selection or projection, it is a pretty
1227 : * cheap node.
1228 : */
1229 1069 : pathnode->path.rows = 0;
1230 1069 : pathnode->path.startup_cost = 0;
1231 1069 : pathnode->path.total_cost = 0;
1232 3495 : foreach(l, subpaths)
1233 : {
1234 2426 : Path *subpath = (Path *) lfirst(l);
1235 :
1236 2426 : pathnode->path.rows += subpath->rows;
1237 :
1238 2426 : if (l == list_head(subpaths)) /* first node? */
1239 930 : pathnode->path.startup_cost = subpath->startup_cost;
1240 2426 : pathnode->path.total_cost += subpath->total_cost;
1241 4092 : pathnode->path.parallel_safe = pathnode->path.parallel_safe &&
1242 1666 : subpath->parallel_safe;
1243 :
1244 : /* All child paths must have same parameterization */
1245 2426 : Assert(bms_equal(PATH_REQ_OUTER(subpath), required_outer));
1246 : }
1247 :
1248 1069 : return pathnode;
1249 : }
1250 :
1251 : /*
1252 : * create_merge_append_path
1253 : * Creates a path corresponding to a MergeAppend plan, returning the
1254 : * pathnode.
1255 : */
1256 : MergeAppendPath *
1257 81 : create_merge_append_path(PlannerInfo *root,
1258 : RelOptInfo *rel,
1259 : List *subpaths,
1260 : List *pathkeys,
1261 : Relids required_outer,
1262 : List *partitioned_rels)
1263 : {
1264 81 : MergeAppendPath *pathnode = makeNode(MergeAppendPath);
1265 : Cost input_startup_cost;
1266 : Cost input_total_cost;
1267 : ListCell *l;
1268 :
1269 81 : pathnode->path.pathtype = T_MergeAppend;
1270 81 : pathnode->path.parent = rel;
1271 81 : pathnode->path.pathtarget = rel->reltarget;
1272 81 : pathnode->path.param_info = get_appendrel_parampathinfo(rel,
1273 : required_outer);
1274 81 : pathnode->path.parallel_aware = false;
1275 81 : pathnode->path.parallel_safe = rel->consider_parallel;
1276 81 : pathnode->path.parallel_workers = 0;
1277 81 : pathnode->path.pathkeys = pathkeys;
1278 81 : pathnode->partitioned_rels = list_copy(partitioned_rels);
1279 81 : pathnode->subpaths = subpaths;
1280 :
1281 : /*
1282 : * Apply query-wide LIMIT if known and path is for sole base relation.
1283 : * (Handling this at this low level is a bit klugy.)
1284 : */
1285 81 : if (bms_equal(rel->relids, root->all_baserels))
1286 36 : pathnode->limit_tuples = root->limit_tuples;
1287 : else
1288 45 : pathnode->limit_tuples = -1.0;
1289 :
1290 : /*
1291 : * Add up the sizes and costs of the input paths.
1292 : */
1293 81 : pathnode->path.rows = 0;
1294 81 : input_startup_cost = 0;
1295 81 : input_total_cost = 0;
1296 293 : foreach(l, subpaths)
1297 : {
1298 212 : Path *subpath = (Path *) lfirst(l);
1299 :
1300 212 : pathnode->path.rows += subpath->rows;
1301 355 : pathnode->path.parallel_safe = pathnode->path.parallel_safe &&
1302 143 : subpath->parallel_safe;
1303 :
1304 212 : if (pathkeys_contained_in(pathkeys, subpath->pathkeys))
1305 : {
1306 : /* Subpath is adequately ordered, we won't need to sort it */
1307 173 : input_startup_cost += subpath->startup_cost;
1308 173 : input_total_cost += subpath->total_cost;
1309 : }
1310 : else
1311 : {
1312 : /* We'll need to insert a Sort node, so include cost for that */
1313 : Path sort_path; /* dummy for result of cost_sort */
1314 :
1315 117 : cost_sort(&sort_path,
1316 : root,
1317 : pathkeys,
1318 : subpath->total_cost,
1319 39 : subpath->parent->tuples,
1320 39 : subpath->pathtarget->width,
1321 : 0.0,
1322 : work_mem,
1323 : pathnode->limit_tuples);
1324 39 : input_startup_cost += sort_path.startup_cost;
1325 39 : input_total_cost += sort_path.total_cost;
1326 : }
1327 :
1328 : /* All child paths must have same parameterization */
1329 212 : Assert(bms_equal(PATH_REQ_OUTER(subpath), required_outer));
1330 : }
1331 :
1332 : /* Now we can compute total costs of the MergeAppend */
1333 81 : cost_merge_append(&pathnode->path, root,
1334 : pathkeys, list_length(subpaths),
1335 : input_startup_cost, input_total_cost,
1336 : pathnode->path.rows);
1337 :
1338 81 : return pathnode;
1339 : }
1340 :
1341 : /*
1342 : * create_result_path
1343 : * Creates a path representing a Result-and-nothing-else plan.
1344 : *
1345 : * This is only used for degenerate cases, such as a query with an empty
1346 : * jointree.
1347 : */
1348 : ResultPath *
1349 11509 : create_result_path(PlannerInfo *root, RelOptInfo *rel,
1350 : PathTarget *target, List *resconstantqual)
1351 : {
1352 11509 : ResultPath *pathnode = makeNode(ResultPath);
1353 :
1354 11509 : pathnode->path.pathtype = T_Result;
1355 11509 : pathnode->path.parent = rel;
1356 11509 : pathnode->path.pathtarget = target;
1357 11509 : pathnode->path.param_info = NULL; /* there are no other rels... */
1358 11509 : pathnode->path.parallel_aware = false;
1359 11509 : pathnode->path.parallel_safe = rel->consider_parallel;
1360 11509 : pathnode->path.parallel_workers = 0;
1361 11509 : pathnode->path.pathkeys = NIL;
1362 11509 : pathnode->quals = resconstantqual;
1363 :
1364 : /* Hardly worth defining a cost_result() function ... just do it */
1365 11509 : pathnode->path.rows = 1;
1366 11509 : pathnode->path.startup_cost = target->cost.startup;
1367 23018 : pathnode->path.total_cost = target->cost.startup +
1368 11509 : cpu_tuple_cost + target->cost.per_tuple;
1369 11509 : if (resconstantqual)
1370 : {
1371 : QualCost qual_cost;
1372 :
1373 63 : cost_qual_eval(&qual_cost, resconstantqual, root);
1374 : /* resconstantqual is evaluated once at startup */
1375 63 : pathnode->path.startup_cost += qual_cost.startup + qual_cost.per_tuple;
1376 63 : pathnode->path.total_cost += qual_cost.startup + qual_cost.per_tuple;
1377 : }
1378 :
1379 11509 : return pathnode;
1380 : }
1381 :
1382 : /*
1383 : * create_material_path
1384 : * Creates a path corresponding to a Material plan, returning the
1385 : * pathnode.
1386 : */
1387 : MaterialPath *
1388 12691 : create_material_path(RelOptInfo *rel, Path *subpath)
1389 : {
1390 12691 : MaterialPath *pathnode = makeNode(MaterialPath);
1391 :
1392 12691 : Assert(subpath->parent == rel);
1393 :
1394 12691 : pathnode->path.pathtype = T_Material;
1395 12691 : pathnode->path.parent = rel;
1396 12691 : pathnode->path.pathtarget = rel->reltarget;
1397 12691 : pathnode->path.param_info = subpath->param_info;
1398 12691 : pathnode->path.parallel_aware = false;
1399 21856 : pathnode->path.parallel_safe = rel->consider_parallel &&
1400 9165 : subpath->parallel_safe;
1401 12691 : pathnode->path.parallel_workers = subpath->parallel_workers;
1402 12691 : pathnode->path.pathkeys = subpath->pathkeys;
1403 :
1404 12691 : pathnode->subpath = subpath;
1405 :
1406 12691 : cost_material(&pathnode->path,
1407 : subpath->startup_cost,
1408 : subpath->total_cost,
1409 : subpath->rows,
1410 12691 : subpath->pathtarget->width);
1411 :
1412 12691 : return pathnode;
1413 : }
1414 :
1415 : /*
1416 : * create_unique_path
1417 : * Creates a path representing elimination of distinct rows from the
1418 : * input data. Distinct-ness is defined according to the needs of the
1419 : * semijoin represented by sjinfo. If it is not possible to identify
1420 : * how to make the data unique, NULL is returned.
1421 : *
1422 : * If used at all, this is likely to be called repeatedly on the same rel;
1423 : * and the input subpath should always be the same (the cheapest_total path
1424 : * for the rel). So we cache the result.
1425 : */
1426 : UniquePath *
1427 1781 : create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
1428 : SpecialJoinInfo *sjinfo)
1429 : {
1430 : UniquePath *pathnode;
1431 : Path sort_path; /* dummy for result of cost_sort */
1432 : Path agg_path; /* dummy for result of cost_agg */
1433 : MemoryContext oldcontext;
1434 : int numCols;
1435 :
1436 : /* Caller made a mistake if subpath isn't cheapest_total ... */
1437 1781 : Assert(subpath == rel->cheapest_total_path);
1438 1781 : Assert(subpath->parent == rel);
1439 : /* ... or if SpecialJoinInfo is the wrong one */
1440 1781 : Assert(sjinfo->jointype == JOIN_SEMI);
1441 1781 : Assert(bms_equal(rel->relids, sjinfo->syn_righthand));
1442 :
1443 : /* If result already cached, return it */
1444 1781 : if (rel->cheapest_unique_path)
1445 1467 : return (UniquePath *) rel->cheapest_unique_path;
1446 :
1447 : /* If it's not possible to unique-ify, return NULL */
1448 314 : if (!(sjinfo->semi_can_btree || sjinfo->semi_can_hash))
1449 8 : return NULL;
1450 :
1451 : /*
1452 : * We must ensure path struct and subsidiary data are allocated in main
1453 : * planning context; otherwise GEQO memory management causes trouble.
1454 : */
1455 306 : oldcontext = MemoryContextSwitchTo(root->planner_cxt);
1456 :
1457 306 : pathnode = makeNode(UniquePath);
1458 :
1459 306 : pathnode->path.pathtype = T_Unique;
1460 306 : pathnode->path.parent = rel;
1461 306 : pathnode->path.pathtarget = rel->reltarget;
1462 306 : pathnode->path.param_info = subpath->param_info;
1463 306 : pathnode->path.parallel_aware = false;
1464 597 : pathnode->path.parallel_safe = rel->consider_parallel &&
1465 291 : subpath->parallel_safe;
1466 306 : pathnode->path.parallel_workers = subpath->parallel_workers;
1467 :
1468 : /*
1469 : * Assume the output is unsorted, since we don't necessarily have pathkeys
1470 : * to represent it. (This might get overridden below.)
1471 : */
1472 306 : pathnode->path.pathkeys = NIL;
1473 :
1474 306 : pathnode->subpath = subpath;
1475 306 : pathnode->in_operators = sjinfo->semi_operators;
1476 306 : pathnode->uniq_exprs = sjinfo->semi_rhs_exprs;
1477 :
1478 : /*
1479 : * If the input is a relation and it has a unique index that proves the
1480 : * semi_rhs_exprs are unique, then we don't need to do anything. Note
1481 : * that relation_has_unique_index_for automatically considers restriction
1482 : * clauses for the rel, as well.
1483 : */
1484 338 : if (rel->rtekind == RTE_RELATION && sjinfo->semi_can_btree &&
1485 32 : relation_has_unique_index_for(root, rel, NIL,
1486 : sjinfo->semi_rhs_exprs,
1487 : sjinfo->semi_operators))
1488 : {
1489 0 : pathnode->umethod = UNIQUE_PATH_NOOP;
1490 0 : pathnode->path.rows = rel->rows;
1491 0 : pathnode->path.startup_cost = subpath->startup_cost;
1492 0 : pathnode->path.total_cost = subpath->total_cost;
1493 0 : pathnode->path.pathkeys = subpath->pathkeys;
1494 :
1495 0 : rel->cheapest_unique_path = (Path *) pathnode;
1496 :
1497 0 : MemoryContextSwitchTo(oldcontext);
1498 :
1499 0 : return pathnode;
1500 : }
1501 :
1502 : /*
1503 : * If the input is a subquery whose output must be unique already, then we
1504 : * don't need to do anything. The test for uniqueness has to consider
1505 : * exactly which columns we are extracting; for example "SELECT DISTINCT
1506 : * x,y" doesn't guarantee that x alone is distinct. So we cannot check for
1507 : * this optimization unless semi_rhs_exprs consists only of simple Vars
1508 : * referencing subquery outputs. (Possibly we could do something with
1509 : * expressions in the subquery outputs, too, but for now keep it simple.)
1510 : */
1511 306 : if (rel->rtekind == RTE_SUBQUERY)
1512 : {
1513 8 : RangeTblEntry *rte = planner_rt_fetch(rel->relid, root);
1514 :
1515 8 : if (query_supports_distinctness(rte->subquery))
1516 : {
1517 : List *sub_tlist_colnos;
1518 :
1519 3 : sub_tlist_colnos = translate_sub_tlist(sjinfo->semi_rhs_exprs,
1520 3 : rel->relid);
1521 :
1522 6 : if (sub_tlist_colnos &&
1523 3 : query_is_distinct_for(rte->subquery,
1524 : sub_tlist_colnos,
1525 : sjinfo->semi_operators))
1526 : {
1527 0 : pathnode->umethod = UNIQUE_PATH_NOOP;
1528 0 : pathnode->path.rows = rel->rows;
1529 0 : pathnode->path.startup_cost = subpath->startup_cost;
1530 0 : pathnode->path.total_cost = subpath->total_cost;
1531 0 : pathnode->path.pathkeys = subpath->pathkeys;
1532 :
1533 0 : rel->cheapest_unique_path = (Path *) pathnode;
1534 :
1535 0 : MemoryContextSwitchTo(oldcontext);
1536 :
1537 0 : return pathnode;
1538 : }
1539 : }
1540 : }
1541 :
1542 : /* Estimate number of output rows */
1543 306 : pathnode->path.rows = estimate_num_groups(root,
1544 : sjinfo->semi_rhs_exprs,
1545 : rel->rows,
1546 : NULL);
1547 306 : numCols = list_length(sjinfo->semi_rhs_exprs);
1548 :
1549 306 : if (sjinfo->semi_can_btree)
1550 : {
1551 : /*
1552 : * Estimate cost for sort+unique implementation
1553 : */
1554 612 : cost_sort(&sort_path, root, NIL,
1555 : subpath->total_cost,
1556 : rel->rows,
1557 306 : subpath->pathtarget->width,
1558 : 0.0,
1559 : work_mem,
1560 : -1.0);
1561 :
1562 : /*
1563 : * Charge one cpu_operator_cost per comparison per input tuple. We
1564 : * assume all columns get compared at most of the tuples. (XXX
1565 : * probably this is an overestimate.) This should agree with
1566 : * create_upper_unique_path.
1567 : */
1568 306 : sort_path.total_cost += cpu_operator_cost * rel->rows * numCols;
1569 : }
1570 :
1571 306 : if (sjinfo->semi_can_hash)
1572 : {
1573 : /*
1574 : * Estimate the overhead per hashtable entry at 64 bytes (same as in
1575 : * planner.c).
1576 : */
1577 301 : int hashentrysize = subpath->pathtarget->width + 64;
1578 :
1579 301 : if (hashentrysize * pathnode->path.rows > work_mem * 1024L)
1580 : {
1581 : /*
1582 : * We should not try to hash. Hack the SpecialJoinInfo to
1583 : * remember this, in case we come through here again.
1584 : */
1585 0 : sjinfo->semi_can_hash = false;
1586 : }
1587 : else
1588 301 : cost_agg(&agg_path, root,
1589 : AGG_HASHED, NULL,
1590 : numCols, pathnode->path.rows,
1591 : subpath->startup_cost,
1592 : subpath->total_cost,
1593 : rel->rows);
1594 : }
1595 :
1596 306 : if (sjinfo->semi_can_btree && sjinfo->semi_can_hash)
1597 : {
1598 602 : if (agg_path.total_cost < sort_path.total_cost)
1599 299 : pathnode->umethod = UNIQUE_PATH_HASH;
1600 : else
1601 2 : pathnode->umethod = UNIQUE_PATH_SORT;
1602 : }
1603 5 : else if (sjinfo->semi_can_btree)
1604 5 : pathnode->umethod = UNIQUE_PATH_SORT;
1605 0 : else if (sjinfo->semi_can_hash)
1606 0 : pathnode->umethod = UNIQUE_PATH_HASH;
1607 : else
1608 : {
1609 : /* we can get here only if we abandoned hashing above */
1610 0 : MemoryContextSwitchTo(oldcontext);
1611 0 : return NULL;
1612 : }
1613 :
1614 306 : if (pathnode->umethod == UNIQUE_PATH_HASH)
1615 : {
1616 299 : pathnode->path.startup_cost = agg_path.startup_cost;
1617 299 : pathnode->path.total_cost = agg_path.total_cost;
1618 : }
1619 : else
1620 : {
1621 7 : pathnode->path.startup_cost = sort_path.startup_cost;
1622 7 : pathnode->path.total_cost = sort_path.total_cost;
1623 : }
1624 :
1625 306 : rel->cheapest_unique_path = (Path *) pathnode;
1626 :
1627 306 : MemoryContextSwitchTo(oldcontext);
1628 :
1629 306 : return pathnode;
1630 : }
1631 :
1632 : /*
1633 : * create_gather_merge_path
1634 : *
1635 : * Creates a path corresponding to a gather merge scan, returning
1636 : * the pathnode.
1637 : */
1638 : GatherMergePath *
1639 46 : create_gather_merge_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
1640 : PathTarget *target, List *pathkeys,
1641 : Relids required_outer, double *rows)
1642 : {
1643 46 : GatherMergePath *pathnode = makeNode(GatherMergePath);
1644 46 : Cost input_startup_cost = 0;
1645 46 : Cost input_total_cost = 0;
1646 :
1647 46 : Assert(subpath->parallel_safe);
1648 46 : Assert(pathkeys);
1649 :
1650 46 : pathnode->path.pathtype = T_GatherMerge;
1651 46 : pathnode->path.parent = rel;
1652 46 : pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1653 : required_outer);
1654 46 : pathnode->path.parallel_aware = false;
1655 :
1656 46 : pathnode->subpath = subpath;
1657 46 : pathnode->num_workers = subpath->parallel_workers;
1658 46 : pathnode->path.pathkeys = pathkeys;
1659 46 : pathnode->path.pathtarget = target ? target : rel->reltarget;
1660 46 : pathnode->path.rows += subpath->rows;
1661 :
1662 46 : if (pathkeys_contained_in(pathkeys, subpath->pathkeys))
1663 : {
1664 : /* Subpath is adequately ordered, we won't need to sort it */
1665 46 : input_startup_cost += subpath->startup_cost;
1666 46 : input_total_cost += subpath->total_cost;
1667 : }
1668 : else
1669 : {
1670 : /* We'll need to insert a Sort node, so include cost for that */
1671 : Path sort_path; /* dummy for result of cost_sort */
1672 :
1673 0 : cost_sort(&sort_path,
1674 : root,
1675 : pathkeys,
1676 : subpath->total_cost,
1677 : subpath->rows,
1678 0 : subpath->pathtarget->width,
1679 : 0.0,
1680 : work_mem,
1681 : -1);
1682 0 : input_startup_cost += sort_path.startup_cost;
1683 0 : input_total_cost += sort_path.total_cost;
1684 : }
1685 :
1686 46 : cost_gather_merge(pathnode, root, rel, pathnode->path.param_info,
1687 : input_startup_cost, input_total_cost, rows);
1688 :
1689 46 : return pathnode;
1690 : }
1691 :
1692 : /*
1693 : * translate_sub_tlist - get subquery column numbers represented by tlist
1694 : *
1695 : * The given targetlist usually contains only Vars referencing the given relid.
1696 : * Extract their varattnos (ie, the column numbers of the subquery) and return
1697 : * as an integer List.
1698 : *
1699 : * If any of the tlist items is not a simple Var, we cannot determine whether
1700 : * the subquery's uniqueness condition (if any) matches ours, so punt and
1701 : * return NIL.
1702 : */
1703 : static List *
1704 3 : translate_sub_tlist(List *tlist, int relid)
1705 : {
1706 3 : List *result = NIL;
1707 : ListCell *l;
1708 :
1709 6 : foreach(l, tlist)
1710 : {
1711 3 : Var *var = (Var *) lfirst(l);
1712 :
1713 6 : if (!var || !IsA(var, Var) ||
1714 3 : var->varno != relid)
1715 0 : return NIL; /* punt */
1716 :
1717 3 : result = lappend_int(result, var->varattno);
1718 : }
1719 3 : return result;
1720 : }
1721 :
1722 : /*
1723 : * create_gather_path
1724 : * Creates a path corresponding to a gather scan, returning the
1725 : * pathnode.
1726 : *
1727 : * 'rows' may optionally be set to override row estimates from other sources.
1728 : */
1729 : GatherPath *
1730 314 : create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
1731 : PathTarget *target, Relids required_outer, double *rows)
1732 : {
1733 314 : GatherPath *pathnode = makeNode(GatherPath);
1734 :
1735 314 : Assert(subpath->parallel_safe);
1736 :
1737 314 : pathnode->path.pathtype = T_Gather;
1738 314 : pathnode->path.parent = rel;
1739 314 : pathnode->path.pathtarget = target;
1740 314 : pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1741 : required_outer);
1742 314 : pathnode->path.parallel_aware = false;
1743 314 : pathnode->path.parallel_safe = false;
1744 314 : pathnode->path.parallel_workers = 0;
1745 314 : pathnode->path.pathkeys = NIL; /* Gather has unordered result */
1746 :
1747 314 : pathnode->subpath = subpath;
1748 314 : pathnode->num_workers = subpath->parallel_workers;
1749 314 : pathnode->single_copy = false;
1750 :
1751 314 : if (pathnode->num_workers == 0)
1752 : {
1753 0 : pathnode->path.pathkeys = subpath->pathkeys;
1754 0 : pathnode->num_workers = 1;
1755 0 : pathnode->single_copy = true;
1756 : }
1757 :
1758 314 : cost_gather(pathnode, root, rel, pathnode->path.param_info, rows);
1759 :
1760 314 : return pathnode;
1761 : }
1762 :
1763 : /*
1764 : * create_subqueryscan_path
1765 : * Creates a path corresponding to a scan of a subquery,
1766 : * returning the pathnode.
1767 : */
1768 : SubqueryScanPath *
1769 1111 : create_subqueryscan_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
1770 : List *pathkeys, Relids required_outer)
1771 : {
1772 1111 : SubqueryScanPath *pathnode = makeNode(SubqueryScanPath);
1773 :
1774 1111 : pathnode->path.pathtype = T_SubqueryScan;
1775 1111 : pathnode->path.parent = rel;
1776 1111 : pathnode->path.pathtarget = rel->reltarget;
1777 1111 : pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1778 : required_outer);
1779 1111 : pathnode->path.parallel_aware = false;
1780 1761 : pathnode->path.parallel_safe = rel->consider_parallel &&
1781 650 : subpath->parallel_safe;
1782 1111 : pathnode->path.parallel_workers = subpath->parallel_workers;
1783 1111 : pathnode->path.pathkeys = pathkeys;
1784 1111 : pathnode->subpath = subpath;
1785 :
1786 1111 : cost_subqueryscan(pathnode, root, rel, pathnode->path.param_info);
1787 :
1788 1111 : return pathnode;
1789 : }
1790 :
1791 : /*
1792 : * create_functionscan_path
1793 : * Creates a path corresponding to a sequential scan of a function,
1794 : * returning the pathnode.
1795 : */
1796 : Path *
1797 1327 : create_functionscan_path(PlannerInfo *root, RelOptInfo *rel,
1798 : List *pathkeys, Relids required_outer)
1799 : {
1800 1327 : Path *pathnode = makeNode(Path);
1801 :
1802 1327 : pathnode->pathtype = T_FunctionScan;
1803 1327 : pathnode->parent = rel;
1804 1327 : pathnode->pathtarget = rel->reltarget;
1805 1327 : pathnode->param_info = get_baserel_parampathinfo(root, rel,
1806 : required_outer);
1807 1327 : pathnode->parallel_aware = false;
1808 1327 : pathnode->parallel_safe = rel->consider_parallel;
1809 1327 : pathnode->parallel_workers = 0;
1810 1327 : pathnode->pathkeys = pathkeys;
1811 :
1812 1327 : cost_functionscan(pathnode, root, rel, pathnode->param_info);
1813 :
1814 1327 : return pathnode;
1815 : }
1816 :
1817 : /*
1818 : * create_tablefuncscan_path
1819 : * Creates a path corresponding to a sequential scan of a table function,
1820 : * returning the pathnode.
1821 : */
1822 : Path *
1823 22 : create_tablefuncscan_path(PlannerInfo *root, RelOptInfo *rel,
1824 : Relids required_outer)
1825 : {
1826 22 : Path *pathnode = makeNode(Path);
1827 :
1828 22 : pathnode->pathtype = T_TableFuncScan;
1829 22 : pathnode->parent = rel;
1830 22 : pathnode->pathtarget = rel->reltarget;
1831 22 : pathnode->param_info = get_baserel_parampathinfo(root, rel,
1832 : required_outer);
1833 22 : pathnode->parallel_aware = false;
1834 22 : pathnode->parallel_safe = rel->consider_parallel;
1835 22 : pathnode->parallel_workers = 0;
1836 22 : pathnode->pathkeys = NIL; /* result is always unordered */
1837 :
1838 22 : cost_tablefuncscan(pathnode, root, rel, pathnode->param_info);
1839 :
1840 22 : return pathnode;
1841 : }
1842 :
1843 : /*
1844 : * create_valuesscan_path
1845 : * Creates a path corresponding to a scan of a VALUES list,
1846 : * returning the pathnode.
1847 : */
1848 : Path *
1849 463 : create_valuesscan_path(PlannerInfo *root, RelOptInfo *rel,
1850 : Relids required_outer)
1851 : {
1852 463 : Path *pathnode = makeNode(Path);
1853 :
1854 463 : pathnode->pathtype = T_ValuesScan;
1855 463 : pathnode->parent = rel;
1856 463 : pathnode->pathtarget = rel->reltarget;
1857 463 : pathnode->param_info = get_baserel_parampathinfo(root, rel,
1858 : required_outer);
1859 463 : pathnode->parallel_aware = false;
1860 463 : pathnode->parallel_safe = rel->consider_parallel;
1861 463 : pathnode->parallel_workers = 0;
1862 463 : pathnode->pathkeys = NIL; /* result is always unordered */
1863 :
1864 463 : cost_valuesscan(pathnode, root, rel, pathnode->param_info);
1865 :
1866 463 : return pathnode;
1867 : }
1868 :
1869 : /*
1870 : * create_ctescan_path
1871 : * Creates a path corresponding to a scan of a non-self-reference CTE,
1872 : * returning the pathnode.
1873 : */
1874 : Path *
1875 162 : create_ctescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
1876 : {
1877 162 : Path *pathnode = makeNode(Path);
1878 :
1879 162 : pathnode->pathtype = T_CteScan;
1880 162 : pathnode->parent = rel;
1881 162 : pathnode->pathtarget = rel->reltarget;
1882 162 : pathnode->param_info = get_baserel_parampathinfo(root, rel,
1883 : required_outer);
1884 162 : pathnode->parallel_aware = false;
1885 162 : pathnode->parallel_safe = rel->consider_parallel;
1886 162 : pathnode->parallel_workers = 0;
1887 162 : pathnode->pathkeys = NIL; /* XXX for now, result is always unordered */
1888 :
1889 162 : cost_ctescan(pathnode, root, rel, pathnode->param_info);
1890 :
1891 162 : return pathnode;
1892 : }
1893 :
1894 : /*
1895 : * create_namedtuplestorescan_path
1896 : * Creates a path corresponding to a scan of a named tuplestore, returning
1897 : * the pathnode.
1898 : */
1899 : Path *
1900 43 : create_namedtuplestorescan_path(PlannerInfo *root, RelOptInfo *rel,
1901 : Relids required_outer)
1902 : {
1903 43 : Path *pathnode = makeNode(Path);
1904 :
1905 43 : pathnode->pathtype = T_NamedTuplestoreScan;
1906 43 : pathnode->parent = rel;
1907 43 : pathnode->pathtarget = rel->reltarget;
1908 43 : pathnode->param_info = get_baserel_parampathinfo(root, rel,
1909 : required_outer);
1910 43 : pathnode->parallel_aware = false;
1911 43 : pathnode->parallel_safe = rel->consider_parallel;
1912 43 : pathnode->parallel_workers = 0;
1913 43 : pathnode->pathkeys = NIL; /* result is always unordered */
1914 :
1915 43 : cost_namedtuplestorescan(pathnode, root, rel, pathnode->param_info);
1916 :
1917 43 : return pathnode;
1918 : }
1919 :
1920 : /*
1921 : * create_worktablescan_path
1922 : * Creates a path corresponding to a scan of a self-reference CTE,
1923 : * returning the pathnode.
1924 : */
1925 : Path *
1926 40 : create_worktablescan_path(PlannerInfo *root, RelOptInfo *rel,
1927 : Relids required_outer)
1928 : {
1929 40 : Path *pathnode = makeNode(Path);
1930 :
1931 40 : pathnode->pathtype = T_WorkTableScan;
1932 40 : pathnode->parent = rel;
1933 40 : pathnode->pathtarget = rel->reltarget;
1934 40 : pathnode->param_info = get_baserel_parampathinfo(root, rel,
1935 : required_outer);
1936 40 : pathnode->parallel_aware = false;
1937 40 : pathnode->parallel_safe = rel->consider_parallel;
1938 40 : pathnode->parallel_workers = 0;
1939 40 : pathnode->pathkeys = NIL; /* result is always unordered */
1940 :
1941 : /* Cost is the same as for a regular CTE scan */
1942 40 : cost_ctescan(pathnode, root, rel, pathnode->param_info);
1943 :
1944 40 : return pathnode;
1945 : }
1946 :
1947 : /*
1948 : * create_foreignscan_path
1949 : * Creates a path corresponding to a scan of a foreign table, foreign join,
1950 : * or foreign upper-relation processing, returning the pathnode.
1951 : *
1952 : * This function is never called from core Postgres; rather, it's expected
1953 : * to be called by the GetForeignPaths, GetForeignJoinPaths, or
1954 : * GetForeignUpperPaths function of a foreign data wrapper. We make the FDW
1955 : * supply all fields of the path, since we do not have any way to calculate
1956 : * them in core. However, there is a usually-sane default for the pathtarget
1957 : * (rel->reltarget), so we let a NULL for "target" select that.
1958 : */
1959 : ForeignPath *
1960 0 : create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
1961 : PathTarget *target,
1962 : double rows, Cost startup_cost, Cost total_cost,
1963 : List *pathkeys,
1964 : Relids required_outer,
1965 : Path *fdw_outerpath,
1966 : List *fdw_private)
1967 : {
1968 0 : ForeignPath *pathnode = makeNode(ForeignPath);
1969 :
1970 0 : pathnode->path.pathtype = T_ForeignScan;
1971 0 : pathnode->path.parent = rel;
1972 0 : pathnode->path.pathtarget = target ? target : rel->reltarget;
1973 0 : pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1974 : required_outer);
1975 0 : pathnode->path.parallel_aware = false;
1976 0 : pathnode->path.parallel_safe = rel->consider_parallel;
1977 0 : pathnode->path.parallel_workers = 0;
1978 0 : pathnode->path.rows = rows;
1979 0 : pathnode->path.startup_cost = startup_cost;
1980 0 : pathnode->path.total_cost = total_cost;
1981 0 : pathnode->path.pathkeys = pathkeys;
1982 :
1983 0 : pathnode->fdw_outerpath = fdw_outerpath;
1984 0 : pathnode->fdw_private = fdw_private;
1985 :
1986 0 : return pathnode;
1987 : }
1988 :
1989 : /*
1990 : * calc_nestloop_required_outer
1991 : * Compute the required_outer set for a nestloop join path
1992 : *
1993 : * Note: result must not share storage with either input
1994 : */
1995 : Relids
1996 53567 : calc_nestloop_required_outer(Relids outerrelids,
1997 : Relids outer_paramrels,
1998 : Relids innerrelids,
1999 : Relids inner_paramrels)
2000 : {
2001 : Relids required_outer;
2002 :
2003 : /* inner_path can require rels from outer path, but not vice versa */
2004 53567 : Assert(!bms_overlap(outer_paramrels, innerrelids));
2005 : /* easy case if inner path is not parameterized */
2006 53567 : if (!inner_paramrels)
2007 41978 : return bms_copy(outer_paramrels);
2008 : /* else, form the union ... */
2009 11589 : required_outer = bms_union(outer_paramrels, inner_paramrels);
2010 : /* ... and remove any mention of now-satisfied outer rels */
2011 11589 : required_outer = bms_del_members(required_outer,
2012 : outerrelids);
2013 : /* maintain invariant that required_outer is exactly NULL if empty */
2014 11589 : if (bms_is_empty(required_outer))
2015 : {
2016 9140 : bms_free(required_outer);
2017 9140 : required_outer = NULL;
2018 : }
2019 11589 : return required_outer;
2020 : }
2021 :
2022 : /*
2023 : * calc_non_nestloop_required_outer
2024 : * Compute the required_outer set for a merge or hash join path
2025 : *
2026 : * Note: result must not share storage with either input
2027 : */
2028 : Relids
2029 34159 : calc_non_nestloop_required_outer(Path *outer_path, Path *inner_path)
2030 : {
2031 34159 : Relids outer_paramrels = PATH_REQ_OUTER(outer_path);
2032 34159 : Relids inner_paramrels = PATH_REQ_OUTER(inner_path);
2033 : Relids required_outer;
2034 :
2035 : /* neither path can require rels from the other */
2036 34159 : Assert(!bms_overlap(outer_paramrels, inner_path->parent->relids));
2037 34159 : Assert(!bms_overlap(inner_paramrels, outer_path->parent->relids));
2038 : /* form the union ... */
2039 34159 : required_outer = bms_union(outer_paramrels, inner_paramrels);
2040 : /* we do not need an explicit test for empty; bms_union gets it right */
2041 34159 : return required_outer;
2042 : }
2043 :
2044 : /*
2045 : * create_nestloop_path
2046 : * Creates a pathnode corresponding to a nestloop join between two
2047 : * relations.
2048 : *
2049 : * 'joinrel' is the join relation.
2050 : * 'jointype' is the type of join required
2051 : * 'workspace' is the result from initial_cost_nestloop
2052 : * 'extra' contains various information about the join
2053 : * 'outer_path' is the outer path
2054 : * 'inner_path' is the inner path
2055 : * 'restrict_clauses' are the RestrictInfo nodes to apply at the join
2056 : * 'pathkeys' are the path keys of the new join path
2057 : * 'required_outer' is the set of required outer rels
2058 : *
2059 : * Returns the resulting path node.
2060 : */
2061 : NestPath *
2062 25841 : create_nestloop_path(PlannerInfo *root,
2063 : RelOptInfo *joinrel,
2064 : JoinType jointype,
2065 : JoinCostWorkspace *workspace,
2066 : JoinPathExtraData *extra,
2067 : Path *outer_path,
2068 : Path *inner_path,
2069 : List *restrict_clauses,
2070 : List *pathkeys,
2071 : Relids required_outer)
2072 : {
2073 25841 : NestPath *pathnode = makeNode(NestPath);
2074 25841 : Relids inner_req_outer = PATH_REQ_OUTER(inner_path);
2075 :
2076 : /*
2077 : * If the inner path is parameterized by the outer, we must drop any
2078 : * restrict_clauses that are due to be moved into the inner path. We have
2079 : * to do this now, rather than postpone the work till createplan time,
2080 : * because the restrict_clauses list can affect the size and cost
2081 : * estimates for this path.
2082 : */
2083 25841 : if (bms_overlap(inner_req_outer, outer_path->parent->relids))
2084 : {
2085 4929 : Relids inner_and_outer = bms_union(inner_path->parent->relids,
2086 : inner_req_outer);
2087 4929 : List *jclauses = NIL;
2088 : ListCell *lc;
2089 :
2090 10619 : foreach(lc, restrict_clauses)
2091 : {
2092 5690 : RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
2093 :
2094 5690 : if (!join_clause_is_movable_into(rinfo,
2095 5690 : inner_path->parent->relids,
2096 : inner_and_outer))
2097 569 : jclauses = lappend(jclauses, rinfo);
2098 : }
2099 4929 : restrict_clauses = jclauses;
2100 : }
2101 :
2102 25841 : pathnode->path.pathtype = T_NestLoop;
2103 25841 : pathnode->path.parent = joinrel;
2104 25841 : pathnode->path.pathtarget = joinrel->reltarget;
2105 25841 : pathnode->path.param_info =
2106 25841 : get_joinrel_parampathinfo(root,
2107 : joinrel,
2108 : outer_path,
2109 : inner_path,
2110 : extra->sjinfo,
2111 : required_outer,
2112 : &restrict_clauses);
2113 25841 : pathnode->path.parallel_aware = false;
2114 69063 : pathnode->path.parallel_safe = joinrel->consider_parallel &&
2115 43170 : outer_path->parallel_safe && inner_path->parallel_safe;
2116 : /* This is a foolish way to estimate parallel_workers, but for now... */
2117 25841 : pathnode->path.parallel_workers = outer_path->parallel_workers;
2118 25841 : pathnode->path.pathkeys = pathkeys;
2119 25841 : pathnode->jointype = jointype;
2120 25841 : pathnode->inner_unique = extra->inner_unique;
2121 25841 : pathnode->outerjoinpath = outer_path;
2122 25841 : pathnode->innerjoinpath = inner_path;
2123 25841 : pathnode->joinrestrictinfo = restrict_clauses;
2124 :
2125 25841 : final_cost_nestloop(root, pathnode, workspace, extra);
2126 :
2127 25841 : return pathnode;
2128 : }
2129 :
2130 : /*
2131 : * create_mergejoin_path
2132 : * Creates a pathnode corresponding to a mergejoin join between
2133 : * two relations
2134 : *
2135 : * 'joinrel' is the join relation
2136 : * 'jointype' is the type of join required
2137 : * 'workspace' is the result from initial_cost_mergejoin
2138 : * 'extra' contains various information about the join
2139 : * 'outer_path' is the outer path
2140 : * 'inner_path' is the inner path
2141 : * 'restrict_clauses' are the RestrictInfo nodes to apply at the join
2142 : * 'pathkeys' are the path keys of the new join path
2143 : * 'required_outer' is the set of required outer rels
2144 : * 'mergeclauses' are the RestrictInfo nodes to use as merge clauses
2145 : * (this should be a subset of the restrict_clauses list)
2146 : * 'outersortkeys' are the sort varkeys for the outer relation
2147 : * 'innersortkeys' are the sort varkeys for the inner relation
2148 : */
2149 : MergePath *
2150 6510 : create_mergejoin_path(PlannerInfo *root,
2151 : RelOptInfo *joinrel,
2152 : JoinType jointype,
2153 : JoinCostWorkspace *workspace,
2154 : JoinPathExtraData *extra,
2155 : Path *outer_path,
2156 : Path *inner_path,
2157 : List *restrict_clauses,
2158 : List *pathkeys,
2159 : Relids required_outer,
2160 : List *mergeclauses,
2161 : List *outersortkeys,
2162 : List *innersortkeys)
2163 : {
2164 6510 : MergePath *pathnode = makeNode(MergePath);
2165 :
2166 6510 : pathnode->jpath.path.pathtype = T_MergeJoin;
2167 6510 : pathnode->jpath.path.parent = joinrel;
2168 6510 : pathnode->jpath.path.pathtarget = joinrel->reltarget;
2169 6510 : pathnode->jpath.path.param_info =
2170 6510 : get_joinrel_parampathinfo(root,
2171 : joinrel,
2172 : outer_path,
2173 : inner_path,
2174 : extra->sjinfo,
2175 : required_outer,
2176 : &restrict_clauses);
2177 6510 : pathnode->jpath.path.parallel_aware = false;
2178 17255 : pathnode->jpath.path.parallel_safe = joinrel->consider_parallel &&
2179 10737 : outer_path->parallel_safe && inner_path->parallel_safe;
2180 : /* This is a foolish way to estimate parallel_workers, but for now... */
2181 6510 : pathnode->jpath.path.parallel_workers = outer_path->parallel_workers;
2182 6510 : pathnode->jpath.path.pathkeys = pathkeys;
2183 6510 : pathnode->jpath.jointype = jointype;
2184 6510 : pathnode->jpath.inner_unique = extra->inner_unique;
2185 6510 : pathnode->jpath.outerjoinpath = outer_path;
2186 6510 : pathnode->jpath.innerjoinpath = inner_path;
2187 6510 : pathnode->jpath.joinrestrictinfo = restrict_clauses;
2188 6510 : pathnode->path_mergeclauses = mergeclauses;
2189 6510 : pathnode->outersortkeys = outersortkeys;
2190 6510 : pathnode->innersortkeys = innersortkeys;
2191 : /* pathnode->skip_mark_restore will be set by final_cost_mergejoin */
2192 : /* pathnode->materialize_inner will be set by final_cost_mergejoin */
2193 :
2194 6510 : final_cost_mergejoin(root, pathnode, workspace, extra);
2195 :
2196 6510 : return pathnode;
2197 : }
2198 :
2199 : /*
2200 : * create_hashjoin_path
2201 : * Creates a pathnode corresponding to a hash join between two relations.
2202 : *
2203 : * 'joinrel' is the join relation
2204 : * 'jointype' is the type of join required
2205 : * 'workspace' is the result from initial_cost_hashjoin
2206 : * 'extra' contains various information about the join
2207 : * 'outer_path' is the cheapest outer path
2208 : * 'inner_path' is the cheapest inner path
2209 : * 'restrict_clauses' are the RestrictInfo nodes to apply at the join
2210 : * 'required_outer' is the set of required outer rels
2211 : * 'hashclauses' are the RestrictInfo nodes to use as hash clauses
2212 : * (this should be a subset of the restrict_clauses list)
2213 : */
2214 : HashPath *
2215 7067 : create_hashjoin_path(PlannerInfo *root,
2216 : RelOptInfo *joinrel,
2217 : JoinType jointype,
2218 : JoinCostWorkspace *workspace,
2219 : JoinPathExtraData *extra,
2220 : Path *outer_path,
2221 : Path *inner_path,
2222 : List *restrict_clauses,
2223 : Relids required_outer,
2224 : List *hashclauses)
2225 : {
2226 7067 : HashPath *pathnode = makeNode(HashPath);
2227 :
2228 7067 : pathnode->jpath.path.pathtype = T_HashJoin;
2229 7067 : pathnode->jpath.path.parent = joinrel;
2230 7067 : pathnode->jpath.path.pathtarget = joinrel->reltarget;
2231 7067 : pathnode->jpath.path.param_info =
2232 7067 : get_joinrel_parampathinfo(root,
2233 : joinrel,
2234 : outer_path,
2235 : inner_path,
2236 : extra->sjinfo,
2237 : required_outer,
2238 : &restrict_clauses);
2239 7067 : pathnode->jpath.path.parallel_aware = false;
2240 18912 : pathnode->jpath.path.parallel_safe = joinrel->consider_parallel &&
2241 11837 : outer_path->parallel_safe && inner_path->parallel_safe;
2242 : /* This is a foolish way to estimate parallel_workers, but for now... */
2243 7067 : pathnode->jpath.path.parallel_workers = outer_path->parallel_workers;
2244 :
2245 : /*
2246 : * A hashjoin never has pathkeys, since its output ordering is
2247 : * unpredictable due to possible batching. XXX If the inner relation is
2248 : * small enough, we could instruct the executor that it must not batch,
2249 : * and then we could assume that the output inherits the outer relation's
2250 : * ordering, which might save a sort step. However there is considerable
2251 : * downside if our estimate of the inner relation size is badly off. For
2252 : * the moment we don't risk it. (Note also that if we wanted to take this
2253 : * seriously, joinpath.c would have to consider many more paths for the
2254 : * outer rel than it does now.)
2255 : */
2256 7067 : pathnode->jpath.path.pathkeys = NIL;
2257 7067 : pathnode->jpath.jointype = jointype;
2258 7067 : pathnode->jpath.inner_unique = extra->inner_unique;
2259 7067 : pathnode->jpath.outerjoinpath = outer_path;
2260 7067 : pathnode->jpath.innerjoinpath = inner_path;
2261 7067 : pathnode->jpath.joinrestrictinfo = restrict_clauses;
2262 7067 : pathnode->path_hashclauses = hashclauses;
2263 : /* final_cost_hashjoin will fill in pathnode->num_batches */
2264 :
2265 7067 : final_cost_hashjoin(root, pathnode, workspace, extra);
2266 :
2267 7067 : return pathnode;
2268 : }
2269 :
2270 : /*
2271 : * create_projection_path
2272 : * Creates a pathnode that represents performing a projection.
2273 : *
2274 : * 'rel' is the parent relation associated with the result
2275 : * 'subpath' is the path representing the source of data
2276 : * 'target' is the PathTarget to be computed
2277 : */
2278 : ProjectionPath *
2279 801 : create_projection_path(PlannerInfo *root,
2280 : RelOptInfo *rel,
2281 : Path *subpath,
2282 : PathTarget *target)
2283 : {
2284 801 : ProjectionPath *pathnode = makeNode(ProjectionPath);
2285 801 : PathTarget *oldtarget = subpath->pathtarget;
2286 :
2287 801 : pathnode->path.pathtype = T_Result;
2288 801 : pathnode->path.parent = rel;
2289 801 : pathnode->path.pathtarget = target;
2290 : /* For now, assume we are above any joins, so no parameterization */
2291 801 : pathnode->path.param_info = NULL;
2292 801 : pathnode->path.parallel_aware = false;
2293 2243 : pathnode->path.parallel_safe = rel->consider_parallel &&
2294 1425 : subpath->parallel_safe &&
2295 624 : is_parallel_safe(root, (Node *) target->exprs);
2296 801 : pathnode->path.parallel_workers = subpath->parallel_workers;
2297 : /* Projection does not change the sort order */
2298 801 : pathnode->path.pathkeys = subpath->pathkeys;
2299 :
2300 801 : pathnode->subpath = subpath;
2301 :
2302 : /*
2303 : * We might not need a separate Result node. If the input plan node type
2304 : * can project, we can just tell it to project something else. Or, if it
2305 : * can't project but the desired target has the same expression list as
2306 : * what the input will produce anyway, we can still give it the desired
2307 : * tlist (possibly changing its ressortgroupref labels, but nothing else).
2308 : * Note: in the latter case, create_projection_plan has to recheck our
2309 : * conclusion; see comments therein.
2310 : */
2311 1529 : if (is_projection_capable_path(subpath) ||
2312 728 : equal(oldtarget->exprs, target->exprs))
2313 : {
2314 : /* No separate Result node needed */
2315 652 : pathnode->dummypp = true;
2316 :
2317 : /*
2318 : * Set cost of plan as subpath's cost, adjusted for tlist replacement.
2319 : */
2320 652 : pathnode->path.rows = subpath->rows;
2321 1956 : pathnode->path.startup_cost = subpath->startup_cost +
2322 1304 : (target->cost.startup - oldtarget->cost.startup);
2323 3912 : pathnode->path.total_cost = subpath->total_cost +
2324 1304 : (target->cost.startup - oldtarget->cost.startup) +
2325 1956 : (target->cost.per_tuple - oldtarget->cost.per_tuple) * subpath->rows;
2326 : }
2327 : else
2328 : {
2329 : /* We really do need the Result node */
2330 149 : pathnode->dummypp = false;
2331 :
2332 : /*
2333 : * The Result node's cost is cpu_tuple_cost per row, plus the cost of
2334 : * evaluating the tlist. There is no qual to worry about.
2335 : */
2336 149 : pathnode->path.rows = subpath->rows;
2337 298 : pathnode->path.startup_cost = subpath->startup_cost +
2338 149 : target->cost.startup;
2339 596 : pathnode->path.total_cost = subpath->total_cost +
2340 149 : target->cost.startup +
2341 298 : (cpu_tuple_cost + target->cost.per_tuple) * subpath->rows;
2342 : }
2343 :
2344 801 : return pathnode;
2345 : }
2346 :
2347 : /*
2348 : * apply_projection_to_path
2349 : * Add a projection step, or just apply the target directly to given path.
2350 : *
2351 : * This has the same net effect as create_projection_path(), except that if
2352 : * a separate Result plan node isn't needed, we just replace the given path's
2353 : * pathtarget with the desired one. This must be used only when the caller
2354 : * knows that the given path isn't referenced elsewhere and so can be modified
2355 : * in-place.
2356 : *
2357 : * If the input path is a GatherPath, we try to push the new target down to
2358 : * its input as well; this is a yet more invasive modification of the input
2359 : * path, which create_projection_path() can't do.
2360 : *
2361 : * Note that we mustn't change the source path's parent link; so when it is
2362 : * add_path'd to "rel" things will be a bit inconsistent. So far that has
2363 : * not caused any trouble.
2364 : *
2365 : * 'rel' is the parent relation associated with the result
2366 : * 'path' is the path representing the source of data
2367 : * 'target' is the PathTarget to be computed
2368 : */
2369 : Path *
2370 26946 : apply_projection_to_path(PlannerInfo *root,
2371 : RelOptInfo *rel,
2372 : Path *path,
2373 : PathTarget *target)
2374 : {
2375 : QualCost oldcost;
2376 :
2377 : /*
2378 : * If given path can't project, we might need a Result node, so make a
2379 : * separate ProjectionPath.
2380 : */
2381 26946 : if (!is_projection_capable_path(path))
2382 572 : return (Path *) create_projection_path(root, rel, path, target);
2383 :
2384 : /*
2385 : * We can just jam the desired tlist into the existing path, being sure to
2386 : * update its cost estimates appropriately.
2387 : */
2388 26374 : oldcost = path->pathtarget->cost;
2389 26374 : path->pathtarget = target;
2390 :
2391 26374 : path->startup_cost += target->cost.startup - oldcost.startup;
2392 105496 : path->total_cost += target->cost.startup - oldcost.startup +
2393 79122 : (target->cost.per_tuple - oldcost.per_tuple) * path->rows;
2394 :
2395 : /*
2396 : * If the path happens to be a Gather path, we'd like to arrange for the
2397 : * subpath to return the required target list so that workers can help
2398 : * project. But if there is something that is not parallel-safe in the
2399 : * target expressions, then we can't.
2400 : */
2401 26403 : if (IsA(path, GatherPath) &&
2402 29 : is_parallel_safe(root, (Node *) target->exprs))
2403 27 : {
2404 27 : GatherPath *gpath = (GatherPath *) path;
2405 :
2406 : /*
2407 : * We always use create_projection_path here, even if the subpath is
2408 : * projection-capable, so as to avoid modifying the subpath in place.
2409 : * It seems unlikely at present that there could be any other
2410 : * references to the subpath, but better safe than sorry.
2411 : *
2412 : * Note that we don't change the GatherPath's cost estimates; it might
2413 : * be appropriate to do so, to reflect the fact that the bulk of the
2414 : * target evaluation will happen in workers.
2415 : */
2416 27 : gpath->subpath = (Path *)
2417 54 : create_projection_path(root,
2418 27 : gpath->subpath->parent,
2419 : gpath->subpath,
2420 : target);
2421 : }
2422 39964 : else if (path->parallel_safe &&
2423 13617 : !is_parallel_safe(root, (Node *) target->exprs))
2424 : {
2425 : /*
2426 : * We're inserting a parallel-restricted target list into a path
2427 : * currently marked parallel-safe, so we have to mark it as no longer
2428 : * safe.
2429 : */
2430 2876 : path->parallel_safe = false;
2431 : }
2432 :
2433 26374 : return path;
2434 : }
2435 :
2436 : /*
2437 : * create_set_projection_path
2438 : * Creates a pathnode that represents performing a projection that
2439 : * includes set-returning functions.
2440 : *
2441 : * 'rel' is the parent relation associated with the result
2442 : * 'subpath' is the path representing the source of data
2443 : * 'target' is the PathTarget to be computed
2444 : */
2445 : ProjectSetPath *
2446 232 : create_set_projection_path(PlannerInfo *root,
2447 : RelOptInfo *rel,
2448 : Path *subpath,
2449 : PathTarget *target)
2450 : {
2451 232 : ProjectSetPath *pathnode = makeNode(ProjectSetPath);
2452 : double tlist_rows;
2453 : ListCell *lc;
2454 :
2455 232 : pathnode->path.pathtype = T_ProjectSet;
2456 232 : pathnode->path.parent = rel;
2457 232 : pathnode->path.pathtarget = target;
2458 : /* For now, assume we are above any joins, so no parameterization */
2459 232 : pathnode->path.param_info = NULL;
2460 232 : pathnode->path.parallel_aware = false;
2461 606 : pathnode->path.parallel_safe = rel->consider_parallel &&
2462 372 : subpath->parallel_safe &&
2463 140 : is_parallel_safe(root, (Node *) target->exprs);
2464 232 : pathnode->path.parallel_workers = subpath->parallel_workers;
2465 : /* Projection does not change the sort order XXX? */
2466 232 : pathnode->path.pathkeys = subpath->pathkeys;
2467 :
2468 232 : pathnode->subpath = subpath;
2469 :
2470 : /*
2471 : * Estimate number of rows produced by SRFs for each row of input; if
2472 : * there's more than one in this node, use the maximum.
2473 : */
2474 232 : tlist_rows = 1;
2475 655 : foreach(lc, target->exprs)
2476 : {
2477 423 : Node *node = (Node *) lfirst(lc);
2478 : double itemrows;
2479 :
2480 423 : itemrows = expression_returns_set_rows(node);
2481 423 : if (tlist_rows < itemrows)
2482 205 : tlist_rows = itemrows;
2483 : }
2484 :
2485 : /*
2486 : * In addition to the cost of evaluating the tlist, charge cpu_tuple_cost
2487 : * per input row, and half of cpu_tuple_cost for each added output row.
2488 : * This is slightly bizarre maybe, but it's what 9.6 did; we may revisit
2489 : * this estimate later.
2490 : */
2491 232 : pathnode->path.rows = subpath->rows * tlist_rows;
2492 464 : pathnode->path.startup_cost = subpath->startup_cost +
2493 232 : target->cost.startup;
2494 1392 : pathnode->path.total_cost = subpath->total_cost +
2495 232 : target->cost.startup +
2496 464 : (cpu_tuple_cost + target->cost.per_tuple) * subpath->rows +
2497 464 : (pathnode->path.rows - subpath->rows) * cpu_tuple_cost / 2;
2498 :
2499 232 : return pathnode;
2500 : }
2501 :
2502 : /*
2503 : * create_sort_path
2504 : * Creates a pathnode that represents performing an explicit sort.
2505 : *
2506 : * 'rel' is the parent relation associated with the result
2507 : * 'subpath' is the path representing the source of data
2508 : * 'pathkeys' represents the desired sort order
2509 : * 'limit_tuples' is the estimated bound on the number of output tuples,
2510 : * or -1 if no LIMIT or couldn't estimate
2511 : */
2512 : SortPath *
2513 2838 : create_sort_path(PlannerInfo *root,
2514 : RelOptInfo *rel,
2515 : Path *subpath,
2516 : List *pathkeys,
2517 : double limit_tuples)
2518 : {
2519 2838 : SortPath *pathnode = makeNode(SortPath);
2520 :
2521 2838 : pathnode->path.pathtype = T_Sort;
2522 2838 : pathnode->path.parent = rel;
2523 : /* Sort doesn't project, so use source path's pathtarget */
2524 2838 : pathnode->path.pathtarget = subpath->pathtarget;
2525 : /* For now, assume we are above any joins, so no parameterization */
2526 2838 : pathnode->path.param_info = NULL;
2527 2838 : pathnode->path.parallel_aware = false;
2528 4629 : pathnode->path.parallel_safe = rel->consider_parallel &&
2529 1791 : subpath->parallel_safe;
2530 2838 : pathnode->path.parallel_workers = subpath->parallel_workers;
2531 2838 : pathnode->path.pathkeys = pathkeys;
2532 :
2533 2838 : pathnode->subpath = subpath;
2534 :
2535 5676 : cost_sort(&pathnode->path, root, pathkeys,
2536 : subpath->total_cost,
2537 : subpath->rows,
2538 2838 : subpath->pathtarget->width,
2539 : 0.0, /* XXX comparison_cost shouldn't be 0? */
2540 : work_mem, limit_tuples);
2541 :
2542 2838 : return pathnode;
2543 : }
2544 :
2545 : /*
2546 : * create_group_path
2547 : * Creates a pathnode that represents performing grouping of presorted input
2548 : *
2549 : * 'rel' is the parent relation associated with the result
2550 : * 'subpath' is the path representing the source of data
2551 : * 'target' is the PathTarget to be computed
2552 : * 'groupClause' is a list of SortGroupClause's representing the grouping
2553 : * 'qual' is the HAVING quals if any
2554 : * 'numGroups' is the estimated number of groups
2555 : */
2556 : GroupPath *
2557 51 : create_group_path(PlannerInfo *root,
2558 : RelOptInfo *rel,
2559 : Path *subpath,
2560 : PathTarget *target,
2561 : List *groupClause,
2562 : List *qual,
2563 : double numGroups)
2564 : {
2565 51 : GroupPath *pathnode = makeNode(GroupPath);
2566 :
2567 51 : pathnode->path.pathtype = T_Group;
2568 51 : pathnode->path.parent = rel;
2569 51 : pathnode->path.pathtarget = target;
2570 : /* For now, assume we are above any joins, so no parameterization */
2571 51 : pathnode->path.param_info = NULL;
2572 51 : pathnode->path.parallel_aware = false;
2573 75 : pathnode->path.parallel_safe = rel->consider_parallel &&
2574 24 : subpath->parallel_safe;
2575 51 : pathnode->path.parallel_workers = subpath->parallel_workers;
2576 : /* Group doesn't change sort ordering */
2577 51 : pathnode->path.pathkeys = subpath->pathkeys;
2578 :
2579 51 : pathnode->subpath = subpath;
2580 :
2581 51 : pathnode->groupClause = groupClause;
2582 51 : pathnode->qual = qual;
2583 :
2584 51 : cost_group(&pathnode->path, root,
2585 : list_length(groupClause),
2586 : numGroups,
2587 : subpath->startup_cost, subpath->total_cost,
2588 : subpath->rows);
2589 :
2590 : /* add tlist eval cost for each output row */
2591 51 : pathnode->path.startup_cost += target->cost.startup;
2592 153 : pathnode->path.total_cost += target->cost.startup +
2593 102 : target->cost.per_tuple * pathnode->path.rows;
2594 :
2595 51 : return pathnode;
2596 : }
2597 :
2598 : /*
2599 : * create_upper_unique_path
2600 : * Creates a pathnode that represents performing an explicit Unique step
2601 : * on presorted input.
2602 : *
2603 : * This produces a Unique plan node, but the use-case is so different from
2604 : * create_unique_path that it doesn't seem worth trying to merge the two.
2605 : *
2606 : * 'rel' is the parent relation associated with the result
2607 : * 'subpath' is the path representing the source of data
2608 : * 'numCols' is the number of grouping columns
2609 : * 'numGroups' is the estimated number of groups
2610 : *
2611 : * The input path must be sorted on the grouping columns, plus possibly
2612 : * additional columns; so the first numCols pathkeys are the grouping columns
2613 : */
2614 : UpperUniquePath *
2615 83 : create_upper_unique_path(PlannerInfo *root,
2616 : RelOptInfo *rel,
2617 : Path *subpath,
2618 : int numCols,
2619 : double numGroups)
2620 : {
2621 83 : UpperUniquePath *pathnode = makeNode(UpperUniquePath);
2622 :
2623 83 : pathnode->path.pathtype = T_Unique;
2624 83 : pathnode->path.parent = rel;
2625 : /* Unique doesn't project, so use source path's pathtarget */
2626 83 : pathnode->path.pathtarget = subpath->pathtarget;
2627 : /* For now, assume we are above any joins, so no parameterization */
2628 83 : pathnode->path.param_info = NULL;
2629 83 : pathnode->path.parallel_aware = false;
2630 136 : pathnode->path.parallel_safe = rel->consider_parallel &&
2631 53 : subpath->parallel_safe;
2632 83 : pathnode->path.parallel_workers = subpath->parallel_workers;
2633 : /* Unique doesn't change the input ordering */
2634 83 : pathnode->path.pathkeys = subpath->pathkeys;
2635 :
2636 83 : pathnode->subpath = subpath;
2637 83 : pathnode->numkeys = numCols;
2638 :
2639 : /*
2640 : * Charge one cpu_operator_cost per comparison per input tuple. We assume
2641 : * all columns get compared at most of the tuples. (XXX probably this is
2642 : * an overestimate.)
2643 : */
2644 83 : pathnode->path.startup_cost = subpath->startup_cost;
2645 166 : pathnode->path.total_cost = subpath->total_cost +
2646 83 : cpu_operator_cost * subpath->rows * numCols;
2647 83 : pathnode->path.rows = numGroups;
2648 :
2649 83 : return pathnode;
2650 : }
2651 :
2652 : /*
2653 : * create_agg_path
2654 : * Creates a pathnode that represents performing aggregation/grouping
2655 : *
2656 : * 'rel' is the parent relation associated with the result
2657 : * 'subpath' is the path representing the source of data
2658 : * 'target' is the PathTarget to be computed
2659 : * 'aggstrategy' is the Agg node's basic implementation strategy
2660 : * 'aggsplit' is the Agg node's aggregate-splitting mode
2661 : * 'groupClause' is a list of SortGroupClause's representing the grouping
2662 : * 'qual' is the HAVING quals if any
2663 : * 'aggcosts' contains cost info about the aggregate functions to be computed
2664 : * 'numGroups' is the estimated number of groups (1 if not grouping)
2665 : */
2666 : AggPath *
2667 2712 : create_agg_path(PlannerInfo *root,
2668 : RelOptInfo *rel,
2669 : Path *subpath,
2670 : PathTarget *target,
2671 : AggStrategy aggstrategy,
2672 : AggSplit aggsplit,
2673 : List *groupClause,
2674 : List *qual,
2675 : const AggClauseCosts *aggcosts,
2676 : double numGroups)
2677 : {
2678 2712 : AggPath *pathnode = makeNode(AggPath);
2679 :
2680 2712 : pathnode->path.pathtype = T_Agg;
2681 2712 : pathnode->path.parent = rel;
2682 2712 : pathnode->path.pathtarget = target;
2683 : /* For now, assume we are above any joins, so no parameterization */
2684 2712 : pathnode->path.param_info = NULL;
2685 2712 : pathnode->path.parallel_aware = false;
2686 4804 : pathnode->path.parallel_safe = rel->consider_parallel &&
2687 2092 : subpath->parallel_safe;
2688 2712 : pathnode->path.parallel_workers = subpath->parallel_workers;
2689 2712 : if (aggstrategy == AGG_SORTED)
2690 232 : pathnode->path.pathkeys = subpath->pathkeys; /* preserves order */
2691 : else
2692 2480 : pathnode->path.pathkeys = NIL; /* output is unordered */
2693 2712 : pathnode->subpath = subpath;
2694 :
2695 2712 : pathnode->aggstrategy = aggstrategy;
2696 2712 : pathnode->aggsplit = aggsplit;
2697 2712 : pathnode->numGroups = numGroups;
2698 2712 : pathnode->groupClause = groupClause;
2699 2712 : pathnode->qual = qual;
2700 :
2701 2712 : cost_agg(&pathnode->path, root,
2702 : aggstrategy, aggcosts,
2703 : list_length(groupClause), numGroups,
2704 : subpath->startup_cost, subpath->total_cost,
2705 : subpath->rows);
2706 :
2707 : /* add tlist eval cost for each output row */
2708 2712 : pathnode->path.startup_cost += target->cost.startup;
2709 8136 : pathnode->path.total_cost += target->cost.startup +
2710 5424 : target->cost.per_tuple * pathnode->path.rows;
2711 :
2712 2712 : return pathnode;
2713 : }
2714 :
2715 : /*
2716 : * create_groupingsets_path
2717 : * Creates a pathnode that represents performing GROUPING SETS aggregation
2718 : *
2719 : * GroupingSetsPath represents sorted grouping with one or more grouping sets.
2720 : * The input path's result must be sorted to match the last entry in
2721 : * rollup_groupclauses.
2722 : *
2723 : * 'rel' is the parent relation associated with the result
2724 : * 'subpath' is the path representing the source of data
2725 : * 'target' is the PathTarget to be computed
2726 : * 'having_qual' is the HAVING quals if any
2727 : * 'rollups' is a list of RollupData nodes
2728 : * 'agg_costs' contains cost info about the aggregate functions to be computed
2729 : * 'numGroups' is the estimated total number of groups
2730 : */
2731 : GroupingSetsPath *
2732 199 : create_groupingsets_path(PlannerInfo *root,
2733 : RelOptInfo *rel,
2734 : Path *subpath,
2735 : PathTarget *target,
2736 : List *having_qual,
2737 : AggStrategy aggstrategy,
2738 : List *rollups,
2739 : const AggClauseCosts *agg_costs,
2740 : double numGroups)
2741 : {
2742 199 : GroupingSetsPath *pathnode = makeNode(GroupingSetsPath);
2743 : ListCell *lc;
2744 199 : bool is_first = true;
2745 199 : bool is_first_sort = true;
2746 :
2747 : /* The topmost generated Plan node will be an Agg */
2748 199 : pathnode->path.pathtype = T_Agg;
2749 199 : pathnode->path.parent = rel;
2750 199 : pathnode->path.pathtarget = target;
2751 199 : pathnode->path.param_info = subpath->param_info;
2752 199 : pathnode->path.parallel_aware = false;
2753 285 : pathnode->path.parallel_safe = rel->consider_parallel &&
2754 86 : subpath->parallel_safe;
2755 199 : pathnode->path.parallel_workers = subpath->parallel_workers;
2756 199 : pathnode->subpath = subpath;
2757 :
2758 : /*
2759 : * Simplify callers by downgrading AGG_SORTED to AGG_PLAIN, and AGG_MIXED
2760 : * to AGG_HASHED, here if possible.
2761 : */
2762 288 : if (aggstrategy == AGG_SORTED &&
2763 137 : list_length(rollups) == 1 &&
2764 48 : ((RollupData *) linitial(rollups))->groupClause == NIL)
2765 7 : aggstrategy = AGG_PLAIN;
2766 :
2767 287 : if (aggstrategy == AGG_MIXED &&
2768 88 : list_length(rollups) == 1)
2769 0 : aggstrategy = AGG_HASHED;
2770 :
2771 : /*
2772 : * Output will be in sorted order by group_pathkeys if, and only if, there
2773 : * is a single rollup operation on a non-empty list of grouping
2774 : * expressions.
2775 : */
2776 199 : if (aggstrategy == AGG_SORTED && list_length(rollups) == 1)
2777 41 : pathnode->path.pathkeys = root->group_pathkeys;
2778 : else
2779 158 : pathnode->path.pathkeys = NIL;
2780 :
2781 199 : pathnode->aggstrategy = aggstrategy;
2782 199 : pathnode->rollups = rollups;
2783 199 : pathnode->qual = having_qual;
2784 :
2785 199 : Assert(rollups != NIL);
2786 199 : Assert(aggstrategy != AGG_PLAIN || list_length(rollups) == 1);
2787 199 : Assert(aggstrategy != AGG_MIXED || list_length(rollups) > 1);
2788 :
2789 696 : foreach(lc, rollups)
2790 : {
2791 497 : RollupData *rollup = lfirst(lc);
2792 497 : List *gsets = rollup->gsets;
2793 497 : int numGroupCols = list_length(linitial(gsets));
2794 :
2795 : /*
2796 : * In AGG_SORTED or AGG_PLAIN mode, the first rollup takes the
2797 : * (already-sorted) input, and following ones do their own sort.
2798 : *
2799 : * In AGG_HASHED mode, there is one rollup for each grouping set.
2800 : *
2801 : * In AGG_MIXED mode, the first rollups are hashed, the first
2802 : * non-hashed one takes the (already-sorted) input, and following ones
2803 : * do their own sort.
2804 : */
2805 497 : if (is_first)
2806 : {
2807 199 : cost_agg(&pathnode->path, root,
2808 : aggstrategy,
2809 : agg_costs,
2810 : numGroupCols,
2811 : rollup->numGroups,
2812 : subpath->startup_cost,
2813 : subpath->total_cost,
2814 : subpath->rows);
2815 199 : is_first = false;
2816 199 : if (!rollup->is_hashed)
2817 89 : is_first_sort = false;
2818 : }
2819 : else
2820 : {
2821 : Path sort_path; /* dummy for result of cost_sort */
2822 : Path agg_path; /* dummy for result of cost_agg */
2823 :
2824 298 : if (rollup->is_hashed || is_first_sort)
2825 : {
2826 : /*
2827 : * Account for cost of aggregation, but don't charge input
2828 : * cost again
2829 : */
2830 438 : cost_agg(&agg_path, root,
2831 219 : rollup->is_hashed ? AGG_HASHED : AGG_SORTED,
2832 : agg_costs,
2833 : numGroupCols,
2834 : rollup->numGroups,
2835 : 0.0, 0.0,
2836 : subpath->rows);
2837 438 : if (!rollup->is_hashed)
2838 88 : is_first_sort = false;
2839 : }
2840 : else
2841 : {
2842 : /* Account for cost of sort, but don't charge input cost again */
2843 158 : cost_sort(&sort_path, root, NIL,
2844 : 0.0,
2845 : subpath->rows,
2846 79 : subpath->pathtarget->width,
2847 : 0.0,
2848 : work_mem,
2849 : -1.0);
2850 :
2851 : /* Account for cost of aggregation */
2852 :
2853 79 : cost_agg(&agg_path, root,
2854 : AGG_SORTED,
2855 : agg_costs,
2856 : numGroupCols,
2857 : rollup->numGroups,
2858 : sort_path.startup_cost,
2859 : sort_path.total_cost,
2860 : sort_path.rows);
2861 : }
2862 :
2863 298 : pathnode->path.total_cost += agg_path.total_cost;
2864 298 : pathnode->path.rows += agg_path.rows;
2865 : }
2866 : }
2867 :
2868 : /* add tlist eval cost for each output row */
2869 199 : pathnode->path.startup_cost += target->cost.startup;
2870 597 : pathnode->path.total_cost += target->cost.startup +
2871 398 : target->cost.per_tuple * pathnode->path.rows;
2872 :
2873 199 : return pathnode;
2874 : }
2875 :
2876 : /*
2877 : * create_minmaxagg_path
2878 : * Creates a pathnode that represents computation of MIN/MAX aggregates
2879 : *
2880 : * 'rel' is the parent relation associated with the result
2881 : * 'target' is the PathTarget to be computed
2882 : * 'mmaggregates' is a list of MinMaxAggInfo structs
2883 : * 'quals' is the HAVING quals if any
2884 : */
2885 : MinMaxAggPath *
2886 86 : create_minmaxagg_path(PlannerInfo *root,
2887 : RelOptInfo *rel,
2888 : PathTarget *target,
2889 : List *mmaggregates,
2890 : List *quals)
2891 : {
2892 86 : MinMaxAggPath *pathnode = makeNode(MinMaxAggPath);
2893 : Cost initplan_cost;
2894 : ListCell *lc;
2895 :
2896 : /* The topmost generated Plan node will be a Result */
2897 86 : pathnode->path.pathtype = T_Result;
2898 86 : pathnode->path.parent = rel;
2899 86 : pathnode->path.pathtarget = target;
2900 : /* For now, assume we are above any joins, so no parameterization */
2901 86 : pathnode->path.param_info = NULL;
2902 86 : pathnode->path.parallel_aware = false;
2903 : /* A MinMaxAggPath implies use of subplans, so cannot be parallel-safe */
2904 86 : pathnode->path.parallel_safe = false;
2905 86 : pathnode->path.parallel_workers = 0;
2906 : /* Result is one unordered row */
2907 86 : pathnode->path.rows = 1;
2908 86 : pathnode->path.pathkeys = NIL;
2909 :
2910 86 : pathnode->mmaggregates = mmaggregates;
2911 86 : pathnode->quals = quals;
2912 :
2913 : /* Calculate cost of all the initplans ... */
2914 86 : initplan_cost = 0;
2915 178 : foreach(lc, mmaggregates)
2916 : {
2917 92 : MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
2918 :
2919 92 : initplan_cost += mminfo->pathcost;
2920 : }
2921 :
2922 : /* add tlist eval cost for each output row, plus cpu_tuple_cost */
2923 86 : pathnode->path.startup_cost = initplan_cost + target->cost.startup;
2924 172 : pathnode->path.total_cost = initplan_cost + target->cost.startup +
2925 86 : target->cost.per_tuple + cpu_tuple_cost;
2926 :
2927 86 : return pathnode;
2928 : }
2929 :
2930 : /*
2931 : * create_windowagg_path
2932 : * Creates a pathnode that represents computation of window functions
2933 : *
2934 : * 'rel' is the parent relation associated with the result
2935 : * 'subpath' is the path representing the source of data
2936 : * 'target' is the PathTarget to be computed
2937 : * 'windowFuncs' is a list of WindowFunc structs
2938 : * 'winclause' is a WindowClause that is common to all the WindowFuncs
2939 : * 'winpathkeys' is the pathkeys for the PARTITION keys + ORDER keys
2940 : *
2941 : * The actual sort order of the input must match winpathkeys, but might
2942 : * have additional keys after those.
2943 : */
2944 : WindowAggPath *
2945 147 : create_windowagg_path(PlannerInfo *root,
2946 : RelOptInfo *rel,
2947 : Path *subpath,
2948 : PathTarget *target,
2949 : List *windowFuncs,
2950 : WindowClause *winclause,
2951 : List *winpathkeys)
2952 : {
2953 147 : WindowAggPath *pathnode = makeNode(WindowAggPath);
2954 :
2955 147 : pathnode->path.pathtype = T_WindowAgg;
2956 147 : pathnode->path.parent = rel;
2957 147 : pathnode->path.pathtarget = target;
2958 : /* For now, assume we are above any joins, so no parameterization */
2959 147 : pathnode->path.param_info = NULL;
2960 147 : pathnode->path.parallel_aware = false;
2961 254 : pathnode->path.parallel_safe = rel->consider_parallel &&
2962 107 : subpath->parallel_safe;
2963 147 : pathnode->path.parallel_workers = subpath->parallel_workers;
2964 : /* WindowAgg preserves the input sort order */
2965 147 : pathnode->path.pathkeys = subpath->pathkeys;
2966 :
2967 147 : pathnode->subpath = subpath;
2968 147 : pathnode->winclause = winclause;
2969 147 : pathnode->winpathkeys = winpathkeys;
2970 :
2971 : /*
2972 : * For costing purposes, assume that there are no redundant partitioning
2973 : * or ordering columns; it's not worth the trouble to deal with that
2974 : * corner case here. So we just pass the unmodified list lengths to
2975 : * cost_windowagg.
2976 : */
2977 441 : cost_windowagg(&pathnode->path, root,
2978 : windowFuncs,
2979 147 : list_length(winclause->partitionClause),
2980 147 : list_length(winclause->orderClause),
2981 : subpath->startup_cost,
2982 : subpath->total_cost,
2983 : subpath->rows);
2984 :
2985 : /* add tlist eval cost for each output row */
2986 147 : pathnode->path.startup_cost += target->cost.startup;
2987 441 : pathnode->path.total_cost += target->cost.startup +
2988 294 : target->cost.per_tuple * pathnode->path.rows;
2989 :
2990 147 : return pathnode;
2991 : }
2992 :
2993 : /*
2994 : * create_setop_path
2995 : * Creates a pathnode that represents computation of INTERSECT or EXCEPT
2996 : *
2997 : * 'rel' is the parent relation associated with the result
2998 : * 'subpath' is the path representing the source of data
2999 : * 'cmd' is the specific semantics (INTERSECT or EXCEPT, with/without ALL)
3000 : * 'strategy' is the implementation strategy (sorted or hashed)
3001 : * 'distinctList' is a list of SortGroupClause's representing the grouping
3002 : * 'flagColIdx' is the column number where the flag column will be, if any
3003 : * 'firstFlag' is the flag value for the first input relation when hashing;
3004 : * or -1 when sorting
3005 : * 'numGroups' is the estimated number of distinct groups
3006 : * 'outputRows' is the estimated number of output rows
3007 : */
3008 : SetOpPath *
3009 37 : create_setop_path(PlannerInfo *root,
3010 : RelOptInfo *rel,
3011 : Path *subpath,
3012 : SetOpCmd cmd,
3013 : SetOpStrategy strategy,
3014 : List *distinctList,
3015 : AttrNumber flagColIdx,
3016 : int firstFlag,
3017 : double numGroups,
3018 : double outputRows)
3019 : {
3020 37 : SetOpPath *pathnode = makeNode(SetOpPath);
3021 :
3022 37 : pathnode->path.pathtype = T_SetOp;
3023 37 : pathnode->path.parent = rel;
3024 : /* SetOp doesn't project, so use source path's pathtarget */
3025 37 : pathnode->path.pathtarget = subpath->pathtarget;
3026 : /* For now, assume we are above any joins, so no parameterization */
3027 37 : pathnode->path.param_info = NULL;
3028 37 : pathnode->path.parallel_aware = false;
3029 37 : pathnode->path.parallel_safe = rel->consider_parallel &&
3030 0 : subpath->parallel_safe;
3031 37 : pathnode->path.parallel_workers = subpath->parallel_workers;
3032 : /* SetOp preserves the input sort order if in sort mode */
3033 37 : pathnode->path.pathkeys =
3034 37 : (strategy == SETOP_SORTED) ? subpath->pathkeys : NIL;
3035 :
3036 37 : pathnode->subpath = subpath;
3037 37 : pathnode->cmd = cmd;
3038 37 : pathnode->strategy = strategy;
3039 37 : pathnode->distinctList = distinctList;
3040 37 : pathnode->flagColIdx = flagColIdx;
3041 37 : pathnode->firstFlag = firstFlag;
3042 37 : pathnode->numGroups = numGroups;
3043 :
3044 : /*
3045 : * Charge one cpu_operator_cost per comparison per input tuple. We assume
3046 : * all columns get compared at most of the tuples.
3047 : */
3048 37 : pathnode->path.startup_cost = subpath->startup_cost;
3049 111 : pathnode->path.total_cost = subpath->total_cost +
3050 74 : cpu_operator_cost * subpath->rows * list_length(distinctList);
3051 37 : pathnode->path.rows = outputRows;
3052 :
3053 37 : return pathnode;
3054 : }
3055 :
3056 : /*
3057 : * create_recursiveunion_path
3058 : * Creates a pathnode that represents a recursive UNION node
3059 : *
3060 : * 'rel' is the parent relation associated with the result
3061 : * 'leftpath' is the source of data for the non-recursive term
3062 : * 'rightpath' is the source of data for the recursive term
3063 : * 'target' is the PathTarget to be computed
3064 : * 'distinctList' is a list of SortGroupClause's representing the grouping
3065 : * 'wtParam' is the ID of Param representing work table
3066 : * 'numGroups' is the estimated number of groups
3067 : *
3068 : * For recursive UNION ALL, distinctList is empty and numGroups is zero
3069 : */
3070 : RecursiveUnionPath *
3071 40 : create_recursiveunion_path(PlannerInfo *root,
3072 : RelOptInfo *rel,
3073 : Path *leftpath,
3074 : Path *rightpath,
3075 : PathTarget *target,
3076 : List *distinctList,
3077 : int wtParam,
3078 : double numGroups)
3079 : {
3080 40 : RecursiveUnionPath *pathnode = makeNode(RecursiveUnionPath);
3081 :
3082 40 : pathnode->path.pathtype = T_RecursiveUnion;
3083 40 : pathnode->path.parent = rel;
3084 40 : pathnode->path.pathtarget = target;
3085 : /* For now, assume we are above any joins, so no parameterization */
3086 40 : pathnode->path.param_info = NULL;
3087 40 : pathnode->path.parallel_aware = false;
3088 80 : pathnode->path.parallel_safe = rel->consider_parallel &&
3089 40 : leftpath->parallel_safe && rightpath->parallel_safe;
3090 : /* Foolish, but we'll do it like joins for now: */
3091 40 : pathnode->path.parallel_workers = leftpath->parallel_workers;
3092 : /* RecursiveUnion result is always unsorted */
3093 40 : pathnode->path.pathkeys = NIL;
3094 :
3095 40 : pathnode->leftpath = leftpath;
3096 40 : pathnode->rightpath = rightpath;
3097 40 : pathnode->distinctList = distinctList;
3098 40 : pathnode->wtParam = wtParam;
3099 40 : pathnode->numGroups = numGroups;
3100 :
3101 40 : cost_recursive_union(&pathnode->path, leftpath, rightpath);
3102 :
3103 40 : return pathnode;
3104 : }
3105 :
3106 : /*
3107 : * create_lockrows_path
3108 : * Creates a pathnode that represents acquiring row locks
3109 : *
3110 : * 'rel' is the parent relation associated with the result
3111 : * 'subpath' is the path representing the source of data
3112 : * 'rowMarks' is a list of PlanRowMark's
3113 : * 'epqParam' is the ID of Param for EvalPlanQual re-eval
3114 : */
3115 : LockRowsPath *
3116 332 : create_lockrows_path(PlannerInfo *root, RelOptInfo *rel,
3117 : Path *subpath, List *rowMarks, int epqParam)
3118 : {
3119 332 : LockRowsPath *pathnode = makeNode(LockRowsPath);
3120 :
3121 332 : pathnode->path.pathtype = T_LockRows;
3122 332 : pathnode->path.parent = rel;
3123 : /* LockRows doesn't project, so use source path's pathtarget */
3124 332 : pathnode->path.pathtarget = subpath->pathtarget;
3125 : /* For now, assume we are above any joins, so no parameterization */
3126 332 : pathnode->path.param_info = NULL;
3127 332 : pathnode->path.parallel_aware = false;
3128 332 : pathnode->path.parallel_safe = false;
3129 332 : pathnode->path.parallel_workers = 0;
3130 332 : pathnode->path.rows = subpath->rows;
3131 :
3132 : /*
3133 : * The result cannot be assumed sorted, since locking might cause the sort
3134 : * key columns to be replaced with new values.
3135 : */
3136 332 : pathnode->path.pathkeys = NIL;
3137 :
3138 332 : pathnode->subpath = subpath;
3139 332 : pathnode->rowMarks = rowMarks;
3140 332 : pathnode->epqParam = epqParam;
3141 :
3142 : /*
3143 : * We should charge something extra for the costs of row locking and
3144 : * possible refetches, but it's hard to say how much. For now, use
3145 : * cpu_tuple_cost per row.
3146 : */
3147 332 : pathnode->path.startup_cost = subpath->startup_cost;
3148 664 : pathnode->path.total_cost = subpath->total_cost +
3149 332 : cpu_tuple_cost * subpath->rows;
3150 :
3151 332 : return pathnode;
3152 : }
3153 :
3154 : /*
3155 : * create_modifytable_path
3156 : * Creates a pathnode that represents performing INSERT/UPDATE/DELETE mods
3157 : *
3158 : * 'rel' is the parent relation associated with the result
3159 : * 'operation' is the operation type
3160 : * 'canSetTag' is true if we set the command tag/es_processed
3161 : * 'nominalRelation' is the parent RT index for use of EXPLAIN
3162 : * 'partitioned_rels' is an integer list of RT indexes of non-leaf tables in
3163 : * the partition tree, if this is an UPDATE/DELETE to a partitioned table.
3164 : * Otherwise NIL.
3165 : * 'resultRelations' is an integer list of actual RT indexes of target rel(s)
3166 : * 'subpaths' is a list of Path(s) producing source data (one per rel)
3167 : * 'subroots' is a list of PlannerInfo structs (one per rel)
3168 : * 'withCheckOptionLists' is a list of WCO lists (one per rel)
3169 : * 'returningLists' is a list of RETURNING tlists (one per rel)
3170 : * 'rowMarks' is a list of PlanRowMarks (non-locking only)
3171 : * 'onconflict' is the ON CONFLICT clause, or NULL
3172 : * 'epqParam' is the ID of Param for EvalPlanQual re-eval
3173 : */
3174 : ModifyTablePath *
3175 4340 : create_modifytable_path(PlannerInfo *root, RelOptInfo *rel,
3176 : CmdType operation, bool canSetTag,
3177 : Index nominalRelation, List *partitioned_rels,
3178 : List *resultRelations, List *subpaths,
3179 : List *subroots,
3180 : List *withCheckOptionLists, List *returningLists,
3181 : List *rowMarks, OnConflictExpr *onconflict,
3182 : int epqParam)
3183 : {
3184 4340 : ModifyTablePath *pathnode = makeNode(ModifyTablePath);
3185 : double total_size;
3186 : ListCell *lc;
3187 :
3188 4340 : Assert(list_length(resultRelations) == list_length(subpaths));
3189 4340 : Assert(list_length(resultRelations) == list_length(subroots));
3190 4340 : Assert(withCheckOptionLists == NIL ||
3191 : list_length(resultRelations) == list_length(withCheckOptionLists));
3192 4340 : Assert(returningLists == NIL ||
3193 : list_length(resultRelations) == list_length(returningLists));
3194 :
3195 4340 : pathnode->path.pathtype = T_ModifyTable;
3196 4340 : pathnode->path.parent = rel;
3197 : /* pathtarget is not interesting, just make it minimally valid */
3198 4340 : pathnode->path.pathtarget = rel->reltarget;
3199 : /* For now, assume we are above any joins, so no parameterization */
3200 4340 : pathnode->path.param_info = NULL;
3201 4340 : pathnode->path.parallel_aware = false;
3202 4340 : pathnode->path.parallel_safe = false;
3203 4340 : pathnode->path.parallel_workers = 0;
3204 4340 : pathnode->path.pathkeys = NIL;
3205 :
3206 : /*
3207 : * Compute cost & rowcount as sum of subpath costs & rowcounts.
3208 : *
3209 : * Currently, we don't charge anything extra for the actual table
3210 : * modification work, nor for the WITH CHECK OPTIONS or RETURNING
3211 : * expressions if any. It would only be window dressing, since
3212 : * ModifyTable is always a top-level node and there is no way for the
3213 : * costs to change any higher-level planning choices. But we might want
3214 : * to make it look better sometime.
3215 : */
3216 4340 : pathnode->path.startup_cost = 0;
3217 4340 : pathnode->path.total_cost = 0;
3218 4340 : pathnode->path.rows = 0;
3219 4340 : total_size = 0;
3220 8796 : foreach(lc, subpaths)
3221 : {
3222 4456 : Path *subpath = (Path *) lfirst(lc);
3223 :
3224 4456 : if (lc == list_head(subpaths)) /* first node? */
3225 4340 : pathnode->path.startup_cost = subpath->startup_cost;
3226 4456 : pathnode->path.total_cost += subpath->total_cost;
3227 4456 : pathnode->path.rows += subpath->rows;
3228 4456 : total_size += subpath->pathtarget->width * subpath->rows;
3229 : }
3230 :
3231 : /*
3232 : * Set width to the average width of the subpath outputs. XXX this is
3233 : * totally wrong: we should report zero if no RETURNING, else an average
3234 : * of the RETURNING tlist widths. But it's what happened historically,
3235 : * and improving it is a task for another day.
3236 : */
3237 4340 : if (pathnode->path.rows > 0)
3238 4334 : total_size /= pathnode->path.rows;
3239 4340 : pathnode->path.pathtarget->width = rint(total_size);
3240 :
3241 4340 : pathnode->operation = operation;
3242 4340 : pathnode->canSetTag = canSetTag;
3243 4340 : pathnode->nominalRelation = nominalRelation;
3244 4340 : pathnode->partitioned_rels = list_copy(partitioned_rels);
3245 4340 : pathnode->resultRelations = resultRelations;
3246 4340 : pathnode->subpaths = subpaths;
3247 4340 : pathnode->subroots = subroots;
3248 4340 : pathnode->withCheckOptionLists = withCheckOptionLists;
3249 4340 : pathnode->returningLists = returningLists;
3250 4340 : pathnode->rowMarks = rowMarks;
3251 4340 : pathnode->onconflict = onconflict;
3252 4340 : pathnode->epqParam = epqParam;
3253 :
3254 4340 : return pathnode;
3255 : }
3256 :
3257 : /*
3258 : * create_limit_path
3259 : * Creates a pathnode that represents performing LIMIT/OFFSET
3260 : *
3261 : * In addition to providing the actual OFFSET and LIMIT expressions,
3262 : * the caller must provide estimates of their values for costing purposes.
3263 : * The estimates are as computed by preprocess_limit(), ie, 0 represents
3264 : * the clause not being present, and -1 means it's present but we could
3265 : * not estimate its value.
3266 : *
3267 : * 'rel' is the parent relation associated with the result
3268 : * 'subpath' is the path representing the source of data
3269 : * 'limitOffset' is the actual OFFSET expression, or NULL
3270 : * 'limitCount' is the actual LIMIT expression, or NULL
3271 : * 'offset_est' is the estimated value of the OFFSET expression
3272 : * 'count_est' is the estimated value of the LIMIT expression
3273 : */
3274 : LimitPath *
3275 205 : create_limit_path(PlannerInfo *root, RelOptInfo *rel,
3276 : Path *subpath,
3277 : Node *limitOffset, Node *limitCount,
3278 : int64 offset_est, int64 count_est)
3279 : {
3280 205 : LimitPath *pathnode = makeNode(LimitPath);
3281 :
3282 205 : pathnode->path.pathtype = T_Limit;
3283 205 : pathnode->path.parent = rel;
3284 : /* Limit doesn't project, so use source path's pathtarget */
3285 205 : pathnode->path.pathtarget = subpath->pathtarget;
3286 : /* For now, assume we are above any joins, so no parameterization */
3287 205 : pathnode->path.param_info = NULL;
3288 205 : pathnode->path.parallel_aware = false;
3289 286 : pathnode->path.parallel_safe = rel->consider_parallel &&
3290 81 : subpath->parallel_safe;
3291 205 : pathnode->path.parallel_workers = subpath->parallel_workers;
3292 205 : pathnode->path.rows = subpath->rows;
3293 205 : pathnode->path.startup_cost = subpath->startup_cost;
3294 205 : pathnode->path.total_cost = subpath->total_cost;
3295 205 : pathnode->path.pathkeys = subpath->pathkeys;
3296 205 : pathnode->subpath = subpath;
3297 205 : pathnode->limitOffset = limitOffset;
3298 205 : pathnode->limitCount = limitCount;
3299 :
3300 : /*
3301 : * Adjust the output rows count and costs according to the offset/limit.
3302 : * This is only a cosmetic issue if we are at top level, but if we are
3303 : * building a subquery then it's important to report correct info to the
3304 : * outer planner.
3305 : *
3306 : * When the offset or count couldn't be estimated, use 10% of the
3307 : * estimated number of rows emitted from the subpath.
3308 : *
3309 : * XXX we don't bother to add eval costs of the offset/limit expressions
3310 : * themselves to the path costs. In theory we should, but in most cases
3311 : * those expressions are trivial and it's just not worth the trouble.
3312 : */
3313 205 : if (offset_est != 0)
3314 : {
3315 : double offset_rows;
3316 :
3317 19 : if (offset_est > 0)
3318 15 : offset_rows = (double) offset_est;
3319 : else
3320 4 : offset_rows = clamp_row_est(subpath->rows * 0.10);
3321 19 : if (offset_rows > pathnode->path.rows)
3322 3 : offset_rows = pathnode->path.rows;
3323 19 : if (subpath->rows > 0)
3324 76 : pathnode->path.startup_cost +=
3325 38 : (subpath->total_cost - subpath->startup_cost)
3326 19 : * offset_rows / subpath->rows;
3327 19 : pathnode->path.rows -= offset_rows;
3328 19 : if (pathnode->path.rows < 1)
3329 3 : pathnode->path.rows = 1;
3330 : }
3331 :
3332 205 : if (count_est != 0)
3333 : {
3334 : double count_rows;
3335 :
3336 201 : if (count_est > 0)
3337 200 : count_rows = (double) count_est;
3338 : else
3339 1 : count_rows = clamp_row_est(subpath->rows * 0.10);
3340 201 : if (count_rows > pathnode->path.rows)
3341 8 : count_rows = pathnode->path.rows;
3342 201 : if (subpath->rows > 0)
3343 804 : pathnode->path.total_cost = pathnode->path.startup_cost +
3344 402 : (subpath->total_cost - subpath->startup_cost)
3345 201 : * count_rows / subpath->rows;
3346 201 : pathnode->path.rows = count_rows;
3347 201 : if (pathnode->path.rows < 1)
3348 0 : pathnode->path.rows = 1;
3349 : }
3350 :
3351 205 : return pathnode;
3352 : }
3353 :
3354 :
3355 : /*
3356 : * reparameterize_path
3357 : * Attempt to modify a Path to have greater parameterization
3358 : *
3359 : * We use this to attempt to bring all child paths of an appendrel to the
3360 : * same parameterization level, ensuring that they all enforce the same set
3361 : * of join quals (and thus that that parameterization can be attributed to
3362 : * an append path built from such paths). Currently, only a few path types
3363 : * are supported here, though more could be added at need. We return NULL
3364 : * if we can't reparameterize the given path.
3365 : *
3366 : * Note: we intentionally do not pass created paths to add_path(); it would
3367 : * possibly try to delete them on the grounds of being cost-inferior to the
3368 : * paths they were made from, and we don't want that. Paths made here are
3369 : * not necessarily of general-purpose usefulness, but they can be useful
3370 : * as members of an append path.
3371 : */
3372 : Path *
3373 40 : reparameterize_path(PlannerInfo *root, Path *path,
3374 : Relids required_outer,
3375 : double loop_count)
3376 : {
3377 40 : RelOptInfo *rel = path->parent;
3378 :
3379 : /* Can only increase, not decrease, path's parameterization */
3380 40 : if (!bms_is_subset(PATH_REQ_OUTER(path), required_outer))
3381 0 : return NULL;
3382 40 : switch (path->pathtype)
3383 : {
3384 : case T_SeqScan:
3385 24 : return create_seqscan_path(root, rel, required_outer, 0);
3386 : case T_SampleScan:
3387 0 : return (Path *) create_samplescan_path(root, rel, required_outer);
3388 : case T_IndexScan:
3389 : case T_IndexOnlyScan:
3390 : {
3391 0 : IndexPath *ipath = (IndexPath *) path;
3392 0 : IndexPath *newpath = makeNode(IndexPath);
3393 :
3394 : /*
3395 : * We can't use create_index_path directly, and would not want
3396 : * to because it would re-compute the indexqual conditions
3397 : * which is wasted effort. Instead we hack things a bit:
3398 : * flat-copy the path node, revise its param_info, and redo
3399 : * the cost estimate.
3400 : */
3401 0 : memcpy(newpath, ipath, sizeof(IndexPath));
3402 0 : newpath->path.param_info =
3403 0 : get_baserel_parampathinfo(root, rel, required_outer);
3404 0 : cost_index(newpath, root, loop_count, false);
3405 0 : return (Path *) newpath;
3406 : }
3407 : case T_BitmapHeapScan:
3408 : {
3409 0 : BitmapHeapPath *bpath = (BitmapHeapPath *) path;
3410 :
3411 0 : return (Path *) create_bitmap_heap_path(root,
3412 : rel,
3413 : bpath->bitmapqual,
3414 : required_outer,
3415 : loop_count, 0);
3416 : }
3417 : case T_SubqueryScan:
3418 : {
3419 16 : SubqueryScanPath *spath = (SubqueryScanPath *) path;
3420 :
3421 16 : return (Path *) create_subqueryscan_path(root,
3422 : rel,
3423 : spath->subpath,
3424 : spath->path.pathkeys,
3425 : required_outer);
3426 : }
3427 : default:
3428 0 : break;
3429 : }
3430 0 : return NULL;
3431 : }
|