On Thu, Feb 17, 2022 at 6:17 PM Tom Lane <tgl@xxxxxxxxxxxxx> wrote:
"David G. Johnston" <david.g.johnston@xxxxxxxxx> writes:
> Maybe, but the behavior does exist but is bugged in its current state.
> Whether it is advisable for users to use this feature is immaterial, the
> bug needs to be fixed so that is works as documented for those that choose
> to do so.
There is no bug here; it's operating as designed and documented.
Maybe the docs need some refinement.
We should just say that ALTER FUNCTION ALTER DEPENDS ON makes the target function/procedure a (transient?) member of the extension and it will be dropped when the extension be dropped.
"This form marks the function as a member of the named extension, or removes such membership if NO is specified. As a consequence of membership the restrict clause of the DROP EXTENSION (link) command will ignore this function (if applicable) and it will always be dropped along with all other members of the extension."
Different terminology may be better, but we'd want to update DROP EXTENSION to match. Member is already used there.
(continued ranting below)
The way this is intended to work is that if you have a function that
depends on an extension -- say by using an extension-defined data
type -- then the *default* behavior is that you'd have to say CASCADE
in order to drop the extension. The point of the ALTER DEPENDS ON
functionality is to declare that you don't want that behavior, but
would like the function to go away silently (ie, without CASCADE)
when the extension is dropped.
I don't get why we bothered then. We have to now ignore any possibility of using RESTRICT here in order to avoid having the DROP EXTENSION user add CASCADE to their command? At least the "black box" reason added a capability to the system that wasn't already available.
While writing the above, and considering the stated goal of "avoid having to specify cascade (i.e., bypass restrict)", I figured I'd test:
test=# create extension cube;
CREATE EXTENSION
test=# create function myfunc(int) returns int as 'select cube_dim(cube($1,$1))' language sql;
CREATE FUNCTION
test=# alter function myfunc(int) depends on extension cube;
test=# drop extension cube;
DROP EXTENSION
CREATE EXTENSION
test=# create function myfunc(int) returns int as 'select cube_dim(cube($1,$1))' language sql;
CREATE FUNCTION
test=# alter function myfunc(int) depends on extension cube;
test=# drop extension cube;
DROP EXTENSION
--myfunc(int) no longer exists even though absent the membership it would have, regardless of whether cascade or restrict was specified. So it's not just avoiding the specification of CASCADE that is happening here.
That only partially matches the declared use case, you get the free drop without having to specify cascade but the behavior you were trying to avoid - the restrict error - never happened anyway.
That's acting as designed and we're not going to change it
for fear of breaking existing use-cases.
Fair.
However, maybe
the use of "automatic" in the documentation isn't sufficiently
clear.
Now, if you have a function that has some internal,
not-visible-to-the-dependency-system extension dependency,
it's true that you don't get any protection against that:
In any case, ALTER DEPENDS ON EXTENSION is not meant to provide
protection against that scenario.
Well, the documentation's use of the word "depend" instead of "member" led me and the OP to reasonably conclude that it was in fact designed to handle just this situation. I'd argue the fact that it doesn't is a POLA violation given that, as I said upthread, we already have a way to add members to extensions. Though upon further thought that particular form has permissions issues that this method is capable of bypassing.
The best thing we have for
one-off internal dependencies right now is that new-style SQL
functions do expose them:
I don't really mind that we lack this ability overall - and the fact that the expected behavior would have only solved it for extensions did seem a bit odd, but not unreasonable. Especially if, for instance, the extension itself was creating these functions instead of some external-to-the-extension code. Solving the black-box problem there made perfect sense.
David J.