Back-patch fix to not change pg_database.datvacuumxid or truncate CLOG

when an unprivileged user runs VACUUM.
REL7_2_STABLE
Tom Lane 24 years ago
parent 826692788d
commit a829ad1570
  1. 48
      src/backend/commands/vacuum.c

@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * 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 */ /* non-export function prototypes */
static void vacuum_init(VacuumStmt *vacstmt); 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 VRelList getrels(Name VacRelP, const char *stmttype);
static void vac_update_dbstats(Oid dbid, static void vac_update_dbstats(Oid dbid,
TransactionId vacuumXID, TransactionId vacuumXID,
TransactionId frozenXID); TransactionId frozenXID);
static void vac_truncate_clog(TransactionId vacuumXID, static void vac_truncate_clog(TransactionId vacuumXID,
TransactionId frozenXID); 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 full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt);
static void scan_heap(VRelStats *vacrelstats, Relation onerel, static void scan_heap(VRelStats *vacrelstats, Relation onerel,
VacPageList vacuum_pages, VacPageList fraged_pages); VacPageList vacuum_pages, VacPageList fraged_pages);
@ -171,6 +171,7 @@ vacuum(VacuumStmt *vacstmt)
const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE"; const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE";
NameData VacRel; NameData VacRel;
Name VacRelName; Name VacRelName;
bool all_rels;
VRelList vrl, VRelList vrl,
cur; cur;
@ -218,6 +219,9 @@ vacuum(VacuumStmt *vacstmt)
else else
VacRelName = NULL; 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) */ /* Build list of relations to process (note this lives in vac_context) */
vrl = getrels(VacRelName, stmttype); vrl = getrels(VacRelName, stmttype);
@ -236,13 +240,16 @@ vacuum(VacuumStmt *vacstmt)
for (cur = vrl; cur != (VRelList) NULL; cur = cur->vrl_next) for (cur = vrl; cur != (VRelList) NULL; cur = cur->vrl_next)
{ {
if (vacstmt->vacuum) 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) if (vacstmt->analyze)
analyze_rel(cur->vrl_relid, vacstmt); analyze_rel(cur->vrl_relid, vacstmt);
} }
/* clean up */ /* clean up */
vacuum_shutdown(vacstmt); vacuum_shutdown(vacstmt, all_rels);
} }
/* /*
@ -296,7 +303,7 @@ vacuum_init(VacuumStmt *vacstmt)
} }
static void static void
vacuum_shutdown(VacuumStmt *vacstmt) vacuum_shutdown(VacuumStmt *vacstmt, bool all_rels)
{ {
/* on entry, we are not in a transaction */ /* on entry, we are not in a transaction */
@ -304,11 +311,11 @@ vacuum_shutdown(VacuumStmt *vacstmt)
StartTransactionCommand(); StartTransactionCommand();
/* /*
* If we did a database-wide VACUUM, update the database's pg_database * If we completed a database-wide VACUUM without skipping any
* row with info about the transaction IDs used, and try to truncate * relations, update the database's pg_database row with info
* pg_clog. * 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, vac_update_dbstats(MyDatabaseId,
initialOldestXmin, initialFreezeLimit); initialOldestXmin, initialFreezeLimit);
@ -702,6 +709,11 @@ vac_truncate_clog(TransactionId vacuumXID, TransactionId frozenXID)
/* /*
* vacuum_rel() -- vacuum one heap relation * 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 * 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 * 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 * 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. * At entry and exit, we are not inside a transaction.
*/ */
static void static bool
vacuum_rel(Oid relid, VacuumStmt *vacstmt) vacuum_rel(Oid relid, VacuumStmt *vacstmt)
{ {
LOCKMODE lmode; LOCKMODE lmode;
Relation onerel; Relation onerel;
LockRelId onerelid; LockRelId onerelid;
Oid toast_relid; Oid toast_relid;
bool result;
/* Begin a transaction for vacuuming this relation */ /* Begin a transaction for vacuuming this relation */
StartTransactionCommand(); StartTransactionCommand();
@ -736,7 +749,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
0, 0, 0)) 0, 0, 0))
{ {
CommitTransactionCommand(); CommitTransactionCommand();
return; return true; /* okay 'cause no data there */
} }
/* /*
@ -768,7 +781,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
RelationGetRelationName(onerel)); RelationGetRelationName(onerel));
heap_close(onerel, lmode); heap_close(onerel, lmode);
CommitTransactionCommand(); CommitTransactionCommand();
return; return false;
} }
/* /*
@ -797,6 +810,8 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
else else
lazy_vacuum_rel(onerel, vacstmt); lazy_vacuum_rel(onerel, vacstmt);
result = true; /* did the vacuum */
/* all done with this class, but hold lock until commit */ /* all done with this class, but hold lock until commit */
heap_close(onerel, NoLock); heap_close(onerel, NoLock);
@ -813,12 +828,17 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
* statistics are totally unimportant for toast relations. * statistics are totally unimportant for toast relations.
*/ */
if (toast_relid != InvalidOid) 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. * Now release the session-level lock on the master table.
*/ */
UnlockRelationForSession(&onerelid, lmode); UnlockRelationForSession(&onerelid, lmode);
return result;
} }

Loading…
Cancel
Save