aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2002-04-02 01:03:07 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2002-04-02 01:03:07 +0000
commit1dc43ea75f92d46b137ca5d92de5d9d1ecc34af2 (patch)
tree6c89a396929b5674be08d15ac80df886e6487a15 /src
parent789ddcb5fe0584fd7524db97909ff43cb2ac37f6 (diff)
downloadpostgresql-1dc43ea75f92d46b137ca5d92de5d9d1ecc34af2.tar.gz
postgresql-1dc43ea75f92d46b137ca5d92de5d9d1ecc34af2.zip
Make VACUUM handle schema-qualified relation names properly.
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/analyze.c60
-rw-r--r--src/backend/commands/vacuum.c174
-rw-r--r--src/backend/commands/vacuumlazy.c7
-rw-r--r--src/backend/utils/adt/ri_triggers.c18
-rw-r--r--src/backend/utils/cache/lsyscache.c32
-rw-r--r--src/include/utils/lsyscache.h3
6 files changed, 152 insertions, 142 deletions
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index df9735089aa..ea778de3360 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.29 2002/03/21 23:27:20 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.30 2002/04/02 01:03:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,6 +20,7 @@
#include "access/tuptoaster.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
+#include "catalog/pg_namespace.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
@@ -30,6 +31,7 @@
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/tuplesort.h"
@@ -147,7 +149,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
numrows;
double totalrows;
HeapTuple *rows;
- HeapTuple tuple;
if (vacstmt->verbose)
elevel = INFO;
@@ -173,46 +174,61 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
* Race condition -- if the pg_class tuple has gone away since the
* last time we saw it, we don't need to process it.
*/
- tuple = SearchSysCache(RELOID,
- ObjectIdGetDatum(relid),
- 0, 0, 0);
- if (!HeapTupleIsValid(tuple))
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(relid),
+ 0, 0, 0))
{
CommitTransactionCommand();
return;
}
/*
- * We can ANALYZE any table except pg_statistic. See update_attstats
+ * Open the class, getting only a read lock on it, and check
+ * permissions. Permissions check should match vacuum's check!
*/
- if (strcmp(NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname),
- StatisticRelationName) == 0)
+ onerel = relation_open(relid, AccessShareLock);
+
+ if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) ||
+ (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared)))
{
- ReleaseSysCache(tuple);
+ /* No need for a WARNING if we already complained during VACUUM */
+ if (!vacstmt->vacuum)
+ elog(WARNING, "Skipping \"%s\" --- only table or database owner can ANALYZE it",
+ RelationGetRelationName(onerel));
+ relation_close(onerel, AccessShareLock);
CommitTransactionCommand();
return;
}
- ReleaseSysCache(tuple);
/*
- * Open the class, getting only a read lock on it, and check
- * permissions. Permissions check should match vacuum's check!
+ * Check that it's a plain table; we used to do this in getrels() but
+ * seems safer to check after we've locked the relation.
*/
- onerel = heap_open(relid, AccessShareLock);
-
- if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) ||
- (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared)))
+ if (onerel->rd_rel->relkind != RELKIND_RELATION)
{
/* No need for a WARNING if we already complained during VACUUM */
if (!vacstmt->vacuum)
- elog(WARNING, "Skipping \"%s\" --- only table or database owner can ANALYZE it",
+ elog(WARNING, "Skipping \"%s\" --- can not process indexes, views or special system tables",
RelationGetRelationName(onerel));
- heap_close(onerel, NoLock);
+ relation_close(onerel, AccessShareLock);
+ CommitTransactionCommand();
+ return;
+ }
+
+ /*
+ * We can ANALYZE any table except pg_statistic. See update_attstats
+ */
+ if (RelationGetNamespace(onerel) == PG_CATALOG_NAMESPACE &&
+ strcmp(RelationGetRelationName(onerel), StatisticRelationName) == 0)
+ {
+ relation_close(onerel, AccessShareLock);
CommitTransactionCommand();
return;
}
- elog(elevel, "Analyzing %s", RelationGetRelationName(onerel));
+ elog(elevel, "Analyzing %s.%s",
+ get_namespace_name(RelationGetNamespace(onerel)),
+ RelationGetRelationName(onerel));
/*
* Determine which columns to analyze
@@ -266,7 +282,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
*/
if (attr_cnt <= 0)
{
- heap_close(onerel, NoLock);
+ relation_close(onerel, NoLock);
CommitTransactionCommand();
return;
}
@@ -353,7 +369,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
* before we commit. (If someone did, they'd fail to clean up the
* entries we made in pg_statistic.)
*/
- heap_close(onerel, NoLock);
+ relation_close(onerel, NoLock);
/* Commit and release working memory */
CommitTransactionCommand();
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 6553529cdcf..fff0320eca2 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.220 2002/03/31 06:26:30 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.221 2002/04/02 01:03:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,6 +27,7 @@
#include "access/xlog.h"
#include "catalog/catalog.h"
#include "catalog/catname.h"
+#include "catalog/namespace.h"
#include "catalog/pg_database.h"
#include "catalog/pg_index.h"
#include "commands/vacuum.h"
@@ -40,19 +41,12 @@
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
+#include "utils/lsyscache.h"
#include "utils/relcache.h"
#include "utils/syscache.h"
#include "pgstat.h"
-typedef struct VRelListData
-{
- Oid vrl_relid;
- struct VRelListData *vrl_next;
-} VRelListData;
-
-typedef VRelListData *VRelList;
-
typedef struct VacPageData
{
BlockNumber blkno; /* BlockNumber of this Page */
@@ -118,13 +112,13 @@ static TransactionId initialFreezeLimit;
/* non-export function prototypes */
static void vacuum_init(VacuumStmt *vacstmt);
static void vacuum_shutdown(VacuumStmt *vacstmt);
-static VRelList getrels(Name VacRelP, const char *stmttype);
+static List *getrels(const RangeVar *vacrel, 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 void vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind);
static void full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt);
static void scan_heap(VRelStats *vacrelstats, Relation onerel,
VacPageList vacuum_pages, VacPageList fraged_pages);
@@ -167,10 +161,13 @@ void
vacuum(VacuumStmt *vacstmt)
{
const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE";
- NameData VacRel;
- Name VacRelName;
- VRelList vrl,
- cur;
+ List *vrl,
+ *cur;
+
+ if (vacstmt->verbose)
+ elevel = INFO;
+ else
+ elevel = DEBUG1;
/*
* We cannot run VACUUM inside a user transaction block; if we were
@@ -189,11 +186,6 @@ vacuum(VacuumStmt *vacstmt)
*/
pgstat_vacuum_tabstat();
- if (vacstmt->verbose)
- elevel = INFO;
- else
- elevel = DEBUG1;
-
/*
* Create special memory context for cross-transaction storage.
*
@@ -207,17 +199,8 @@ vacuum(VacuumStmt *vacstmt)
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
- /* Convert relname, which is just a string, to a Name */
- if (vacstmt->relation)
- {
- namestrcpy(&VacRel, vacstmt->relation->relname);
- VacRelName = &VacRel;
- }
- else
- VacRelName = NULL;
-
/* Build list of relations to process (note this lives in vac_context) */
- vrl = getrels(VacRelName, stmttype);
+ vrl = getrels(vacstmt->relation, stmttype);
/*
* Start up the vacuum cleaner.
@@ -231,12 +214,14 @@ vacuum(VacuumStmt *vacstmt)
* ANALYZE part runs as a separate transaction from the VACUUM to
* further reduce locking.
*/
- for (cur = vrl; cur != (VRelList) NULL; cur = cur->vrl_next)
+ foreach(cur, vrl)
{
+ Oid relid = (Oid) lfirsti(cur);
+
if (vacstmt->vacuum)
- vacuum_rel(cur->vrl_relid, vacstmt);
+ vacuum_rel(relid, vacstmt, RELKIND_RELATION);
if (vacstmt->analyze)
- analyze_rel(cur->vrl_relid, vacstmt);
+ analyze_rel(relid, vacstmt);
}
/* clean up */
@@ -323,86 +308,58 @@ vacuum_shutdown(VacuumStmt *vacstmt)
}
/*
- * Build a list of VRelListData nodes for each relation to be processed
+ * Build a list of Oids for each relation to be processed
*
* The list is built in vac_context so that it will survive across our
* per-relation transactions.
*/
-static VRelList
-getrels(Name VacRelP, const char *stmttype)
+static List *
+getrels(const RangeVar *vacrel, const char *stmttype)
{
- Relation rel;
- TupleDesc tupdesc;
- HeapScanDesc scan;
- HeapTuple tuple;
- VRelList vrl,
- cur;
- Datum d;
- char *rname;
- char rkind;
- bool n;
- ScanKeyData key;
-
- if (VacRelP)
+ List *vrl = NIL;
+ MemoryContext oldcontext;
+
+ if (vacrel)
{
- /*
- * we could use the cache here, but it is clearer to use scankeys
- * for both vacuum cases, bjm 2000/01/19
- */
- ScanKeyEntryInitialize(&key, 0x0, Anum_pg_class_relname,
- F_NAMEEQ,
- PointerGetDatum(NameStr(*VacRelP)));
+ /* Process specific relation */
+ Oid relid;
+
+ relid = RangeVarGetRelid(vacrel, false);
+
+ /* Make a relation list entry for this guy */
+ oldcontext = MemoryContextSwitchTo(vac_context);
+ vrl = lappendi(vrl, relid);
+ MemoryContextSwitchTo(oldcontext);
}
else
{
- /* find all plain relations listed in pg_class */
- ScanKeyEntryInitialize(&key, 0x0, Anum_pg_class_relkind,
- F_CHAREQ, CharGetDatum(RELKIND_RELATION));
- }
-
- vrl = cur = (VRelList) NULL;
-
- rel = heap_openr(RelationRelationName, AccessShareLock);
- tupdesc = RelationGetDescr(rel);
-
- scan = heap_beginscan(rel, false, SnapshotNow, 1, &key);
+ /* Process all plain relations listed in pg_class */
+ Relation pgclass;
+ HeapScanDesc scan;
+ HeapTuple tuple;
+ ScanKeyData key;
- while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
- {
- d = heap_getattr(tuple, Anum_pg_class_relname, tupdesc, &n);
- rname = (char *) DatumGetName(d);
+ ScanKeyEntryInitialize(&key, 0x0,
+ Anum_pg_class_relkind,
+ F_CHAREQ,
+ CharGetDatum(RELKIND_RELATION));
- d = heap_getattr(tuple, Anum_pg_class_relkind, tupdesc, &n);
- rkind = DatumGetChar(d);
+ pgclass = heap_openr(RelationRelationName, AccessShareLock);
- if (rkind != RELKIND_RELATION)
- {
- elog(WARNING, "%s: can not process indexes, views or special system tables",
- stmttype);
- continue;
- }
+ scan = heap_beginscan(pgclass, false, SnapshotNow, 1, &key);
- /* Make a relation list entry for this guy */
- if (vrl == (VRelList) NULL)
- vrl = cur = (VRelList)
- MemoryContextAlloc(vac_context, sizeof(VRelListData));
- else
+ while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{
- cur->vrl_next = (VRelList)
- MemoryContextAlloc(vac_context, sizeof(VRelListData));
- cur = cur->vrl_next;
+ /* Make a relation list entry for this guy */
+ oldcontext = MemoryContextSwitchTo(vac_context);
+ vrl = lappendi(vrl, tuple->t_data->t_oid);
+ MemoryContextSwitchTo(oldcontext);
}
- cur->vrl_relid = tuple->t_data->t_oid;
- cur->vrl_next = (VRelList) NULL;
+ heap_endscan(scan);
+ heap_close(pgclass, AccessShareLock);
}
- heap_endscan(scan);
- heap_close(rel, AccessShareLock);
-
- if (vrl == NULL)
- elog(WARNING, "%s: table not found", stmttype);
-
return vrl;
}
@@ -663,7 +620,7 @@ vac_truncate_clog(TransactionId vacuumXID, TransactionId frozenXID)
* At entry and exit, we are not inside a transaction.
*/
static void
-vacuum_rel(Oid relid, VacuumStmt *vacstmt)
+vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
{
LOCKMODE lmode;
Relation onerel;
@@ -710,14 +667,27 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
* Note we choose to treat permissions failure as a WARNING and keep
* trying to vacuum the rest of the DB --- is this appropriate?
*/
- onerel = heap_open(relid, lmode);
+ onerel = relation_open(relid, lmode);
if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) ||
(is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared)))
{
elog(WARNING, "Skipping \"%s\" --- only table or database owner can VACUUM it",
RelationGetRelationName(onerel));
- heap_close(onerel, lmode);
+ relation_close(onerel, lmode);
+ CommitTransactionCommand();
+ return;
+ }
+
+ /*
+ * Check that it's a plain table; we used to do this in getrels() but
+ * seems safer to check after we've locked the relation.
+ */
+ if (onerel->rd_rel->relkind != expected_relkind)
+ {
+ elog(WARNING, "Skipping \"%s\" --- can not process indexes, views or special system tables",
+ RelationGetRelationName(onerel));
+ relation_close(onerel, lmode);
CommitTransactionCommand();
return;
}
@@ -749,7 +719,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
lazy_vacuum_rel(onerel, vacstmt);
/* all done with this class, but hold lock until commit */
- heap_close(onerel, NoLock);
+ relation_close(onerel, NoLock);
/*
* Complete the transaction and free all temporary memory used.
@@ -764,7 +734,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
* statistics are totally unimportant for toast relations.
*/
if (toast_relid != InvalidOid)
- vacuum_rel(toast_relid, vacstmt);
+ vacuum_rel(toast_relid, vacstmt, RELKIND_TOASTVALUE);
/*
* Now release the session-level lock on the master table.
@@ -954,7 +924,9 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
vac_init_rusage(&ru0);
relname = RelationGetRelationName(onerel);
- elog(elevel, "--Relation %s--", relname);
+ elog(elevel, "--Relation %s.%s--",
+ get_namespace_name(RelationGetNamespace(onerel)),
+ relname);
empty_pages = new_pages = changed_pages = empty_end_pages = 0;
num_tuples = tups_vacuumed = nkeep = nunused = 0;
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index 516fe35f2a9..b7da9f5bbb0 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -31,7 +31,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.13 2002/03/06 06:09:38 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.14 2002/04/02 01:03:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -45,6 +45,7 @@
#include "storage/freespace.h"
#include "storage/sinval.h"
#include "storage/smgr.h"
+#include "utils/lsyscache.h"
/*
@@ -207,7 +208,9 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
vac_init_rusage(&ru0);
relname = RelationGetRelationName(onerel);
- elog(elevel, "--Relation %s--", relname);
+ elog(elevel, "--Relation %s.%s--",
+ get_namespace_name(RelationGetNamespace(onerel)),
+ relname);
empty_pages = changed_pages = 0;
num_tuples = tups_vacuumed = nkeep = nunused = 0;
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index b073e514573..f9accfefc24 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -18,7 +18,7 @@
* Portions Copyright (c) 2000-2001, PostgreSQL Global Development Group
* Copyright 1999 Jan Wieck
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.35 2002/04/01 22:36:10 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.36 2002/04/02 01:03:07 tgl Exp $
*
* ----------
*/
@@ -33,11 +33,10 @@
#include "postgres.h"
-#include "catalog/pg_namespace.h"
#include "catalog/pg_operator.h"
#include "commands/trigger.h"
#include "executor/spi_priv.h"
-#include "nodes/makefuncs.h"
+#include "utils/lsyscache.h"
#include "miscadmin.h"
@@ -2954,18 +2953,7 @@ quoteOneName(char *buffer, const char *name)
static void
quoteRelationName(char *buffer, Relation rel)
{
- HeapTuple tuple;
- char *nsname;
-
- tuple = SearchSysCache(NAMESPACEOID,
- ObjectIdGetDatum(RelationGetNamespace(rel)),
- 0, 0, 0);
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "Failed to lookup namespace %u of relation %s",
- RelationGetNamespace(rel), RelationGetRelationName(rel));
- nsname = NameStr(((Form_pg_namespace) GETSTRUCT(tuple))->nspname);
- quoteOneName(buffer, nsname);
- ReleaseSysCache(tuple);
+ quoteOneName(buffer, get_namespace_name(RelationGetNamespace(rel)));
buffer += strlen(buffer);
*buffer++ = '.';
quoteOneName(buffer, RelationGetRelationName(rel));
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 6ec682f5206..bf0981e6372 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.67 2002/03/29 19:06:15 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.68 2002/04/02 01:03:07 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -17,6 +17,7 @@
#include "access/tupmacs.h"
#include "catalog/pg_amop.h"
+#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
@@ -1279,6 +1280,35 @@ free_attstatsslot(Oid atttype,
pfree(numbers);
}
+/* ---------- PG_NAMESPACE CACHE ---------- */
+
+/*
+ * get_namespace_name
+ * Returns the name of a given namespace
+ *
+ * Returns a palloc'd copy of the string, or NULL if no such namespace.
+ */
+char *
+get_namespace_name(Oid nspid)
+{
+ HeapTuple tp;
+
+ tp = SearchSysCache(NAMESPACEOID,
+ ObjectIdGetDatum(nspid),
+ 0, 0, 0);
+ if (HeapTupleIsValid(tp))
+ {
+ Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
+ char *result;
+
+ result = pstrdup(NameStr(nsptup->nspname));
+ ReleaseSysCache(tp);
+ return result;
+ }
+ else
+ return NULL;
+}
+
/* ---------- PG_SHADOW CACHE ---------- */
/*
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 90130178ca1..cb2d7cfdf68 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: lsyscache.h,v 1.47 2002/03/29 19:06:26 tgl Exp $
+ * $Id: lsyscache.h,v 1.48 2002/04/02 01:03:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -59,6 +59,7 @@ extern bool get_attstatsslot(HeapTuple statstuple,
extern void free_attstatsslot(Oid atttype,
Datum *values, int nvalues,
float4 *numbers, int nnumbers);
+extern char *get_namespace_name(Oid nspid);
extern int32 get_usesysid(const char *username);
#define TypeIsToastable(typid) (get_typstorage(typid) != 'p')