summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2002-09-30 19:45:57 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2002-09-30 19:45:57 +0000
commita829ad15707b06d1e79657b2e8b3e63fd7fe4e11 (patch)
tree99b6f1a988a1bb7f96a75bc29b99dd35b59d926a
parent826692788df2772cae77ae0453e40b0a664e735f (diff)
downloadpostgresql-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.c48
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;
}