I wrote: > Andres Freund <and...@anarazel.de> writes: >> Tom, do you have an opinion?
> Yes, it's broken. split_pathtarget_at_srfs seems to be doing the right > thing, but then something later is recombining the last two steps. Ah, no, I take that back: split_pathtarget_at_srfs is doing the wrong thing. It's generating the desired list of PathTargets, but it's mistakenly concluding that the last one contains_srfs, which leads to making a ProjectSet plan node for it instead of Result. The problem is specific to targetlists like f(g(x)), g(x) where g() is a SRF and f() can be any sort of non-set-returning expression. split_pathtarget_at_srfs() examines the f() node, sees that it's not a SRF, and calls split_pathtarget_walker which finds the g(x) subexpression and correctly assigns that to the next level down. But then split_pathtarget_at_srfs finds the top-level g(x) occurrence and concludes that this level contains_srfs. Nothing's broken quite yet, but when we get to setrefs.c, it replaces *both* occurrences of g(x) with Vars referencing the g(x) output from the next level down. So now we have the tlist of the upper ProjectSet node as "f(Var), Var" and ProjectSet complains that it has no SRF to evaluate. I think the appropriate fix is that, once split_pathtarget_at_srfs() has computed a tentative list of SRFs it needs to evaluate, it has to make a second pass to see if any of them match expressions that were assigned to the next level down. This is pretty annoying, but we'd only have to do it if target_contains_srfs and context.nextlevel_contains_srfs are both true, which will be a negligibly small fraction of queries in practice. Or we could take out that Assert in nodeProjectSet.c. But that seems like a hack not a fix. I'm pretty tired but I'll work on a fix tomorrow. regards, tom lane -- Sent via pgsql-hackers mailing list (firstname.lastname@example.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers