* build_minmax_path * Given a MIN/MAX aggregate, try to build an indexscan Path it can be * optimized with. * * If successful, stash the best path in *mminfo and return true. * Otherwise, return false. */
| 330 | * Otherwise, return false. |
| 331 | */ |
| 332 | static bool |
| 333 | build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo, |
| 334 | Oid eqop, Oid sortop, bool nulls_first) |
| 335 | { |
| 336 | PlannerInfo *subroot; |
| 337 | Query *parse; |
| 338 | TargetEntry *tle; |
| 339 | List *tlist; |
| 340 | NullTest *ntest; |
| 341 | SortGroupClause *sortcl; |
| 342 | RelOptInfo *final_rel; |
| 343 | Path *sorted_path; |
| 344 | Cost path_cost; |
| 345 | double path_fraction; |
| 346 | |
| 347 | /* |
| 348 | * We are going to construct what is effectively a sub-SELECT query, so |
| 349 | * clone the current query level's state and adjust it to make it look |
| 350 | * like a subquery. Any outer references will now be one level higher |
| 351 | * than before. (This means that when we are done, there will be no Vars |
| 352 | * of level 1, which is why the subquery can become an initplan.) |
| 353 | */ |
| 354 | subroot = (PlannerInfo *) palloc(sizeof(PlannerInfo)); |
| 355 | memcpy(subroot, root, sizeof(PlannerInfo)); |
| 356 | subroot->query_level++; |
| 357 | subroot->parent_root = root; |
| 358 | /* reset subplan-related stuff */ |
| 359 | subroot->plan_params = NIL; |
| 360 | subroot->outer_params = NULL; |
| 361 | subroot->init_plans = NIL; |
| 362 | subroot->agginfos = NIL; |
| 363 | subroot->aggtransinfos = NIL; |
| 364 | |
| 365 | subroot->parse = parse = copyObject(root->parse); |
| 366 | IncrementVarSublevelsUp((Node *) parse, 1, 1); |
| 367 | |
| 368 | /* append_rel_list might contain outer Vars? */ |
| 369 | subroot->append_rel_list = copyObject(root->append_rel_list); |
| 370 | IncrementVarSublevelsUp((Node *) subroot->append_rel_list, 1, 1); |
| 371 | /* There shouldn't be any OJ info to translate, as yet */ |
| 372 | Assert(subroot->join_info_list == NIL); |
| 373 | /* and we haven't made equivalence classes, either */ |
| 374 | Assert(subroot->eq_classes == NIL); |
| 375 | /* and we haven't created PlaceHolderInfos, either */ |
| 376 | Assert(subroot->placeholder_list == NIL); |
| 377 | |
| 378 | /*---------- |
| 379 | * Generate modified query of the form |
| 380 | * (SELECT col FROM tab |
| 381 | * WHERE col IS NOT NULL AND existing-quals |
| 382 | * ORDER BY col ASC/DESC |
| 383 | * LIMIT 1) |
| 384 | *---------- |
| 385 | */ |
| 386 | /* single tlist entry that is the aggregate target */ |
| 387 | tle = makeTargetEntry(copyObject(mminfo->target), |
| 388 | (AttrNumber) 1, |
| 389 | pstrdup("agg_target"), |
no test coverage detected