Thread: pl/pgsql: END verbosity

pl/pgsql: END verbosity

From
Neil Conway
Date:
In PL/PgSQL, "END LOOP" is used to terminate loop blocks, and "END IF" 
is used to terminate IF blocks. This is needlessly verbose: we could 
simply accept "END" in both cases without syntactic ambiguity. I'd like 
to make this change, so that END can be used to terminate any kind of 
block. There's no need to remove support for the present syntax, of 
course, so there's no backward compatibility concern. Oracle's PL/SQL 
does require "END IF" and "END LOOP", but folks interested in maximum 
compatibility can always use those forms if they like.

Any objections?

-Neil


Re: pl/pgsql: END verbosity

From
Josh Berkus
Date:
Neil,

> In PL/PgSQL, "END LOOP" is used to terminate loop blocks, and "END IF"
> is used to terminate IF blocks. This is needlessly verbose: we could
> simply accept "END" in both cases without syntactic ambiguity. I'd like
> to make this change, so that END can be used to terminate any kind of
> block. There's no need to remove support for the present syntax, of
> course, so there's no backward compatibility concern. Oracle's PL/SQL
> does require "END IF" and "END LOOP", but folks interested in maximum
> compatibility can always use those forms if they like.

No problem from me.   Since the parser checks for block closure for all 
block types, I can't see how this would be a problem.

-- 
--Josh

Josh Berkus
Aglio Database Solutions
San Francisco


Re: pl/pgsql: END verbosity

From
"Andrew Dunstan"
Date:
Neil Conway said:
> In PL/PgSQL, "END LOOP" is used to terminate loop blocks, and "END IF"
> is used to terminate IF blocks. This is needlessly verbose: we could
> simply accept "END" in both cases without syntactic ambiguity. I'd like
>  to make this change, so that END can be used to terminate any kind of
> block. There's no need to remove support for the present syntax, of
> course, so there's no backward compatibility concern. Oracle's PL/SQL
> does require "END IF" and "END LOOP", but folks interested in maximum
> compatibility can always use those forms if they like.
>
> Any objections?
>

I'm unkeen. I see no technical advantage - it's just a matter of taste. We
advertise that plpgsql is similar to plsql - we should not do anything to
make that less so IMNSHO. Terseness is not always good, redundancy is not
always bad.

cheers

andrew




Re: pl/pgsql: END verbosity

From
Tom Lane
Date:
"Andrew Dunstan" <andrew@dunslane.net> writes:
> Neil Conway said:
>> Any objections?

> I'm unkeen. I see no technical advantage - it's just a matter of taste. We
> advertise that plpgsql is similar to plsql - we should not do anything to
> make that less so IMNSHO. Terseness is not always good, redundancy is not
> always bad.

That was my reaction too, though I'm too tired at this hour to phrase it
so well ;-).  The long-term point in my mind is that removing
syntactical redundancy always reduces the ability to detect errors or
report errors acccurately; and it may limit our freedom to introduce
new features later.  Consider for example the possibility that Oracle's
next release adds some new frammish that can't be duplicated because we
chose not to distinguish various forms of "END xxx" ...
        regards, tom lane


Re: pl/pgsql: END verbosity

From
Neil Conway
Date:
Andrew Dunstan wrote:
> I'm unkeen. I see no technical advantage - it's just a matter of taste.

There is no "technical advantage" to case insensitive keywords, or 
dollar quoting, or a variety of other programming language features that 
don't change functionality but exist to make using the programming 
language easier.

> We advertise that plpgsql is similar to plsql - we should not do
> anything to make that less so IMNSHO.

Do you *really* mean that? This principle would mean we should reject 
patches like the CONTINUE statement patch I just applied, for example, 
as PL/SQL has no such construct.

In any case, I think you are overestimating the value of strict PL/SQL 
compatibility. IMHO, PL/PgSQL should be a useful procedural programming 
language first, and a reimplementation of PL/SQL second. We should 
provide an equivalent feature (not necessarily with the same syntax) for 
all of PL/SQL's useful features, but I don't see the value in copying 
Oracle when PL/SQL's implementation of a feature is ugly, broken, or 
inconsistent with the rest of Postgres. It's not as if complete 
source-level compatibility with PL/SQL has been a goal for PL/PgSQL 
anyway (and besides, there are other people, like EnterpriseDB, who can 
provide that for those who need it).

> Terseness is not always good, redundancy is not always bad.

Granted -- but why is redundancy a good thing here?

-Neil


Re: pl/pgsql: END verbosity

From
Neil Conway
Date:
Tom Lane wrote:
> The long-term point in my mind is that removing syntactical
> redundancy always reduces the ability to detect errors or report
> errors acccurately

Lexical scoping is unambiguous in a language like PL/PgSQL. Since it is 
simple to determine whether a given END matches an IF, LOOP, or BEGIN, I 
don't see how it would reduce our "ability to detect errors or report 
errors accurately".

> Consider for example the possibility that Oracle's next release adds
> some new frammish that can't be duplicated because we chose not to
> distinguish various forms of "END xxx" ...

As lexical scoping is still unambiguous, we could actually add a K_LOOP 
/ K_IF token to the input stream, if that would make you happier :) (Of 
course I'm not suggesting this -- the point is that as far as the parser 
is concerned, we should have precisely the same information for 
disambiguating the input as we used to have.)

BTW, I notice that Oracle actually allows:

<<label>>
LOOP    -- ...
END LOOP label;

whereas we don't allow the optional label following END LOOP. Which goes 
to my general point: this frammish has existed in PL/SQL for a while, 
but it's not as if people are clamoring for us to implement it. I would 
wager that most people care about having *equivalent* features to 
PL/SQL, not exactly identical syntax. For example, the lack of 
autonomous transactions is something people have asked for in the past, 
because it *does* make porting PL/SQL applications more difficult. I 
can't see anyone losing any sleep because we are slightly more relaxed 
about the input we accept.

-Neil


Re: pl/pgsql: END verbosity

From
"Andrew Dunstan"
Date:
Neil Conway said:
> Andrew Dunstan wrote:
>> I'm unkeen. I see no technical advantage - it's just a matter of
>> taste.
>
> There is no "technical advantage" to case insensitive keywords, or
> dollar quoting, or a variety of other programming language features
> that  don't change functionality but exist to make using the
> programming  language easier.
>


But this doesn't make it easier to use - users don't just include those who
write it. The antecedent language of these, Ada, from which this syntax
comes, was explicitly designed to be reader-friendly as opposed to
writer-friendly, and this is a part of that. I can tell you from experience
of programming Ada a long time ago that I have been profoundly grateful that
this was required in the language when disentangling a badly written 1000+
line long multibranch IF statement. And I still find myself having to hunt
for what sort of block a } is closing in C, and I still find it annoying.

>> We advertise that plpgsql is similar to plsql - we should not do
>> anything to make that less so IMNSHO.
>
> Do you *really* mean that? This principle would mean we should reject
> patches like the CONTINUE statement patch I just applied, for example,
> as PL/SQL has no such construct.
>

Well, perhaps I should have qualified that a bit - we shouldn't do it
gratuitously.

Getting the effect of CONTINUE for nested loops can be sufficiently hard
that it is arguable that implementing it is not just syntactic sugar. I seem
to recall muttering about how implementing GOTO wasn't worth the trouble.

>
>> Terseness is not always good, redundancy is not always bad.
>
> Granted -- but why is redundancy a good thing here?
>

see above

cheers

andrew





Re: pl/pgsql: END verbosity

From
Neil Conway
Date:
Andrew Dunstan wrote:
> But this doesn't make it easier to use - users don't just include those who
> write it. The antecedent language of these, Ada, from which this syntax
> comes, was explicitly designed to be reader-friendly as opposed to
> writer-friendly, and this is a part of that.

IMHO it is just needless verbiage that makes programs both harder to 
read *and* harder to write, albeit marginally so. I think there is a 
reason why Ada-style block terminators are in the minority among 
block-structured languages :)

But obviously this is a matter of taste -- does anyone else like or 
dislike the current syntax?

-Neil


Re: pl/pgsql: END verbosity

From
Steve Atkins
Date:
On Thu, Jun 23, 2005 at 01:41:49AM +1000, Neil Conway wrote:
> Andrew Dunstan wrote:
> >But this doesn't make it easier to use - users don't just include those who
> >write it. The antecedent language of these, Ada, from which this syntax
> >comes, was explicitly designed to be reader-friendly as opposed to
> >writer-friendly, and this is a part of that.
> 
> IMHO it is just needless verbiage that makes programs both harder to 
> read *and* harder to write, albeit marginally so. I think there is a 
> reason why Ada-style block terminators are in the minority among 
> block-structured languages :)
> 
> But obviously this is a matter of taste -- does anyone else like or 
> dislike the current syntax?

"Like" is a bit strong. But it does make functions written in it easier
to read. And given that the primary debugging methodolofy for pl/pgsql
is "Look at it hard and see what might be incorrect" I can't see that
as a bad thing.

I'd trade a whole lot of "harder to write" for even some "likely to
work".

Cheers, Steve


Re: pl/pgsql: END verbosity

From
Alvaro Herrera
Date:
On Wed, Jun 22, 2005 at 09:23:17AM -0700, Steve Atkins wrote:
> On Thu, Jun 23, 2005 at 01:41:49AM +1000, Neil Conway wrote:
> > Andrew Dunstan wrote:
> > >But this doesn't make it easier to use - users don't just include those who
> > >write it. The antecedent language of these, Ada, from which this syntax
> > >comes, was explicitly designed to be reader-friendly as opposed to
> > >writer-friendly, and this is a part of that.
> > 
> > IMHO it is just needless verbiage that makes programs both harder to 
> > read *and* harder to write, albeit marginally so. I think there is a 
> > reason why Ada-style block terminators are in the minority among 
> > block-structured languages :)
> > 
> > But obviously this is a matter of taste -- does anyone else like or 
> > dislike the current syntax?
> 
> "Like" is a bit strong. But it does make functions written in it easier
> to read. And given that the primary debugging methodolofy for pl/pgsql
> is "Look at it hard and see what might be incorrect" I can't see that
> as a bad thing.

Yeah, while we don't have good debugging support in pl/pgsql we
shouldn't be making it harder to read.  (FWIW, yes, I think it's useful
for those keywords to be required when you have to look at homongous
functions.)

-- 
Alvaro Herrera (<alvherre[a]surnet.cl>)
"No renuncies a nada. No te aferres a nada."


Re: pl/pgsql: END verbosity

From
Pavel Stehule
Date:
On Tue, 21 Jun 2005, Andrew Dunstan wrote:

> Neil Conway said:
> > In PL/PgSQL, "END LOOP" is used to terminate loop blocks, and "END IF"
> > is used to terminate IF blocks. This is needlessly verbose: we could
> > simply accept "END" in both cases without syntactic ambiguity. I'd like
> >  to make this change, so that END can be used to terminate any kind of
> > block. There's no need to remove support for the present syntax, of
> > course, so there's no backward compatibility concern. Oracle's PL/SQL
> > does require "END IF" and "END LOOP", but folks interested in maximum
> > compatibility can always use those forms if they like.
> >

Hello,

I prefer actual syntax too, Neil. The reason isn't compatibility with 
Oracle, but better readibility - it's mean more work with finishing code 
but less with debugging

Regards
Pavel



Re: pl/pgsql: END verbosity

From
"Merlin Moncure"
Date:
> > Neil Conway said:
> > > In PL/PgSQL, "END LOOP" is used to terminate loop blocks, and "END
IF"
> > > is used to terminate IF blocks. This is needlessly verbose: we
could
> > > simply accept "END" in both cases without syntactic ambiguity. I'd
> like
> > >  to make this change, so that END can be used to terminate any
kind of
> > > block. There's no need to remove support for the present syntax,
of
> > > course, so there's no backward compatibility concern. Oracle's
PL/SQL
> > > does require "END IF" and "END LOOP", but folks interested in
maximum
> > > compatibility can always use those forms if they like.
> > >
>
> Hello,
>
> I prefer actual syntax too, Neil. The reason isn't compatibility with
> Oracle, but better readibility - it's mean more work with finishing
code
> but less with debugging

COBOL, which is a kissing-cousin of pl/sql, allows this.  You can have a
line terminator (a period) or a specialized block terminator.  Based on
my experience here I would suggest not allowing a choice.  It's a famous
source of bugs.

Merlin


PL/pgSQL Debugger Support

From
Denis Lussier
Date:
<font face="Verdana, Helvetica, Arial"><span style="font-size:12.0px">Hi All,<br /><br /> Sorry if this isn’t the right
forumfor this question...  But, I noticed that Alvaro wrote<br /><br />  “... we don't have good debugging support in
pl/pgsql...”<br /></span></font><blockquote><font face="Verdana, Helvetica, Arial"><span style="font-size:12.0px"><br
/></span></font></blockquote><fontface="Verdana, Helvetica, Arial"><span style="font-size:12.0px">I got to thinking
it’dbe kewl if PgAdmin3 supported an interactive debugger for pl/pgsql.  If anyone’s interested in expertly tackling
sucha community project, with some financial sponsorship from EDB, please contact me privately.<br /><br /> --Denis
Lussier<br/>   Founder & Chief Dweeb<br />   EnterpriseDB<br /><br /></span></font> 

Re: PL/pgSQL Debugger Support

From
Tom Lane
Date:
Denis Lussier <denisl@enterprisedb.com> writes:
> I got to thinking it'd be kewl if PgAdmin3 supported an interactive debugger
> for pl/pgsql.

That's been kicked around before, although I don't think anyone wants to
tie it to pgAdmin specifically.  Check the archives...
        regards, tom lane


Re: pl/pgsql: END verbosity

From
Jan Wieck
Date:
On 6/22/2005 1:29 AM, Neil Conway wrote:

> Tom Lane wrote:
>> The long-term point in my mind is that removing syntactical
>> redundancy always reduces the ability to detect errors or report
>> errors acccurately
> 
> Lexical scoping is unambiguous in a language like PL/PgSQL. Since it is 
> simple to determine whether a given END matches an IF, LOOP, or BEGIN, I 
> don't see how it would reduce our "ability to detect errors or report 
> errors accurately".
> 
>> Consider for example the possibility that Oracle's next release adds
>> some new frammish that can't be duplicated because we chose not to
>> distinguish various forms of "END xxx" ...
> 
> As lexical scoping is still unambiguous, we could actually add a K_LOOP 
> / K_IF token to the input stream, if that would make you happier :) (Of 
> course I'm not suggesting this -- the point is that as far as the parser 
> is concerned, we should have precisely the same information for 
> disambiguating the input as we used to have.)
> 
> BTW, I notice that Oracle actually allows:
> 
> <<label>>
> LOOP
>      -- ...
> END LOOP label;

But what if they decide to allow

LOOP    -- ...    IF condition THEN        EXIT;
END LOOP;

at some point? There you'd get ambiguity.


Jan


> 
> whereas we don't allow the optional label following END LOOP. Which goes 
> to my general point: this frammish has existed in PL/SQL for a while, 
> but it's not as if people are clamoring for us to implement it. I would 
> wager that most people care about having *equivalent* features to 
> PL/SQL, not exactly identical syntax. For example, the lack of 
> autonomous transactions is something people have asked for in the past, 
> because it *does* make porting PL/SQL applications more difficult. I 
> can't see anyone losing any sleep because we are slightly more relaxed 
> about the input we accept.
> 
> -Neil
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 6: Have you searched our list archives?
> 
>                http://archives.postgresql.org


-- 
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#================================================== JanWieck@Yahoo.com #


Re: PL/pgSQL Debugger Support

From
"Matthew T. O'Connor"
Date:
Tom Lane wrote:

>Denis Lussier <denisl@enterprisedb.com> writes:
>  
>
>>I got to thinking it'd be kewl if PgAdmin3 supported an interactive debugger
>>for pl/pgsql.
>>    
>>
>
>That's been kicked around before, although I don't think anyone wants to
>tie it to pgAdmin specifically.  Check the archives...
>  
>

I didn't find anything relevant after a quick search, but if memory 
serves, one of the objections to PgAdmin was that it was windows only.  
This of course is no longer true as of PgAdmin III 1.0.  It now support 
Win32, Linux and FreeBSD.  So perhaps that objection is no longer valid.


Re: PL/pgSQL Debugger Support

From
Alvaro Herrera
Date:
On Thu, Jun 23, 2005 at 01:40:18PM -0400, Matthew T. O'Connor wrote:
> Tom Lane wrote:
> 
> >Denis Lussier <denisl@enterprisedb.com> writes:
> > 
> >
> >>I got to thinking it'd be kewl if PgAdmin3 supported an interactive
> >>debugger for pl/pgsql.
> >
> >That's been kicked around before, although I don't think anyone wants to
> >tie it to pgAdmin specifically.  Check the archives...
> 
> I didn't find anything relevant after a quick search, but if memory 
> serves, one of the objections to PgAdmin was that it was windows only.  
> This of course is no longer true as of PgAdmin III 1.0.  It now support 
> Win32, Linux and FreeBSD.  So perhaps that objection is no longer valid.

I think the point is that we will have to make some modifications to
PL/pgSQL, so why not make sure we write something that any tool can use?
Say, a well-defined BE/FE protocol extension.

-- 
Alvaro Herrera (<alvherre[a]surnet.cl>)
"Sallah, I said NO camels! That's FIVE camels; can't you count?"
(Indiana Jones)


Re: PL/pgSQL Debugger Support

From
"Jonah H. Harris"
Date:
Alvaro,

I agree, a protocol seems to generally be the best option.

-Jonah

Alvaro Herrera wrote:

>On Thu, Jun 23, 2005 at 01:40:18PM -0400, Matthew T. O'Connor wrote:
>  
>
>>Tom Lane wrote:
>>
>>    
>>
>>>Denis Lussier <denisl@enterprisedb.com> writes:
>>>
>>>
>>>      
>>>
>>>>I got to thinking it'd be kewl if PgAdmin3 supported an interactive
>>>>debugger for pl/pgsql.
>>>>        
>>>>
>>>That's been kicked around before, although I don't think anyone wants to
>>>tie it to pgAdmin specifically.  Check the archives...
>>>      
>>>
>>I didn't find anything relevant after a quick search, but if memory 
>>serves, one of the objections to PgAdmin was that it was windows only.  
>>This of course is no longer true as of PgAdmin III 1.0.  It now support 
>>Win32, Linux and FreeBSD.  So perhaps that objection is no longer valid.
>>    
>>
>
>I think the point is that we will have to make some modifications to
>PL/pgSQL, so why not make sure we write something that any tool can use?
>Say, a well-defined BE/FE protocol extension.
>
>  
>



Re: PL/pgSQL Debugger Support

From
Josh Berkus
Date:
Denis, all,

> I got to thinking it¹d be kewl if PgAdmin3 supported an interactive
> debugger for pl/pgsql.  If anyone¹s interested in expertly tackling such a
> community project, with some financial sponsorship from EDB, please contact
> me privately.

Just FYI, EMS Hitech has a windows-only PL/pgSQL debugger.  So it's apparently
possible even with the current tech.

Overally, though, we'd want to support something command-line like the Perl
debug shell.  Then any tool could use it.

--
Josh Berkus
Aglio Database Solutions
San Francisco


Re: PL/pgSQL Debugger Support

From
Robert Treat
Date:
On Thursday 23 June 2005 14:21, Josh Berkus wrote:
> Denis, all,
>
> > I got to thinking it¹d be kewl if PgAdmin3 supported an interactive
> > debugger for pl/pgsql.  If anyone¹s interested in expertly tackling such
> > a community project, with some financial sponsorship from EDB, please
> > contact me privately.
>
> Just FYI, EMS Hitech has a windows-only PL/pgSQL debugger.  So it's
> apparently possible even with the current tech.
>

IIRC thier debugger is little more than BEGIN; SELECT foo(); ROLLBACK; which
isn't great as far as debuggers go.

> Overally, though, we'd want to support something command-line like the Perl
> debug shell.  Then any tool could use it.

Uh... a lot of tools have issues executing stuff from the command line... what
we need is something sql driven, or at least that opeates at that level,
inside the db.

--
Robert Treat
Build A Brighter Lamp :: Linux Apache {middleware} PostgreSQL


Re: pl/pgsql: END verbosity

From
Robert Treat
Date:
On Wednesday 22 June 2005 11:41, Neil Conway wrote:
> Andrew Dunstan wrote:
> > But this doesn't make it easier to use - users don't just include those
> > who write it. The antecedent language of these, Ada, from which this
> > syntax comes, was explicitly designed to be reader-friendly as opposed to
> > writer-friendly, and this is a part of that.
>
> IMHO it is just needless verbiage that makes programs both harder to
> read *and* harder to write, albeit marginally so. I think there is a
> reason why Ada-style block terminators are in the minority among
> block-structured languages :)
>
> But obviously this is a matter of taste -- does anyone else like or
> dislike the current syntax?
>

-1 on the proposal to me... ambiguous END statements just looks like trouble 
to me.  I'd actually rather see you implement label...END LOOP label if you 
felt like you had to change *something*.

-- 
Robert Treat
Build A Brighter Lamp :: Linux Apache {middleware} PostgreSQL


Re: pl/pgsql: END verbosity

From
Neil Conway
Date:
Jan Wieck wrote:
> But what if they decide to allow
> 
> LOOP
>     -- ...
>     IF condition THEN
>         EXIT;
> END LOOP;
> 
> at some point? There you'd get ambiguity.

ISTM this would be ambiguous in any case:

IF condition1 THEN    foo;    IF condition2 THEN        bar;
END IF;

-Neil


Re: PL/pgSQL Debugger Support

From
Bob
Date:
My understanding is that EMS Hitech is just doing client side debugging.
 
That is they are taking your function and creating a new process to follow the flow of the program. So if they mess up something you may thing your  program is doing one thing when it is really doing something else. Maybe I'm wrong here but I assume that is what is going on.  While this is better than nothing, it doesn't compare to a built in API in pl/pgsql that would allow any tool to hook into a function and debug.  Would love to work on this if I had the low level programming skills that the main hackers have.
 
 
On 6/23/05, Josh Berkus <josh@agliodbs.com> wrote:
Denis, all,

> I got to thinking it¹d be kewl if PgAdmin3 supported an interactive
> debugger for pl/pgsql. If anyone¹s interested in expertly tackling such a
> community project, with some financial sponsorship from EDB, please contact
> me privately.

Just FYI, EMS Hitech has a windows-only PL/pgSQL debugger.  So it's apparently
possible even with the current tech.

Overally, though, we'd want to support something command-line like the Perl
debug shell.  Then any tool could use it.

--
Josh Berkus
Aglio Database Solutions
San Francisco

---------------------------(end of broadcast)---------------------------
TIP 3: if posting/reading through Usenet, please send an appropriate
      subscribe-nomail command to majordomo@postgresql.org so that your
      message can get through to the mailing list cleanly

Re: pl/pgsql: END verbosity

From
Peter Eisentraut
Date:
Am Mittwoch, 22. Juni 2005 04:17 schrieb Neil Conway:
> In PL/PgSQL, "END LOOP" is used to terminate loop blocks, and "END IF"
> is used to terminate IF blocks. This is needlessly verbose:

It is required by the SQL standard.


pl/pgsql: END verbosity [patch]

From
Pavel Stehule
Date:
Hello

this patch allows optional using label with END and END LOOP. Ending label
has only informational value, but can enhance readability large block and
enhance likeness with Oracle.

<<main>>LOOP
 ...
 ...
END LOOP<<main>>;

Regards
Pavel Stehule

Re: pl/pgsql: END verbosity

From
Neil Conway
Date:
Peter Eisentraut wrote:
> It is required by the SQL standard.

No, it isn't -- PL/PgSQL is not defined by the SQL standard. I guess 
you're referring to SQL/PSM, but that has only a passing resemblance to 
PL/PgSQL. Implementing SQL/PSM in some form would definitely be worth 
doing (especially now that MySQL have), but I haven't seen any plans to 
do that by adapting PL/PgSQL to SQL/PSM.

In any case, there are plenty of cases in which we accept a superset of 
the syntax defined by the SQL standard -- DROP TABLE { RESTRICT | 
CASCADE }, for example. We have never interpreted compliance with the 
SQL specification to mean that we must *only* accept the standard's 
syntax and nothing else.

-Neil


Re: pl/pgsql: END verbosity

From
Peter Eisentraut
Date:
Neil Conway wrote:
> No, it isn't -- PL/PgSQL is not defined by the SQL standard. I guess
> you're referring to SQL/PSM, but that has only a passing resemblance
> to PL/PgSQL. Implementing SQL/PSM in some form would definitely be
> worth doing (especially now that MySQL have), but I haven't seen any
> plans to do that by adapting PL/PgSQL to SQL/PSM.

I don't claim to recall the details, but we have frequently referred to 
the SQL standard when resolving issues about PL/pgSQL's syntax.

> In any case, there are plenty of cases in which we accept a superset
> of the syntax defined by the SQL standard -- DROP TABLE { RESTRICT |
> CASCADE }, for example. We have never interpreted compliance with the
> SQL specification to mean that we must *only* accept the standard's
> syntax and nothing else.

The cases were we accept a superset of the SQL standard are either 
additional features, backward compatibility, or compatibility to other 
systems -- none of which seem to apply here.

-- 
Peter Eisentraut
http://developer.postgresql.org/~petere/


Re: pl/pgsql: END verbosity

From
Pavel Stehule
Date:
On Mon, 27 Jun 2005, Neil Conway wrote:

> Peter Eisentraut wrote:
> > It is required by the SQL standard.
> 
> No, it isn't -- PL/PgSQL is not defined by the SQL standard. I guess 
> you're referring to SQL/PSM, but that has only a passing resemblance to 
> PL/PgSQL. Implementing SQL/PSM in some form would definitely be worth 
> doing (especially now that MySQL have), but I haven't seen any plans to 
> do that by adapting PL/PgSQL to SQL/PSM.

PL/pgSQL is different language than SQL/PSM and is little bit nonsenc 
adapting them to SQL/PSM. PL/SQL live still - Oracle did some enhancing, 
and we can do it too. 

Some parts both languages are similar and some enough different. I had 
plan start develop new interpret for SQL/PSM two years ago, but I hadn't 
knowleages at that time. Situation is different now. If anybody wont to 
work on SQL/PSM  I will go too. Solution is another pl - pl/psm. We can 
adapt gram.y plpgsql to psm

Regards
Pavel Stehule




Re: pl/pgsql: END verbosity [patch]

From
Neil Conway
Date:
Pavel Stehule wrote:
> this patch allows optional using label with END and END LOOP. Ending label
> has only informational value, but can enhance readability large block and
> enhance likeness with Oracle.
>
> <<main>>LOOP
>  ...
>  ...
> END LOOP<<main>>;

Attached is a revised version of this patch. Changes / comments:

- AFAICS Oracle's syntax is actually

<<label>> LOOP
...
END LOOP label;

i.e. the ending block label isn't enclosed in <<>>. I've adjusted the
patch accordingly.

- your patch broke EXIT and CONTINUE, as running the regression tests
would have made clear.

- yyerror() will set plpgsql_error_lineno, so you needn't do it
yourself. I changed it to use ereport(ERROR) anyway, as it seems a bit
more appropriate. I'm not quite happy with the error message text:

ERROR:  end label "outer_label" differs from block's label "inner_label"
CONTEXT:  compile of PL/pgSQL function "end_label3" near line 6

ERROR:  end label "outer_label" specified for unlabelled block
CONTEXT:  compile of PL/pgSQL function "end_label4" near line 5

suggestions for improvement are welcome.

BTW, I notice that some but not all the call sites of ereport(ERROR) in
PL/PgSQL's gram.y set plpgsql_error_lineno. Is there a reason for this?

Barring any objections, I'll apply the attached patch to CVS tomorrow.

-Neil
Index: doc/src/sgml/plpgsql.sgml
===================================================================
RCS file: /Users/neilc/local/cvs/pgsql/doc/src/sgml/plpgsql.sgml,v
retrieving revision 1.74
diff -c -r1.74 plpgsql.sgml
*** doc/src/sgml/plpgsql.sgml    22 Jun 2005 01:35:02 -0000    1.74
--- doc/src/sgml/plpgsql.sgml    1 Jul 2005 11:43:36 -0000
***************
*** 456,462 ****
      <replaceable>declarations</replaceable> </optional>
  BEGIN
      <replaceable>statements</replaceable>
! END;
  </synopsis>
      </para>

--- 456,462 ----
      <replaceable>declarations</replaceable> </optional>
  BEGIN
      <replaceable>statements</replaceable>
! END <optional> <replaceable>label</replaceable> </optional>;
  </synopsis>
      </para>

***************
*** 1789,1806 ****
       <title><literal>LOOP</></title>

  <synopsis>
! <optional><<<replaceable>label</replaceable>>></optional>
  LOOP
      <replaceable>statements</replaceable>
! END LOOP;
  </synopsis>

       <para>
!       <literal>LOOP</> defines an unconditional loop that is repeated indefinitely
!       until terminated by an <literal>EXIT</> or <command>RETURN</command>
!       statement.  The optional label can be used by <literal>EXIT</> statements in
!       nested loops to specify which level of nesting should be
!       terminated.
       </para>
      </sect3>

--- 1789,1807 ----
       <title><literal>LOOP</></title>

  <synopsis>
! <optional> <<<replaceable>label</replaceable>>> </optional>
  LOOP
      <replaceable>statements</replaceable>
! END LOOP <optional> <replaceable>label</replaceable> </optional>;
  </synopsis>

       <para>
!       <literal>LOOP</> defines an unconditional loop that is repeated
!       indefinitely until terminated by an <literal>EXIT</> or
!       <command>RETURN</command> statement.  The optional
!       <replaceable>label</replaceable> can be used by <literal>EXIT</>
!       and <literal>CONTINUE</literal> statements in nested loops to
!       specify which loop the statement should be applied to.
       </para>
      </sect3>

***************
*** 1920,1929 ****
       </indexterm>

  <synopsis>
! <optional><<<replaceable>label</replaceable>>></optional>
  WHILE <replaceable>expression</replaceable> LOOP
      <replaceable>statements</replaceable>
! END LOOP;
  </synopsis>

         <para>
--- 1921,1930 ----
       </indexterm>

  <synopsis>
! <optional> <<<replaceable>label</replaceable>>> </optional>
  WHILE <replaceable>expression</replaceable> LOOP
      <replaceable>statements</replaceable>
! END LOOP <optional> <replaceable>label</replaceable> </optional>;
  </synopsis>

         <para>
***************
*** 1951,1960 ****
        <title><literal>FOR</> (integer variant)</title>

  <synopsis>
! <optional><<<replaceable>label</replaceable>>></optional>
  FOR <replaceable>name</replaceable> IN <optional> REVERSE </optional> <replaceable>expression</replaceable> ..
<replaceable>expression</replaceable>LOOP 
      <replaceable>statements</replaceable>
! END LOOP;
  </synopsis>

         <para>
--- 1952,1961 ----
        <title><literal>FOR</> (integer variant)</title>

  <synopsis>
! <optional> <<<replaceable>label</replaceable>>> </optional>
  FOR <replaceable>name</replaceable> IN <optional> REVERSE </optional> <replaceable>expression</replaceable> ..
<replaceable>expression</replaceable>LOOP 
      <replaceable>statements</replaceable>
! END LOOP <optional> <replaceable>labal</replaceable> </optional>;
  </synopsis>

         <para>
***************
*** 1997,2006 ****
       the results of a query and manipulate that data
       accordingly. The syntax is:
  <synopsis>
! <optional><<<replaceable>label</replaceable>>></optional>
  FOR <replaceable>record_or_row</replaceable> IN <replaceable>query</replaceable> LOOP
      <replaceable>statements</replaceable>
! END LOOP;
  </synopsis>
       The record or row variable is successively assigned each row
       resulting from the <replaceable>query</replaceable> (which must be a
--- 1998,2007 ----
       the results of a query and manipulate that data
       accordingly. The syntax is:
  <synopsis>
! <optional> <<<replaceable>label</replaceable>>> </optional>
  FOR <replaceable>record_or_row</replaceable> IN <replaceable>query</replaceable> LOOP
      <replaceable>statements</replaceable>
! END LOOP <optional> <replaceable>label</replaceable> </optional>;
  </synopsis>
       The record or row variable is successively assigned each row
       resulting from the <replaceable>query</replaceable> (which must be a
***************
*** 2036,2045 ****
       The <literal>FOR-IN-EXECUTE</> statement is another way to iterate over
       rows:
  <synopsis>
! <optional><<<replaceable>label</replaceable>>></optional>
  FOR <replaceable>record_or_row</replaceable> IN EXECUTE <replaceable>text_expression</replaceable> LOOP
      <replaceable>statements</replaceable>
! END LOOP;
  </synopsis>
       This is like the previous form, except that the source
       <command>SELECT</command> statement is specified as a string
--- 2037,2046 ----
       The <literal>FOR-IN-EXECUTE</> statement is another way to iterate over
       rows:
  <synopsis>
! <optional> <<<replaceable>label</replaceable>>> </optional>
  FOR <replaceable>record_or_row</replaceable> IN EXECUTE <replaceable>text_expression</replaceable> LOOP
      <replaceable>statements</replaceable>
! END LOOP <optional> <replaceable>label</replaceable> </optional>;
  </synopsis>
       This is like the previous form, except that the source
       <command>SELECT</command> statement is specified as a string
Index: src/pl/plpgsql/src/gram.y
===================================================================
RCS file: /Users/neilc/local/cvs/pgsql/src/pl/plpgsql/src/gram.y,v
retrieving revision 1.77
diff -c -r1.77 gram.y
*** src/pl/plpgsql/src/gram.y    22 Jun 2005 01:35:02 -0000    1.77
--- src/pl/plpgsql/src/gram.y    1 Jul 2005 12:08:45 -0000
***************
*** 56,61 ****
--- 56,63 ----
                                                 PLpgSQL_datum *initial_datum);
  static    void             check_sql_expr(const char *stmt);
  static    void             plpgsql_sql_error_callback(void *arg);
+ static    void             check_labels(const char *start_label,
+                                       const char *end_label);

  %}

***************
*** 69,75 ****
              int  lineno;
          }                        varname;
          struct
!         {
              char *name;
              int  lineno;
              PLpgSQL_rec     *rec;
--- 71,77 ----
              int  lineno;
          }                        varname;
          struct
!         {
              char *name;
              int  lineno;
              PLpgSQL_rec     *rec;
***************
*** 81,86 ****
--- 83,93 ----
              int  n_initvars;
              int  *initvarnos;
          }                        declhdr;
+         struct
+         {
+             char *end_label;
+             List *stmts;
+         }                        loop_body;
          List                    *list;
          PLpgSQL_type            *dtype;
          PLpgSQL_datum            *scalar;    /* a VAR, RECFIELD, or TRIGARG */
***************
*** 119,129 ****
  %type <forvariable>    for_variable
  %type <stmt>    for_control

! %type <str>        opt_lblname opt_label
! %type <str>        opt_exitlabel
  %type <str>        execsql_start

! %type <list>    proc_sect proc_stmts stmt_else loop_body
  %type <stmt>    proc_stmt pl_block
  %type <stmt>    stmt_assign stmt_if stmt_loop stmt_while stmt_exit
  %type <stmt>    stmt_return stmt_return_next stmt_raise stmt_execsql
--- 126,136 ----
  %type <forvariable>    for_variable
  %type <stmt>    for_control

! %type <str>        opt_lblname opt_block_label opt_label
  %type <str>        execsql_start

! %type <list>    proc_sect proc_stmts stmt_else
! %type <loop_body>    loop_body
  %type <stmt>    proc_stmt pl_block
  %type <stmt>    stmt_assign stmt_if stmt_loop stmt_while stmt_exit
  %type <stmt>    stmt_return stmt_return_next stmt_raise stmt_execsql
***************
*** 248,257 ****
                  | ';'
                  ;

! pl_block        : decl_sect K_BEGIN lno proc_sect exception_sect K_END
                      {
                          PLpgSQL_stmt_block *new;

                          new = palloc0(sizeof(PLpgSQL_stmt_block));

                          new->cmd_type    = PLPGSQL_STMT_BLOCK;
--- 255,266 ----
                  | ';'
                  ;

! pl_block        : decl_sect K_BEGIN lno proc_sect exception_sect K_END opt_label
                      {
                          PLpgSQL_stmt_block *new;

+                         check_labels($1.label, $7);
+
                          new = palloc0(sizeof(PLpgSQL_stmt_block));

                          new->cmd_type    = PLPGSQL_STMT_BLOCK;
***************
*** 269,275 ****
                  ;


! decl_sect        : opt_label
                      {
                          plpgsql_ns_setlocal(false);
                          $$.label      = $1;
--- 278,284 ----
                  ;


! decl_sect        : opt_block_label
                      {
                          plpgsql_ns_setlocal(false);
                          $$.label      = $1;
***************
*** 277,283 ****
                          $$.initvarnos = NULL;
                          plpgsql_add_initdatums(NULL);
                      }
!                 | opt_label decl_start
                      {
                          plpgsql_ns_setlocal(false);
                          $$.label      = $1;
--- 286,292 ----
                          $$.initvarnos = NULL;
                          plpgsql_add_initdatums(NULL);
                      }
!                 | opt_block_label decl_start
                      {
                          plpgsql_ns_setlocal(false);
                          $$.label      = $1;
***************
*** 285,291 ****
                          $$.initvarnos = NULL;
                          plpgsql_add_initdatums(NULL);
                      }
!                 | opt_label decl_start decl_stmts
                      {
                          plpgsql_ns_setlocal(false);
                          if ($3 != NULL)
--- 294,300 ----
                          $$.initvarnos = NULL;
                          plpgsql_add_initdatums(NULL);
                      }
!                 | opt_block_label decl_start decl_stmts
                      {
                          plpgsql_ns_setlocal(false);
                          if ($3 != NULL)
***************
*** 409,415 ****
                          plpgsql_ns_setlocal(false);
                          query = read_sql_stmt("");
                          plpgsql_ns_setlocal(true);
!
                          $$ = query;
                      }
                  ;
--- 418,424 ----
                          plpgsql_ns_setlocal(false);
                          query = read_sql_stmt("");
                          plpgsql_ns_setlocal(true);
!
                          $$ = query;
                      }
                  ;
***************
*** 757,763 ****
                           *     ...                               ...
                           * ELSE                               ELSE
                           *     ...                               ...
!                          * END IF                           END IF
                           *                               END IF
                           */
                          PLpgSQL_stmt_if *new_if;
--- 766,772 ----
                           *     ...                               ...
                           * ELSE                               ELSE
                           *     ...                               ...
!                          * END IF                           END IF
                           *                               END IF
                           */
                          PLpgSQL_stmt_if *new_if;
***************
*** 776,786 ****

                  | K_ELSE proc_sect
                      {
!                         $$ = $2;
                      }
                  ;

! stmt_loop        : opt_label K_LOOP lno loop_body
                      {
                          PLpgSQL_stmt_loop *new;

--- 785,795 ----

                  | K_ELSE proc_sect
                      {
!                         $$ = $2;
                      }
                  ;

! stmt_loop        : opt_block_label K_LOOP lno loop_body
                      {
                          PLpgSQL_stmt_loop *new;

***************
*** 788,802 ****
                          new->cmd_type = PLPGSQL_STMT_LOOP;
                          new->lineno   = $3;
                          new->label      = $1;
!                         new->body      = $4;

                          plpgsql_ns_pop();

                          $$ = (PLpgSQL_stmt *)new;
                      }
                  ;

! stmt_while        : opt_label K_WHILE lno expr_until_loop loop_body
                      {
                          PLpgSQL_stmt_while *new;

--- 797,812 ----
                          new->cmd_type = PLPGSQL_STMT_LOOP;
                          new->lineno   = $3;
                          new->label      = $1;
!                         new->body      = $4.stmts;

+                         check_labels($1, $4.end_label);
                          plpgsql_ns_pop();

                          $$ = (PLpgSQL_stmt *)new;
                      }
                  ;

! stmt_while        : opt_block_label K_WHILE lno expr_until_loop loop_body
                      {
                          PLpgSQL_stmt_while *new;

***************
*** 805,819 ****
                          new->lineno   = $3;
                          new->label      = $1;
                          new->cond      = $4;
!                         new->body      = $5;

                          plpgsql_ns_pop();

                          $$ = (PLpgSQL_stmt *)new;
                      }
                  ;

! stmt_for        : opt_label K_FOR for_control loop_body
                      {
                          /* This runs after we've scanned the loop body */
                          if ($3->cmd_type == PLPGSQL_STMT_FORI)
--- 815,830 ----
                          new->lineno   = $3;
                          new->label      = $1;
                          new->cond      = $4;
!                         new->body      = $5.stmts;

+                         check_labels($1, $5.end_label);
                          plpgsql_ns_pop();

                          $$ = (PLpgSQL_stmt *)new;
                      }
                  ;

! stmt_for        : opt_block_label K_FOR for_control loop_body
                      {
                          /* This runs after we've scanned the loop body */
                          if ($3->cmd_type == PLPGSQL_STMT_FORI)
***************
*** 822,828 ****

                              new = (PLpgSQL_stmt_fori *) $3;
                              new->label      = $1;
!                             new->body      = $4;
                              $$ = (PLpgSQL_stmt *) new;
                          }
                          else if ($3->cmd_type == PLPGSQL_STMT_FORS)
--- 833,839 ----

                              new = (PLpgSQL_stmt_fori *) $3;
                              new->label      = $1;
!                             new->body      = $4.stmts;
                              $$ = (PLpgSQL_stmt *) new;
                          }
                          else if ($3->cmd_type == PLPGSQL_STMT_FORS)
***************
*** 831,837 ****

                              new = (PLpgSQL_stmt_fors *) $3;
                              new->label      = $1;
!                             new->body      = $4;
                              $$ = (PLpgSQL_stmt *) new;
                          }
                          else
--- 842,848 ----

                              new = (PLpgSQL_stmt_fors *) $3;
                              new->label      = $1;
!                             new->body      = $4.stmts;
                              $$ = (PLpgSQL_stmt *) new;
                          }
                          else
***************
*** 841,850 ****
                              Assert($3->cmd_type == PLPGSQL_STMT_DYNFORS);
                              new = (PLpgSQL_stmt_dynfors *) $3;
                              new->label      = $1;
!                             new->body      = $4;
                              $$ = (PLpgSQL_stmt *) new;
                          }

                          /* close namespace started in opt_label */
                          plpgsql_ns_pop();
                      }
--- 852,862 ----
                              Assert($3->cmd_type == PLPGSQL_STMT_DYNFORS);
                              new = (PLpgSQL_stmt_dynfors *) $3;
                              new->label      = $1;
!                             new->body      = $4.stmts;
                              $$ = (PLpgSQL_stmt *) new;
                          }

+                         check_labels($1, $4.end_label);
                          /* close namespace started in opt_label */
                          plpgsql_ns_pop();
                      }
***************
*** 1037,1043 ****
                      }
                  ;

! stmt_exit        : exit_type lno opt_exitlabel opt_exitcond
                      {
                          PLpgSQL_stmt_exit *new;

--- 1049,1055 ----
                      }
                  ;

! stmt_exit        : exit_type lno opt_label opt_exitcond
                      {
                          PLpgSQL_stmt_exit *new;

***************
*** 1245,1252 ****
                      }
                  ;

! loop_body        : proc_sect K_END K_LOOP ';'
!                     { $$ = $1; }
                  ;

  stmt_execsql    : execsql_start lno
--- 1257,1267 ----
                      }
                  ;

! loop_body        : proc_sect K_END K_LOOP opt_label ';'
!                     {
!                         $$.stmts = $1;
!                         $$.end_label = $4;
!                     }
                  ;

  stmt_execsql    : execsql_start lno
***************
*** 1262,1268 ****
                      }
                  ;

! stmt_dynexecute : K_EXECUTE lno
                      {
                          PLpgSQL_stmt_dynexecute *new;
                          PLpgSQL_expr *expr;
--- 1277,1283 ----
                      }
                  ;

! stmt_dynexecute : K_EXECUTE lno
                      {
                          PLpgSQL_stmt_dynexecute *new;
                          PLpgSQL_expr *expr;
***************
*** 1418,1424 ****
                                               errmsg("cursor \"%s\" has no arguments",
                                                      $3->refname)));
                                  }
!
                                  if (tok != ';')
                                  {
                                      plpgsql_error_lineno = plpgsql_scanner_lineno();
--- 1433,1439 ----
                                               errmsg("cursor \"%s\" has no arguments",
                                                      $3->refname)));
                                  }
!
                                  if (tok != ';')
                                  {
                                      plpgsql_error_lineno = plpgsql_scanner_lineno();
***************
*** 1596,1602 ****
                      { $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
                  ;

! opt_label        :
                      {
                          plpgsql_ns_push(NULL);
                          $$ = NULL;
--- 1611,1617 ----
                      { $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
                  ;

! opt_block_label    :
                      {
                          plpgsql_ns_push(NULL);
                          $$ = NULL;
***************
*** 1608,1621 ****
                      }
                  ;

! opt_exitlabel    :
!                     { $$ = NULL; }
                  | T_LABEL
                      {
!                         char    *name;
!
!                         plpgsql_convert_ident(yytext, &name, 1);
!                         $$ = name;
                      }
                  | T_WORD
                      {
--- 1623,1637 ----
                      }
                  ;

! opt_label    :
!                     {
!                         $$ = NULL;
!                     }
                  | T_LABEL
                      {
!                         char *label_name;
!                         plpgsql_convert_ident(yytext, &label_name, 1);
!                         $$ = label_name;
                      }
                  | T_WORD
                      {
***************
*** 2210,2213 ****
--- 2226,2254 ----
      errposition(0);
  }

+ static void
+ check_labels(const char *start_label, const char *end_label)
+ {
+     if (end_label)
+     {
+         if (!start_label)
+         {
+             plpgsql_error_lineno = plpgsql_scanner_lineno();
+             ereport(ERROR,
+                     (errcode(ERRCODE_SYNTAX_ERROR),
+                      errmsg("end label \"%s\" specified for unlabelled block",
+                             end_label)));
+         }
+
+         if (strcmp(start_label, end_label) != 0)
+         {
+             plpgsql_error_lineno = plpgsql_scanner_lineno();
+             ereport(ERROR,
+                     (errcode(ERRCODE_SYNTAX_ERROR),
+                      errmsg("end label \"%s\" differs from block's label \"%s\"",
+                             end_label, start_label)));
+         }
+     }
+ }
+
  #include "pl_scan.c"
Index: src/test/regress/expected/plpgsql.out
===================================================================
RCS file: /Users/neilc/local/cvs/pgsql/src/test/regress/expected/plpgsql.out,v
retrieving revision 1.36
diff -c -r1.36 plpgsql.out
*** src/test/regress/expected/plpgsql.out    22 Jun 2005 07:28:47 -0000    1.36
--- src/test/regress/expected/plpgsql.out    1 Jul 2005 11:53:55 -0000
***************
*** 2491,2497 ****
  (1 row)

  drop function raise_exprs();
! -- continue statement
  create table conttesttbl(idx serial, v integer);
  NOTICE:  CREATE TABLE will create implicit sequence "conttesttbl_idx_seq" for serial column "conttesttbl.idx"
  insert into conttesttbl(v) values(10);
--- 2491,2497 ----
  (1 row)

  drop function raise_exprs();
! -- continue statement
  create table conttesttbl(idx serial, v integer);
  NOTICE:  CREATE TABLE will create implicit sequence "conttesttbl_idx_seq" for serial column "conttesttbl.idx"
  insert into conttesttbl(v) values(10);
***************
*** 2532,2538 ****
    for _i in 1..10 loop
      begin
        -- applies to outer loop, not the nested begin block
!       continue when _i < 5;
        raise notice '%', _i;
      end;
    end loop;
--- 2532,2538 ----
    for _i in 1..10 loop
      begin
        -- applies to outer loop, not the nested begin block
!       continue when _i < 5;
        raise notice '%', _i;
      end;
    end loop;
***************
*** 2666,2668 ****
--- 2666,2723 ----
  drop function continue_test2();
  drop function continue_test3();
  drop table conttesttbl;
+ -- verbose end block and end loop
+ create function end_label1() returns void as $$
+ <<blbl>>
+ begin
+   <<flbl1>>
+   for _i in 1 .. 10 loop
+     exit flbl1;
+   end loop flbl1;
+   <<flbl2>>
+   for _i in 1 .. 10 loop
+     exit flbl2;
+   end loop;
+ end blbl;
+ $$ language plpgsql;
+ select end_label1();
+  end_label1
+ ------------
+
+ (1 row)
+
+ drop function end_label1();
+ -- should fail: undefined end label
+ create function end_label2() returns void as $$
+ begin
+   for _i in 1 .. 10 loop
+     exit;
+   end loop flbl1;
+ end;
+ $$ language plpgsql;
+ ERROR:  no such label at or near "flbl1" at character 101
+ LINE 5:   end loop flbl1;
+                    ^
+ -- should fail: end label does not match start label
+ create function end_label3() returns void as $$
+ <<outer_label>>
+ begin
+   <<inner_label>>
+   for _i in 1 .. 10 loop
+     exit;
+   end loop outer_label;
+ end;
+ $$ language plpgsql;
+ ERROR:  end label "outer_label" differs from block's label "inner_label"
+ CONTEXT:  compile of PL/pgSQL function "end_label3" near line 6
+ -- should fail: end label on a block without a start label
+ create function end_label4() returns void as $$
+ <<outer_label>>
+ begin
+   for _i in 1 .. 10 loop
+     exit;
+   end loop outer_label;
+ end;
+ $$ language plpgsql;
+ ERROR:  end label "outer_label" specified for unlabelled block
+ CONTEXT:  compile of PL/pgSQL function "end_label4" near line 5
Index: src/test/regress/sql/plpgsql.sql
===================================================================
RCS file: /Users/neilc/local/cvs/pgsql/src/test/regress/sql/plpgsql.sql,v
retrieving revision 1.31
diff -c -r1.31 plpgsql.sql
*** src/test/regress/sql/plpgsql.sql    22 Jun 2005 07:28:47 -0000    1.31
--- src/test/regress/sql/plpgsql.sql    1 Jul 2005 11:43:36 -0000
***************
*** 2113,2119 ****
  select raise_exprs();
  drop function raise_exprs();

! -- continue statement
  create table conttesttbl(idx serial, v integer);
  insert into conttesttbl(v) values(10);
  insert into conttesttbl(v) values(20);
--- 2113,2119 ----
  select raise_exprs();
  drop function raise_exprs();

! -- continue statement
  create table conttesttbl(idx serial, v integer);
  insert into conttesttbl(v) values(10);
  insert into conttesttbl(v) values(20);
***************
*** 2154,2160 ****
    for _i in 1..10 loop
      begin
        -- applies to outer loop, not the nested begin block
!       continue when _i < 5;
        raise notice '%', _i;
      end;
    end loop;
--- 2154,2160 ----
    for _i in 1..10 loop
      begin
        -- applies to outer loop, not the nested begin block
!       continue when _i < 5;
        raise notice '%', _i;
      end;
    end loop;
***************
*** 2232,2234 ****
--- 2232,2282 ----
  drop function continue_test2();
  drop function continue_test3();
  drop table conttesttbl;
+
+ -- verbose end block and end loop
+ create function end_label1() returns void as $$
+ <<blbl>>
+ begin
+   <<flbl1>>
+   for _i in 1 .. 10 loop
+     exit flbl1;
+   end loop flbl1;
+   <<flbl2>>
+   for _i in 1 .. 10 loop
+     exit flbl2;
+   end loop;
+ end blbl;
+ $$ language plpgsql;
+
+ select end_label1();
+ drop function end_label1();
+
+ -- should fail: undefined end label
+ create function end_label2() returns void as $$
+ begin
+   for _i in 1 .. 10 loop
+     exit;
+   end loop flbl1;
+ end;
+ $$ language plpgsql;
+
+ -- should fail: end label does not match start label
+ create function end_label3() returns void as $$
+ <<outer_label>>
+ begin
+   <<inner_label>>
+   for _i in 1 .. 10 loop
+     exit;
+   end loop outer_label;
+ end;
+ $$ language plpgsql;
+
+ -- should fail: end label on a block without a start label
+ create function end_label4() returns void as $$
+ <<outer_label>>
+ begin
+   for _i in 1 .. 10 loop
+     exit;
+   end loop outer_label;
+ end;
+ $$ language plpgsql;

Re: [PATCHES] pl/pgsql: END verbosity [patch]

From
Tom Lane
Date:
Neil Conway <neilc@samurai.com> writes:
> BTW, I notice that some but not all the call sites of ereport(ERROR) in
> PL/PgSQL's gram.y set plpgsql_error_lineno. Is there a reason for this?

Without looking at the code, I think it may be that you only need to set
the variable if you want the error to point someplace different than the
last "lno" nonterminal.

            regards, tom lane

Re: pl/pgsql: END verbosity [patch]

From
Neil Conway
Date:
Pavel Stehule wrote:
> this patch allows optional using label with END and END LOOP. Ending label
> has only informational value, but can enhance readability large block and
> enhance likeness with Oracle.

Reviewed and applied -- thanks for the patch.

-Neil