📄 predmig.c
字号:
{ Stream temp, parent; int lowest = xfunc_num_relids((Stream) xfunc_get_upjoin(bottom)); bool progress; LispValue primjoin; int whichchild; if (!lowest) return; /* no joins in stream, so no groups */ /* initialize groups to be single nodes */ for (temp = root; temp != (Stream) NULL && temp != bottom; temp = (Stream) get_downstream(temp)) { /* if a Join node */ if (!is_clause(temp)) { if (get_pathptr((Stream) get_downstream(temp)) == (pathPtr) get_outerjoinpath((JoinPath) get_pathptr(temp))) whichchild = OUTER; else whichchild = INNER; set_groupcost(temp, xfunc_join_expense((JoinPath) get_pathptr(temp), whichchild)); if (primjoin = xfunc_primary_join((JoinPath) get_pathptr(temp))) { set_groupsel(temp, compute_clause_selec(queryInfo, primjoin, NIL)); } else set_groupsel(temp, 1.0); } else/* a restriction, or 2-ary join pred */ { set_groupcost(temp, xfunc_expense(queryInfo, get_clause(get_cinfo(temp)))); set_groupsel(temp, compute_clause_selec(queryInfo, get_clause(get_cinfo(temp)), NIL)); } set_groupup(temp, false); } /* make passes upwards, forming groups */ do { progress = false; for (temp = (Stream) get_upstream(bottom); temp != (Stream) NULL; temp = (Stream) get_upstream(temp)) { /* check for grouping with node upstream */ if (!get_groupup(temp) && /* not already grouped */ (parent = (Stream) get_upstream(temp)) != (Stream) NULL && /* temp is a join or temp is the top of a group */ (is_join((Path) get_pathptr(temp)) || get_downstream(temp) && get_groupup((Stream) get_downstream(temp))) && get_grouprank(parent) < get_grouprank(temp)) { progress = true;/* we formed a new group */ set_groupup(temp, true); set_groupcost(temp, get_groupcost(temp) + get_groupsel(temp) * get_groupcost(parent)); set_groupsel(temp, get_groupsel(temp) * get_groupsel(parent)); /* fix costs and sels of all members of group */ xfunc_setup_group(temp, bottom); } } } while (progress);}/* ------------------- UTILITY FUNCTIONS ------------------------- *//* ** xfunc_free_stream ** walk down a stream and pfree it */static voidxfunc_free_stream(Stream root){ Stream cur, next; Assert(xfunc_check_stream(root)); if (root != (Stream) NULL) for (cur = root; cur != (Stream) NULL; cur = next) { next = (Stream) get_downstream(cur); pfree(cur); }}/* ** xfunc_add<_clauses ** find any clauses above current, and insert them into stream as ** appropriate. Return uppermost clause inserted, or current if none. */static Streamxfunc_add_clauses(Stream current){ Stream topnode = current; LispValue temp; LispValue primjoin; /* first add in the local clauses */ foreach(temp, get_loc_restrictinfo((Path) get_pathptr(current))) { topnode = xfunc_streaminsert((RestrictInfo) lfirst(temp), topnode, XFUNC_LOCPRD); } /* and add in the join clauses */ if (IsA(get_pathptr(current), JoinPath)) { primjoin = xfunc_primary_join((JoinPath) get_pathptr(current)); foreach(temp, get_pathrestrictinfo((JoinPath) get_pathptr(current))) { if (!equal(get_clause((RestrictInfo) lfirst(temp)), primjoin)) topnode = xfunc_streaminsert((RestrictInfo) lfirst(temp), topnode, XFUNC_JOINPRD); } } return topnode;}/* ** xfunc_setup_group ** find all elements of stream that are grouped with node and are above ** bottom, and set their groupcost and groupsel to be the same as node's. */static voidxfunc_setup_group(Stream node, Stream bottom){ Stream temp; if (node != bottom) /* traverse downwards */ for (temp = (Stream) get_downstream(node); temp != (Stream) NULL && temp != bottom; temp = (Stream) get_downstream(temp)) { if (!get_groupup(temp)) break; else { set_groupcost(temp, get_groupcost(node)); set_groupsel(temp, get_groupsel(node)); } } /* traverse upwards */ for (temp = (Stream) get_upstream(node); temp != (Stream) NULL; temp = (Stream) get_upstream(temp)) { if (!get_groupup((Stream) get_downstream(temp))) break; else { set_groupcost(temp, get_groupcost(node)); set_groupsel(temp, get_groupsel(node)); } }}/* ** xfunc_streaminsert ** Make a new Stream node to hold clause, and insert it above current. ** Return new node. */static Streamxfunc_streaminsert(RestrictInfo restrictinfo, Stream current, int clausetype) /* XFUNC_LOCPRD or XFUNC_JOINPRD */{ Stream newstream = RMakeStream(); set_upstream(newstream, get_upstream(current)); if (get_upstream(current)) set_downstream((Stream) (get_upstream(current)), (StreamPtr) newstream); set_upstream(current, (StreamPtr) newstream); set_downstream(newstream, (StreamPtr) current); set_pathptr(newstream, get_pathptr(current)); set_cinfo(newstream, restrictinfo); set_clausetype(newstream, clausetype); return newstream;}/* ** Given a Stream node, find the number of relids referenced in the pathnode ** associated with the stream node. The number of relids gives a unique ** ordering on the joins in a stream, which we use to compare the height of ** join nodes. */static intxfunc_num_relids(Stream node){ if (!node || !IsA(get_pathptr(node), JoinPath)) return 0; else return (length (get_relids(get_parent((JoinPath) get_pathptr(node)))));}/* ** xfunc_get_downjoin ** Given a stream node, find the next lowest node which points to a ** join predicate or a scan node. */static StreamPtrxfunc_get_downjoin(Stream node){ Stream temp; if (!is_clause(node)) /* if this is a join */ node = (Stream) get_downstream(node); for (temp = node; temp && is_clause(temp); temp = (Stream) get_downstream(temp)) /* empty body in for loop */ ; return (StreamPtr) temp;}/* ** xfunc_get_upjoin ** same as above, but upwards. */static StreamPtrxfunc_get_upjoin(Stream node){ Stream temp; if (!is_clause(node)) /* if this is a join */ node = (Stream) get_upstream(node); for (temp = node; temp && is_clause(temp); temp = (Stream) get_upstream(temp)) /* empty body in for loop */ ; return (StreamPtr) temp;}/* ** xfunc_stream_qsort ** Given a stream, sort by group rank the elements in the stream from the ** node "bottom" up. DESTRUCTIVELY MODIFIES STREAM! Returns new root. */static Streamxfunc_stream_qsort(Stream root, Stream bottom){ int i; size_t num; Stream *nodearray, output; Stream tmp; /* find size of list */ for (num = 0, tmp = root; tmp != bottom; tmp = (Stream) get_downstream(tmp)) num++; if (num <= 1) return root; /* copy elements of the list into an array */ nodearray = (Stream *) palloc(num * sizeof(Stream)); for (tmp = root, i = 0; tmp != bottom; tmp = (Stream) get_downstream(tmp), i++) nodearray[i] = tmp; /* sort the array */ qsort(nodearray, num, sizeof(LispValue), xfunc_stream_compare); /* paste together the array elements */ output = nodearray[num - 1]; set_upstream(output, (StreamPtr) NULL); for (i = num - 2; i >= 0; i--) { set_downstream(nodearray[i + 1], (StreamPtr) nodearray[i]); set_upstream(nodearray[i], (StreamPtr) nodearray[i + 1]); } set_downstream(nodearray[0], (StreamPtr) bottom); if (bottom) set_upstream(bottom, (StreamPtr) nodearray[0]); Assert(xfunc_check_stream(output)); return output;}/* ** xfunc_stream_compare ** comparison function for xfunc_stream_qsort. ** Compare nodes by group rank. If group ranks are equal, ensure that ** join nodes appear in same order as in plan tree. */static intxfunc_stream_compare(void *arg1, void *arg2){ Stream stream1 = *(Stream *) arg1; Stream stream2 = *(Stream *) arg2; Cost rank1, rank2; rank1 = get_grouprank(stream1); rank2 = get_grouprank(stream2); if (rank1 > rank2) return 1; else if (rank1 < rank2) return -1; else { if (is_clause(stream1) && is_clause(stream2)) return 0; /* doesn't matter what order if both are * restrictions */ else if (!is_clause(stream1) && !is_clause(stream2)) { if (xfunc_num_relids(stream1) < xfunc_num_relids(stream2)) return -1; else return 1; } else if (is_clause(stream1) && !is_clause(stream2)) { if (xfunc_num_relids(stream1) == xfunc_num_relids(stream2)) /* stream1 is a restriction over stream2 */ return 1; else return -1; } else if (!is_clause(stream1) && is_clause(stream2)) { /* stream2 is a restriction over stream1: never push down */ return -1; } }}/* ------------------ DEBUGGING ROUTINES ---------------------------- *//* ** Make sure all pointers in stream make sense. Make sure no joins are ** out of order. */static boolxfunc_check_stream(Stream node){ Stream temp; int numrelids, tmp; /* set numrelids higher than max */ if (!is_clause(node)) numrelids = xfunc_num_relids(node) + 1; else if (xfunc_get_downjoin(node)) numrelids = xfunc_num_relids((Stream) xfunc_get_downjoin(node)) + 1; else numrelids = 1; for (temp = node; get_downstream(temp); temp = (Stream) get_downstream(temp)) { if ((Stream) get_upstream((Stream) get_downstream(temp)) != temp) { elog(ERROR, "bad pointers in stream"); return false; } if (!is_clause(temp)) { if ((tmp = xfunc_num_relids(temp)) >= numrelids) { elog(ERROR, "Joins got reordered!"); return false; } numrelids = tmp; } } return true;}/* ** xfunc_in_stream ** check if node is in stream */static boolxfunc_in_stream(Stream node, Stream stream){ Stream temp; for (temp = stream; temp; temp = (Stream) get_downstream(temp)) if (temp == node) return 1; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -