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

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 (pgsql-hackers@postgresql.org)
To make changes to your subscription:

Reply via email to