Thread: PL/PgSQL "bare" function calls

PL/PgSQL "bare" function calls

From
Neil Conway
Date:
I'd like to make it possible to perform function calls in PL/PgSQL
without needing to use PERFORM. I think this would be useful because (a)
it is closer to how PL/SQL works (b) PERFORM is (IMHO) a kludge, and
making it unnecessary would make programming in PL/PgSQL more natural.

Attached is a proof of concept patch that implements this. With this
patch, you can now write functions like so:

CREATE OR REPLACE FUNCTION some_func() RETURNS INT AS
'BEGIN
call_some_function();
RETURN 5;
END;
' LANGUAGE 'plpgsql';

Known issues with the patch:

(1) It seems to induce an intermittent segfault in the regression tests
on one of my machines (but not any others) which I need to fix.

(2) We should probably allow the name of a function to be double-quoted
so that it is possible to call functions with unusual names (mixed-case
and so on). I believe this should be possible, I just haven't
implemented it yet.

(3) The parser must distinguish between two cases when it sees an
unknown word (T_WORD) beginning a statement. The word could be the
beginning of a SQL statement (stmt_execsql in the grammar), such as:

UPDATE ...;

or the name of a function in a function call:

invoke_func(...);

The patch currently distinguishes between these cases by looking at the
next token -- if it is a left parenthesis, the patch assumes it is a
function call, otherwise it assumes it is a SQL statement. Is this the
best approach?

(Another method would be to teach the PL/PgSQL lexer about the basic SQL
keywords like UPDATE, INSERT, and so on, and then distinguish the two
cases that way. This would impose a maintenance burden when new SQL
commands are added, so I didn't adopt this approach.)

(4) This is proof-of-concept, so there's some mopup I still need to do
(for example, more extensive regression tests, and consider whether it
is better to reuse PLpgSQL_stmt_perform or to invent a new statement
type for this feature, update the docs, etc.)

Any comments?

-Neil




Re: PL/PgSQL "bare" function calls

From
Neil Conway
Date:
On Thu, 2004-09-16 at 00:06, Neil Conway wrote:
> Attached is a proof of concept patch that implements this.

Woops, the patch is really attached this time.

-Neil


Attachment

Re: PL/PgSQL "bare" function calls

From
Tom Lane
Date:
Neil Conway <neilc@samurai.com> writes:
> (3) The parser must distinguish between two cases when it sees an
> unknown word (T_WORD) beginning a statement. The word could be the
> beginning of a SQL statement (stmt_execsql in the grammar), such as:

> UPDATE ...;

> or the name of a function in a function call:

> invoke_func(...);

> The patch currently distinguishes between these cases by looking at the
> next token -- if it is a left parenthesis, the patch assumes it is a
> function call, otherwise it assumes it is a SQL statement. Is this the
> best approach?

That seems fairly unworkable.  For example
SELECT (2,3,4);

is valid SQL.  Also I'm not sure if you can extend this to cope with
schema-qualified function names.
        regards, tom lane


Re: PL/PgSQL "bare" function calls

From
Andrew Dunstan
Date:

Tom Lane wrote:

>Neil Conway <neilc@samurai.com> writes:
>  
>
>>(3) The parser must distinguish between two cases when it sees an
>>unknown word (T_WORD) beginning a statement. The word could be the
>>beginning of a SQL statement (stmt_execsql in the grammar), such as:
>>    
>>
>
>  
>
>>UPDATE ...;
>>    
>>
>
>  
>
>>or the name of a function in a function call:
>>    
>>
>
>  
>
>>invoke_func(...);
>>    
>>
>
>  
>
>>The patch currently distinguishes between these cases by looking at the
>>next token -- if it is a left parenthesis, the patch assumes it is a
>>function call, otherwise it assumes it is a SQL statement. Is this the
>>best approach?
>>    
>>
>
>That seems fairly unworkable.  For example
>
>    SELECT (2,3,4);
>
>is valid SQL.  Also I'm not sure if you can extend this to cope with
>schema-qualified function names.
>
>
>  
>

ISTM that this is being done at the wrong level anyway. I'd like to see 
a facility available in our SQL, e.g.
 CALL foo();

with the restriction that foo() should be declared to return void. Of 
course, that doesn't remove the keyword requirement as Neil wanted, but 
doing that would probably require a lot more work - we'd have to make 
procedures a whole lot closer to  first-class objects.

cheers

andrew


Re: PL/PgSQL "bare" function calls

From
Joe Conway
Date:
Andrew Dunstan wrote:
> ISTM that this is being done at the wrong level anyway. I'd like to see 
> a facility available in our SQL, e.g.
> 
>  CALL foo();
> 
> with the restriction that foo() should be declared to return void. Of 
> course, that doesn't remove the keyword requirement as Neil wanted, but 
> doing that would probably require a lot more work - we'd have to make 
> procedures a whole lot closer to  first-class objects.

I agree with this, except that foo() should be a PROCEDURE, not a FUNCTION.

Joe


Re: PL/PgSQL "bare" function calls

From
Neil Conway
Date:
On Thu, 2004-09-16 at 01:05, Tom Lane wrote:
> That seems fairly unworkable.  For example
> 
>     SELECT (2,3,4);
> 
> is valid SQL.

Good point. The disambiguation algorithm I suggested isn't sufficient,
but I think there ought to be _some_ reasonable algorithm.

>From glancing over the SQL commands, I believe SELECT is the only case
where a SQL statement starts with a T_WORD token followed by a left
parenthesis (correct me if I'm mistaken). If that's the case, one
solution would be to just special-case SELECT: if the name of the
"function" is 'select', we treat it as a SQL statement and not a
function call. Of course, this wouldn't apply if the function name is
double-quoted or schema-qualified.

Another technique would be to delay distinguishing between these two
cases until the function is first invoked; then lookup the function name
in pg_proc, and if a candidate function with that name is found, assume
it's a function call. I don't really like this technique, though.

> Also I'm not sure if you can extend this to cope with
> schema-qualified function names.

Sorry, I forgot to mention that -- yes, that is intended.

-Neil




Re: PL/PgSQL "bare" function calls

From
Neil Conway
Date:
On Thu, 2004-09-16 at 01:19, Andrew Dunstan wrote:
> ISTM that this is being done at the wrong level anyway. I'd like to see 
> a facility available in our SQL, e.g.
> 
>   CALL foo();
> 
> with the restriction that foo() should be declared to return void.

I think these are two distinct issues. The patch I sent along is
intended to make it more natural to invoke functions (and eventually
procedures) from PL/PgSQL, whereas adding support for CALL to SQL is
part of proper support for stored procedures. Gavin and I are hoping to
send a proposal for the latter to -hackers in a few days.

-Neil




Re: PL/PgSQL "bare" function calls

From
Greg Stark
Date:
Neil Conway <neilc@samurai.com> writes:

> whereas adding support for CALL to SQL is part of proper support for stored
> procedures. Gavin and I are hoping to send a proposal for the latter to
> -hackers in a few days.

What is the point of stored procedures being distinct from functions anyways?
Is there any real difference other than the irregular calling syntax? Is there
anything you can't do with functions that you can do with procedures? Or is it
purely a question of satisfying a spec or providing a more Oracle compatible
syntax?

-- 
greg



Re: PL/PgSQL "bare" function calls

From
Gavin Sherry
Date:
On Thu, 16 Sep 2004, Greg Stark wrote:

>
> Neil Conway <neilc@samurai.com> writes:
>
> > whereas adding support for CALL to SQL is part of proper support for stored
> > procedures. Gavin and I are hoping to send a proposal for the latter to
> > -hackers in a few days.
>
> What is the point of stored procedures being distinct from functions anyways?
> Is there any real difference other than the irregular calling syntax? Is there
> anything you can't do with functions that you can do with procedures? Or is it
> purely a question of satisfying a spec or providing a more Oracle compatible
> syntax?

SQL-invoked procedures (ie, stored procedures) differ in two ways from
functions. These are:

1) Procedures do not return a value.

2) Arguments have 'parameter modes'. These modes are: IN - an input
parameter, which has been initialised to some value and is read-only; OUT
- an uninitialised parameter which can be written to; IN OUT - which has
the properties of each of the above.

What this actually means is that you can declare a procedure as follows:

CREATE PROCEDURE foo(IN bar INT, OUT baz INT, OUT bat INT, ...)

That is, a procedure can actually 'return' many values from a call. We can
do this with composite types but, speaking from experience, this can make
migration from PL/SQL just that much harder.

The other thing which SQL-invoked procedures necessitate is support for
the concept of a 'variable'. The reason being that if you use CALL in top
level SQL, you cannot make reference to a field of a relation in any
meaningful way and passing a column reference, for example, as an OUT
parameter does make any sense.


So, SQL2003 defines a few types of variables but the one people may be
most familiar with is the host parameter. This is a named variable which
is referenced as :foo.

I'm putting together a much more detailed email on all this which I hope
to send out in the next few days.

Thanks,

Gavin


Re: PL/PgSQL "bare" function calls

From
Tom Lane
Date:
Neil Conway <neilc@samurai.com> writes:
> On Thu, 2004-09-16 at 01:19, Andrew Dunstan wrote:
>> ISTM that this is being done at the wrong level anyway.

> I think these are two distinct issues.

I think Andrew has a point: why aren't they the same issue?  It would
certainly be no harder to supportfunc( ... );
as a SQL statement than as something allowed only in plpgsql.  I think
it'd be easier to make it work in the full bison grammar than with some
lookahead hack in plpgsql.
        regards, tom lane


Re: PL/PgSQL "bare" function calls

From
Neil Conway
Date:
On Fri, 2004-09-17 at 00:34, Tom Lane wrote:
> I think Andrew has a point: why aren't they the same issue?  It would
> certainly be no harder to support
>     func( ... );
> as a SQL statement than as something allowed only in plpgsql.

If there's a consensus that it is better to modify the main grammar so
that unadorned function calls are legal anywhere, that's fine with me.
If anyone doesn't want this, speak up now.

(Note that we need to support CALL proc(...); in SQL for standards
compliance in any event.)

> I think it'd be easier to make it work in the full bison grammar
> than with some lookahead hack in plpgsql.

Well, as it turns out, it's easy to do in PL/PgSQL as well. The SELECT
issue you mentioned doesn't actually pose a problem, because
   SELECT (2, 3, 4);

is _not_ legal SQL in PL/PgSQL (PL/PgSQL requires SELECT INTO). Also, we
get support for double-quotes and schema-qualified function names for
free, because of how the PL/PgSQL scanner works.

-Neil




Re: PL/PgSQL "bare" function calls

From
Tom Lane
Date:
Neil Conway <neilc@samurai.com> writes:
> On Fri, 2004-09-17 at 00:34, Tom Lane wrote:
>> I think Andrew has a point: why aren't they the same issue?

> (Note that we need to support CALL proc(...); in SQL for standards
> compliance in any event.)

Right.  I'm thinking we could effectively make the CALL keyword optional
(though of course this is just speculation that it can be done without
any parsing conflicts).

> Well, as it turns out, it's easy to do in PL/PgSQL as well. The SELECT
> issue you mentioned doesn't actually pose a problem, because
>     SELECT (2, 3, 4);
> is _not_ legal SQL in PL/PgSQL (PL/PgSQL requires SELECT INTO).

So?  Lookahead won't help you if the INTO is at the end.
        regards, tom lane