diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2002-09-30 19:45:57 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2002-09-30 19:45:57 +0000 |
commit | a829ad15707b06d1e79657b2e8b3e63fd7fe4e11 (patch) | |
tree | 99b6f1a988a1bb7f96a75bc29b99dd35b59d926a | |
parent | 826692788df2772cae77ae0453e40b0a664e735f (diff) | |
download | postgresql-a829ad15707b06d1e79657b2e8b3e63fd7fe4e11.tar.gz |
Back-patch fix to not change pg_database.datvacuumxid or truncate CLOG
when an unprivileged user runs VACUUM.
-rw-r--r-- | src/backend/commands/vacuum.c | 48 |
1 files changed, 34 insertions, 14 deletions
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index a853344b9e..5def52a9a2 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -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; } |