*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.8 2002/04/24 02:38:58 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.9 2002/04/24 02:48:54 momjian Exp $
*
*-------------------------------------------------------------------------
*/
}
/*
+ * renametrig - changes the name of a trigger on a relation
+ *
+ * trigger name is changed in trigger catalog.
+ * No record of the previous name is kept.
+ *
+ * get proper relrelation from relation catalog (if not arg)
+ * scan trigger catalog
+ * for name conflict (within rel)
+ * for original trigger (if not arg)
+ * modify tgname in trigger tuple
+ * insert modified trigger in trigger catalog
+ * delete original trigger from trigger catalog
+ */
+extern void renametrig(Oid relid,
+ const char *oldname,
+ const char *newname)
+{
+ Relation targetrel;
+ Relation tgrel;
+ HeapTuple tuple;
+ SysScanDesc tgscan;
+ ScanKeyData key;
+ bool found = FALSE;
+ Relation idescs[Num_pg_trigger_indices];
+
+ /*
+ * Grab an exclusive lock on the target table, which we will NOT
+ * release until end of transaction.
+ */
+ targetrel = heap_open(relid, AccessExclusiveLock);
+
+ /*
+ * Scan pg_trigger twice for existing triggers on relation. We do this in
+ * order to ensure a trigger does not exist with newname (The unique index
+ * on tgrelid/tgname would complain anyway) and to ensure a trigger does
+ * exist with oldname.
+ *
+ * NOTE that this is cool only because we have AccessExclusiveLock on the
+ * relation, so the trigger set won't be changing underneath us.
+ */
+ tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
+
+ /*
+ * First pass -- look for name conflict
+ */
+ ScanKeyEntryInitialize(&key, 0,
+ Anum_pg_trigger_tgrelid,
+ F_OIDEQ,
+ ObjectIdGetDatum(relid));
+ tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true,
+ SnapshotNow, 1, &key);
+ while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
+ {
+ Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
+
+ if (namestrcmp(&(pg_trigger->tgname), newname) == 0)
+ elog(ERROR, "renametrig: trigger %s already defined on relation %s",
+ newname, RelationGetRelationName(targetrel));
+ }
+ systable_endscan(tgscan);
+
+ /*
+ * Second pass -- look for trigger existing with oldname and update
+ */
+ ScanKeyEntryInitialize(&key, 0,
+ Anum_pg_trigger_tgrelid,
+ F_OIDEQ,
+ ObjectIdGetDatum(relid));
+ tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true,
+ SnapshotNow, 1, &key);
+ while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
+ {
+ Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
+
+ if (namestrcmp(&(pg_trigger->tgname), oldname) == 0)
+ {
+ /*
+ * Update pg_trigger tuple with new tgname.
+ * (Scribbling on tuple is OK because it's a copy...)
+ */
+ namestrcpy(&(pg_trigger->tgname), newname);
+ simple_heap_update(tgrel, &tuple->t_self, tuple);
+
+ /*
+ * keep system catalog indices current
+ */
+ CatalogOpenIndices(Num_pg_trigger_indices, Name_pg_trigger_indices, idescs);
+ CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
+ CatalogCloseIndices(Num_pg_trigger_indices, idescs);
+
+ /*
+ * Invalidate relation's relcache entry so that other
+ * backends (and this one too!) are sent SI message to make them
+ * rebuild relcache entries.
+ */
+ CacheInvalidateRelcache(relid);
+
+ found = TRUE;
+ break;
+ }
+ }
+ systable_endscan(tgscan);
+
+ heap_close(tgrel, RowExclusiveLock);
+
+ if (!found)
+ elog(ERROR, "renametrig: trigger %s not defined on relation %s",
+ oldname, RelationGetRelationName(targetrel));
+
+ /*
+ * Close rel, but keep exclusive lock!
+ */
+ heap_close(targetrel, NoLock);
+}
+
+
+/*
* Given a trigger function OID, determine whether it is an RI trigger,
* and if so whether it is attached to PK or FK relation.
*
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.180 2002/04/18 20:01:09 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.181 2002/04/24 02:48:54 momjian Exp $
*
*-------------------------------------------------------------------------
*/
RenameStmt *newnode = makeNode(RenameStmt);
Node_Copy(from, newnode, relation);
- if (from->column)
- newnode->column = pstrdup(from->column);
+ if (from->oldname)
+ newnode->oldname = pstrdup(from->oldname);
if (from->newname)
newnode->newname = pstrdup(from->newname);
+ newnode->renameType = from->renameType;
return newnode;
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.128 2002/04/18 20:01:09 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.129 2002/04/24 02:48:54 momjian Exp $
*
*-------------------------------------------------------------------------
*/
{
if (!equal(a->relation, b->relation))
return false;
- if (!equalstr(a->column, b->column))
+ if (!equalstr(a->oldname, b->oldname))
return false;
if (!equalstr(a->newname, b->newname))
return false;
+ if (a->renameType != b->renameType)
+ return false;
return true;
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.309 2002/04/21 21:53:23 thomas Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.310 2002/04/24 02:48:54 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
{
RenameStmt *n = makeNode(RenameStmt);
n->relation = $3;
- n->column = $6;
+ n->oldname = $6;
n->newname = $8;
+ if ($6 == NULL)
+ n->renameType = RENAME_TABLE;
+ else
+ n->renameType = RENAME_COLUMN;
+ $$ = (Node *)n;
+ }
+ | ALTER TRIGGER name ON relation_expr RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->relation = $5;
+ n->oldname = $3;
+ n->newname = $8;
+ n->renameType = RENAME_TRIGGER;
$$ = (Node *)n;
}
;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.150 2002/04/18 20:01:09 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.151 2002/04/24 02:48:55 momjian Exp $
*
*-------------------------------------------------------------------------
*/
CheckOwnership(stmt->relation, true);
- if (stmt->column == NULL)
+ switch (stmt->renameType)
{
- /*
- * rename relation
- */
- renamerel(RangeVarGetRelid(stmt->relation, false),
- stmt->newname);
- }
- else
- {
- /*
- * rename attribute
- */
- renameatt(RangeVarGetRelid(stmt->relation, false),
- stmt->column, /* old att name */
+ case RENAME_TABLE:
+ renamerel(RangeVarGetRelid(stmt->relation, false),
+ stmt->newname);
+ break;
+ case RENAME_COLUMN:
+ renameatt(RangeVarGetRelid(stmt->relation, false),
+ stmt->oldname, /* old att name */
stmt->newname, /* new att name */
- interpretInhOption(stmt->relation->inhOpt)); /* recursive? */
+ interpretInhOption(stmt->relation->inhOpt)); /* recursive? */
+ break;
+ case RENAME_TRIGGER:
+ renametrig(RangeVarGetRelid(stmt->relation, false),
+ stmt->oldname, /* old att name */
+ stmt->newname); /* new att name */
+ break;
+ case RENAME_RULE:
+ elog(ERROR, "ProcessUtility: Invalid target for RENAME: %d",
+ stmt->renameType);
+ break;
+ default:
+ elog(ERROR, "ProcessUtility: Invalid target for RENAME: %d",
+ stmt->renameType);
}
}
break;
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: tablecmds.h,v 1.1 2002/04/15 05:22:04 tgl Exp $
+ * $Id: tablecmds.h,v 1.2 2002/04/24 02:48:55 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#define TABLECMDS_H
#include "nodes/parsenodes.h"
+#include "utils/inval.h"
extern void AlterTableAddColumn(Oid myrelid, bool inherits,
ColumnDef *colDef);
extern void renamerel(Oid relid,
const char *newrelname);
+extern void renametrig(Oid relid,
+ const char *oldname,
+ const char *newname);
+
#endif /* TABLECMDS_H */
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parsenodes.h,v 1.173 2002/04/21 00:26:43 tgl Exp $
+ * $Id: parsenodes.h,v 1.174 2002/04/24 02:48:55 momjian Exp $
*
*-------------------------------------------------------------------------
*/
} RemoveOperStmt;
/* ----------------------
- * Alter Table Rename Statement
+ * Alter Object Rename Statement
* ----------------------
+ * Currently supports renaming tables, table columns, and triggers.
+ * If renaming a table, oldname is ignored.
*/
+#define RENAME_TABLE 110
+#define RENAME_COLUMN 111
+#define RENAME_TRIGGER 112
+#define RENAME_RULE 113
+
typedef struct RenameStmt
{
NodeTag type;
- RangeVar *relation; /* relation to be altered */
- char *column; /* if NULL, rename the relation name to
- * the new name. Otherwise, rename this
- * column name. */
+ RangeVar *relation; /* owning relation */
+ char *oldname; /* name of rule, trigger, etc */
char *newname; /* the new name */
+ int renameType; /* RENAME_TABLE, RENAME_COLUMN, etc */
} RenameStmt;
/* ----------------------