• R/O
  • HTTP
  • SSH
  • HTTPS

pg_hint_plan: Commit

firtst release


Commit MetaInfo

Révision08e5c94b9dc0cba1febf92c1cd88b0e9b0a126b9 (tree)
l'heure2019-10-29 18:24:38
AuteurKyotaro Horiguchi <horikyota.ntt@gmai...>
CommiterKyotaro Horiguchi

Message de Log

Update core.c based on PG12.0

The following commits changes the original functions in core.c as of
REL_12_0. Took in the changes.

7ad6498fd5a654de6e743814c36cf619a3b5ddb6
45f8eaa8e3031c9cb12deb1b5e294bc052b378f2
f49842d1ee31b976c681322f76025d7732e860f3
7ad6498fd5a654de6e743814c36cf619a3b5ddb6

Change Summary

Modification

--- a/core.c
+++ b/core.c
@@ -861,6 +861,10 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
861861 {
862862 SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(l);
863863
864+ /* ignore full joins --- their ordering is predetermined */
865+ if (sjinfo->jointype == JOIN_FULL)
866+ continue;
867+
864868 if (bms_overlap(sjinfo->min_lefthand, join_plus_rhs) &&
865869 !bms_is_subset(sjinfo->min_righthand, join_plus_rhs))
866870 {
@@ -868,15 +872,6 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
868872 sjinfo->min_righthand);
869873 more = true;
870874 }
871- /* full joins constrain both sides symmetrically */
872- if (sjinfo->jointype == JOIN_FULL &&
873- bms_overlap(sjinfo->min_righthand, join_plus_rhs) &&
874- !bms_is_subset(sjinfo->min_lefthand, join_plus_rhs))
875- {
876- join_plus_rhs = bms_add_members(join_plus_rhs,
877- sjinfo->min_lefthand);
878- more = true;
879- }
880875 }
881876 } while (more);
882877 if (bms_overlap(join_plus_rhs, join_lateral_rels))
@@ -941,52 +936,6 @@ has_join_restriction(PlannerInfo *root, RelOptInfo *rel)
941936 return false;
942937 }
943938
944-
945-/*
946- * Mark a relation as proven empty.
947- *
948- * During GEQO planning, this can get invoked more than once on the same
949- * baserel struct, so it's worth checking to see if the rel is already marked
950- * dummy.
951- *
952- * Also, when called during GEQO join planning, we are in a short-lived
953- * memory context. We must make sure that the dummy path attached to a
954- * baserel survives the GEQO cycle, else the baserel is trashed for future
955- * GEQO cycles. On the other hand, when we are marking a joinrel during GEQO,
956- * we don't want the dummy path to clutter the main planning context. Upshot
957- * is that the best solution is to explicitly make the dummy path in the same
958- * context the given RelOptInfo is in.
959- */
960-void
961-mark_dummy_rel(RelOptInfo *rel)
962-{
963- MemoryContext oldcontext;
964-
965- /* Already marked? */
966- if (is_dummy_rel(rel))
967- return;
968-
969- /* No, so choose correct context to make the dummy path in */
970- oldcontext = MemoryContextSwitchTo(GetMemoryChunkContext(rel));
971-
972- /* Set dummy size estimate */
973- rel->rows = 0;
974-
975- /* Evict any previously chosen paths */
976- rel->pathlist = NIL;
977- rel->partial_pathlist = NIL;
978-
979- /* Set up the dummy path */
980- add_path(rel, (Path *) create_append_path(NULL, rel, NIL, NIL, NULL,
981- 0, false, NIL, -1));
982-
983- /* Set or update cheapest_total_path and related fields */
984- set_cheapest(rel);
985-
986- MemoryContextSwitchTo(oldcontext);
987-}
988-
989-
990939 /*
991940 * restriction_is_constant_false --- is a restrictlist just FALSE?
992941 *
@@ -1033,29 +982,6 @@ restriction_is_constant_false(List *restrictlist,
1033982 return false;
1034983 }
1035984
1036-
1037-/*
1038- * Set up tlist expressions for the childrel, and add EC members referencing
1039- * the childrel.
1040- */
1041-static void
1042-update_child_rel_info(PlannerInfo *root,
1043- RelOptInfo *rel, RelOptInfo *childrel)
1044-{
1045- AppendRelInfo *appinfo = root->append_rel_array[childrel->relid];
1046-
1047- /* Make child tlist expressions */
1048- childrel->reltarget->exprs = (List *)
1049- adjust_appendrel_attrs(root,
1050- (Node *) rel->reltarget->exprs,
1051- 1, &appinfo);
1052-
1053- /* Make child entries in the EquivalenceClass as well */
1054- if (rel->has_eclass_joins || has_useful_pathkeys(root, rel))
1055- add_child_rel_equivalences(root, appinfo, rel, childrel);
1056- childrel->has_eclass_joins = rel->has_eclass_joins;
1057-}
1058-
1059985 /*
1060986 * Construct the SpecialJoinInfo for a child-join by translating
1061987 * SpecialJoinInfo for the join between parents. left_relids and right_relids
@@ -1182,6 +1108,10 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
11821108 {
11831109 RelOptInfo *child_rel1 = rel1->part_rels[cnt_parts];
11841110 RelOptInfo *child_rel2 = rel2->part_rels[cnt_parts];
1111+ bool rel1_empty = (child_rel1 == NULL ||
1112+ IS_DUMMY_REL(child_rel1));
1113+ bool rel2_empty = (child_rel2 == NULL ||
1114+ IS_DUMMY_REL(child_rel2));
11851115 SpecialJoinInfo *child_sjinfo;
11861116 List *child_restrictlist;
11871117 RelOptInfo *child_joinrel;
@@ -1190,24 +1120,69 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
11901120 int nappinfos;
11911121
11921122 /*
1193- * If a child table has consider_partitionwise_join=false, it means
1123+ * Check for cases where we can prove that this segment of the join
1124+ * returns no rows, due to one or both inputs being empty (including
1125+ * inputs that have been pruned away entirely). If so just ignore it.
1126+ * These rules are equivalent to populate_joinrel_with_paths's rules
1127+ * for dummy input relations.
1128+ */
1129+ switch (parent_sjinfo->jointype)
1130+ {
1131+ case JOIN_INNER:
1132+ case JOIN_SEMI:
1133+ if (rel1_empty || rel2_empty)
1134+ continue; /* ignore this join segment */
1135+ break;
1136+ case JOIN_LEFT:
1137+ case JOIN_ANTI:
1138+ if (rel1_empty)
1139+ continue; /* ignore this join segment */
1140+ break;
1141+ case JOIN_FULL:
1142+ if (rel1_empty && rel2_empty)
1143+ continue; /* ignore this join segment */
1144+ break;
1145+ default:
1146+ /* other values not expected here */
1147+ elog(ERROR, "unrecognized join type: %d",
1148+ (int) parent_sjinfo->jointype);
1149+ break;
1150+ }
1151+
1152+ /*
1153+ * If a child has been pruned entirely then we can't generate paths
1154+ * for it, so we have to reject partitionwise joining unless we were
1155+ * able to eliminate this partition above.
1156+ */
1157+ if (child_rel1 == NULL || child_rel2 == NULL)
1158+ {
1159+ /*
1160+ * Mark the joinrel as unpartitioned so that later functions treat
1161+ * it correctly.
1162+ */
1163+ joinrel->nparts = 0;
1164+ return;
1165+ }
1166+
1167+ /*
1168+ * If a leaf relation has consider_partitionwise_join=false, it means
11941169 * that it's a dummy relation for which we skipped setting up tlist
1195- * expressions and adding EC members in set_append_rel_size(), so do
1196- * that now for use later.
1170+ * expressions and adding EC members in set_append_rel_size(), so
1171+ * again we have to fail here.
11971172 */
11981173 if (rel1_is_simple && !child_rel1->consider_partitionwise_join)
11991174 {
12001175 Assert(child_rel1->reloptkind == RELOPT_OTHER_MEMBER_REL);
12011176 Assert(IS_DUMMY_REL(child_rel1));
1202- update_child_rel_info(root, rel1, child_rel1);
1203- child_rel1->consider_partitionwise_join = true;
1177+ joinrel->nparts = 0;
1178+ return;
12041179 }
12051180 if (rel2_is_simple && !child_rel2->consider_partitionwise_join)
12061181 {
12071182 Assert(child_rel2->reloptkind == RELOPT_OTHER_MEMBER_REL);
12081183 Assert(IS_DUMMY_REL(child_rel2));
1209- update_child_rel_info(root, rel2, child_rel2);
1210- child_rel2->consider_partitionwise_join = true;
1184+ joinrel->nparts = 0;
1185+ return;
12111186 }
12121187
12131188 /* We should never try to join two overlapping sets of rels. */
Afficher sur ancien navigateur de dépôt.