← Back to Overview

src/backend/optimizer/plan/planner.c

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