Thread: Missing pg_depend entries for constraints created by extensions (deptype 'e')
Missing pg_depend entries for constraints created by extensions (deptype 'e')
From
"Joel Jacobson"
Date:
Hi hackers, Foreign key constraints created during CREATE EXTENSION lack a pg_depend entry with deptype='e'. Looking at the code, I found that CreateConstraintEntry() in src/backend/catalog/pg_constraint.c does not call recordDependencyOnCurrentExtension(), unlike most other CREATE functions. This seems to affect all constraint types created through CreateConstraintEntry. I stumbled upon this issue when trying to query all database objects belonging to an extension using: SELECT * FROM pg_depend WHERE deptype = 'e' AND refobjid = <ext_oid> AND refclassid = 'pg_extension'::regclass Is this omission intentional? I couldn't find any documentation or code comments explaining why constraints should not be extension members. Currently, it seems impossible to distinguish between: - Constraints created by CREATE EXTENSION - Constraints added manually to extension tables after extension creation Would it make sense to add recordDependencyOnCurrentExtension() to CreateConstraintEntry()? Or is there a specific reason why constraints should be handled differently from other extension objects? /Joel
Attachment
Re: Missing pg_depend entries for constraints created by extensions (deptype 'e')
From
"Joel Jacobson"
Date:
On Sat, May 31, 2025, at 23:56, Tom Lane wrote: > "Joel Jacobson" <joel@compiler.org> writes: >> Foreign key constraints created during CREATE EXTENSION >> lack a pg_depend entry with deptype='e'. > > Why would it be a sensible thing for an extension to create a > foreign-key constraint on table(s) that it didn't itself create? That wouldn't make any sense, no. > (If it did create them, the indirect dependency seems sufficient.) The indirect dependency might seem sufficient initially but becomes problematic when needing to distinguish between objects originally created by an extension and those manually added later by users. Consider this scenario: 1. A company modularizes its system using extensions. Each extension defines tables, indexes, and constraints necessary for its operation. 2. During an emergency (e.g., slow queries or high load), a DBA quickly adds an index directly to an extension-defined table as a temporary fix but neglects to document this change in the extension upgrade scripts. 3. Later, during a PostgreSQL upgrade using pg_dump / pg_restore: - Extension objects are correctly skipped by pg_dump. - However, the manually-added index, indistinguishable from extension-created indexes due to the lack of explicit deptype='e' marking, is also unintentionally skipped. - Consequently, the manually-added index is silently lost. Currently, neither indexes nor constraints have explicit deptype='e' entries. To reliably detect manually-added objects, one would have to: - Install the extension in a clean database. - Query all indirect dependencies in both the clean and production databases. - Perform a diff between these datasets to identify discrepancies. This approach seems cumbersome and impractical in production environments. Explicitly adding deptype='e' entries for all objects created during CREATE EXTENSION would significantly improve this situation. With this enhancement, pg_dump could easily detect and warn users about manually-added objects, or even dump these objects as comments for manual review. Even if pg_dump itself isn't improved, users would at least be able to write a straightforward query to identify such objects in production environments. While manually adding objects to extension-defined tables is of course bad practice, I think it would help DBAs if they at least had a simple way to detect such a situation. /Joel
Re: Missing pg_depend entries for constraints created by extensions (deptype 'e')
From
"Joel Jacobson"
Date:
On Sun, Jun 1, 2025, at 08:24, Joel Jacobson wrote: > On Sat, May 31, 2025, at 23:56, Tom Lane wrote: >> "Joel Jacobson" <joel@compiler.org> writes: >>> Foreign key constraints created during CREATE EXTENSION >>> lack a pg_depend entry with deptype='e'. >> >> Why would it be a sensible thing for an extension to create a >> foreign-key constraint on table(s) that it didn't itself create? > > That wouldn't make any sense, no. > >> (If it did create them, the indirect dependency seems sufficient.) > > The indirect dependency might seem sufficient initially but becomes problematic > when needing to distinguish between objects originally created by an extension > and those manually added later by users. ... > Explicitly adding deptype='e' entries for all objects created during > CREATE EXTENSION would significantly improve this situation. > With this enhancement, pg_dump could easily detect and warn users about > manually-added objects, or even dump these objects as comments for > manual review. Upon further reflection, perhaps we can address this issue more cleanly without resorting to workarounds like warnings or comments. Given that pg_dump already emits CREATE EXTENSION commands in dump files, if we enhanced pg_depend to track all object classes associated with extensions explicitly, we could just emit commands to recreate any manually-added objects immediately after the corresponding CREATE EXTENSION commands in the dump file. This would ensure that manually-added extension objects, regardless of the reason for their creation, would be reliably preserved and not risk being lost. /Joel
Re: Missing pg_depend entries for constraints created by extensions (deptype 'e')
From
Tom Lane
Date:
"Joel Jacobson" <joel@compiler.org> writes: > Explicitly adding deptype='e' entries for all objects created during > CREATE EXTENSION would significantly improve this situation. > With this enhancement, pg_dump could easily detect and warn users about > manually-added objects, or even dump these objects as comments for manual review. I'm pretty skeptical that this situation justifies the amount of pg_depend bloat that you're suggesting. I also don't think it'd be easy or cheap for pg_dump to detect objects that should be dumped because they lack an 'e' dependency but depend on objects that do have one. Normally, because extension member objects aren't dumped, pg_dump doesn't even collect info on their indexes etc. In short, it seems like quite a lot of work and quite a lot of overhead (paid by everybody) to accommodate somebody abusing extensions in one very specific way. There are a lot of scenarios in which a cowboy DBA can cause the database contents to differ from what the extension scripts say, and most of them would not be helped by what you're suggesting. regards, tom lane