I've just looked over the v4 patch. I agree that having an RTE for a from-less SELECT seems like a good idea.
While reading the patch, I noted the following: 1. It's more efficient to use bms_next_member as it does not need to re-skip 0 words on each iteration. (Likely bms_first_member() is not needed anywhere in the code base) int varno; while ((varno = bms_first_member(result_relids)) >= 0) remove_result_refs(root, varno, (Node *) f); can also make the loop condition > 0, rather than >= 0 to save the final futile attempt at finding a value that'll never be there. 2. The following comment seems to indicate that we can go ahead and make parallelise the result processing, but the code still defers to the checks below and may still end up not parallelising if say, there's a non-parallel safe function call in the SELECT's target list. case RTE_RESULT: /* Sure, execute it in a worker if you want. */ break; 3. You may as well just ditch the variable and just do: Assert(rel->relid > 0); Assert(planner_rt_fetch(rel->relid, root)->rtekind == RTE_RESULT); instead of: RangeTblEntry *rte PG_USED_FOR_ASSERTS_ONLY; /* Should only be applied to RTE_RESULT base relations */ Assert(rel->relid > 0); rte = planner_rt_fetch(rel->relid, root); Assert(rte->rtekind == RTE_RESULT); There are a few other cases doing just that in costsize.c 4. I don't quite understand why this changed in join.out @@ -3596,7 +3588,7 @@ select t1.* from > Hash Right Join Output: i8.q2 Hash Cond: ((NULL::integer) = i8b1.q2) - -> Hash Left Join + -> Hash Join Can you explain why that's valid? I understand this normally occurs when a qual exists which would filter out the NULL rows produced by the join, but I don't see that in this case. -- David Rowley http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Training & Services