Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9f1a223

Browse files
committed
Make renaming a temp table behave sensibly. We don't need to touch
the underlying table at all, just change the mapping entry ... butthat logic was missing.
1 parent38db5fa commit9f1a223

File tree

3 files changed

+130
-33
lines changed

3 files changed

+130
-33
lines changed

‎src/backend/commands/rename.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.45 2000/05/25 21:30:20 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.46 2000/06/20 06:41:13 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -29,6 +29,7 @@
2929
#include"utils/acl.h"
3030
#include"utils/relcache.h"
3131
#include"utils/syscache.h"
32+
#include"utils/temprel.h"
3233

3334

3435
/*
@@ -199,6 +200,13 @@ renamerel(const char *oldrelname, const char *newrelname)
199200
elog(ERROR,"renamerel: Illegal class name: \"%s\" -- pg_ is reserved for system catalogs",
200201
newrelname);
201202

203+
/*
204+
* Check for renaming a temp table, which only requires altering
205+
* the temp-table mapping, not the physical table.
206+
*/
207+
if (rename_temp_relation(oldrelname,newrelname))
208+
return;/* all done... */
209+
202210
/*
203211
* Instead of using heap_openr(), do it the hard way, so that we
204212
* can rename indexes as well as regular relations.

‎src/backend/utils/cache/temprel.c

Lines changed: 109 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,29 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/temprel.c,v 1.23 2000/05/30 00:49:54 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/temprel.c,v 1.24 2000/06/20 06:41:12 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
1515

1616
/*
1717
* This implements temp tables by modifying the relname cache lookups
1818
* of pg_class.
19-
* When a temp table is created, a linked list of temp table tuples is
20-
* stored here. When a relname cache lookup is done, references to user-named
21-
* temp tables are converted to the internal temp table names.
19+
*
20+
* When a temp table is created, normal entries are made for it in pg_class,
21+
* pg_type, etc using a unique "physical" relation name. We also make an
22+
* entry in the temp table list maintained by this module. Subsequently,
23+
* relname lookups are filtered through the temp table list, and attempts
24+
* to look up a temp table name are changed to look up the physical name.
25+
* This allows temp table names to mask a regular table of the same name
26+
* for the duration of the session. The temp table list is also used
27+
* to drop the underlying physical relations at session shutdown.
2228
*/
2329

2430
#include<sys/types.h>
2531

2632
#include"postgres.h"
33+
2734
#include"catalog/heap.h"
2835
#include"catalog/index.h"
2936
#include"utils/catcache.h"
@@ -39,39 +46,47 @@ static List *temp_rels = NIL;
3946

4047
typedefstructTempTable
4148
{
42-
char*user_relname;
43-
char*relname;
44-
Oidrelid;
49+
char*user_relname;/* logical name of temp table */
50+
char*relname;/* underlying unique name */
51+
Oidrelid;/* needed properties of rel */
4552
charrelkind;
46-
TransactionIdxid;
53+
TransactionIdxid;/* xact in which temp tab was created */
4754
}TempTable;
4855

4956

57+
/*
58+
* Create a temp-relation list entry given the logical temp table name
59+
* and the already-created pg_class tuple for the underlying relation.
60+
*
61+
* NB: we assume a check has already been made for a duplicate logical name.
62+
*/
5063
void
5164
create_temp_relation(constchar*relname,HeapTuplepg_class_tuple)
5265
{
66+
Form_pg_classpg_class_form= (Form_pg_class)GETSTRUCT(pg_class_tuple);
5367
MemoryContextoldcxt;
5468
TempTable*temp_rel;
5569

5670
oldcxt=MemoryContextSwitchTo((MemoryContext)CacheCxt);
5771

58-
temp_rel=palloc(sizeof(TempTable));
59-
temp_rel->user_relname=palloc(NAMEDATALEN);
60-
temp_rel->relname=palloc(NAMEDATALEN);
72+
temp_rel=(TempTable*)palloc(sizeof(TempTable));
73+
temp_rel->user_relname=(char*)palloc(NAMEDATALEN);
74+
temp_rel->relname=(char*)palloc(NAMEDATALEN);
6175

62-
/* save user-supplied name */
63-
strcpy(temp_rel->user_relname,relname);
64-
StrNCpy(temp_rel->relname,NameStr(((Form_pg_class)
65-
GETSTRUCT(pg_class_tuple))->relname),NAMEDATALEN);
76+
StrNCpy(temp_rel->user_relname,relname,NAMEDATALEN);
77+
StrNCpy(temp_rel->relname,NameStr(pg_class_form->relname),NAMEDATALEN);
6678
temp_rel->relid=pg_class_tuple->t_data->t_oid;
67-
temp_rel->relkind=((Form_pg_class)GETSTRUCT(pg_class_tuple))->relkind;
79+
temp_rel->relkind=pg_class_form->relkind;
6880
temp_rel->xid=GetCurrentTransactionId();
6981

7082
temp_rels=lcons(temp_rel,temp_rels);
7183

7284
MemoryContextSwitchTo(oldcxt);
7385
}
7486

87+
/*
88+
* Remove underlying relations for all temp rels at backend shutdown.
89+
*/
7590
void
7691
remove_all_temp_relations(void)
7792
{
@@ -87,7 +102,7 @@ remove_all_temp_relations(void)
87102
l=temp_rels;
88103
while (l!=NIL)
89104
{
90-
TempTable*temp_rel=lfirst(l);
105+
TempTable*temp_rel=(TempTable*)lfirst(l);
91106

92107
next=lnext(l);/* do this first, l is deallocated */
93108

@@ -108,11 +123,14 @@ remove_all_temp_relations(void)
108123
CommitTransactionCommand();
109124
}
110125

111-
/* we don't have the relname for indexes, so we just pass the oid */
126+
/*
127+
* Remove a temp relation map entry (part of DROP TABLE on a temp table)
128+
*
129+
* we don't have the relname for indexes, so we just pass the oid
130+
*/
112131
void
113132
remove_temp_relation(Oidrelid)
114133
{
115-
116134
MemoryContextoldcxt;
117135
List*l,
118136
*prev;
@@ -123,7 +141,7 @@ remove_temp_relation(Oid relid)
123141
l=temp_rels;
124142
while (l!=NIL)
125143
{
126-
TempTable*temp_rel=lfirst(l);
144+
TempTable*temp_rel=(TempTable*)lfirst(l);
127145

128146
if (temp_rel->relid==relid)
129147
{
@@ -154,7 +172,12 @@ remove_temp_relation(Oid relid)
154172
MemoryContextSwitchTo(oldcxt);
155173
}
156174

157-
/* remove entries from aborted transactions */
175+
/*
176+
* Remove freshly-created map entries during transaction abort.
177+
*
178+
* The underlying physical rel will be removed by normal abort processing.
179+
* We just have to delete the map entry.
180+
*/
158181
void
159182
invalidate_temp_relations(void)
160183
{
@@ -168,7 +191,7 @@ invalidate_temp_relations(void)
168191
l=temp_rels;
169192
while (l!=NIL)
170193
{
171-
TempTable*temp_rel=lfirst(l);
194+
TempTable*temp_rel=(TempTable*)lfirst(l);
172195

173196
if (temp_rel->xid==GetCurrentTransactionId())
174197
{
@@ -194,35 +217,96 @@ invalidate_temp_relations(void)
194217
prev=l;
195218
l=lnext(l);
196219
}
197-
198220
}
199221

200222
MemoryContextSwitchTo(oldcxt);
201223
}
202224

225+
/*
226+
* To implement ALTER TABLE RENAME on a temp table, we shouldn't touch
227+
* the underlying physical table at all, just change the map entry!
228+
*
229+
* This routine is invoked early in ALTER TABLE RENAME to check for
230+
* the temp-table case. If oldname matches a temp table name, change
231+
* the map entry to the new logical name and return TRUE (or elog if
232+
* there is a conflict with another temp table name). If there is
233+
* no match, return FALSE indicating that normal rename should proceed.
234+
*
235+
* We also reject an attempt to rename a normal table to a name in use
236+
* as a temp table name. That would fail later on anyway when rename.c
237+
* looks for a rename conflict, but we can give a more specific error
238+
* message for the problem here.
239+
*
240+
* It might seem that we need to check for attempts to rename the physical
241+
* file underlying a temp table, but that'll be rejected anyway because
242+
* pg_tempXXX looks like a system table name.
243+
*
244+
* A nitpicker might complain that the rename should be undone if the
245+
* current xact is later aborted, but I'm not going to fix that now.
246+
* This whole mapping mechanism ought to be replaced with something
247+
* schema-based, anyhow.
248+
*/
249+
bool
250+
rename_temp_relation(constchar*oldname,
251+
constchar*newname)
252+
{
253+
List*l;
254+
255+
foreach(l,temp_rels)
256+
{
257+
TempTable*temp_rel= (TempTable*)lfirst(l);
258+
259+
if (strcmp(temp_rel->user_relname,oldname)==0)
260+
{
261+
if (get_temp_rel_by_username(newname)!=NULL)
262+
elog(ERROR,"Cannot rename temp table \"%s\": temp table \"%s\" already exists",
263+
oldname,newname);
264+
/* user_relname was palloc'd NAMEDATALEN, so safe to re-use it */
265+
StrNCpy(temp_rel->user_relname,newname,NAMEDATALEN);
266+
return true;
267+
}
268+
}
269+
270+
/* Old name does not match any temp table name, what about new? */
271+
if (get_temp_rel_by_username(newname)!=NULL)
272+
elog(ERROR,"Cannot rename \"%s\" to \"%s\": a temp table by that name already exists",
273+
oldname,newname);
274+
275+
return false;
276+
}
277+
278+
279+
/*
280+
* Map user name to physical name --- returns NULL if no entry.
281+
*
282+
* This is the normal way to test whether a name is a temp table name.
283+
*/
203284
char*
204285
get_temp_rel_by_username(constchar*user_relname)
205286
{
206287
List*l;
207288

208289
foreach(l,temp_rels)
209290
{
210-
TempTable*temp_rel=lfirst(l);
291+
TempTable*temp_rel=(TempTable*)lfirst(l);
211292

212293
if (strcmp(temp_rel->user_relname,user_relname)==0)
213294
returntemp_rel->relname;
214295
}
215296
returnNULL;
216297
}
217298

299+
/*
300+
* Map physical name to user name --- returns pstrdup'd input if no match.
301+
*/
218302
char*
219303
get_temp_rel_by_physicalname(constchar*relname)
220304
{
221305
List*l;
222306

223307
foreach(l,temp_rels)
224308
{
225-
TempTable*temp_rel=lfirst(l);
309+
TempTable*temp_rel=(TempTable*)lfirst(l);
226310

227311
if (strcmp(temp_rel->relname,relname)==0)
228312
returntemp_rel->user_relname;

‎src/include/utils/temprel.h

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: temprel.h,v 1.9 2000/04/12 17:16:55 momjian Exp $
10+
* $Id: temprel.h,v 1.10 2000/06/20 06:41:11 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -16,11 +16,16 @@
1616

1717
#include"access/htup.h"
1818

19-
voidcreate_temp_relation(constchar*relname,HeapTuplepg_class_tuple);
20-
voidremove_all_temp_relations(void);
21-
voidinvalidate_temp_relations(void);
22-
voidremove_temp_relation(Oidrelid);
23-
char*get_temp_rel_by_username(constchar*user_relname);
24-
char*get_temp_rel_by_physicalname(constchar*relname);
19+
externvoidcreate_temp_relation(constchar*relname,
20+
HeapTuplepg_class_tuple);
21+
externvoidremove_temp_relation(Oidrelid);
22+
externboolrename_temp_relation(constchar*oldname,
23+
constchar*newname);
24+
25+
externvoidremove_all_temp_relations(void);
26+
externvoidinvalidate_temp_relations(void);
27+
28+
externchar*get_temp_rel_by_username(constchar*user_relname);
29+
externchar*get_temp_rel_by_physicalname(constchar*relname);
2530

2631
#endif/* TEMPREL_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp