> [email protected] wrote:
>
> It's not a member though; there's a different syntax for that (ALTER
> EXTENSION name ADD member_object). The differences are a bit subtle, but for
> example making the function an extension member would change how pg_dump
> treats it.
I read, and re-read, the six replies from Tom and David that came in yesterday
(17-Feb) after my most recent turn in this thread. Here’s what I’ve concluded:
(1) Tom has ruled that there are no implementation bugs in this space. This
means that all the functionality that the tests that I have done (and
presumably could do) reflect the intended behavior.
(2) The reasons for deciding on at least some of this behavior are lost in the
mists of time. But anyway, no implementation changes will be made.
(3) I, for one, found it very hard to build an overall, predictive, mental
model from the documentation. But, then, you’ve seen (somewhat to my
embarrassment) that I often have such difficulties. I’m grateful therefore,
especially in these work-from-home days, for the answers that my questions to
this list have received.
(4) The clue to the whole thing is the semantics of the LoV for "pg_depend.
deptype" (see below) — but you all kept this a secret from me!
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
Here’s some detailed observations and responses to what Tom and David wrote:
> David: « An extension neither depends on nor is dependent upon its members. »
This must be a typo: "depends on" and "is dependent upon" mean the same. I’m
guessing that this was meant: « An extension neither depends on nor is
*depended* upon by its members. » If so, then it’s wrong. Yes: an extension
doesn’t depend on its members. This query (which runs without error) shows that
an extension depends upon only the schema nominated by "create extension… with
schema…".
select nspname from
pg_namespace
where oid = (
select refobjid
from pg_catalog.pg_depend
where objid = (
select oid
from pg_catalog.pg_extension
where extname::text = $1));
But no: the objects do depend upon the extension that creates them, as this
query shows:
prepare dependents_on_extension(text) as
select
p.proname::text as dependent_name,
'subprogram'::text as dependent_type,
e.extname::text as parent_name,
'extension'::text as parent_type,
d.deptype::text as dependecy_type
from
pg_catalog.pg_proc p
inner join
pg_catalog.pg_depend d
on p.oid = d.objid
inner join
pg_catalog.pg_extension e
on d.refobjid = e.oid
where e.extname::text = $1;
I tried it for the "cube" extension and it listed out the same function names
that "\df the_schema.*" lists (where "the_schema" is the provided argument for
the "with schema" clause of "create extension".
Moreover, it showed that the "dependency_type" is 'e' for the objects that
creating the extension brings. And the section "52.18. pg_depend" says this
about that value:
«
DEPENDENCY_EXTENSION (e) — The dependent object is a member of the extension
that is the referenced object (see pg_extension). The dependent object can be
dropped only via DROP EXTENSION on the referenced object. Functionally this
dependency type acts the same as an INTERNAL dependency, but it's kept separate
for clarity and to simplify pg_dump.
»
and it says this about "internal":
«
DEPENDENCY_INTERNAL (i) — The dependent object was created as part of creation
of the referenced object, and is really just a part of its internal
implementation. A direct DROP of the dependent object will be disallowed
outright (we'll tell the user to issue a DROP against the referenced object,
instead). A DROP of the referenced object will result in automatically dropping
the dependent object whether CASCADE is specified or not…
»
Seems to me that the account of the "create extension" DDL would benefit from
words to this effect and an x-ref to the account of "pg_depend"
In my tests, I installed the "cube" extension in schema "cube". Then I did this:
alter function cube.cube_cmp(cube.cube, cube.cube)depends on extension cube;
And then I repeated the query that I showed above. Now the results included
these two rows:
dependent_name | dependent_type | parent_name | parent_type |
dependecy_type
--------------------+----------------+-------------+-------------+----------------
cube_cmp | subprogram | cube | extension | e
cube_cmp | subprogram | cube | extension | x
Here's what the doc says about the new result:
«
DEPENDENCY_AUTO_EXTENSION (x) — The dependent object is not a member of the
extension that is the referenced object (and so it should not be ignored by
pg_dump), but it cannot function without the extension and should be
auto-dropped if the extension is. The dependent object may be dropped on its
own as well. Functionally this dependency type acts the same as an AUTO
dependency, but it's kept separate for clarity and to simplify pg_dump.
»
This is the clue to everything that's been confusing me. But nobody mentioned
"pg_depend. deptype"!
After reading and re-reading the accounts for all values of "pg_depend.
deptype" I saw, eventually, that this means that "drop extension" will always
silently remove all of its dependents of type 'x' whatever you might say about
"restrict" (or "cascade").
B.t.w., a query like I show above but for the "parent_type" (user-defined) type
shows that a function with an argument whose data type is such a user-defined)
type depends on that type with deptype = 'n'.
«
DEPENDENCY_NORMAL (n)
A normal relationship between separately-created objects. The dependent object
can be dropped without affecting the referenced object. The referenced object
can only be dropped by specifying CASCADE, in which case the dependent object
is dropped, too. Example: a table column has a normal dependency on its data
type.
»
A slow learner like me would always appreciate a commentary, with
self-contained runnable examples along the lines of what I've sketched here, to
accompany every maximally terse definitional account. But I appreciate that the
PG Doc doesn't aim to do this.