mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +03:00
Fix handling of type tuple associated with a temp relation. We have
to apply the tempname->realname mapping to type name lookup as well as relation name lookup, else the type tuple will not be found when wanted. This fixes bugs like this one: create temp table foo (f1 int); select foo.f2 from foo; ERROR: Unable to locate type name 'foo' in catalog
This commit is contained in:
@ -8,13 +8,14 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.43 2000/06/12 19:40:42 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.44 2000/06/20 01:41:21 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
#include "access/htup.h"
|
#include "access/htup.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
@ -27,43 +28,39 @@
|
|||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Information defining the "system" attributes of every relation.
|
||||||
|
*/
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
char *field;
|
char *attrname; /* name of system attribute */
|
||||||
int code;
|
int attrnum; /* its attribute number (always < 0) */
|
||||||
|
Oid attrtype; /* its type id */
|
||||||
} special_attr[] =
|
} special_attr[] =
|
||||||
|
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
"ctid", SelfItemPointerAttributeNumber
|
"ctid", SelfItemPointerAttributeNumber, TIDOID
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"oid", ObjectIdAttributeNumber
|
"oid", ObjectIdAttributeNumber, OIDOID
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"xmin", MinTransactionIdAttributeNumber
|
"xmin", MinTransactionIdAttributeNumber, XIDOID
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cmin", MinCommandIdAttributeNumber
|
"cmin", MinCommandIdAttributeNumber, CIDOID
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"xmax", MaxTransactionIdAttributeNumber
|
"xmax", MaxTransactionIdAttributeNumber, XIDOID
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cmax", MaxCommandIdAttributeNumber
|
"cmax", MaxCommandIdAttributeNumber, CIDOID
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SPECIALS ((int) (sizeof(special_attr)/sizeof(*special_attr)))
|
#define SPECIALS ((int) (sizeof(special_attr)/sizeof(special_attr[0])))
|
||||||
|
|
||||||
static char *attnum_type[SPECIALS] = {
|
|
||||||
"tid",
|
|
||||||
"oid",
|
|
||||||
"xid",
|
|
||||||
"cid",
|
|
||||||
"xid",
|
|
||||||
"cid",
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef NOT_USED
|
#ifdef NOT_USED
|
||||||
/* refnameRangeTableEntries()
|
/* refnameRangeTableEntries()
|
||||||
@ -459,8 +456,8 @@ specialAttNum(char *a)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < SPECIALS; i++)
|
for (i = 0; i < SPECIALS; i++)
|
||||||
if (!strcmp(special_attr[i].field, a))
|
if (strcmp(special_attr[i].attrname, a) == 0)
|
||||||
return special_attr[i].code;
|
return special_attr[i].attrnum;
|
||||||
|
|
||||||
return InvalidAttrNumber;
|
return InvalidAttrNumber;
|
||||||
}
|
}
|
||||||
@ -485,10 +482,8 @@ attnameIsSet(Relation rd, char *name)
|
|||||||
/* First check if this is a system attribute */
|
/* First check if this is a system attribute */
|
||||||
for (i = 0; i < SPECIALS; i++)
|
for (i = 0; i < SPECIALS; i++)
|
||||||
{
|
{
|
||||||
if (!strcmp(special_attr[i].field, name))
|
if (strcmp(special_attr[i].attrname, name) == 0)
|
||||||
{
|
|
||||||
return false; /* no sys attr is a set */
|
return false; /* no sys attr is a set */
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return get_attisset(RelationGetRelid(rd), name);
|
return get_attisset(RelationGetRelid(rd), name);
|
||||||
}
|
}
|
||||||
@ -516,13 +511,21 @@ attnumAttNelems(Relation rd, int attid)
|
|||||||
Oid
|
Oid
|
||||||
attnumTypeId(Relation rd, int attid)
|
attnumTypeId(Relation rd, int attid)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (attid < 0)
|
if (attid < 0)
|
||||||
return typeTypeId(typenameType(attnum_type[-attid - 1]));
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < SPECIALS; i++)
|
||||||
|
{
|
||||||
|
if (special_attr[i].attrnum == attid)
|
||||||
|
return special_attr[i].attrtype;
|
||||||
|
}
|
||||||
|
/* negative but not a valid system attr? */
|
||||||
|
elog(ERROR, "attnumTypeId: bogus attribute number %d", attid);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* -1 because varattno (where attid comes from) returns one more than
|
* -1 because attid is 1-based
|
||||||
* index
|
|
||||||
*/
|
*/
|
||||||
return rd->rd_att->attrs[attid - 1]->atttypid;
|
return rd->rd_att->attrs[attid - 1]->atttypid;
|
||||||
}
|
}
|
||||||
|
18
src/backend/utils/cache/syscache.c
vendored
18
src/backend/utils/cache/syscache.c
vendored
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.54 2000/06/17 04:56:33 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.55 2000/06/20 01:41:22 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* These routines allow the parser/planner/executor to perform
|
* These routines allow the parser/planner/executor to perform
|
||||||
@ -482,14 +482,20 @@ SearchSysCacheTuple(int cacheId,/* cache selection code */
|
|||||||
cacheId);
|
cacheId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* temp table name remapping */
|
/*
|
||||||
if (cacheId == RELNAME)
|
* If someone tries to look up a relname, translate temp relation
|
||||||
|
* names to real names. Less obviously, apply the same translation
|
||||||
|
* to type names, so that the type tuple of a temp table will be found
|
||||||
|
* when sought. This is a kluge ... temp table substitution should be
|
||||||
|
* happening at a higher level ...
|
||||||
|
*/
|
||||||
|
if (cacheId == RELNAME || cacheId == TYPENAME)
|
||||||
{
|
{
|
||||||
char *nontemp_relname;
|
char *nontemp_relname;
|
||||||
|
|
||||||
if ((nontemp_relname =
|
nontemp_relname = get_temp_rel_by_username(DatumGetCString(key1));
|
||||||
get_temp_rel_by_username(DatumGetPointer(key1))) != NULL)
|
if (nontemp_relname != NULL)
|
||||||
key1 = PointerGetDatum(nontemp_relname);
|
key1 = CStringGetDatum(nontemp_relname);
|
||||||
}
|
}
|
||||||
|
|
||||||
tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4);
|
tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4);
|
||||||
|
Reference in New Issue
Block a user