mirror of
https://github.com/postgres/postgres.git
synced 2026-04-09 11:06:21 -04:00
Back-patch fix to not change pg_database.datvacuumxid or truncate CLOG
when an unprivileged user runs VACUUM.
This commit is contained in:
parent
826692788d
commit
a829ad1570
1 changed files with 34 additions and 14 deletions
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.213.2.1 2002/04/02 05:12:00 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.213.2.2 2002/09/30 19:45:57 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
@ -119,14 +119,14 @@ static TransactionId initialFreezeLimit;
|
|||
|
||||
/* non-export function prototypes */
|
||||
static void vacuum_init(VacuumStmt *vacstmt);
|
||||
static void vacuum_shutdown(VacuumStmt *vacstmt);
|
||||
static void vacuum_shutdown(VacuumStmt *vacstmt, bool all_rels);
|
||||
static VRelList getrels(Name VacRelP, const char *stmttype);
|
||||
static void vac_update_dbstats(Oid dbid,
|
||||
TransactionId vacuumXID,
|
||||
TransactionId frozenXID);
|
||||
static void vac_truncate_clog(TransactionId vacuumXID,
|
||||
TransactionId frozenXID);
|
||||
static void vacuum_rel(Oid relid, VacuumStmt *vacstmt);
|
||||
static bool vacuum_rel(Oid relid, VacuumStmt *vacstmt);
|
||||
static void full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt);
|
||||
static void scan_heap(VRelStats *vacrelstats, Relation onerel,
|
||||
VacPageList vacuum_pages, VacPageList fraged_pages);
|
||||
|
|
@ -171,6 +171,7 @@ vacuum(VacuumStmt *vacstmt)
|
|||
const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE";
|
||||
NameData VacRel;
|
||||
Name VacRelName;
|
||||
bool all_rels;
|
||||
VRelList vrl,
|
||||
cur;
|
||||
|
||||
|
|
@ -218,6 +219,9 @@ vacuum(VacuumStmt *vacstmt)
|
|||
else
|
||||
VacRelName = NULL;
|
||||
|
||||
/* Assume we are processing everything unless one table is mentioned */
|
||||
all_rels = (VacRelName == NULL);
|
||||
|
||||
/* Build list of relations to process (note this lives in vac_context) */
|
||||
vrl = getrels(VacRelName, stmttype);
|
||||
|
||||
|
|
@ -236,13 +240,16 @@ vacuum(VacuumStmt *vacstmt)
|
|||
for (cur = vrl; cur != (VRelList) NULL; cur = cur->vrl_next)
|
||||
{
|
||||
if (vacstmt->vacuum)
|
||||
vacuum_rel(cur->vrl_relid, vacstmt);
|
||||
{
|
||||
if (! vacuum_rel(cur->vrl_relid, vacstmt))
|
||||
all_rels = false; /* forget about updating dbstats */
|
||||
}
|
||||
if (vacstmt->analyze)
|
||||
analyze_rel(cur->vrl_relid, vacstmt);
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
vacuum_shutdown(vacstmt);
|
||||
vacuum_shutdown(vacstmt, all_rels);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -296,7 +303,7 @@ vacuum_init(VacuumStmt *vacstmt)
|
|||
}
|
||||
|
||||
static void
|
||||
vacuum_shutdown(VacuumStmt *vacstmt)
|
||||
vacuum_shutdown(VacuumStmt *vacstmt, bool all_rels)
|
||||
{
|
||||
/* on entry, we are not in a transaction */
|
||||
|
||||
|
|
@ -304,11 +311,11 @@ vacuum_shutdown(VacuumStmt *vacstmt)
|
|||
StartTransactionCommand();
|
||||
|
||||
/*
|
||||
* If we did a database-wide VACUUM, update the database's pg_database
|
||||
* row with info about the transaction IDs used, and try to truncate
|
||||
* pg_clog.
|
||||
* If we completed a database-wide VACUUM without skipping any
|
||||
* relations, update the database's pg_database row with info
|
||||
* about the transaction IDs used, and try to truncate pg_clog.
|
||||
*/
|
||||
if (vacstmt->vacuum && vacstmt->vacrel == NULL)
|
||||
if (vacstmt->vacuum && all_rels)
|
||||
{
|
||||
vac_update_dbstats(MyDatabaseId,
|
||||
initialOldestXmin, initialFreezeLimit);
|
||||
|
|
@ -702,6 +709,11 @@ vac_truncate_clog(TransactionId vacuumXID, TransactionId frozenXID)
|
|||
/*
|
||||
* vacuum_rel() -- vacuum one heap relation
|
||||
*
|
||||
* Returns TRUE if we actually processed the relation (or can ignore it
|
||||
* for some reason), FALSE if we failed to process it due to permissions
|
||||
* or other reasons. (A FALSE result really means that some data
|
||||
* may have been left unvacuumed, so we can't update XID stats.)
|
||||
*
|
||||
* Doing one heap at a time incurs extra overhead, since we need to
|
||||
* check that the heap exists again just before we vacuum it. The
|
||||
* reason that we do this is so that vacuuming can be spread across
|
||||
|
|
@ -710,13 +722,14 @@ vac_truncate_clog(TransactionId vacuumXID, TransactionId frozenXID)
|
|||
*
|
||||
* At entry and exit, we are not inside a transaction.
|
||||
*/
|
||||
static void
|
||||
static bool
|
||||
vacuum_rel(Oid relid, VacuumStmt *vacstmt)
|
||||
{
|
||||
LOCKMODE lmode;
|
||||
Relation onerel;
|
||||
LockRelId onerelid;
|
||||
Oid toast_relid;
|
||||
bool result;
|
||||
|
||||
/* Begin a transaction for vacuuming this relation */
|
||||
StartTransactionCommand();
|
||||
|
|
@ -736,7 +749,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
|
|||
0, 0, 0))
|
||||
{
|
||||
CommitTransactionCommand();
|
||||
return;
|
||||
return true; /* okay 'cause no data there */
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -768,7 +781,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
|
|||
RelationGetRelationName(onerel));
|
||||
heap_close(onerel, lmode);
|
||||
CommitTransactionCommand();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -797,6 +810,8 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
|
|||
else
|
||||
lazy_vacuum_rel(onerel, vacstmt);
|
||||
|
||||
result = true; /* did the vacuum */
|
||||
|
||||
/* all done with this class, but hold lock until commit */
|
||||
heap_close(onerel, NoLock);
|
||||
|
||||
|
|
@ -813,12 +828,17 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
|
|||
* statistics are totally unimportant for toast relations.
|
||||
*/
|
||||
if (toast_relid != InvalidOid)
|
||||
vacuum_rel(toast_relid, vacstmt);
|
||||
{
|
||||
if (! vacuum_rel(toast_relid, vacstmt))
|
||||
result = false; /* failed to vacuum the TOAST table? */
|
||||
}
|
||||
|
||||
/*
|
||||
* Now release the session-level lock on the master table.
|
||||
*/
|
||||
UnlockRelationForSession(&onerelid, lmode);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue