]> granicus.if.org Git - postgresql/blob - src/backend/commands/rename.c
From: t-ishii@sra.co.jp
[postgresql] / src / backend / commands / rename.c
1 /*-------------------------------------------------------------------------
2  *
3  * rename.c--
4  *        renameatt() and renamerel() reside here.
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.13 1998/07/26 04:30:24 scrappy Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include <postgres.h>
15
16 #include <access/heapam.h>
17 #include <access/relscan.h>
18 #include <utils/builtins.h>
19 #include <catalog/catname.h>
20 #include <utils/syscache.h>
21 #include <catalog/indexing.h>
22 #include <catalog/catalog.h>
23 #include <commands/copy.h>
24 #include <commands/rename.h>
25 #include <executor/execdefs.h>  /* for EXEC_{FOR,BACK,FDEBUG,BDEBUG} */
26 #include <miscadmin.h>
27 #include <utils/portal.h>
28 #include <tcop/dest.h>
29 #include <commands/command.h>
30 #include <utils/excid.h>
31 #include <utils/mcxt.h>
32 #include <catalog/pg_proc.h>
33 #ifdef MULTIBYTE
34 #include <catalog/pg_class_mb.h>
35 #else
36 #include <catalog/pg_class.h>
37 #endif
38 #include <optimizer/internal.h>
39 #include <optimizer/prep.h>             /* for find_all_inheritors */
40 #ifndef NO_SECURITY
41 #include <utils/acl.h>
42 #endif                                                  /* !NO_SECURITY */
43 #ifndef HAVE_MEMMOVE
44 #include <regex/utils.h>
45 #else
46 #include <string.h>
47 #endif
48
49 /*
50  *              renameatt               - changes the name of a attribute in a relation
51  *
52  *              Attname attribute is changed in attribute catalog.
53  *              No record of the previous attname is kept (correct?).
54  *
55  *              get proper reldesc from relation catalog (if not arg)
56  *              scan attribute catalog
57  *                              for name conflict (within rel)
58  *                              for original attribute (if not arg)
59  *              modify attname in attribute tuple
60  *              insert modified attribute in attribute catalog
61  *              delete original attribute from attribute catalog
62  *
63  *              XXX Renaming an indexed attribute must (eventually) also change
64  *                              the attribute name in the associated indexes.
65  */
66 void
67 renameatt(char *relname,
68                   char *oldattname,
69                   char *newattname,
70                   char *userName,
71                   int recurse)
72 {
73         Relation        relrdesc,
74                                 attrdesc;
75         HeapTuple       reltup,
76                                 oldatttup,
77                                 newatttup;
78         ItemPointerData oldTID;
79         Relation        idescs[Num_pg_attr_indices];
80
81         /*
82          * permissions checking.  this would normally be done in utility.c,
83          * but this particular routine is recursive.
84          *
85          * normally, only the owner of a class can change its schema.
86          */
87         if (IsSystemRelationName(relname))
88                 elog(ERROR, "renameatt: class \"%s\" is a system catalog",
89                          relname);
90 #ifndef NO_SECURITY
91         if (!IsBootstrapProcessingMode() &&
92                 !pg_ownercheck(userName, relname, RELNAME))
93                 elog(ERROR, "renameatt: you do not own class \"%s\"",
94                          relname);
95 #endif
96
97         /*
98          * if the 'recurse' flag is set then we are supposed to rename this
99          * attribute in all classes that inherit from 'relname' (as well as in
100          * 'relname').
101          *
102          * any permissions or problems with duplicate attributes will cause the
103          * whole transaction to abort, which is what we want -- all or
104          * nothing.
105          */
106         if (recurse)
107         {
108                 Oid                     myrelid,
109                                         childrelid;
110                 List       *child,
111                                    *children;
112
113                 relrdesc = heap_openr(relname);
114                 if (!RelationIsValid(relrdesc))
115                 {
116                         elog(ERROR, "renameatt: unknown relation: \"%s\"",
117                                  relname);
118                 }
119                 myrelid = relrdesc->rd_id;
120                 heap_close(relrdesc);
121
122                 /* this routine is actually in the planner */
123                 children = find_all_inheritors(lconsi(myrelid, NIL), NIL);
124
125
126                 /*
127                  * find_all_inheritors does the recursive search of the
128                  * inheritance hierarchy, so all we have to do is process all of
129                  * the relids in the list that it returns.
130                  */
131                 foreach(child, children)
132                 {
133                         char       *childname;
134
135                         childrelid = lfirsti(child);
136                         if (childrelid == myrelid)
137                                 continue;
138                         relrdesc = heap_open(childrelid);
139                         if (!RelationIsValid(relrdesc))
140                         {
141                                 elog(ERROR, "renameatt: can't find catalog entry for inheriting class with oid %d",
142                                          childrelid);
143                         }
144                         childname = (relrdesc->rd_rel->relname).data;
145                         heap_close(relrdesc);
146                         renameatt(childname, oldattname, newattname,
147                                           userName, 0);         /* no more recursion! */
148                 }
149         }
150
151         relrdesc = heap_openr(RelationRelationName);
152         reltup = ClassNameIndexScan(relrdesc, relname);
153         if (!PointerIsValid(reltup))
154         {
155                 heap_close(relrdesc);
156                 elog(ERROR, "renameatt: relation \"%s\" nonexistent",
157                          relname);
158                 return;
159         }
160         heap_close(relrdesc);
161
162         attrdesc = heap_openr(AttributeRelationName);
163         oldatttup = AttributeNameIndexScan(attrdesc, reltup->t_oid, oldattname);
164         if (!PointerIsValid(oldatttup))
165         {
166                 heap_close(attrdesc);
167                 elog(ERROR, "renameatt: attribute \"%s\" nonexistent",
168                          oldattname);
169         }
170         if (((AttributeTupleForm) GETSTRUCT(oldatttup))->attnum < 0)
171         {
172                 elog(ERROR, "renameatt: system attribute \"%s\" not renamed",
173                          oldattname);
174         }
175
176         newatttup = AttributeNameIndexScan(attrdesc, reltup->t_oid, newattname);
177         if (PointerIsValid(newatttup))
178         {
179                 pfree(oldatttup);
180                 heap_close(attrdesc);
181                 elog(ERROR, "renameatt: attribute \"%s\" exists",
182                          newattname);
183         }
184
185         namestrcpy(&(((AttributeTupleForm) (GETSTRUCT(oldatttup)))->attname),
186                            newattname);
187         oldTID = oldatttup->t_ctid;
188
189         /* insert "fixed" tuple */
190         heap_replace(attrdesc, &oldTID, oldatttup);
191
192         /* keep system catalog indices current */
193         CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
194         CatalogIndexInsert(idescs, Num_pg_attr_indices, attrdesc, oldatttup);
195         CatalogCloseIndices(Num_pg_attr_indices, idescs);
196
197         heap_close(attrdesc);
198         pfree(oldatttup);
199 }
200
201 /*
202  *              renamerel               - change the name of a relation
203  *
204  *              Relname attribute is changed in relation catalog.
205  *              No record of the previous relname is kept (correct?).
206  *
207  *              scan relation catalog
208  *                              for name conflict
209  *                              for original relation (if not arg)
210  *              modify relname in relation tuple
211  *              insert modified relation in relation catalog
212  *              delete original relation from relation catalog
213  *
214  *              XXX Will currently lose track of a relation if it is unable to
215  *                              properly replace the new relation tuple.
216  */
217 void
218 renamerel(char oldrelname[], char newrelname[])
219 {
220         Relation        relrdesc;               /* for RELATION relation */
221         HeapTuple       oldreltup,
222                                 newreltup;
223         ItemPointerData oldTID;
224         char            oldpath[MAXPGPATH],
225                                 newpath[MAXPGPATH];
226         Relation        idescs[Num_pg_class_indices];
227
228         if (IsSystemRelationName(oldrelname))
229         {
230                 elog(ERROR, "renamerel: system relation \"%s\" not renamed",
231                          oldrelname);
232                 return;
233         }
234         if (IsSystemRelationName(newrelname))
235         {
236                 elog(ERROR, "renamerel: Illegal class name: \"%s\" -- pg_ is reserved for system catalogs",
237                          newrelname);
238                 return;
239         }
240
241         relrdesc = heap_openr(RelationRelationName);
242         oldreltup = ClassNameIndexScan(relrdesc, oldrelname);
243
244         if (!PointerIsValid(oldreltup))
245         {
246                 heap_close(relrdesc);
247                 elog(ERROR, "renamerel: relation \"%s\" does not exist",
248                          oldrelname);
249         }
250
251         newreltup = ClassNameIndexScan(relrdesc, newrelname);
252         if (PointerIsValid(newreltup))
253         {
254                 pfree(oldreltup);
255                 heap_close(relrdesc);
256                 elog(ERROR, "renamerel: relation \"%s\" exists",
257                          newrelname);
258         }
259
260         /* rename the directory first, so if this fails the rename's not done */
261         strcpy(oldpath, relpath(oldrelname));
262         strcpy(newpath, relpath(newrelname));
263         if (rename(oldpath, newpath) < 0)
264                 elog(ERROR, "renamerel: unable to rename file: %m");
265
266         memmove((char *) (((Form_pg_class) GETSTRUCT(oldreltup))->relname.data),
267                         newrelname,
268                         NAMEDATALEN);
269         oldTID = oldreltup->t_ctid;
270
271         /* insert fixed rel tuple */
272         heap_replace(relrdesc, &oldTID, oldreltup);
273
274         /* keep the system catalog indices current */
275         CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
276         CatalogIndexInsert(idescs, Num_pg_class_indices, relrdesc, oldreltup);
277         CatalogCloseIndices(Num_pg_class_indices, idescs);
278
279         pfree(oldreltup);
280         heap_close(relrdesc);
281 }