| Line | Hits | Source | Commit |
| 693 |
- |
subquery_planner(PlannerGlobal *glob, Query *parse, char *plan_name, |
- |
| 694 |
- |
PlannerInfo *parent_root, bool hasRecursion, |
- |
| 695 |
- |
double tuple_fraction, SetOperationStmt *setops) |
- |
| 696 |
- |
{ |
- |
| 697 |
- |
PlannerInfo *root; |
- |
| 698 |
- |
List *newWithCheckOptions; |
- |
| 699 |
- |
List *newHaving; |
- |
| 700 |
- |
bool hasOuterJoins; |
- |
| 701 |
- |
bool hasResultRTEs; |
- |
| 702 |
- |
RelOptInfo *final_rel; |
- |
| 703 |
- |
ListCell *l; |
- |
| 704 |
- |
|
- |
| 705 |
- |
/* Create a PlannerInfo data structure for this subquery */ |
- |
| 706 |
- |
root = makeNode(PlannerInfo); |
- |
| 707 |
- |
root->parse = parse; |
- |
| 708 |
- |
root->glob = glob; |
- |
| 709 |
- |
root->query_level = parent_root ? parent_root->query_level + 1 : 1; |
- |
| 710 |
- |
root->plan_name = plan_name; |
- |
| 711 |
- |
root->parent_root = parent_root; |
- |
| 712 |
- |
root->plan_params = NIL; |
- |
| 713 |
- |
root->outer_params = NULL; |
- |
| 714 |
- |
root->planner_cxt = CurrentMemoryContext; |
- |
| 715 |
- |
root->init_plans = NIL; |
- |
| 716 |
- |
root->cte_plan_ids = NIL; |
- |
| 717 |
- |
root->multiexpr_params = NIL; |
- |
| 718 |
- |
root->join_domains = NIL; |
- |
| 719 |
- |
root->eq_classes = NIL; |
- |
| 720 |
- |
root->ec_merging_done = false; |
- |
| 721 |
- |
root->last_rinfo_serial = 0; |
- |
| 722 |
- |
root->all_result_relids = |
- |
| 723 |
- |
parse->resultRelation ? bms_make_singleton(parse->resultRelation) : NULL; |
- |
| 724 |
- |
root->leaf_result_relids = NULL; /* we'll find out leaf-ness later */ |
- |
| 725 |
- |
root->append_rel_list = NIL; |
- |
| 726 |
- |
root->row_identity_vars = NIL; |
- |
| 727 |
- |
root->rowMarks = NIL; |
- |
| 728 |
- |
memset(root->upper_rels, 0, sizeof(root->upper_rels)); |
- |
| 729 |
- |
memset(root->upper_targets, 0, sizeof(root->upper_targets)); |
- |
| 730 |
- |
root->processed_groupClause = NIL; |
- |
| 731 |
- |
root->processed_distinctClause = NIL; |
- |
| 732 |
- |
root->processed_tlist = NIL; |
- |
| 733 |
- |
root->update_colnos = NIL; |
- |
| 734 |
- |
root->grouping_map = NULL; |
- |
| 735 |
- |
root->minmax_aggs = NIL; |
- |
| 736 |
- |
root->qual_security_level = 0; |
- |
| 737 |
- |
root->hasPseudoConstantQuals = false; |
- |
| 738 |
- |
root->hasAlternativeSubPlans = false; |
- |
| 739 |
- |
root->placeholdersFrozen = false; |
- |
| 740 |
- |
root->hasRecursion = hasRecursion; |
- |
| 741 |
- |
root->assumeReplanning = false; |
- |
| 742 |
- |
if (hasRecursion) |
- |
| 743 |
- |
root->wt_param_id = assign_special_exec_param(root); |
- |
| 744 |
- |
else |
- |
| 745 |
- |
root->wt_param_id = -1; |
- |
| 746 |
- |
root->non_recursive_path = NULL; |
- |
| 747 |
- |
|
- |
| 748 |
- |
/* |
- |
| 749 |
- |
* Create the top-level join domain. This won't have valid contents until |
- |
| 750 |
- |
* deconstruct_jointree fills it in, but the node needs to exist before |
- |
| 751 |
- |
* that so we can build EquivalenceClasses referencing it. |
- |
| 752 |
- |
*/ |
- |
| 753 |
- |
root->join_domains = list_make1(makeNode(JoinDomain)); |
- |
| 754 |
- |
|
- |
| 755 |
- |
/* |
- |
| 756 |
- |
* If there is a WITH list, process each WITH query and either convert it |
- |
| 757 |
- |
* to RTE_SUBQUERY RTE(s) or build an initplan SubPlan structure for it. |
- |
| 758 |
- |
*/ |
- |
| 759 |
- |
if (parse->cteList) |
- |
| 760 |
- |
SS_process_ctes(root); |
- |
| 761 |
- |
|
- |
| 762 |
- |
/* |
- |
| 763 |
- |
* If it's a MERGE command, transform the joinlist as appropriate. |
- |
| 764 |
- |
*/ |
- |
| 765 |
- |
transform_MERGE_to_join(parse); |
- |
| 766 |
- |
|
- |
| 767 |
- |
/* |
- |
| 768 |
- |
* Scan the rangetable for relation RTEs and retrieve the necessary |
- |
| 769 |
- |
* catalog information for each relation. Using this information, clear |
- |
| 770 |
- |
* the inh flag for any relation that has no children, collect not-null |
- |
| 771 |
- |
* attribute numbers for any relation that has column not-null |
- |
| 772 |
- |
* constraints, and expand virtual generated columns for any relation that |
- |
| 773 |
- |
* contains them. Note that this step does not descend into sublinks and |
- |
| 774 |
- |
* subqueries; if we pull up any sublinks or subqueries below, their |
- |
| 775 |
- |
* relation RTEs are processed just before pulling them up. |
- |
| 776 |
- |
*/ |
- |
| 777 |
- |
parse = root->parse = preprocess_relation_rtes(root); |
- |
| 778 |
- |
|
- |
| 779 |
- |
/* |
- |
| 780 |
- |
* If the FROM clause is empty, replace it with a dummy RTE_RESULT RTE, so |
- |
| 781 |
- |
* that we don't need so many special cases to deal with that situation. |
- |
| 782 |
- |
*/ |
- |
| 783 |
- |
replace_empty_jointree(parse); |
- |
| 784 |
- |
|
- |
| 785 |
- |
/* |
- |
| 786 |
- |
* Look for ANY and EXISTS SubLinks in WHERE and JOIN/ON clauses, and try |
- |
| 787 |
- |
* to transform them into joins. Note that this step does not descend |
- |
| 788 |
- |
* into subqueries; if we pull up any subqueries below, their SubLinks are |
- |
| 789 |
- |
* processed just before pulling them up. |
- |
| 790 |
- |
*/ |
- |
| 791 |
- |
if (parse->hasSubLinks) |
- |
| 792 |
- |
pull_up_sublinks(root); |
- |
| 793 |
- |
|
- |
| 794 |
- |
/* |
- |
| 795 |
- |
* Scan the rangetable for function RTEs, do const-simplification on them, |
- |
| 796 |
- |
* and then inline them if possible (producing subqueries that might get |
- |
| 797 |
- |
* pulled up next). Recursion issues here are handled in the same way as |
- |
| 798 |
- |
* for SubLinks. |
- |
| 799 |
- |
*/ |
- |
| 800 |
- |
preprocess_function_rtes(root); |
- |
| 801 |
- |
|
- |
| 802 |
- |
/* |
- |
| 803 |
- |
* Check to see if any subqueries in the jointree can be merged into this |
- |
| 804 |
- |
* query. |
- |
| 805 |
- |
*/ |
- |
| 806 |
- |
pull_up_subqueries(root); |
- |
| 807 |
- |
|
- |
| 808 |
- |
/* |
- |
| 809 |
- |
* If this is a simple UNION ALL query, flatten it into an appendrel. We |
- |
| 810 |
- |
* do this now because it requires applying pull_up_subqueries to the leaf |
- |
| 811 |
- |
* queries of the UNION ALL, which weren't touched above because they |
- |
| 812 |
- |
* weren't referenced by the jointree (they will be after we do this). |
- |
| 813 |
- |
*/ |
- |
| 814 |
- |
if (parse->setOperations) |
- |
| 815 |
- |
flatten_simple_union_all(root); |
- |
| 816 |
- |
|
- |
| 817 |
- |
/* |
- |
| 818 |
- |
* Survey the rangetable to see what kinds of entries are present. We can |
- |
| 819 |
- |
* skip some later processing if relevant SQL features are not used; for |
- |
| 820 |
- |
* example if there are no JOIN RTEs we can avoid the expense of doing |
- |
| 821 |
- |
* flatten_join_alias_vars(). This must be done after we have finished |
- |
| 822 |
- |
* adding rangetable entries, of course. (Note: actually, processing of |
- |
| 823 |
- |
* inherited or partitioned rels can cause RTEs for their child tables to |
- |
| 824 |
- |
* get added later; but those must all be RTE_RELATION entries, so they |
- |
| 825 |
- |
* don't invalidate the conclusions drawn here.) |
- |
| 826 |
- |
*/ |
- |
| 827 |
- |
root->hasJoinRTEs = false; |
- |
| 828 |
- |
root->hasLateralRTEs = false; |
- |
| 829 |
- |
root->group_rtindex = 0; |
- |
| 830 |
- |
hasOuterJoins = false; |
- |
| 831 |
- |
hasResultRTEs = false; |
- |
| 832 |
- |
foreach(l, parse->rtable) |
- |
| 833 |
- |
{ |
- |
| 834 |
- |
RangeTblEntry *rte = lfirst_node(RangeTblEntry, l); |
- |
| 835 |
- |
|
- |
| 836 |
- |
switch (rte->rtekind) |
- |
| 837 |
- |
{ |
- |
| 838 |
- |
case RTE_JOIN: |
- |
| 839 |
- |
root->hasJoinRTEs = true; |
- |
| 840 |
- |
if (IS_OUTER_JOIN(rte->jointype)) |
- |
| 841 |
- |
hasOuterJoins = true; |
- |
| 842 |
- |
break; |
- |
| 843 |
- |
case RTE_RESULT: |
- |
| 844 |
- |
hasResultRTEs = true; |
- |
| 845 |
- |
break; |
- |
| 846 |
- |
case RTE_GROUP: |
- |
| 847 |
- |
Assert(parse->hasGroupRTE); |
- |
| 848 |
- |
root->group_rtindex = list_cell_number(parse->rtable, l) + 1; |
- |
| 849 |
- |
break; |
- |
| 850 |
- |
default: |
- |
| 851 |
- |
/* No work here for other RTE types */ |
- |
| 852 |
- |
break; |
- |
| 853 |
- |
} |
- |
| 854 |
- |
|
- |
| 855 |
- |
if (rte->lateral) |
- |
| 856 |
- |
root->hasLateralRTEs = true; |
- |
| 857 |
- |
|
- |
| 858 |
- |
/* |
- |
| 859 |
- |
* We can also determine the maximum security level required for any |
- |
| 860 |
- |
* securityQuals now. Addition of inheritance-child RTEs won't affect |
- |
| 861 |
- |
* this, because child tables don't have their own securityQuals; see |
- |
| 862 |
- |
* expand_single_inheritance_child(). |
- |
| 863 |
- |
*/ |
- |
| 864 |
- |
if (rte->securityQuals) |
- |
| 865 |
- |
root->qual_security_level = Max(root->qual_security_level, |
- |
| 866 |
- |
list_length(rte->securityQuals)); |
- |
| 867 |
- |
} |
- |
| 868 |
- |
|
- |
| 869 |
- |
/* |
- |
| 870 |
- |
* If we have now verified that the query target relation is |
- |
| 871 |
- |
* non-inheriting, mark it as a leaf target. |
- |
| 872 |
- |
*/ |
- |
| 873 |
- |
if (parse->resultRelation) |
- |
| 874 |
- |
{ |
- |
| 875 |
- |
RangeTblEntry *rte = rt_fetch(parse->resultRelation, parse->rtable); |
- |
| 876 |
- |
|
- |
| 877 |
- |
if (!rte->inh) |
- |
| 878 |
- |
root->leaf_result_relids = |
- |
| 879 |
- |
bms_make_singleton(parse->resultRelation); |
- |
| 880 |
- |
} |
- |
| 881 |
- |
|
- |
| 882 |
- |
/* |
- |
| 883 |
- |
* This would be a convenient time to check access permissions for all |
- |
| 884 |
- |
* relations mentioned in the query, since it would be better to fail now, |
- |
| 885 |
- |
* before doing any detailed planning. However, for historical reasons, |
- |
| 886 |
- |
* we leave this to be done at executor startup. |
- |
| 887 |
- |
* |
- |
| 888 |
- |
* Note, however, that we do need to check access permissions for any view |
- |
| 889 |
- |
* relations mentioned in the query, in order to prevent information being |
- |
| 890 |
- |
* leaked by selectivity estimation functions, which only check view owner |
- |
| 891 |
- |
* permissions on underlying tables (see all_rows_selectable() and its |
- |
| 892 |
- |
* callers). This is a little ugly, because it means that access |
- |
| 893 |
- |
* permissions for views will be checked twice, which is another reason |
- |
| 894 |
- |
* why it would be better to do all the ACL checks here. |
- |
| 895 |
- |
*/ |
- |
| 896 |
- |
foreach(l, parse->rtable) |
- |
| 897 |
- |
{ |
- |
| 898 |
- |
RangeTblEntry *rte = lfirst_node(RangeTblEntry, l); |
- |
| 899 |
- |
|
- |
| 900 |
- |
if (rte->perminfoindex != 0 && |
- |
| 901 |
- |
rte->relkind == RELKIND_VIEW) |
- |
| 902 |
- |
{ |
- |
| 903 |
- |
RTEPermissionInfo *perminfo; |
- |
| 904 |
- |
bool result; |
- |
| 905 |
- |
|
- |
| 906 |
- |
perminfo = getRTEPermissionInfo(parse->rteperminfos, rte); |
- |
| 907 |
- |
result = ExecCheckOneRelPerms(perminfo); |
- |
| 908 |
- |
if (!result) |
- |
| 909 |
- |
aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_VIEW, |
- |
| 910 |
- |
get_rel_name(perminfo->relid)); |
- |
| 911 |
- |
} |
- |
| 912 |
- |
} |
- |
| 913 |
- |
|
- |
| 914 |
- |
/* |
- |
| 915 |
- |
* Preprocess RowMark information. We need to do this after subquery |
- |
| 916 |
- |
* pullup, so that all base relations are present. |
- |
| 917 |
- |
*/ |
- |
| 918 |
- |
preprocess_rowmarks(root); |
- |
| 919 |
- |
|
- |
| 920 |
- |
/* |
- |
| 921 |
- |
* Set hasHavingQual to remember if HAVING clause is present. Needed |
- |
| 922 |
- |
* because preprocess_expression will reduce a constant-true condition to |
- |
| 923 |
- |
* an empty qual list ... but "HAVING TRUE" is not a semantic no-op. |
- |
| 924 |
- |
*/ |
- |
| 925 |
- |
root->hasHavingQual = (parse->havingQual != NULL); |
- |
| 926 |
- |
|
- |
| 927 |
- |
/* |
- |
| 928 |
- |
* Do expression preprocessing on targetlist and quals, as well as other |
- |
| 929 |
- |
* random expressions in the querytree. Note that we do not need to |
- |
| 930 |
- |
* handle sort/group expressions explicitly, because they are actually |
- |
| 931 |
- |
* part of the targetlist. |
- |
| 932 |
- |
*/ |
- |
| 933 |
- |
parse->targetList = (List *) |
- |
| 934 |
- |
preprocess_expression(root, (Node *) parse->targetList, |
- |
| 935 |
- |
EXPRKIND_TARGET); |
- |
| 936 |
- |
|
- |
| 937 |
- |
newWithCheckOptions = NIL; |
- |
| 938 |
- |
foreach(l, parse->withCheckOptions) |
- |
| 939 |
- |
{ |
- |
| 940 |
- |
WithCheckOption *wco = lfirst_node(WithCheckOption, l); |
- |
| 941 |
- |
|
- |
| 942 |
- |
wco->qual = preprocess_expression(root, wco->qual, |
- |
| 943 |
- |
EXPRKIND_QUAL); |
- |
| 944 |
- |
if (wco->qual != NULL) |
- |
| 945 |
- |
newWithCheckOptions = lappend(newWithCheckOptions, wco); |
- |
| 946 |
- |
} |
- |
| 947 |
- |
parse->withCheckOptions = newWithCheckOptions; |
- |
| 948 |
- |
|
- |
| 949 |
- |
parse->returningList = (List *) |
- |
| 950 |
- |
preprocess_expression(root, (Node *) parse->returningList, |
- |
| 951 |
- |
EXPRKIND_TARGET); |
- |
| 952 |
- |
|
- |
| 953 |
- |
preprocess_qual_conditions(root, (Node *) parse->jointree); |
- |
| 954 |
- |
|
- |
| 955 |
- |
parse->havingQual = preprocess_expression(root, parse->havingQual, |
- |
| 956 |
- |
EXPRKIND_QUAL); |
- |
| 957 |
- |
|
- |
| 958 |
- |
foreach(l, parse->windowClause) |
- |
| 959 |
- |
{ |
- |
| 960 |
- |
WindowClause *wc = lfirst_node(WindowClause, l); |
- |
| 961 |
- |
|
- |
| 962 |
- |
/* partitionClause/orderClause are sort/group expressions */ |
- |
| 963 |
- |
wc->startOffset = preprocess_expression(root, wc->startOffset, |
- |
| 964 |
- |
EXPRKIND_LIMIT); |
- |
| 965 |
- |
wc->endOffset = preprocess_expression(root, wc->endOffset, |
- |
| 966 |
- |
EXPRKIND_LIMIT); |
- |
| 967 |
1489 |
wc->defineClause = (List *) preprocess_expression(root, |
e33632aRow pattern recognition patch (planner). |
| 968 |
1489 |
(Node *) wc->defineClause, |
e33632aRow pattern recognition patch (planner). |
| 969 |
- |
EXPRKIND_TARGET); |
e33632aRow pattern recognition patch (planner). |
| 970 |
- |
} |
- |
| 971 |
- |
|
- |
| 972 |
- |
parse->limitOffset = preprocess_expression(root, parse->limitOffset, |
- |
| 973 |
- |
EXPRKIND_LIMIT); |
- |
| 974 |
- |
parse->limitCount = preprocess_expression(root, parse->limitCount, |
- |
| 975 |
- |
EXPRKIND_LIMIT); |
- |
| 976 |
- |
|
- |
| 977 |
- |
if (parse->onConflict) |
- |
| 978 |
- |
{ |
- |
| 979 |
- |
parse->onConflict->arbiterElems = (List *) |
- |
| 980 |
- |
preprocess_expression(root, |
- |
| 981 |
- |
(Node *) parse->onConflict->arbiterElems, |
- |
| 982 |
- |
EXPRKIND_ARBITER_ELEM); |
- |
| 983 |
- |
parse->onConflict->arbiterWhere = |
- |
| 984 |
- |
preprocess_expression(root, |
- |
| 985 |
- |
parse->onConflict->arbiterWhere, |
- |
| 986 |
- |
EXPRKIND_QUAL); |
- |
| 987 |
- |
parse->onConflict->onConflictSet = (List *) |
- |
| 988 |
- |
preprocess_expression(root, |
- |
| 989 |
- |
(Node *) parse->onConflict->onConflictSet, |
- |
| 990 |
- |
EXPRKIND_TARGET); |
- |
| 991 |
- |
parse->onConflict->onConflictWhere = |
- |
| 992 |
- |
preprocess_expression(root, |
- |
| 993 |
- |
parse->onConflict->onConflictWhere, |
- |
| 994 |
- |
EXPRKIND_QUAL); |
- |
| 995 |
- |
/* exclRelTlist contains only Vars, so no preprocessing needed */ |
- |
| 996 |
- |
} |
- |
| 997 |
- |
|
- |
| 998 |
- |
foreach(l, parse->mergeActionList) |
- |
| 999 |
- |
{ |
- |
| 1000 |
- |
MergeAction *action = (MergeAction *) lfirst(l); |
- |
| 1001 |
- |
|
- |
| 1002 |
- |
action->targetList = (List *) |
- |
| 1003 |
- |
preprocess_expression(root, |
- |
| 1004 |
- |
(Node *) action->targetList, |
- |
| 1005 |
- |
EXPRKIND_TARGET); |
- |
| 1006 |
- |
action->qual = |
- |
| 1007 |
- |
preprocess_expression(root, |
- |
| 1008 |
- |
(Node *) action->qual, |
- |
| 1009 |
- |
EXPRKIND_QUAL); |
- |
| 1010 |
- |
} |
- |
| 1011 |
- |
|
- |
| 1012 |
- |
parse->mergeJoinCondition = |
- |
| 1013 |
- |
preprocess_expression(root, parse->mergeJoinCondition, EXPRKIND_QUAL); |
- |
| 1014 |
- |
|
- |
| 1015 |
- |
root->append_rel_list = (List *) |
- |
| 1016 |
- |
preprocess_expression(root, (Node *) root->append_rel_list, |
- |
| 1017 |
- |
EXPRKIND_APPINFO); |
- |
| 1018 |
- |
|
- |
| 1019 |
- |
/* Also need to preprocess expressions within RTEs */ |
- |
| 1020 |
- |
foreach(l, parse->rtable) |
- |
| 1021 |
- |
{ |
- |
| 1022 |
- |
RangeTblEntry *rte = lfirst_node(RangeTblEntry, l); |
- |
| 1023 |
- |
int kind; |
- |
| 1024 |
- |
ListCell *lcsq; |
- |
| 1025 |
- |
|
- |
| 1026 |
- |
if (rte->rtekind == RTE_RELATION) |
- |
| 1027 |
- |
{ |
- |
| 1028 |
- |
if (rte->tablesample) |
- |
| 1029 |
- |
rte->tablesample = (TableSampleClause *) |
- |
| 1030 |
- |
preprocess_expression(root, |
- |
| 1031 |
- |
(Node *) rte->tablesample, |
- |
| 1032 |
- |
EXPRKIND_TABLESAMPLE); |
- |
| 1033 |
- |
} |
- |
| 1034 |
- |
else if (rte->rtekind == RTE_SUBQUERY) |
- |
| 1035 |
- |
{ |
- |
| 1036 |
- |
/* |
- |
| 1037 |
- |
* We don't want to do all preprocessing yet on the subquery's |
- |
| 1038 |
- |
* expressions, since that will happen when we plan it. But if it |
- |
| 1039 |
- |
* contains any join aliases of our level, those have to get |
- |
| 1040 |
- |
* expanded now, because planning of the subquery won't do it. |
- |
| 1041 |
- |
* That's only possible if the subquery is LATERAL. |
- |
| 1042 |
- |
*/ |
- |
| 1043 |
- |
if (rte->lateral && root->hasJoinRTEs) |
- |
| 1044 |
- |
rte->subquery = (Query *) |
- |
| 1045 |
- |
flatten_join_alias_vars(root, root->parse, |
- |
| 1046 |
- |
(Node *) rte->subquery); |
- |
| 1047 |
- |
} |
- |
| 1048 |
- |
else if (rte->rtekind == RTE_FUNCTION) |
- |
| 1049 |
- |
{ |
- |
| 1050 |
- |
/* Preprocess the function expression(s) fully */ |
- |
| 1051 |
- |
kind = rte->lateral ? EXPRKIND_RTFUNC_LATERAL : EXPRKIND_RTFUNC; |
- |
| 1052 |
- |
rte->functions = (List *) |
- |
| 1053 |
- |
preprocess_expression(root, (Node *) rte->functions, kind); |
- |
| 1054 |
- |
} |
- |
| 1055 |
- |
else if (rte->rtekind == RTE_TABLEFUNC) |
- |
| 1056 |
- |
{ |
- |
| 1057 |
- |
/* Preprocess the function expression(s) fully */ |
- |
| 1058 |
- |
kind = rte->lateral ? EXPRKIND_TABLEFUNC_LATERAL : EXPRKIND_TABLEFUNC; |
- |
| 1059 |
- |
rte->tablefunc = (TableFunc *) |
- |
| 1060 |
- |
preprocess_expression(root, (Node *) rte->tablefunc, kind); |
- |
| 1061 |
- |
} |
- |
| 1062 |
- |
else if (rte->rtekind == RTE_VALUES) |
- |
| 1063 |
- |
{ |
- |
| 1064 |
- |
/* Preprocess the values lists fully */ |
- |
| 1065 |
- |
kind = rte->lateral ? EXPRKIND_VALUES_LATERAL : EXPRKIND_VALUES; |
- |
| 1066 |
- |
rte->values_lists = (List *) |
- |
| 1067 |
- |
preprocess_expression(root, (Node *) rte->values_lists, kind); |
- |
| 1068 |
- |
} |
- |
| 1069 |
- |
else if (rte->rtekind == RTE_GROUP) |
- |
| 1070 |
- |
{ |
- |
| 1071 |
- |
/* Preprocess the groupexprs list fully */ |
- |
| 1072 |
- |
rte->groupexprs = (List *) |
- |
| 1073 |
- |
preprocess_expression(root, (Node *) rte->groupexprs, |
- |
| 1074 |
- |
EXPRKIND_GROUPEXPR); |
- |
| 1075 |
- |
} |
- |
| 1076 |
- |
|
- |
| 1077 |
- |
/* |
- |
| 1078 |
- |
* Process each element of the securityQuals list as if it were a |
- |
| 1079 |
- |
* separate qual expression (as indeed it is). We need to do it this |
- |
| 1080 |
- |
* way to get proper canonicalization of AND/OR structure. Note that |
- |
| 1081 |
- |
* this converts each element into an implicit-AND sublist. |
- |
| 1082 |
- |
*/ |
- |
| 1083 |
- |
foreach(lcsq, rte->securityQuals) |
- |
| 1084 |
- |
{ |
- |
| 1085 |
- |
lfirst(lcsq) = preprocess_expression(root, |
- |
| 1086 |
- |
(Node *) lfirst(lcsq), |
- |
| 1087 |
- |
EXPRKIND_QUAL); |
- |
| 1088 |
- |
} |
- |
| 1089 |
- |
} |
- |
| 1090 |
- |
|
- |
| 1091 |
- |
/* |
- |
| 1092 |
- |
* Now that we are done preprocessing expressions, and in particular done |
- |
| 1093 |
- |
* flattening join alias variables, get rid of the joinaliasvars lists. |
- |
| 1094 |
- |
* They no longer match what expressions in the rest of the tree look |
- |
| 1095 |
- |
* like, because we have not preprocessed expressions in those lists (and |
- |
| 1096 |
- |
* do not want to; for example, expanding a SubLink there would result in |
- |
| 1097 |
- |
* a useless unreferenced subplan). Leaving them in place simply creates |
- |
| 1098 |
- |
* a hazard for later scans of the tree. We could try to prevent that by |
- |
| 1099 |
- |
* using QTW_IGNORE_JOINALIASES in every tree scan done after this point, |
- |
| 1100 |
- |
* but that doesn't sound very reliable. |
- |
| 1101 |
- |
*/ |
- |
| 1102 |
- |
if (root->hasJoinRTEs) |
- |
| 1103 |
- |
{ |
- |
| 1104 |
- |
foreach(l, parse->rtable) |
- |
| 1105 |
- |
{ |
- |
| 1106 |
- |
RangeTblEntry *rte = lfirst_node(RangeTblEntry, l); |
- |
| 1107 |
- |
|
- |
| 1108 |
- |
rte->joinaliasvars = NIL; |
- |
| 1109 |
- |
} |
- |
| 1110 |
- |
} |
- |
| 1111 |
- |
|
- |
| 1112 |
- |
/* |
- |
| 1113 |
- |
* Replace any Vars in the subquery's targetlist and havingQual that |
- |
| 1114 |
- |
* reference GROUP outputs with the underlying grouping expressions. |
- |
| 1115 |
- |
* |
- |
| 1116 |
- |
* Note that we need to perform this replacement after we've preprocessed |
- |
| 1117 |
- |
* the grouping expressions. This is to ensure that there is only one |
- |
| 1118 |
- |
* instance of SubPlan for each SubLink contained within the grouping |
- |
| 1119 |
- |
* expressions. |
- |
| 1120 |
- |
*/ |
- |
| 1121 |
- |
if (parse->hasGroupRTE) |
- |
| 1122 |
- |
{ |
- |
| 1123 |
- |
parse->targetList = (List *) |
- |
| 1124 |
- |
flatten_group_exprs(root, root->parse, (Node *) parse->targetList); |
- |
| 1125 |
- |
parse->havingQual = |
- |
| 1126 |
- |
flatten_group_exprs(root, root->parse, parse->havingQual); |
- |
| 1127 |
- |
} |
- |
| 1128 |
- |
|
- |
| 1129 |
- |
/* Constant-folding might have removed all set-returning functions */ |
- |
| 1130 |
- |
if (parse->hasTargetSRFs) |
- |
| 1131 |
- |
parse->hasTargetSRFs = expression_returns_set((Node *) parse->targetList); |
- |
| 1132 |
- |
|
- |
| 1133 |
- |
/* |
- |
| 1134 |
- |
* If we have grouping sets, expand the groupingSets tree of this query to |
- |
| 1135 |
- |
* a flat list of grouping sets. We need to do this before optimizing |
- |
| 1136 |
- |
* HAVING, since we can't easily tell if there's an empty grouping set |
- |
| 1137 |
- |
* until we have this representation. |
- |
| 1138 |
- |
*/ |
- |
| 1139 |
- |
if (parse->groupingSets) |
- |
| 1140 |
- |
{ |
- |
| 1141 |
- |
parse->groupingSets = |
- |
| 1142 |
- |
expand_grouping_sets(parse->groupingSets, parse->groupDistinct, -1); |
- |
| 1143 |
- |
} |
- |
| 1144 |
- |
|
- |
| 1145 |
- |
/* |
- |
| 1146 |
- |
* In some cases we may want to transfer a HAVING clause into WHERE. We |
- |
| 1147 |
- |
* cannot do so if the HAVING clause contains aggregates (obviously) or |
- |
| 1148 |
- |
* volatile functions (since a HAVING clause is supposed to be executed |
- |
| 1149 |
- |
* only once per group). We also can't do this if there are any grouping |
- |
| 1150 |
- |
* sets and the clause references any columns that are nullable by the |
- |
| 1151 |
- |
* grouping sets; the nulled values of those columns are not available |
- |
| 1152 |
- |
* before the grouping step. (The test on groupClause might seem wrong, |
- |
| 1153 |
- |
* but it's okay: it's just an optimization to avoid running pull_varnos |
- |
| 1154 |
- |
* when there cannot be any Vars in the HAVING clause.) |
- |
| 1155 |
- |
* |
- |
| 1156 |
- |
* Also, it may be that the clause is so expensive to execute that we're |
- |
| 1157 |
- |
* better off doing it only once per group, despite the loss of |
- |
| 1158 |
- |
* selectivity. This is hard to estimate short of doing the entire |
- |
| 1159 |
- |
* planning process twice, so we use a heuristic: clauses containing |
- |
| 1160 |
- |
* subplans are left in HAVING. Otherwise, we move or copy the HAVING |
- |
| 1161 |
- |
* clause into WHERE, in hopes of eliminating tuples before aggregation |
- |
| 1162 |
- |
* instead of after. |
- |
| 1163 |
- |
* |
- |
| 1164 |
- |
* If the query has no empty grouping set then we can simply move such a |
- |
| 1165 |
- |
* clause into WHERE; any group that fails the clause will not be in the |
- |
| 1166 |
- |
* output because none of its tuples will reach the grouping or |
- |
| 1167 |
- |
* aggregation stage. Otherwise we have to keep the clause in HAVING to |
- |
| 1168 |
- |
* ensure that we don't emit a bogus aggregated row. But then the HAVING |
- |
| 1169 |
- |
* clause must be degenerate (variable-free), so we can copy it into WHERE |
- |
| 1170 |
- |
* so that query_planner() can use it in a gating Result node. (This could |
- |
| 1171 |
- |
* be done better, but it seems not worth optimizing.) |
- |
| 1172 |
- |
* |
- |
| 1173 |
- |
* Note that a HAVING clause may contain expressions that are not fully |
- |
| 1174 |
- |
* preprocessed. This can happen if these expressions are part of |
- |
| 1175 |
- |
* grouping items. In such cases, they are replaced with GROUP Vars in |
- |
| 1176 |
- |
* the parser and then replaced back after we're done with expression |
- |
| 1177 |
- |
* preprocessing on havingQual. This is not an issue if the clause |
- |
| 1178 |
- |
* remains in HAVING, because these expressions will be matched to lower |
- |
| 1179 |
- |
* target items in setrefs.c. However, if the clause is moved or copied |
- |
| 1180 |
- |
* into WHERE, we need to ensure that these expressions are fully |
- |
| 1181 |
- |
* preprocessed. |
- |
| 1182 |
- |
* |
- |
| 1183 |
- |
* Note that both havingQual and parse->jointree->quals are in |
- |
| 1184 |
- |
* implicitly-ANDed-list form at this point, even though they are declared |
- |
| 1185 |
- |
* as Node *. |
- |
| 1186 |
- |
*/ |
- |
| 1187 |
- |
newHaving = NIL; |
- |
| 1188 |
- |
foreach(l, (List *) parse->havingQual) |
- |
| 1189 |
- |
{ |
- |
| 1190 |
- |
Node *havingclause = (Node *) lfirst(l); |
- |
| 1191 |
- |
|
- |
| 1192 |
- |
if (contain_agg_clause(havingclause) || |
- |
| 1193 |
- |
contain_volatile_functions(havingclause) || |
- |
| 1194 |
- |
contain_subplans(havingclause) || |
- |
| 1195 |
- |
(parse->groupClause && parse->groupingSets && |
- |
| 1196 |
- |
bms_is_member(root->group_rtindex, pull_varnos(root, havingclause)))) |
- |
| 1197 |
- |
{ |
- |
| 1198 |
- |
/* keep it in HAVING */ |
- |
| 1199 |
- |
newHaving = lappend(newHaving, havingclause); |
- |
| 1200 |
- |
} |
- |
| 1201 |
- |
else if (parse->groupClause && |
- |
| 1202 |
- |
(parse->groupingSets == NIL || |
- |
| 1203 |
- |
(List *) linitial(parse->groupingSets) != NIL)) |
- |
| 1204 |
- |
{ |
- |
| 1205 |
- |
/* There is GROUP BY, but no empty grouping set */ |
- |
| 1206 |
- |
Node *whereclause; |
- |
| 1207 |
- |
|
- |
| 1208 |
- |
/* Preprocess the HAVING clause fully */ |
- |
| 1209 |
- |
whereclause = preprocess_expression(root, havingclause, |
- |
| 1210 |
- |
EXPRKIND_QUAL); |
- |
| 1211 |
- |
/* ... and move it to WHERE */ |
- |
| 1212 |
- |
parse->jointree->quals = (Node *) |
- |
| 1213 |
- |
list_concat((List *) parse->jointree->quals, |
- |
| 1214 |
- |
(List *) whereclause); |
- |
| 1215 |
- |
} |
- |
| 1216 |
- |
else |
- |
| 1217 |
- |
{ |
- |
| 1218 |
- |
/* There is an empty grouping set (perhaps implicitly) */ |
- |
| 1219 |
- |
Node *whereclause; |
- |
| 1220 |
- |
|
- |
| 1221 |
- |
/* Preprocess the HAVING clause fully */ |
- |
| 1222 |
- |
whereclause = preprocess_expression(root, copyObject(havingclause), |
- |
| 1223 |
- |
EXPRKIND_QUAL); |
- |
| 1224 |
- |
/* ... and put a copy in WHERE */ |
- |
| 1225 |
- |
parse->jointree->quals = (Node *) |
- |
| 1226 |
- |
list_concat((List *) parse->jointree->quals, |
- |
| 1227 |
- |
(List *) whereclause); |
- |
| 1228 |
- |
/* ... and also keep it in HAVING */ |
- |
| 1229 |
- |
newHaving = lappend(newHaving, havingclause); |
- |
| 1230 |
- |
} |
- |
| 1231 |
- |
} |
- |
| 1232 |
- |
parse->havingQual = (Node *) newHaving; |
- |
| 1233 |
- |
|
- |
| 1234 |
- |
/* |
- |
| 1235 |
- |
* If we have any outer joins, try to reduce them to plain inner joins. |
- |
| 1236 |
- |
* This step is most easily done after we've done expression |
- |
| 1237 |
- |
* preprocessing. |
- |
| 1238 |
- |
*/ |
- |
| 1239 |
- |
if (hasOuterJoins) |
- |
| 1240 |
- |
reduce_outer_joins(root); |
- |
| 1241 |
- |
|
- |
| 1242 |
- |
/* |
- |
| 1243 |
- |
* If we have any RTE_RESULT relations, see if they can be deleted from |
- |
| 1244 |
- |
* the jointree. We also rely on this processing to flatten single-child |
- |
| 1245 |
- |
* FromExprs underneath outer joins. This step is most effectively done |
- |
| 1246 |
- |
* after we've done expression preprocessing and outer join reduction. |
- |
| 1247 |
- |
*/ |
- |
| 1248 |
- |
if (hasResultRTEs || hasOuterJoins) |
- |
| 1249 |
- |
remove_useless_result_rtes(root); |
- |
| 1250 |
- |
|
- |
| 1251 |
- |
/* |
- |
| 1252 |
- |
* Do the main planning. |
- |
| 1253 |
- |
*/ |
- |
| 1254 |
- |
grouping_planner(root, tuple_fraction, setops); |
- |
| 1255 |
- |
|
- |
| 1256 |
- |
/* |
- |
| 1257 |
- |
* Capture the set of outer-level param IDs we have access to, for use in |
- |
| 1258 |
- |
* extParam/allParam calculations later. |
- |
| 1259 |
- |
*/ |
- |
| 1260 |
- |
SS_identify_outer_params(root); |
- |
| 1261 |
- |
|
- |
| 1262 |
- |
/* |
- |
| 1263 |
- |
* If any initPlans were created in this query level, adjust the surviving |
- |
| 1264 |
- |
* Paths' costs and parallel-safety flags to account for them. The |
- |
| 1265 |
- |
* initPlans won't actually get attached to the plan tree till |
- |
| 1266 |
- |
* create_plan() runs, but we must include their effects now. |
- |
| 1267 |
- |
*/ |
- |
| 1268 |
- |
final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL); |
- |
| 1269 |
- |
SS_charge_for_initplans(root, final_rel); |
- |
| 1270 |
- |
|
- |
| 1271 |
- |
/* |
- |
| 1272 |
- |
* Make sure we've identified the cheapest Path for the final rel. (By |
- |
| 1273 |
- |
* doing this here not in grouping_planner, we include initPlan costs in |
- |
| 1274 |
- |
* the decision, though it's unlikely that will change anything.) |
- |
| 1275 |
- |
*/ |
- |
| 1276 |
- |
set_cheapest(final_rel); |
- |
| 1277 |
- |
|
- |
| 1278 |
- |
return root; |
- |
| 1279 |
- |
} |
- |