Getting ERROR: could not open file "base/13164/t3_16388" with partition table with ON COMMIT
Hi,
I am getting below error while creating temp root partition table with on
commit. getting same error from v10 onwards.
[edb@localhost bin]$ ./psql postgres
psql (10.5)
Type "help" for help.
postgres=# CREATE TEMP TABLE test ( c1 varchar, c2 int) PARTITION BY RANGE
(c1) ON COMMIT DELETE ROWS;
ERROR: could not open file "base/13164/t3_16388": No such file or directory
Thanks & Regards,
Rajkumar Raghuwanshi
QMG, EnterpriseDB Corporation
On 2018/09/12 19:29, Rajkumar Raghuwanshi wrote:
Hi,
I am getting below error while creating temp root partition table with on
commit. getting same error from v10 onwards.[edb@localhost bin]$ ./psql postgres
psql (10.5)
Type "help" for help.postgres=# CREATE TEMP TABLE test ( c1 varchar, c2 int) PARTITION BY RANGE
(c1) ON COMMIT DELETE ROWS;
ERROR: could not open file "base/13164/t3_16388": No such file or directory
Oops, good catch.
The infamous missing-relkind-check in heap_truncate() seems to be behind
this. Perhaps, a patch like the attached will do?
Thanks,
Amit
Attachments:
heap-truncate-check-relkind.patchtext/plain; charset=UTF-8; name=heap-truncate-check-relkind.patchDownload
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 9176f6280b..3f0be39940 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -3174,7 +3174,8 @@ heap_truncate(List *relids)
Relation rel = lfirst(cell);
/* Truncate the relation */
- heap_truncate_one_rel(rel);
+ if (rel->rd_rel->relkind == RELKIND_RELATION)
+ heap_truncate_one_rel(rel);
/* Close the relation, but keep exclusive lock on it until commit */
heap_close(rel, NoLock);
Amit Langote <Langote_Amit_f8@lab.ntt.co.jp> writes:
The infamous missing-relkind-check in heap_truncate() seems to be behind
this. Perhaps, a patch like the attached will do?
That seems excessively restrictive. Anything that has storage (e.g.
matviews) ought to be truncatable, no?
I thought we had a macro or utility function somewhere that knew which
relkinds have storage, though I can't find it right now. I'd be
inclined to instantiate that if it doesn't exist, and then the code
here ought to read something like
if (RelkindHasStorage(rel->rd_rel->relkind))
heap_truncate_one_rel(rel);
Also, possibly the test ought to be inside heap_truncate_one_rel
rather than its callers?
regards, tom lane
On Wed, Sep 12, 2018 at 12:14:00PM -0400, Tom Lane wrote:
I thought we had a macro or utility function somewhere that knew which
relkinds have storage, though I can't find it right now. I'd be
inclined to instantiate that if it doesn't exist, and then the code
here ought to read something like
Perhaps you are thinking about heap_create() which decides if a relkind
can have storage created by setting create_storage. If you introduce a
new macro, I would think that refactoring as well heap.c so as it makes
use of it could make sense.
--
Michael
On 2018/09/13 1:14, Tom Lane wrote:
Amit Langote <Langote_Amit_f8@lab.ntt.co.jp> writes:
The infamous missing-relkind-check in heap_truncate() seems to be behind
this. Perhaps, a patch like the attached will do?That seems excessively restrictive. Anything that has storage (e.g.
matviews) ought to be truncatable, no?
Not by heap_truncate it seems. The header comment of heap_truncate says
that it concerns itself only with ON COMMIT truncation of temporary tables:
/*
* heap_truncate
*
* This routine deletes all data within all the specified relations.
*
* This is not transaction-safe! There is another, transaction-safe
* implementation in commands/tablecmds.c. We now use this only for
* ON COMMIT truncation of temporary tables, where it doesn't matter.
*/
ON COMMIT clause can only be used with temporary tables, so the only two
possible relkind values that can be encountered here are RELKIND_RELATION
and RELKIND_PARTITIONED_TABLE. Of the two, only the RELKIND_RELATION can
have storage.
I thought we had a macro or utility function somewhere that knew which
relkinds have storage, though I can't find it right now. I'd be
inclined to instantiate that if it doesn't exist, and then the code
here ought to read something likeif (RelkindHasStorage(rel->rd_rel->relkind))
heap_truncate_one_rel(rel);
There have been discussions (such as [1]Macros bundling RELKIND_* conditions /messages/by-id/CAFjFpRcfzs+yst6YBCseD_orEcDNuAr9GUTraZ5GC=AvCYh55Q@mail.gmail.com), but none that led to some patch
being committed. Might be a good idea to revive that discussion again, or
perhaps there is already some solution being discussed on the pluggable
storage thread.
Also, possibly the test ought to be inside heap_truncate_one_rel
rather than its callers?
Hmm, perhaps. ExecuteTruncateGuts, the only other caller of
heap_truncate_one_rel, also checks the relkind to skip partitioned tables.
There seem to be reasons to do it in the caller in that case though,
other than heap_truncate_one_rel being incapable of handling them.
Thanks,
Amit
[1]: Macros bundling RELKIND_* conditions /messages/by-id/CAFjFpRcfzs+yst6YBCseD_orEcDNuAr9GUTraZ5GC=AvCYh55Q@mail.gmail.com
/messages/by-id/CAFjFpRcfzs+yst6YBCseD_orEcDNuAr9GUTraZ5GC=AvCYh55Q@mail.gmail.com
On 2018/09/13 12:37, Michael Paquier wrote:
On Wed, Sep 12, 2018 at 12:14:00PM -0400, Tom Lane wrote:
I thought we had a macro or utility function somewhere that knew which
relkinds have storage, though I can't find it right now. I'd be
inclined to instantiate that if it doesn't exist, and then the code
here ought to read something likePerhaps you are thinking about heap_create() which decides if a relkind
can have storage created by setting create_storage. If you introduce a
new macro, I would think that refactoring as well heap.c so as it makes
use of it could make sense.
Ashutosh Bapat had proposed patches in this area last year [1]Macros bundling RELKIND_* conditions /messages/by-id/CAFjFpRcfzs+yst6YBCseD_orEcDNuAr9GUTraZ5GC=AvCYh55Q@mail.gmail.com, but it
seems the discussion didn't lead to any development.
Thanks,
Amit
[1]: Macros bundling RELKIND_* conditions /messages/by-id/CAFjFpRcfzs+yst6YBCseD_orEcDNuAr9GUTraZ5GC=AvCYh55Q@mail.gmail.com
/messages/by-id/CAFjFpRcfzs+yst6YBCseD_orEcDNuAr9GUTraZ5GC=AvCYh55Q@mail.gmail.com
Amit Langote <Langote_Amit_f8@lab.ntt.co.jp> writes:
On 2018/09/13 1:14, Tom Lane wrote:
That seems excessively restrictive. Anything that has storage (e.g.
matviews) ought to be truncatable, no?
Not by heap_truncate it seems. The header comment of heap_truncate says
that it concerns itself only with ON COMMIT truncation of temporary tables:
Ah. Well, in that case I'm OK with just a simple test for
RELKIND_RELATION, but I definitely feel that it should be inside
heap_truncate. Callers don't need to know about the limited scope
of what that does.
regards, tom lane
On 2018/09/13 23:13, Tom Lane wrote:
Amit Langote <Langote_Amit_f8@lab.ntt.co.jp> writes:
On 2018/09/13 1:14, Tom Lane wrote:
That seems excessively restrictive. Anything that has storage (e.g.
matviews) ought to be truncatable, no?Not by heap_truncate it seems. The header comment of heap_truncate says
that it concerns itself only with ON COMMIT truncation of temporary tables:Ah. Well, in that case I'm OK with just a simple test for
RELKIND_RELATION, but I definitely feel that it should be inside
heap_truncate. Callers don't need to know about the limited scope
of what that does.
I guess you meant inside heap_truncate_one_rel. I updated the patch that
way, but I wonder if we shouldn't also allow other relkinds that have
storage which RelationTruncate et al can technically deal with.
Thanks,
Amit
Attachments:
heap-truncate-check-relkind-v3.patchtext/plain; charset=UTF-8; name=heap-truncate-check-relkind-v3.patchDownload
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 9176f6280b..57df70f7b9 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -3195,6 +3195,10 @@ heap_truncate_one_rel(Relation rel)
{
Oid toastrelid;
+ /* Only certain relkinds have storage. */
+ if (rel->rd_rel->relkind != RELKIND_RELATION)
+ return;
+
/* Truncate the actual file (and discard buffers) */
RelationTruncate(rel, 0);
On Fri, Sep 14, 2018 at 7:23 AM, Amit Langote <Langote_Amit_f8@lab.ntt.co.jp
wrote:
On 2018/09/13 23:13, Tom Lane wrote:
Amit Langote <Langote_Amit_f8@lab.ntt.co.jp> writes:
On 2018/09/13 1:14, Tom Lane wrote:
That seems excessively restrictive. Anything that has storage (e.g.
matviews) ought to be truncatable, no?Not by heap_truncate it seems. The header comment of heap_truncate says
that it concerns itself only with ON COMMIT truncation of temporarytables:
Ah. Well, in that case I'm OK with just a simple test for
RELKIND_RELATION, but I definitely feel that it should be inside
heap_truncate. Callers don't need to know about the limited scope
of what that does.I guess you meant inside heap_truncate_one_rel. I updated the patch that
way, but I wonder if we shouldn't also allow other relkinds that have
storage which RelationTruncate et al can technically deal with.
Verified. This patch fixed issue.
On 2018/09/14 10:53, Amit Langote wrote:
On 2018/09/13 23:13, Tom Lane wrote:
Amit Langote <Langote_Amit_f8@lab.ntt.co.jp> writes:
On 2018/09/13 1:14, Tom Lane wrote:
That seems excessively restrictive. Anything that has storage (e.g.
matviews) ought to be truncatable, no?Not by heap_truncate it seems. The header comment of heap_truncate says
that it concerns itself only with ON COMMIT truncation of temporary tables:Ah. Well, in that case I'm OK with just a simple test for
RELKIND_RELATION, but I definitely feel that it should be inside
heap_truncate. Callers don't need to know about the limited scope
of what that does.I guess you meant inside heap_truncate_one_rel. I updated the patch that
way, but I wonder if we shouldn't also allow other relkinds that have
storage which RelationTruncate et al can technically deal with.
Rajkumar pointed out off-list that the patch still remains to be applied.
Considering that there is a planned point release on Nov 8, maybe we
should do something about this?
Thanks,
Amit
On Thu, Nov 01, 2018 at 12:39:16PM +0900, Amit Langote wrote:
Rajkumar pointed out off-list that the patch still remains to be applied.
Considering that there is a planned point release on Nov 8, maybe we
should do something about this?
Yes doing something about that very soon would be a good idea. Tom,
are you planning to look at it or should I jump in?
--
Michael
On Thu, Nov 01, 2018 at 01:04:43PM +0900, Michael Paquier wrote:
On Thu, Nov 01, 2018 at 12:39:16PM +0900, Amit Langote wrote:
Rajkumar pointed out off-list that the patch still remains to be applied.
Considering that there is a planned point release on Nov 8, maybe we
should do something about this?Yes doing something about that very soon would be a good idea. Tom,
are you planning to look at it or should I jump in?
And so I am looking at v3 now...
Adding a test case in temp.sql would be nice.
Would it make sense to support TRUNCATE on a materialized as well in the
future? It seems to me that it is dangerous to assume that only
relations make use of heap_truncate_one_rel() anyway as modules or
external code could perfectly call it. And the thing is documented
to work on a relation, including materialized views, not just an
ordinary table which is what RELKIND_RELATION only mentions. On the
contrary we know that heap_truncate() works only on temporary
relations. It is documented to do so and does so.
So it seems to me that Tom correctly mentioned to add the check in
heap_truncate, not heap_truncate_one_rel(), so v3 looks incorrect to
me.
--
Michael
On 2018/11/02 10:51, Michael Paquier wrote:
On Thu, Nov 01, 2018 at 01:04:43PM +0900, Michael Paquier wrote:
On Thu, Nov 01, 2018 at 12:39:16PM +0900, Amit Langote wrote:
Rajkumar pointed out off-list that the patch still remains to be applied.
Considering that there is a planned point release on Nov 8, maybe we
should do something about this?Yes doing something about that very soon would be a good idea. Tom,
are you planning to look at it or should I jump in?And so I am looking at v3 now...
Thanks for looking.
Adding a test case in temp.sql would be nice.
Good idea, done.
When writing the test, I noticed something to be pointed out. As of
1c7c317cd9d, partitions of a temporary partition table themselves must be
temporary, but the ON COMMIT action has to be specified for each table
separately. Maybe, there is nothing to be concerned about here, because
there's nowhere to record what's specified for the parent to use it on the
children. So, children's CREATE TABLE commands must specify the ON COMMIT
action for themselves.
Would it make sense to support TRUNCATE on a materialized as well in the
future? It seems to me that it is dangerous to assume that only
relations make use of heap_truncate_one_rel() anyway as modules or
external code could perfectly call it. And the thing is documented
to work on a relation, including materialized views, not just an
ordinary table which is what RELKIND_RELATION only mentions. On the
contrary we know that heap_truncate() works only on temporary
relations. It is documented to do so and does so.So it seems to me that Tom correctly mentioned to add the check in
heap_truncate, not heap_truncate_one_rel(), so v3 looks incorrect to
me.
Okay, I agree that adding the preventive check in heap_truncate is a good
idea.
Updated patch attached.
Thanks,
Amit
Attachments:
heap-truncate-check-relkind-v4.patchtext/plain; charset=UTF-8; name=heap-truncate-check-relkind-v4.patchDownload
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 064cf9dbf6..2c2d287f0e 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -3121,7 +3121,8 @@ RelationTruncateIndexes(Relation heapRelation)
/*
* heap_truncate
*
- * This routine deletes all data within all the specified relations.
+ * This routine deletes all data within all the specified relations,
+ * ignoring any that don't have any storage to begin with
*
* This is not transaction-safe! There is another, transaction-safe
* implementation in commands/tablecmds.c. We now use this only for
@@ -3151,8 +3152,12 @@ heap_truncate(List *relids)
{
Relation rel = lfirst(cell);
- /* Truncate the relation */
- heap_truncate_one_rel(rel);
+ /*
+ * Truncate the relation. Regular and partitioned tables can be
+ * temporary relations, but only regular tables have storage.
+ */
+ if (rel->rd_rel->relkind == RELKIND_RELATION)
+ heap_truncate_one_rel(rel);
/* Close the relation, but keep exclusive lock on it until commit */
heap_close(rel, NoLock);
diff --git a/src/test/regress/expected/temp.out b/src/test/regress/expected/temp.out
index addf1ec444..ed2c591fc6 100644
--- a/src/test/regress/expected/temp.out
+++ b/src/test/regress/expected/temp.out
@@ -199,3 +199,17 @@ select pg_temp.whoami();
(1 row)
drop table public.whereami;
+-- for partitioned temp tables, ON COMMIT action should ignore storage-less
+-- partitioned parent table
+begin;
+create temp table temp_parted_oncommit_test (a int) partition by list (a) on commit delete rows;
+create temp table temp_parted_oncommit_test1 partition of temp_parted_oncommit_test for values in (1) on commit delete rows;
+insert into temp_parted_oncommit_test values (1);
+commit;
+-- temp_parted_oncommit_test1 must've been emptied during the commit
+select * from temp_parted_oncommit_test;
+ a
+---
+(0 rows)
+
+drop table temp_parted_oncommit_test;
diff --git a/src/test/regress/sql/temp.sql b/src/test/regress/sql/temp.sql
index 5183c727f5..0274bdb13f 100644
--- a/src/test/regress/sql/temp.sql
+++ b/src/test/regress/sql/temp.sql
@@ -151,3 +151,14 @@ select whoami();
select pg_temp.whoami();
drop table public.whereami;
+
+-- for partitioned temp tables, ON COMMIT action should ignore storage-less
+-- partitioned parent table
+begin;
+create temp table temp_parted_oncommit_test (a int) partition by list (a) on commit delete rows;
+create temp table temp_parted_oncommit_test1 partition of temp_parted_oncommit_test for values in (1) on commit delete rows;
+insert into temp_parted_oncommit_test values (1);
+commit;
+-- temp_parted_oncommit_test1 must've been emptied during the commit
+select * from temp_parted_oncommit_test;
+drop table temp_parted_oncommit_test;
On Fri, Nov 02, 2018 at 01:36:05PM +0900, Amit Langote wrote:
When writing the test, I noticed something to be pointed out. As of
1c7c317cd9d, partitions of a temporary partition table themselves must be
temporary, but the ON COMMIT action has to be specified for each table
separately. Maybe, there is nothing to be concerned about here, because
there's nowhere to record what's specified for the parent to use it on the
children. So, children's CREATE TABLE commands must specify the ON COMMIT
action for themselves.
Well, I would actually expect callers to do so. ON COMMIT PRESERVE or
DELETE rows does not make much sense for partitioned tables as
they have no physical presence (like today's thread about tablespaces
which you know about), but it looks better to just let the command go
through instead of complaining about it if we worry about inheritance.
And actually, your point has just made me aware of a second bug:
=# begin;
BEGIN
=# create temp table temp_parent (a int) partition by list (a) on commit
drop;
CREATE TABLE
=# create temp table temp_child_2 partition of temp_parent for values in
(2) on commit delete rows;
CREATE TABLE
=# insert into temp_parent values (2);
INSERT 0 1
=# table temp_parent;
a
---
2
(1 row)
=# commit;
ERROR: XX000: could not open relation with OID 16420
LOCATION: relation_open, heapam.c:1138
This case is funky. The parent gets dropped at commit time, but it does
not know that it should drop the child as well per their dependencies.
This actually goes into the internals of performDeletion(), which is
scary to touch on back-branches just for such cases..
--
Michael
On Fri, Nov 02, 2018 at 02:18:04PM +0900, Michael Paquier wrote:
This case is funky. The parent gets dropped at commit time, but it does
not know that it should drop the child as well per their dependencies.
This actually goes into the internals of performDeletion(), which is
scary to touch on back-branches just for such cases..
A bit more fun with inheritance:
=# begin;
BEGIN
=# create temp table aa_p (a int) on commit drop;
CREATE TABLE
=# create temp table aa_c (a int) inherits (aa_p) on commit delete rows;
NOTICE: 00000: merging column "a" with inherited definition
LOCATION: MergeAttributes, tablecmds.c:2339
CREATE TABLE
=# insert into aa_p values (1);
INSERT 0 1
=# insert into aa_c values (1);
INSERT 0 1
=# commit;
NOTICE: 00000: drop cascades to table aa_c
LOCATION: reportDependentObjects, dependency.c:995
ERROR: XX000: could not open relation with OID 16426
LOCATION: relation_open, heapam.c:1138
Let's treat that as a separate issue, as this happens also with an
unpatched build. The only reason why you cannot trigger it with
partitions is that ON COMMIT is currently broken for them, so we should
fix the reported case first. In consequence, I would tend to commit the
patch proposed and take care of the first, except if of course anybody
has an objection.
--
Michael
Hi,
On 2018/11/02 14:27, Michael Paquier wrote:
On Fri, Nov 02, 2018 at 02:18:04PM +0900, Michael Paquier wrote:
This case is funky.
Interesting indeed.
The parent gets dropped at commit time, but it does
not know that it should drop the child as well per their dependencies.
This actually goes into the internals of performDeletion(), which is
scary to touch on back-branches just for such cases..
Well, performDeletion *does* drop the child, because when the parent is
dropped due to its ON COMMIT DROP action, it's done using:
/*
* Since this is an automatic drop, rather than one
* directly initiated by the user, we pass the
* PERFORM_DELETION_INTERNAL flag.
*/
performDeletion(&object,
DROP_CASCADE, PERFORM_DELETION_INTERNAL);
Note the DROP_CASCADE, which means its children will be deleted as part of
this.
A bit more fun with inheritance:
=# begin;
BEGIN
=# create temp table aa_p (a int) on commit drop;
CREATE TABLE
=# create temp table aa_c (a int) inherits (aa_p) on commit delete rows;
NOTICE: 00000: merging column "a" with inherited definition
LOCATION: MergeAttributes, tablecmds.c:2339
CREATE TABLE
=# insert into aa_p values (1);
INSERT 0 1
=# insert into aa_c values (1);
INSERT 0 1
=# commit;
NOTICE: 00000: drop cascades to table aa_c
LOCATION: reportDependentObjects, dependency.c:995
ERROR: XX000: could not open relation with OID 16426
LOCATION: relation_open, heapam.c:1138
I think the problem here is that the ON COMMIT DROP action on the parent
is executed before the ON COMMIT DELETE ROWS on the child. The first
action drops the child along with its parent, causing the 2nd one to fail
upon not finding the table to apply heap_truncate() to. It's
heap_truncate() that produces "ERROR: could not open relation with OID
xxx". So, the NOTICE comes from the *successful* dropping of the child
and the ERROR comes from failure of heap_truncate() to find it.
By the way, this error is same as in the partitioned case. It's simply
that the dependency type is different for regular inheritance child tables
than it is for partitions. The former requires a user command to specify
CASCADE when dropping via parent, whereas the latter doesn't. So, you see
the NOTICE in the regular inheritance case, whereas you don't in the
partitioning case. The error itself is same in both cases.
Let's treat that as a separate issue, as this happens also with an
unpatched build. The only reason why you cannot trigger it with
partitions is that ON COMMIT is currently broken for them, so we should
fix the reported case first. In consequence, I would tend to commit the
patch proposed and take care of the first, except if of course anybody
has an objection.
Agreed that they're two independent issues, although it wouldn't be such a
bad idea to fix them in one go, as they're both issues related to the
handling of ON COMMIT actions on tables in inheritance trees.
I've created a patch for the other issue and attached both.
Thanks,
Amit
Attachments:
0002-Check-relation-still-exists-before-applying-ON-CO.patchtext/plain; charset=UTF-8; name=0002-Check-relation-still-exists-before-applying-ON-CO.patchDownload
From 5d1cb1beda9a4d3c020933e85715cdd2423e5ba7 Mon Sep 17 00:00:00 2001
From: amit <amitlangote09@gmail.com>
Date: Fri, 2 Nov 2018 15:26:37 +0900
Subject: [PATCH v5 2/2] Check relation still exists before applying ON COMMIT
action
---
src/backend/commands/tablecmds.c | 17 +++++++++++++++++
src/test/regress/expected/temp.out | 23 +++++++++++++++++++++++
src/test/regress/sql/temp.sql | 15 +++++++++++++++
3 files changed, 55 insertions(+)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index ba76c3f9b9..7f742dba7b 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -13291,6 +13291,23 @@ PreCommit_on_commit_actions(void)
}
if (oids_to_truncate != NIL)
{
+ List *tmp = oids_to_truncate;
+
+ /*
+ * Check that relations we're about to truncate still exist. Some of
+ * them might be inheritance children, which would be gone as a result
+ * of their parent being dropped due to ONCOMMIT_DROP action of its
+ * own.
+ */
+ oids_to_truncate = NIL;
+ foreach(l, tmp)
+ {
+ Oid relid = lfirst_oid(l);
+
+ if (SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relid)))
+ oids_to_truncate = lappend_oid(oids_to_truncate, relid);
+ }
+
heap_truncate(oids_to_truncate);
CommandCounterIncrement(); /* XXX needed? */
}
diff --git a/src/test/regress/expected/temp.out b/src/test/regress/expected/temp.out
index ed2c591fc6..2cfc5debf1 100644
--- a/src/test/regress/expected/temp.out
+++ b/src/test/regress/expected/temp.out
@@ -213,3 +213,26 @@ select * from temp_parted_oncommit_test;
(0 rows)
drop table temp_parted_oncommit_test;
+-- another case where a child table is gone by the time it's ON COMMIT
+-- action is executed (whatever it is) due to the ON COMMIT DROP action
+-- on its parent
+begin;
+create temp table temp_parted_oncommit_test (a int) partition by list (a) on commit drop;
+create temp table temp_parted_oncommit_test1 partition of temp_parted_oncommit_test for values in (1) on commit delete rows;
+insert into temp_parted_oncommit_test values (1);
+create temp table temp_inh_oncommit_test (a int) on commit drop;
+create temp table temp_inh_oncommit_test1 () inherits(temp_inh_oncommit_test) on commit delete rows;
+insert into temp_inh_oncommit_test1 values (1);
+commit;
+NOTICE: drop cascades to table temp_inh_oncommit_test1
+-- zero rows in both cases
+select relname from pg_class where relname like 'temp_parted_oncommit_test%';
+ relname
+---------
+(0 rows)
+
+select relname from pg_class where relname like 'temp_inh_oncommit_test%';
+ relname
+---------
+(0 rows)
+
diff --git a/src/test/regress/sql/temp.sql b/src/test/regress/sql/temp.sql
index 0274bdb13f..59b11c4894 100644
--- a/src/test/regress/sql/temp.sql
+++ b/src/test/regress/sql/temp.sql
@@ -162,3 +162,18 @@ commit;
-- temp_parted_oncommit_test1 must've been emptied during the commit
select * from temp_parted_oncommit_test;
drop table temp_parted_oncommit_test;
+
+-- another case where a child table is gone by the time it's ON COMMIT
+-- action is executed (whatever it is) due to the ON COMMIT DROP action
+-- on its parent
+begin;
+create temp table temp_parted_oncommit_test (a int) partition by list (a) on commit drop;
+create temp table temp_parted_oncommit_test1 partition of temp_parted_oncommit_test for values in (1) on commit delete rows;
+insert into temp_parted_oncommit_test values (1);
+create temp table temp_inh_oncommit_test (a int) on commit drop;
+create temp table temp_inh_oncommit_test1 () inherits(temp_inh_oncommit_test) on commit delete rows;
+insert into temp_inh_oncommit_test1 values (1);
+commit;
+-- zero rows in both cases
+select relname from pg_class where relname like 'temp_parted_oncommit_test%';
+select relname from pg_class where relname like 'temp_inh_oncommit_test%';
--
2.11.0
heap-truncate-check-relkind-v5.patchtext/plain; charset=UTF-8; name=heap-truncate-check-relkind-v5.patchDownload
From 710f3a0830a4cb58ca7d1e7968d613d144c0fdda Mon Sep 17 00:00:00 2001
From: amit <amitlangote09@gmail.com>
Date: Fri, 2 Nov 2018 15:28:57 +0900
Subject: [PATCH v5 1/2] Ignore partitioned tables during ON COMMIT DELETE ROWS
---
src/backend/catalog/heap.c | 11 ++++++++---
src/test/regress/expected/temp.out | 14 ++++++++++++++
src/test/regress/sql/temp.sql | 11 +++++++++++
3 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 064cf9dbf6..2c2d287f0e 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -3121,7 +3121,8 @@ RelationTruncateIndexes(Relation heapRelation)
/*
* heap_truncate
*
- * This routine deletes all data within all the specified relations.
+ * This routine deletes all data within all the specified relations,
+ * ignoring any that don't have any storage to begin with
*
* This is not transaction-safe! There is another, transaction-safe
* implementation in commands/tablecmds.c. We now use this only for
@@ -3151,8 +3152,12 @@ heap_truncate(List *relids)
{
Relation rel = lfirst(cell);
- /* Truncate the relation */
- heap_truncate_one_rel(rel);
+ /*
+ * Truncate the relation. Regular and partitioned tables can be
+ * temporary relations, but only regular tables have storage.
+ */
+ if (rel->rd_rel->relkind == RELKIND_RELATION)
+ heap_truncate_one_rel(rel);
/* Close the relation, but keep exclusive lock on it until commit */
heap_close(rel, NoLock);
diff --git a/src/test/regress/expected/temp.out b/src/test/regress/expected/temp.out
index addf1ec444..ed2c591fc6 100644
--- a/src/test/regress/expected/temp.out
+++ b/src/test/regress/expected/temp.out
@@ -199,3 +199,17 @@ select pg_temp.whoami();
(1 row)
drop table public.whereami;
+-- for partitioned temp tables, ON COMMIT action should ignore storage-less
+-- partitioned parent table
+begin;
+create temp table temp_parted_oncommit_test (a int) partition by list (a) on commit delete rows;
+create temp table temp_parted_oncommit_test1 partition of temp_parted_oncommit_test for values in (1) on commit delete rows;
+insert into temp_parted_oncommit_test values (1);
+commit;
+-- temp_parted_oncommit_test1 must've been emptied during the commit
+select * from temp_parted_oncommit_test;
+ a
+---
+(0 rows)
+
+drop table temp_parted_oncommit_test;
diff --git a/src/test/regress/sql/temp.sql b/src/test/regress/sql/temp.sql
index 5183c727f5..0274bdb13f 100644
--- a/src/test/regress/sql/temp.sql
+++ b/src/test/regress/sql/temp.sql
@@ -151,3 +151,14 @@ select whoami();
select pg_temp.whoami();
drop table public.whereami;
+
+-- for partitioned temp tables, ON COMMIT action should ignore storage-less
+-- partitioned parent table
+begin;
+create temp table temp_parted_oncommit_test (a int) partition by list (a) on commit delete rows;
+create temp table temp_parted_oncommit_test1 partition of temp_parted_oncommit_test for values in (1) on commit delete rows;
+insert into temp_parted_oncommit_test values (1);
+commit;
+-- temp_parted_oncommit_test1 must've been emptied during the commit
+select * from temp_parted_oncommit_test;
+drop table temp_parted_oncommit_test;
--
2.11.0
On Fri, Nov 02, 2018 at 04:39:07PM +0900, Amit Langote wrote:
Agreed that they're two independent issues, although it wouldn't be such a
bad idea to fix them in one go, as they're both issues related to the
handling of ON COMMIT actions on tables in inheritance trees.
I have pushed 0001 which fixes the bug reported on this thread down to
v10, after tweaking a bit the patch after more review. I was testing
heap_truncate_one_rel() a bit more deeply and it actually happens that
it can work with matviews. Re-reading the thread and sleeping on it,
Tom was been actually suggesting to move the check one level down to
heap_truncate_one_rel(), which actually makes more sense. So I have
changed the patch so as a check on RELKIND_PARTITIONED_TABLE is done
instead of RELKIND_RELATION which is what has been proposed until now.
Regarding the second patch, could you start a second thread? The scope
is not only related to partitioned tables but also to inheritance trees
so this goes way back in time, and I think that we could attract a
better audience about the problem. I don't mind starting a thread
myself, not without your authorization as you wrote a patch to deal with
the problem. My apologies, I have not looked at what you are proposing
yet.
--
Michael
On 2018/11/05 9:19, Michael Paquier wrote:
On Fri, Nov 02, 2018 at 04:39:07PM +0900, Amit Langote wrote:
Agreed that they're two independent issues, although it wouldn't be such a
bad idea to fix them in one go, as they're both issues related to the
handling of ON COMMIT actions on tables in inheritance trees.I have pushed 0001 which fixes the bug reported on this thread down to
v10, after tweaking a bit the patch after more review. I was testing
heap_truncate_one_rel() a bit more deeply and it actually happens that
it can work with matviews. Re-reading the thread and sleeping on it,
Tom was been actually suggesting to move the check one level down to
heap_truncate_one_rel(), which actually makes more sense. So I have
changed the patch so as a check on RELKIND_PARTITIONED_TABLE is done
instead of RELKIND_RELATION which is what has been proposed until now.
Okay, it's good that heap_truncate_one_rel() continues to work for all
relation types that can have storage. Thanks for making the changes
yourself and committing.
Regarding the second patch, could you start a second thread? The scope
is not only related to partitioned tables but also to inheritance trees
so this goes way back in time, and I think that we could attract a
better audience about the problem. I don't mind starting a thread
myself, not without your authorization as you wrote a patch to deal with
the problem. My apologies, I have not looked at what you are proposing
yet.
Okay, no problem. I will post that patch in a new thread detailing what
the problem is and how the proposed patch fixes it.
Thanks,
Amit
On Mon, Nov 5, 2018 at 5:49 AM Michael Paquier <michael@paquier.xyz> wrote:
On Fri, Nov 02, 2018 at 04:39:07PM +0900, Amit Langote wrote:
Agreed that they're two independent issues, although it wouldn't be such
a
bad idea to fix them in one go, as they're both issues related to the
handling of ON COMMIT actions on tables in inheritance trees.I have pushed 0001 which fixes the bug reported on this thread down to
v10
Thanks Michael, Amit.
On 2018-Nov-02, Amit Langote wrote:
Well, performDeletion *does* drop the child, because when the parent is
dropped due to its ON COMMIT DROP action, it's done using:/*
* Since this is an automatic drop, rather than one
* directly initiated by the user, we pass the
* PERFORM_DELETION_INTERNAL flag.
*/
performDeletion(&object,
DROP_CASCADE, PERFORM_DELETION_INTERNAL);Note the DROP_CASCADE, which means its children will be deleted as part of
this.
I think this code should collect all the OIDs to be dropped, then use a
single performMultipleDeletions() at the end, after the heap_truncate
call is done. That seems better to me than a relkind check.
--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
On Mon, Nov 05, 2018 at 04:37:25PM -0300, Alvaro Herrera wrote:
I think this code should collect all the OIDs to be dropped, then use a
single performMultipleDeletions() at the end, after the heap_truncate
call is done. That seems better to me than a relkind check.
Yes, using a relkind checks seems error-prone to me, and you worked hard
to make sure that the drop machinery handles dependencies by itself,
(because you authored that work, right? :) ).
Amit has started a new thread about this problem as that's not only
related to partitions, but also to inheritance:
/messages/by-id/68f17907-ec98-1192-f99f-8011400517f5@lab.ntt.co.jp
Could it be possible to move the thread there? I have some other
comments about the patch, which I am going to provide there.
--
Michael
On 2018/11/06 4:37, Alvaro Herrera wrote:
On 2018-Nov-02, Amit Langote wrote:
Well, performDeletion *does* drop the child, because when the parent is
dropped due to its ON COMMIT DROP action, it's done using:/*
* Since this is an automatic drop, rather than one
* directly initiated by the user, we pass the
* PERFORM_DELETION_INTERNAL flag.
*/
performDeletion(&object,
DROP_CASCADE, PERFORM_DELETION_INTERNAL);Note the DROP_CASCADE, which means its children will be deleted as part of
this.I think this code should collect all the OIDs to be dropped, then use a
single performMultipleDeletions() at the end, after the heap_truncate
call is done. That seems better to me than a relkind check.
I've posted in a new thread about this:
* ON COMMIT actions and inheritance *
/messages/by-id/68f17907-ec98-1192-f99f-8011400517f5@lab.ntt.co.jp
I've to say that what you suggest seems to be a more elegant way to fix
this issue. My patch fixes it by reconstructing the oids_to_truncate list
by removing the OIDs of children that were dropped via the ON COMMIT DROP
action of the parent using a SearchSysCacheExists1 test.
Thanks,
Amit