1996-07-09 06:22:35 +00:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-13 23:22:53 +00:00
|
|
|
* rename.c
|
1997-09-07 05:04:48 +00:00
|
|
|
* renameatt() and renamerel() reside here.
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
2000-01-26 05:58:53 +00:00
|
|
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2000-11-08 22:10:03 +00:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.52 2000/11/08 22:09:57 tgl Exp $
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1999-07-16 05:41:19 +00:00
|
|
|
#include "postgres.h"
|
1999-07-16 05:00:38 +00:00
|
|
|
|
1999-09-24 00:25:33 +00:00
|
|
|
#include <errno.h>
|
|
|
|
|
1999-07-15 23:04:24 +00:00
|
|
|
#include "access/heapam.h"
|
|
|
|
#include "catalog/catname.h"
|
2000-05-11 03:54:18 +00:00
|
|
|
#include "catalog/pg_type.h"
|
1999-07-15 23:04:24 +00:00
|
|
|
#include "catalog/heap.h"
|
|
|
|
#include "catalog/indexing.h"
|
|
|
|
#include "catalog/catalog.h"
|
|
|
|
#include "commands/rename.h"
|
|
|
|
#include "miscadmin.h"
|
1999-09-24 00:25:33 +00:00
|
|
|
#include "storage/smgr.h"
|
1999-07-16 03:14:30 +00:00
|
|
|
#include "optimizer/prep.h"
|
1999-07-15 23:04:24 +00:00
|
|
|
#include "utils/acl.h"
|
2000-05-11 03:54:18 +00:00
|
|
|
#include "utils/relcache.h"
|
2000-05-25 21:30:20 +00:00
|
|
|
#include "utils/syscache.h"
|
2000-06-20 06:41:13 +00:00
|
|
|
#include "utils/temprel.h"
|
2000-05-11 03:54:18 +00:00
|
|
|
|
1996-07-09 06:22:35 +00:00
|
|
|
|
|
|
|
/*
|
1997-09-07 05:04:48 +00:00
|
|
|
* renameatt - changes the name of a attribute in a relation
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
1997-09-07 05:04:48 +00:00
|
|
|
* Attname attribute is changed in attribute catalog.
|
|
|
|
* No record of the previous attname is kept (correct?).
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
1998-08-19 02:04:17 +00:00
|
|
|
* get proper relrelation from relation catalog (if not arg)
|
1997-09-07 05:04:48 +00:00
|
|
|
* scan attribute catalog
|
|
|
|
* for name conflict (within rel)
|
|
|
|
* for original attribute (if not arg)
|
|
|
|
* modify attname in attribute tuple
|
|
|
|
* insert modified attribute in attribute catalog
|
|
|
|
* delete original attribute from attribute catalog
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
1997-09-07 05:04:48 +00:00
|
|
|
* XXX Renaming an indexed attribute must (eventually) also change
|
|
|
|
* the attribute name in the associated indexes.
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
renameatt(char *relname,
|
1997-09-07 05:04:48 +00:00
|
|
|
char *oldattname,
|
|
|
|
char *newattname,
|
|
|
|
int recurse)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
1999-09-18 19:08:25 +00:00
|
|
|
Relation targetrelation;
|
1998-08-19 02:04:17 +00:00
|
|
|
Relation attrelation;
|
1997-09-08 02:41:22 +00:00
|
|
|
HeapTuple reltup,
|
|
|
|
oldatttup,
|
|
|
|
newatttup;
|
1998-08-19 02:04:17 +00:00
|
|
|
Oid relid;
|
1998-09-01 04:40:42 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/*
|
|
|
|
* permissions checking. this would normally be done in utility.c,
|
|
|
|
* but this particular routine is recursive.
|
|
|
|
*
|
|
|
|
* normally, only the owner of a class can change its schema.
|
|
|
|
*/
|
1999-03-17 22:53:31 +00:00
|
|
|
if (!allowSystemTableMods && IsSystemRelationName(relname))
|
1998-01-05 16:40:20 +00:00
|
|
|
elog(ERROR, "renameatt: class \"%s\" is a system catalog",
|
1997-09-07 05:04:48 +00:00
|
|
|
relname);
|
|
|
|
if (!IsBootstrapProcessingMode() &&
|
2000-09-06 14:15:31 +00:00
|
|
|
!pg_ownercheck(GetUserId(), relname, RELNAME))
|
1998-01-05 16:40:20 +00:00
|
|
|
elog(ERROR, "renameatt: you do not own class \"%s\"",
|
1997-09-07 05:04:48 +00:00
|
|
|
relname);
|
1996-07-09 06:22:35 +00:00
|
|
|
|
1999-09-18 19:08:25 +00:00
|
|
|
/*
|
2000-04-12 17:17:23 +00:00
|
|
|
* Grab an exclusive lock on the target table, which we will NOT
|
|
|
|
* release until end of transaction.
|
1999-09-18 19:08:25 +00:00
|
|
|
*/
|
|
|
|
targetrelation = heap_openr(relname, AccessExclusiveLock);
|
|
|
|
relid = RelationGetRelid(targetrelation);
|
2000-04-12 17:17:23 +00:00
|
|
|
heap_close(targetrelation, NoLock); /* close rel but keep lock! */
|
1999-09-18 19:08:25 +00:00
|
|
|
|
1996-07-09 06:22:35 +00:00
|
|
|
/*
|
1997-09-07 05:04:48 +00:00
|
|
|
* if the 'recurse' flag is set then we are supposed to rename this
|
|
|
|
* attribute in all classes that inherit from 'relname' (as well as in
|
|
|
|
* 'relname').
|
|
|
|
*
|
|
|
|
* any permissions or problems with duplicate attributes will cause the
|
|
|
|
* whole transaction to abort, which is what we want -- all or
|
|
|
|
* nothing.
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
1997-09-07 05:04:48 +00:00
|
|
|
if (recurse)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
List *child,
|
|
|
|
*children;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
/* this routine is actually in the planner */
|
1999-12-14 03:35:28 +00:00
|
|
|
children = find_all_inheritors(relid);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* find_all_inheritors does the recursive search of the
|
|
|
|
* inheritance hierarchy, so all we have to do is process all of
|
|
|
|
* the relids in the list that it returns.
|
|
|
|
*/
|
|
|
|
foreach(child, children)
|
|
|
|
{
|
1999-12-14 03:35:28 +00:00
|
|
|
Oid childrelid = lfirsti(child);
|
1998-09-01 04:40:42 +00:00
|
|
|
char childname[NAMEDATALEN];
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1999-09-18 19:08:25 +00:00
|
|
|
if (childrelid == relid)
|
1997-09-07 05:04:48 +00:00
|
|
|
continue;
|
1998-08-19 02:04:17 +00:00
|
|
|
reltup = SearchSysCacheTuple(RELOID,
|
|
|
|
ObjectIdGetDatum(childrelid),
|
|
|
|
0, 0, 0);
|
|
|
|
if (!HeapTupleIsValid(reltup))
|
1997-09-07 05:04:48 +00:00
|
|
|
{
|
1999-05-10 00:46:32 +00:00
|
|
|
elog(ERROR, "renameatt: can't find catalog entry for inheriting class with oid %u",
|
1997-09-07 05:04:48 +00:00
|
|
|
childrelid);
|
|
|
|
}
|
1998-08-19 02:04:17 +00:00
|
|
|
/* make copy of cache value, could disappear in call */
|
|
|
|
StrNCpy(childname,
|
1999-11-07 23:08:36 +00:00
|
|
|
NameStr(((Form_pg_class) GETSTRUCT(reltup))->relname),
|
1998-09-01 04:40:42 +00:00
|
|
|
NAMEDATALEN);
|
1999-09-18 19:08:25 +00:00
|
|
|
/* note we need not recurse again! */
|
2000-09-06 14:15:31 +00:00
|
|
|
renameatt(childname, oldattname, newattname, 0);
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-09-18 19:08:25 +00:00
|
|
|
attrelation = heap_openr(AttributeRelationName, RowExclusiveLock);
|
1998-08-19 02:04:17 +00:00
|
|
|
|
|
|
|
oldatttup = SearchSysCacheTupleCopy(ATTNAME,
|
1998-09-01 04:40:42 +00:00
|
|
|
ObjectIdGetDatum(relid),
|
|
|
|
PointerGetDatum(oldattname),
|
|
|
|
0, 0);
|
1998-08-19 02:04:17 +00:00
|
|
|
if (!HeapTupleIsValid(oldatttup))
|
2000-10-22 23:32:48 +00:00
|
|
|
elog(ERROR, "renameatt: attribute \"%s\" does not exist", oldattname);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1998-09-01 03:29:17 +00:00
|
|
|
if (((Form_pg_attribute) GETSTRUCT(oldatttup))->attnum < 0)
|
1998-08-19 02:04:17 +00:00
|
|
|
elog(ERROR, "renameatt: system attribute \"%s\" not renamed", oldattname);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1998-08-19 02:04:17 +00:00
|
|
|
newatttup = SearchSysCacheTuple(ATTNAME,
|
1998-09-01 04:40:42 +00:00
|
|
|
ObjectIdGetDatum(relid),
|
|
|
|
PointerGetDatum(newattname),
|
|
|
|
0, 0);
|
1998-08-19 02:04:17 +00:00
|
|
|
/* should not already exist */
|
|
|
|
if (HeapTupleIsValid(newatttup))
|
1997-09-07 05:04:48 +00:00
|
|
|
{
|
1999-12-16 22:20:03 +00:00
|
|
|
heap_freetuple(oldatttup);
|
1998-08-19 02:04:17 +00:00
|
|
|
elog(ERROR, "renameatt: attribute \"%s\" exists", newattname);
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
|
1999-11-07 23:08:36 +00:00
|
|
|
StrNCpy(NameStr(((Form_pg_attribute) GETSTRUCT(oldatttup))->attname),
|
1998-09-01 04:40:42 +00:00
|
|
|
newattname, NAMEDATALEN);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1999-11-24 00:44:37 +00:00
|
|
|
heap_update(attrelation, &oldatttup->t_self, oldatttup, NULL);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
/* keep system catalog indices current */
|
1999-11-25 00:15:57 +00:00
|
|
|
{
|
|
|
|
Relation irelations[Num_pg_attr_indices];
|
2000-04-12 17:17:23 +00:00
|
|
|
|
1999-11-25 00:15:57 +00:00
|
|
|
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, irelations);
|
|
|
|
CatalogIndexInsert(irelations, Num_pg_attr_indices, attrelation, oldatttup);
|
|
|
|
CatalogCloseIndices(Num_pg_attr_indices, irelations);
|
|
|
|
}
|
2000-04-12 17:17:23 +00:00
|
|
|
|
1999-12-16 22:20:03 +00:00
|
|
|
heap_freetuple(oldatttup);
|
1999-09-18 19:08:25 +00:00
|
|
|
heap_close(attrelation, RowExclusiveLock);
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 05:04:48 +00:00
|
|
|
* renamerel - change the name of a relation
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
|
|
|
void
|
2000-01-22 14:20:56 +00:00
|
|
|
renamerel(const char *oldrelname, const char *newrelname)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
1999-09-18 19:08:25 +00:00
|
|
|
Relation targetrelation;
|
1998-09-01 04:40:42 +00:00
|
|
|
Relation relrelation; /* for RELATION relation */
|
1999-02-02 03:45:56 +00:00
|
|
|
HeapTuple oldreltup;
|
2000-05-25 21:30:20 +00:00
|
|
|
Oid reloid;
|
2000-05-11 03:54:18 +00:00
|
|
|
char relkind;
|
2000-10-20 02:53:10 +00:00
|
|
|
Relation irelations[Num_pg_class_indices];
|
1998-09-01 04:40:42 +00:00
|
|
|
|
1999-03-17 22:53:31 +00:00
|
|
|
if (!allowSystemTableMods && IsSystemRelationName(oldrelname))
|
2000-11-08 22:10:03 +00:00
|
|
|
elog(ERROR, "renamerel: system relation \"%s\" may not be renamed",
|
1997-09-07 05:04:48 +00:00
|
|
|
oldrelname);
|
1998-08-19 02:04:17 +00:00
|
|
|
|
1999-03-17 22:53:31 +00:00
|
|
|
if (!allowSystemTableMods && IsSystemRelationName(newrelname))
|
1998-01-05 16:40:20 +00:00
|
|
|
elog(ERROR, "renamerel: Illegal class name: \"%s\" -- pg_ is reserved for system catalogs",
|
1997-09-07 05:04:48 +00:00
|
|
|
newrelname);
|
|
|
|
|
2000-06-20 06:41:13 +00:00
|
|
|
/*
|
|
|
|
* Check for renaming a temp table, which only requires altering
|
2000-11-08 22:10:03 +00:00
|
|
|
* the temp-table mapping, not the underlying table.
|
2000-06-20 06:41:13 +00:00
|
|
|
*/
|
|
|
|
if (rename_temp_relation(oldrelname, newrelname))
|
|
|
|
return; /* all done... */
|
|
|
|
|
2000-05-11 03:54:18 +00:00
|
|
|
/*
|
|
|
|
* Instead of using heap_openr(), do it the hard way, so that we
|
|
|
|
* can rename indexes as well as regular relations.
|
|
|
|
*/
|
|
|
|
targetrelation = RelationNameGetRelation(oldrelname);
|
|
|
|
|
|
|
|
if (!RelationIsValid(targetrelation))
|
2000-11-08 22:10:03 +00:00
|
|
|
elog(ERROR, "Relation \"%s\" does not exist", oldrelname);
|
2000-05-11 03:54:18 +00:00
|
|
|
|
1999-09-18 19:08:25 +00:00
|
|
|
/*
|
2000-04-12 17:17:23 +00:00
|
|
|
* Grab an exclusive lock on the target table, which we will NOT
|
|
|
|
* release until end of transaction.
|
1999-09-18 19:08:25 +00:00
|
|
|
*/
|
2000-05-11 03:54:18 +00:00
|
|
|
LockRelation(targetrelation, AccessExclusiveLock);
|
1999-09-18 19:08:25 +00:00
|
|
|
|
2000-05-25 21:30:20 +00:00
|
|
|
reloid = RelationGetRelid(targetrelation);
|
2000-05-11 03:54:18 +00:00
|
|
|
relkind = targetrelation->rd_rel->relkind;
|
|
|
|
|
1999-09-24 00:25:33 +00:00
|
|
|
/*
|
|
|
|
* Close rel, but keep exclusive lock!
|
|
|
|
*/
|
|
|
|
heap_close(targetrelation, NoLock);
|
|
|
|
|
2000-05-25 21:30:20 +00:00
|
|
|
/*
|
|
|
|
* Flush the relcache entry (easier than trying to change it at exactly
|
|
|
|
* the right instant). It'll get rebuilt on next access to relation.
|
|
|
|
*
|
|
|
|
* XXX What if relation is myxactonly?
|
2000-11-08 22:10:03 +00:00
|
|
|
*
|
|
|
|
* XXX this is probably not necessary anymore?
|
2000-05-25 21:30:20 +00:00
|
|
|
*/
|
|
|
|
RelationIdInvalidateRelationCacheByRelationId(reloid);
|
|
|
|
|
1999-09-24 00:25:33 +00:00
|
|
|
/*
|
2000-04-12 17:17:23 +00:00
|
|
|
* Find relation's pg_class tuple, and make sure newrelname isn't in
|
|
|
|
* use.
|
1999-09-24 00:25:33 +00:00
|
|
|
*/
|
1999-09-18 19:08:25 +00:00
|
|
|
relrelation = heap_openr(RelationRelationName, RowExclusiveLock);
|
|
|
|
|
1998-08-19 02:04:17 +00:00
|
|
|
oldreltup = SearchSysCacheTupleCopy(RELNAME,
|
1998-09-01 04:40:42 +00:00
|
|
|
PointerGetDatum(oldrelname),
|
|
|
|
0, 0, 0);
|
1998-08-19 02:04:17 +00:00
|
|
|
if (!HeapTupleIsValid(oldreltup))
|
|
|
|
elog(ERROR, "renamerel: relation \"%s\" does not exist", oldrelname);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1999-02-02 03:45:56 +00:00
|
|
|
if (RelnameFindRelid(newrelname) != InvalidOid)
|
1998-08-19 02:04:17 +00:00
|
|
|
elog(ERROR, "renamerel: relation \"%s\" exists", newrelname);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2000-05-25 21:30:20 +00:00
|
|
|
/*
|
2000-11-08 22:10:03 +00:00
|
|
|
* Update pg_class tuple with new relname. (Scribbling on oldreltup
|
|
|
|
* is OK because it's a copy...)
|
2000-05-25 21:30:20 +00:00
|
|
|
*/
|
|
|
|
StrNCpy(NameStr(((Form_pg_class) GETSTRUCT(oldreltup))->relname),
|
|
|
|
newrelname, NAMEDATALEN);
|
|
|
|
|
|
|
|
heap_update(relrelation, &oldreltup->t_self, oldreltup, NULL);
|
|
|
|
|
|
|
|
/* keep the system catalog indices current */
|
|
|
|
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, irelations);
|
|
|
|
CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, oldreltup);
|
|
|
|
CatalogCloseIndices(Num_pg_class_indices, irelations);
|
|
|
|
|
|
|
|
heap_close(relrelation, NoLock);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Also rename the associated type, if any.
|
|
|
|
*/
|
|
|
|
if (relkind != RELKIND_INDEX)
|
|
|
|
TypeRename(oldrelname, newrelname);
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|