diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 952496fc1df9986bc169763c4dd6e3b55370bcee..e8b0d8bc013b3b527394e080a70069e220064d3c 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * 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 $ * *------------------------------------------------------------------------- */ @@ -2846,6 +2846,123 @@ renamerel(Oid relid, const char *newrelname) relation_close(targetrelation, NoLock); } +/* + * 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. diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index d9d5d13d8d46ef89c4639ccf8efe11ae404c6bde..ac25cd522956a0a34939aed7f362cff2947c72a8 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * 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 $ * *------------------------------------------------------------------------- */ @@ -2137,10 +2137,11 @@ _copyRenameStmt(RenameStmt *from) 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; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 42030b272684e54c4628ae3ae41f0cb392f6b8a9..3deb6207c3e43927732ddbbfcfa177a3dd80bfc0 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -20,7 +20,7 @@ * 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 $ * *------------------------------------------------------------------------- */ @@ -983,10 +983,12 @@ _equalRenameStmt(RenameStmt *a, RenameStmt *b) { 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; } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index a7cae5b116fec5002b308b9963546e347439c408..6e768c5bc4196a268d3f266b81b7f93b504c49b1 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * 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 @@ -2919,8 +2919,21 @@ RenameStmt: ALTER TABLE relation_expr RENAME opt_column opt_name TO name { 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; } ; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 24a1e3d2964133cfa0bacca89f22e531cfdb7b75..d1d670228ffe3b22bc674f7d7afb83e18bfacb70 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * 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 $ * *------------------------------------------------------------------------- */ @@ -377,23 +377,30 @@ ProcessUtility(Node *parsetree, 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; diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h index 5d895972f5b069fbabcbf521ff366a594ecdb906..f3dfcd6b9b1af0c6c5afbb14725e36b6ceb618e1 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -7,7 +7,7 @@ * 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 $ * *------------------------------------------------------------------------- */ @@ -15,6 +15,7 @@ #define TABLECMDS_H #include "nodes/parsenodes.h" +#include "utils/inval.h" extern void AlterTableAddColumn(Oid myrelid, bool inherits, ColumnDef *colDef); @@ -60,4 +61,8 @@ extern void renameatt(Oid relid, extern void renamerel(Oid relid, const char *newrelname); +extern void renametrig(Oid relid, + const char *oldname, + const char *newname); + #endif /* TABLECMDS_H */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 1433083b2fba9354832dad97df79de7b4563ebca..60703a06dccfd7c0897e85ba08048bbbd435f95e 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * 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 $ * *------------------------------------------------------------------------- */ @@ -1233,17 +1233,23 @@ typedef struct RemoveOperStmt } 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; /* ----------------------