Rearrange order of operations in heap_create_with_catalog so that if

two transactions create the same table name concurrently, the one that
fails will complain about unique index pg_class_relname_index, rather than
about pg_type_typname_index which'll confuse most people.  Free side
benefit: pg_class.reltype is correctly linked to the pg_type entry now.
It's been zero in all but the preloaded pg_class entries since who knows
when.
This commit is contained in:
Tom Lane 2001-02-12 20:07:21 +00:00
parent d8c4cb740c
commit aa88e59ade
4 changed files with 106 additions and 90 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.158 2001/01/24 19:42:51 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.159 2001/02/12 20:07:21 tgl Exp $
*
*
* INTERFACE ROUTINES
@ -68,15 +68,15 @@
static void AddNewRelationTuple(Relation pg_class_desc,
Relation new_rel_desc, Oid new_rel_oid,
int natts,
char relkind, char *temp_relname);
Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid,
int natts, char relkind, char *temp_relname);
static void DeleteAttributeTuples(Relation rel);
static void DeleteRelationTuple(Relation rel);
static void DeleteTypeTuple(Relation rel);
static void RelationRemoveIndexes(Relation relation);
static void RelationRemoveInheritance(Relation relation);
static void AddNewRelationType(char *typeName, Oid new_rel_oid);
static void AddNewRelationType(char *typeName, Oid new_rel_oid,
Oid new_type_oid);
static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
bool updatePgAttribute);
static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
@ -317,6 +317,7 @@ heap_create(char *relname,
strcpy(RelationGetPhysicalRelationName(rel), relname);
rel->rd_rel->relkind = RELKIND_UNCATALOGED;
rel->rd_rel->relnatts = natts;
rel->rd_rel->reltype = InvalidOid;
if (tupDesc->constr)
rel->rd_rel->relchecks = tupDesc->constr->num_check;
@ -325,12 +326,6 @@ heap_create(char *relname,
RelationGetRelid(rel) = relid;
if (nailme)
{
/* for system relations, set the reltype field here */
rel->rd_rel->reltype = relid;
}
rel->rd_node.tblNode = tblNode;
rel->rd_node.relNode = relid;
rel->rd_rel->relfilenode = relid;
@ -373,18 +368,17 @@ heap_storage_create(Relation rel)
* performs a scan to ensure that no relation with the
* same name already exists.
*
* 3) heap_create_with_catalog() is called to create the new relation
* on disk.
* 3) heap_create() is called to create the new relation on disk.
*
* 4) TypeDefine() is called to define a new type corresponding
* 4) AddNewRelationTuple() is called to register the
* relation in pg_class.
*
* 5) TypeCreate() is called to define a new type corresponding
* to the new relation.
*
* 5) AddNewAttributeTuples() is called to register the
* 6) AddNewAttributeTuples() is called to register the
* new relation's schema in pg_attribute.
*
* 6) AddNewRelationTuple() is called to register the
* relation itself in the catalogs.
*
* 7) StoreConstraints is called () - vadim 08/22/97
*
* 8) the relations are closed and the new relation's oid
@ -656,6 +650,7 @@ static void
AddNewRelationTuple(Relation pg_class_desc,
Relation new_rel_desc,
Oid new_rel_oid,
Oid new_type_oid,
int natts,
char relkind,
char *temp_relname)
@ -665,7 +660,7 @@ AddNewRelationTuple(Relation pg_class_desc,
Relation idescs[Num_pg_class_indices];
/* ----------------
* first we munge some of the information in our
* first we update some of the information in our
* uncataloged relation's relation descriptor.
* ----------------
*/
@ -694,6 +689,7 @@ AddNewRelationTuple(Relation pg_class_desc,
new_rel_reltup->reltuples = 1000;
new_rel_reltup->relowner = GetUserId();
new_rel_reltup->reltype = new_type_oid;
new_rel_reltup->relkind = relkind;
new_rel_reltup->relnatts = natts;
@ -705,6 +701,8 @@ AddNewRelationTuple(Relation pg_class_desc,
tup = heap_addheader(Natts_pg_class_fixed,
CLASS_TUPLE_SIZE,
(char *) new_rel_reltup);
/* force tuple to have the desired OID */
tup->t_data->t_oid = new_rel_oid;
/*
@ -738,10 +736,8 @@ AddNewRelationTuple(Relation pg_class_desc,
* --------------------------------
*/
static void
AddNewRelationType(char *typeName, Oid new_rel_oid)
AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid)
{
Oid new_type_oid;
/*
* The sizes are set to oid size because it makes implementing sets
* MUCH easier, and no one (we hope) uses these fields to figure out
@ -750,23 +746,25 @@ AddNewRelationType(char *typeName, Oid new_rel_oid)
* actually get is the oid of a tuple in the pg_proc catalog, so the
* size of the "set" is the size of an oid. Similarly, byval being
* true makes sets much easier, and it isn't used by anything else.
* Note the assumption that OIDs are the same size as int4s.
*
* XXX Note the assumption that OIDs are the same size as int4s.
*/
new_type_oid = TypeCreate(typeName, /* type name */
new_rel_oid, /* relation oid */
sizeof(Oid), /* internal size */
sizeof(Oid), /* external size */
'c', /* type-type (catalog) */
',', /* default array delimiter */
"int4in", /* input procedure */
"int4out", /* output procedure */
"int4in", /* receive procedure */
"int4out", /* send procedure */
NULL, /* array element type - irrelevent */
"-", /* default type value */
(bool) 1, /* passed by value */
'i', /* default alignment */
'p'); /* Not TOASTable */
TypeCreate(typeName, /* type name */
new_type_oid, /* preassigned oid for type */
new_rel_oid, /* relation oid */
sizeof(Oid), /* internal size */
sizeof(Oid), /* external size */
'c', /* type-type (catalog) */
',', /* default array delimiter */
"int4in", /* input procedure */
"int4out", /* output procedure */
"int4in", /* receive procedure */
"int4out", /* send procedure */
NULL, /* array element type - irrelevant */
"-", /* default type value */
true, /* passed by value */
'i', /* default alignment */
'p'); /* Not TOASTable */
}
/* --------------------------------
@ -785,6 +783,7 @@ heap_create_with_catalog(char *relname,
Relation pg_class_desc;
Relation new_rel_desc;
Oid new_rel_oid;
Oid new_type_oid;
int natts = tupdesc->natts;
char *temp_relname = NULL;
@ -814,18 +813,10 @@ heap_create_with_catalog(char *relname,
}
/* ----------------
* RelnameFindRelid couldn't detect simultaneous
* creation. Uniqueness will be really checked by unique
* indexes of system tables but we couldn't check it here.
* We have to postpone creating the disk file for this
* relation.
* Another boolean parameter "storage_create" was added
* to heap_create() function. If the parameter is false
* heap_create() only registers an uncataloged relation
* to relation cache and heap_storage_create() should be
* called later.
* We could pull its relation oid from the newly formed
* relation descriptor.
* Tell heap_create not to create a physical file; we'll do that
* below after all our catalog updates are done. (This isn't really
* necessary anymore, but we may as well avoid the cycles of creating
* and deleting the file in case we fail.)
*
* Note: The call to heap_create() changes relname for
* temp tables; it becomes the true physical relname.
@ -836,24 +827,18 @@ heap_create_with_catalog(char *relname,
new_rel_desc = heap_create(relname, tupdesc, istemp, false,
allow_system_table_mods);
/* Fetch the relation OID assigned by heap_create */
new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
/* ----------------
* since defining a relation also defines a complex type,
* we add a new system type corresponding to the new relation.
* ----------------
*/
AddNewRelationType(relname, new_rel_oid);
/* Assign an OID for the relation's tuple type */
new_type_oid = newoid();
/* ----------------
* now add tuples to pg_attribute for the attributes in
* our new relation.
* ----------------
*/
AddNewAttributeTuples(new_rel_oid, tupdesc);
/* ----------------
* now update the information in pg_class.
* now create an entry in pg_class for the relation.
*
* NOTE: we could get a unique-index failure here, in case someone else
* is creating the same relation name in parallel but hadn't committed
* yet when we checked for a duplicate name above.
* ----------------
*/
pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
@ -861,10 +846,28 @@ heap_create_with_catalog(char *relname,
AddNewRelationTuple(pg_class_desc,
new_rel_desc,
new_rel_oid,
new_type_oid,
natts,
relkind,
temp_relname);
/* ----------------
* since defining a relation also defines a complex type,
* we add a new system type corresponding to the new relation.
*
* NOTE: we could get a unique-index failure here, in case the same name
* has already been used for a type.
* ----------------
*/
AddNewRelationType(relname, new_rel_oid, new_type_oid);
/* ----------------
* now add tuples to pg_attribute for the attributes in
* our new relation.
* ----------------
*/
AddNewAttributeTuples(new_rel_oid, tupdesc);
StoreConstraints(new_rel_desc);
if (istemp)
@ -912,7 +915,6 @@ heap_create_with_catalog(char *relname,
* attribute catalog (needed?). (Anything else?)
*
* get proper relation from relation catalog (if not arg)
* check if relation is vital (strcmp()/reltype?)
* scan attribute catalog deleting attributes of reldesc
* (necessary?)
* delete relation from relation catalog

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.58 2001/01/24 19:42:52 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.59 2001/02/12 20:07:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -46,18 +46,17 @@ TypeGetWithOpenRelation(Relation pg_type_desc,
HeapScanDesc scan;
HeapTuple tup;
Oid typoid;
static ScanKeyData typeKey[1] = {
{0, Anum_pg_type_typname, F_NAMEEQ}
};
ScanKeyData typeKey[1];
/* ----------------
* initialize the scan key and begin a scan of pg_type
* ----------------
*/
fmgr_info(F_NAMEEQ, &typeKey[0].sk_func);
typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs;
typeKey[0].sk_argument = PointerGetDatum(typeName);
ScanKeyEntryInitialize(typeKey,
0,
Anum_pg_type_typname,
F_NAMEEQ,
PointerGetDatum(typeName));
scan = heap_beginscan(pg_type_desc,
0,
@ -269,10 +268,16 @@ TypeShellMake(char *typeName)
* TypeCreate
*
* This does all the necessary work needed to define a new type.
*
* NOTE: if assignedTypeOid is not InvalidOid, then that OID is assigned to
* the new type (which, therefore, cannot already exist as a shell type).
* This hack is only intended for use in creating a relation's associated
* type, where we need to have created the relation tuple already.
* ----------------------------------------------------------------
*/
Oid
TypeCreate(char *typeName,
Oid assignedTypeOid,
Oid relationOid, /* only for 'c'atalog typeTypes */
int16 internalSize,
int16 externalSize,
@ -292,35 +297,28 @@ TypeCreate(char *typeName,
j;
Relation pg_type_desc;
HeapScanDesc pg_type_scan;
Oid typeObjectId;
Oid elementObjectId = InvalidOid;
HeapTuple tup;
char nulls[Natts_pg_type];
char replaces[Natts_pg_type];
Datum values[Natts_pg_type];
char *procname;
char *procs[4];
bool defined;
NameData name;
TupleDesc tupDesc;
Oid argList[FUNC_MAX_ARGS];
static ScanKeyData typeKey[1] = {
{0, Anum_pg_type_typname, F_NAMEEQ}
};
fmgr_info(F_NAMEEQ, &typeKey[0].sk_func);
typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs;
ScanKeyData typeKey[1];
/* ----------------
* check that the type is not already defined.
* check that the type is not already defined. It might exist as
* a shell type, however (but only if assignedTypeOid is not given).
* ----------------
*/
typeObjectId = TypeGet(typeName, &defined);
if (OidIsValid(typeObjectId) && defined)
if (OidIsValid(typeObjectId) &&
(defined || assignedTypeOid != InvalidOid))
elog(ERROR, "TypeCreate: type %s already defined", typeName);
/* ----------------
@ -468,7 +466,12 @@ TypeCreate(char *typeName,
*/
pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
typeKey[0].sk_argument = PointerGetDatum(typeName);
ScanKeyEntryInitialize(typeKey,
0,
Anum_pg_type_typname,
F_NAMEEQ,
PointerGetDatum(typeName));
pg_type_scan = heap_beginscan(pg_type_desc,
0,
SnapshotSelf, /* cache? */
@ -484,6 +487,10 @@ TypeCreate(char *typeName,
tup = heap_getnext(pg_type_scan, 0);
if (HeapTupleIsValid(tup))
{
/* should not happen given prior test? */
if (assignedTypeOid != InvalidOid)
elog(ERROR, "TypeCreate: type %s already defined", typeName);
tup = heap_modifytuple(tup,
pg_type_desc,
values,
@ -502,6 +509,9 @@ TypeCreate(char *typeName,
values,
nulls);
/* preassign tuple Oid, if one was given */
tup->t_data->t_oid = assignedTypeOid;
heap_insert(pg_type_desc, tup);
typeObjectId = tup->t_data->t_oid;

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.51 2001/01/24 19:42:52 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.52 2001/02/12 20:07:21 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@ -640,6 +640,7 @@ DefineType(char *typeName, List *parameters)
* ----------------
*/
TypeCreate(typeName, /* type name */
InvalidOid, /* preassigned type oid (not done here) */
InvalidOid, /* relation oid (n/a here) */
internalLength, /* internal size */
externalLength, /* external size */
@ -652,7 +653,7 @@ DefineType(char *typeName, List *parameters)
elemName, /* element type name */
defaultValue, /* default type value */
byValue, /* passed by value */
alignment,
alignment, /* required alignment */
storage); /* TOAST strategy */
/* ----------------
@ -663,6 +664,7 @@ DefineType(char *typeName, List *parameters)
shadow_type = makeArrayTypeName(typeName);
TypeCreate(shadow_type, /* type name */
InvalidOid, /* preassigned type oid (not done here) */
InvalidOid, /* relation oid (n/a here) */
-1, /* internal size */
-1, /* external size */

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_type.h,v 1.100 2001/01/24 19:43:22 momjian Exp $
* $Id: pg_type.h,v 1.101 2001/02/12 20:07:20 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -420,6 +420,7 @@ DESCR("numeric(precision, decimal), arbitrary precision number");
extern Oid TypeGet(char *typeName, bool *defined);
extern Oid TypeShellMake(char *typeName);
extern Oid TypeCreate(char *typeName,
Oid assignedTypeOid,
Oid relationOid,
int16 internalSize,
int16 externalSize,
@ -431,7 +432,8 @@ extern Oid TypeCreate(char *typeName,
char *sendProcedure,
char *elementTypeName,
char *defaultTypeValue,
bool passedByValue, char alignment,
bool passedByValue,
char alignment,
char storage);
extern void TypeRename(const char *oldTypeName, const char *newTypeName);
extern char *makeArrayTypeName(char *typeName);