Thread: Drop all overloads of a function without knowing parameter types

Drop all overloads of a function without knowing parameter types

From
Evan Martin
Date:
Hi All,

Is there any easy way to drop a function (all overloads of it) without knowing the parameter types? If not, it would be good to see it added.

When I change a function definition I just want to run the SQL script that defines it and have any existing function replaced. CREATE OR REPLACE FUNCTION does this - except if the parameter types, or even names, have changed. If this SO thread is correct, it's quite tricky to drop existing functions without knowing the parameter types:

http://stackoverflow.com/questions/7622908/drop-function-without-knowing-the-number-type-of-parameters

I'd like to see a much easier way. Either something like "DROP FUNCTION name ALL" or a system function that does the same thing or at least a built-in, "supported" way to get the signature of all the overloads, so they can be dropped one by one.

Regards,

Evan

Re: Drop all overloads of a function without knowing parameter types

From
Tom Lane
Date:
Evan Martin <postgresql@realityexists.net> writes:
> Is there any easy way to drop a function (all overloads of it) without
> knowing the parameter types?

Something along the lines of

do $$
declare fname text;
begin
for fname in select oid::regprocedure from pg_proc where proname = 'foo' loop
  execute 'drop function ' || fname;
end loop;
end$$;

Adjust WHERE condition to taste.

> If not, it would be good to see it added.

People periodically ask for extensions flavored more or less like this,
but I'm suspicious of building any such thing into the core.  There's too
little commonality in the exact conditions they want to search on.
Leaving it at the level of a scripting problem, as above, allows arbitrary
customization of the search condition.

            regards, tom lane


Re: Drop all overloads of a function without knowing parameter types

From
Evan Martin
Date:
Thanks for that "oid::regprocedure" trick! A query like this is fairly
simple once you know it, but completely non-obvious when you don't.

I'm not sure what conditions others want to search on (couldn't find it
in the list archives), but "by qualified function name" seems like the
obvious one. If you don't wish to add that to the core, how about a
system function that does this and is mentioned in the documentation for
DROP FUNCTION? That way, if people have other criteria they can find the
function, look at its source and adapt it to their needs. If you don't
want to add a function, either, it would be good to at least document
this (on the DROP FUNCTION page). Something like "Note: DROP FUNCTION
does not allow you to drop a function without knowing its argument
types, but you can use the following script to drop all overloads of a
given function name..."

Regards,

Evan

On 03/02/2014 19:09, Tom Lane wrote:
> Evan Martin <postgresql@realityexists.net> writes:
>> Is there any easy way to drop a function (all overloads of it) without
>> knowing the parameter types?
> Something along the lines of
>
> do $$
> declare fname text;
> begin
> for fname in select oid::regprocedure from pg_proc where proname = 'foo' loop
>    execute 'drop function ' || fname;
> end loop;
> end$$;
>
> Adjust WHERE condition to taste.
>
>> If not, it would be good to see it added.
> People periodically ask for extensions flavored more or less like this,
> but I'm suspicious of building any such thing into the core.  There's too
> little commonality in the exact conditions they want to search on.
> Leaving it at the level of a scripting problem, as above, allows arbitrary
> customization of the search condition.
>
>             regards, tom lane
>
>



Re: Drop all overloads of a function without knowing parameter types

From
Sergey Konoplev
Date:
On Mon, Feb 3, 2014 at 10:09 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> People periodically ask for extensions flavored more or less like this,
> but I'm suspicious of building any such thing into the core.  There's too
> little commonality in the exact conditions they want to search on.
> Leaving it at the level of a scripting problem, as above, allows arbitrary
> customization of the search condition.

I understand the POV of both Evan and you here. However, I think that
there might be a good solution for this particular case - to allow
dropping functions by name only if it has the only signature, but if
there are 2 or more signatures then print an error specifying all the
forms of the function, eg.:

ERROR: Can not drop function 'foo' because it has more then one
signature: foo(integer), foo(text).

I am sure It would simplify life significantly.

--
Kind regards,
Sergey Konoplev
PostgreSQL Consultant and DBA

http://www.linkedin.com/in/grayhemp
+1 (415) 867-9984, +7 (901) 903-0499, +7 (988) 888-1979
gray.ru@gmail.com


Re: Drop all overloads of a function without knowing parameter types

From
Alvaro Herrera
Date:
Sergey Konoplev escribió:
> On Mon, Feb 3, 2014 at 10:09 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> > People periodically ask for extensions flavored more or less like this,
> > but I'm suspicious of building any such thing into the core.  There's too
> > little commonality in the exact conditions they want to search on.
> > Leaving it at the level of a scripting problem, as above, allows arbitrary
> > customization of the search condition.
>
> I understand the POV of both Evan and you here. However, I think that
> there might be a good solution for this particular case - to allow
> dropping functions by name only if it has the only signature, but if
> there are 2 or more signatures then print an error specifying all the
> forms of the function, eg.:
>
> ERROR: Can not drop function 'foo' because it has more then one
> signature: foo(integer), foo(text).

But that doesn't solve Evan's request.  He would want both functions
gone, not an error.

--
Álvaro Herrera                http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services


Re: Drop all overloads of a function without knowing parameter types

From
Sergey Konoplev
Date:
On Tue, Feb 4, 2014 at 8:35 AM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
> Sergey Konoplev escribió:
>> On Mon, Feb 3, 2014 at 10:09 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> > People periodically ask for extensions flavored more or less like this,
>> > but I'm suspicious of building any such thing into the core.  There's too
>> > little commonality in the exact conditions they want to search on.
>> > Leaving it at the level of a scripting problem, as above, allows arbitrary
>> > customization of the search condition.
>>
>> I understand the POV of both Evan and you here. However, I think that
>> there might be a good solution for this particular case - to allow
>> dropping functions by name only if it has the only signature, but if
>> there are 2 or more signatures then print an error specifying all the
>> forms of the function, eg.:
>>
>> ERROR: Can not drop function 'foo' because it has more then one
>> signature: foo(integer), foo(text).
>
> But that doesn't solve Evan's request.  He would want both functions
> gone, not an error.

I was writing about some kind of a compromise.

--
Kind regards,
Sergey Konoplev
PostgreSQL Consultant and DBA

http://www.linkedin.com/in/grayhemp
+1 (415) 867-9984, +7 (901) 903-0499, +7 (988) 888-1979
gray.ru@gmail.com


Re: Drop all overloads of a function without knowing parameter types

From
Dmitriy Igrishin
Date:



2014-02-03 Evan Martin <postgresql@realityexists.net>:
Thanks for that "oid::regprocedure" trick! A query like this is fairly simple once you know it, but completely non-obvious when you don't.

I'm not sure what conditions others want to search on (couldn't find it in the list archives), but "by qualified function name" seems like the obvious one. If you don't wish to add that to the core, how about a system function that does this and is mentioned in the documentation for DROP FUNCTION? That way, if people have other criteria they can find the function, look at its source and adapt it to their needs. If you don't want to add a function, either, it would be good to at least document this (on the DROP FUNCTION page). Something like "Note: DROP FUNCTION does not allow you to drop a function without knowing its argument types, but you can use the following script to drop all overloads of a given function name..."
The function name (as well as the name of any other database object, such as view or rule)
can have a prefix or suffix. (We are prefix our functions with the class name to consider
them as methods in terms of object-oriented design.) Thus, such system function
for dropping functions should accept something like a regular expression as
it argument.
Moreover, how about other database objects which can be dropped: views, triggers, rules,
domains etc etc. For completeness it is necessary the existence of system functions
for dropping these objects too.
So, I am with Tom here.



--
// Dmitry.

Re: Drop all overloads of a function without knowing parameter types

From
Sergey Konoplev
Date:
On Tue, Feb 4, 2014 at 8:35 AM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
> Sergey Konoplev escribió:
>> On Mon, Feb 3, 2014 at 10:09 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> > People periodically ask for extensions flavored more or less like this,
>> > but I'm suspicious of building any such thing into the core.  There's too
>> > little commonality in the exact conditions they want to search on.
>> > Leaving it at the level of a scripting problem, as above, allows arbitrary
>> > customization of the search condition.
>>
>> I understand the POV of both Evan and you here. However, I think that
>> there might be a good solution for this particular case - to allow
>> dropping functions by name only if it has the only signature, but if
>> there are 2 or more signatures then print an error specifying all the
>> forms of the function, eg.:
>>
>> ERROR: Can not drop function 'foo' because it has more then one
>> signature: foo(integer), foo(text).
>
> But that doesn't solve Evan's request.  He would want both functions
> gone, not an error.

Yes, I was mostly writing about the general case rather than about the OP's one.

--
Kind regards,
Sergey Konoplev
PostgreSQL Consultant and DBA

http://www.linkedin.com/in/grayhemp
+1 (415) 867-9984, +7 (901) 903-0499, +7 (988) 888-1979
gray.ru@gmail.com


Re: Drop all overloads of a function without knowing parameter types

From
Tom Lane
Date:
Sergey Konoplev <gray.ru@gmail.com> writes:
> On Tue, Feb 4, 2014 at 8:35 AM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
>> Sergey Konoplev escribi�:
>>> On Mon, Feb 3, 2014 at 10:09 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>>>> People periodically ask for extensions flavored more or less like this,
>>>> but I'm suspicious of building any such thing into the core.  There's too
>>>> little commonality in the exact conditions they want to search on.
>>>> Leaving it at the level of a scripting problem, as above, allows arbitrary
>>>> customization of the search condition.

>>> I understand the POV of both Evan and you here. However, I think that
>>> there might be a good solution for this particular case - to allow
>>> dropping functions by name only if it has the only signature, but if
>>> there are 2 or more signatures then print an error specifying all the
>>> forms of the function, eg.:
>>>
>>> ERROR: Can not drop function 'foo' because it has more then one
>>> signature: foo(integer), foo(text).

>> But that doesn't solve Evan's request.  He would want both functions
>> gone, not an error.

> I was writing about some kind of a compromise.

My point was precisely that a compromise would satisfy nobody.  There
would be a few cases for which it was Exactly The Right Thing, and many
more for which you'd still need to learn how to do the EXECUTE trick.

I wonder whether we shouldn't address this by adding a few examples
of that type of trick to the docs.  Not sure where, though ...

            regards, tom lane


Re: Drop all overloads of a function without knowing parameter types

From
David Johnston
Date:
Tom Lane-2 wrote
> I wonder whether we shouldn't address this by adding a few examples
> of that type of trick to the docs.  Not sure where, though ...

Probably the Wiki would be a better place to put this kind of material.  A
link to there from "21. Managing Database" would seem to be most
appropriate.

Adding another section to chapter III is a possibility as well.  Something
like:  "XX. Database Scripting".  It could point to the Wiki as well as
cross-reference both the "System Catalogs" section and the "PL/pgSQL[...]"
section with a brief overview of the kinds of activities that are not
provided for by standard internal functions or SQL commands.

David J.



--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Drop-all-overloads-of-a-function-without-knowing-parameter-types-tp5790367p5790515.html
Sent from the PostgreSQL - general mailing list archive at Nabble.com.


Re: Drop all overloads of a function without knowing parameter types

From
Evan Martin
Date:
In a nutshell: I think the difficulty of dropping functions is inconsistent with the difficulty of dropping other objects and I'd like to see this inconsistency fixed.

So I don't agree with the suggestion of matching function names using a regex, since that's not supported for other types of objects. To explain the use case a little better:

I maintain a set of scripts that can create a database from scratch. Sometimes I also need to update an existing database to the latest version. For tables this obviously requires separate scripts to preserve data, but views, rules and triggers can be updated just by using CREATE OR REPLACE in the DB creation scripts. Functions can almost be updated this way, but not quite. Function arguments may change over time. The script that creates them doesn't know and doesn't care which old version of the function already exists, if any - it just wants to replace it.

I'm sure this is not an uncommon scenario. Current options for the user are:

1) Maintain a list of DROP IF EXISTS statements for all function signatures that ever existed.
2) Roll their own code to find any existing functions, which is not simple as the SO thread I mentioned shows. 2 users with over 20K reputation answered and nobody knew the "oid:regprocedure" trick.
3) Since yesterday: find Tom Lane's post in this list.

I'd just like to see an easy to use, reliable and easy to discover way to do this. The general "execute trick" is good to know, but a user shouldn't resort to it for something that (from the user's point of view) is as simple as DROP VIEW or DROP INDEX.

If nothing else, the manual page for DROP FUNCTION seems like a good place to document this, since that's the obvious place where anyone would look to find out how to drop a function.

Regards,

Evan

On 04/02/2014 17:48, Tom Lane wrote:
I was writing about some kind of a compromise.
My point was precisely that a compromise would satisfy nobody.  There
would be a few cases for which it was Exactly The Right Thing, and many
more for which you'd still need to learn how to do the EXECUTE trick.

I wonder whether we shouldn't address this by adding a few examples
of that type of trick to the docs.  Not sure where, though ...
		regards, tom lane


Re: Drop all overloads of a function without knowing parameter types

From
David Johnston
Date:
Evan Martin wrote
> In a nutshell: I think the difficulty of dropping functions is
> inconsistent with the difficulty of dropping other objects and I'd like
> to see this inconsistency fixed.
>
> So I don't agree with the suggestion of matching function names using a
> regex, since that's not supported for other types of objects. To explain
> the use case a little better:
>
> I maintain a set of scripts that can create a database from scratch.
> Sometimes I also need to update an existing database to the latest
> version. For tables this obviously requires separate scripts to preserve
> data, but views, rules and triggers can be updated just by using CREATE
> OR REPLACE in the DB creation scripts. Functions can /almost/ be updated
> this way, but not quite.
> Function arguments may change over time.

No, they cannot.  If the arguments change you are dealing with an entirely
new object.  And often you end up keeping the old function around for
backward-compatibility.  The two objects have their own life-cycle that they
should be in full control of and not subjected to external objects dropping
them because they share the same name.

For an analogy how would your scripts deal with.

ALTER TABLE table1 RENAME table2;

This is exactly what you are effectively doing when you go and change a
function signature though there is no "RENAME" action available for
functions.


> The script that creates them doesn't know and doesn't care /which/ old
> version of the function already exists, if any - it just wants to
> replace it.
>
> I'm sure this is not an uncommon scenario. Current options for the user
> are:
>
> 1) Maintain a list of DROP IF EXISTS statements for all function
> signatures that ever existed.
> 2) Roll their own code to find any existing functions, which is not
> simple as the SO thread
> <stackoverflow.com/questions/7622908/drop-function-without-knowing-the-number-type-of-parameters>
> I mentioned shows. 2 users with over 20K reputation answered and nobody
> knew the "oid:regprocedure" trick.
> 3) Since yesterday: find Tom Lane's post in this list.
>
> I'd just like to see an easy to use, reliable and easy to discover way
> to do this. The general "execute trick" is good to know, but a user
> shouldn't resort to it for something that (from the user's point of
> view) is as simple as DROP VIEW or DROP INDEX.
>
> If nothing else, the manual page for DROP FUNCTION seems like a good
> place to document this, since that's the obvious place where anyone
> would look to find out how to drop a function.
>
> Regards,
>
> Evan
>
> On 04/02/2014 17:48, Tom Lane wrote:
>>> I was writing about some kind of a compromise.
>> My point was precisely that a compromise would satisfy nobody.  There
>> would be a few cases for which it was Exactly The Right Thing, and many
>> more for which you'd still need to learn how to do the EXECUTE trick.
>>
>> I wonder whether we shouldn't address this by adding a few examples
>> of that type of trick to the docs.  Not sure where, though ...
>>
>>             regards, tom lane
>>
>>

function(text, text) is not the same as function(text, integer).  If you no
longer are supporting function(text, text) in your current database version
you should have a "DROP FUNCTION function(text, text)" command somewhere in
your "upgrade routine".  This is partly a learning exercise in how things
are.  DROP FUNCTION function; better continue to fail as not having
specified a correct function name since the signature IS part of the name
and defines a unique and self-contained database object.

However, I'll concede that since functions are the only class of object that
allow for "name overloading" providing a built-in ability to "DROP ALL
FUNCTION WITH BASE NAME function" - excluding those in pg_catalog - would
have value.  No regular expressions just a simple name-without-args literal
match.

If you are doing version controlled upgrades you should not be using this
function but during the R&D phase I can imagine it would come in quite
handy.

David J.




--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Drop-all-overloads-of-a-function-without-knowing-parameter-types-tp5790367p5790522.html
Sent from the PostgreSQL - general mailing list archive at Nabble.com.


Re: Drop all overloads of a function without knowing parameter types

From
Alvaro Herrera
Date:
Sergey Konoplev escribió:

> >> I understand the POV of both Evan and you here. However, I think that
> >> there might be a good solution for this particular case - to allow
> >> dropping functions by name only if it has the only signature, but if
> >> there are 2 or more signatures then print an error specifying all the
> >> forms of the function, eg.:
> >>
> >> ERROR: Can not drop function 'foo' because it has more then one
> >> signature: foo(integer), foo(text).

> I was writing about some kind of a compromise.

I wonder if it'd work to have some way to specify wildcards for function
arguments.  For instance, if you say
    DROP FUNCTION foo('*');
all versions with a single argument are dropped;
    DROP FUNCTION foo('*', '*');
drops all versions with two arguments.  If you do
    DROP FUNCTION foo('*+');
then all versions are dropped regardless of number of arguments.

Maybe some kind of keyword instead of the funny-looking operators would
work better --- not proposing that exact syntax, only the general idea.

--
Álvaro Herrera                http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services


Re: Re: Drop all overloads of a function without knowing parameter types

From
Stephen Frost
Date:
* David Johnston (polobo@yahoo.com) wrote:
> Evan Martin wrote
> > So I don't agree with the suggestion of matching function names using a
> > regex, since that's not supported for other types of objects. To explain
> > the use case a little better:

Uh, we could add such support, which might be very handy.

> > I maintain a set of scripts that can create a database from scratch.
> > Sometimes I also need to update an existing database to the latest
> > version. For tables this obviously requires separate scripts to preserve
> > data, but views, rules and triggers can be updated just by using CREATE
> > OR REPLACE in the DB creation scripts. Functions can /almost/ be updated
> > this way, but not quite.
> > Function arguments may change over time.
>
> No, they cannot.  If the arguments change you are dealing with an entirely
> new object.

Yeah, for better or worse, we allow function overloading and we're not
going to be dropping that.

    Thanks,

        Stephen

Attachment

Re: Re: Drop all overloads of a function without knowing parameter types

From
Evan Martin
Date:
On 04/02/2014 19:56, David Johnston wrote:
> No, they cannot.  If the arguments change you are dealing with an entirely
> new object.  And often you end up keeping the old function around for
> backward-compatibility.
Of course, I understand that it's a different object, technically, but
from the user point of view it may replace the old function. Whether it
does or not depends on your upgrade strategy, but in our case it always
does. I'm making an argument from the point of view of usability here,
not based on the technicalities of what is the "same" object. And I also
agree that users should be aware that overloaded functions are different
objects. I think there is no danger of anyone missing that fact, even if
support for dropping all overloads was added, because it would still
require different syntax. The usual CREATE OR REPLACE syntax still
wouldn't work.

> For an analogy how would your scripts deal with.
>
> ALTER TABLE table1 RENAME table2;
>
They would deal with it by doing:

DROP TABLE IF EXISTS table1;
CREATE TABLE table2 (...);

... if it wasn't for the fact that this would lose all data in the
table. For functions this is not a problem.

(Of course, you could always add support for "ALTER TABLE table1 RENAME
table2 IF NOT ALREADY RENAMED FROM table1" but the use case is not as
strong. ;))

> However, I'll concede that since functions are the only class of object that
> allow for "name overloading" providing a built-in ability to "DROP ALL
> FUNCTION WITH BASE NAME function" - excluding those in pg_catalog - would
> have value.  No regular expressions just a simple name-without-args literal
> match.
>
> If you are doing version controlled upgrades you should not be using this
> function but during the R&D phase I can imagine it would come in quite
> handy.
>
Thank you - that's what I meant. It would make dropping functions
consistent with dropping other objects. Whether users then use this in
production or only in development is up to them.


Re: Re: Drop all overloads of a function without knowing parameter types

From
Andrew Sullivan
Date:
On Tue, Feb 04, 2014 at 10:56:28AM -0800, David Johnston wrote:
> If you are doing version controlled upgrades you should not be using this
> function but during the R&D phase I can imagine it would come in quite
> handy.

Or add Tom's remarks to a little corner of contrib/, or as Tom
suggested, the docs, though I don't have a clear way to state it.

One could actually add a reference to Tom's note to the comments
section of the docs so that some mroe thinking could go into how to
putting words about this in the docs.

I agree that the function signature is part of the function.  This is
strange to people because when you're developing it's normal to think
of functionname(args) as the thing you're changing, but in a system
that allows overloading like Postgres that's not really true for
production.

A

--
Andrew Sullivan
ajs@crankycanuck.ca