* create_ordered_paths * * Build a new upperrel containing Paths for ORDER BY evaluation. * * All paths in the result must satisfy the ORDER BY ordering. * The only new paths we need consider are an explicit full sort * and incremental sort on the cheapest-total existing path. * * input_rel: contains the source-data Paths * target: the output tlist the result Paths must emit * limit_tupl
| 5351 | * other pathkeys (grouping, ...) like generate_useful_gather_paths. |
| 5352 | */ |
| 5353 | static RelOptInfo * |
| 5354 | create_ordered_paths(PlannerInfo *root, |
| 5355 | RelOptInfo *input_rel, |
| 5356 | PathTarget *target, |
| 5357 | bool target_parallel_safe, |
| 5358 | double limit_tuples) |
| 5359 | { |
| 5360 | Path *cheapest_input_path = input_rel->cheapest_total_path; |
| 5361 | RelOptInfo *ordered_rel; |
| 5362 | ListCell *lc; |
| 5363 | |
| 5364 | /* For now, do all work in the (ORDERED, NULL) upperrel */ |
| 5365 | ordered_rel = fetch_upper_rel(root, UPPERREL_ORDERED, NULL); |
| 5366 | |
| 5367 | /* |
| 5368 | * If the input relation is not parallel-safe, then the ordered relation |
| 5369 | * can't be parallel-safe, either. Otherwise, it's parallel-safe if the |
| 5370 | * target list is parallel-safe. |
| 5371 | */ |
| 5372 | if (input_rel->consider_parallel && target_parallel_safe) |
| 5373 | ordered_rel->consider_parallel = true; |
| 5374 | |
| 5375 | /* |
| 5376 | * If the input rel belongs to a single FDW, so does the ordered_rel. |
| 5377 | */ |
| 5378 | ordered_rel->serverid = input_rel->serverid; |
| 5379 | ordered_rel->userid = input_rel->userid; |
| 5380 | ordered_rel->useridiscurrent = input_rel->useridiscurrent; |
| 5381 | ordered_rel->fdwroutine = input_rel->fdwroutine; |
| 5382 | ordered_rel->exec_location = input_rel->exec_location; |
| 5383 | |
| 5384 | foreach(lc, input_rel->pathlist) |
| 5385 | { |
| 5386 | Path *input_path = (Path *) lfirst(lc); |
| 5387 | Path *sorted_path = input_path; |
| 5388 | bool is_sorted; |
| 5389 | int presorted_keys; |
| 5390 | |
| 5391 | is_sorted = pathkeys_count_contained_in(root->sort_pathkeys, |
| 5392 | input_path->pathkeys, &presorted_keys); |
| 5393 | |
| 5394 | if (is_sorted) |
| 5395 | { |
| 5396 | /* Use the input path as is, but add a projection step if needed */ |
| 5397 | if (sorted_path->pathtarget != target) |
| 5398 | sorted_path = apply_projection_to_path(root, ordered_rel, |
| 5399 | sorted_path, target); |
| 5400 | |
| 5401 | add_path(ordered_rel, sorted_path, root); |
| 5402 | } |
| 5403 | else |
| 5404 | { |
| 5405 | /* |
| 5406 | * Try adding an explicit sort, but only to the cheapest total |
| 5407 | * path since a full sort should generally add the same cost to |
| 5408 | * all paths. |
| 5409 | */ |
| 5410 | if (input_path == cheapest_input_path) |
no test coverage detected