Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4e086f7

Browse files
committed
Dept. of second thoughts: rejigger the TRUNCATE ... CASCADE patch so that
relations are still checked for permissions etc as soon as they areopened. The original form of the patch could hold exclusive lock for along time on relations that the user doesn't even have permissions toaccess, let alone truncate.
1 parenta6add72 commit4e086f7

File tree

1 file changed

+63
-68
lines changed

1 file changed

+63
-68
lines changed

‎src/backend/commands/tablecmds.c

Lines changed: 63 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.178 2006/03/0303:30:52 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.179 2006/03/0318:25:14 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -156,6 +156,7 @@ typedef struct NewColumnValue
156156
}NewColumnValue;
157157

158158

159+
staticvoidtruncate_check_rel(Relationrel);
159160
staticList*MergeAttributes(List*schema,List*supers,boolistemp,
160161
List**supOids,List**supconstr,int*supOidCount);
161162
staticboolchange_varattnos_of_a_node(Node*node,constAttrNumber*newattno);
@@ -539,33 +540,33 @@ void
539540
ExecuteTruncate(TruncateStmt*stmt)
540541
{
541542
List*rels=NIL;
542-
List*directRelids=NIL;
543+
List*relids=NIL;
543544
ListCell*cell;
544-
Oidrelid;
545-
Relationrel;
546545

547546
/*
548-
* Open andexclusive-lock all the explicitly-specified relations
547+
* Open,exclusive-lock, and check all the explicitly-specified relations
549548
*/
550549
foreach(cell,stmt->relations)
551550
{
552551
RangeVar*rv=lfirst(cell);
552+
Relationrel;
553553

554554
rel=heap_openrv(rv,AccessExclusiveLock);
555+
truncate_check_rel(rel);
555556
rels=lappend(rels,rel);
556-
directRelids=lappend_oid(directRelids,RelationGetRelid(rel));
557+
relids=lappend_oid(relids,RelationGetRelid(rel));
557558
}
558559

559560
/*
560561
* In CASCADE mode, suck in all referencing relations as well. This
561562
* requires multiple iterations to find indirectly-dependent relations.
562563
* At each phase, we need to exclusive-lock new rels before looking
563-
* for their dependencies, else we might miss something.
564+
* for their dependencies, else we might miss something. Also, we
565+
* check each rel as soon as we open it, to avoid a faux pas such as
566+
* holding lock for a long time on a rel we have no permissions for.
564567
*/
565568
if (stmt->behavior==DROP_CASCADE)
566569
{
567-
List*relids=list_copy(directRelids);
568-
569570
for (;;)
570571
{
571572
List*newrelids;
@@ -576,70 +577,20 @@ ExecuteTruncate(TruncateStmt *stmt)
576577

577578
foreach(cell,newrelids)
578579
{
579-
relid=lfirst_oid(cell);
580+
Oidrelid=lfirst_oid(cell);
581+
Relationrel;
582+
580583
rel=heap_open(relid,AccessExclusiveLock);
584+
ereport(NOTICE,
585+
(errmsg("truncate cascades to table \"%s\"",
586+
RelationGetRelationName(rel))));
587+
truncate_check_rel(rel);
581588
rels=lappend(rels,rel);
582589
relids=lappend_oid(relids,relid);
583590
}
584591
}
585592
}
586593

587-
/* now check all involved relations */
588-
foreach(cell,rels)
589-
{
590-
rel= (Relation)lfirst(cell);
591-
relid=RelationGetRelid(rel);
592-
593-
/*
594-
* If this table was added to the command by CASCADE, report it.
595-
* We don't do this earlier because if we error out on one of the
596-
* tables, it'd be confusing to list subsequently-added tables.
597-
*/
598-
if (stmt->behavior==DROP_CASCADE&&
599-
!list_member_oid(directRelids,relid))
600-
ereport(NOTICE,
601-
(errmsg("truncate cascades to table \"%s\"",
602-
RelationGetRelationName(rel))));
603-
604-
/* Only allow truncate on regular tables */
605-
if (rel->rd_rel->relkind!=RELKIND_RELATION)
606-
ereport(ERROR,
607-
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
608-
errmsg("\"%s\" is not a table",
609-
RelationGetRelationName(rel))));
610-
611-
/* Permissions checks */
612-
if (!pg_class_ownercheck(RelationGetRelid(rel),GetUserId()))
613-
aclcheck_error(ACLCHECK_NOT_OWNER,ACL_KIND_CLASS,
614-
RelationGetRelationName(rel));
615-
616-
if (!allowSystemTableMods&&IsSystemRelation(rel))
617-
ereport(ERROR,
618-
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
619-
errmsg("permission denied: \"%s\" is a system catalog",
620-
RelationGetRelationName(rel))));
621-
622-
/*
623-
* We can never allow truncation of shared or nailed-in-cache
624-
* relations, because we can't support changing their relfilenode
625-
* values.
626-
*/
627-
if (rel->rd_rel->relisshared||rel->rd_isnailed)
628-
ereport(ERROR,
629-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
630-
errmsg("cannot truncate system relation \"%s\"",
631-
RelationGetRelationName(rel))));
632-
633-
/*
634-
* Don't allow truncate on temp tables of other backends ... their
635-
* local buffer manager is not going to cope.
636-
*/
637-
if (isOtherTempNamespace(RelationGetNamespace(rel)))
638-
ereport(ERROR,
639-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
640-
errmsg("cannot truncate temporary tables of other sessions")));
641-
}
642-
643594
/*
644595
* Check foreign key references. In CASCADE mode, this should be
645596
* unnecessary since we just pulled in all the references; but as
@@ -657,11 +608,10 @@ ExecuteTruncate(TruncateStmt *stmt)
657608
*/
658609
foreach(cell,rels)
659610
{
611+
Relationrel= (Relation)lfirst(cell);
660612
Oidheap_relid;
661613
Oidtoast_relid;
662614

663-
rel= (Relation)lfirst(cell);
664-
665615
/*
666616
* Create a new empty storage file for the relation, and assign it as
667617
* the relfilenode value.The old storage file is scheduled for
@@ -691,6 +641,51 @@ ExecuteTruncate(TruncateStmt *stmt)
691641
}
692642
}
693643

644+
/*
645+
* Check that a given rel is safe to truncate. Subroutine for ExecuteTruncate
646+
*/
647+
staticvoid
648+
truncate_check_rel(Relationrel)
649+
{
650+
/* Only allow truncate on regular tables */
651+
if (rel->rd_rel->relkind!=RELKIND_RELATION)
652+
ereport(ERROR,
653+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
654+
errmsg("\"%s\" is not a table",
655+
RelationGetRelationName(rel))));
656+
657+
/* Permissions checks */
658+
if (!pg_class_ownercheck(RelationGetRelid(rel),GetUserId()))
659+
aclcheck_error(ACLCHECK_NOT_OWNER,ACL_KIND_CLASS,
660+
RelationGetRelationName(rel));
661+
662+
if (!allowSystemTableMods&&IsSystemRelation(rel))
663+
ereport(ERROR,
664+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
665+
errmsg("permission denied: \"%s\" is a system catalog",
666+
RelationGetRelationName(rel))));
667+
668+
/*
669+
* We can never allow truncation of shared or nailed-in-cache
670+
* relations, because we can't support changing their relfilenode
671+
* values.
672+
*/
673+
if (rel->rd_rel->relisshared||rel->rd_isnailed)
674+
ereport(ERROR,
675+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
676+
errmsg("cannot truncate system relation \"%s\"",
677+
RelationGetRelationName(rel))));
678+
679+
/*
680+
* Don't allow truncate on temp tables of other backends ... their
681+
* local buffer manager is not going to cope.
682+
*/
683+
if (isOtherTempNamespace(RelationGetNamespace(rel)))
684+
ereport(ERROR,
685+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
686+
errmsg("cannot truncate temporary tables of other sessions")));
687+
}
688+
694689
/*----------
695690
* MergeAttributes
696691
*Returns new schema given initial schema and superclasses.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp