mirror of
https://github.com/postgres/postgres.git
synced 2025-11-24 00:23:06 +03:00
Prevent ALTER TYPE/DOMAIN/OPERATOR from changing extension membership.
If recordDependencyOnCurrentExtension is invoked on a pre-existing, free-standing object during an extension update script, that object will become owned by the extension. In our current code this is possible in three cases: * Replacing a "shell" type or operator. * CREATE OR REPLACE overwriting an existing object. * ALTER TYPE SET, ALTER DOMAIN SET, and ALTER OPERATOR SET. The first of these cases is intentional behavior, as noted by the existing comments for GenerateTypeDependencies. It seems like appropriate behavior for CREATE OR REPLACE too; at least, the obvious alternatives are not better. However, the fact that it happens during ALTER is an artifact of trying to share code (GenerateTypeDependencies and makeOperatorDependencies) between the CREATE and ALTER cases. Since an extension script would be unlikely to ALTER an object that didn't already belong to the extension, this behavior is not very troubling for the direct target object ... but ALTER TYPE SET will recurse to dependent domains, and it is very uncool for those to become owned by the extension if they were not already. Let's fix this by redefining the ALTER cases to never change extension membership, full stop. We could minimize the behavioral change by only changing the behavior when ALTER TYPE SET is recursing to a domain, but that would complicate the code and it does not seem like a better definition. Per bug #17144 from Alex Kozhemyakin. Back-patch to v13 where ALTER TYPE SET was added. (The other cases are older, but since they only affect the directly-named object, there's not enough of a problem to justify changing the behavior further back.) Discussion: https://postgr.es/m/17144-e67d7a8f049de9af@postgresql.org
This commit is contained in:
@@ -179,6 +179,13 @@ recordMultipleDependencies(const ObjectAddress *depender,
|
||||
* existed), so we must check for a pre-existing extension membership entry.
|
||||
* Passing false is a guarantee that the object is newly created, and so
|
||||
* could not already be a member of any extension.
|
||||
*
|
||||
* Note: isReplace = true is typically used when updating a object in
|
||||
* CREATE OR REPLACE and similar commands. The net effect is that if an
|
||||
* extension script uses such a command on a pre-existing free-standing
|
||||
* object, the object will be absorbed into the extension. If the object
|
||||
* is already a member of some other extension, the command will fail.
|
||||
* This behavior is desirable for cases such as replacing a shell type.
|
||||
*/
|
||||
void
|
||||
recordDependencyOnCurrentExtension(const ObjectAddress *object,
|
||||
|
||||
Reference in New Issue
Block a user