* cdbpullup_findEclassInTargetList * * Searches the given equivalence class for a member that uses no rels * outside the 'relids' set, and either is a member of 'targetlist', or * uses no Vars that are not in 'targetlist'. Furthermore, if * 'hashOpFamily' is valid, the member must be hashable using that hash * operator family. * * If found, returns the chosen member's expression, otherwise
| 240 | * targetlist expr.) |
| 241 | */ |
| 242 | Expr * |
| 243 | cdbpullup_findEclassInTargetList(EquivalenceClass *eclass, List *targetlist, |
| 244 | Oid hashOpFamily, bool *relabel_stripped) |
| 245 | { |
| 246 | ListCell *lc; |
| 247 | |
| 248 | foreach(lc, eclass->ec_members) |
| 249 | { |
| 250 | EquivalenceMember *em = (EquivalenceMember *) lfirst(lc); |
| 251 | Expr *key = (Expr *) em->em_expr; |
| 252 | ListCell *lc_tle; |
| 253 | |
| 254 | if (OidIsValid(hashOpFamily) && |
| 255 | !get_opfamily_member(hashOpFamily, em->em_datatype, em->em_datatype, |
| 256 | HTEqualStrategyNumber)) |
| 257 | continue; |
| 258 | |
| 259 | /* A constant is OK regardless of the target list */ |
| 260 | if (em->em_is_const) |
| 261 | return key; |
| 262 | |
| 263 | /*------- |
| 264 | * Try to find this EC member in the target list. |
| 265 | * |
| 266 | * We do the search in a very lenient way: |
| 267 | * |
| 268 | * 1. Ignore RelabelType nodes on top of both sides, like |
| 269 | * tlist_member_ignore_relabel() does. |
| 270 | * 2. Ignore varnoold/varoattno fields in Var nodes, like |
| 271 | * tlist_member_match_var() does. |
| 272 | * 3. Also Accept "naked" targetlists, without TargetEntry nodes |
| 273 | * |
| 274 | * Unfortunately, neither tlist_member_ignore_relabel() nor |
| 275 | * tlist_member_match_var() does exactly what we need. |
| 276 | *------- |
| 277 | */ |
| 278 | while (IsA(key, RelabelType)) |
| 279 | { |
| 280 | key = (Expr *) ((RelabelType *) key)->arg; |
| 281 | if(relabel_stripped && (!*relabel_stripped)) |
| 282 | *relabel_stripped = true; |
| 283 | } |
| 284 | |
| 285 | foreach(lc_tle, targetlist) |
| 286 | { |
| 287 | Node *tlexpr = lfirst(lc_tle); |
| 288 | Node *naked_tlexpr; |
| 289 | |
| 290 | /* |
| 291 | * Check if targetlist is a List of TargetEntry. (Planner's |
| 292 | * RelOptInfo targetlists don't have TargetEntry nodes.) |
| 293 | */ |
| 294 | if (IsA(tlexpr, TargetEntry)) |
| 295 | tlexpr = (Node *) ((TargetEntry *) tlexpr)->expr; |
| 296 | |
| 297 | /* ignore RelabelType nodes on both sides */ |
| 298 | naked_tlexpr = tlexpr; |
| 299 | while (naked_tlexpr && IsA(naked_tlexpr, RelabelType)) |
no test coverage detected