W dniu 04.10.2013 00:28, Robert Haas pisze:
> I wonder if we shouldn't be trying to handle resolution of these names
> at an earlier processing stage, closer to the processor.
Maybe it can be done in parser (in flex?) but at now it seems to be more
isolated feature.
> In fact, we can already get approximately the
> desired effect already:
>
> rhaas=# update foo as after set a = before.a + 1 from foo as before
> where before.a = after.a returning before.a, after.a;
> a | a
> ---+---
> 1 | 2
> (1 row)
Compare EXPLAIN ANALYZE VERBOSE on your statement and on "patched"
workflow. I can see significant difference. And your "after" returns the
value after whole the work (after trigger fired) as I know (I don't know
if it is needed or not, I only point at the difference).
> Now this is a hack, because we don't really want to add an extra
> scan/join just to get the behavior we want. But it seems to me
> significant that this processing makes Vars that refer to the target
> table refer to the new values, and if we got rid of it, they'd refer
> to the old values. Can't we contrive to make AFTER.x parse into the
> same Var node that x currently does? Then we don't need an RTE for
> it. And maybe BEFORE.x ought to parse to the same node that just
> plain x does but with some marking, or some other node wrapped around
> it (like a TargetEntry with some flag set?) that suppresses this
> processing. I'm just shooting from the hip here; that might be wrong
> in detail, or even in broad strokes, but it just looks to me like the
> additional RTE kind is going to bleed into a lot of places.
While planning/analyzing the problem there were many ideas about hot to
solve it. I was trying to avoid adding new RTE and referencing to "core"
table. However it makes more and more issues. You can see some PoC on
the
https://github.com/davidfetter/postgresql_projects/compare/returning_before_after
(other ideas I revert w/o commit because I couldn't get expected
result). The other major reason was that we can avoid touching executor
and/or parser's core (flex) this way. One observation: why shouldn't we
use the values computed at the moment (it would be computed again if we
want to do it later, in executor)?
I think we can do it by modify the Var structure (add some kind of flag
while generating the vars in parser?) but I'm not sure if it is good
idea. The major issue is to know if the Var/TargetEntry references to
the real alias "BEFORE" (named with "AS" syntax or even the real
table-name - I can see there is no difference in code) or the virtual
(from feature patch) "BEFORE". Doing it in parser (more "low-level")
would be very awful - we'd need to check in which part of statement
BEFORE/AFTER is placed (it is not allowed to use it in the other places
than in "RETURNING"). We don't want to make "BEFORE" and "AFTER"
restricted keywords.
Now most of the code means "don't touch these because they are not real" :)
If anyone has the fresh idea to it better, please write it by mail, I
don't have more ideas how to solve it.
> This patch also has significant style issues.
I'll try to fix it soon.
Regards,
Karol Trzcionka