← Back to Overview

src/backend/optimizer/path/allpaths.c

Coverage: 18/18 lines (100.0%)
Total Lines
18
modified
Covered
18
100.0%
Uncovered
0
0.0%
Keyboard navigation
find_window_run_conditions() lines 2416-2600
Modified Lines Coverage: 1/1 lines (100.0%)
LineHitsSourceCommit
2416 - find_window_run_conditions(Query *subquery, AttrNumber attno, -
2417 - WindowFunc *wfunc, OpExpr *opexpr, bool wfunc_left, -
2418 - bool *keep_original, Bitmapset **run_cond_attrs) -
2419 - { -
2420 - Oid prosupport; -
2421 - Expr *otherexpr; -
2422 - SupportRequestWFuncMonotonic req; -
2423 - SupportRequestWFuncMonotonic *res; -
2424 - WindowClause *wclause; -
2425 - List *opinfos; -
2426 - OpExpr *runopexpr; -
2427 - Oid runoperator; -
2428 - ListCell *lc; -
2429 - -
2430 - *keep_original = true; -
2431 - -
2432 - while (IsA(wfunc, RelabelType)) -
2433 - wfunc = (WindowFunc *) ((RelabelType *) wfunc)->arg; -
2434 - -
2435 - /* we can only work with window functions */ -
2436 - if (!IsA(wfunc, WindowFunc)) -
2437 - return false; -
2438 - -
2439 - /* can't use it if there are subplans in the WindowFunc */ -
2440 - if (contain_subplans((Node *) wfunc)) -
2441 - return false; -
2442 - -
2443 - prosupport = get_func_support(wfunc->winfnoid); -
2444 - -
2445 - /* Check if there's a support function for 'wfunc' */ -
2446 - if (!OidIsValid(prosupport)) -
2447 - return false; -
2448 - -
2449 - /* get the Expr from the other side of the OpExpr */ -
2450 - if (wfunc_left) -
2451 - otherexpr = lsecond(opexpr->args); -
2452 - else -
2453 - otherexpr = linitial(opexpr->args); -
2454 - -
2455 - /* -
2456 - * The value being compared must not change during the evaluation of the -
2457 - * window partition. -
2458 - */ -
2459 - if (!is_pseudo_constant_clause((Node *) otherexpr)) -
2460 - return false; -
2461 - -
2462 - /* find the window clause belonging to the window function */ -
2463 - wclause = (WindowClause *) list_nth(subquery->windowClause, -
2464 - wfunc->winref - 1); -
2465 - -
2466 - /* 7521a30Row pattern recognition patch (planner).
2467 - * If a DEFINE clause exists, we cannot push down a run condition. In the 7521a30Row pattern recognition patch (planner).
2468 - * case, a window partition (or frame) is divided into multiple reduced 7521a30Row pattern recognition patch (planner).
2469 - * frames and each frame should be evaluated to the end of the partition 7521a30Row pattern recognition patch (planner).
2470 - * (or full frame end). This means we cannot apply the run condition 7521a30Row pattern recognition patch (planner).
2471 - * optimization because it stops evaluation window functions in certain 7521a30Row pattern recognition patch (planner).
2472 - * cases. 7521a30Row pattern recognition patch (planner).
2473 - */ 7521a30Row pattern recognition patch (planner).
2474 330 if (wclause->defineClause != NIL) 7521a30Row pattern recognition patch (planner).
2475 - return false; 7521a30Row pattern recognition patch (planner).
2476 - 7521a30Row pattern recognition patch (planner).
2477 - req.type = T_SupportRequestWFuncMonotonic; -
2478 - req.window_func = wfunc; -
2479 - req.window_clause = wclause; -
2480 - -
2481 - /* call the support function */ -
2482 - res = (SupportRequestWFuncMonotonic *) -
2483 - DatumGetPointer(OidFunctionCall1(prosupport, -
2484 - PointerGetDatum(&req))); -
2485 - -
2486 - /* -
2487 - * Nothing to do if the function is neither monotonically increasing nor -
2488 - * monotonically decreasing. -
2489 - */ -
2490 - if (res == NULL || res->monotonic == MONOTONICFUNC_NONE) -
2491 - return false; -
2492 - -
2493 - runopexpr = NULL; -
2494 - runoperator = InvalidOid; -
2495 - opinfos = get_op_index_interpretation(opexpr->opno); -
2496 - -
2497 - foreach(lc, opinfos) -
2498 - { -
2499 - OpIndexInterpretation *opinfo = (OpIndexInterpretation *) lfirst(lc); -
2500 - CompareType cmptype = opinfo->cmptype; -
2501 - -
2502 - /* handle < / <= */ -
2503 - if (cmptype == COMPARE_LT || cmptype == COMPARE_LE) -
2504 - { -
2505 - /* -
2506 - * < / <= is supported for monotonically increasing functions in -
2507 - * the form <wfunc> op <pseudoconst> and <pseudoconst> op <wfunc> -
2508 - * for monotonically decreasing functions. -
2509 - */ -
2510 - if ((wfunc_left && (res->monotonic & MONOTONICFUNC_INCREASING)) || -
2511 - (!wfunc_left && (res->monotonic & MONOTONICFUNC_DECREASING))) -
2512 - { -
2513 - *keep_original = false; -
2514 - runopexpr = opexpr; -
2515 - runoperator = opexpr->opno; -
2516 - } -
2517 - break; -
2518 - } -
2519 - /* handle > / >= */ -
2520 - else if (cmptype == COMPARE_GT || cmptype == COMPARE_GE) -
2521 - { -
2522 - /* -
2523 - * > / >= is supported for monotonically decreasing functions in -
2524 - * the form <wfunc> op <pseudoconst> and <pseudoconst> op <wfunc> -
2525 - * for monotonically increasing functions. -
2526 - */ -
2527 - if ((wfunc_left && (res->monotonic & MONOTONICFUNC_DECREASING)) || -
2528 - (!wfunc_left && (res->monotonic & MONOTONICFUNC_INCREASING))) -
2529 - { -
2530 - *keep_original = false; -
2531 - runopexpr = opexpr; -
2532 - runoperator = opexpr->opno; -
2533 - } -
2534 - break; -
2535 - } -
2536 - /* handle = */ -
2537 - else if (cmptype == COMPARE_EQ) -
2538 - { -
2539 - CompareType newcmptype; -
2540 - -
2541 - /* -
2542 - * When both monotonically increasing and decreasing then the -
2543 - * return value of the window function will be the same each time. -
2544 - * We can simply use 'opexpr' as the run condition without -
2545 - * modifying it. -
2546 - */ -
2547 - if ((res->monotonic & MONOTONICFUNC_BOTH) == MONOTONICFUNC_BOTH) -
2548 - { -
2549 - *keep_original = false; -
2550 - runopexpr = opexpr; -
2551 - runoperator = opexpr->opno; -
2552 - break; -
2553 - } -
2554 - -
2555 - /* -
2556 - * When monotonically increasing we make a qual with <wfunc> <= -
2557 - * <value> or <value> >= <wfunc> in order to filter out values -
2558 - * which are above the value in the equality condition. For -
2559 - * monotonically decreasing functions we want to filter values -
2560 - * below the value in the equality condition. -
2561 - */ -
2562 - if (res->monotonic & MONOTONICFUNC_INCREASING) -
2563 - newcmptype = wfunc_left ? COMPARE_LE : COMPARE_GE; -
2564 - else -
2565 - newcmptype = wfunc_left ? COMPARE_GE : COMPARE_LE; -
2566 - -
2567 - /* We must keep the original equality qual */ -
2568 - *keep_original = true; -
2569 - runopexpr = opexpr; -
2570 - -
2571 - /* determine the operator to use for the WindowFuncRunCondition */ -
2572 - runoperator = get_opfamily_member_for_cmptype(opinfo->opfamily_id, -
2573 - opinfo->oplefttype, -
2574 - opinfo->oprighttype, -
2575 - newcmptype); -
2576 - break; -
2577 - } -
2578 - } -
2579 - -
2580 - if (runopexpr != NULL) -
2581 - { -
2582 - WindowFuncRunCondition *wfuncrc; -
2583 - -
2584 - wfuncrc = makeNode(WindowFuncRunCondition); -
2585 - wfuncrc->opno = runoperator; -
2586 - wfuncrc->inputcollid = runopexpr->inputcollid; -
2587 - wfuncrc->wfunc_left = wfunc_left; -
2588 - wfuncrc->arg = copyObject(otherexpr); -
2589 - -
2590 - wfunc->runCondition = lappend(wfunc->runCondition, wfuncrc); -
2591 - -
2592 - /* record that this attno was used in a run condition */ -
2593 - *run_cond_attrs = bms_add_member(*run_cond_attrs, -
2594 - attno - FirstLowInvalidHeapAttributeNumber); -
2595 - return true; -
2596 - } -
2597 - -
2598 - /* unsupported OpExpr */ -
2599 - return false; -
2600 - } -
remove_unused_subquery_outputs() lines 4657-4835
Modified Lines Coverage: 17/17 lines (100.0%)
LineHitsSourceCommit
4657 - remove_unused_subquery_outputs(Query *subquery, RelOptInfo *rel, -
4658 - Bitmapset *extra_used_attrs) -
4659 - { -
4660 - Bitmapset *attrs_used; -
4661 - ListCell *lc; -
4662 - -
4663 - /* -
4664 - * Just point directly to extra_used_attrs. No need to bms_copy as none of -
4665 - * the current callers use the Bitmapset after calling this function. -
4666 - */ -
4667 - attrs_used = extra_used_attrs; -
4668 - -
4669 - /* -
4670 - * Do nothing if subquery has UNION/INTERSECT/EXCEPT: in principle we -
4671 - * could update all the child SELECTs' tlists, but it seems not worth the -
4672 - * trouble presently. -
4673 - */ -
4674 - if (subquery->setOperations) -
4675 - return; -
4676 - -
4677 - /* -
4678 - * If subquery has regular DISTINCT (not DISTINCT ON), we're wasting our -
4679 - * time: all its output columns must be used in the distinctClause. -
4680 - */ -
4681 - if (subquery->distinctClause && !subquery->hasDistinctOn) -
4682 - return; -
4683 - -
4684 - /* -
4685 - * Collect a bitmap of all the output column numbers used by the upper -
4686 - * query. -
4687 - * -
4688 - * Add all the attributes needed for joins or final output. Note: we must -
4689 - * look at rel's targetlist, not the attr_needed data, because attr_needed -
4690 - * isn't computed for inheritance child rels, cf set_append_rel_size(). -
4691 - * (XXX might be worth changing that sometime.) -
4692 - */ -
4693 - pull_varattnos((Node *) rel->reltarget->exprs, rel->relid, &attrs_used); -
4694 - -
4695 - /* Add all the attributes used by un-pushed-down restriction clauses. */ -
4696 - foreach(lc, rel->baserestrictinfo) -
4697 - { -
4698 - RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); -
4699 - -
4700 - pull_varattnos((Node *) rinfo->clause, rel->relid, &attrs_used); -
4701 - } -
4702 - -
4703 - /* -
4704 - * If there's a whole-row reference to the subquery, we can't remove -
4705 - * anything. -
4706 - */ -
4707 - if (bms_is_member(0 - FirstLowInvalidHeapAttributeNumber, attrs_used)) -
4708 - return; -
4709 - -
4710 - /* -
4711 - * Run through the tlist and zap entries we don't need. It's okay to -
4712 - * modify the tlist items in-place because set_subquery_pathlist made a -
4713 - * copy of the subquery. -
4714 - */ -
4715 - foreach(lc, subquery->targetList) -
4716 - { -
4717 - TargetEntry *tle = (TargetEntry *) lfirst(lc); -
4718 - Node *texpr = (Node *) tle->expr; -
4719 - -
4720 - /* -
4721 - * If it has a sortgroupref number, it's used in some sort/group -
4722 - * clause so we'd better not remove it. Also, don't remove any -
4723 - * resjunk columns, since their reason for being has nothing to do -
4724 - * with anybody reading the subquery's output. (It's likely that -
4725 - * resjunk columns in a sub-SELECT would always have ressortgroupref -
4726 - * set, but even if they don't, it seems imprudent to remove them.) -
4727 - */ -
4728 - if (tle->ressortgroupref || tle->resjunk) -
4729 - continue; -
4730 - -
4731 - /* -
4732 - * If it's used by the upper query, we can't remove it. -
4733 - */ -
4734 - if (bms_is_member(tle->resno - FirstLowInvalidHeapAttributeNumber, -
4735 - attrs_used)) -
4736 - continue; -
4737 - -
4738 - /* -
4739 - * If it contains a set-returning function, we can't remove it since -
4740 - * that could change the number of rows returned by the subquery. -
4741 - */ -
4742 - if (subquery->hasTargetSRFs && -
4743 - expression_returns_set(texpr)) -
4744 - continue; -
4745 - -
4746 - /* -
4747 - * If it contains volatile functions, we daren't remove it for fear -
4748 - * that the user is expecting their side-effects to happen. -
4749 - */ -
4750 - if (contain_volatile_functions(texpr)) -
4751 - continue; -
4752 - -
4753 - /* 7521a30Row pattern recognition patch (planner).
4754 - * If any RPR (Row Pattern Recognition) window clause references this 7521a30Row pattern recognition patch (planner).
4755 - * column in its DEFINE clause, don't remove it. The DEFINE 7521a30Row pattern recognition patch (planner).
4756 - * expression needs these columns in the tuplestore slot for pattern 7521a30Row pattern recognition patch (planner).
4757 - * matching evaluation, even if the outer query doesn't reference 7521a30Row pattern recognition patch (planner).
4758 - * them. 7521a30Row pattern recognition patch (planner).
4759 - */ 7521a30Row pattern recognition patch (planner).
4760 27223 if (IsA(texpr, Var)) 7521a30Row pattern recognition patch (planner).
4761 - { 7521a30Row pattern recognition patch (planner).
4762 - Var *var = (Var *) texpr; 7521a30Row pattern recognition patch (planner).
4763 - bool needed_by_define = false; 7521a30Row pattern recognition patch (planner).
4764 - 7521a30Row pattern recognition patch (planner).
4765 12762 foreach_node(WindowClause, wc, subquery->windowClause) 7521a30Row pattern recognition patch (planner).
4766 - { 7521a30Row pattern recognition patch (planner).
4767 55 if (wc->defineClause != NIL) 7521a30Row pattern recognition patch (planner).
4768 - { 7521a30Row pattern recognition patch (planner).
4769 50 List *vars = pull_var_clause((Node *) wc->defineClause, 0); 7521a30Row pattern recognition patch (planner).
4770 - 7521a30Row pattern recognition patch (planner).
4771 80 foreach_node(Var, dvar, vars) 7521a30Row pattern recognition patch (planner).
4772 - { 7521a30Row pattern recognition patch (planner).
4773 - 7521a30Row pattern recognition patch (planner).
4774 - /* 7521a30Row pattern recognition patch (planner).
4775 - * Match varno as well as varattno: a Var pulled from 7521a30Row pattern recognition patch (planner).
4776 - * a DEFINE clause can share an attribute number with 7521a30Row pattern recognition patch (planner).
4777 - * an unrelated output column of a different relation, 7521a30Row pattern recognition patch (planner).
4778 - * which would otherwise be over-retained. Checking 7521a30Row pattern recognition patch (planner).
4779 - * varlevelsup is just paranoia, since outer 7521a30Row pattern recognition patch (planner).
4780 - * references in DEFINE are rejected during parse 7521a30Row pattern recognition patch (planner).
4781 - * analysis. 7521a30Row pattern recognition patch (planner).
4782 - */ 7521a30Row pattern recognition patch (planner).
4783 60 if (dvar->varno == var->varno && 7521a30Row pattern recognition patch (planner).
4784 55 dvar->varattno == var->varattno && 7521a30Row pattern recognition patch (planner).
4785 30 dvar->varlevelsup == var->varlevelsup) 7521a30Row pattern recognition patch (planner).
4786 - { 7521a30Row pattern recognition patch (planner).
4787 - needed_by_define = true; 7521a30Row pattern recognition patch (planner).
4788 - break; 7521a30Row pattern recognition patch (planner).
4789 - } 7521a30Row pattern recognition patch (planner).
4790 - } 7521a30Row pattern recognition patch (planner).
4791 50 list_free(vars); 7521a30Row pattern recognition patch (planner).
4792 50 if (needed_by_define) 7521a30Row pattern recognition patch (planner).
4793 - break; 7521a30Row pattern recognition patch (planner).
4794 - } 7521a30Row pattern recognition patch (planner).
4795 - } 7521a30Row pattern recognition patch (planner).
4796 12737 if (needed_by_define) 7521a30Row pattern recognition patch (planner).
4797 30 continue; 7521a30Row pattern recognition patch (planner).
4798 - } 7521a30Row pattern recognition patch (planner).
4799 - 7521a30Row pattern recognition patch (planner).
4800 - /* 7521a30Row pattern recognition patch (planner).
4801 - * If it's a window function referencing a window clause with RPR, 7521a30Row pattern recognition patch (planner).
4802 - * don't remove it. Even when the window function result is unused by 7521a30Row pattern recognition patch (planner).
4803 - * the outer query, the RPR pattern matching (frame reduction via 7521a30Row pattern recognition patch (planner).
4804 - * DEFINE/PATTERN) must still execute. Replacing this with NULL would 7521a30Row pattern recognition patch (planner).
4805 - * leave no active window functions for the WindowClause, causing the 7521a30Row pattern recognition patch (planner).
4806 - * planner to omit the WindowAgg node entirely. 7521a30Row pattern recognition patch (planner).
4807 - */ 7521a30Row pattern recognition patch (planner).
4808 27193 if (IsA(texpr, WindowFunc)) 7521a30Row pattern recognition patch (planner).
4809 - { 7521a30Row pattern recognition patch (planner).
4810 - bool is_rpr = false; b848408Tidy up row pattern recognition plumbing
4811 - WindowFunc *wfunc = (WindowFunc *) texpr; 7521a30Row pattern recognition patch (planner).
4812 - 7521a30Row pattern recognition patch (planner).
4813 35 foreach_node(WindowClause, wc, subquery->windowClause) b848408Tidy up row pattern recognition plumbing
4814 - { 7521a30Row pattern recognition patch (planner).
4815 30 if (wc->winref == wfunc->winref && wc->defineClause != NIL) b848408Tidy up row pattern recognition plumbing
4816 - { 7521a30Row pattern recognition patch (planner).
4817 - is_rpr = true; b848408Tidy up row pattern recognition plumbing
4818 - break; 7521a30Row pattern recognition patch (planner).
4819 - } 7521a30Row pattern recognition patch (planner).
4820 - } 7521a30Row pattern recognition patch (planner).
4821 - b848408Tidy up row pattern recognition plumbing
4822 30 if (is_rpr) b848408Tidy up row pattern recognition plumbing
4823 25 continue; 7521a30Row pattern recognition patch (planner).
4824 - } 7521a30Row pattern recognition patch (planner).
4825 - 7521a30Row pattern recognition patch (planner).
4826 - /* -
4827 - * OK, we don't need it. Replace the expression with a NULL constant. -
4828 - * Preserve the exposed type of the expression, in case something -
4829 - * looks at the rowtype of the subquery's result. -
4830 - */ -
4831 - tle->expr = (Expr *) makeNullConst(exprType(texpr), -
4832 - exprTypmod(texpr), -
4833 - exprCollation(texpr)); -
4834 - } -
4835 - } -