On Tue, Mar 4, 2014 at 4:06 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Joel Jacobson <joel@trustly.com> writes:
>> On Tue, Mar 4, 2014 at 12:55 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>>> You're reasoning from a false premise: it's *not* necessarily an error.
>
>> Isn't this almost exactly the same situation as we had in 9.0?
>> "PL/pgSQL now throws an error if a variable name conflicts with a
>> column name used in a query (Tom Lane)"
>
> No; the reason why the old behavior was problematic was precisely that
> it failed to conform to normal block-structured language design rules
> (namely that the most closely nested definition should win). If it
> had been like that to start with we'd probably have just left it that
> way. The complexity of behavior that you see there today is there to
> help people with debugging issues created by that change of behavior.
>
> While I don't necessarily have an objection to creating a way to help
> debug variable-name-shadowing issues, the idea that they're broken and
> we can just start throwing errors is *wrong*. The whole point of block
> structure in a language is that a block of code can be understood
> independently of what surrounds it.
I agree it should be possible to reuse a variable in a new block,
but I think the IN/OUT variable should be considered to be at the
*same* block-level
as the first block of code, thus an error should be thrown.
Consider the same scenario in for instance Perl:
# Example 1
# Prints "1" and doesn't throw an error, which is perfectly OK.
use warnings;
my $foo = 1;
{ my $foo = 2;
}
print $foo;
# Example 2
# "my" variable $foo masks earlier declaration in same scope at
warn_shadow.pl line 3.
use warnings;
my $foo = 1;
my $foo = 2;
print $foo;
Or maybe this is a better example, since we are talking about functions:
# Example 3
# "my" variable $bar masks earlier declaration in same scope at
warn_shadow.pl line 7.
use warnings;
sub foo
{ # IN-variables: my ($bar) = @_; # DECLARE: my $bar; # BEGIN: $bar = 1; return $bar;
}
foo(2);
I understand that from a technical perspective, the mandatory
BEGIN...END you always need in a PL/pgSQL function, is a new block,
and the variables declared are perhaps technically in a new block, at
a deeper level than the IN/OUT variables. But I would still argue the
expected behaviour of PL/pgSQL for a new user would be to consider the
IN/OUT variables to be in the same block as the variables declared in
the function's first block.