Thread: Function and Procedure with same signature?

Function and Procedure with same signature?

From
Deepak M
Date:
Hello Hackers,

Folks, When tried to create a function with the same signature as procedure it fails.

postgres=#  create or replace procedure obj1(char) language plpgsql as $$  begin select $1; end; $$;
CREATE PROCEDURE
postgres=# create or replace function obj1(char) returns void language sql as $$ select $1 $$;
ERROR:  cannot change routine kind
DETAIL:  "obj1" is a procedure.

any reason for failures?
Can procedure or function can be defined with the same signature i.e. name and IN arguments ?
as callable for both is different.?

Re: Function and Procedure with same signature?

From
"David G. Johnston"
Date:
On Fri, Feb 9, 2024, 12:05 Deepak M <mahtodeepak05@gmail.com> wrote:
Hello Hackers,

Wrong list, this is for discussions regarding patches.



Folks, When tried to create a function with the same signature as procedure it fails.

That seems like a good hint you cannot do it.  Specifically because they get defined in the same internal catalog within which names must be unique.

David J.

Re: Function and Procedure with same signature?

From
Tom Lane
Date:
"David G. Johnston" <david.g.johnston@gmail.com> writes:
> On Fri, Feb 9, 2024, 12:05 Deepak M <mahtodeepak05@gmail.com> wrote:
>> Folks, When tried to create a function with the same signature as
>> procedure it fails.

> That seems like a good hint you cannot do it.  Specifically because they
> get defined in the same internal catalog within which names must be unique.

Worth noting perhaps that this is actually required by the SQL
standard: per spec, functions and procedures are both "routines"
and share the same namespace, which is necessary so that commands
like DROP ROUTINE are well-defined.

            regards, tom lane



Re: Function and Procedure with same signature?

From
Hannu Krosing
Date:
Hi Tom

On Sat, Feb 10, 2024 at 12:38 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:
>
> "David G. Johnston" <david.g.johnston@gmail.com> writes:
> > On Fri, Feb 9, 2024, 12:05 Deepak M <mahtodeepak05@gmail.com> wrote:
> >> Folks, When tried to create a function with the same signature as
> >> procedure it fails.
>
> > That seems like a good hint you cannot do it.  Specifically because they
> > get defined in the same internal catalog within which names must be unique.

The fact that we currently enforce it this way seems like an
implementation deficiency that should be fixed.

Bringing this up again, as there seems to be no good reason to have
this restriction as there is no place in the call syntax where it
would be unclear if a FUNCTION or a PROCEDURE is used.

And at least Oracle does allow this (and possibly others) so having
this unnecessary restriction in PostgreSQL makes migrations from
Oracle applications where this feature is used needlessly complicated.

> Worth noting perhaps that this is actually required by the SQL
> standard: per spec, functions and procedures are both "routines"
> and share the same namespace,

Can you point me to a place in the standard where it requires all
kinds of ROUTINES to be using the same namespace ?

All I could find was that ROUTINES are either FUNCTIONS, PROCEDURES or
METHODS and then samples of their usage which made clear that all
three are different and usage is disjoint at syntax level.

As for DROP ROUTINE we could just raise an error and recommend using
more specific DROP FUNCTION or DROP PROCEDURE if there is ambiguity.

--------------
Best Regards
Hannu



Re: Function and Procedure with same signature?

From
Tom Lane
Date:
Hannu Krosing <hannuk@google.com> writes:
> On Sat, Feb 10, 2024 at 12:38 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> Worth noting perhaps that this is actually required by the SQL
>> standard: per spec, functions and procedures are both "routines"
>> and share the same namespace,

> Can you point me to a place in the standard where it requires all
> kinds of ROUTINES to be using the same namespace ?

[ digs around a bit... ]  Well, the spec is vaguer about this than
I thought.  It is clear on one thing: 11.60 <SQL-invoked routine>
conformance rules include

    2) Without Feature T341, “Overloading of SQL-invoked functions and
    SQL-invoked procedures”, conforming SQL language shall not
    contain a <schema routine> in which the schema identified by the
    explicit or implicit <schema name> of the <schema qualified
    routine name> includes a routine descriptor whose routine name is
    <schema qualified routine name>.

("<schema routine>" means a CREATE FUNCTION or CREATE PROCEDURE
statement.)

That is, basic SQL doesn't allow you to have two routines with the
same qualified name at all, whether they have different types and
parameter lists or not.  Now the above text is the entire definition
of T341, and it doesn't say just what an implementation that claims
feature T341 is expected to allow.  Looking through the rest of 11.60,
we find

    9) u) The schema identified by the explicit or implicit <schema
    name> of the <specific name> shall not include a routine
    descriptor whose specific name is equivalent to <specific name> or
    a user-defined type descriptor that includes a method
    specification descriptor whose specific name is equivalent to
    <specific name>.

which evidently is describing the base case (with no mention of T341).
We also find

    20) Case:

      a) If R is an SQL-invoked procedure, then S shall not include
      another SQL-invoked procedure whose <schema qualified routine
      name> is equivalent to RN and whose number of SQL parameters is
      PN.

which is a weird halfway measure indeed, and there's no
acknowledgement that this contradicts 9u.  The other arm of the case
is pretty impenetrable prose, but what it appears to be saying is that
you can't create two functions of the same name and same number of
parameters if that would create any call-time ambiguity, that is that
a call could be written that might refer to either.  So I guess these
paras are meant to explain what should happen if T341 is implemented,
but it's far from clear, and certainly their restrictions on
overloading are much stronger than what we allow.

If you look in 10.6 <specific routine designator> (which is what is
referenced by 11.62 <drop routine statement>) you find

    4) If <routine type> specifies ROUTINE, then there shall be
    exactly one SQL-invoked routine in the schema identified by SCN
    whose <schema qualified routine name> is RN such that, for all i,
    1 (one) ≤ i ≤ the number of arguments, when the Syntax Rules of
    Subclause 9.25, “Data type identity”, are applied with the
    declared type of its i-th SQL parameter as TYPE1 and the i-th
    <data type> in the <data type list> of MN as TYPE2, those Syntax
    Rules are satisfied. The <specific routine designator> identifies
    that SQL-invoked routine.

It could be argued that this doesn't prohibit having both a function
and a procedure with the same data type list, only that you can't
write ROUTINE when trying to drop or alter one.  But I think that's
just motivated reasoning.  The paragraphs for <routine type> being
FUNCTION or PROCEDURE are exactly like the above except they say
"exactly one function" or "exactly one procedure".  If you argue that
this text means we must allow functions and procedures with the same
parameter lists, then you are also arguing that we must allow multiple
functions with the same parameter lists, and it's just the user's
tough luck if they need to drop one of them.

A related point is that our tolerance for overloading routine
names isn't unlimited: we don't allow duplicate names with the
same list of input parameters, even if the output parameters are
different.  This is not something that the SQL spec cares to
address, but there are good ambiguity-avoidance reasons for it.
I think limiting overloading so that a ROUTINE specification is
unambiguous is also a good thing.

I remain unexcited about changing our definition of this.
"Oracle allows it" is not something that has any weight in
my view: they have made a bunch of bad design decisions
as well as good ones, and I think this is a bad one.

            regards, tom lane



Re: Function and Procedure with same signature?

From
Hannu Krosing
Date:
On Thu, Mar 7, 2024 at 5:46 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
>
> Hannu Krosing <hannuk@google.com> writes:
> > On Sat, Feb 10, 2024 at 12:38 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> >> Worth noting perhaps that this is actually required by the SQL
> >> standard: per spec, functions and procedures are both "routines"
> >> and share the same namespace,
>
> > Can you point me to a place in the standard where it requires all
> > kinds of ROUTINES to be using the same namespace ?
>
> [ digs around a bit... ]  Well, the spec is vaguer about this than
> I thought.  It is clear on one thing: 11.60 <SQL-invoked routine>
> conformance rules include
...

Thanks for thorough analysis of the standard.

I went and looked at more what other relevant database do in this
space based on their documentation

Tl;DR

* MS SQL Server
   - no overloading allowed anywhere
* MySQL
   - no overloading
* Oracle
   - no overloading at top level
   - overloading and independent namespaces for functions and procedures
* Teradata
   - function overloading allowed
   - not clear from documentation if this also applies procedures
   - function overloading docs does not mention possible clashes with
procedure names anywhere
* DB2
   - function overloading fully supported
   - procedure overloading supported, but only for distinct NUMBER OF ARGUMENTS

I'll try to get access to a Teradata instance to verify the above

So at high level most other Serious Databases
  - do support function overloading
  - keep functions and procedures in separated namespaces

I still think that PostgreSQL having functions and procedures share
the same namespace is an unneeded and unjustified restriction


I plan to do some hands-on testing on Teradata and DB2 to understand it

But my current thinking is that we should not be more restrictive than
others unless there is a strong technical reason for it. And currently
I do not see any.

> It could be argued that this doesn't prohibit having both a function
> and a procedure with the same data type list, only that you can't
> write ROUTINE when trying to drop or alter one.  But I think that's
> just motivated reasoning.  The paragraphs for <routine type> being
> FUNCTION or PROCEDURE are exactly like the above except they say
> "exactly one function" or "exactly one procedure".  If you argue that
> this text means we must allow functions and procedures with the same
> parameter lists, then you are also arguing that we must allow multiple
> functions with the same parameter lists, and it's just the user's
> tough luck if they need to drop one of them.

The main issue is not dropping them, but inability to determine which
one to call.

We already have this in case of two overloaded functions with same
initial argument types and the rest having defaults - when

---
hannuk=# create function get(i int, out o int) begin atomic select i; end;
CREATE FUNCTION
hannuk=# create function get(i int, j int default 0, out o int) begin
atomic select i+j; end;
CREATE FUNCTION
hannuk=# select get(1);
ERROR:  function get(integer) is not unique
LINE 1: select get(1);
               ^
HINT:  Could not choose a best candidate function. You might need to
add explicit type casts.
---

> A related point is that our tolerance for overloading routine
> names isn't unlimited: we don't allow duplicate names with the
> same list of input parameters, even if the output parameters are
> different.

This again has a good reason, as there would be many cases where you
could not decide which one to call

Not allowing overloading based on only return types is common across
all OO languages.

My point is that this does not apply to FUNCTION vs. PROCEDURE as it
is very clear from the CALL syntax which one is meant.

> This is not something that the SQL spec cares to
> address, but there are good ambiguity-avoidance reasons for it.
> I think limiting overloading so that a ROUTINE specification is
> unambiguous is also a good thing.

I think ROUTINE being unambiguous is not e very good goal.

What if next version of standard introduces DROP DATABASE OBJECT ?

> I remain unexcited about changing our definition of this.
> "Oracle allows it" is not something that has any weight in
> my view: they have made a bunch of bad design decisions
> as well as good ones, and I think this is a bad one.

Fully agree that  "Oracle allows it" is a non-argument.

My main point is that there is no strong reason to have objects which
are distinct at syntax level to be in the same namespace.

# Oracle is actually much more restrictive in top level object namespace -

All of the following share the same namespace - [Packages, Private
synonyms, Sequences, Stand-alone procedures, Stand-alone stored
functions, Tables, User-defined operators, User-defined types, Views].
(I guess this makes parser easier to write)

The equivalent in postgreSQL would be [extensions, schemas, tables,
procedures, functions and a few more] all sharing the namespace.

Where Oracle *does* allow overloading is "packaged functions and
procedures" which are probably using a separate parser altogether.

My (wildly speculative) explanation of the above is that when creating
the top-level syntax requirements it was easiest to just not allow any
need to complex determination as the aim was to get the whole thing
out quickly.

Later, when adding the package support there was more time to pay
attention to eas-of-use for developers, so overloading and
non-name-basesd distinction between objects, including functions and
procedures was added.

# DB2- I also checked wher DB2 does and it has a different set of rules

1. FUNCTIONS and METHODS share a namespace in a way that when
overloading the "type instance" of a method is moved to first argument
of function and then the uniqueness of argument list is checked.

2. PROCEDURES can be overloaded but you can not have two procedures
with same NUMBER OF ARGUMENTS irrespective of types

but there is no mention anywhere about signatures having to be
different between FUNCTIONS and PROCEDURES.



Re: Function and Procedure with same signature?

From
Hannu Krosing
Date:
Hi Peter and Tom

Following up on our conversation art pgcon.dev

If I understood correctly Peter has some old patch for splitting the
namespaces which could be resurrected to try to move forward on this ?

Can you share what you did there ?

Also, while at it we should extend the function lookup to support full
"method call syntax" in general, up from one-argument case  so that

SELECT function(a_thing, arg2, arg 2, ...)

could also be called as

SELECT a_thing.function(arg2, arg 2, ...)


--
Hannu



On Mon, Mar 11, 2024 at 12:55 PM Hannu Krosing <hannuk@google.com> wrote:
>
> On Thu, Mar 7, 2024 at 5:46 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> >
> > Hannu Krosing <hannuk@google.com> writes:
> > > On Sat, Feb 10, 2024 at 12:38 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> > >> Worth noting perhaps that this is actually required by the SQL
> > >> standard: per spec, functions and procedures are both "routines"
> > >> and share the same namespace,
> >
> > > Can you point me to a place in the standard where it requires all
> > > kinds of ROUTINES to be using the same namespace ?
> >
> > [ digs around a bit... ]  Well, the spec is vaguer about this than
> > I thought.  It is clear on one thing: 11.60 <SQL-invoked routine>
> > conformance rules include
> ...
>
> Thanks for thorough analysis of the standard.
>
> I went and looked at more what other relevant database do in this
> space based on their documentation
>
> Tl;DR
>
> * MS SQL Server
>    - no overloading allowed anywhere
> * MySQL
>    - no overloading
> * Oracle
>    - no overloading at top level
>    - overloading and independent namespaces for functions and procedures
> * Teradata
>    - function overloading allowed
>    - not clear from documentation if this also applies procedures
>    - function overloading docs does not mention possible clashes with
> procedure names anywhere
> * DB2
>    - function overloading fully supported
>    - procedure overloading supported, but only for distinct NUMBER OF ARGUMENTS
>
> I'll try to get access to a Teradata instance to verify the above
>
> So at high level most other Serious Databases
>   - do support function overloading
>   - keep functions and procedures in separated namespaces
>
> I still think that PostgreSQL having functions and procedures share
> the same namespace is an unneeded and unjustified restriction
>
>
> I plan to do some hands-on testing on Teradata and DB2 to understand it
>
> But my current thinking is that we should not be more restrictive than
> others unless there is a strong technical reason for it. And currently
> I do not see any.
>
> > It could be argued that this doesn't prohibit having both a function
> > and a procedure with the same data type list, only that you can't
> > write ROUTINE when trying to drop or alter one.  But I think that's
> > just motivated reasoning.  The paragraphs for <routine type> being
> > FUNCTION or PROCEDURE are exactly like the above except they say
> > "exactly one function" or "exactly one procedure".  If you argue that
> > this text means we must allow functions and procedures with the same
> > parameter lists, then you are also arguing that we must allow multiple
> > functions with the same parameter lists, and it's just the user's
> > tough luck if they need to drop one of them.
>
> The main issue is not dropping them, but inability to determine which
> one to call.
>
> We already have this in case of two overloaded functions with same
> initial argument types and the rest having defaults - when
>
> ---
> hannuk=# create function get(i int, out o int) begin atomic select i; end;
> CREATE FUNCTION
> hannuk=# create function get(i int, j int default 0, out o int) begin
> atomic select i+j; end;
> CREATE FUNCTION
> hannuk=# select get(1);
> ERROR:  function get(integer) is not unique
> LINE 1: select get(1);
>                ^
> HINT:  Could not choose a best candidate function. You might need to
> add explicit type casts.
> ---
>
> > A related point is that our tolerance for overloading routine
> > names isn't unlimited: we don't allow duplicate names with the
> > same list of input parameters, even if the output parameters are
> > different.
>
> This again has a good reason, as there would be many cases where you
> could not decide which one to call
>
> Not allowing overloading based on only return types is common across
> all OO languages.
>
> My point is that this does not apply to FUNCTION vs. PROCEDURE as it
> is very clear from the CALL syntax which one is meant.
>
> > This is not something that the SQL spec cares to
> > address, but there are good ambiguity-avoidance reasons for it.
> > I think limiting overloading so that a ROUTINE specification is
> > unambiguous is also a good thing.
>
> I think ROUTINE being unambiguous is not e very good goal.
>
> What if next version of standard introduces DROP DATABASE OBJECT ?
>
> > I remain unexcited about changing our definition of this.
> > "Oracle allows it" is not something that has any weight in
> > my view: they have made a bunch of bad design decisions
> > as well as good ones, and I think this is a bad one.
>
> Fully agree that  "Oracle allows it" is a non-argument.
>
> My main point is that there is no strong reason to have objects which
> are distinct at syntax level to be in the same namespace.
>
> # Oracle is actually much more restrictive in top level object namespace -
>
> All of the following share the same namespace - [Packages, Private
> synonyms, Sequences, Stand-alone procedures, Stand-alone stored
> functions, Tables, User-defined operators, User-defined types, Views].
> (I guess this makes parser easier to write)
>
> The equivalent in postgreSQL would be [extensions, schemas, tables,
> procedures, functions and a few more] all sharing the namespace.
>
> Where Oracle *does* allow overloading is "packaged functions and
> procedures" which are probably using a separate parser altogether.
>
> My (wildly speculative) explanation of the above is that when creating
> the top-level syntax requirements it was easiest to just not allow any
> need to complex determination as the aim was to get the whole thing
> out quickly.
>
> Later, when adding the package support there was more time to pay
> attention to eas-of-use for developers, so overloading and
> non-name-basesd distinction between objects, including functions and
> procedures was added.
>
> # DB2- I also checked wher DB2 does and it has a different set of rules
>
> 1. FUNCTIONS and METHODS share a namespace in a way that when
> overloading the "type instance" of a method is moved to first argument
> of function and then the uniqueness of argument list is checked.
>
> 2. PROCEDURES can be overloaded but you can not have two procedures
> with same NUMBER OF ARGUMENTS irrespective of types
>
> but there is no mention anywhere about signatures having to be
> different between FUNCTIONS and PROCEDURES.