diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2019-02-11 14:41:13 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2019-02-11 14:41:17 -0500 |
commit | 1d92a0c9f7dd547ad14cd8a3974289c5ec7f04ce (patch) | |
tree | 78b0f37ecf473fc8517acd0973356ad8f6468752 /doc/src | |
parent | c603b392c32513982439bc466312d3a6b697d53e (diff) | |
download | postgresql-1d92a0c9f7dd547ad14cd8a3974289c5ec7f04ce.tar.gz postgresql-1d92a0c9f7dd547ad14cd8a3974289c5ec7f04ce.zip |
Redesign the partition dependency mechanism.
The original setup for dependencies of partitioned objects had
serious problems:
1. It did not verify that a drop cascading to a partition-child object
also cascaded to at least one of the object's partition parents. Now,
normally a child object would share all its dependencies with one or
another parent (e.g. a child index's opclass dependencies would be shared
with the parent index), so that this oversight is usually harmless.
But if some dependency failed to fit this pattern, the child could be
dropped while all its parents remain, creating a logically broken
situation. (It's easy to construct artificial cases that break it,
such as attaching an unrelated extension dependency to the child object
and then dropping the extension. I'm not sure if any less-artificial
cases exist.)
2. Management of partition dependencies during ATTACH/DETACH PARTITION
was complicated and buggy; for example, after detaching a partition
table it was possible to create cases where a formerly-child index
should be dropped and was not, because the correct set of dependencies
had not been reconstructed.
Less seriously, because multiple partition relationships were
represented identically in pg_depend, there was an order-of-traversal
dependency on which partition parent was cited in error messages.
We also had some pre-existing order-of-traversal hazards for error
messages related to internal and extension dependencies. This is
cosmetic to users but causes testing problems.
To fix #1, add a check at the end of the partition tree traversal
to ensure that at least one partition parent got deleted. To fix #2,
establish a new policy that partition dependencies are in addition to,
not instead of, a child object's usual dependencies; in this way
ATTACH/DETACH PARTITION need not cope with adding or removing the
usual dependencies.
To fix the cosmetic problem, distinguish between primary and secondary
partition dependency entries in pg_depend, by giving them different
deptypes. (They behave identically except for having different
priorities for being cited in error messages.) This means that the
former 'I' dependency type is replaced with new 'P' and 'S' types.
This also fixes a longstanding bug that after handling an internal
dependency by recursing to the owning object, findDependentObjects
did not verify that the current target was now scheduled for deletion,
and did not apply the current recursion level's objflags to it.
Perhaps that should be back-patched; but in the back branches it
would only matter if some concurrent transaction had removed the
internal-linkage pg_depend entry before the recursive call found it,
or the recursive call somehow failed to find it, both of which seem
unlikely.
Catversion bump because the contents of pg_depend change for
partitioning relationships.
Patch HEAD only. It's annoying that we're not fixing #2 in v11,
but there seems no practical way to do so given that the problem
is exactly a poor choice of what entries to put in pg_depend.
We can't really fix that while staying compatible with what's
in pg_depend in existing v11 installations.
Discussion: https://postgr.es/m/CAH2-Wzkypv1R+teZrr71U23J578NnTBt2X8+Y=Odr4pOdW1rXg@mail.gmail.com
Diffstat (limited to 'doc/src')
-rw-r--r-- | doc/src/sgml/catalogs.sgml | 100 |
1 files changed, 70 insertions, 30 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 6dd0700da75..0fd792ff1a2 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -2970,7 +2970,7 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l referenced object, and should be automatically dropped (regardless of <literal>RESTRICT</literal> or <literal>CASCADE</literal> mode) if the referenced object is dropped. Example: a named - constraint on a table is made autodependent on the table, so + constraint on a table is made auto-dependent on the table, so that it will go away if the table is dropped. </para> </listitem> @@ -2982,38 +2982,61 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l <para> The dependent object was created as part of creation of the referenced object, and is really just a part of its internal - implementation. A <command>DROP</command> of the dependent object - will be disallowed outright (we'll tell the user to issue a - <command>DROP</command> against the referenced object, instead). A - <command>DROP</command> of the referenced object will be propagated - through to drop the dependent object whether - <command>CASCADE</command> is specified or not. Example: a trigger - that's created to enforce a foreign-key constraint is made - internally dependent on the constraint's - <structname>pg_constraint</structname> entry. + implementation. A direct <command>DROP</command> of the dependent + object will be disallowed outright (we'll tell the user to issue + a <command>DROP</command> against the referenced object, instead). + A <command>DROP</command> of the referenced object will result in + automatically dropping the dependent object + whether <literal>CASCADE</literal> is specified or not. If the + dependent object is reached due to a dependency on some other object, + the drop is converted to a drop of the referenced object, so + that <literal>NORMAL</literal> and <literal>AUTO</literal> + dependencies of the dependent object behave much like they were + dependencies of the referenced object. + Example: a view's <literal>ON SELECT</literal> rule is made + internally dependent on the view, preventing it from being dropped + while the view remains. Dependencies of the rule (such as tables it + refers to) act as if they were dependencies of the view. </para> </listitem> </varlistentry> <varlistentry> - <term><symbol>DEPENDENCY_INTERNAL_AUTO</symbol> (<literal>I</literal>)</term> + <term><symbol>DEPENDENCY_PARTITION_PRI</symbol> (<literal>P</literal>)</term> + <term><symbol>DEPENDENCY_PARTITION_SEC</symbol> (<literal>S</literal>)</term> <listitem> <para> The dependent object was created as part of creation of the referenced object, and is really just a part of its internal - implementation. A <command>DROP</command> of the dependent object - will be disallowed outright (we'll tell the user to issue a - <command>DROP</command> against the referenced object, instead). - While a regular internal dependency will prevent - the dependent object from being dropped while any such dependencies - remain, <literal>DEPENDENCY_INTERNAL_AUTO</literal> will allow such - a drop as long as the object can be found by following any of such + implementation; however, unlike <literal>INTERNAL</literal>, + there is more than one such referenced object. The dependent object + must not be dropped unless at least one of these referenced objects + is dropped; if any one is, the dependent object should be dropped + whether or not <literal>CASCADE</literal> is specified. Also + unlike <literal>INTERNAL</literal>, a drop of some other object + that the dependent object depends on does not result in automatic + deletion of any partition-referenced object. Hence, if the drop + does not cascade to at least one of these objects via some other + path, it will be refused. (In most cases, the dependent object + shares all its non-partition dependencies with at least one + partition-referenced object, so that this restriction does not + result in blocking any cascaded delete.) + Primary and secondary partition dependencies behave identically + except that the primary dependency is preferred for use in error + messages; hence, a partition-dependent object should have one + primary partition dependency and one or more secondary partition dependencies. - Example: an index on a partition is made internal-auto-dependent on - both the partition itself as well as on the index on the parent - partitioned table; so the partition index is dropped together with - either the partition it indexes, or with the parent index it is - attached to. + Note that partition dependencies are made in addition to, not + instead of, any dependencies the object would normally have. This + simplifies <command>ATTACH/DETACH PARTITION</command> operations: + the partition dependencies need only be added or removed. + Example: a child partitioned index is made partition-dependent + on both the partition table it is on and the parent partitioned + index, so that it goes away if either of those is dropped, but + not otherwise. The dependency on the parent index is primary, + so that if the user tries to drop the child partitioned index, + the error message will suggest dropping the parent index instead + (not the table). </para> </listitem> </varlistentry> @@ -3026,9 +3049,10 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l the referenced object (see <link linkend="catalog-pg-extension"><structname>pg_extension</structname></link>). The dependent object can be dropped only via - <command>DROP EXTENSION</command> 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 <application>pg_dump</application>. + <command>DROP EXTENSION</command> on the referenced object. + Functionally this dependency type acts the same as + an <literal>INTERNAL</literal> dependency, but it's kept separate for + clarity and to simplify <application>pg_dump</application>. </para> </listitem> </varlistentry> @@ -3038,10 +3062,13 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l <listitem> <para> The dependent object is not a member of the extension that is the - referenced object (and so should not be ignored by pg_dump), but - cannot function without it and should be dropped when the - extension itself is. The dependent object may be dropped on its - own as well. + referenced object (and so it should not be ignored + by <application>pg_dump</application>), 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 <literal>AUTO</literal> dependency, but it's kept separate for + clarity and to simplify <application>pg_dump</application>. </para> </listitem> </varlistentry> @@ -3063,6 +3090,19 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l Other dependency flavors might be needed in future. </para> + <para> + Note that it's quite possible for two objects to be linked by more than + one <structname>pg_depend</structname> entry. For example, a child + partitioned index would have both a partition-type dependency on its + associated partition table, and an auto dependency on each column of + that table that it indexes. This sort of situation expresses the union + of multiple dependency semantics. A dependent object can be dropped + without <literal>CASCADE</literal> if any of its dependencies satisfies + its condition for automatic dropping. Conversely, all the + dependencies' restrictions about which objects must be dropped together + must be satisfied. + </para> + </sect1> |