* convert_subquery_pathkeys * Build a pathkeys list that describes the ordering of a subquery's * result, in the terms of the outer query. This is essentially a * task of conversion. * * 'rel': outer query's RelOptInfo for the subquery relation. * 'subquery_pathkeys': the subquery's output pathkeys, in its terms. * 'subquery_tlist': the subquery's output targetlist, in its terms. *
| 1164 | * right_merge_direction heuristic would have us throw the knowledge away. |
| 1165 | */ |
| 1166 | List * |
| 1167 | convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel, |
| 1168 | List *subquery_pathkeys, |
| 1169 | List *subquery_tlist) |
| 1170 | { |
| 1171 | List *retval = NIL; |
| 1172 | int retvallen = 0; |
| 1173 | int outer_query_keys = list_length(root->query_pathkeys); |
| 1174 | ListCell *i; |
| 1175 | |
| 1176 | foreach(i, subquery_pathkeys) |
| 1177 | { |
| 1178 | PathKey *sub_pathkey = (PathKey *) lfirst(i); |
| 1179 | EquivalenceClass *sub_eclass = sub_pathkey->pk_eclass; |
| 1180 | PathKey *best_pathkey = NULL; |
| 1181 | |
| 1182 | if (sub_eclass->ec_has_volatile) |
| 1183 | { |
| 1184 | /* |
| 1185 | * If the sub_pathkey's EquivalenceClass is volatile, then it must |
| 1186 | * have come from an ORDER BY clause, and we have to match it to |
| 1187 | * that same targetlist entry. |
| 1188 | */ |
| 1189 | TargetEntry *tle; |
| 1190 | Var *outer_var; |
| 1191 | |
| 1192 | if (sub_eclass->ec_sortref == 0) /* can't happen */ |
| 1193 | elog(ERROR, "volatile EquivalenceClass has no sortref"); |
| 1194 | tle = get_sortgroupref_tle(sub_eclass->ec_sortref, subquery_tlist); |
| 1195 | Assert(tle); |
| 1196 | /* Is TLE actually available to the outer query? */ |
| 1197 | outer_var = find_var_for_subquery_tle(rel, tle); |
| 1198 | if (outer_var) |
| 1199 | { |
| 1200 | /* We can represent this sub_pathkey */ |
| 1201 | EquivalenceMember *sub_member; |
| 1202 | EquivalenceClass *outer_ec; |
| 1203 | |
| 1204 | Assert(list_length(sub_eclass->ec_members) == 1); |
| 1205 | sub_member = (EquivalenceMember *) linitial(sub_eclass->ec_members); |
| 1206 | |
| 1207 | /* |
| 1208 | * Note: it might look funny to be setting sortref = 0 for a |
| 1209 | * reference to a volatile sub_eclass. However, the |
| 1210 | * expression is *not* volatile in the outer query: it's just |
| 1211 | * a Var referencing whatever the subquery emitted. (IOW, the |
| 1212 | * outer query isn't going to re-execute the volatile |
| 1213 | * expression itself.) So this is okay. Likewise, it's |
| 1214 | * correct to pass nullable_relids = NULL, because we're |
| 1215 | * underneath any outer joins appearing in the outer query. |
| 1216 | */ |
| 1217 | outer_ec = |
| 1218 | get_eclass_for_sort_expr(root, |
| 1219 | (Expr *) outer_var, |
| 1220 | NULL, |
| 1221 | sub_eclass->ec_opfamilies, |
| 1222 | sub_member->em_datatype, |
| 1223 | sub_eclass->ec_collation, |
no test coverage detected